[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
// Le Chromium des épreuves du navigateur : celui de Playwright par défaut,
[FIX] web storage: refuse a name Chromium did not convert, UTF-8 launch
Under a non-UTF-8 locale, Chromium returns the parent folder for an
accented folder name without raising, so a write meant for that folder
replaced a file of the same name in its parent. Each step of a path walk
now compares the handle with its parent and refuses NOM_NON_CONVERTI —
LECTURE on reads, ECRITURE on writes — and nothing lands elsewhere. The
test launcher gives Chromium LANG=C.UTF-8 when the locale is not UTF-8, as
the containers do, and the matrix installs ps where an image lacks it.
Checked: 1776 node and 45 browser tests; the guard holds under LC_ALL=C.
--- FR ---
[FIX] stockage web : refuser un nom non converti, lancement en UTF-8
Hors locale UTF-8, Chromium rend le dossier parent pour un nom de dossier
accentué, sans lever : une écriture destinée à ce dossier remplaçait un
fichier homonyme de son parent. Chaque pas d'un chemin compare désormais le
dossier obtenu à son parent et refuse NOM_NON_CONVERTI — LECTURE en lecture,
ECRITURE en écriture — : rien n'atterrit ailleurs. Le lanceur des épreuves
donne LANG=C.UTF-8 à Chromium quand la locale n'est pas UTF-8, comme les
conteneurs, et la matrice installe ps là où une image en manque.
Vérifié : 1776 node, 45 navigateur ; la garde tient sous LC_ALL=C.
Assisted-by: Claude Opus 5.5
2026-10-07 02:35:12 -04:00
// celui que GTT_CHROMIUM désigne sinon ; sous des paramètres régionaux qui ne
[ADD] docs: photographed walkthrough publishes doc/captures
The screenshots must come from the tested walkthrough, not from a separate
script that can drift. The browser walkthrough runs on the simulated file
system with a driven clock and the direct executor, light theme, 1366 x
700 at scale 1, transitions off, and photographs each step once its
condition holds. make captures writes the images and the manifest; the
plain test run compares them instead. Eighteen captures are published, the
later ones named as postponed. The forged-names scan skips the manifest,
which records the demo names shown on screen.
Checked: red first; 3620 node, 681 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] docs : parcours photographié, publication de doc/captures
Les captures doivent venir du parcours éprouvé, non d'un script à part qui
dérive. Le parcours navigateur joue sur le système de fichiers simulé,
l'horloge pilotée et l'exécuteur direct, thème clair, 1366 × 700 au facteur
1, transitions coupées, et photographie chaque étape quand sa condition
tient. make captures écrit les images et le manifeste ; la série ordinaire
les compare au lieu de les écrire. Dix-huit captures sont publiées, les
suivantes nommées reportées. Le balayage des noms forgés saute le
manifeste, qui relève les noms de démonstration affichés.
Vérifié : rouge d'abord ; 3620 node, 681 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 15:33:59 -04:00
// sont pas UTF-8, il reçoit l'environnement sous LANG=C.UTF-8. Le projet
// navigateur le lance sans réseau hors de la boucle locale, au facteur
// d'échelle 1 (§ 19.2, § 19.4), et lui donne les commandes et le mode des
// captures d'écran (§ 19.5). vitest.config.js applique la règle ; le Makefile
// lance la publication.
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
import assert from 'node:assert/strict' ;
[ADD] docs: photographed walkthrough publishes doc/captures
The screenshots must come from the tested walkthrough, not from a separate
script that can drift. The browser walkthrough runs on the simulated file
system with a driven clock and the direct executor, light theme, 1366 x
700 at scale 1, transitions off, and photographs each step once its
condition holds. make captures writes the images and the manifest; the
plain test run compares them instead. Eighteen captures are published, the
later ones named as postponed. The forged-names scan skips the manifest,
which records the demo names shown on screen.
Checked: red first; 3620 node, 681 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] docs : parcours photographié, publication de doc/captures
Les captures doivent venir du parcours éprouvé, non d'un script à part qui
dérive. Le parcours navigateur joue sur le système de fichiers simulé,
l'horloge pilotée et l'exécuteur direct, thème clair, 1366 × 700 au facteur
1, transitions coupées, et photographie chaque étape quand sa condition
tient. make captures écrit les images et le manifeste ; la série ordinaire
les compare au lieu de les écrire. Dix-huit captures sont publiées, les
suivantes nommées reportées. Le balayage des noms forgés saute le
manifeste, qui relève les noms de démonstration affichés.
Vérifié : rouge d'abord ; 3620 node, 681 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 15:33:59 -04:00
import { readFileSync } from 'node:fs' ;
import { join } from 'node:path' ;
import { fileURLToPath } from 'node:url' ;
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
import configuration from '../vitest.config.js' ;
[ADD] docs: photographed walkthrough publishes doc/captures
The screenshots must come from the tested walkthrough, not from a separate
script that can drift. The browser walkthrough runs on the simulated file
system with a driven clock and the direct executor, light theme, 1366 x
700 at scale 1, transitions off, and photographs each step once its
condition holds. make captures writes the images and the manifest; the
plain test run compares them instead. Eighteen captures are published, the
later ones named as postponed. The forged-names scan skips the manifest,
which records the demo names shown on screen.
Checked: red first; 3620 node, 681 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] docs : parcours photographié, publication de doc/captures
Les captures doivent venir du parcours éprouvé, non d'un script à part qui
dérive. Le parcours navigateur joue sur le système de fichiers simulé,
l'horloge pilotée et l'exécuteur direct, thème clair, 1366 × 700 au facteur
1, transitions coupées, et photographie chaque étape quand sa condition
tient. make captures écrit les images et le manifeste ; la série ordinaire
les compare au lieu de les écrire. Dix-huit captures sont publiées, les
suivantes nommées reportées. Le balayage des noms forgés saute le
manifeste, qui relève les noms de démonstration affichés.
Vérifié : rouge d'abord ; 3620 node, 681 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 15:33:59 -04:00
import { ARGUMENTS _NAVIGATEUR , horsBoucle , optionsChromium , optionsNavigateur , suivreRequetes } from './chromium.js' ;
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
import { describe , test } from './lanceur.js' ;
[ADD] docs: photographed walkthrough publishes doc/captures
The screenshots must come from the tested walkthrough, not from a separate
script that can drift. The browser walkthrough runs on the simulated file
system with a driven clock and the direct executor, light theme, 1366 x
700 at scale 1, transitions off, and photographs each step once its
condition holds. make captures writes the images and the manifest; the
plain test run compares them instead. Eighteen captures are published, the
later ones named as postponed. The forged-names scan skips the manifest,
which records the demo names shown on screen.
Checked: red first; 3620 node, 681 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] docs : parcours photographié, publication de doc/captures
Les captures doivent venir du parcours éprouvé, non d'un script à part qui
dérive. Le parcours navigateur joue sur le système de fichiers simulé,
l'horloge pilotée et l'exécuteur direct, thème clair, 1366 × 700 au facteur
1, transitions coupées, et photographie chaque étape quand sa condition
tient. make captures écrit les images et le manifeste ; la série ordinaire
les compare au lieu de les écrire. Dix-huit captures sont publiées, les
suivantes nommées reportées. Le balayage des noms forgés saute le
manifeste, qui relève les noms de démonstration affichés.
Vérifié : rouge d'abord ; 3620 node, 681 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 15:33:59 -04:00
import * as commandesDocumentation from './navigateur/commandes_documentation.js' ;
const RACINE = fileURLToPath ( new URL ( '..' , import . meta . url ) ) ;
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
[FIX] web storage: refuse a name Chromium did not convert, UTF-8 launch
Under a non-UTF-8 locale, Chromium returns the parent folder for an
accented folder name without raising, so a write meant for that folder
replaced a file of the same name in its parent. Each step of a path walk
now compares the handle with its parent and refuses NOM_NON_CONVERTI —
LECTURE on reads, ECRITURE on writes — and nothing lands elsewhere. The
test launcher gives Chromium LANG=C.UTF-8 when the locale is not UTF-8, as
the containers do, and the matrix installs ps where an image lacks it.
Checked: 1776 node and 45 browser tests; the guard holds under LC_ALL=C.
--- FR ---
[FIX] stockage web : refuser un nom non converti, lancement en UTF-8
Hors locale UTF-8, Chromium rend le dossier parent pour un nom de dossier
accentué, sans lever : une écriture destinée à ce dossier remplaçait un
fichier homonyme de son parent. Chaque pas d'un chemin compare désormais le
dossier obtenu à son parent et refuse NOM_NON_CONVERTI — LECTURE en lecture,
ECRITURE en écriture — : rien n'atterrit ailleurs. Le lanceur des épreuves
donne LANG=C.UTF-8 à Chromium quand la locale n'est pas UTF-8, comme les
conteneurs, et la matrice installe ps là où une image en manque.
Vérifié : 1776 node, 45 navigateur ; la garde tient sous LC_ALL=C.
Assisted-by: Claude Opus 5.5
2026-10-07 02:35:12 -04:00
// Un environnement d'épreuve, sous des paramètres régionaux UTF-8.
const UTF8 = { PATH : '/usr/bin' , LANG : 'fr_CA.UTF-8' } ;
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
describe ( 'chromium : l’ exécutable des épreuves du navigateur' , ( ) => {
test ( 'sans GTT_CHROMIUM, Playwright lance le Chromium qu’ il a téléchargé' , ( ) => {
[FIX] web storage: refuse a name Chromium did not convert, UTF-8 launch
Under a non-UTF-8 locale, Chromium returns the parent folder for an
accented folder name without raising, so a write meant for that folder
replaced a file of the same name in its parent. Each step of a path walk
now compares the handle with its parent and refuses NOM_NON_CONVERTI —
LECTURE on reads, ECRITURE on writes — and nothing lands elsewhere. The
test launcher gives Chromium LANG=C.UTF-8 when the locale is not UTF-8, as
the containers do, and the matrix installs ps where an image lacks it.
Checked: 1776 node and 45 browser tests; the guard holds under LC_ALL=C.
--- FR ---
[FIX] stockage web : refuser un nom non converti, lancement en UTF-8
Hors locale UTF-8, Chromium rend le dossier parent pour un nom de dossier
accentué, sans lever : une écriture destinée à ce dossier remplaçait un
fichier homonyme de son parent. Chaque pas d'un chemin compare désormais le
dossier obtenu à son parent et refuse NOM_NON_CONVERTI — LECTURE en lecture,
ECRITURE en écriture — : rien n'atterrit ailleurs. Le lanceur des épreuves
donne LANG=C.UTF-8 à Chromium quand la locale n'est pas UTF-8, comme les
conteneurs, et la matrice installe ps là où une image en manque.
Vérifié : 1776 node, 45 navigateur ; la garde tient sous LC_ALL=C.
Assisted-by: Claude Opus 5.5
2026-10-07 02:35:12 -04:00
assert . deepEqual ( optionsChromium ( UTF8 ) , { } ) ;
assert . deepEqual ( optionsChromium ( { ... UTF8 , GTT _CHROMIUM : '' } ) , { } ) ;
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
} ) ;
test ( 'GTT_CHROMIUM désigne l’ exécutable que Playwright lance' , ( ) => {
[FIX] web storage: refuse a name Chromium did not convert, UTF-8 launch
Under a non-UTF-8 locale, Chromium returns the parent folder for an
accented folder name without raising, so a write meant for that folder
replaced a file of the same name in its parent. Each step of a path walk
now compares the handle with its parent and refuses NOM_NON_CONVERTI —
LECTURE on reads, ECRITURE on writes — and nothing lands elsewhere. The
test launcher gives Chromium LANG=C.UTF-8 when the locale is not UTF-8, as
the containers do, and the matrix installs ps where an image lacks it.
Checked: 1776 node and 45 browser tests; the guard holds under LC_ALL=C.
--- FR ---
[FIX] stockage web : refuser un nom non converti, lancement en UTF-8
Hors locale UTF-8, Chromium rend le dossier parent pour un nom de dossier
accentué, sans lever : une écriture destinée à ce dossier remplaçait un
fichier homonyme de son parent. Chaque pas d'un chemin compare désormais le
dossier obtenu à son parent et refuse NOM_NON_CONVERTI — LECTURE en lecture,
ECRITURE en écriture — : rien n'atterrit ailleurs. Le lanceur des épreuves
donne LANG=C.UTF-8 à Chromium quand la locale n'est pas UTF-8, comme les
conteneurs, et la matrice installe ps là où une image en manque.
Vérifié : 1776 node, 45 navigateur ; la garde tient sous LC_ALL=C.
Assisted-by: Claude Opus 5.5
2026-10-07 02:35:12 -04:00
assert . deepEqual ( optionsChromium ( { ... UTF8 , GTT _CHROMIUM : '/nix/store/abc-chromium/bin/chromium' } ) , {
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
launchOptions : { executablePath : '/nix/store/abc-chromium/bin/chromium' } ,
} ) ;
} ) ;
[ADD] docs: photographed walkthrough publishes doc/captures
The screenshots must come from the tested walkthrough, not from a separate
script that can drift. The browser walkthrough runs on the simulated file
system with a driven clock and the direct executor, light theme, 1366 x
700 at scale 1, transitions off, and photographs each step once its
condition holds. make captures writes the images and the manifest; the
plain test run compares them instead. Eighteen captures are published, the
later ones named as postponed. The forged-names scan skips the manifest,
which records the demo names shown on screen.
Checked: red first; 3620 node, 681 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] docs : parcours photographié, publication de doc/captures
Les captures doivent venir du parcours éprouvé, non d'un script à part qui
dérive. Le parcours navigateur joue sur le système de fichiers simulé,
l'horloge pilotée et l'exécuteur direct, thème clair, 1366 × 700 au facteur
1, transitions coupées, et photographie chaque étape quand sa condition
tient. make captures écrit les images et le manifeste ; la série ordinaire
les compare au lieu de les écrire. Dix-huit captures sont publiées, les
suivantes nommées reportées. Le balayage des noms forgés saute le
manifeste, qui relève les noms de démonstration affichés.
Vérifié : rouge d'abord ; 3620 node, 681 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 15:33:59 -04:00
test ( 'vitest.config.js passe au projet navigateur les options de cet environnement, réseau et échelle compris' , ( ) => {
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
const navigateur = configuration . test . projects . find ( ( { test : { name } } ) => name === 'navigateur' ) ;
[ADD] docs: photographed walkthrough publishes doc/captures
The screenshots must come from the tested walkthrough, not from a separate
script that can drift. The browser walkthrough runs on the simulated file
system with a driven clock and the direct executor, light theme, 1366 x
700 at scale 1, transitions off, and photographs each step once its
condition holds. make captures writes the images and the manifest; the
plain test run compares them instead. Eighteen captures are published, the
later ones named as postponed. The forged-names scan skips the manifest,
which records the demo names shown on screen.
Checked: red first; 3620 node, 681 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] docs : parcours photographié, publication de doc/captures
Les captures doivent venir du parcours éprouvé, non d'un script à part qui
dérive. Le parcours navigateur joue sur le système de fichiers simulé,
l'horloge pilotée et l'exécuteur direct, thème clair, 1366 × 700 au facteur
1, transitions coupées, et photographie chaque étape quand sa condition
tient. make captures écrit les images et le manifeste ; la série ordinaire
les compare au lieu de les écrire. Dix-huit captures sont publiées, les
suivantes nommées reportées. Le balayage des noms forgés saute le
manifeste, qui relève les noms de démonstration affichés.
Vérifié : rouge d'abord ; 3620 node, 681 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 15:33:59 -04:00
assert . deepEqual ( navigateur . test . browser . provider . options , optionsNavigateur ( process . env ) ) ;
[ADD] install: Node 26 and system packages, per family and under Nix
./install.sh installs what is missing through apt, dnf, zypper or
pacman, then Node of the .node-version major from nodejs.org, SHA-256
checked, outside the repository, then npm ci and Electron's binary,
which its package no longer fetches at install; ldd refuses a missing
library. ./install_dev.sh adds Playwright's Chromium, fonts, and podman
on amd64. Under NixOS a pinned shell.nix provides Node, Electron and
Chromium, which the browser tests then launch. Build-script tests run
on Linux only, where § 16 builds.
Checked: ten library tests, three mutations caught; local install.
--- FR ---
[ADD] installation : Node 26 et paquets du système, par famille et Nix
./install.sh installe ce qui manque par apt, dnf, zypper ou pacman, puis
Node de la majeure de .node-version, de nodejs.org, somme SHA-256
vérifiée, hors du dépôt, puis npm ci et le binaire d'Electron, que son
paquet ne télécharge plus à l'installation ; ldd refuse une bibliothèque
absente. ./install_dev.sh ajoute le Chromium de Playwright, des polices,
et podman sur amd64. Sous NixOS, un shell.nix épinglé fournit Node,
Electron et Chromium, que lancent alors les épreuves du navigateur. Les
épreuves du script de construction ne se jouent que sous Linux (§ 16).
Vérifié : dix épreuves de la bibliothèque, trois mutations attrapées ;
installation locale.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 05:51:48 -04:00
} ) ;
} ) ;
[FIX] web storage: refuse a name Chromium did not convert, UTF-8 launch
Under a non-UTF-8 locale, Chromium returns the parent folder for an
accented folder name without raising, so a write meant for that folder
replaced a file of the same name in its parent. Each step of a path walk
now compares the handle with its parent and refuses NOM_NON_CONVERTI —
LECTURE on reads, ECRITURE on writes — and nothing lands elsewhere. The
test launcher gives Chromium LANG=C.UTF-8 when the locale is not UTF-8, as
the containers do, and the matrix installs ps where an image lacks it.
Checked: 1776 node and 45 browser tests; the guard holds under LC_ALL=C.
--- FR ---
[FIX] stockage web : refuser un nom non converti, lancement en UTF-8
Hors locale UTF-8, Chromium rend le dossier parent pour un nom de dossier
accentué, sans lever : une écriture destinée à ce dossier remplaçait un
fichier homonyme de son parent. Chaque pas d'un chemin compare désormais le
dossier obtenu à son parent et refuse NOM_NON_CONVERTI — LECTURE en lecture,
ECRITURE en écriture — : rien n'atterrit ailleurs. Le lanceur des épreuves
donne LANG=C.UTF-8 à Chromium quand la locale n'est pas UTF-8, comme les
conteneurs, et la matrice installe ps là où une image en manque.
Vérifié : 1776 node, 45 navigateur ; la garde tient sous LC_ALL=C.
Assisted-by: Claude Opus 5.5
2026-10-07 02:35:12 -04:00
describe ( 'chromium : les paramètres régionaux du navigateur des épreuves' , ( ) => {
test ( 'des paramètres régionaux UTF-8 laissent Chromium hériter de l’ environnement : LC_ALL, puis LC_CTYPE, puis LANG décident' , ( ) => {
const utf8 = [
{ LANG : 'C.UTF-8' } ,
{ LANG : 'C.utf8' } ,
{ LANG : 'de_DE.UTF-8@euro' } ,
{ LANG : 'C' , LC _CTYPE : 'fr_CA.utf8' } ,
{ LANG : 'C' , LC _CTYPE : 'C' , LC _ALL : 'fr_CA.UTF-8' } ,
{ LANG : 'fr_CA.UTF-8' , LC _ALL : '' , LC _CTYPE : '' } ,
] ;
for ( const env of utf8 ) assert . deepEqual ( optionsChromium ( env ) , { } , JSON . stringify ( env ) ) ;
} ) ;
test ( 'hors UTF-8, Chromium reçoit une copie de l’ environnement sous LANG=C.UTF-8, sans LC_ALL ni LC_CTYPE' , ( ) => {
const cas = [
[ { } , { } ] ,
[ { PATH : '/usr/bin' , LC _ALL : 'C' } , { PATH : '/usr/bin' } ] ,
[ { PATH : '/usr/bin' , LANG : 'POSIX' , LC _MESSAGES : 'fr_CA.UTF-8' } , { PATH : '/usr/bin' , LC _MESSAGES : 'fr_CA.UTF-8' } ] ,
[ { LANG : 'fr_CA.UTF-8' , LC _CTYPE : 'C' } , { } ] ,
[ { LANG : 'fr_CA.UTF-8' , LC _ALL : 'fr_CA.ISO-8859-1' } , { } ] ,
[ { LANG : 'C.UTF-8-ancien' } , { } ] ,
] ;
for ( const [ env , reste ] of cas ) {
const avant = { ... env } ;
assert . deepEqual (
optionsChromium ( env ) ,
{ launchOptions : { env : { ... reste , LANG : 'C.UTF-8' } } } ,
JSON . stringify ( env ) ,
) ;
assert . deepEqual ( env , avant , ` ${ JSON . stringify ( env ) } : l'environnement reçu reste tel quel ` ) ;
}
} ) ;
test ( 'hors UTF-8, GTT_CHROMIUM désigne toujours l’ exécutable, que l’ environnement accompagne' , ( ) => {
const env = { LC _ALL : 'C' , GTT _CHROMIUM : '/opt/essai/chromium' } ;
assert . deepEqual ( optionsChromium ( env ) , {
launchOptions : { executablePath : '/opt/essai/chromium' , env : { GTT _CHROMIUM : '/opt/essai/chromium' , LANG : 'C.UTF-8' } } ,
} ) ;
} ) ;
} ) ;
[ADD] docs: photographed walkthrough publishes doc/captures
The screenshots must come from the tested walkthrough, not from a separate
script that can drift. The browser walkthrough runs on the simulated file
system with a driven clock and the direct executor, light theme, 1366 x
700 at scale 1, transitions off, and photographs each step once its
condition holds. make captures writes the images and the manifest; the
plain test run compares them instead. Eighteen captures are published, the
later ones named as postponed. The forged-names scan skips the manifest,
which records the demo names shown on screen.
Checked: red first; 3620 node, 681 browser and 101 long tests green from
the index alone.
--- FR ---
[ADD] docs : parcours photographié, publication de doc/captures
Les captures doivent venir du parcours éprouvé, non d'un script à part qui
dérive. Le parcours navigateur joue sur le système de fichiers simulé,
l'horloge pilotée et l'exécuteur direct, thème clair, 1366 × 700 au facteur
1, transitions coupées, et photographie chaque étape quand sa condition
tient. make captures écrit les images et le manifeste ; la série ordinaire
les compare au lieu de les écrire. Dix-huit captures sont publiées, les
suivantes nommées reportées. Le balayage des noms forgés saute le
manifeste, qui relève les noms de démonstration affichés.
Vérifié : rouge d'abord ; 3620 node, 681 navigateur et 101 longues vertes
depuis l'index seul.
Assisted-by: Claude Opus 5.5
2026-10-09 15:33:59 -04:00
describe ( 'chromium : aucun réseau hors de la boucle locale, le facteur d’ échelle 1 (§ 19.2, § 19.4)' , ( ) => {
test ( 'les arguments du navigateur : le résolveur ne résout que la boucle locale, un mandataire mort reçoit le reste, le facteur d’ échelle est fixé au lancement' , ( ) => {
assert . deepEqual ( ARGUMENTS _NAVIGATEUR , [
'--host-resolver-rules=MAP * ~NOTFOUND, EXCLUDE localhost' ,
'--proxy-server=127.0.0.1:9' ,
'--force-device-scale-factor=1' ,
] ) ;
// La boucle locale contourne le mandataire d'office ; <-loopback> la
// ferait passer par lui, et la page des épreuves ne se chargerait plus.
assert . equal ( ARGUMENTS _NAVIGATEUR . some ( ( argument ) => argument . includes ( '<-loopback>' ) ) , false ) ;
assert . equal ( Object . isFrozen ( ARGUMENTS _NAVIGATEUR ) , true ) ;
} ) ;
test ( 'optionsNavigateur : les options de optionsChromium, les arguments ajoutés, un contexte au facteur 1 ; l’ environnement reçu reste tel quel' , ( ) => {
assert . deepEqual ( optionsNavigateur ( { LANG : 'fr_CA.UTF-8' } ) , {
launchOptions : { args : [ ... ARGUMENTS _NAVIGATEUR ] } ,
contextOptions : { deviceScaleFactor : 1 } ,
} ) ;
const env = { LC _ALL : 'C' , GTT _CHROMIUM : '/opt/essai/chromium' } ;
assert . deepEqual ( optionsNavigateur ( env ) , {
launchOptions : {
executablePath : '/opt/essai/chromium' ,
env : { GTT _CHROMIUM : '/opt/essai/chromium' , LANG : 'C.UTF-8' } ,
args : [ ... ARGUMENTS _NAVIGATEUR ] ,
} ,
contextOptions : { deviceScaleFactor : 1 } ,
} ) ;
assert . deepEqual ( env , { LC _ALL : 'C' , GTT _CHROMIUM : '/opt/essai/chromium' } ) ;
} ) ;
test ( 'horsBoucle : une adresse hors de la boucle locale est relevée ; la boucle locale et les adresses sans réseau ne le sont pas' , ( ) => {
const dehors = [
'http://192.0.2.1/' ,
'https://exemple.invalid/police.woff2' ,
'ws://198.51.100.7:8080/' ,
'http://localhost.exemple.invalid/' ,
'http://127.0.0.1.exemple.invalid/' ,
'http://[2001:db8::1]/' ,
'ftp://exemple.invalid/x' ,
'gopher://exemple.invalid/' ,
] ;
const dedans = [
'http://localhost:63315/__vitest_test__/' ,
'ws://localhost:63315/__vitest_browser_api__' ,
'http://LOCALHOST/' ,
'http://127.0.0.1:5173/collecteur.js' ,
'http://127.8.9.10/' ,
'http://[::1]:63315/' ,
'data:text/plain,x' ,
'blob:http://localhost:63315/0f3c' ,
'about:blank' ,
] ;
for ( const adresse of dehors ) assert . equal ( horsBoucle ( adresse ) , true , adresse ) ;
for ( const adresse of dedans ) assert . equal ( horsBoucle ( adresse ) , false , adresse ) ;
assert . equal ( horsBoucle ( 'pas une adresse' ) , true ) ;
} ) ;
test ( 'suivreRequetes : chaque requête hors boucle de la page, relevée une fois et dans l’ ordre ; un second suivi de la même page reprend le premier' , ( ) => {
const ecouteurs = [ ] ;
const page = { on : ( evenement , fn ) => ecouteurs . push ( [ evenement , fn ] ) } ;
const requete = ( adresse ) => ( { url : ( ) => adresse } ) ;
const suivi = suivreRequetes ( page ) ;
assert . deepEqual ( ecouteurs . map ( ( [ evenement ] ) => evenement ) , [ 'request' , 'requestfailed' ] ) ;
const [ [ , ecouter ] ] = ecouteurs ;
ecouter ( requete ( 'http://localhost:63315/a.js' ) ) ;
ecouter ( requete ( 'http://192.0.2.1/' ) ) ;
ecouter ( requete ( 'https://exemple.invalid/b' ) ) ;
assert . deepEqual ( suivreRequetes ( page ) . relever ( ) , [ 'http://192.0.2.1/' , 'https://exemple.invalid/b' ] ) ;
assert . equal ( ecouteurs . length , 2 ) ;
assert . deepEqual ( suivi . relever ( ) , [ ] ) ;
ecouter ( requete ( 'http://192.0.2.1/c' ) ) ;
assert . deepEqual ( suivi . relever ( ) , [ 'http://192.0.2.1/c' ] ) ;
assert . deepEqual ( suivreRequetes ( { on : ( ) => { } } ) . relever ( ) , [ ] ) ;
} ) ;
test ( 'suivreRequetes : chaque échec d’ une requête hors boucle, avec sa cause, relevé une fois ; ceux de la boucle locale ne le sont pas' , ( ) => {
const ecouteurs = new Map ( ) ;
const page = { on : ( evenement , fn ) => ecouteurs . set ( evenement , fn ) } ;
const suivi = suivreRequetes ( page ) ;
assert . deepEqual ( [ ... ecouteurs . keys ( ) ] , [ 'request' , 'requestfailed' ] ) ;
const echec = ( adresse , errorText ) => ( { url : ( ) => adresse , failure : ( ) => ( errorText === null ? null : { errorText } ) } ) ;
ecouteurs . get ( 'requestfailed' ) ( echec ( 'http://localhost:63315/a.js' , 'net::ERR_ABORTED' ) ) ;
ecouteurs . get ( 'requestfailed' ) ( echec ( 'http://192.0.2.1/' , 'net::ERR_PROXY_CONNECTION_FAILED' ) ) ;
ecouteurs . get ( 'requestfailed' ) ( echec ( 'http://192.0.2.1/b' , null ) ) ;
assert . deepEqual ( suivi . releverEchecs ( ) , [
{ adresse : 'http://192.0.2.1/' , cause : 'net::ERR_PROXY_CONNECTION_FAILED' } ,
{ adresse : 'http://192.0.2.1/b' , cause : null } ,
] ) ;
assert . deepEqual ( suivi . releverEchecs ( ) , [ ] ) ;
assert . deepEqual ( suivi . relever ( ) , [ ] ) ;
} ) ;
} ) ;
describe ( 'le projet navigateur : les commandes et le mode des captures d’ écran (§ 19.5)' , ( ) => {
const navigateur = configuration . test . projects . find ( ( { test : { name } } ) => name === 'navigateur' ) ;
test ( 'modeCaptures : verifier par défaut, ecrire sous GTT_CAPTURES=ecrire ; une autre valeur lève en la nommant' , ( ) => {
assert . equal ( commandesDocumentation . modeCaptures ( { } ) , 'verifier' ) ;
assert . equal ( commandesDocumentation . modeCaptures ( { GTT _CAPTURES : '' } ) , 'verifier' ) ;
assert . equal ( commandesDocumentation . modeCaptures ( { GTT _CAPTURES : 'verifier' } ) , 'verifier' ) ;
assert . equal ( commandesDocumentation . modeCaptures ( { GTT _CAPTURES : 'ecrire' } ) , 'ecrire' ) ;
assert . throws ( ( ) => commandesDocumentation . modeCaptures ( { GTT _CAPTURES : 'ecrir' } ) , /GTT_CAPTURES.*« ecrir »/ ) ;
} ) ;
test ( 'vitest.config.js fournit le mode à la page par provide, et déclare chaque commande de commandes_documentation.js' , ( ) => {
assert . deepEqual ( navigateur . test . provide , { captures : { mode : commandesDocumentation . modeCaptures ( process . env ) } } ) ;
const declarees = navigateur . test . browser . commands ;
assert . deepEqual ( Object . keys ( declarees ) . sort ( ) , [ ... commandesDocumentation . COMMANDES ] . sort ( ) ) ;
for ( const nom of commandesDocumentation . COMMANDES ) {
assert . equal ( typeof commandesDocumentation [ nom ] , 'function' , nom ) ;
assert . equal ( declarees [ nom ] , commandesDocumentation [ nom ] , nom ) ;
}
assert . ok ( commandesDocumentation . COMMANDES . length > 0 ) ;
} ) ;
test ( 'make captures lance le parcours du projet navigateur sous GTT_CAPTURES=ecrire, par avec_node ; .gitignore tait le dossier d’ attente' , ( ) => {
const makefile = readFileSync ( join ( RACINE , 'Makefile' ) , 'utf8' ) ;
assert . match ( makefile , /^\.PHONY: captures$/m ) ;
assert . match ( makefile , /^captures: export GTT_CAPTURES := ecrire$/m ) ;
assert . match (
makefile ,
/^captures: ## Photographie le parcours et publie doc\/captures \(§ 19\.5\)\n\t\$\(AVEC_NODE\) npx vitest run --project navigateur src\/interface\/parcours\.navigateur\.test\.js$/m ,
) ;
const ignores = readFileSync ( join ( RACINE , '.gitignore' ) , 'utf8' ) . split ( '\n' ) ;
assert . ok ( ignores . includes ( 'doc/captures/.attente/' ) , ignores . join ( ' | ' ) ) ;
assert . equal ( ignores . some ( ( ligne ) => / ^ doc \ / captures \ / ? $ | ^ doc \ / ? $ | \ * \ . png / . test ( ligne ) ) , false ) ;
} ) ;
} ) ;