@roomi-fields/grillhouse 0.23.0 → 0.24.0

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.
Files changed (65) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/METACADRE.md +1 -1
  3. package/agents/explorateur.md +4 -2
  4. package/agents/questionneur.md +1 -1
  5. package/bin/grillhouse.mjs +3 -58
  6. package/cadre/templates/projet/CLAUDE.md +5 -1
  7. package/cadre/templates/projet/docs/agents/issue-tracker.md +4 -4
  8. package/charte.md +23 -6
  9. package/docs/ARCHITECTURE.md +127 -1
  10. package/hooks/register.tsx +3 -13
  11. package/package.json +13 -1
  12. package/scripts/bilan.mjs +134 -88
  13. package/scripts/circuit.mjs +1547 -2248
  14. package/scripts/composants-affectes.mjs +27 -108
  15. package/scripts/consommateurs-arbitres.mjs +15 -21
  16. package/scripts/consommateurs.d.ts +8 -0
  17. package/scripts/consommateurs.mjs +5 -1
  18. package/scripts/dette.d.ts +23 -0
  19. package/scripts/dette.mjs +76 -13
  20. package/scripts/droits.mjs +38 -44
  21. package/scripts/elements-du-lot.mjs +246 -0
  22. package/scripts/enveloppe/enveloppe.mjs +105 -232
  23. package/scripts/enveloppe/lancer.sh +79 -49
  24. package/scripts/enveloppe/paquets-du-plan.mjs +49 -0
  25. package/scripts/etapes.mjs +148 -213
  26. package/scripts/gardes-du-cadre.mjs +8 -6
  27. package/scripts/grillhouse-maj.mjs +31 -9
  28. package/scripts/index-interfaces.mjs +21 -1
  29. package/scripts/integration/integrer.mjs +2 -2
  30. package/scripts/interfaces-contre-code.mjs +25 -17
  31. package/scripts/migrations/0.23.0-config-vitest.mjs +26 -23
  32. package/scripts/migrations/0.23.2-copies-du-cadre.mjs +201 -0
  33. package/scripts/migrations/0.24.0-circuit-simplifie.mjs +231 -0
  34. package/scripts/migrations.mjs +41 -6
  35. package/scripts/paquets.d.ts +5 -0
  36. package/scripts/paquets.mjs +3 -0
  37. package/scripts/references-par-les-types.mjs +55 -36
  38. package/scripts/registre.mjs +7 -15
  39. package/scripts/resultats.mjs +283 -142
  40. package/scripts/resumes.mjs +1 -1
  41. package/scripts/session-start.sh +1 -2
  42. package/scripts/sortie.mjs +1 -1
  43. package/scripts/sources.mjs +28 -0
  44. package/scripts/sous-commandes.mjs +62 -0
  45. package/scripts/tableau.mjs +85 -191
  46. package/scripts/tests.mjs +19 -17
  47. package/scripts/verifier.mjs +5 -4
  48. package/scripts/verrou-de-machine.mjs +131 -24
  49. package/scripts/verrous/verrou.mjs +66 -5
  50. package/skills/developpeur/SKILL.md +60 -50
  51. package/skills/explorateur/SKILL.md +90 -64
  52. package/skills/grill/SKILL.md +1 -1
  53. package/skills/mesure/SKILL.md +2 -1
  54. package/skills/pitmaster/SKILL.md +132 -118
  55. package/skills/pitmaster/references/consigne-agent.md +54 -148
  56. package/skills/questionneur/SKILL.md +18 -18
  57. package/skills/relecteur/SKILL.md +69 -23
  58. package/skills/testwriter/SKILL.md +46 -35
  59. package/types/index.d.ts +1 -3
  60. package/agents/referent-technique.md +0 -9
  61. package/agents/regulateur.md +0 -11
  62. package/scripts/enveloppe/composant.mjs +0 -11
  63. package/scripts/etat-du-circuit.mjs +0 -104
  64. package/skills/referent-technique/SKILL.md +0 -145
  65. package/skills/regulateur/SKILL.md +0 -220
@@ -4,21 +4,37 @@
4
4
  //
5
5
  // - A migration exports `version` (the version of the package that brings the change of form),
6
6
  // `nom` and `migrer(projet)`, which brings the project at <projet> to the new form and returns
7
- // the lines of what it changed: none when the project already has it. It is replayable without
8
- // effect: a second pass changes no byte and returns no line.
7
+ // the lines of what it changed: none when the project already has it. A line `{ aFaire }` is
8
+ // what it leaves to the project (a copy of the frame the project modified), which the update
9
+ // writes on its error stream, its exit code non-zero, as `@turbo/codemod` fails on a file it
10
+ // could not transform. It is replayable without effect: a second pass changes no byte and
11
+ // returns no line.
9
12
  // - MIGRATIONS lists them, each imported by its module; the update plays those newer than the
10
13
  // version the project recorded (`grillhouse.version` of its package.json), in the order of their
11
14
  // versions; a project that recorded none plays them all. The package carries no migration newer
12
15
  // than itself once released, so the range ends with the package.
16
+ // - A migration may also export `restes(projet)`: the lines of what stays to the project once the
17
+ // update is done, which the update plays after its own update and its regeneration, for each
18
+ // migration it played, and reports (« reste au projet ») without holding back the version, as a
19
+ // codemod reports what it leaves without failing (restesAuProjet).
13
20
  // - Each migration has its test, tests/unit/migration.<nom>.spec.ts.
14
21
  import semver from 'semver';
15
22
  import * as charteImportee from './migrations/0.23.0-charte-importee.mjs';
16
23
  import * as configVitest from './migrations/0.23.0-config-vitest.mjs';
17
24
  import * as crochetsDeSeance from './migrations/0.23.0-crochets-de-seance.mjs';
18
25
  import * as marcheDuProjet from './migrations/0.23.0-marche-du-projet.mjs';
26
+ import * as copiesDuCadre from './migrations/0.23.2-copies-du-cadre.mjs';
27
+ import * as circuitSimplifie from './migrations/0.24.0-circuit-simplifie.mjs';
19
28
 
20
29
  /** The migrations of the package. */
21
- export const MIGRATIONS = [crochetsDeSeance, configVitest, marcheDuProjet, charteImportee];
30
+ export const MIGRATIONS = [
31
+ crochetsDeSeance,
32
+ configVitest,
33
+ marcheDuProjet,
34
+ charteImportee,
35
+ copiesDuCadre,
36
+ circuitSimplifie,
37
+ ];
22
38
 
23
39
  /**
24
40
  * The migrations of <liste> newer than <depuis> (all of them when it is null), in the order of
@@ -32,12 +48,31 @@ export function migrationsAJouer(depuis, liste = MIGRATIONS) {
32
48
  .map(({ m }) => m);
33
49
  }
34
50
 
51
+ /**
52
+ * What stays to the project at <projet> after the update, for each migration newer than <depuis>
53
+ * that exports `restes` and names something: `{ version, nom, lignes }`.
54
+ */
55
+ export function restesAuProjet(projet, depuis, liste = MIGRATIONS) {
56
+ return migrationsAJouer(depuis, liste)
57
+ .filter(m => typeof m.restes === 'function')
58
+ .map(m => ({ version: m.version, nom: m.nom, lignes: m.restes(projet) }))
59
+ .filter(r => r.lignes.length > 0);
60
+ }
61
+
35
62
  /**
36
63
  * Plays on the project at <projet> each migration newer than <depuis>; returns, for each one that
37
- * changed something, `{ version, nom, lignes }`.
64
+ * changed something or left something to do, `{ version, nom, lignes, aFaire }`.
38
65
  */
39
66
  export function migrer(projet, depuis, liste = MIGRATIONS) {
40
67
  return migrationsAJouer(depuis, liste)
41
- .map(m => ({ version: m.version, nom: m.nom, lignes: m.migrer(projet) }))
42
- .filter(r => r.lignes.length > 0);
68
+ .map(m => {
69
+ const tout = m.migrer(projet);
70
+ return {
71
+ version: m.version,
72
+ nom: m.nom,
73
+ lignes: tout.filter(l => typeof l === 'string'),
74
+ aFaire: tout.filter(l => typeof l !== 'string').map(l => l.aFaire),
75
+ };
76
+ })
77
+ .filter(r => r.lignes.length > 0 || r.aFaire.length > 0);
43
78
  }
@@ -0,0 +1,5 @@
1
+ // The types of ./paquets.mjs as the entry `@roomi-fields/grillhouse/paquets` publishes it, for a
2
+ // project's guard that leaves out the packages out of the frame.
3
+
4
+ /** The names listed in `racine`'s `docs/agents/hors-cadre.txt`: empty without the file. */
5
+ export function horsCadre(racine: string): Set<string>;
@@ -12,6 +12,9 @@
12
12
  //
13
13
  // This module and the ones it imports use Node alone: the update runs them from a source checkout
14
14
  // of the frame that installs no dependency.
15
+ //
16
+ // A project's guard imports `horsCadre` by the package's entry `@roomi-fields/grillhouse/paquets`,
17
+ // its types in ./paquets.d.ts (docs/ARCHITECTURE.md, the package's named entries).
15
18
  import { existsSync, globSync, readFileSync } from 'node:fs';
16
19
  import path from 'node:path';
17
20
 
@@ -3,7 +3,8 @@
3
3
  // repository's code (a declaration of a package, a member of a type, a function internal to a
4
4
  // package), and its references are those the language service resolves to that symbol, never a
5
5
  // text that happens to bear its name. scripts/composants-affectes.mjs runs it beside its survey
6
- // by the names.
6
+ // by the names; scripts/elements-du-lot.mjs reads the declarations and the exports of a lot
7
+ // through the same service (`leService`).
7
8
  //
8
9
  // - The code read is the files of each component's `tsconfig.json` (its `include`), in one
9
10
  // language service, so that a reference crosses packages. A workspace package's import resolves
@@ -100,14 +101,15 @@ function entreeDe(c, sous = '.') {
100
101
  );
101
102
  }
102
103
 
103
- const estTest = (c, f) =>
104
+ // Whether the file <f> (absolute) of the component <c> is a test: a test's name, or a test folder.
105
+ export const estTest = (c, f) =>
104
106
  NOM_DE_TEST.test(path.basename(f)) ||
105
107
  path
106
108
  .relative(c.dir, f)
107
109
  .split(path.sep)
108
110
  .some(d => DOSSIERS_DE_TEST.has(d));
109
111
 
110
- // The language service over the components <tous> of <racine>: { ts, ls, programme, composantDe }
112
+ // The language service over the components <tous> of <racine>: { ls, programme, composantDe }
111
113
  // or { raison } when it cannot run.
112
114
  function service(ts, racine, tous) {
113
115
  const hote = { ...ts.sys, onUnRecoverableConfigFileDiagnostic: () => {} };
@@ -209,6 +211,51 @@ function service(ts, racine, tous) {
209
211
  return { ls, programme, composantDe };
210
212
  }
211
213
 
214
+ // The language service over the components <tous> of <racine>, and what it says of their
215
+ // declarations: `{ ts, ls, programme, checker, composantDe, sources, entree, publie }`, `sources`
216
+ // the production sources it reads (each `{ sf, c }`, the tests and the declaration files left
217
+ // out), `entree(c)` the source of the entry of the component <c> (or null), `publie(c, noeud)`
218
+ // whether that entry exports the symbol whose name is the node <noeud>; or `{ raison }` when it
219
+ // cannot run. scripts/elements-du-lot.mjs reads it.
220
+ export function leService(racine, tous) {
221
+ const ts = requis('typescript');
222
+ const s = service(ts, racine, tous);
223
+ if (s.raison) {
224
+ return s;
225
+ }
226
+ const { programme, composantDe } = s;
227
+ const checker = programme.getTypeChecker();
228
+ const sources = programme.getSourceFiles().flatMap(sf => {
229
+ const c = composantDe(sf.fileName);
230
+ return !c || estTest(c, sf.fileName) || DECLARATION.test(sf.fileName) ? [] : [{ sf, c }];
231
+ });
232
+ const exportes = new Map();
233
+ const reel = sym => {
234
+ let x = sym;
235
+ if (x && x.flags & ts.SymbolFlags.Alias) {
236
+ x = checker.getAliasedSymbol(x);
237
+ }
238
+ return x ? checker.getExportSymbolOfSymbol(x) : x;
239
+ };
240
+ const exportsDe = c => {
241
+ if (!exportes.has(c)) {
242
+ const f = entreeDe(c);
243
+ const sf = f ? programme.getSourceFile(f) : undefined;
244
+ const mod = sf ? checker.getSymbolAtLocation(sf) : undefined;
245
+ exportes.set(
246
+ c,
247
+ mod ? checker.getExportsOfModule(mod).map(x => ({ nom: x.name, sym: reel(x) })) : []
248
+ );
249
+ }
250
+ return exportes.get(c);
251
+ };
252
+ const publie = (c, noeud) => {
253
+ const sym = reel(checker.getSymbolAtLocation(noeud));
254
+ return Boolean(sym) && exportsDe(c).some(x => x.sym === sym);
255
+ };
256
+ return { ts, ...s, checker, sources, entree: c => entreeDe(c), publie };
257
+ }
258
+
212
259
  // The survey by the types of the elements <ecrits> (`elementsEcrits`) in the components <tous> of
213
260
  // <racine>, an element that resolves to several declarations kept to those of the files and the
214
261
  // components the ticket names (<contexte>: `{ fichiers, composants }`, Sets of file names and of
@@ -224,13 +271,11 @@ export function parLesTypes(racine, tous, ecrits, contexte = {}) {
224
271
  }
225
272
 
226
273
  function releveParLesTypes(racine, tous, ecrits, { fichiers = new Set(), composants = new Set() }) {
227
- const ts = requis('typescript');
228
- const s = service(ts, racine, tous);
274
+ const s = leService(racine, tous);
229
275
  if (s.raison) {
230
276
  return { etat: 'impossible', raison: s.raison, elements: [] };
231
277
  }
232
- const { ls, programme, composantDe } = s;
233
- const checker = programme.getTypeChecker();
278
+ const { ts, ls, programme, composantDe } = s;
234
279
 
235
280
  // The declarations of the components' sources, at their top and as members of their types.
236
281
  const hauts = [];
@@ -244,11 +289,7 @@ function releveParLesTypes(racine, tous, ecrits, { fichiers = new Set(), composa
244
289
  }
245
290
  }
246
291
  };
247
- for (const sf of programme.getSourceFiles()) {
248
- const c = composantDe(sf.fileName);
249
- if (!c || estTest(c, sf.fileName) || DECLARATION.test(sf.fileName)) {
250
- continue;
251
- }
292
+ for (const { sf, c } of s.sources) {
252
293
  for (const st of sf.statements) {
253
294
  const decls = ts.isVariableStatement(st)
254
295
  ? st.declarationList.declarations.filter(d => ts.isIdentifier(d.name))
@@ -270,32 +311,10 @@ function releveParLesTypes(racine, tous, ecrits, { fichiers = new Set(), composa
270
311
  }
271
312
  }
272
313
 
273
- // The symbols each component's entry exports.
274
- const exportes = new Map();
275
- const reel = sym => {
276
- let x = sym;
277
- if (x && x.flags & ts.SymbolFlags.Alias) {
278
- x = checker.getAliasedSymbol(x);
279
- }
280
- return x ? checker.getExportSymbolOfSymbol(x) : x;
281
- };
282
- const exportsDe = c => {
283
- if (!exportes.has(c)) {
284
- const f = entreeDe(c);
285
- const sf = f ? programme.getSourceFile(f) : undefined;
286
- const mod = sf ? checker.getSymbolAtLocation(sf) : undefined;
287
- exportes.set(
288
- c,
289
- mod ? checker.getExportsOfModule(mod).map(x => ({ nom: x.name, sym: reel(x) })) : []
290
- );
291
- }
292
- return exportes.get(c);
293
- };
294
- const symDe = d => reel(checker.getSymbolAtLocation(d.noeud));
314
+ // Whether the entry of its component exports a declaration (a member, when its type is).
295
315
  const publie = d => {
296
316
  const h = d.haut ?? d;
297
- const sym = symDe(h);
298
- return Boolean(sym) && exportsDe(h.c).some(x => x.sym === sym);
317
+ return s.publie(h.c, h.noeud);
299
318
  };
300
319
 
301
320
  // The references of the declaration <d>: [{ c, appel }], its own declarations left out.
@@ -4,11 +4,11 @@
4
4
  // role agent launched in a shell included). An agent resumed by a message has one line per stop; the board
5
5
  // reads an agent's latest line, and the transcripts of running ones. The circuit of a ticket
6
6
  // (scripts/circuit.mjs) writes a line at the end of each step it leads itself, with no agent
7
- // (`ligneDEtape`: its role `circuit`, its step and component, one turn, no tokens).
7
+ // (`ligneDEtape`: its role `circuit`, its step, one turn, no tokens).
8
8
  //
9
9
  // - The line: the project (the main tree of the directory the session opened in, which the hook
10
- // reads in CLAUDE_PROJECT_DIR, else in its input's `cwd`), the agent, its ticket (« TON TICKET : »; a sub-agent
11
- // whose prompt names none takes that of the regulator that launched it), its role,
10
+ // reads in CLAUDE_PROJECT_DIR, else in its input's `cwd`), the agent, its ticket (« TON TICKET : »),
11
+ // its role,
12
12
  // its start and end, its working time and the turns it sums (start and end in milliseconds, the
13
13
  // waits for a message left out), its tokens, its cache reads and its cost when the session wrote
14
14
  // one. All of it is read from the agent's transcript; the agent declares nothing.
@@ -36,14 +36,7 @@ import { appendFileSync, existsSync, mkdirSync, readdirSync, readFileSync } from
36
36
  import os from 'node:os';
37
37
  import path from 'node:path';
38
38
  import { pathToFileURL } from 'node:url';
39
- import {
40
- lireFichier,
41
- ROLE_DU_CIRCUIT,
42
- roleDeLAgent,
43
- roleDuMeta,
44
- ticketDuRegulateur,
45
- tourne,
46
- } from './tableau.mjs';
39
+ import { lireFichier, ROLE_DU_CIRCUIT, roleDeLAgent, roleDuMeta, tourne } from './tableau.mjs';
47
40
  import { lacherVerrou, prendreVerrou } from './verrou-de-fichier.mjs';
48
41
 
49
42
  const REGISTRE =
@@ -87,14 +80,14 @@ export function source(input) {
87
80
  // The register's line for this hook input and the reading `t` of its transcript (`lireFichier` or
88
81
  // `lireTranscription`), or null. `projet` is the main tree of the session.
89
82
  export function ligne(input, t, projet) {
90
- const { transcription, role, agent } = source(input);
83
+ const { role, agent } = source(input);
91
84
  if (t.premier === null) {
92
85
  return null;
93
86
  }
94
87
  return {
95
88
  projet,
96
89
  agent,
97
- ticket: t.ticket ?? (transcription ? ticketDuRegulateur(transcription) : null),
90
+ ticket: t.ticket ?? null,
98
91
  role: role ?? t.role,
99
92
  debut: new Date(t.premier).toISOString(),
100
93
  fin: new Date(t.dernier).toISOString(),
@@ -108,7 +101,7 @@ export function ligne(input, t, projet) {
108
101
 
109
102
  // The register's line of a step the circuit of <ticket> leads itself (scripts/circuit.mjs), from
110
103
  // <debut> to <fin> (ISO dates): one agent per step, its role `circuit`, one turn, no tokens.
111
- export function ligneDEtape({ projet, ticket, etape, composant, debut, fin }) {
104
+ export function ligneDEtape({ projet, ticket, etape, debut, fin }) {
112
105
  const [d, f] = [Date.parse(debut), Date.parse(fin)];
113
106
  return {
114
107
  projet,
@@ -116,7 +109,6 @@ export function ligneDEtape({ projet, ticket, etape, composant, debut, fin }) {
116
109
  ticket,
117
110
  role: ROLE_DU_CIRCUIT,
118
111
  etape,
119
- composant,
120
112
  debut,
121
113
  fin,
122
114
  travail: f - d,