@roomi-fields/grillhouse 0.23.1 → 0.24.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/METACADRE.md +1 -1
- package/agents/explorateur.md +4 -2
- package/agents/questionneur.md +1 -1
- package/bin/grillhouse.mjs +3 -58
- package/cadre/templates/projet/CLAUDE.md +5 -1
- package/cadre/templates/projet/docs/agents/issue-tracker.md +4 -4
- package/charte.md +23 -6
- package/docs/ARCHITECTURE.md +130 -1
- package/hooks/register.tsx +3 -13
- package/package.json +13 -1
- package/scripts/bilan.mjs +134 -88
- package/scripts/circuit.mjs +1547 -2248
- package/scripts/composants-affectes.mjs +27 -108
- package/scripts/consommateurs-arbitres.mjs +15 -21
- package/scripts/consommateurs.d.ts +8 -0
- package/scripts/consommateurs.mjs +5 -1
- package/scripts/dette.d.ts +23 -0
- package/scripts/dette.mjs +76 -13
- package/scripts/droits.mjs +38 -44
- package/scripts/elements-du-lot.mjs +246 -0
- package/scripts/enveloppe/enveloppe.mjs +105 -232
- package/scripts/enveloppe/lancer.sh +79 -49
- package/scripts/enveloppe/paquets-du-plan.mjs +49 -0
- package/scripts/etapes.mjs +148 -213
- package/scripts/frontieres.mjs +4 -2
- package/scripts/gardes-du-cadre.mjs +8 -6
- package/scripts/grillhouse-maj.mjs +113 -19
- package/scripts/index-interfaces.mjs +21 -1
- package/scripts/integration/integrer.mjs +2 -2
- package/scripts/interfaces-contre-code.mjs +25 -17
- package/scripts/migrations/0.23.0-config-vitest.mjs +26 -23
- package/scripts/migrations/0.23.2-copies-du-cadre.mjs +201 -0
- package/scripts/migrations/0.24.0-circuit-simplifie.mjs +274 -0
- package/scripts/migrations.mjs +41 -6
- package/scripts/paquets.d.ts +5 -0
- package/scripts/paquets.mjs +3 -0
- package/scripts/references-par-les-types.mjs +55 -36
- package/scripts/registre.mjs +7 -15
- package/scripts/resultats.mjs +283 -142
- package/scripts/resumes.mjs +1 -1
- package/scripts/session-start.sh +1 -2
- package/scripts/sources.mjs +28 -0
- package/scripts/sous-commandes.mjs +62 -0
- package/scripts/tableau.mjs +85 -191
- package/scripts/tests.mjs +19 -17
- package/scripts/verifier.mjs +5 -4
- package/scripts/verrou-de-machine.mjs +131 -24
- package/scripts/verrous/verrou.mjs +66 -5
- package/skills/developpeur/SKILL.md +60 -50
- package/skills/explorateur/SKILL.md +90 -64
- package/skills/grill/SKILL.md +1 -1
- package/skills/mesure/SKILL.md +2 -1
- package/skills/pitmaster/SKILL.md +132 -118
- package/skills/pitmaster/references/consigne-agent.md +54 -148
- package/skills/questionneur/SKILL.md +18 -18
- package/skills/relecteur/SKILL.md +69 -23
- package/skills/testwriter/SKILL.md +46 -35
- package/types/index.d.ts +1 -3
- package/agents/referent-technique.md +0 -9
- package/agents/regulateur.md +0 -11
- package/scripts/enveloppe/composant.mjs +0 -11
- package/scripts/etat-du-circuit.mjs +0 -104
- package/skills/referent-technique/SKILL.md +0 -145
- package/skills/regulateur/SKILL.md +0 -220
|
@@ -13,7 +13,14 @@
|
|
|
13
13
|
// - The migrations first (scripts/migrations.mjs): each migration of the package newer than the
|
|
14
14
|
// version the project recorded (`grillhouse.version` of its package.json; none recorded, every
|
|
15
15
|
// migration), in the order of their versions; each is replayable without effect, and the report
|
|
16
|
-
// names each one that changed something, with what it changed.
|
|
16
|
+
// names each one that changed something, with what it changed. What a migration leaves to the
|
|
17
|
+
// project (a copy of the frame the project modified, scripts/migrations/0.23.2-copies-du-cadre.mjs)
|
|
18
|
+
// is written on the error stream, with the command that does it, and the exit code is non-zero;
|
|
19
|
+
// the project keeps the version it recorded, so that the next update plays that migration again.
|
|
20
|
+
// Last, after the update and the regeneration, what stays to the project (`restes` of a
|
|
21
|
+
// migration played, scripts/migrations.mjs: in 0.24.0, a file that still calls a former copy of
|
|
22
|
+
// the frame) is reported on the standard output, « reste au projet », with no effect on the exit
|
|
23
|
+
// code nor on the version recorded.
|
|
17
24
|
// - The frame copies no file into a project: its scripts are the package's, its skills, agents,
|
|
18
25
|
// hooks of Claude Code, common charter and meta-frame the plugin's, which the package carries
|
|
19
26
|
// (scripts/cadre.mjs): the frame arrives in one piece, at the version npm installs.
|
|
@@ -31,7 +38,8 @@
|
|
|
31
38
|
// the frame's status line (`ligne-etat`, whatever its former form); a status line of the
|
|
32
39
|
// project's own stays. The settings keep their other keys, in their order.
|
|
33
40
|
// - `package.json`, when there is one: the version of the frame it is brought to
|
|
34
|
-
// (`grillhouse.version`, the package's version
|
|
41
|
+
// (`grillhouse.version`, the package's version once no migration leaves anything to do), the
|
|
42
|
+
// frame's npm scripts (`tableau`,
|
|
35
43
|
// `grillhouse:maj`), its `prepare` beginning with `grillhouse hooks` (the frame's git hooks at
|
|
36
44
|
// each `npm install`, as Husky's `prepare`; a `prepare` of the project's own follows it,
|
|
37
45
|
// `grillhouse hooks && …`), and `grillhouse:gardes` (scripts/gardes-du-cadre.mjs, the frame's controls), `grillhouse:dette:inscrire` and
|
|
@@ -89,6 +97,13 @@
|
|
|
89
97
|
// `^<version>` of the package), a declaration it holds kept; a package out of the frame is not
|
|
90
98
|
// touched. The report names the packages that received it, `npm install`, which links it, and the
|
|
91
99
|
// import; the update writes no Vitest configuration.
|
|
100
|
+
// - A package of the frame whose code imports the frame's package (a file of its `src/` out of the
|
|
101
|
+
// tests, the files whose development dependencies the guard of the boundaries refuses,
|
|
102
|
+
// scripts/frontieres.mjs; its imports read by TypeScript's `preProcessFile`) declares it in its
|
|
103
|
+
// `dependencies`, as npm puts there what the published code imports: a declaration in its
|
|
104
|
+
// `devDependencies` moves there with its range, else the range the root declares (else
|
|
105
|
+
// `^<version>`); this comes first, so that the declaration of the Vitest base above keeps it.
|
|
106
|
+
// The report names the packages and `npm install`.
|
|
92
107
|
// - The git hooks: both of the frame (commit-msg « a closed ticket refuses a second commit, a reopened ticket takes its corrections », pre-push night branch
|
|
93
108
|
// guard) are placed by scripts/crochets.mjs, the mechanism `grillhouse hooks` (the project's
|
|
94
109
|
// `prepare`) also runs, in the hooks folder git reads for the project (`core.hooksPath`, else the
|
|
@@ -114,14 +129,17 @@
|
|
|
114
129
|
// - The report names the version of the frame, « Cadre 0.23.0. », the package's.
|
|
115
130
|
import { spawnSync } from 'node:child_process';
|
|
116
131
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
132
|
+
import { createRequire } from 'node:module';
|
|
117
133
|
import path from 'node:path';
|
|
118
134
|
import { pathToFileURL } from 'node:url';
|
|
119
135
|
import semver from 'semver';
|
|
120
136
|
import { CADRE, VERSION } from './cadre.mjs';
|
|
121
137
|
import { poserCrochets } from './crochets.mjs';
|
|
122
138
|
import { installerGreffons } from './greffons.mjs';
|
|
123
|
-
import { migrer } from './migrations.mjs';
|
|
139
|
+
import { migrer, restesAuProjet } from './migrations.mjs';
|
|
140
|
+
import { CODE, TESTS } from './frontieres.mjs';
|
|
124
141
|
import { paquets } from './paquets.mjs';
|
|
142
|
+
import { sources } from './sources.mjs';
|
|
125
143
|
|
|
126
144
|
const SCRIPTS = {
|
|
127
145
|
tableau: 'grillhouse tableau --texte',
|
|
@@ -211,6 +229,64 @@ function poserTurbo(projet, source) {
|
|
|
211
229
|
return gabarit;
|
|
212
230
|
}
|
|
213
231
|
|
|
232
|
+
// <deps> written sorted by name, as npm writes them.
|
|
233
|
+
const trie = deps =>
|
|
234
|
+
Object.fromEntries(Object.entries(deps).sort(([a], [b]) => a.localeCompare(b, 'en')));
|
|
235
|
+
// The range at which the root package.json <p> declares the frame's package, or undefined.
|
|
236
|
+
const plageDeLaRacine = p =>
|
|
237
|
+
CHAMPS_INSTALLES.map(c => p[c]?.[PAQUET_DU_CADRE]).find(v => v !== undefined);
|
|
238
|
+
|
|
239
|
+
// Whether the code of the package at <dossier> of <projet> imports the frame's package (an entry of
|
|
240
|
+
// it): a file of its `src/` out of the tests (CODE and TESTS of scripts/frontieres.mjs, the files
|
|
241
|
+
// whose development dependencies its guard refuses), its imports read by TypeScript
|
|
242
|
+
// (`preProcessFile`), a comment or a string importing nothing.
|
|
243
|
+
function codeImporteLeCadre(projet, dossier) {
|
|
244
|
+
const ts = createRequire(import.meta.url)('typescript');
|
|
245
|
+
return sources(path.join(projet, dossier))
|
|
246
|
+
.map(f => `${dossier}/${f}`)
|
|
247
|
+
.filter(f => new RegExp(CODE).test(f) && !new RegExp(TESTS).test(f))
|
|
248
|
+
.some(f =>
|
|
249
|
+
ts
|
|
250
|
+
.preProcessFile(readFileSync(path.join(projet, f), 'utf8'), true, true)
|
|
251
|
+
.importedFiles.some(
|
|
252
|
+
({ fileName: m }) => m === PAQUET_DU_CADRE || m.startsWith(`${PAQUET_DU_CADRE}/`)
|
|
253
|
+
)
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Declares the frame's package in the dependencies of each package of the frame of the project of
|
|
258
|
+
// packages at <projet> (root package.json <p>) whose code imports it (codeImporteLeCadre), as npm
|
|
259
|
+
// puts what the published code imports: a declaration in its devDependencies moves there with its
|
|
260
|
+
// range, else the range the root declares (else `^<version>` of the package); one already in its
|
|
261
|
+
// dependencies or optionalDependencies stays. Returns { nom, paquets } (paquets: the packages
|
|
262
|
+
// whose dependencies received it), or null when nothing changes.
|
|
263
|
+
function declarerDependanceDuCadre(projet, p) {
|
|
264
|
+
if (p.workspaces === undefined) {
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
const racine = plageDeLaRacine(p);
|
|
268
|
+
const declarants = [];
|
|
269
|
+
for (const { dossier, pkg, hors } of paquets(projet)) {
|
|
270
|
+
const declare = ['dependencies', 'optionalDependencies'].some(
|
|
271
|
+
c => pkg[c]?.[PAQUET_DU_CADRE] !== undefined
|
|
272
|
+
);
|
|
273
|
+
if (hors || declare || !codeImporteLeCadre(projet, dossier)) {
|
|
274
|
+
continue;
|
|
275
|
+
}
|
|
276
|
+
const { [PAQUET_DU_CADRE]: dev, ...autres } = pkg.devDependencies ?? {};
|
|
277
|
+
pkg.dependencies = trie({
|
|
278
|
+
...(pkg.dependencies ?? {}),
|
|
279
|
+
[PAQUET_DU_CADRE]: dev ?? racine ?? `^${VERSION}`,
|
|
280
|
+
});
|
|
281
|
+
if (dev !== undefined) {
|
|
282
|
+
pkg.devDependencies = autres;
|
|
283
|
+
}
|
|
284
|
+
writeFileSync(path.join(projet, dossier, 'package.json'), `${JSON.stringify(pkg, null, 2)}\n`);
|
|
285
|
+
declarants.push(dossier);
|
|
286
|
+
}
|
|
287
|
+
return declarants.length > 0 ? { nom: PAQUET_DU_CADRE, paquets: declarants } : null;
|
|
288
|
+
}
|
|
289
|
+
|
|
214
290
|
// Declares the frame's package, whose base configuration of Vitest each Vitest configuration
|
|
215
291
|
// imports, in the devDependencies of each package of the frame of the project of packages at
|
|
216
292
|
// <projet> (root package.json <p>) whose scripts hold `test:vitest`, at the range the root declares
|
|
@@ -222,16 +298,14 @@ function poserConfigVitest(projet, p) {
|
|
|
222
298
|
const testes = paquets(projet).filter(
|
|
223
299
|
({ pkg, hors }) => !hors && typeof pkg.scripts?.['test:vitest'] === 'string'
|
|
224
300
|
);
|
|
225
|
-
const racine =
|
|
301
|
+
const racine = plageDeLaRacine(p);
|
|
226
302
|
const declarants = [];
|
|
227
303
|
for (const { dossier, pkg } of testes) {
|
|
228
304
|
if (CHAMPS_INSTALLES.some(c => pkg[c]?.[PAQUET_DU_CADRE] !== undefined)) continue;
|
|
229
|
-
pkg.devDependencies =
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
}).sort(([a], [b]) => a.localeCompare(b, 'en'))
|
|
234
|
-
);
|
|
305
|
+
pkg.devDependencies = trie({
|
|
306
|
+
...(pkg.devDependencies ?? {}),
|
|
307
|
+
[PAQUET_DU_CADRE]: racine ?? `^${VERSION}`,
|
|
308
|
+
});
|
|
235
309
|
writeFileSync(path.join(projet, dossier, 'package.json'), `${JSON.stringify(pkg, null, 2)}\n`);
|
|
236
310
|
declarants.push(dossier);
|
|
237
311
|
}
|
|
@@ -285,15 +359,17 @@ export function versionDuProjet(projet) {
|
|
|
285
359
|
|
|
286
360
|
/**
|
|
287
361
|
* Brings the project at `projet` to the frame's files at `source` (CADRE, scripts/cadre.mjs; a
|
|
288
|
-
* trial's own in the tests)
|
|
362
|
+
* trial's own in the tests); <inscrite> is the version it records (the package's; null records
|
|
363
|
+
* none, the project keeping its own). Returns what changed.
|
|
289
364
|
*/
|
|
290
|
-
export function mettreAJour(projet, source) {
|
|
365
|
+
export function mettreAJour(projet, source, { inscrite = VERSION } = {}) {
|
|
291
366
|
const bilan = {
|
|
292
367
|
dependances: [],
|
|
293
368
|
test: null,
|
|
294
369
|
vitest: null,
|
|
295
370
|
turbo: null,
|
|
296
371
|
configVitest: null,
|
|
372
|
+
dependanceDuCadre: null,
|
|
297
373
|
gardes: null,
|
|
298
374
|
ligneEtat: false,
|
|
299
375
|
greffon: false,
|
|
@@ -301,7 +377,7 @@ export function mettreAJour(projet, source) {
|
|
|
301
377
|
const pkg = path.join(projet, 'package.json');
|
|
302
378
|
if (existsSync(pkg)) {
|
|
303
379
|
const p = lireJson(pkg, {});
|
|
304
|
-
p.grillhouse = { ...(p.grillhouse ?? {}), version:
|
|
380
|
+
if (inscrite !== null) p.grillhouse = { ...(p.grillhouse ?? {}), version: inscrite };
|
|
305
381
|
const pkgSource = lireJson(path.join(source, GABARIT), {});
|
|
306
382
|
const gardes = pkgSource.scripts?.['grillhouse:gardes'];
|
|
307
383
|
p.scripts = { ...(p.scripts ?? {}), ...SCRIPTS };
|
|
@@ -353,9 +429,7 @@ export function mettreAJour(projet, source) {
|
|
|
353
429
|
}
|
|
354
430
|
}
|
|
355
431
|
if (p.devDependencies) {
|
|
356
|
-
p.devDependencies =
|
|
357
|
-
Object.entries(p.devDependencies).sort(([a], [b]) => a.localeCompare(b, 'en'))
|
|
358
|
-
);
|
|
432
|
+
p.devDependencies = trie(p.devDependencies);
|
|
359
433
|
}
|
|
360
434
|
if (typeof pkgSource.packageManager === 'string' && typeof p.packageManager !== 'string') {
|
|
361
435
|
p.packageManager = pkgSource.packageManager;
|
|
@@ -394,6 +468,7 @@ export function mettreAJour(projet, source) {
|
|
|
394
468
|
bilan.gardes = { deplace: false };
|
|
395
469
|
}
|
|
396
470
|
}
|
|
471
|
+
bilan.dependanceDuCadre = declarerDependanceDuCadre(projet, p);
|
|
397
472
|
bilan.configVitest = poserConfigVitest(projet, p);
|
|
398
473
|
writeFileSync(pkg, `${JSON.stringify(p, null, 2)}\n`);
|
|
399
474
|
}
|
|
@@ -453,6 +528,12 @@ export function rapport(b) {
|
|
|
453
528
|
`Configuration de base de Vitest : ${nom} déclaré dans les devDependencies de ${declarants.join(', ')}. \`npm install\` relie le paquet. La configuration Vitest de chaque paquet l'importe par son nom : \`import base from '${CONFIG_VITEST}'\`.`
|
|
454
529
|
);
|
|
455
530
|
}
|
|
531
|
+
if (b.dependanceDuCadre) {
|
|
532
|
+
const { nom, paquets: declarants } = b.dependanceDuCadre;
|
|
533
|
+
lignes.push(
|
|
534
|
+
`Dépendance d'exécution : ${nom} déclaré dans les dependencies de ${declarants.join(', ')}, dont le code hors des tests importe une entrée du paquet. \`npm install\` relie le paquet.`
|
|
535
|
+
);
|
|
536
|
+
}
|
|
456
537
|
if (b.turbo) {
|
|
457
538
|
lignes.push(
|
|
458
539
|
`turbo.json écrit depuis le gabarit du cadre ${b.turbo} ; il est au projet, la mise à jour n'y touche plus.`
|
|
@@ -497,18 +578,31 @@ if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
|
|
|
497
578
|
process.exitCode = 2;
|
|
498
579
|
} else {
|
|
499
580
|
const projet = process.cwd();
|
|
500
|
-
const
|
|
501
|
-
const
|
|
581
|
+
const depuis = versionDuProjet(projet);
|
|
582
|
+
const migrations = migrer(projet, depuis);
|
|
583
|
+
const resteAFaire = migrations.some(m => m.aFaire.length > 0);
|
|
584
|
+
const b = mettreAJour(projet, CADRE, resteAFaire ? { inscrite: null } : {});
|
|
502
585
|
process.stdout.write(`Cadre ${VERSION}.\n`);
|
|
503
|
-
for (const { version, nom, lignes } of migrations) {
|
|
586
|
+
for (const { version, nom, lignes, aFaire } of migrations) {
|
|
504
587
|
process.stdout.write(
|
|
505
588
|
`Migration ${version} (${nom}) :\n${lignes.map(l => `- ${l}\n`).join('')}`
|
|
506
589
|
);
|
|
590
|
+
if (aFaire.length > 0) {
|
|
591
|
+
process.stderr.write(
|
|
592
|
+
`Migration ${version} (${nom}), à faire :\n${aFaire.map(l => `- ${l}\n`).join('')}`
|
|
593
|
+
);
|
|
594
|
+
process.exitCode = 1;
|
|
595
|
+
}
|
|
507
596
|
}
|
|
508
597
|
process.stdout.write(rapport(b));
|
|
509
598
|
for (const l of [...regenerer(projet), ...installerGreffons(projet)]) {
|
|
510
599
|
process.stderr.write(`${l}\n`);
|
|
511
600
|
process.exitCode = 1;
|
|
512
601
|
}
|
|
602
|
+
for (const { version, nom, lignes } of restesAuProjet(projet, depuis)) {
|
|
603
|
+
process.stdout.write(
|
|
604
|
+
`Migration ${version} (${nom}), reste au projet :\n${lignes.map(l => `- ${l}\n`).join('')}`
|
|
605
|
+
);
|
|
606
|
+
}
|
|
513
607
|
}
|
|
514
608
|
}
|
|
@@ -36,6 +36,7 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
|
36
36
|
import path from 'node:path';
|
|
37
37
|
import { pathToFileURL } from 'node:url';
|
|
38
38
|
import { composants, declares } from './consommateurs.mjs';
|
|
39
|
+
import { lireLaListe } from './enveloppe/paquets-du-plan.mjs';
|
|
39
40
|
import { DEBUT, FIN, marques } from './interfaces-contre-code.mjs';
|
|
40
41
|
import { ecrireSarif } from './resultats.mjs';
|
|
41
42
|
|
|
@@ -179,7 +180,10 @@ function rend(racine, rel) {
|
|
|
179
180
|
// What the components before <composant> publish, as the section the launcher writes after the
|
|
180
181
|
// instruction of a role agent (scripts/enveloppe/lancer.sh). <composant> is the component's path
|
|
181
182
|
// in the repository at <racine> (`packages/a`, `src/parser`), or `.` for a copy of the whole
|
|
182
|
-
// repository, which the section points to the index of the interfaces
|
|
183
|
+
// repository, which the section points to the index of the interfaces; or the plan of a session,
|
|
184
|
+
// several paths in the form of the envelope's list (`packages/a:packages/b`, `lireLaListe`), one
|
|
185
|
+
// part of the section per package of the plan, its providers under it, as one session works the
|
|
186
|
+
// whole plan of a ticket (grillhouse-3uv.95.6). Its providers are the
|
|
183
187
|
// components whose `## Consommateurs` section names it; for each, its line in the index of the
|
|
184
188
|
// interfaces (its heading, its first sentence, its interface), the names of the elements its
|
|
185
189
|
// `## Consommateurs` line declares for the component, never their sentence, which the index of the
|
|
@@ -187,7 +191,23 @@ function rend(racine, rel) {
|
|
|
187
191
|
// or one line saying the frame or the rubric is missing. A declaration of `*`, an import of the
|
|
188
192
|
// whole component, names no element: its line says the elements are in the index. Each interface
|
|
189
193
|
// and each frame is read once.
|
|
194
|
+
/** @param {string} racine @param {string} composant @returns {string} */
|
|
190
195
|
export function publie(racine, composant) {
|
|
196
|
+
const plan = lireLaListe(composant);
|
|
197
|
+
if (plan.length > 1) {
|
|
198
|
+
const parties = plan.map(c =>
|
|
199
|
+
publie(racine, c)
|
|
200
|
+
.split('\n')
|
|
201
|
+
.slice(2)
|
|
202
|
+
.map(l => (l.startsWith('### ') ? `#${l}` : l))
|
|
203
|
+
);
|
|
204
|
+
return [
|
|
205
|
+
TITRE_PUBLIE,
|
|
206
|
+
'',
|
|
207
|
+
'Ton plan porte plusieurs paquets : pour chacun, ce que publient les composants dont il dépend.',
|
|
208
|
+
...plan.flatMap((c, i) => ['', `### Pour \`${path.basename(c)}\``, '', ...parties[i]]),
|
|
209
|
+
].join('\n');
|
|
210
|
+
}
|
|
191
211
|
if (composant === '.') {
|
|
192
212
|
return [
|
|
193
213
|
TITRE_PUBLIE,
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
// --ticket is a usage error, named. In order, each step refusing stops the run:
|
|
15
15
|
// 1. the verdict: the ticket has `ACCEPTÉ` as its last reviewer verdict (`ACCEPTÉ` or
|
|
16
16
|
// `RENDU` at the start of a comment of the author `relecteur`; another author's is none) and, when labelled `arbitrage`, each arbitrage
|
|
17
|
-
// (`estArbitrage`: a « ## Arbitrage » comment,
|
|
18
|
-
// (`arbitrageTranche`:
|
|
17
|
+
// (`estArbitrage`: a « ## Arbitrage » comment, the supervisor's) is settled
|
|
18
|
+
// (`arbitrageTranche`: `### Verdict — tranché`, or a « ## Réponse du
|
|
19
19
|
// responsable » comment after it);
|
|
20
20
|
// 2. the lots: the tests lot touches only what the testwriter writes (`isTesterFile`: test files
|
|
21
21
|
// and the shared test material), the code lot none of it;
|
|
@@ -45,10 +45,10 @@
|
|
|
45
45
|
// `faute-mal-formee`, `faute-hors-catalogue`, `faute-non-nommee`, `faute-non-produite`,
|
|
46
46
|
// `faute-non-listee`), or by the declaration file and TSDoc's message id for a TSDoc message.
|
|
47
47
|
//
|
|
48
|
-
// In the envelope of
|
|
49
|
-
// check and `npm run api`
|
|
50
|
-
//
|
|
51
|
-
//
|
|
48
|
+
// In the envelope of an agent (`GRILLHOUSE_ENVELOPPE`, scripts/enveloppe/paquets-du-plan.mjs), the
|
|
49
|
+
// check and `npm run api` judge and write the components of its plan alone: the others are
|
|
50
|
+
// read-only there, and the integration checks every component on the whole repository. The
|
|
51
|
+
// component's build comes first, as outside (`npm test -- <its files>` builds it).
|
|
52
52
|
//
|
|
53
53
|
// A component without `docs/INTERFACE.md` is reported and skipped. A project that prefers a
|
|
54
54
|
// bench per component calls `verifierComposant(racine, composant)` from its test.
|
|
@@ -58,7 +58,7 @@ import { tmpdir } from 'node:os';
|
|
|
58
58
|
import path from 'node:path';
|
|
59
59
|
import { pathToFileURL } from 'node:url';
|
|
60
60
|
import { composants, lireSiPresent, parcourir } from './consommateurs.mjs';
|
|
61
|
-
import {
|
|
61
|
+
import { paquetsDeLEnveloppe } from './enveloppe/paquets-du-plan.mjs';
|
|
62
62
|
import { trancher } from './dette.mjs';
|
|
63
63
|
|
|
64
64
|
const require = createRequire(import.meta.url);
|
|
@@ -428,7 +428,10 @@ function avecPartie(m, texte, partie) {
|
|
|
428
428
|
// the debt (`dette.mjs`) judges, keyed by the component's interface (by the declaration file for a
|
|
429
429
|
// TSDoc message, its rule TSDoc's message id); a refusal that a command or a build repairs (a
|
|
430
430
|
// generated part, an API report, a built entry, the marks, the TSDoc configuration) has no key and
|
|
431
|
-
// is never inscribed.
|
|
431
|
+
// is never inscribed. The refusals `npm run api` lifts carry their rule without a file, never
|
|
432
|
+
// inscribed either: `rapport-api` (the API report absent or stale) and `partie-generee` (the
|
|
433
|
+
// generated part of the interface), by which the circuit regenerates them at the final pass
|
|
434
|
+
// (scripts/circuit.mjs, the references of the frame).
|
|
432
435
|
export function verifierComposant(racine, c, { ecrire = false } = {}) {
|
|
433
436
|
const refus = [];
|
|
434
437
|
const signaux = [];
|
|
@@ -442,6 +445,8 @@ export function verifierComposant(racine, c, { ecrire = false } = {}) {
|
|
|
442
445
|
? { fichier, ...(ligne ? { ligne } : {}), regle, message: `${rel} : ${texte}` }
|
|
443
446
|
: { message: `${rel} : ${texte}` }
|
|
444
447
|
);
|
|
448
|
+
// A refusal `npm run api` lifts: its rule, no file.
|
|
449
|
+
const aRegenerer = (texte, regle) => refus.push({ regle, message: `${rel} : ${texte}` });
|
|
445
450
|
if (!existsSync(iface)) {
|
|
446
451
|
signaux.push(`${rel} n'a pas d'interface (docs/INTERFACE.md) : rien n'est vérifié.`);
|
|
447
452
|
return { refus, signaux };
|
|
@@ -474,12 +479,14 @@ export function verifierComposant(racine, c, { ecrire = false } = {}) {
|
|
|
474
479
|
}
|
|
475
480
|
const manque = !ecrire && !existsSync(path.join(c.dir, 'docs', 'INTERFACE.api.md'));
|
|
476
481
|
if (manque) {
|
|
477
|
-
|
|
478
|
-
"son rapport docs/INTERFACE.api.md manque ; npm run api l'écrit, après la construction."
|
|
482
|
+
aRegenerer(
|
|
483
|
+
"son rapport docs/INTERFACE.api.md manque ; npm run api l'écrit, après la construction.",
|
|
484
|
+
'rapport-api'
|
|
479
485
|
);
|
|
480
486
|
} else if (!api.ajour && !ecrire) {
|
|
481
|
-
|
|
482
|
-
"l'API a changé sans son rapport docs/INTERFACE.api.md ; npm run api le régénère, après la construction."
|
|
487
|
+
aRegenerer(
|
|
488
|
+
"l'API a changé sans son rapport docs/INTERFACE.api.md ; npm run api le régénère, après la construction.",
|
|
489
|
+
'rapport-api'
|
|
483
490
|
);
|
|
484
491
|
}
|
|
485
492
|
const nommees = new Set();
|
|
@@ -497,8 +504,9 @@ export function verifierComposant(racine, c, { ecrire = false } = {}) {
|
|
|
497
504
|
if (ecrire) {
|
|
498
505
|
if (attendu !== texte) writeFileSync(iface, attendu);
|
|
499
506
|
} else if (attendu !== texte) {
|
|
500
|
-
|
|
501
|
-
`la part générée de docs/INTERFACE.md (entre ${DEBUT} et ${FIN}) n'est pas celle du code ; npm run api la refait
|
|
507
|
+
aRegenerer(
|
|
508
|
+
`la part générée de docs/INTERFACE.md (entre ${DEBUT} et ${FIN}) n'est pas celle du code ; npm run api la refait.`,
|
|
509
|
+
'partie-generee'
|
|
502
510
|
);
|
|
503
511
|
}
|
|
504
512
|
}
|
|
@@ -522,13 +530,13 @@ function codesContreCatalogue(c, racine, fautes, refuser) {
|
|
|
522
530
|
}
|
|
523
531
|
}
|
|
524
532
|
|
|
525
|
-
// The components a run reads: every one of <racine>; in
|
|
526
|
-
//
|
|
533
|
+
// The components a run reads: every one of <racine>; in an envelope, those its plan names, the
|
|
534
|
+
// others never written; every one when the plan names none of them (a folder of the root, `.`).
|
|
527
535
|
export function aVerifier(racine, env = process.env) {
|
|
528
536
|
const tous = composants(racine);
|
|
529
|
-
const
|
|
530
|
-
const
|
|
531
|
-
return
|
|
537
|
+
const plan = (paquetsDeLEnveloppe(env) ?? []).map(p => path.resolve(racine, p));
|
|
538
|
+
const siens = tous.filter(c => plan.includes(path.resolve(c.dir)));
|
|
539
|
+
return siens.length ? siens : tous;
|
|
532
540
|
}
|
|
533
541
|
|
|
534
542
|
if (import.meta.url === pathToFileURL(process.argv[1] ?? '').href) {
|
|
@@ -2,22 +2,24 @@
|
|
|
2
2
|
// (and `/mesure`), in place of the workspace package `@grillhouse/vitest-config` that the frame's
|
|
3
3
|
// copied files held.
|
|
4
4
|
//
|
|
5
|
-
// - Each source file of the project (
|
|
6
|
-
// .git, dist, coverage, .turbo, .claude, .beads, .codegraph and .rtfm left out) that names
|
|
5
|
+
// - Each source file of the project (scripts/sources.mjs) that names
|
|
7
6
|
// `@grillhouse/vitest-config` or `@grillhouse/vitest-config/mesure` in quotes names the package's
|
|
8
7
|
// instead; a root configuration that imports the base by its former path
|
|
9
8
|
// (`./scripts/vitest-config/base.mjs`, `./packages/grillhouse/scripts/vitest-config/base.mjs`)
|
|
10
|
-
// imports it by its name.
|
|
9
|
+
// imports it by its name. `formesAnterieures` gives back what a text so rewritten held before,
|
|
10
|
+
// by which the migration of the copies (0.23.2-copies-du-cadre.mjs) still knows a former copy of
|
|
11
|
+
// the frame by its fingerprint.
|
|
11
12
|
// - Each package.json of the project (the root's and each workspace's) that declares
|
|
12
13
|
// `@grillhouse/vitest-config` declares `@roomi-fields/grillhouse` in the same field in its place,
|
|
13
14
|
// at the range the root declares (else `^<version>` of the package), unless it already declares
|
|
14
15
|
// it; the root's workspaces lose the former directory of the package (`scripts/vitest-config`,
|
|
15
16
|
// `packages/grillhouse/scripts/vitest-config`).
|
|
16
17
|
// - A project already in the new form is not written.
|
|
17
|
-
import { existsSync,
|
|
18
|
+
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
18
19
|
import path from 'node:path';
|
|
19
20
|
import { VERSION } from '../cadre.mjs';
|
|
20
21
|
import { paquets } from '../paquets.mjs';
|
|
22
|
+
import { sources } from '../sources.mjs';
|
|
21
23
|
|
|
22
24
|
export const version = '0.23.0';
|
|
23
25
|
export const nom = 'configuration de base de Vitest';
|
|
@@ -27,33 +29,34 @@ const PAQUET = '@roomi-fields/grillhouse';
|
|
|
27
29
|
const NOUVEAU = `${PAQUET}/vitest-config`;
|
|
28
30
|
const ANCIENS_ESPACES = ['scripts/vitest-config', 'packages/grillhouse/scripts/vitest-config'];
|
|
29
31
|
const CHAMPS = ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'];
|
|
30
|
-
const EXTENSIONS = /\.(?:[mc]?ts|[mc]?js)$/;
|
|
31
|
-
const HORS = new Set([
|
|
32
|
-
'node_modules',
|
|
33
|
-
'.git',
|
|
34
|
-
'dist',
|
|
35
|
-
'coverage',
|
|
36
|
-
'.turbo',
|
|
37
|
-
'.claude',
|
|
38
|
-
'.beads',
|
|
39
|
-
'.codegraph',
|
|
40
|
-
'.rtfm',
|
|
41
|
-
]);
|
|
42
32
|
// A quoted name of the former package, or a former path of the base at the root.
|
|
43
33
|
const NOMME =
|
|
44
34
|
/(['"])(?:@grillhouse\/vitest-config(\/mesure)?|\.\/(?:packages\/grillhouse\/)?scripts\/vitest-config\/base\.mjs)\1/g;
|
|
45
35
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
}
|
|
36
|
+
// A quoted name of the package's base, as this migration writes it.
|
|
37
|
+
const ECRIT = /(['"])@roomi-fields\/grillhouse\/vitest-config(\/mesure)?\1/g;
|
|
38
|
+
const ANCIENS_CHEMINS = [
|
|
39
|
+
'./scripts/vitest-config/base.mjs',
|
|
40
|
+
'./packages/grillhouse/scripts/vitest-config/base.mjs',
|
|
41
|
+
];
|
|
53
42
|
|
|
54
43
|
const lireJson = f => JSON.parse(readFileSync(f, 'utf8'));
|
|
55
44
|
const ecrireJson = (f, v) => writeFileSync(f, `${JSON.stringify(v, null, 2)}\n`);
|
|
56
45
|
|
|
46
|
+
/**
|
|
47
|
+
* The texts <texte> may have held before this migration rewrote it: each name it wrote back to the
|
|
48
|
+
* former package's, or each name of the base back to one former path; none when it wrote nothing.
|
|
49
|
+
*/
|
|
50
|
+
export function formesAnterieures(texte) {
|
|
51
|
+
if (texte.search(ECRIT) < 0) return [];
|
|
52
|
+
return [
|
|
53
|
+
texte.replace(ECRIT, (_, q, mesure) => `${q}${ANCIEN}${mesure ?? ''}${q}`),
|
|
54
|
+
...ANCIENS_CHEMINS.map(c =>
|
|
55
|
+
texte.replace(ECRIT, (tout, q, mesure) => (mesure ? tout : `${q}${c}${q}`))
|
|
56
|
+
),
|
|
57
|
+
];
|
|
58
|
+
}
|
|
59
|
+
|
|
57
60
|
/** Brings the project to the package's base configuration of Vitest; returns what it did. */
|
|
58
61
|
export function migrer(projet) {
|
|
59
62
|
const lignes = [];
|