[IMP] tests: watched series adapts to the core count, threads below 4
Below four cores the runner carried the watched series in one process,
and a relaunch after a base module took 2.5 to 3 s, over the 2 s budget
of § 14.14. The configuration now reads the cores the process may use:
from four, full processes and the whole series, as before; below, threads
on every core, and the end-to-end test moves to the long series. No test
disappears or changes behaviour. A guard refuses, in these series, what a
thread refuses and a process accepts; the reporter names the mode.
Checked: relaunch on 2 cores 1.0 to 1.3 s, was 2.5 to 3.0; on 4 cores
1.2 to 1.5 s; process.env is copied per thread, measured.
--- FR ---
[IMP] épreuves : la série surveillée suit les cœurs, threads sous 4
Sous quatre cœurs, le lanceur portait la série surveillée dans un seul
processus, et une relance après un module de base prenait 2,5 à 3 s,
au-delà du budget de 2 s du § 14.14. La configuration lit les cœurs que
le processus peut occuper : à partir de quatre, processus complets et
série entière, comme avant ; en deçà, threads sur tous les cœurs, et
l'épreuve de bout en bout passe dans la série longue. Aucune épreuve ne
disparaît ni ne change. Une garde refuse dans ces séries ce qu'un thread
refuse et qu'un processus accepte ; le rapporteur nomme le mode.
Vérifié : relance sur 2 cœurs en 1,0 à 1,3 s, contre 2,5 à 3,0 ; sur 4
cœurs en 1,2 à 1,5 s ; process.env est copié par thread, mesuré.
Assisted-by: Claude Opus 5.5
2026-10-06 04:54:01 -04:00
// © 2026 TechnoLibre (http://www.technolibre.ca)
// License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl)
[ADD] tests: guards for layers, clock, sources, colours, watch patterns
Guards scan the tree file by file and line by line, fail on an empty scan,
and are each shown red on a temporary tree. They cover the interface import
graph, the Electron bridge, one clock, refused dependencies, how tests are
written, hard-coded strings, translation keys, forbidden words, colours and
the conflict hue, markup, pruned selectors and watch patterns. Coverage
keeps the engine integration test on a small machine. Fixes: delays in
tests, the conflict hatch class; « la rend évitable » is a named exception
(§ 5.6). Checked: 2587 node, 465 browser tests, from the index alone.
--- FR ---
[ADD] épreuves : gardes des couches, horloge, sources, couleurs, motifs
Les gardes relèvent par fichier et par ligne, échouent sur un balayage vide
et sont chacune montrées rouges sur un arbre temporaire. Elles couvrent le
graphe d'imports de l'interface, le pont d'Electron, l'horloge unique, les
dépendances refusées, l'écriture des épreuves, les chaînes en dur, les clés
de traduction, les mots interdits, les couleurs et la teinte de conflit, le
balisage, les sélecteurs élagués et les motifs de surveillance. Corrigés :
délais d'épreuves, classe de la trame de conflit ; « la rend évitable » est
une exception nommée (§ 5.6). Vérifié : 2587 node, 465 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 13:21:21 -04:00
// Les réglages des séries node selon le nombre de cœurs (§ 14.14), sous la
// mesure de la couverture comme hors d'elle (§ 14.4, § 14.13), et leur
[IMP] tests: watched series adapts to the core count, threads below 4
Below four cores the runner carried the watched series in one process,
and a relaunch after a base module took 2.5 to 3 s, over the 2 s budget
of § 14.14. The configuration now reads the cores the process may use:
from four, full processes and the whole series, as before; below, threads
on every core, and the end-to-end test moves to the long series. No test
disappears or changes behaviour. A guard refuses, in these series, what a
thread refuses and a process accepts; the reporter names the mode.
Checked: relaunch on 2 cores 1.0 to 1.3 s, was 2.5 to 3.0; on 4 cores
1.2 to 1.5 s; process.env is copied per thread, measured.
--- FR ---
[IMP] épreuves : la série surveillée suit les cœurs, threads sous 4
Sous quatre cœurs, le lanceur portait la série surveillée dans un seul
processus, et une relance après un module de base prenait 2,5 à 3 s,
au-delà du budget de 2 s du § 14.14. La configuration lit les cœurs que
le processus peut occuper : à partir de quatre, processus complets et
série entière, comme avant ; en deçà, threads sur tous les cœurs, et
l'épreuve de bout en bout passe dans la série longue. Aucune épreuve ne
disparaît ni ne change. Une garde refuse dans ces séries ce qu'un thread
refuse et qu'un processus accepte ; le rapporteur nomme le mode.
Vérifié : relance sur 2 cœurs en 1,0 à 1,3 s, contre 2,5 à 3,0 ; sur 4
cœurs en 1,2 à 1,5 s ; process.env est copié par thread, mesuré.
Assisted-by: Claude Opus 5.5
2026-10-06 04:54:01 -04:00
// application dans vitest.config.js.
import assert from 'node:assert/strict' ;
[ADD] tests: guards for layers, clock, sources, colours, watch patterns
Guards scan the tree file by file and line by line, fail on an empty scan,
and are each shown red on a temporary tree. They cover the interface import
graph, the Electron bridge, one clock, refused dependencies, how tests are
written, hard-coded strings, translation keys, forbidden words, colours and
the conflict hue, markup, pruned selectors and watch patterns. Coverage
keeps the engine integration test on a small machine. Fixes: delays in
tests, the conflict hatch class; « la rend évitable » is a named exception
(§ 5.6). Checked: 2587 node, 465 browser tests, from the index alone.
--- FR ---
[ADD] épreuves : gardes des couches, horloge, sources, couleurs, motifs
Les gardes relèvent par fichier et par ligne, échouent sur un balayage vide
et sont chacune montrées rouges sur un arbre temporaire. Elles couvrent le
graphe d'imports de l'interface, le pont d'Electron, l'horloge unique, les
dépendances refusées, l'écriture des épreuves, les chaînes en dur, les clés
de traduction, les mots interdits, les couleurs et la teinte de conflit, le
balisage, les sélecteurs élagués et les motifs de surveillance. Corrigés :
délais d'épreuves, classe de la trame de conflit ; « la rend évitable » est
une exception nommée (§ 5.6). Vérifié : 2587 node, 465 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 13:21:21 -04:00
import { execFile } from 'node:child_process' ;
import { promisify } from 'node:util' ;
[IMP] tests: watched series adapts to the core count, threads below 4
Below four cores the runner carried the watched series in one process,
and a relaunch after a base module took 2.5 to 3 s, over the 2 s budget
of § 14.14. The configuration now reads the cores the process may use:
from four, full processes and the whole series, as before; below, threads
on every core, and the end-to-end test moves to the long series. No test
disappears or changes behaviour. A guard refuses, in these series, what a
thread refuses and a process accepts; the reporter names the mode.
Checked: relaunch on 2 cores 1.0 to 1.3 s, was 2.5 to 3.0; on 4 cores
1.2 to 1.5 s; process.env is copied per thread, measured.
--- FR ---
[IMP] épreuves : la série surveillée suit les cœurs, threads sous 4
Sous quatre cœurs, le lanceur portait la série surveillée dans un seul
processus, et une relance après un module de base prenait 2,5 à 3 s,
au-delà du budget de 2 s du § 14.14. La configuration lit les cœurs que
le processus peut occuper : à partir de quatre, processus complets et
série entière, comme avant ; en deçà, threads sur tous les cœurs, et
l'épreuve de bout en bout passe dans la série longue. Aucune épreuve ne
disparaît ni ne change. Une garde refuse dans ces séries ce qu'un thread
refuse et qu'un processus accepte ; le rapporteur nomme le mode.
Vérifié : relance sur 2 cœurs en 1,0 à 1,3 s, contre 2,5 à 3,0 ; sur 4
cœurs en 1,2 à 1,5 s ; process.env est copié par thread, mesuré.
Assisted-by: Claude Opus 5.5
2026-10-06 04:54:01 -04:00
import { existsSync } from 'node:fs' ;
import { availableParallelism } from 'node:os' ;
import { join } from 'node:path' ;
import { fileURLToPath } from 'node:url' ;
import configuration from '../vitest.config.js' ;
import { describe , test } from './lanceur.js' ;
import { LOURDES , SEUIL _COEURS , coeursDisponibles , ligneMachine , reglagesSeries } from './machine.js' ;
const RACINE = fileURLToPath ( new URL ( '..' , import . meta . url ) ) ;
const projet = ( nom ) => configuration . test . projects . find ( ( { test : { name } } ) => name === nom ) . test ;
describe ( 'machine : les réglages selon le nombre de cœurs (§ 14.14)' , ( ) => {
test ( 'à partir de quatre cœurs, des processus complets et la série surveillée entière' , ( ) => {
for ( const coeurs of [ SEUIL _COEURS , 8 , 16 , 64 ] ) {
assert . deepEqual ( reglagesSeries ( coeurs ) , {
petiteMachine : false ,
coeurs ,
pool : 'forks' ,
maxWorkers : undefined ,
horsSerieSurveillee : [ ] ,
} , ` ${ coeurs } cœurs ` ) ;
}
} ) ;
test ( 'en deçà de quatre cœurs, des threads sur tous les cœurs, et les épreuves lourdes en série longue' , ( ) => {
for ( const coeurs of [ 1 , 2 , 3 ] ) {
assert . deepEqual ( reglagesSeries ( coeurs ) , {
petiteMachine : true ,
coeurs ,
pool : 'threads' ,
maxWorkers : coeurs ,
horsSerieSurveillee : [ ... LOURDES ] ,
} , ` ${ coeurs } cœurs ` ) ;
}
} ) ;
[ADD] tests: guards for layers, clock, sources, colours, watch patterns
Guards scan the tree file by file and line by line, fail on an empty scan,
and are each shown red on a temporary tree. They cover the interface import
graph, the Electron bridge, one clock, refused dependencies, how tests are
written, hard-coded strings, translation keys, forbidden words, colours and
the conflict hue, markup, pruned selectors and watch patterns. Coverage
keeps the engine integration test on a small machine. Fixes: delays in
tests, the conflict hatch class; « la rend évitable » is a named exception
(§ 5.6). Checked: 2587 node, 465 browser tests, from the index alone.
--- FR ---
[ADD] épreuves : gardes des couches, horloge, sources, couleurs, motifs
Les gardes relèvent par fichier et par ligne, échouent sur un balayage vide
et sont chacune montrées rouges sur un arbre temporaire. Elles couvrent le
graphe d'imports de l'interface, le pont d'Electron, l'horloge unique, les
dépendances refusées, l'écriture des épreuves, les chaînes en dur, les clés
de traduction, les mots interdits, les couleurs et la teinte de conflit, le
balisage, les sélecteurs élagués et les motifs de surveillance. Corrigés :
délais d'épreuves, classe de la trame de conflit ; « la rend évitable » est
une exception nommée (§ 5.6). Vérifié : 2587 node, 465 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 13:21:21 -04:00
test ( 'sous la mesure de la couverture, aucune épreuve ne quitte la série node, sur une petite machine comme sur une grande ; le reste des réglages ne change pas' , ( ) => {
for ( const coeurs of [ 1 , 2 , 3 , SEUIL _COEURS , 16 ] ) {
assert . deepEqual (
reglagesSeries ( coeurs , { couverture : true } ) ,
{ ... reglagesSeries ( coeurs ) , horsSerieSurveillee : [ ] } ,
` ${ coeurs } cœurs ` ,
) ;
assert . deepEqual ( reglagesSeries ( coeurs , { couverture : false } ) , reglagesSeries ( coeurs ) , ` ${ coeurs } cœurs ` ) ;
}
assert . deepEqual ( reglagesSeries ( 2 ) . horsSerieSurveillee , [ ... LOURDES ] ) ;
} ) ;
[IMP] tests: watched series adapts to the core count, threads below 4
Below four cores the runner carried the watched series in one process,
and a relaunch after a base module took 2.5 to 3 s, over the 2 s budget
of § 14.14. The configuration now reads the cores the process may use:
from four, full processes and the whole series, as before; below, threads
on every core, and the end-to-end test moves to the long series. No test
disappears or changes behaviour. A guard refuses, in these series, what a
thread refuses and a process accepts; the reporter names the mode.
Checked: relaunch on 2 cores 1.0 to 1.3 s, was 2.5 to 3.0; on 4 cores
1.2 to 1.5 s; process.env is copied per thread, measured.
--- FR ---
[IMP] épreuves : la série surveillée suit les cœurs, threads sous 4
Sous quatre cœurs, le lanceur portait la série surveillée dans un seul
processus, et une relance après un module de base prenait 2,5 à 3 s,
au-delà du budget de 2 s du § 14.14. La configuration lit les cœurs que
le processus peut occuper : à partir de quatre, processus complets et
série entière, comme avant ; en deçà, threads sur tous les cœurs, et
l'épreuve de bout en bout passe dans la série longue. Aucune épreuve ne
disparaît ni ne change. Une garde refuse dans ces séries ce qu'un thread
refuse et qu'un processus accepte ; le rapporteur nomme le mode.
Vérifié : relance sur 2 cœurs en 1,0 à 1,3 s, contre 2,5 à 3,0 ; sur 4
cœurs en 1,2 à 1,5 s ; process.env est copié par thread, mesuré.
Assisted-by: Claude Opus 5.5
2026-10-06 04:54:01 -04:00
test ( 'un nombre de cœurs qui n’ est pas un entier ≥ 1 lève RangeError' , ( ) => {
for ( const coeurs of [ 0 , - 1 , 2.5 , Number . NaN , '4' , undefined ] ) {
assert . throws ( ( ) => reglagesSeries ( coeurs ) , RangeError , String ( coeurs ) ) ;
}
} ) ;
test ( 'les épreuves lourdes existent, sont de la série surveillée, et la liste n’ est pas vide' , ( ) => {
assert . ok ( LOURDES . length > 0 , 'aucune épreuve lourde nommée' ) ;
for ( const fichier of LOURDES ) {
assert . ok ( existsSync ( join ( RACINE , fichier ) ) , ` ${ fichier } absent ` ) ;
assert . match ( fichier , /\.test\.js$/ ) ;
assert . doesNotMatch ( fichier , /\.(long|navigateur)\.test\.js$/ , ` ${ fichier } n'est pas de la série surveillée ` ) ;
}
} ) ;
test ( 'les cœurs disponibles suivent l’ affinité du processus, comme availableParallelism' , ( ) => {
assert . equal ( coeursDisponibles ( ) , availableParallelism ( ) ) ;
assert . ok ( coeursDisponibles ( ) >= 1 ) ;
} ) ;
test ( 'la ligne annoncée dit le mode, sur une petite machine comme sur une grande' , ( ) => {
assert . equal (
ligneMachine ( reglagesSeries ( 2 ) ) ,
'Machine : 2 cœurs, en deçà de 4 — threads sur les 2 cœurs ; '
+ 'en série longue : src/moteur/integration.test.js.' ,
) ;
assert . equal (
ligneMachine ( reglagesSeries ( 1 ) ) ,
'Machine : 1 cœur, en deçà de 4 — threads sur son seul cœur ; '
+ 'en série longue : src/moteur/integration.test.js.' ,
) ;
assert . equal ( ligneMachine ( reglagesSeries ( 16 ) ) , 'Machine : 16 cœurs — processus complets, série surveillée entière.' ) ;
} ) ;
} ) ;
describe ( 'machine : vitest.config.js applique les réglages de cette machine' , ( ) => {
[ADD] tests: guards for layers, clock, sources, colours, watch patterns
Guards scan the tree file by file and line by line, fail on an empty scan,
and are each shown red on a temporary tree. They cover the interface import
graph, the Electron bridge, one clock, refused dependencies, how tests are
written, hard-coded strings, translation keys, forbidden words, colours and
the conflict hue, markup, pruned selectors and watch patterns. Coverage
keeps the engine integration test on a small machine. Fixes: delays in
tests, the conflict hatch class; « la rend évitable » is a named exception
(§ 5.6). Checked: 2587 node, 465 browser tests, from the index alone.
--- FR ---
[ADD] épreuves : gardes des couches, horloge, sources, couleurs, motifs
Les gardes relèvent par fichier et par ligne, échouent sur un balayage vide
et sont chacune montrées rouges sur un arbre temporaire. Elles couvrent le
graphe d'imports de l'interface, le pont d'Electron, l'horloge unique, les
dépendances refusées, l'écriture des épreuves, les chaînes en dur, les clés
de traduction, les mots interdits, les couleurs et la teinte de conflit, le
balisage, les sélecteurs élagués et les motifs de surveillance. Corrigés :
délais d'épreuves, classe de la trame de conflit ; « la rend évitable » est
une exception nommée (§ 5.6). Vérifié : 2587 node, 465 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 13:21:21 -04:00
// Les réglages de ce processus : ses cœurs, et la mesure de la couverture
// quand ses arguments portent --coverage, la règle de vitest.config.js.
const reglages = reglagesSeries ( coeursDisponibles ( ) , { couverture : process . argv . includes ( '--coverage' ) } ) ;
[IMP] tests: watched series adapts to the core count, threads below 4
Below four cores the runner carried the watched series in one process,
and a relaunch after a base module took 2.5 to 3 s, over the 2 s budget
of § 14.14. The configuration now reads the cores the process may use:
from four, full processes and the whole series, as before; below, threads
on every core, and the end-to-end test moves to the long series. No test
disappears or changes behaviour. A guard refuses, in these series, what a
thread refuses and a process accepts; the reporter names the mode.
Checked: relaunch on 2 cores 1.0 to 1.3 s, was 2.5 to 3.0; on 4 cores
1.2 to 1.5 s; process.env is copied per thread, measured.
--- FR ---
[IMP] épreuves : la série surveillée suit les cœurs, threads sous 4
Sous quatre cœurs, le lanceur portait la série surveillée dans un seul
processus, et une relance après un module de base prenait 2,5 à 3 s,
au-delà du budget de 2 s du § 14.14. La configuration lit les cœurs que
le processus peut occuper : à partir de quatre, processus complets et
série entière, comme avant ; en deçà, threads sur tous les cœurs, et
l'épreuve de bout en bout passe dans la série longue. Aucune épreuve ne
disparaît ni ne change. Une garde refuse dans ces séries ce qu'un thread
refuse et qu'un processus accepte ; le rapporteur nomme le mode.
Vérifié : relance sur 2 cœurs en 1,0 à 1,3 s, contre 2,5 à 3,0 ; sur 4
cœurs en 1,2 à 1,5 s ; process.env est copié par thread, mesuré.
Assisted-by: Claude Opus 5.5
2026-10-06 04:54:01 -04:00
test ( 'les projets node et node-long prennent le pool et le nombre de processus retenus' , ( ) => {
for ( const nom of [ 'node' , 'node-long' ] ) {
assert . equal ( projet ( nom ) . pool , reglages . pool , nom ) ;
assert . equal ( projet ( nom ) . maxWorkers , reglages . maxWorkers , nom ) ;
}
} ) ;
test ( 'une épreuve hors de la série surveillée entre dans la série longue, et nulle part ailleurs' , ( ) => {
for ( const fichier of reglages . horsSerieSurveillee ) {
assert . ok ( projet ( 'node' ) . exclude . includes ( fichier ) , ` ${ fichier } reste dans node ` ) ;
assert . ok ( projet ( 'node-long' ) . include . includes ( fichier ) , ` ${ fichier } manque à node-long ` ) ;
}
for ( const fichier of LOURDES . filter ( ( f ) => ! reglages . horsSerieSurveillee . includes ( f ) ) ) {
assert . ok ( ! projet ( 'node' ) . exclude . includes ( fichier ) , ` ${ fichier } sort de node sur cette machine ` ) ;
assert . ok ( ! projet ( 'node-long' ) . include . includes ( fichier ) , ` ${ fichier } entre dans node-long sur cette machine ` ) ;
}
} ) ;
test ( 'le projet navigateur ne prend aucun de ces réglages' , ( ) => {
const navigateur = projet ( 'navigateur' ) ;
assert . equal ( navigateur . pool , undefined ) ;
assert . equal ( navigateur . maxWorkers , undefined ) ;
} ) ;
} ) ;
[ADD] tests: guards for layers, clock, sources, colours, watch patterns
Guards scan the tree file by file and line by line, fail on an empty scan,
and are each shown red on a temporary tree. They cover the interface import
graph, the Electron bridge, one clock, refused dependencies, how tests are
written, hard-coded strings, translation keys, forbidden words, colours and
the conflict hue, markup, pruned selectors and watch patterns. Coverage
keeps the engine integration test on a small machine. Fixes: delays in
tests, the conflict hatch class; « la rend évitable » is a named exception
(§ 5.6). Checked: 2587 node, 465 browser tests, from the index alone.
--- FR ---
[ADD] épreuves : gardes des couches, horloge, sources, couleurs, motifs
Les gardes relèvent par fichier et par ligne, échouent sur un balayage vide
et sont chacune montrées rouges sur un arbre temporaire. Elles couvrent le
graphe d'imports de l'interface, le pont d'Electron, l'horloge unique, les
dépendances refusées, l'écriture des épreuves, les chaînes en dur, les clés
de traduction, les mots interdits, les couleurs et la teinte de conflit, le
balisage, les sélecteurs élagués et les motifs de surveillance. Corrigés :
délais d'épreuves, classe de la trame de conflit ; « la rend évitable » est
une exception nommée (§ 5.6). Vérifié : 2587 node, 465 navigateur.
Assisted-by: Claude Opus 5.5
2026-10-07 13:21:21 -04:00
// Projets node et node-long de vitest.config.js, chargé dans un processus à
// part dont la machine n'a que deux cœurs — availableParallelism remplacé
// avant tout import — et dont process.argv porte les arguments donnés, comme
// celui de npm run couverture porte --coverage. Rend la promesse de
// { node, long } : exclude du premier, include du second.
async function projetsSurDeuxCoeurs ( argumentsDuLanceur ) {
const deuxCoeurs = [
"import os from 'node:os';" ,
"import { syncBuiltinESMExports } from 'node:module';" ,
'os.availableParallelism = () => 2;' ,
'syncBuiltinESMExports();' ,
] . join ( '\n' ) ;
const lire = [
"const { default: configuration } = await import('./vitest.config.js');" ,
'const projet = (nom) => configuration.test.projects.find(({ test: { name } }) => name === nom).test;' ,
"console.log(JSON.stringify({ node: projet('node').exclude, long: projet('node-long').include }));" ,
] . join ( '\n' ) ;
const { stdout } = await promisify ( execFile ) (
process . execPath ,
[ '--import' , ` data:text/javascript, ${ encodeURIComponent ( deuxCoeurs ) } ` , '--input-type=module' , '-e' , lire , '--' , ... argumentsDuLanceur ] ,
{ cwd : RACINE , encoding : 'utf8' } ,
) ;
return JSON . parse ( stdout ) ;
}
describe ( 'machine : vitest.config.js garde la série node entière sous la mesure de la couverture (§ 14.13)' , ( ) => {
test ( 'sur deux cœurs, --coverage garde les épreuves lourdes dans node, où se mesurent les seuils d’ indicateurs.js et de plafond.js ; sans lui, elles passent dans node-long' , async ( ) => {
// Les deux processus partent ensemble : la durée de l'épreuve est celle
// d'un seul.
const [ mesure , surveillee ] = await Promise . all ( [
projetsSurDeuxCoeurs ( [ '--project' , 'node' , '--coverage' ] ) ,
projetsSurDeuxCoeurs ( [ '--project' , 'node' ] ) ,
] ) ;
assert . ok ( LOURDES . length > 0 , 'aucune épreuve lourde nommée' ) ;
for ( const fichier of LOURDES ) {
assert . ok ( ! mesure . node . includes ( fichier ) , ` ${ fichier } sort de node sous --coverage ` ) ;
assert . ok ( ! mesure . long . includes ( fichier ) , ` ${ fichier } entre dans node-long sous --coverage ` ) ;
assert . ok ( surveillee . node . includes ( fichier ) , ` ${ fichier } reste dans node sur deux cœurs ` ) ;
assert . ok ( surveillee . long . includes ( fichier ) , ` ${ fichier } manque à node-long sur deux cœurs ` ) ;
}
} ) ;
} ) ;