[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
// Gardes de l'arborescence, lues dans le texte des sources : le moteur, la
// géométrie du plan, le générateur de démonstrations, le stockage et
// l'analyseur CSV n'appellent aucune source non reproductible (§ 14.7), et ne parcourent les clés d'un
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// objet que par exception nommée (§ 15.5, point 4) ; le graphe d'imports de
// chaque couche ne rejoint que ce que le § 13.4 lui permet ; chaque paquet
// importé est déclaré dans devDependencies ; une valeur du contrat de données
// n'a qu'une définition, celle de configuration.js ; la mesure de la
// couverture joue la série node, publie chaque module et tient ses seuils
// durs sur des modules qui existent (§ 14.13). Chaque relevé lit le
// texte entier, commentaires et chaînes compris, hors celui des accès au
// navigateur, qui saute les chaînes littérales : un commentaire qui nomme un
// appel refusé fait échouer la garde comme l'appel lui-même. Chaque garde
// refuse de passer sur un balayage vide (§ 14.2), et d'autres épreuves la
// font tourner sur des arbres temporaires qui portent, à plus d'un niveau de
// profondeur, les formes qu'elle refuse et des formes voisines qu'elle admet.
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
import assert from 'node:assert/strict' ;
import { existsSync , mkdirSync , mkdtempSync , readdirSync , readFileSync , rmSync , writeFileSync } from 'node:fs' ;
import { isBuiltin } from 'node:module' ;
import { tmpdir } from 'node:os' ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
import { dirname , extname , join , matchesGlob , relative , resolve , sep } from 'node:path' ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
import { fileURLToPath } from 'node:url' ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
import configuration from '../vitest.config.js' ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
import { chargements } from './chargements.js' ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
import { describe , test } from './lanceur.js' ;
const RACINE = fileURLToPath ( new URL ( '..' , import . meta . url ) ) ;
// Écrit dans un répertoire temporaire l'arbre { chemin relatif: contenu }, le
// passe à examiner, puis l'efface ; rend ce que rend examiner.
function avecArbre ( fichiers , examiner ) {
const racine = mkdtempSync ( join ( tmpdir ( ) , 'arborescence-' ) ) ;
try {
for ( const [ chemin , contenu ] of Object . entries ( fichiers ) ) {
mkdirSync ( dirname ( join ( racine , chemin ) ) , { recursive : true } ) ;
writeFileSync ( join ( racine , chemin ) , contenu ) ;
}
return examiner ( racine ) ;
} finally {
rmSync ( racine , { recursive : true , force : true } ) ;
}
}
// Fichiers d'un arbre, à toute profondeur, en chemins absolus. Un arbre
// absent n'en fournit aucun.
function fichiersDe ( dossier ) {
try {
return readdirSync ( dossier , { withFileTypes : true , recursive : true } )
. filter ( ( e ) => e . isFile ( ) )
. map ( ( e ) => join ( e . parentPath , e . name ) ) ;
} catch ( erreur ) {
if ( erreur . code === 'ENOENT' ) return [ ] ;
throw erreur ;
}
}
// Modules d'un arbre : ses fichiers JavaScript, épreuves exclues, triés.
const EXTENSIONS _MODULE = new Set ( [ '.js' , '.mjs' , '.cjs' ] ) ;
const EPREUVE = /\.test\.[cm]?js$/ ;
const modulesDe = ( dossier ) =>
fichiersDe ( dossier )
. filter ( ( fichier ) => EXTENSIONS _MODULE . has ( extname ( fichier ) ) && ! EPREUVE . test ( fichier ) )
. sort ( ) ;
// Numéro, à partir de 1, de la ligne qui porte le caractère d'indice donné.
const ligneDe = ( texte , indice ) => texte . slice ( 0 , indice ) . split ( '\n' ) . length ;
// Appels dont le résultat change d'une exécution à l'autre, ou d'un poste à
// l'autre : localeCompare, Intl et les méthodes toLocale… suivent la langue
// et les données régionales du moteur d'exécution (§ 14.7, § 15.5). Chaque
// motif à point admet des blancs autour de lui, que la mise en forme
// introduit quand elle coupe une chaîne d'appels, et le chaînage optionnel.
// Math, Date et performance suivis d'un crochet, accolé ou après « ?. »,
// sont refusés eux aussi, quel que soit le membre nommé. new Date se relève
// avec ou sans parenthèses, et Date appelée sans new, « Date() » comme
// « Date?.() », rend elle aussi l'heure courante. getRandomValues,
// randomUUID et les tirages de node:crypto — randomInt, randomBytes,
// randomFill — se reconnaissent au nom de la fonction, quel que soit l'objet
// qui la porte ou l'import qui la nomme.
const SOURCES _NON _REPRODUCTIBLES = [
[ 'Math.random' , /\bMath\s*\??\.\s*random\b/g ] ,
[ 'Math[' , /\bMath\s*(?:\?\.)?\s*\[/g ] ,
[ 'Date.now' , /\bDate\s*\??\.\s*now\b/g ] ,
[ 'Date[' , /\bDate\s*(?:\?\.)?\s*\[/g ] ,
[ 'new Date' , /\bnew\s+Date\b/g ] ,
[ 'Date()' , /(?<!\bnew\s+)\bDate\s*(?:\?\.\s*)?\(/g ] ,
[ 'performance.now' , /\bperformance\s*\??\.\s*now\b/g ] ,
[ 'performance[' , /\bperformance\s*(?:\?\.)?\s*\[/g ] ,
[ 'crypto.getRandomValues' , /\bgetRandomValues\b/g ] ,
[ 'crypto.randomUUID' , /\brandomUUID\b/g ] ,
[ 'localeCompare' , /\blocaleCompare\b/g ] ,
[ 'toLocale…' , /\btoLocale\w*/g ] ,
[ 'Intl' , /\bIntl\b/g ] ,
[ 'crypto.randomInt' , /\brandomInt\b/g ] ,
[ 'crypto.randomBytes' , /\brandomBytes\b/g ] ,
[ 'crypto.randomFill' , /\brandomFill(?:Sync)?\b/g ] ,
] ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
// Parcours des clés d'un objet (§ 15.5, point 4) : les clés entières y
// viennent d'abord, croissantes, puis les autres dans l'ordre où l'objet les
// a reçues. Un résultat qui en dépend change quand l'objet se construit
// autrement, sans qu'aucune épreuve ne le voie ; un départage se fait par
// identifiant entier. Les motifs à point suivent les règles de
// SOURCES_NON_REPRODUCTIBLES, et Object suivi d'un crochet est refusé quel
// que soit le membre nommé. for…in se relève sur une variable, un chemin
// pointé ou un motif de déstructuration suivi de « in », avec ou sans
// déclaration : la boucle à compteur, for…of et l'opérateur in hors d'une
// boucle n'en sont pas.
const PARCOURS _DE _CLES = [
[ 'Object.keys' , /\bObject\s*\??\.\s*keys\b/g ] ,
[ 'Object.entries' , /\bObject\s*\??\.\s*entries\b/g ] ,
[ 'Object.values' , /\bObject\s*\??\.\s*values\b/g ] ,
[FIX] tests: four-core budget, quoted values, key guard, switch floor
The relaunch budget of § 14.14 was out of reach on two cores whatever the
tests did; the spec now names its reference machine, four cores, and the
watched series drops a 200 000-move search the long series already runs.
The itinerary guard quotes a string value as the indexed-plan guard does,
through one shared helper. The key-order guard no longer mistakes the
JSDoc type {Object[]} for a computed access, and the property grid counts
the proposals that switch to the constraint order, under a floor.
Checked: 456 node tests in 1.8 s; each new test failed first; cutting the
descent to one move drops the switch count from 86 to 30, under its floor.
--- FR ---
[FIX] épreuves : budget sur quatre cœurs, citation, clés, bascule
Le budget de relance du § 14.14 était hors d'atteinte sur deux cœurs,
quoi que fassent les épreuves ; le spec nomme désormais sa machine de
référence, quatre cœurs, et la série surveillée quitte une recherche de
200 000 mouvements que la série longue joue déjà. La garde d'itinéraire
cite une chaîne comme la garde du plan indexé, par un seul assistant. La
garde de l'ordre des clés ne prend plus le type JSDoc {Object[]} pour un
accès calculé, et la grille compte, sous un plancher, les propositions
qui basculent dans l'ordre des contraintes.
Vérifié : 456 épreuves node en 1,8 s ; chaque épreuve nouvelle a échoué
d'abord ; une descente coupée au premier mouvement fait tomber les
bascules de 86 à 30, sous leur plancher.
Assisted-by: Claude Opus 5.5
2026-10-06 04:26:08 -04:00
[ 'Object[' , /\bObject\s*(?:\?\.)?\s*\[(?!\s*\])/g ] ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
[ 'for…in' , /\bfor\s*\(\s*(?:(?:const|let|var)\s+)?(?:[\p{L}_$][\p{L}\p{N}_$.]*|\[[^\]]*\]|\{[^}]*\})\s+in\b/gu ] ,
[ 'Reflect.ownKeys' , /\bReflect\s*\??\.\s*ownKeys\b/g ] ,
[ 'Object.getOwnPropertyNames' , /\bObject\s*\??\.\s*getOwnPropertyNames\b/g ] ,
] ;
// Parcours de clés admis, chacun nommé par son fichier, relatif à la racine,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// et par un motif : l'expression régulière de la forme admise, qui se lit à
// partir du parcours relevé, sur une ligne ou sur plusieurs — non un numéro
// de ligne, qu'un ajout au-dessus déplace. Sa raison dit pourquoi l'ordre n'y
// décide d'aucun résultat. Une exception admet dans son fichier chaque
// parcours de sa forme, et rien d'autre : le parcours écrit autrement, ou un
// second parcours sur la même ligne, se relève. Elle ne couvre aucune source
// de SOURCES_NON_REPRODUCTIBLES, que rien n'admet.
const PARCOURS _DE _CLES _ADMIS = [
{
fichier : join ( 'src' , 'stockage' , 'document.js' ) ,
motif : /Object\s*\.\s*keys\s*\(\s*\w+\s*\)\s*\.\s*sort\s*\(\s*comparerTextes\s*\)/ ,
raison :
'clesRangees, que lisent le relevé des clés inconnues et la recopie de canonique.js : ' +
"les clés propres d'un objet, rangées sur-le-champ par comparerTextes, un ordre total des chaînes ; " +
'le résultat ne dépend que de leur ensemble' ,
} ,
] ;
// Arbres dont les modules ne lisent aucune source non reproductible (§ 14.7) :
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
// le moteur, la géométrie du plan et le générateur de démonstrations, puis le
// stockage et l'analyseur CSV, qui reçoivent l'horloge et l'aléa de
// l'application, en paramètre.
const ARBRES _DETERMINISTES = [ 'src/moteur' , 'src/geometrie' , 'src/demo' , 'src/stockage' , 'src/csv' ] ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// Vrai quand le motif se lit dans le texte à partir de l'indice donné, et non
// plus loin : une copie collante du motif, ses drapeaux g et y retirés.
function seLitA ( motif , texte , indice ) {
const collant = new RegExp ( motif . source , ` ${ motif . flags . replace ( /[gy]/g , '' ) } y ` ) ;
collant . lastIndex = indice ;
return collant . test ( texte ) ;
}
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
// Relevé « fichier:ligne appel » des sources non reproductibles et des
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// parcours de clés non admis dans les modules de ARBRES_DETERMINISTES, arbre
// par arbre, puis par fichier et par ligne, et sur une même ligne dans
// l'ordre de SOURCES_NON_REPRODUCTIBLES puis de PARCOURS_DE_CLES. Les
// épreuves en sont exclues : un tirage y sert légitimement (§ 14.12). Suit une
// ligne « exception sans objet : fichier /motif/ » par exception qui n'admet
// rien, dans l'ordre de la liste. Lève quand l'un des arbres ne fournit aucun
// module.
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
function releverDeterminisme ( racine , admis = PARCOURS _DE _CLES _ADMIS ) {
const servies = new Set ( ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// Vrai quand une exception du fichier admet le parcours relevé à l'indice
// donné : son motif s'y lit.
const estAdmis = ( fichier , texte , indice ) => {
const exception = admis . find ( ( e ) => e . fichier === fichier && seLitA ( e . motif , texte , indice ) ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
if ( exception !== undefined ) servies . add ( exception ) ;
return exception !== undefined ;
} ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
const releve = ARBRES _DETERMINISTES . flatMap ( ( arbre ) => {
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
const modules = modulesDe ( join ( racine , arbre ) ) ;
assert . ok ( modules . length > 0 , ` ${ arbre } ne fournit aucun module ` ) ;
return modules . flatMap ( ( fichier ) => {
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
const nom = relative ( racine , fichier ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
const texte = readFileSync ( fichier , 'utf8' ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
const trouves = ( motifs ) =>
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
motifs . flatMap ( ( [ appel , motif ] ) => [ ... texte . matchAll ( motif ) ] . map ( ( { index } ) => ( { index , appel } ) ) ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
return [
... trouves ( SOURCES _NON _REPRODUCTIBLES ) ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
... trouves ( PARCOURS _DE _CLES ) . filter ( ( { index } ) => ! estAdmis ( nom , texte , index ) ) ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
]
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
. map ( ( { index , appel } ) => ( { ligne : ligneDe ( texte , index ) , appel } ) )
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
. sort ( ( a , b ) => a . ligne - b . ligne )
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
. map ( ( { ligne , appel } ) => ` ${ nom } : ${ ligne } ${ appel } ` ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
} ) ;
} ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
const sansObjet = admis
. filter ( ( exception ) => ! servies . has ( exception ) )
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
. map ( ( { fichier , motif } ) => ` exception sans objet : ${ fichier } ${ motif } ` ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
return [ ... releve , ... sansObjet ] ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
}
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// Un module vide dans chaque arbre que les gardes exigent : une donnée
// d'épreuve y ajoute ce qu'elle éprouve, ou en retire un arbre (sansArbre)
// pour éprouver le refus d'un balayage vide.
const MODULES _VIDES = Object . freeze ( {
'src/moteur/a.js' : '' ,
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
'src/geometrie/a.js' : '' ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
'src/demo/a.js' : '' ,
'src/stockage/a.js' : '' ,
'src/csv/a.js' : '' ,
} ) ;
// Les fichiers donnés, sans ceux de l'arbre nommé.
const sansArbre = ( fichiers , arbre ) =>
Object . fromEntries ( Object . entries ( fichiers ) . filter ( ( [ chemin ] ) => ! chemin . startsWith ( ` ${ arbre } / ` ) ) ) ;
// Le relevé du déterminisme sans exception : une donnée d'épreuve ne porte pas
// les fichiers que nomment les exceptions de l'arbre réel.
const releverSansException = ( racine ) => releverDeterminisme ( racine , [ ] ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
describe ( 'arborescence : déterminisme (§ 14.7)' , ( ) => {
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
test ( "ni src/moteur, ni src/geometrie, ni src/demo, ni src/stockage, ni src/csv ne lisent une source non reproductible, ni ne parcourent les clés d'un objet hors des exceptions nommées" , ( ) => {
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
assert . deepEqual ( releverDeterminisme ( RACINE ) , [ ] ) ;
} ) ;
test ( 'les tirages de node:crypto se relèvent comme ceux du navigateur' , ( ) => {
const fichiers = {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
... MODULES _VIDES ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/moteur/a.js' : 'export const a = 1;\n' ,
'src/demo/tirage.js' : [
"import { randomInt, randomBytes, randomFillSync } from 'node:crypto';" ,
'export const a = randomInt(6);' ,
'export const b = randomBytes(4);' ,
'export const c = randomFillSync(new Uint8Array(4));' ,
] . join ( '\n' ) ,
} ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
assert . deepEqual ( avecArbre ( fichiers , releverSansException ) , [
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/demo/tirage.js:1 crypto.randomInt' ,
'src/demo/tirage.js:1 crypto.randomBytes' ,
'src/demo/tirage.js:1 crypto.randomFill' ,
'src/demo/tirage.js:2 crypto.randomInt' ,
'src/demo/tirage.js:3 crypto.randomBytes' ,
'src/demo/tirage.js:4 crypto.randomFill' ,
] ) ;
} ) ;
test ( 'la garde relève chaque appel par sa ligne, à toute profondeur, hors épreuves, et refuse un arbre sans module' , ( ) => {
const fichiers = {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
... MODULES _VIDES ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/moteur/tirage.js' : [
'export const a = Math.random();' ,
'export const b = Date.now() - performance.now();' ,
'export const c = new Date(0);' ,
'export const d = globalThis.crypto.getRandomValues(new Uint32Array(1));' ,
"export const e = ['b', 'a'].sort((x, y) => x.localeCompare(y));" ,
'export const f = Math' ,
' .random;' ,
'export const i = Date' ,
' .now() + performance .now();' ,
'export const j = globalThis.crypto' ,
' .getRandomValues(t);' ,
'export const k = new Date;' ,
'export const p = Date();' ,
'export const q = crypto.randomUUID();' ,
"export const r = Math['random']();" ,
"export const s = new Intl.Collator('fr').compare;" ,
"export const u = 'É'.toLocaleLowerCase();" ,
'export const v = webcrypto.getRandomValues(t);' ,
'const { Collator } = Intl;' ,
'export const x = source.randomUUID();' ,
'export const y = (1234.5).toLocaleString();' ,
'export const t1 = globalThis.performance?.now?.() ?? 0;' ,
'export const t2 = Date?.now() + Math?.random();' ,
"export const t3 = performance['now']();" ,
"export const t4 = Date['now']() + Math?.['random']();" ,
"export const t5 = Date?.['now']() - performance?.['now']();" ,
'export const t6 = Date?.();' ,
] . join ( '\n' ) ,
'src/moteur/tirage.test.js' : 'export const g = Math.random();\n' ,
'src/moteur/sous/profond.js' : 'export const l = Math.random();\n' ,
'src/demo/propre.js' : [
'export const h = Math.floor(2.5) + Date.UTC(2000, 0, 1);' ,
'export const mathRandom = 1;' ,
'export const debutDate = { now: 2 };' ,
'export const m = debutDate.now + xMath.random;' ,
"export const w = 'É'.toLowerCase();" ,
] . join ( '\n' ) ,
'src/demo/tirage.mjs' : 'export const n = Math.random();\n' ,
'src/demo/tirage.cjs' : 'module.exports = Date.now();\n' ,
'src/demo/tirage.test.mjs' : 'export const o = Math.random();\n' ,
'src/demo/tirage.test.cjs' : 'module.exports = Math.random();\n' ,
} ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
assert . deepEqual ( avecArbre ( fichiers , releverSansException ) , [
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/moteur/sous/profond.js:1 Math.random' ,
'src/moteur/tirage.js:1 Math.random' ,
'src/moteur/tirage.js:2 Date.now' ,
'src/moteur/tirage.js:2 performance.now' ,
'src/moteur/tirage.js:3 new Date' ,
'src/moteur/tirage.js:4 crypto.getRandomValues' ,
'src/moteur/tirage.js:5 localeCompare' ,
'src/moteur/tirage.js:6 Math.random' ,
'src/moteur/tirage.js:8 Date.now' ,
'src/moteur/tirage.js:9 performance.now' ,
'src/moteur/tirage.js:11 crypto.getRandomValues' ,
'src/moteur/tirage.js:12 new Date' ,
'src/moteur/tirage.js:13 Date()' ,
'src/moteur/tirage.js:14 crypto.randomUUID' ,
'src/moteur/tirage.js:15 Math[' ,
'src/moteur/tirage.js:16 Intl' ,
'src/moteur/tirage.js:17 toLocale…' ,
'src/moteur/tirage.js:18 crypto.getRandomValues' ,
'src/moteur/tirage.js:19 Intl' ,
'src/moteur/tirage.js:20 crypto.randomUUID' ,
'src/moteur/tirage.js:21 toLocale…' ,
'src/moteur/tirage.js:22 performance.now' ,
'src/moteur/tirage.js:23 Math.random' ,
'src/moteur/tirage.js:23 Date.now' ,
'src/moteur/tirage.js:24 performance[' ,
'src/moteur/tirage.js:25 Math[' ,
'src/moteur/tirage.js:25 Date[' ,
'src/moteur/tirage.js:26 Date[' ,
'src/moteur/tirage.js:26 performance[' ,
'src/moteur/tirage.js:27 Date()' ,
'src/demo/tirage.cjs:1 Date.now' ,
'src/demo/tirage.mjs:1 Math.random' ,
] ) ;
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
for ( const arbre of [ 'src/moteur' , 'src/geometrie' , 'src/demo' , 'src/stockage' , 'src/csv' ] ) {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
const sansModule = { ... sansArbre ( MODULES _VIDES , arbre ) , [ ` ${ arbre } /a.test.js ` ] : '' } ;
assert . throws (
( ) => avecArbre ( sansModule , releverSansException ) ,
new RegExp ( ` ${ arbre } ne fournit aucun module ` ) ,
arbre ,
) ;
}
} ) ;
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
test ( 'src/geometrie se relève comme le moteur, à toute profondeur, hors épreuves' , ( ) => {
const fichiers = {
... MODULES _VIDES ,
'src/geometrie/vue.js' : [
'export const a = Math.random();' ,
'export const b = (o) => Object.keys(o).map((cle) => o[cle]);' ,
'export const c = Math.min(1, 2) + Math.floor(2.5);' ,
] . join ( '\n' ) ,
'src/geometrie/sous/texte.js' : 'for (const champ in ligne) t.push(champ);\n' ,
'src/geometrie/vue.test.js' : 'export const d = Math.random() + Object.keys(o).length;\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverSansException ) , [
'src/geometrie/sous/texte.js:1 for…in' ,
'src/geometrie/vue.js:1 Math.random' ,
'src/geometrie/vue.js:2 Object.keys' ,
] ) ;
} ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
test ( 'src/stockage et src/csv se relèvent comme le moteur et le générateur, à toute profondeur, hors épreuves' , ( ) => {
const fichiers = {
... MODULES _VIDES ,
'src/stockage/horloge.js' : [
'export const a = Date.now();' ,
'export const b = (o) => Object.keys(o).map((cle) => o[cle]);' ,
'export const c = new Date();' ,
] . join ( '\n' ) ,
'src/stockage/sous/tri.js' : 'export const d = (t) => t.sort((x, y) => x.localeCompare(y));\n' ,
'src/stockage/horloge.test.js' : 'export const e = Date.now();\n' ,
'src/csv/tirage.js' : [
'export const f = crypto.randomUUID();' ,
'for (const champ in ligne) t.push(champ);' ,
] . join ( '\n' ) ,
'src/csv/sous/profond.js' : 'export const g = performance.now();\n' ,
'src/csv/tirage.test.js' : 'export const h = Math.random();\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverSansException ) , [
'src/stockage/horloge.js:1 Date.now' ,
'src/stockage/horloge.js:2 Object.keys' ,
'src/stockage/horloge.js:3 new Date' ,
'src/stockage/sous/tri.js:1 localeCompare' ,
'src/csv/sous/profond.js:1 performance.now' ,
'src/csv/tirage.js:1 crypto.randomUUID' ,
'src/csv/tirage.js:2 for…in' ,
] ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
} ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
test ( "les parcours des clés d'un objet se relèvent par leur ligne, hors épreuves, et pas leurs voisins (§ 15.5, point 4)" , ( ) => {
const fichiers = {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
... MODULES _VIDES ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
'src/moteur/cles.js' : [
'export const a = Object.keys(o);' ,
'export const b = Object.entries(o).map(f);' ,
'export const c = Object.values(o);' ,
'for (const k in o) t.push(k);' ,
'for (k in o) t.push(k);' ,
'export const d = Object' ,
' .keys(o);' ,
'export const e = Object?.entries?.(o);' ,
"export const g = Object['keys'](o);" ,
'for(let k in o){}' ,
'for (const [k] in o) t.push(k);' ,
'for (var { length } in o) t.push(length);' ,
'export const h = Reflect.ownKeys(o);' ,
'export const i = Object.getOwnPropertyNames(o);' ,
'for (const k of Object.keys(o)) t.push(k);' ,
'for (a.b in o) t.push(a.b);' ,
] . join ( '\n' ) ,
'src/moteur/cles.test.js' : 'export const x = Object.keys(o);\n' ,
'src/demo/voisins.js' : [
'for (let i = 0; i < n; i += 1) t.push(i);' ,
'for (const v of Object.freeze([])) t.push(v);' ,
"export const f = 'k' in o;" ,
'for (const [k, v] of m) t.push(k, v);' ,
'export const z = monObject.keys + objectKeys;' ,
'export const w = Object.fromEntries(paires);' ,
'for (const index of inventaire) t.push(index);' ,
[FIX] tests: four-core budget, quoted values, key guard, switch floor
The relaunch budget of § 14.14 was out of reach on two cores whatever the
tests did; the spec now names its reference machine, four cores, and the
watched series drops a 200 000-move search the long series already runs.
The itinerary guard quotes a string value as the indexed-plan guard does,
through one shared helper. The key-order guard no longer mistakes the
JSDoc type {Object[]} for a computed access, and the property grid counts
the proposals that switch to the constraint order, under a floor.
Checked: 456 node tests in 1.8 s; each new test failed first; cutting the
descent to one move drops the switch count from 86 to 30, under its floor.
--- FR ---
[FIX] épreuves : budget sur quatre cœurs, citation, clés, bascule
Le budget de relance du § 14.14 était hors d'atteinte sur deux cœurs,
quoi que fassent les épreuves ; le spec nomme désormais sa machine de
référence, quatre cœurs, et la série surveillée quitte une recherche de
200 000 mouvements que la série longue joue déjà. La garde d'itinéraire
cite une chaîne comme la garde du plan indexé, par un seul assistant. La
garde de l'ordre des clés ne prend plus le type JSDoc {Object[]} pour un
accès calculé, et la grille compte, sous un plancher, les propositions
qui basculent dans l'ordre des contraintes.
Vérifié : 456 épreuves node en 1,8 s ; chaque épreuve nouvelle a échoué
d'abord ; une descente coupée au premier mouvement fait tomber les
bascules de 86 à 30, sous leur plancher.
Assisted-by: Claude Opus 5.5
2026-10-06 04:26:08 -04:00
'/** @param {Object[]} entrees les entrées, dans leur ordre */' ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
] . join ( '\n' ) ,
} ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
assert . deepEqual ( avecArbre ( fichiers , releverSansException ) , [
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
'src/moteur/cles.js:1 Object.keys' ,
'src/moteur/cles.js:2 Object.entries' ,
'src/moteur/cles.js:3 Object.values' ,
'src/moteur/cles.js:4 for…in' ,
'src/moteur/cles.js:5 for…in' ,
'src/moteur/cles.js:6 Object.keys' ,
'src/moteur/cles.js:8 Object.entries' ,
'src/moteur/cles.js:9 Object[' ,
'src/moteur/cles.js:10 for…in' ,
'src/moteur/cles.js:11 for…in' ,
'src/moteur/cles.js:12 for…in' ,
'src/moteur/cles.js:13 Reflect.ownKeys' ,
'src/moteur/cles.js:14 Object.getOwnPropertyNames' ,
'src/moteur/cles.js:15 Object.keys' ,
'src/moteur/cles.js:16 for…in' ,
] ) ;
} ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
test ( "une exception nommée par motif n'admet, dans son fichier, que les parcours de sa forme, sur une ligne ou plusieurs ; une exception sans objet se relève" , ( ) => {
const somme = 'Object.values(o).reduce((s, v) => s + v, 0)' ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
const fichiers = {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
... MODULES _VIDES ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
'src/moteur/a.js' : 'export const a = Math.random();\n' ,
'src/demo/somme.js' : [
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
` export const total = (o) => ${ somme } ; ` ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
'export const nombre = (o) => Object.keys(o).length;' ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
` export const double = (o) => 2 * ${ somme } + Object.values(o).length; ` ,
'export const reste = (o) =>' ,
' Object' ,
' .values(o).reduce((s, v) => s + v, 0);' ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
] . join ( '\n' ) ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
'src/demo/autre.js' : ` export const total = (o) => ${ somme } ; \n ` ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
} ;
const exceptions = [
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
{
fichier : 'src/demo/somme.js' ,
motif : /Object\s*\.\s*values\(o\)\.reduce\(\(s, v\) => s \+ v, 0\)/ ,
raison : "une somme d'entiers ne dépend pas de l'ordre de ses termes" ,
} ,
{ fichier : 'src/moteur/a.js' , motif : /Math\.random\(\)/ , raison : 'un tirage ne se nomme pas en exception' } ,
{ fichier : 'src/demo/disparu.js' , motif : /for \(const k in o\)/ , raison : 'le fichier a disparu' } ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
] ;
assert . deepEqual ( avecArbre ( fichiers , ( racine ) => releverDeterminisme ( racine , exceptions ) ) , [
'src/moteur/a.js:1 Math.random' ,
'src/demo/autre.js:1 Object.values' ,
'src/demo/somme.js:2 Object.keys' ,
'src/demo/somme.js:3 Object.values' ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
` exception sans objet : src/moteur/a.js ${ exceptions [ 1 ] . motif } ` ,
` exception sans objet : src/demo/disparu.js ${ exceptions [ 2 ] . motif } ` ,
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
] ) ;
} ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
} ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
// Chargements d'un texte qui désignent un spécificateur, dans l'ordre du
// texte, chacun { indice, specificateur } : ceux que relève l'analyseur
// commun (test/chargements.js), moins les arguments calculés, qui ne
// désignent aucun module.
const chargementsLitteraux = ( texte ) =>
chargements ( texte ) . filter ( ( { specificateur } ) => specificateur !== undefined ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
// « ./ » ou « ../ » en tête, ou « . » et « .. » seuls.
const RELATIF = /^\.{1,2}(?:\/|$)/ ;
// Nom du paquet que désigne un spécificateur nu : son premier segment, ou
// ses deux premiers pour un paquet à portée (@portée/nom).
const nomDePaquet = ( specificateur ) =>
specificateur . split ( '/' ) . slice ( 0 , specificateur . startsWith ( '@' ) ? 2 : 1 ) . join ( '/' ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// Les paquets de l'interface et des plateformes, sous-chemins compris, dont
// le motif s'applique au nom de paquet.
const PAQUETS _DE _PLATEFORME = /^(?:svelte|electron|@capacitor\/.+)$/ ;
// La frontière de chaque couche (§ 13.4), dans l'ordre du relevé. arbres :
// ceux de ses modules, dont requis nomme ceux qui doivent en fournir au moins
// un — une couche encore à écrire peut manquer. exterieures : les couches de
// src/ qu'elle n'importe pas. paquets : ceux qu'elle refuse, outre les
// modules natifs de Node, que la page n'a pas et qu'aucune couche ne charge.
// navigateur : null quand la couche y accède librement ; sinon, les fichiers
// admis à y accéder, chacun dans son seul texte. Aucun module du parcours
// n'importe un fichier admis : il ne passe qu'en paramètre, de la main de
// l'application.
//
// Le moteur et la géométrie ne connaissent ni l'écran, ni les fichiers, ni ce
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
// qui les commande. La géométrie est une couche à part, plus bas que le
// moteur : des fonctions pures du plan, qui n'importent ni le moteur, ni
// l'analyseur CSV, ni le générateur de démonstrations. Le stockage lit et écrit par le système de fichiers qu'il
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// reçoit ; seules ses deux implémentations de plateforme touchent le
// navigateur, par l'OPFS sous web et par le pont window.gtt sous Electron.
// L'analyseur CSV lit le modèle du stockage. L'application câble le moteur,
// le stockage, le CSV et les systèmes de fichiers des plateformes, sous
// l'interface.
const COUCHES = [
{
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
arbres : [ 'src/moteur' ] ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
requis : [ 'src/moteur' ] ,
exterieures : [ 'interface' , 'application' , 'stockage' ] ,
paquets : PAQUETS _DE _PLATEFORME ,
navigateur : [ ] ,
} ,
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
{
arbres : [ 'src/geometrie' ] ,
requis : [ 'src/geometrie' ] ,
exterieures : [ 'interface' , 'application' , 'stockage' , 'moteur' , 'csv' , 'demo' ] ,
paquets : PAQUETS _DE _PLATEFORME ,
navigateur : [ ] ,
} ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
{
arbres : [ 'src/stockage' ] ,
requis : [ 'src/stockage' ] ,
exterieures : [ 'interface' , 'application' , 'csv' ] ,
paquets : PAQUETS _DE _PLATEFORME ,
navigateur : [ 'src/stockage/fichiers_web.js' , 'src/stockage/fichiers_electron.js' ] ,
} ,
{
arbres : [ 'src/csv' ] ,
requis : [ 'src/csv' ] ,
exterieures : [ 'interface' , 'application' ] ,
paquets : PAQUETS _DE _PLATEFORME ,
navigateur : [ ] ,
} ,
{
arbres : [ 'src/application' ] ,
requis : [ ] ,
exterieures : [ 'interface' ] ,
paquets : /^svelte$/ ,
navigateur : null ,
} ,
] ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
// Un accès au navigateur est un nom de document, de window, de navigator, de
// location, de localStorage ou de sessionStorage suivi d'un crochet, ou
// d'un point puis d'un nom de propriété, accolé ou en tête de la ligne
// suivante. Une phrase qui continue après « document. » sur la même ligne
// n'en est pas un, ni une ligne qui finit sur ce mot quand la suivante
// s'ouvre sur autre chose qu'un nom, un commentaire par exemple. Le relevé
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// lit le texte que rend sansChaines : le spécificateur « './document.js' »
// nomme un fichier, et une chaîne n'accède à rien. Il ne distingue pas le
// commentaire du code : une ligne de commentaire qui finit sur « document. »
// juste avant une ligne de code se lit comme un accès.
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
const ACCES _AU _DOM = /\b(document|window|navigator|location|localStorage|sessionStorage)\s*(?:\??\.(?=[\p{L}_$]|[ \t]*\r?\n\s*[\p{L}_$])|(?:\?\.)?\s*\[)/gu ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// Mots après lesquels une barre oblique ouvre une expression régulière
// littérale, comme après un opérateur, et non une division.
const MOTS _AVANT _EXPRESSION = new Set ( [
'await' , 'case' , 'delete' , 'do' , 'else' , 'in' , 'instanceof' , 'new' , 'of' , 'return' , 'throw' , 'typeof' , 'void' , 'yield' ,
] ) ;
const LETTRE _DE _MOT = /[\p{L}\p{N}_$]/u ;
const BLANC = /\s/ ;
// Le texte où chaque caractère d'une chaîne littérale — entre apostrophes,
// entre guillemets, ou partie littérale d'un gabarit entre accents graves —
// devient une espace, délimiteurs et fins de ligne gardés : les indices et
// les numéros de ligne restent ceux du texte. Les commentaires restent tels
// quels, et une apostrophe qui y figure n'ouvre aucune chaîne ; le code
// d'une substitution ${…} reste lu, chaînes blanchies. Une barre oblique
// ouvre une expression régulière littérale après rien, après un opérateur ou
// une ponctuation autre que « ) » et « ] », ou après un mot comme return ;
// l'expression reste telle quelle, et un guillemet de sa classe n'ouvre pas
// de chaîne. Une chaîne entre apostrophes ou guillemets, comme une
// expression, s'arrête au plus tard à la fin de sa ligne : une barre mal lue
// n'y fait blanchir que la fin de cette ligne. Un accent grave mal lu, lui,
// ouvrirait un gabarit jusqu'au suivant.
function sansChaines ( texte ) {
let sortie = '' ;
let i = 0 ;
const recopier = ( fin ) => {
sortie += texte . slice ( i , fin ) ;
i = fin ;
} ;
const blanchir = ( fin ) => {
for ( ; i < fin ; i += 1 ) sortie += texte [ i ] === '\n' ? '\n' : ' ' ;
} ;
// Une chaîne : jusqu'à son délimiteur non échappé, ou jusqu'à la fin de la
// ligne, qu'une barre oblique inverse finale prolonge.
const chaine = ( ) => {
const delimiteur = texte [ i ] ;
recopier ( i + 1 ) ;
let fin = i ;
while ( fin < texte . length && texte [ fin ] !== delimiteur && texte [ fin ] !== '\n' ) {
fin += texte [ fin ] === '\\' ? 2 : 1 ;
}
blanchir ( Math . min ( fin , texte . length ) ) ;
if ( texte [ i ] === delimiteur ) recopier ( i + 1 ) ;
} ;
// Une expression régulière : jusqu'à la barre oblique non échappée hors
// d'une classe, ou jusqu'à la fin de la ligne, puis ses drapeaux.
const expression = ( ) => {
let fin = i + 1 ;
let classe = false ;
while ( fin < texte . length && texte [ fin ] !== '\n' && ( classe || texte [ fin ] !== '/' ) ) {
if ( texte [ fin ] === '\\' ) fin += 1 ;
else if ( texte [ fin ] === '[' ) classe = true ;
else if ( texte [ fin ] === ']' ) classe = false ;
fin += 1 ;
}
if ( texte [ fin ] === '/' ) fin += 1 ;
while ( fin < texte . length && LETTRE _DE _MOT . test ( texte [ fin ] ) ) fin += 1 ;
recopier ( Math . min ( fin , texte . length ) ) ;
} ;
// Du code, jusqu'à la fin du texte, ou, dans une substitution, jusqu'à
// l'accolade qui la ferme, laissée à l'appelant.
const code = ( substitution ) => {
let profondeur = 0 ;
let expressionPermise = true ;
while ( i < texte . length ) {
const c = texte [ i ] ;
if ( c === '/' && texte [ i + 1 ] === '/' ) {
const fin = texte . indexOf ( '\n' , i ) ;
recopier ( fin === - 1 ? texte . length : fin ) ;
} else if ( c === '/' && texte [ i + 1 ] === '*' ) {
const fin = texte . indexOf ( '*/' , i + 2 ) ;
recopier ( fin === - 1 ? texte . length : fin + 2 ) ;
} else if ( c === "'" || c === '"' ) {
chaine ( ) ;
expressionPermise = false ;
} else if ( c === '`' ) {
gabarit ( ) ;
expressionPermise = false ;
} else if ( c === '/' && expressionPermise ) {
expression ( ) ;
expressionPermise = false ;
} else if ( LETTRE _DE _MOT . test ( c ) ) {
let fin = i + 1 ;
while ( fin < texte . length && LETTRE _DE _MOT . test ( texte [ fin ] ) ) fin += 1 ;
expressionPermise = MOTS _AVANT _EXPRESSION . has ( texte . slice ( i , fin ) ) ;
recopier ( fin ) ;
} else {
if ( substitution && c === '}' && profondeur === 0 ) return ;
if ( c === '{' ) profondeur += 1 ;
if ( c === '}' ) profondeur -= 1 ;
if ( ! BLANC . test ( c ) ) expressionPermise = c !== ')' && c !== ']' ;
recopier ( i + 1 ) ;
}
}
} ;
// Un gabarit : ses parties littérales blanchies, chaque substitution lue
// comme du code.
const gabarit = ( ) => {
recopier ( i + 1 ) ;
while ( i < texte . length && texte [ i ] !== '`' ) {
if ( texte [ i ] === '\\' ) {
blanchir ( Math . min ( i + 2 , texte . length ) ) ;
} else if ( texte [ i ] === '$' && texte [ i + 1 ] === '{' ) {
recopier ( i + 2 ) ;
code ( true ) ;
if ( i < texte . length ) recopier ( i + 1 ) ;
} else {
blanchir ( i + 1 ) ;
}
}
if ( i < texte . length ) recopier ( i + 1 ) ;
} ;
code ( false ) ;
return sortie ;
}
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
// Chemin que désigne un spécificateur relatif, ou absolu depuis la racine
// comme Vite le résout ; null pour un spécificateur nu ou une URL.
function cibleDe ( racine , fichier , specificateur ) {
if ( RELATIF . test ( specificateur ) ) return resolve ( dirname ( fichier ) , specificateur ) ;
if ( specificateur . startsWith ( '/' ) ) return join ( racine , specificateur ) ;
return null ;
}
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// Relevé des refus de la frontière d'une couche dans son graphe d'imports.
// Le parcours part des modules de ses arbres, à toute profondeur, épreuves
// exclues. Il suit chaque chemin relatif, ou absolu depuis la racine, vers un
// module JavaScript existant, chaque module une fois. Un type que la JSDoc
// importe par import(…) compte comme un import. Un fichier d'une couche
// extérieure n'est pas parcouru : l'importer est déjà un refus, comme
// importer un fichier admis au navigateur. Un chemin sans extension en est un
// aussi : Node ne le résout pas (§ 14.8), et le parcours ne suit pas le
// module que Vite y trouverait. Un module natif de Node, que reconnaît
// isBuiltin, est refusé : la page où la couche s'exécute n'en a aucun. Un
// accès au navigateur n'est admis que dans le texte d'un fichier admis, parti
// de lui-même. Chaque refus se lit « accès:ligne refus », où l'accès est la
// suite des modules qui mène d'un module de départ à celui qui refuse. Lève
// quand un arbre requis ne fournit aucun module.
function releverCouche ( racine , { arbres , requis , exterieures , paquets , navigateur } ) {
for ( const arbre of requis ) {
assert . ok ( modulesDe ( join ( racine , arbre ) ) . length > 0 , ` ${ arbre } ne fournit aucun module ` ) ;
}
const couches = exterieures . map ( ( couche ) => join ( racine , 'src' , couche ) ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
const exterieur = ( chemin ) => couches . some ( ( c ) => chemin === c || chemin . startsWith ( c + sep ) ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
const admis = new Set ( ( navigateur ? ? [ ] ) . map ( ( fichier ) => join ( racine , fichier ) ) ) ;
const aParcourir = arbres . flatMap ( ( arbre ) => modulesDe ( join ( racine , arbre ) ) ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
const acces = new Map ( aParcourir . map ( ( fichier ) => [ fichier , relative ( racine , fichier ) ] ) ) ;
const refus = [ ] ;
for ( let i = 0 ; i < aParcourir . length ; i += 1 ) {
const fichier = aParcourir [ i ] ;
const texte = readFileSync ( fichier , 'utf8' ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
const trouves =
navigateur === null || admis . has ( fichier )
? [ ]
: [ ... sansChaines ( texte ) . matchAll ( ACCES _AU _DOM ) ] . map ( ( { 0 : lu , 1 : nom , index } ) => ( {
indice : index ,
motif : nom + lu . at ( - 1 ) ,
} ) ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
for ( const { specificateur , indice } of chargementsLitteraux ( texte ) ) {
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
const cible = cibleDe ( racine , fichier , specificateur ) ;
if ( cible === null ) {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
if ( isBuiltin ( specificateur ) || paquets . test ( nomDePaquet ( specificateur ) ) ) {
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
trouves . push ( { indice , motif : ` import ${ specificateur } ` } ) ;
}
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
} else if ( exterieur ( cible ) || admis . has ( cible ) ) {
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
trouves . push ( { indice , motif : ` import ${ specificateur } ` } ) ;
} else if ( extname ( cible ) === '' ) {
trouves . push ( { indice , motif : ` import ${ specificateur } sans extension ` } ) ;
} else if ( ! acces . has ( cible ) && EXTENSIONS _MODULE . has ( extname ( cible ) ) && existsSync ( cible ) ) {
acces . set ( cible , ` ${ acces . get ( fichier ) } → ${ relative ( racine , cible ) } ` ) ;
aParcourir . push ( cible ) ;
}
}
trouves . sort ( ( a , b ) => a . indice - b . indice ) ;
for ( const { indice , motif } of trouves ) {
refus . push ( ` ${ acces . get ( fichier ) } : ${ ligneDe ( texte , indice ) } ${ motif } ` ) ;
}
}
return refus ;
}
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// Relevé des refus de la frontière de chaque couche, dans l'ordre de COUCHES.
const releverFrontiere = ( racine ) => COUCHES . flatMap ( ( couche ) => releverCouche ( racine , couche ) ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
describe ( 'arborescence : frontière des couches (§ 13.4)' , ( ) => {
test ( 'les globales du navigateur hors du DOM se refusent comme lui : navigator, location, localStorage, sessionStorage' , ( ) => {
const fichiers = {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
... MODULES _VIDES ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/moteur/a.js' : [
'export const langue = navigator.language;' ,
'export const adresse = location.href;' ,
"export const memoire = localStorage.getItem('x');" ,
"export const seance = sessionStorage['x'];" ,
] . join ( '\n' ) ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverFrontiere ) , [
'src/moteur/a.js:1 navigator.' ,
'src/moteur/a.js:2 location.' ,
'src/moteur/a.js:3 localStorage.' ,
'src/moteur/a.js:4 sessionStorage[' ,
] ) ;
} ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
test ( "le graphe d'imports de chaque couche ne rejoint que ce que le § 13.4 lui permet" , ( ) => {
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
assert . deepEqual ( releverFrontiere ( RACINE ) , [ ] ) ;
} ) ;
test ( 'la garde suit les imports depuis chaque module à toute profondeur, relève chaque refus par sa ligne, hors épreuves' , ( ) => {
const fichiers = {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
... MODULES _VIDES ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/moteur/a.js' : [
"import { mount } from 'svelte';" ,
"import { Capacitor } from '@capacitor/core';" ,
"import { app } from 'electron';" ,
"import App from '../interface/App.svelte';" ,
"import { lire } from '../stockage/fichiers.js';" ,
"import { aide } from '../commun/aide.js';" ,
"import { ErreurConfiguration } from './erreurs.js';" ,
'export const largeur = document.body.clientWidth;' ,
"import { writable } from 'svelte/store';" ,
"import { ipcRenderer } from 'electron/renderer';" ,
"import { voisin } from '../interface-x/voisin.js';" ,
'export const adresse = window.URL;' ,
"import { x } from '/src/interface/x.js';" ,
"import { f } from '../commun/fenetre';" ,
"import { readFileSync } from 'node:fs';" ,
"export const hauteur = window['innerHeight'];" ,
'export const corps = () => document.' ,
' body;' ,
"import 'svelte';" ,
'import { y } from "electron";' ,
"import { z } from '@capacitor/cli';" ,
'const c = require("svelte");' ,
"export const echelle = window?.['devicePixelRatio'];" ,
"import fs from 'fs';" ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
"import { seance } from '../application/seance.js';" ,
"/** @param {import('../application/seance.js').Seance} s */" ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
] . join ( '\n' ) ,
'src/moteur/b.js' : [
'import {' ,
" // l'écran d'accueil" ,
' App,' ,
"} from '../interface/App.svelte';" ,
] . join ( '\n' ) ,
'src/moteur/erreurs.js' : [
'// Une phrase finit sur le mot document. La suivante commence ici.' ,
"import { rien } from './absent.js';" ,
'export const fenetres = { windows: 1, documentation: 2 };' ,
'// Cette ligne finit sur le mot document.' ,
'// La suivante est un commentaire.' ,
] . join ( '\n' ) ,
'src/moteur/sous/c.js' : [
"import { x } from '../../interface/x.js';" ,
"import { y } from '../interface/y.js';" ,
] . join ( '\n' ) ,
'src/moteur/interface/y.js' : 'export const y = 1;\n' ,
'src/moteur/a.test.js' : "import { mount } from 'svelte';\nexport const corps = document.body;\n" ,
'src/stockage/fichiers.js' : "import { Filesystem } from '@capacitor/core';\n" ,
'src/commun/aide.js' : [
"import { largeur } from '../moteur/a.js';" ,
'export const aide = () => window' ,
' .innerWidth;' ,
] . join ( '\n' ) ,
'src/commun/fenetre.js' : 'export const f = () => window.innerHeight;\n' ,
'src/commun/racine.js' : 'export const r = () => window.top;\n' ,
'src/geometrie/echelle.js' : [
'export const zoom = () => window?.devicePixelRatio;' ,
"import { r } from '/src/commun/racine.js';" ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
"import { commande } from '../application/commandes.js';" ,
"/** @returns {import('../application/seance.js').Seance} */" ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
] . join ( '\n' ) ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverFrontiere ) , [
'src/moteur/a.js:1 import svelte' ,
'src/moteur/a.js:2 import @capacitor/core' ,
'src/moteur/a.js:3 import electron' ,
'src/moteur/a.js:4 import ../interface/App.svelte' ,
'src/moteur/a.js:5 import ../stockage/fichiers.js' ,
'src/moteur/a.js:8 document.' ,
'src/moteur/a.js:9 import svelte/store' ,
'src/moteur/a.js:10 import electron/renderer' ,
'src/moteur/a.js:12 window.' ,
'src/moteur/a.js:13 import /src/interface/x.js' ,
'src/moteur/a.js:14 import ../commun/fenetre sans extension' ,
'src/moteur/a.js:15 import node:fs' ,
'src/moteur/a.js:16 window[' ,
'src/moteur/a.js:17 document.' ,
'src/moteur/a.js:19 import svelte' ,
'src/moteur/a.js:20 import electron' ,
'src/moteur/a.js:21 import @capacitor/cli' ,
'src/moteur/a.js:22 import svelte' ,
'src/moteur/a.js:23 window[' ,
'src/moteur/a.js:24 import fs' ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
'src/moteur/a.js:25 import ../application/seance.js' ,
'src/moteur/a.js:26 import ../application/seance.js' ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/moteur/b.js:4 import ../interface/App.svelte' ,
'src/moteur/sous/c.js:1 import ../../interface/x.js' ,
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
'src/moteur/a.js → src/commun/aide.js:2 window.' ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/geometrie/echelle.js:1 window.' ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
'src/geometrie/echelle.js:3 import ../application/commandes.js' ,
'src/geometrie/echelle.js:4 import ../application/seance.js' ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
'src/geometrie/echelle.js → src/commun/racine.js:1 window.' ,
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
'src/stockage/fichiers.js:1 import @capacitor/core' ,
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
] ) ;
} ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
test ( "la garde du navigateur ne lit pas les chaînes littérales : « ./document.js » nomme un fichier ; elle lit le code d'une substitution et les commentaires, suit l'échappement, et distingue la division de l'expression régulière" , ( ) => {
const fichiers = {
... MODULES _VIDES ,
'src/moteur/a.js' : [
"import { SCHEMA } from './document.js';" ,
'export const a = \'window.name\' + "navigator.language";' ,
'export const b = `document.title`;' ,
'export const c = `${document.title}`;' ,
"export const d = 'l\\'objet'; export const e = window.name;" ,
'export const f = x.replace(/["\'`]/g, \'\'); export const g = window.top;' ,
"// l'accès à document.body se relève, même en commentaire" ,
'export const h = y / 2; export const i = location.href / 3;' ,
"export const j = `a${'location.href'}b` + localStorage.x;" ,
'export const k = /\'/.test(s) ? sessionStorage.x : "";' ,
'export const l = navigator' ,
' .language;' ,
// Après « ) », « ] » ou un nom, la barre oblique divise, et la chaîne
// qui la suit se blanchit ; après un mot-clé, elle ouvre une
// expression, où l'apostrophe n'ouvre rien.
"export const milieu = (a + b) / 2; export const cle = 'document.title';" ,
"export const moitie = largeur / 2 + 'window.name'.length;" ,
"export const quart = cotes[0] / 4 + 'location.href'.length;" ,
"export const langue = (s) => { return /'/.test(s) ? navigator.language : ''; };" ,
// Un accent grave échappé ne ferme pas le gabarit ; l'accolade qui
// referme un objet dans une substitution ne ferme pas la substitution.
'export const m = `\\`` + window.name;' ,
'export const n = `x${ {a: 1}.a + document.title }y`;' ,
// Une barre oblique ne ferme pas l'expression dans une classe, ni
// échappée ; « /* » après un nom ouvre un commentaire, non une division.
"export const p = /[/']/.test(s) ? 'location.href' : document.title;" ,
"export const q = /\\/'/.test(s) ? 'window.name' : navigator.language;" ,
"export const r = somme /* l'entier */ + window.name;" ,
// Une expression après « ) » se lit comme une division : l'apostrophe
// y ouvre une chaîne, que la fin de la ligne arrête.
"if (garde) /'/.test(s) && compter();" ,
'export const z = localStorage.x;' ,
] . join ( '\n' ) ,
'src/moteur/document.js' : 'export const SCHEMA = 1;\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverFrontiere ) , [
'src/moteur/a.js:4 document.' ,
'src/moteur/a.js:5 window.' ,
'src/moteur/a.js:6 window.' ,
'src/moteur/a.js:7 document.' ,
'src/moteur/a.js:8 location.' ,
'src/moteur/a.js:9 localStorage.' ,
'src/moteur/a.js:10 sessionStorage.' ,
'src/moteur/a.js:11 navigator.' ,
'src/moteur/a.js:16 navigator.' ,
'src/moteur/a.js:17 window.' ,
'src/moteur/a.js:18 document.' ,
'src/moteur/a.js:19 document.' ,
'src/moteur/a.js:20 navigator.' ,
'src/moteur/a.js:21 window.' ,
'src/moteur/a.js:23 localStorage.' ,
] ) ;
} ) ;
test ( "src/stockage n'importe ni src/csv, ni src/application, ni src/interface, ni une plateforme, et ne touche le navigateur que dans ses deux systèmes de fichiers, que nul n'y importe" , ( ) => {
const fichiers = {
... MODULES _VIDES ,
'src/stockage/depot.js' : [
"import { decouper } from '../csv/lecture.js';" ,
"import { creerSeance } from '../application/seance.js';" ,
"import App from '../interface/App.svelte';" ,
"import { mount } from 'svelte';" ,
"import { ipcRenderer } from 'electron';" ,
"import { Capacitor } from '@capacitor/core';" ,
"import { readFile } from 'node:fs/promises';" ,
"import { HISTORIQUE } from '../moteur/recherche.js';" ,
"import { SCHEMA } from './document.js';" ,
"import { creerFichiersWeb } from './fichiers_web.js';" ,
"/** @param {import('../application/seance.js').Seance} seance */" ,
"/** @returns {import('./types.js').Charge} */" ,
'export const titre = () => document.title;' ,
"export const cle = 'localStorage.x';" ,
"import { voisin } from './voisin';" ,
] . join ( '\n' ) ,
'src/stockage/document.js' : 'export const SCHEMA = 1;\n' ,
'src/stockage/types.js' : '/** @typedef {Object} Charge */\n' ,
'src/stockage/sous/memoire.js' : "export const lire = () => localStorage.getItem('x');\n" ,
'src/stockage/fichiers_web.js' : 'export const creerFichiersWeb = () => navigator.storage.getDirectory();\n' ,
'src/stockage/fichiers_electron.js' : [
'export const creerFichiersElectron = (pont = window.gtt.fichiers) => pont;' ,
"import { creerFichiersWeb } from './fichiers_web.js';" ,
] . join ( '\n' ) ,
'src/stockage/depot.test.js' : "import { mount } from 'svelte';\nexport const corps = document.body;\n" ,
'src/moteur/recherche.js' : 'export const HISTORIQUE = 1000;\nexport const largeur = () => window.innerWidth;\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverFrontiere ) , [
'src/moteur/recherche.js:2 window.' ,
'src/stockage/depot.js:1 import ../csv/lecture.js' ,
'src/stockage/depot.js:2 import ../application/seance.js' ,
'src/stockage/depot.js:3 import ../interface/App.svelte' ,
'src/stockage/depot.js:4 import svelte' ,
'src/stockage/depot.js:5 import electron' ,
'src/stockage/depot.js:6 import @capacitor/core' ,
'src/stockage/depot.js:7 import node:fs/promises' ,
'src/stockage/depot.js:10 import ./fichiers_web.js' ,
'src/stockage/depot.js:11 import ../application/seance.js' ,
'src/stockage/depot.js:13 document.' ,
'src/stockage/depot.js:15 import ./voisin sans extension' ,
'src/stockage/fichiers_electron.js:2 import ./fichiers_web.js' ,
'src/stockage/sous/memoire.js:1 localStorage.' ,
'src/stockage/depot.js → src/moteur/recherche.js:2 window.' ,
] ) ;
} ) ;
test ( "src/csv n'importe ni src/application, ni src/interface, ni une plateforme, et lit le modèle de src/stockage ; un import de type en JSDoc compte comme un import" , ( ) => {
const fichiers = {
... MODULES _VIDES ,
'src/csv/import.js' : [
"/** @param {import('../stockage/types.js').Charge} charge */" ,
"import { libelle } from '../application/libelles.js';" ,
"/** @returns {import('../interface/vue.js').Vue} */" ,
"import { Capacitor } from '@capacitor/core';" ,
"import { app } from 'electron';" ,
"import { writable } from 'svelte/store';" ,
"import { creerFichiersWeb } from '../stockage/fichiers_web.js';" ,
"import { SCHEMA } from '../stockage/document.js';" ,
'export const largeur = () => window.innerWidth;' ,
] . join ( '\n' ) ,
'src/csv/sous/lecture.js' : "import { readFileSync } from 'fs';\n" ,
'src/stockage/types.js' : '/** @typedef {Object} Charge */\n' ,
'src/stockage/document.js' : 'export const SCHEMA = 1;\n' ,
'src/stockage/fichiers_web.js' : 'export const creerFichiersWeb = () => navigator.storage.getDirectory();\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverFrontiere ) , [
'src/csv/import.js:2 import ../application/libelles.js' ,
'src/csv/import.js:3 import ../interface/vue.js' ,
'src/csv/import.js:4 import @capacitor/core' ,
'src/csv/import.js:5 import electron' ,
'src/csv/import.js:6 import svelte/store' ,
'src/csv/import.js:9 window.' ,
'src/csv/sous/lecture.js:1 import fs' ,
'src/csv/import.js → src/stockage/fichiers_web.js:1 navigator.' ,
] ) ;
} ) ;
test ( "src/application n'importe ni src/interface, ni svelte, ni un module de Node ; elle câble le stockage, le CSV et les systèmes de fichiers des plateformes" , ( ) => {
const fichiers = {
... MODULES _VIDES ,
'src/application/seance.js' : [
"import App from '../interface/App.svelte';" ,
"import { mount } from 'svelte';" ,
"import { creerFichiersWeb } from '../stockage/fichiers_web.js';" ,
"import { decoder } from '../csv/encodage.js';" ,
"import { Capacitor } from '@capacitor/core';" ,
"import { readFile } from 'node:fs/promises';" ,
'export const largeur = () => window.innerWidth;' ,
"/** @param {import('../interface/vue.js').Vue} vue */" ,
] . join ( '\n' ) ,
'src/application/sous/commandes.js' : "import { x } from '../../interface/x.js';\n" ,
'src/stockage/fichiers_web.js' : 'export const creerFichiersWeb = () => navigator.storage.getDirectory();\n' ,
'src/csv/encodage.js' : 'export const decoder = (octets) => octets;\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverFrontiere ) , [
'src/application/seance.js:1 import ../interface/App.svelte' ,
'src/application/seance.js:2 import svelte' ,
'src/application/seance.js:6 import node:fs/promises' ,
'src/application/seance.js:8 import ../interface/vue.js' ,
'src/application/sous/commandes.js:1 import ../../interface/x.js' ,
] ) ;
} ) ;
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
test ( "src/geometrie n'importe ni le moteur, ni le CSV, ni les démonstrations : une couche à part, plus bas que le moteur" , ( ) => {
const fichiers = {
... MODULES _VIDES ,
'src/geometrie/vue.js' : [
"import { mesurer } from '../moteur/indicateurs.js';" ,
"import { decouper } from '../csv/lecture.js';" ,
"import { creerPcg32 } from '../demo/prng.js';" ,
"import { tronquer } from './texte.js';" ,
] . join ( '\n' ) ,
'src/geometrie/texte.js' : 'export const tronquer = (t) => t;\n' ,
'src/moteur/indicateurs.js' : 'export const mesurer = () => 0;\n' ,
'src/csv/lecture.js' : 'export const decouper = () => [];\n' ,
'src/demo/prng.js' : 'export const creerPcg32 = () => null;\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverFrontiere ) , [
'src/geometrie/vue.js:1 import ../moteur/indicateurs.js' ,
'src/geometrie/vue.js:2 import ../csv/lecture.js' ,
'src/geometrie/vue.js:3 import ../demo/prng.js' ,
] ) ;
} ) ;
test ( "src/geometrie n'importe ni l'interface, ni l'application, ni le stockage, ni un paquet de plateforme" , ( ) => {
const fichiers = {
... MODULES _VIDES ,
'src/geometrie/vue.js' : [
"import { x } from '../interface/x.js';" ,
"import { y } from '../application/y.js';" ,
"import { lire } from '../stockage/document.js';" ,
"import { mount } from 'svelte';" ,
"import { writable } from 'svelte/store';" ,
"import { app } from 'electron';" ,
"import { Capacitor } from '@capacitor/core';" ,
"import { tronquer } from './texte.js';" ,
] . join ( '\n' ) ,
'src/geometrie/texte.js' : 'export const tronquer = (t) => t;\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverFrontiere ) , [
'src/geometrie/vue.js:1 import ../interface/x.js' ,
'src/geometrie/vue.js:2 import ../application/y.js' ,
'src/geometrie/vue.js:3 import ../stockage/document.js' ,
'src/geometrie/vue.js:4 import svelte' ,
'src/geometrie/vue.js:5 import svelte/store' ,
'src/geometrie/vue.js:6 import electron' ,
'src/geometrie/vue.js:7 import @capacitor/core' ,
] ) ;
} ) ;
test ( 'src/application peut manquer ; un src/moteur, un src/geometrie, un src/stockage ou un src/csv sans module fait échouer la garde' , ( ) => {
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
assert . deepEqual ( avecArbre ( MODULES _VIDES , releverFrontiere ) , [ ] ) ;
[ADD] geometry: plan view, truncation, scale bar, measured constants
The plan needs one formula between the screen and the drawing, shared by
the drawing, the seat designation and the drop of a drag. src/geometrie/vue
holds the view as k px/cm plus a translation, written in a single
transform attribute, and converts pointer positions without reading the
DOM. Text truncation, the graphic scale and the register of measured
constants live beside it; the layer guard now requires src/geometrie and
keeps it deterministic and away from window.
Checked: 1619 node tests.
--- FR ---
[ADD] géométrie : vue du plan, troncature, échelle, constantes mesurées
Le plan exige une seule formule entre l'écran et le dessin, que partagent le
dessin, la désignation d'un siège et le dépôt d'un glissement.
src/geometrie/vue tient la vue — k px/cm et une translation — écrite dans un
seul attribut transform, et convertit les positions du pointeur sans lire
le DOM. La troncature du texte, l'échelle graphique et le registre des
constantes mesurées vivent à côté ; la garde des couches exige désormais
src/geometrie, déterministe et sans window.
Vérifié : 1619 épreuves node.
Assisted-by: Claude Opus 5.5
2026-10-07 02:32:35 -04:00
for ( const arbre of [ 'src/moteur' , 'src/geometrie' , 'src/stockage' , 'src/csv' ] ) {
const sansModule = { ... sansArbre ( MODULES _VIDES , arbre ) , [ ` ${ arbre } /a.test.js ` ] : '' } ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
assert . throws (
( ) => avecArbre ( sansModule , releverFrontiere ) ,
new RegExp ( ` ${ arbre } ne fournit aucun module ` ) ,
arbre ,
) ;
}
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
} ) ;
} ) ;
// Périmètre du relevé des dépendances : les fichiers de la racine, et les
// arbres des sources, des épreuves, des scripts et de la coquille ; ni
// node_modules ni sortie de construction.
const ARBRES = [ 'src' , 'test' , 'scripts' , 'electron' ] ;
const EXTENSIONS _SOURCE = new Set ( [ '.js' , '.cjs' , '.mjs' , '.svelte' ] ) ;
function sourcesDuProjet ( racine ) {
const racineSeule = readdirSync ( racine , { withFileTypes : true } )
. filter ( ( e ) => e . isFile ( ) )
. map ( ( e ) => join ( racine , e . name ) ) ;
return [ ... racineSeule , ... ARBRES . flatMap ( ( arbre ) => fichiersDe ( join ( racine , arbre ) ) ) ]
. filter ( ( chemin ) => EXTENSIONS _SOURCE . has ( extname ( chemin ) ) )
. sort ( ) ;
}
// Un spécificateur nu n'est ni relatif, ni absolu : ni chemin, ni URL, sinon
// sous node:, la forme des modules natifs.
const URL _ABSOLUE = /^(?!node:)[a-z][a-z\d+.-]*:/i ;
const estNu = ( specificateur ) =>
! RELATIF . test ( specificateur ) && ! specificateur . startsWith ( '/' ) && ! URL _ABSOLUE . test ( specificateur ) ;
// Relevé « fichier:ligne spécificateur » des spécificateurs nus qui ne
// désignent ni un module natif de Node ni un paquet de devDependencies ; un
// paquet que seul dependencies déclare est relevé lui aussi, le projet
// n'ayant aucune dépendance d'exécution. Node et Vite résolvent un
// spécificateur nu en remontant les node_modules des répertoires parents :
// un paquet non déclaré, présent dans un parent sur un poste, s'y charge,
// puis manque dans un clone. isBuiltin admet le nom seul d'un module natif et
// sa forme node:, la seule qu'acceptent certains (node:test) ; il refuse un
// nom inconnu sous node:. Lève quand le périmètre ne porte aucun
// spécificateur nu.
function releverDependances ( racine ) {
const { devDependencies = { } } = JSON . parse ( readFileSync ( join ( racine , 'package.json' ) , 'utf8' ) ) ;
const declares = new Set ( Object . keys ( devDependencies ) ) ;
let nus = 0 ;
const refus = [ ] ;
for ( const fichier of sourcesDuProjet ( racine ) ) {
const texte = readFileSync ( fichier , 'utf8' ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
const trouves = chargementsLitteraux ( texte ) . filter ( ( { specificateur } ) => estNu ( specificateur ) ) ;
[ADD] guards: determinism and layer boundary checked over src/
A seed reproduces a plan only if nothing in the engine or the demo
generator reads the clock, a random source or the locale. One guard reads
every module of src/moteur and src/demo and names each such call by its
line, Node's crypto draws included. A second walks the engine's import
graph and refuses the interface, storage, Svelte, Capacitor, Electron,
Node built-ins and browser globals. Both fail on an empty tree.
Checked: each forbidden form is caught in a temporary tree; the real tree
is clean.
--- FR ---
[ADD] garde-fous : déterminisme et frontière des couches sur src/
Une graine ne reproduit un plan que si rien, dans le moteur ni dans le
générateur de démonstrations, ne lit l'horloge, une source aléatoire ou la
locale. Une garde lit chaque module de src/moteur et de src/demo et nomme
chaque tel appel par sa ligne, tirages de crypto de Node compris. Une
seconde parcourt le graphe d'imports du moteur et refuse l'interface, le
stockage, Svelte, Capacitor, Electron, les modules natifs de Node et les
globales du navigateur. Les deux échouent sur un arbre vide.
Vérifié : chaque forme interdite est relevée dans un arbre temporaire ;
l'arbre réel est propre.
Assisted-by: Claude Opus 5.5
2026-10-05 17:27:06 -04:00
nus += trouves . length ;
for ( const { specificateur , indice } of trouves ) {
if ( ! isBuiltin ( specificateur ) && ! declares . has ( nomDePaquet ( specificateur ) ) ) {
refus . push ( ` ${ relative ( racine , fichier ) } : ${ ligneDe ( texte , indice ) } ${ specificateur } ` ) ;
}
}
}
assert . ok ( nus > 0 , 'aucun spécificateur nu dans le périmètre' ) ;
return refus ;
}
// Un import de module seul par spécificateur, une ligne chacun, entre les
// guillemets donnés, doubles par défaut. Le texte de ce fichier ne porte
// ainsi aucun spécificateur entre guillemets après le mot-clé : un
// spécificateur refusé, écrit en clair dans une instruction d'import de ce
// fichier, ferait échouer la garde sur ce fichier même. Une donnée qui charge
// un paquet refusé par une autre forme l'interpole pour la même raison.
const importsSeuls = ( specificateurs , guillemet = '"' ) =>
specificateurs . map ( ( s ) => ` import ${ guillemet } ${ s } ${ guillemet } ; ` ) . join ( '\n' ) ;
describe ( 'arborescence : dépendances déclarées' , ( ) => {
test ( 'chaque spécificateur nu désigne un module natif de Node ou un paquet de devDependencies' , ( ) => {
assert . deepEqual ( releverDependances ( RACINE ) , [ ] ) ;
} ) ;
test ( 'la garde relève chaque paquet absent de devDependencies, dans son périmètre seul' , ( ) => {
const fichiers = {
'package.json' : JSON . stringify ( {
dependencies : { lodash : '^4.17.21' } ,
devDependencies : { vitest : '^5.0.3' , '@vitest/browser-playwright' : '^5.0.3' } ,
} ) ,
'vite.config.js' : "import { defineConfig } from 'vite';\n" ,
'src/interface/a.svelte' : [
'<script>' ,
" import { mount } from 'svelte';" ,
'</script>' ,
'<style>' ,
" @import 'jetons.css';" ,
'</style>' ,
] . join ( '\n' ) ,
'electron/b.cjs' : "const { app } = require('electron');\n" ,
'scripts/oracle/c.mjs' : [
"const { chromium } = require('playwright');" ,
"import assert from 'node:assert/strict';" ,
'import {' ,
' describe,' ,
"} from 'vitest/config';" ,
"export * from '@vitest/browser-playwright';" ,
"const { join } = require('node:path');" ,
"const vue = await import('svelte/store');" ,
"import './voisin.js';" ,
"import '..';" ,
"spawnSync(process.execPath, ['--import', 'chargeur.js']);" ,
"import { build } from'vite';" ,
'const fc = await import(`fast-check`);' ,
"const { app } = await import('electron', { with: {} });" ,
] . join ( '\n' ) ,
'test/d.test.js' : [
importsSeuls ( [ 'fs/promises' , 'node:test' , 'test' , 'node:inexistant' , '@vitest/inconnu' ] ) ,
importsSeuls ( [ 'jsdom' ] , "'" ) ,
importsSeuls ( [ '/absolu.js' , 'file:///e.js' , 'lodash' ] ) ,
` import x from ${ JSON . stringify ( 'happy-dom' ) } ; ` ,
` require( ${ JSON . stringify ( 'undici' ) } ); ` ,
] . join ( '\n' ) ,
'node_modules/f/index.js' : importsSeuls ( [ 'hors-perimetre' ] ) ,
'www/g.js' : importsSeuls ( [ 'hors-perimetre' ] ) ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverDependances ) , [
'electron/b.cjs:1 electron' ,
'scripts/oracle/c.mjs:1 playwright' ,
'scripts/oracle/c.mjs:8 svelte/store' ,
'scripts/oracle/c.mjs:12 vite' ,
'scripts/oracle/c.mjs:13 fast-check' ,
'scripts/oracle/c.mjs:14 electron' ,
'src/interface/a.svelte:2 svelte' ,
'test/d.test.js:3 test' ,
'test/d.test.js:4 node:inexistant' ,
'test/d.test.js:5 @vitest/inconnu' ,
'test/d.test.js:6 jsdom' ,
'test/d.test.js:9 lodash' ,
'test/d.test.js:10 happy-dom' ,
'test/d.test.js:11 undici' ,
'vite.config.js:1 vite' ,
] ) ;
} ) ;
test ( 'un périmètre sans spécificateur nu fait échouer la garde' , ( ) => {
const fichiers = { 'package.json' : '{}' , 'src/a.js' : "import './b.js';\n" } ;
assert . throws ( ( ) => avecArbre ( fichiers , releverDependances ) , /aucun spécificateur nu/ ) ;
} ) ;
} ) ;
[ADD] tests: budget reporter, one import parser, key-order guard
The time budget of § 14.14 had no enforcement: a reporter now prints the
total and the ten slowest tests, and fails a run whose node project
exceeds 30 s or node-long 60 s. Two guards parsed imports with two
patterns, one blind past an apostrophe in a comment; both now use one
parser anchored on « from ». The determinism guard refuses key-order
walks, and one test binds the application name across its three
declarations. The end-to-end generations drop to 100 000 moves.
Checked: each ceiling, the apostrophe case and a key walk are shown
failing before the guard that catches them.
--- FR ---
[ADD] épreuves : rapporteur de budget, imports, ordre des clés
Le budget de temps du § 14.14 n'avait aucune garde : un rapporteur
imprime désormais la durée totale et les dix épreuves les plus lentes,
et fait échouer une exécution dont le projet node dépasse 30 s ou
node-long 60 s. Deux gardes lisaient les imports par deux motifs, l'un
aveugle après une apostrophe en commentaire ; les deux passent par un
seul analyseur ancré sur « from ». La garde de déterminisme refuse les
parcours de clés, et une épreuve lie le nom de l'application à ses
trois déclarations. Les générations de bout en bout passent à 100 000.
Vérifié : chaque plafond, le cas de l'apostrophe et un parcours de clés
sont montrés en échec avant la garde qui les attrape.
Assisted-by: Claude Opus 5.5
2026-10-06 04:23:13 -04:00
// Valeurs du contrat de données (types.js) : configuration.js les définit et
// les exporte, tout autre fichier de src/moteur les importe, épreuves
// comprises (§ 13.2). Une déclaration de l'un de ces noms ailleurs est une
// seconde définition, qui peut dériver de la première sans qu'aucune épreuve
// ne le voie. Le relevé lit le nom qui suit const, let ou var : une
// déstructuration de STATUT n'est pas relevée, elle lit la définition au lieu
// de la refaire.
const VALEURS _DU _CONTRAT = [
'STATUT' ,
'MOBILE' ,
'PARTIELLEMENT_FIXE' ,
'ANCRE' ,
'LIBRE' ,
'RESERVE' ,
'SANS_GROUPE' ,
] ;
const DECLARATION _DE _VALEUR = new RegExp (
` \\ b(?:const|let|var) \\ s+( ${ VALEURS _DU _CONTRAT . join ( '|' ) } ) \\ b ` ,
'g' ,
) ;
const PROPRIETAIRE _DES _VALEURS = join ( 'src' , 'moteur' , 'configuration.js' ) ;
// Relevé « fichier:ligne nom » des déclarations d'une valeur du contrat dans
// les fichiers JavaScript de src/moteur, à toute profondeur, épreuves
// comprises, configuration.js excepté ; par fichier, puis par ligne. Lève
// quand src/moteur ne fournit aucun fichier JavaScript.
function releverValeursDuContrat ( racine ) {
const fichiers = fichiersDe ( join ( racine , 'src' , 'moteur' ) )
. filter ( ( fichier ) => EXTENSIONS _MODULE . has ( extname ( fichier ) ) )
. sort ( ) ;
assert . ok ( fichiers . length > 0 , 'src/moteur ne fournit aucun fichier JavaScript' ) ;
return fichiers
. filter ( ( fichier ) => relative ( racine , fichier ) !== PROPRIETAIRE _DES _VALEURS )
. flatMap ( ( fichier ) => {
const texte = readFileSync ( fichier , 'utf8' ) ;
return [ ... texte . matchAll ( DECLARATION _DE _VALEUR ) ] . map (
( trouve ) => ` ${ relative ( racine , fichier ) } : ${ ligneDe ( texte , trouve . index ) } ${ trouve [ 1 ] } ` ,
) ;
} ) ;
}
describe ( 'arborescence : un seul propriétaire des valeurs du contrat (types.js)' , ( ) => {
test ( 'hors de configuration.js, aucun fichier de src/moteur ne déclare STATUT, un statut, LIBRE, RESERVE ni SANS_GROUPE' , ( ) => {
assert . deepEqual ( releverValeursDuContrat ( RACINE ) , [ ] ) ;
} ) ;
test ( 'la garde relève chaque déclaration par sa ligne, épreuves comprises, et admet le propriétaire, la déstructuration et les noms voisins' , ( ) => {
const fichiers = {
'src/moteur/configuration.js' : 'export const STATUT = Object.freeze({ ANCRE: 2 });\nexport const LIBRE = -1;\n' ,
'src/moteur/a.js' : [
"import { STATUT } from './configuration.js';" ,
'const { ANCRE } = STATUT;' ,
'const ANCRES = [];' ,
'let LIBRES = 0;' ,
] . join ( '\n' ) ,
'src/moteur/b.js' : 'const ANCRE = 2;\nexport let RESERVE = -1;\n' ,
'src/moteur/sous/c.test.js' : '// Épreuve.\nvar SANS_GROUPE = -1;\n' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , releverValeursDuContrat ) , [
'src/moteur/b.js:1 ANCRE' ,
'src/moteur/b.js:2 RESERVE' ,
'src/moteur/sous/c.test.js:2 SANS_GROUPE' ,
] ) ;
} ) ;
test ( 'un src/moteur sans fichier JavaScript fait échouer la garde' , ( ) => {
for ( const fichiers of [ { 'src/demo/a.js' : '' } , { 'src/moteur/notes.md' : '' } ] ) {
assert . throws (
( ) => avecArbre ( fichiers , releverValeursDuContrat ) ,
/src\/moteur ne fournit aucun fichier JavaScript/ ,
) ;
}
} ) ;
} ) ;
[ADD] tests: per-module coverage, 100 % branch floors, layer guards
make couverture runs the node series under V8 instrumentation and prints one
row per module, full ones included, plus a line-by-line HTML report. Four
modules hold a hard 100 % branch floor — indicateurs.js, plafond.js,
depot.js, journal.js — and the command fails below it; there is no global
threshold, which covering the easy modules would satisfy. The tree guard
refuses a lowered or global floor, a floor on a file the measure never loads,
and a command that does not measure. It extends determinism and layer
boundaries to src/stockage, src/csv and src/application (§ 13.4), and no
longer takes a string literal for DOM access.
Checked: 1266 node tests; the four floors at 100 %.
--- FR ---
[ADD] épreuves : couverture par module, seuils durs, gardes des couches
make couverture joue la série node sous l'instrumentation de V8 et imprime une
ligne par module, pleins compris, et un rapport HTML ligne à ligne. Quatre
modules tiennent un seuil dur de 100 % des branches — indicateurs.js,
plafond.js, depot.js, journal.js — et la commande échoue en deçà ; aucun seuil
global, qu'on satisferait en couvrant les modules faciles. La garde de
l'arborescence refuse un seuil abaissé ou global, un seuil sur un fichier que
la mesure ne charge pas, et une commande qui ne mesure pas. Elle étend le
déterminisme et les frontières des couches à src/stockage, src/csv et
src/application (§ 13.4), et ne prend plus une chaîne littérale pour le DOM.
Vérifié : 1266 épreuves node ; les quatre seuils à 100 %.
Assisted-by: Claude Opus 5.5
Claude-Session: https://claude.ai/code/session_01EUXSGcwCLSC69FWEdCtWSb
2026-10-06 20:41:23 -04:00
// Modules que le § 14.13 tient à 100 % de branches : le module des indicateurs
// et du plafond, et les chemins de reprise du stockage.
const MODULES _A _SEUIL = [
'src/moteur/indicateurs.js' ,
'src/moteur/plafond.js' ,
'src/stockage/depot.js' ,
'src/stockage/journal.js' ,
] ;
// Clés de coverage.thresholds qui vaudraient pour tous les fichiers mesurés.
const SEUILS _GLOBAUX = [ 'statements' , 'branches' , 'functions' , 'lines' , '100' , 'perFile' ] ;
// Vrai quand le chemin relatif répond à l'un des motifs de fichiers donnés.
const repondA = ( chemin , motifs = [ ] ) => motifs . some ( ( motif ) => matchesGlob ( chemin , motif ) ) ;
// La commande de la mesure : make couverture passe la main à npm run
// couverture, qui lance vitest run sur la série node, couverture active.
// Sans --coverage, la série passe et aucun seuil ne se lit. Outre ces deux
// arguments, le script n'admet que le choix du rapporteur des épreuves : une
// option --coverage.* redéfinirait, pour cette exécution, les seuils, include
// ou exclude que relève releverCouverture, et --changed, --config ou un
// filtre de fichiers changeraient ce qui se mesure. Une option et sa valeur
// se lisent en un argument : « --project node » comme « --project=node ».
const RECETTE _DE _MESURE = '$(AVEC_NODE) npm run couverture' ;
const ARGUMENTS _REQUIS = [ '--project=node' , '--coverage' ] ;
const ARGUMENT _ADMIS = /^(?:--project=node|--coverage|--reporter=\S+)$/ ;
const OPTION _A _VALEUR = /^--(?:project|reporter)$/ ;
// Écarts de la commande de la mesure sous la racine : la recette de la cible
// couverture du Makefile, puis le script couverture de package.json, ses
// arguments requis dans l'ordre de ARGUMENTS_REQUIS, puis ses arguments non
// admis dans l'ordre du script. Un script qui ne commence pas par
// « vitest run » n'est pas lu plus loin.
function ecartsDeLaCommande ( racine ) {
const ecarts = [ ] ;
const makefile = readFileSync ( join ( racine , 'Makefile' ) , 'utf8' ) ;
const recette = /^couverture:.*\n((?:\t.*(?:\n|$))*)/m . exec ( makefile ) ? . [ 1 ] ? ? '' ;
if ( recette . trim ( ) !== RECETTE _DE _MESURE ) ecarts . push ( 'make couverture : ne lance pas npm run couverture' ) ;
const { scripts = { } } = JSON . parse ( readFileSync ( join ( racine , 'package.json' ) , 'utf8' ) ) ;
const [ programme , sousCommande , ... mots ] = ( scripts . couverture ? ? '' ) . trim ( ) . split ( /\s+/ ) ;
if ( programme !== 'vitest' || sousCommande !== 'run' ) {
return [ ... ecarts , 'npm run couverture : ne lance pas vitest run' ] ;
}
const lus = [ ] ;
for ( let i = 0 ; i < mots . length ; i += 1 ) {
if ( OPTION _A _VALEUR . test ( mots [ i ] ) && i + 1 < mots . length ) {
lus . push ( ` ${ mots [ i ] } = ${ mots [ i + 1 ] } ` ) ;
i += 1 ;
} else {
lus . push ( mots [ i ] ) ;
}
}
for ( const requis of ARGUMENTS _REQUIS ) {
if ( ! lus . includes ( requis ) ) ecarts . push ( ` npm run couverture : sans ${ requis . replace ( '=' , ' ' ) } ` ) ;
}
for ( const argument of lus ) {
if ( ! ARGUMENT _ADMIS . test ( argument ) ) ecarts . push ( ` npm run couverture : argument non admis ${ argument } ` ) ;
}
return ecarts ;
}
// Écarts des rapports que la configuration nomme : le tableau text, une
// ligne par couche et par module, pleins compris — sans skipFull: false
// écrit, Vitest les tait quand un agent le lance —, puis le rapport html, qui
// montre ligne à ligne ce qui ne s'exécute jamais. Un rapporteur est un nom ou
// un couple [nom, options] ; reporter, un rapporteur seul ou leur liste.
function ecartsDuRapport ( reporter ) {
const rapporteurs = ( Array . isArray ( reporter ) ? reporter : [ reporter ] ) . map ( ( r ) => ( Array . isArray ( r ) ? r : [ r ] ) ) ;
const ecarts = [ ] ;
if ( ! rapporteurs . some ( ( [ nom , options ] ) => nom === 'text' && options ? . skipFull === false ) ) {
ecarts . push ( 'rapport : aucun tableau text à skipFull: false' ) ;
}
if ( ! rapporteurs . some ( ( [ nom ] ) => nom === 'html' ) ) ecarts . push ( 'rapport : aucun rapport html' ) ;
return ecarts ;
}
// Relevé des écarts de la mesure au § 14.13, sur l'arbre qu'elle mesure :
// ceux de la commande, puis ceux des rapports ; puis, dans la configuration
// de couverture de Vitest, un seuil global, qu'un pourcentage d'ensemble
// satisfait en couvrant les modules faciles ; un seuil hors de
// MODULES_A_SEUIL ; un module de MODULES_A_SEUIL dont le seuil de branches
// n'est pas 100 ; un module absent de l'arbre, ou hors de la mesure — hors de
// coverage.include, ou dans coverage.exclude. Vitest tient pour atteint un
// seuil qui ne compte aucune branche, sans rien dire : sans ces deux derniers
// relevés, un module renommé passerait. Les écarts viennent dans cet ordre,
// module par module dans l'ordre de MODULES_A_SEUIL. Lève quand la
// configuration, le Makefile ou package.json manque.
function releverCouverture ( racine , couverture ) {
assert . ok ( couverture , 'aucune configuration de couverture' ) ;
const { thresholds = { } , include , exclude , reporter } = couverture ;
const ecarts = [
... ecartsDeLaCommande ( racine ) ,
... ecartsDuRapport ( reporter ) ,
... SEUILS _GLOBAUX . filter ( ( cle ) => Object . hasOwn ( thresholds , cle ) ) . map ( ( cle ) => ` seuil global : ${ cle } ` ) ,
] ;
for ( const cle of Object . keys ( thresholds ) . sort ( ) ) {
if ( ! SEUILS _GLOBAUX . includes ( cle ) && ! MODULES _A _SEUIL . includes ( cle ) ) {
ecarts . push ( ` seuil hors des modules nommés : ${ cle } ` ) ;
}
}
for ( const module of MODULES _A _SEUIL ) {
const seuil = thresholds [ module ] ;
if ( seuil === undefined ) ecarts . push ( ` ${ module } : aucun seuil ` ) ;
else if ( seuil . branches !== 100 ) ecarts . push ( ` ${ module } : branches à ${ seuil . branches } ` ) ;
if ( ! existsSync ( join ( racine , module ) ) ) ecarts . push ( ` ${ module } : absent de l'arbre ` ) ;
else if ( ! repondA ( module , include ) || repondA ( module , exclude ) ) ecarts . push ( ` ${ module } : hors de la mesure ` ) ;
}
return ecarts ;
}
// Une mesure conforme au § 14.13, que les données d'épreuve altèrent une
// pièce à la fois : les quatre modules, le script de package.json, la recette
// du Makefile, et la configuration de couverture.
const scriptDeMesure = ( script ) => JSON . stringify ( { scripts : { couverture : script } } ) ;
const MODULES _MESURES = Object . freeze ( Object . fromEntries ( MODULES _A _SEUIL . map ( ( module ) => [ module , '' ] ) ) ) ;
const COMMANDE _CONFORME = Object . freeze ( {
'package.json' : scriptDeMesure ( 'vitest run --project node --coverage --reporter=default' ) ,
Makefile : '.PHONY: couverture\ncouverture: ## Mesure la couverture\n\t$(AVEC_NODE) npm run couverture\n' ,
} ) ;
const RAPPORT _CONFORME = Object . freeze ( [ [ 'text' , { skipFull : false } ] , 'html' ] ) ;
const COUVERTURE _CONFORME = Object . freeze ( {
include : [ 'src/**/*.js' ] ,
reporter : RAPPORT _CONFORME ,
thresholds : Object . fromEntries ( MODULES _A _SEUIL . map ( ( module ) => [ module , { branches : 100 } ] ) ) ,
} ) ;
describe ( 'arborescence : la couverture (§ 14.13)' , ( ) => {
test ( "make couverture et npm run couverture mesurent la série node ; le rapport montre chaque module ; aucun seuil global ; 100 % de branches sur chaque module nommé, présent dans l'arbre et dans la mesure" , ( ) => {
assert . deepEqual ( releverCouverture ( RACINE , configuration . test . coverage ) , [ ] ) ;
} ) ;
test ( "la garde relève un seuil global, un seuil hors des modules nommés, abaissé ou absent, un module absent de l'arbre ou de la mesure" , ( ) => {
const couverture = {
include : [ 'src/**/*.js' ] ,
exclude : [ '**/*.test.js' , 'src/stockage/depot.js' ] ,
reporter : RAPPORT _CONFORME ,
thresholds : {
branches : 90 ,
perFile : true ,
'src/moteur/indicateurs.js' : { branches : 100 } ,
'src/moteur/plafond.js' : { branches : 95 } ,
'src/stockage/journal.js' : { branches : 100 , lines : 100 } ,
'src/csv/**' : { branches : 100 } ,
} ,
} ;
const fichiers = {
... COMMANDE _CONFORME ,
'src/moteur/indicateurs.js' : '' ,
'src/stockage/depot.js' : '' ,
'src/stockage/journal.js' : '' ,
} ;
assert . deepEqual ( avecArbre ( fichiers , ( racine ) => releverCouverture ( racine , couverture ) ) , [
'seuil global : branches' ,
'seuil global : perFile' ,
'seuil hors des modules nommés : src/csv/**' ,
'src/moteur/plafond.js : branches à 95' ,
"src/moteur/plafond.js : absent de l'arbre" ,
'src/stockage/depot.js : aucun seuil' ,
'src/stockage/depot.js : hors de la mesure' ,
] ) ;
const sansInclude = { ... couverture , include : undefined , exclude : undefined , thresholds : { } } ;
assert . deepEqual (
avecArbre ( fichiers , ( racine ) => releverCouverture ( racine , sansInclude ) ) . filter ( ( e ) => e . endsWith ( 'mesure' ) ) ,
[ 'src/moteur/indicateurs.js : hors de la mesure' , 'src/stockage/depot.js : hors de la mesure' , 'src/stockage/journal.js : hors de la mesure' ] ,
) ;
assert . throws ( ( ) => releverCouverture ( RACINE , undefined ) , /aucune configuration de couverture/ ) ;
} ) ;
test ( 'la garde relève une commande qui ne mesure pas la série node, ou qui redéfinit la mesure ; make couverture passe par npm run couverture' , ( ) => {
const relever = ( fichiers ) =>
avecArbre ( { ... MODULES _MESURES , ... COMMANDE _CONFORME , ... fichiers } , ( racine ) =>
releverCouverture ( racine , COUVERTURE _CONFORME ) ,
) ;
assert . deepEqual ( relever ( { } ) , [ ] ) ;
assert . deepEqual ( relever ( { 'package.json' : scriptDeMesure ( 'vitest run --project=node --coverage --reporter default' ) } ) , [ ] ) ;
const scripts = [
[ 'vitest run --project node --reporter=default' , [ 'npm run couverture : sans --coverage' ] ] ,
[
'vitest run --project node --coverage --coverage.include=src/moteur/indicateurs.js --coverage.exclude=src/stockage/journal.js' ,
[
'npm run couverture : argument non admis --coverage.include=src/moteur/indicateurs.js' ,
'npm run couverture : argument non admis --coverage.exclude=src/stockage/journal.js' ,
] ,
] ,
[
'vitest run --project node-long --coverage' ,
[ 'npm run couverture : sans --project node' , 'npm run couverture : argument non admis --project=node-long' ] ,
] ,
[
'vitest run --project node --coverage --changed src/moteur' ,
[ 'npm run couverture : argument non admis --changed' , 'npm run couverture : argument non admis src/moteur' ] ,
] ,
[ 'vitest --project node --coverage' , [ 'npm run couverture : ne lance pas vitest run' ] ] ,
] ;
for ( const [ script , attendu ] of scripts ) {
assert . deepEqual ( relever ( { 'package.json' : scriptDeMesure ( script ) } ) , attendu , script ) ;
}
for ( const makefile of [ 'couverture:\n\t$(AVEC_NODE) npm test\n' , 'mesure:\n\t$(AVEC_NODE) npm run couverture\n' ] ) {
assert . deepEqual ( relever ( { Makefile : makefile } ) , [ 'make couverture : ne lance pas npm run couverture' ] , makefile ) ;
}
} ) ;
test ( "la garde relève un rapport qui tait les modules pleins, ou qui ne montre pas, ligne à ligne, ce qui ne s'exécute jamais" , ( ) => {
const relever = ( reporter ) =>
avecArbre ( { ... MODULES _MESURES , ... COMMANDE _CONFORME } , ( racine ) =>
releverCouverture ( racine , { ... COUVERTURE _CONFORME , reporter } ) ,
) ;
const sansTableau = 'rapport : aucun tableau text à skipFull: false' ;
const sansHtml = 'rapport : aucun rapport html' ;
assert . deepEqual ( relever ( [ [ 'html' ] , [ 'text' , { skipFull : false , maxCols : 120 } ] ] ) , [ ] ) ;
const rapporteurs = [
[ [ 'text-summary' ] , [ sansTableau , sansHtml ] ] ,
[ [ 'text' , 'html' ] , [ sansTableau ] ] ,
[ [ [ 'text' , { skipFull : true } ] , 'html' ] , [ sansTableau ] ] ,
[ 'html' , [ sansTableau ] ] ,
[ [ [ 'text' , { skipFull : false } ] ] , [ sansHtml ] ] ,
] ;
for ( const [ reporter , attendu ] of rapporteurs ) {
assert . deepEqual ( relever ( reporter ) , attendu , JSON . stringify ( reporter ) ) ;
}
} ) ;
} ) ;