@roomi-fields/grillhouse 0.0.0-stage → 0.23.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 (166) hide show
  1. package/.claude-plugin/plugin.json +9 -0
  2. package/METACADRE.md +41 -0
  3. package/agents/developpeur.md +10 -0
  4. package/agents/explorateur.md +9 -0
  5. package/agents/questionneur.md +11 -0
  6. package/agents/referent-technique.md +9 -0
  7. package/agents/regulateur.md +11 -0
  8. package/agents/relecteur.md +9 -0
  9. package/agents/testwriter.md +10 -0
  10. package/bin/grillhouse.mjs +125 -0
  11. package/cadre/templates/projet/.claude/settings.json +30 -0
  12. package/cadre/templates/projet/.editorconfig +47 -0
  13. package/cadre/templates/projet/.env.example +57 -0
  14. package/cadre/templates/projet/.eslintrc.cjs +56 -0
  15. package/cadre/templates/projet/.github/workflows/ci.yml +66 -0
  16. package/cadre/templates/projet/.mcp.json +13 -0
  17. package/cadre/templates/projet/.prettierrc +11 -0
  18. package/cadre/templates/projet/CHANGELOG.md +61 -0
  19. package/cadre/templates/projet/CLAUDE.md +46 -0
  20. package/cadre/templates/projet/CONTRIBUTING.md +243 -0
  21. package/cadre/templates/projet/CREDITS.md +41 -0
  22. package/cadre/templates/projet/README.md +152 -0
  23. package/cadre/templates/projet/_gitignore +91 -0
  24. package/cadre/templates/projet/_npmignore +46 -0
  25. package/cadre/templates/projet/deployment/README.md +98 -0
  26. package/cadre/templates/projet/deployment/docs/01-INSTALL.md +145 -0
  27. package/cadre/templates/projet/deployment/docs/02-CONFIGURATION.md +117 -0
  28. package/cadre/templates/projet/deployment/docs/03-API.md +264 -0
  29. package/cadre/templates/projet/deployment/docs/04-TROUBLESHOOTING.md +262 -0
  30. package/cadre/templates/projet/deployment/scripts/install.ps1 +100 -0
  31. package/cadre/templates/projet/deployment/scripts/start.ps1 +61 -0
  32. package/cadre/templates/projet/deployment/scripts/stop.ps1 +37 -0
  33. package/cadre/templates/projet/deployment/scripts/test.ps1 +118 -0
  34. package/cadre/templates/projet/docs/agents/issue-tracker.md +44 -0
  35. package/cadre/templates/projet/ecosystem.config.cjs +73 -0
  36. package/cadre/templates/projet/package.json +90 -0
  37. package/cadre/templates/projet/pitmaster/SUIVI.md +22 -0
  38. package/cadre/templates/projet/src/config.ts +68 -0
  39. package/cadre/templates/projet/src/errors.ts +102 -0
  40. package/cadre/templates/projet/src/index.ts +46 -0
  41. package/cadre/templates/projet/src/services/.gitkeep +8 -0
  42. package/cadre/templates/projet/src/types/index.ts +24 -0
  43. package/cadre/templates/projet/src/utils/logger.ts +106 -0
  44. package/cadre/templates/projet/tests/integration/.gitkeep +7 -0
  45. package/cadre/templates/projet/tests/unit/config.spec.ts +68 -0
  46. package/cadre/templates/projet/tests/unit/errors.spec.ts +132 -0
  47. package/cadre/templates/projet/tests/unit/types.spec.ts +73 -0
  48. package/cadre/templates/projet/tsconfig.eslint.json +9 -0
  49. package/cadre/templates/projet/tsconfig.json +41 -0
  50. package/cadre/templates/projet/tsdoc.json +6 -0
  51. package/cadre/templates/projet/vitest.config.ts +44 -0
  52. package/cadre/templates/turbo/paquets.json +29 -0
  53. package/cadre/templates/turbo/sans-paquets.json +28 -0
  54. package/charte.md +107 -0
  55. package/docs/ARCHITECTURE.md +90 -0
  56. package/hooks/crochet.mjs +33 -0
  57. package/hooks/hooks.json +58 -0
  58. package/hooks/register.tsx +558 -0
  59. package/package.json +75 -4
  60. package/scripts/avancement.mjs +244 -0
  61. package/scripts/bilan.mjs +523 -0
  62. package/scripts/branche-de-nuit.mjs +59 -0
  63. package/scripts/cadre.mjs +109 -0
  64. package/scripts/circuit.mjs +4375 -0
  65. package/scripts/code-mort.mjs +371 -0
  66. package/scripts/composants-affectes.mjs +598 -0
  67. package/scripts/consommateurs-arbitres.mjs +192 -0
  68. package/scripts/consommateurs.mjs +310 -0
  69. package/scripts/crochet.mjs +24 -0
  70. package/scripts/crochets.mjs +135 -0
  71. package/scripts/dernier-vert.mjs +208 -0
  72. package/scripts/dette.mjs +181 -0
  73. package/scripts/droits.mjs +354 -0
  74. package/scripts/enveloppe/codes.mjs +17 -0
  75. package/scripts/enveloppe/composant.mjs +11 -0
  76. package/scripts/enveloppe/enveloppe.mjs +628 -0
  77. package/scripts/enveloppe/lancer.sh +311 -0
  78. package/scripts/etapes.mjs +323 -0
  79. package/scripts/etat-du-circuit.mjs +104 -0
  80. package/scripts/frontieres.mjs +456 -0
  81. package/scripts/gardes-du-cadre.mjs +72 -0
  82. package/scripts/greffons.mjs +338 -0
  83. package/scripts/grillhouse-maj.mjs +514 -0
  84. package/scripts/index-interfaces.mjs +293 -0
  85. package/scripts/init.mjs +117 -0
  86. package/scripts/integration/file-attente.mjs +61 -0
  87. package/scripts/integration/file.mjs +494 -0
  88. package/scripts/integration/integrer.mjs +381 -0
  89. package/scripts/integration/rejeu.mjs +139 -0
  90. package/scripts/integration/verdict.mjs +13 -0
  91. package/scripts/interfaces-contre-code.mjs +547 -0
  92. package/scripts/ligne-etat/defaut.sh +110 -0
  93. package/scripts/ligne-etat/ligne-etat.mjs +93 -0
  94. package/scripts/migrations/0.23.0-charte-importee.mjs +47 -0
  95. package/scripts/migrations/0.23.0-config-vitest.mjs +105 -0
  96. package/scripts/migrations/0.23.0-crochets-de-seance.mjs +55 -0
  97. package/scripts/migrations/0.23.0-marche-du-projet.mjs +82 -0
  98. package/scripts/migrations.mjs +43 -0
  99. package/scripts/nuit.sh +269 -0
  100. package/scripts/paquets.mjs +79 -0
  101. package/scripts/poussee-cles.mjs +46 -0
  102. package/scripts/preparation.mjs +84 -0
  103. package/scripts/references-par-les-types.mjs +420 -0
  104. package/scripts/registre.mjs +336 -0
  105. package/scripts/resultats.mjs +580 -0
  106. package/scripts/resumes.mjs +57 -0
  107. package/scripts/retirer-copie.sh +127 -0
  108. package/scripts/session-start.sh +203 -0
  109. package/scripts/sortie.mjs +155 -0
  110. package/scripts/sous-modules.sh +316 -0
  111. package/scripts/structure-guard.sh +27 -0
  112. package/scripts/superviseur.mjs +102 -0
  113. package/scripts/tableau.mjs +1886 -0
  114. package/scripts/tests.mjs +236 -0
  115. package/scripts/ticket.sh +23 -0
  116. package/scripts/turbo-des-paquets.mjs +899 -0
  117. package/scripts/un-commit-par-ticket.mjs +212 -0
  118. package/scripts/verifier.mjs +469 -0
  119. package/scripts/verrou-de-fichier.mjs +130 -0
  120. package/scripts/verrou-de-machine.mjs +211 -0
  121. package/scripts/verrous/commande.mjs +180 -0
  122. package/scripts/verrous/ticket-du-sous-agent.mjs +39 -0
  123. package/scripts/verrous/verrou.mjs +165 -0
  124. package/scripts/vitest-config/avancement.mjs +39 -0
  125. package/scripts/vitest-config/avancement.reporter.mjs +56 -0
  126. package/scripts/vitest-config/base-de-passe.mjs +128 -0
  127. package/scripts/vitest-config/base.d.ts +6 -0
  128. package/scripts/vitest-config/base.mjs +87 -0
  129. package/scripts/vitest-config/changements.mjs +173 -0
  130. package/scripts/vitest-config/cibles.mjs +207 -0
  131. package/scripts/vitest-config/duree.reporter.mjs +98 -0
  132. package/scripts/vitest-config/machine.setup.mjs +14 -0
  133. package/scripts/vitest-config/mesure.d.ts +6 -0
  134. package/scripts/vitest-config/mesure.mjs +13 -0
  135. package/scripts/vitest-config/mesure.setup.mjs +12 -0
  136. package/scripts/vitest-config/pression.mjs +90 -0
  137. package/scripts/vitest-config/resultats.mjs +23 -0
  138. package/scripts/vitest-config/resultats.setup.mjs +19 -0
  139. package/scripts/vitest.nuit.config.mjs +26 -0
  140. package/skills/developpeur/SKILL.md +175 -0
  141. package/skills/explorateur/SKILL.md +84 -0
  142. package/skills/grill/SKILL.md +238 -0
  143. package/skills/grill/references/releve-structurel.md +38 -0
  144. package/skills/mesure/SKILL.md +168 -0
  145. package/skills/pitmaster/SKILL.md +382 -0
  146. package/skills/pitmaster/references/cadre.md +119 -0
  147. package/skills/pitmaster/references/consigne-agent.md +308 -0
  148. package/skills/pitmaster/references/erreurs.md +25 -0
  149. package/skills/pitmaster/references/tour.md +124 -0
  150. package/skills/questionneur/SKILL.md +64 -0
  151. package/skills/redacteur/SKILL.md +84 -0
  152. package/skills/redacteur/references/documents-d-un-composant.md +105 -0
  153. package/skills/referent-technique/SKILL.md +145 -0
  154. package/skills/regulateur/SKILL.md +220 -0
  155. package/skills/release/SKILL.md +134 -0
  156. package/skills/release/scripts/update-version.cjs +92 -0
  157. package/skills/relecteur/SKILL.md +152 -0
  158. package/skills/relecteur/references/LICENSE-MIT +30 -0
  159. package/skills/relecteur/references/SOURCE.md +8 -0
  160. package/skills/relecteur/references/claims-check.md +14 -0
  161. package/skills/relecteur/references/deletion-check.md +14 -0
  162. package/skills/relecteur/references/edge-case-hunter.md +80 -0
  163. package/skills/relecteur/references/verification-gap.md +113 -0
  164. package/skills/testwriter/SKILL.md +187 -0
  165. package/types/index.d.ts +56 -0
  166. package/README.md +0 -3
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Types module tests
3
+ */
4
+
5
+ import { describe, it, expect } from 'vitest';
6
+ import { success, failure, type Result } from '../../src/types/index.js';
7
+
8
+ describe('Types', () => {
9
+ describe('Result type', () => {
10
+ describe('success', () => {
11
+ it('should create a success result', () => {
12
+ const result = success(42);
13
+ expect(result.success).toBe(true);
14
+ if (result.success) {
15
+ expect(result.data).toBe(42);
16
+ }
17
+ });
18
+
19
+ it('should work with objects', () => {
20
+ const data = { id: 1, name: 'Test' };
21
+ const result = success(data);
22
+ expect(result.success).toBe(true);
23
+ if (result.success) {
24
+ expect(result.data).toEqual(data);
25
+ }
26
+ });
27
+
28
+ it('should work with arrays', () => {
29
+ const data = [1, 2, 3];
30
+ const result = success(data);
31
+ expect(result.success).toBe(true);
32
+ if (result.success) {
33
+ expect(result.data).toEqual(data);
34
+ }
35
+ });
36
+ });
37
+
38
+ describe('failure', () => {
39
+ it('should create a failure result', () => {
40
+ const error = new Error('Something went wrong');
41
+ const result = failure(error);
42
+ expect(result.success).toBe(false);
43
+ if (!result.success) {
44
+ expect(result.error).toBe(error);
45
+ }
46
+ });
47
+
48
+ it('should work with custom error types', () => {
49
+ const customError = { code: 'CUSTOM', message: 'Custom error' };
50
+ const result = failure(customError);
51
+ expect(result.success).toBe(false);
52
+ if (!result.success) {
53
+ expect(result.error).toEqual(customError);
54
+ }
55
+ });
56
+ });
57
+
58
+ describe('type narrowing', () => {
59
+ it('should narrow types correctly', () => {
60
+ function processResult(result: Result<number, string>): string {
61
+ if (result.success) {
62
+ return `Value: ${result.data}`;
63
+ } else {
64
+ return `Error: ${result.error}`;
65
+ }
66
+ }
67
+
68
+ expect(processResult(success(42))).toBe('Value: 42');
69
+ expect(processResult(failure('oops'))).toBe('Error: oops');
70
+ });
71
+ });
72
+ });
73
+ });
@@ -0,0 +1,9 @@
1
+ {
2
+ "extends": "./tsconfig.json",
3
+ "compilerOptions": {
4
+ "noEmit": true,
5
+ "rootDir": "."
6
+ },
7
+ "include": ["src/**/*", "tests/**/*", "*.ts"],
8
+ "exclude": ["node_modules", "dist"]
9
+ }
@@ -0,0 +1,41 @@
1
+ {
2
+ "compilerOptions": {
3
+ /* Language and Environment */
4
+ "target": "ES2022",
5
+ "lib": ["ES2022"],
6
+
7
+ /* Modules */
8
+ "module": "Node16",
9
+ "moduleResolution": "Node16",
10
+ "resolveJsonModule": true,
11
+
12
+ /* JavaScript — a JS project, or one migrating to TS, compiles as is */
13
+ "allowJs": true,
14
+ "checkJs": false,
15
+
16
+ /* Emit */
17
+ "outDir": "./dist",
18
+ "rootDir": "./src",
19
+ "declaration": true,
20
+ "declarationMap": true,
21
+ "sourceMap": true,
22
+
23
+ /* Interop Constraints */
24
+ "esModuleInterop": true,
25
+ "forceConsistentCasingInFileNames": true,
26
+ "isolatedModules": true,
27
+
28
+ /* Type Checking */
29
+ "strict": true,
30
+ "noUnusedLocals": true,
31
+ "noUnusedParameters": true,
32
+ "noImplicitReturns": true,
33
+ "noFallthroughCasesInSwitch": true,
34
+ "noUncheckedIndexedAccess": true,
35
+
36
+ /* Completeness */
37
+ "skipLibCheck": true
38
+ },
39
+ "include": ["src/**/*"],
40
+ "exclude": ["node_modules", "dist", "**/*.{test,spec}.{ts,js,mjs}"]
41
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "$schema": "https://developer.microsoft.com/json-schemas/tsdoc/v0/tsdoc.schema.json",
3
+ "extends": ["@microsoft/api-extractor/extends/tsdoc-base.json"],
4
+ "tagDefinitions": [{ "tagName": "@faute", "syntaxKind": "block", "allowMultiple": true }],
5
+ "supportForTags": { "@faute": true }
6
+ }
@@ -0,0 +1,44 @@
1
+ import { defineConfig, mergeConfig } from 'vitest/config';
2
+ import base from '@roomi-fields/grillhouse/vitest-config';
3
+
4
+ // The day's tests of the project: the frame's base configuration (its exclusions of the night
5
+ // tests and the time budget benches, its common environment), by its name, the frame's package's,
6
+ // extended with what is the root's own.
7
+ export default mergeConfig(
8
+ base,
9
+ defineConfig({
10
+ test: {
11
+ // Global test configuration
12
+ globals: true,
13
+
14
+ // Include patterns
15
+ include: ['src/**/*.{test,spec}.{ts,js,mjs}', 'tests/**/*.{test,spec}.{ts,js,mjs}'],
16
+
17
+ // Coverage configuration
18
+ coverage: {
19
+ provider: 'v8',
20
+ reporter: ['text', 'json', 'html'],
21
+ reportsDirectory: './coverage',
22
+ include: ['src/**/*.{ts,js,mjs}'],
23
+ exclude: ['src/**/*.{test,spec}.{ts,js,mjs}', 'src/**/types.ts', 'src/**/index.{ts,js}'],
24
+ thresholds: {
25
+ lines: 80,
26
+ functions: 80,
27
+ branches: 80,
28
+ statements: 80,
29
+ },
30
+ },
31
+
32
+ // Test timeout
33
+ testTimeout: 10000,
34
+
35
+ // Pool options for parallel execution
36
+ pool: 'threads',
37
+ poolOptions: {
38
+ threads: {
39
+ singleThread: false,
40
+ },
41
+ },
42
+ },
43
+ })
44
+ );
@@ -0,0 +1,29 @@
1
+ {
2
+ "$schema": "https://turborepo.com/schema.json",
3
+ "ui": "stream",
4
+ "globalPassThroughEnv": [
5
+ "GRILLHOUSE_RESULTATS",
6
+ "GRILLHOUSE_CHANGEMENTS",
7
+ "GRILLHOUSE_AVANCEMENT",
8
+ "TMPDIR"
9
+ ],
10
+ "tasks": {
11
+ "build": {
12
+ "dependsOn": ["^build"],
13
+ "outputs": ["dist/**"]
14
+ },
15
+ "test:vitest": {
16
+ "dependsOn": ["build", "^build"],
17
+ "env": ["GRILLHOUSE_TESTS"],
18
+ "outputs": []
19
+ },
20
+ "//#grillhouse:gardes": {
21
+ "dependsOn": [],
22
+ "outputs": []
23
+ },
24
+ "//#gardes": {
25
+ "dependsOn": [],
26
+ "outputs": []
27
+ }
28
+ }
29
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "$schema": "https://turborepo.com/schema.json",
3
+ "ui": "stream",
4
+ "globalPassThroughEnv": [
5
+ "GRILLHOUSE_RESULTATS",
6
+ "GRILLHOUSE_CHANGEMENTS",
7
+ "GRILLHOUSE_AVANCEMENT",
8
+ "TMPDIR"
9
+ ],
10
+ "tasks": {
11
+ "build": {
12
+ "outputs": ["dist/**"]
13
+ },
14
+ "grillhouse:gardes": {
15
+ "dependsOn": ["build"],
16
+ "outputs": []
17
+ },
18
+ "gardes": {
19
+ "dependsOn": ["build"],
20
+ "outputs": []
21
+ },
22
+ "test:vitest": {
23
+ "dependsOn": ["build"],
24
+ "env": ["GRILLHOUSE_TESTS"],
25
+ "outputs": []
26
+ }
27
+ }
28
+ }
package/charte.md ADDED
@@ -0,0 +1,107 @@
1
+ # La charte commune de Roomi's Grillhouse
2
+
3
+ Les règles que tout agent applique, identiques dans chaque projet qui installe le cadre. La charte
4
+ du projet (`CLAUDE.md`) l'importe depuis le paquet installé et porte ce qui lui est propre : son
5
+ nom, son responsable, ce qui décide chez lui, ses critères d'arbitrage, ses commandes. Le détail
6
+ d'un rôle vit dans sa compétence, celui d'un outil dans l'architecture du paquet
7
+ (`node_modules/@roomi-fields/grillhouse/docs/ARCHITECTURE.md`). Ce fichier ne se modifie pas
8
+ dans un projet : un écart se propose à Grillhouse. Ainsi les projets suivent un seul cadre, et
9
+ chaque séance ne charge que ce qu'elle applique.
10
+
11
+ ## Ce qui décide
12
+
13
+ Une décision vit dans le document qu'elle règle. Ainsi on la trouve là où on la cherche.
14
+
15
+ Une règle s'écrit selon le métacadre (`METACADRE.md`, à côté de cette charte, §2).
16
+
17
+ ## Comment on arbitre
18
+
19
+ Une décision ou une question se tranche par les questions de la charte du projet (« Comment on
20
+ arbitre »), dans leur ordre : la première qui s'applique l'emporte, et le choix la nomme ; deux
21
+ réponses de même rang vont au responsable. Ainsi chaque choix construit un produit mature et
22
+ professionnel.
23
+
24
+ ## Le flux d'une tâche
25
+
26
+ 1. `bd ready`, `bd update <id> --claim`, lis le ticket et le cadre de chaque composant touché.
27
+ 2. Un défaut remonté est d'abord une question d'architecture : le ticket s'ouvre sur sa section
28
+ « Architecture » (le modèle mûr nommé, l'adresse dans l'architecture, le mécanisme commun), et
29
+ le correctif va dans ce mécanisme. Ainsi tout correctif passe par l'architecture.
30
+ 3. Une décision reste à prendre : `mattpocock-skills:grilling` avant d'écrire, ses questions dans
31
+ le ticket. Ainsi la décision est prise et écrite avant le code.
32
+ 4. Le plan va dans le ticket (`bd update <id> -d`). Un travail qui change un comportement est un
33
+ seul ticket : les tests d'abord (agent `testwriter`), puis le code qui les rend verts (agent
34
+ `developpeur`). Ainsi le code se mesure à des tests qu'il n'a pas écrits. Un critère répond à
35
+ un besoin réel de l'usage actuel. Ainsi le ticket garde la taille du besoin.
36
+ 5. Le ticket se ferme sur ses tests ciblés, le verdict du `relecteur` sur le lot et le commit du
37
+ circuit, seul à commiter, entré sur main par la file. Ainsi ce qui est déclaré fini l'est
38
+ vraiment.
39
+ 6. Chaque agent laisse sa passation en commentaire au ticket (`bd comments add`), avec ce qui
40
+ n'est pas fait et pourquoi ; une séance que le circuit mène finit sur sa fiche, la sortie
41
+ structurée de son rôle, sur laquelle le circuit décide. Ainsi la passation sert l'humain, et
42
+ la fiche le circuit.
43
+
44
+ Un ticket parcourt les étapes de son circuit (`etapes.mjs`, la seule liste), chacune tenue par un
45
+ rôle, agent du cadre, sous ses droits. Ainsi chaque agent travaille dans son cadre, et le numéro
46
+ d'une étape dit où en est chaque ticket.
47
+
48
+ **Tous les agents jugent sur le plan** : une décision du responsable entre dans la description du
49
+ ticket, comme une RFC amendée ; les commentaires restent l'historique. Ainsi chaque agent lit la
50
+ même décision.
51
+
52
+ **Un ticket de réalisation nomme ses composants** dans son titre (« numéro — sujet — composant,
53
+ composant ») et sa section « Architecture », le fournisseur d'abord ; il fait une seule livraison,
54
+ en un seul commit, et se crée sous sa mère (`docs/agents/issue-tracker.md`). Un objectif dont le
55
+ découpage n'est pas connu commence par une exploration, sans code. Ainsi l'avancement se lit
56
+ ticket par ticket.
57
+
58
+ **Un ticket ouvert naît du mot du responsable**, ou d'un défaut qu'un projet du cadre rencontre.
59
+ Une découverte d'agent se consigne dans un ticket fermé, sous le ticket qui l'a trouvée, étiqueté
60
+ `decouverte`. Ainsi chaque découverte est gardée, et le backlog reste le plan du responsable.
61
+
62
+ ## Ce qui tient le dépôt droit
63
+
64
+ - **Une matière, une adresse** : ce qu'un document décrit déjà s'y verse. Ainsi l'architecture
65
+ écrite reste une, et le code suit une seule version.
66
+ - **Un changement de comportement corrige ses textes** dans le même commit. Ainsi les documents
67
+ restent vrais.
68
+ - **Une décision de structure passe par le grill** (compétence `grill`) : découpage, paquets,
69
+ modules, interfaces, frontières. Ainsi l'architecture décide de la structure, et le code la suit.
70
+ - **Un geste transverse, un seul ticket** : un même changement sur plusieurs composants se décide
71
+ une fois, en gabarit dans la section « Architecture », et se mène dans une seule copie. Ainsi le
72
+ geste reste le même partout.
73
+ - **Les composants suivent un modèle commun** : chacun étend les configurations de base du cadre ;
74
+ un écart passe seulement inscrit, avec sa raison, dans la liste que le superviseur valide.
75
+ Ainsi le cadre ne maintient aucune spécificité par composant.
76
+ - **Une dette connue s'inscrit et se gèle** (`grillhouse-dette.json`) : une garde refuse tout
77
+ constat neuf, et le compte ne remonte jamais. Ainsi la dette ne fait que baisser.
78
+ - **Un remplacement supprime le remplacé** dans le même commit, avec ses consommateurs et ses
79
+ gardes. Ainsi le produit garde une seule façon de faire chaque chose.
80
+ - **Un commentaire dit ce que la chose est**, au présent. Ainsi il reste vrai tant que le code ne
81
+ change pas.
82
+
83
+ ## Outils
84
+
85
+ - ⛔ **Des commandes sans invite** : tout fichier temporaire dans le scratchpad de session ;
86
+ `env -C <dossier>` ou `git -C` à la place de `cd` ; une suppression passe par un script node du
87
+ scratchpad (`rmSync` de `node:fs`) sur un chemin nommé et lu ; un signal vise seulement un
88
+ processus que la séance a lancé. Une commande dont on doute s'écrit dans le compte rendu, sans
89
+ se lancer. Ainsi la séance avance seule.
90
+ - **Les tests se lancent par `npm test`** : `npm test -- <chemins>` pour un lancement ciblé,
91
+ chaque chemin écrit depuis la racine du dépôt ; `npm run test:forcer -- <chemins>` pour rejouer
92
+ pour de vrai un test soupçonné instable. `npm run verifier` joue les gardes et les tests ;
93
+ `npm run verifier -- --gardes`, les gardes seules. Aucun agent ne lance l'outil de test
94
+ directement. Ainsi chaque test tourne avec ce dont il dépend, et une seule fois tant que rien ne
95
+ change.
96
+ - **Main reste vert** : l'intégration exige un `npm run verifier` vert. Un test connu rouge se met
97
+ en quarantaine dans le test lui-même (`it.skip` ou `it.fails`), avec le ticket qui le corrige.
98
+ Ainsi chaque rouge a son ticket.
99
+ - **L'index d'abord** : toute recherche commence par `rtfm_search` (mode `hybrid`) pour le quoi, et
100
+ par `codegraph explore` (ou l'outil `codegraph_explore`) pour l'appel ; le shell lit un fichier
101
+ déjà nommé. Dans son enveloppe, un agent lit son paquet, les interfaces de ses voisins, la
102
+ matière de test partagée et ce que ses tests déclarent lire (`grillhouse.lit`). Ainsi une
103
+ affirmation sur le code repose sur ce que le code contient.
104
+ - Tickets : Beads (`bd`), sous le préfixe du projet, voir `docs/agents/issue-tracker.md`.
105
+ - Le greffon `mattpocock-skills` s'appelle avec son préfixe ; un document pour un agent s'écrit
106
+ avec `mattpocock-skills:writing-for-agents`.
107
+ - Réponses en français ; le code et les noms d'API restent en anglais.
@@ -0,0 +1,90 @@
1
+ # Les outils du cadre
2
+
3
+ Ce que font les outils du paquet `@roomi-fields/grillhouse`, que la charte commune résume pour
4
+ les agents. Chaque règle dit le comportement, et le modèle mûr qu’il suit.
5
+
6
+ **Les tests se lancent par `npm test`** (Turborepo : la construction, puis les tests) :
7
+ `npm test -- <chemins>` pour un lancement ciblé, chaque chemin écrit depuis la racine du dépôt
8
+ et joué dans son paquet avec ce dont ses tests dépendent (un autre jeu de chemins relit les
9
+ constructions du cache ; un changement de ce qu'ils importent les rejoue),
10
+ `npm run test:forcer -- <chemins>` pour rejouer pour de vrai un test soupçonné instable ; un
11
+ lancement qui ne joue aucun test échoue ; un banc de temps ou un test de nuit se joue quand son
12
+ propre fichier est nommé, au repos (un dossier ou un paquet nommé les laisse hors, comme le
13
+ jour) ; aucun agent ne lance l'outil de test directement. `npm run verifier` joue, après la
14
+ construction : les gardes du cadre,
15
+ celles du projet (son script racine `gardes`, un nom que le cadre réserve ; une garde juge les
16
+ fichiers de l'arbre de travail, que le cache de Turborepo compte, jamais l'index de git ; elle
17
+ écrit ses constats en SARIF, chacun avec son fichier et sa ligne, par `ecrireSarif` de
18
+ `packages/grillhouse/scripts/resultats.mjs`, dans le dossier que nomme `GRILLHOUSE_RESULTATS`, et sans eux son rouge
19
+ ne revient à aucun composant) et les tests, côte à côte ; un rouge n'arrête pas la passe, qui joue tout ce que ses tâches
20
+ préalables permettent et nomme chaque rouge ; `npm run verifier -- --gardes` joue les gardes
21
+ seules, ce que le relecteur joue sur la copie du ticket. Une tâche dont
22
+ rien n'a bougé n'est pas rejouée : Turborepo relit sa sortie consignée dans son cache (« cache
23
+ hit, replaying logs »), et cette relecture vaut un lancement. Une passe se mesure contre le
24
+ dernier vert, l'arbre de la dernière passe verte de sa branche, celle de main pour une copie
25
+ qui n'en a pas encore, comme `vitest --changed` : un paquet que Turborepo rejoue joue les seuls tests que Vitest relie aux fichiers changés depuis,
26
+ et tous ses tests quand un changement sort du graphe de Vitest (un fichier supprimé, une
27
+ configuration, un fichier qu'aucun module n'importe, le code d'un paquet dont il dépend, un
28
+ chemin que ses tests déclarent lire, `grillhouse.lit`) ; sans vert connu, la passe est
29
+ complète, et `npm run verifier -- --tout` la joue pour de vrai, comme la nuit. Ainsi un test ne
30
+ tourne qu'une fois tant que rien ne change, et corriger un test ne rejoue que lui.
31
+
32
+ **Une passe écrit sous sa base** : chaque lancement de Vitest, `npm test`, `npm run verifier`,
33
+ un circuit, une intégration et une enveloppe ouvrent leur base dans le dossier temporaire, la
34
+ nomment dans `TMPDIR` à ce qu'ils lancent (les dossiers d'essai des tests, celui de Vitest, celui
35
+ de Claude Code) et l'effacent à leur fin, verte ou rouge ; la base d'une passe tuée, la suivante
36
+ la balaie, comme Bazel donne à chaque test son `TEST_TMPDIR` et nettoie ses bacs à sable
37
+ (`packages/grillhouse/scripts/vitest-config/base-de-passe.mjs`). Ainsi un essai oublié ne remplit jamais le dossier
38
+ temporaire de la machine.
39
+
40
+ **Le dossier du circuit appartient au ticket** : `.claude/worktrees/<ticket>.travail` vit autant
41
+ que le ticket, comme l'espace de travail d'un pipeline ; aucun balayage n'y touche, la file
42
+ l'efface à la clôture, `npx grillhouse retirer-copie` avec la copie d'un ticket fermé sans
43
+ intégration. Ainsi une séance qui survit à son circuit garde ce qu'il lui a remis.
44
+
45
+ **Main reste vert** : l'intégration exige un `npm run verifier` vert, sans rouge admis, mesuré
46
+ contre le dernier vert ; la nuit rejoue la passe complète. Un test connu
47
+ rouge se met en quarantaine dans le test lui-même (`it.skip` ou `it.fails`), avec le ticket qui
48
+ le corrige, comme le fait une intégration continue mature. Ainsi chaque rouge a son ticket, et
49
+ main ne porte aucun rouge.
50
+
51
+ **Une mesure lourde à la fois sur la machine** : chaque `npm run verifier` et chaque passe
52
+ lourde du circuit (preuve du rouge, contrôles, passe finale) prennent le verrou de la machine,
53
+ partagé par tous ses dépôts (`~/.cache/grillhouse/mesure-lourde.lock`) ; une seconde mesure
54
+ attend la fin de la première et le redit toutes les 30 s, en nommant qui tient le verrou (le
55
+ processus, son dossier, sa commande, depuis quand) ; un verrou dont le processus est mort se
56
+ reprend, comme le serveur de tâches de GNU make. L'attente a une borne, 60 min
57
+ (`GRILLHOUSE_ATTENTE_MACHINE_MS`), plus longue que la plus longue passe complète mesurée : au-delà,
58
+ la mesure s'arrête « à repasser » (code 75), comme `flock -w`. Un verrou tenu par un ancêtre de
59
+ celui qui attend est un blocage : l'attente le dit tout de suite et s'arrête, rouge. La passe
60
+ borne ses tâches côte à côte à la moitié des cœurs. Ainsi une mesure rend le résultat du code, et
61
+ non celui d'une autre mesure à côté, et aucune passe ne reste figée sans le dire.
62
+
63
+ **Une passe automatique montre son avancement** : chaque passe automatique écrit ses fichiers
64
+ de tests faits sur prévus (la file, les étapes de sa CI), que le panneau affiche avec le temps
65
+ depuis son dernier signe, « ⚠ figée » au-delà de 5 min, comme le compteur d'actions de Bazel.
66
+ Ainsi une passe qui fige se voit.
67
+
68
+ **Un témoin de temps joue seul** : un fichier de test qui importe `mesurerAuRepos` est un
69
+ témoin de temps ; `npm run verifier` joue tous les autres tests, puis les témoins dans une passe
70
+ à eux, une tâche après l'autre, comme Bazel joue un test `exclusive`. Un échec qui dépend d'une
71
+ durée (un délai dépassé, un banc `*.budget.test.*`, un test marqué `mesurerAuRepos`) survenu sous
72
+ charge (la pression CPU du noyau, `/proc/pressure/cpu`, à 25 % ou plus) est « à repasser » (code
73
+ 75), ni vert ni rouge : `npm run verifier` rejoue sa tâche seule une fois la machine au repos ;
74
+ sans repos en 15 min, la livraison reste en attente et se représente, comme Bazel classe un
75
+ délai dépassé et CTest le rejoue. Ainsi un témoin ne se mesure jamais sous la charge de sa
76
+ propre passe, et un rouge au repos reste un rouge.
77
+
78
+ **Le cadre arrive en un seul morceau** : le paquet npm `@roomi-fields/grillhouse` porte les
79
+ scripts, appelés par `npx grillhouse <sous-commande>`, et il est le greffon `grillhouse`, qui
80
+ porte les compétences, les agents, les crochets de Claude Code, cette charte et le métacadre,
81
+ comme un paquet d'ESLint porte son greffon. La place de marché `roomi-fields`
82
+ (`roomi-fields/claude-plugins`) le désigne par sa source npm ; le projet la déclare et active
83
+ `grillhouse@roomi-fields` (`npx grillhouse maj`). Ce qui est propre à un projet (sa charte, ses
84
+ réglages, sa version du paquet) vit dans le projet, jamais dans ce qui se publie. Une version de
85
+ npm vaut pour les deux ; l'ouverture de séance nomme un greffon chargé à une autre version que
86
+ le paquet du projet, avec la commande qui les remet d'accord. Un projet n'en garde aucune copie ; sans le paquet installé, l'ouverture de séance dit « lance `npm install` », et les autres crochets
87
+ sortent sans effet. Les crochets git du cadre suivent le modèle de Husky : le `prepare` du
88
+ projet lance `grillhouse hooks`, qui les pose à côté des sections de Beads, et chacun appelle
89
+ `grillhouse hook <nom>`, sans effet sans le paquet. Ainsi chaque projet suit la version du cadre qu'il installe, sans fichier à
90
+ recopier.
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ // The hooks of Claude Code the frame's plugin declares (hooks.json): each runs
3
+ //
4
+ // node "${CLAUDE_PLUGIN_ROOT}/hooks/crochet.mjs" <sous-commande>
5
+ //
6
+ // with Node alone, before any installation, as Husky's hooks run before the project's tools.
7
+ //
8
+ // - The project is `CLAUDE_PROJECT_DIR`, else the working directory; its command is
9
+ // `node_modules/.bin/grillhouse`, which the project's `npm install` links (the package
10
+ // @roomi-fields/grillhouse).
11
+ // - The common charter reaches each session, a subagent's included, by the import of the
12
+ // project's CLAUDE.md, from the package installed, which Claude Code loads whole; no hook writes it, since Claude Code caps a hook's output (10,000 characters).
13
+ // - Each subcommand runs `grillhouse <sous-commande>`; without the command, `session-start` writes
14
+ // a section that says to run `npm install`, and any other subcommand exits 0 and writes nothing.
15
+ // - The command receives the hook's input on its standard input, writes on the hook's outputs, and
16
+ // its exit code is the hook's (2 blocks, as Claude Code reads it).
17
+ import { spawnSync } from 'node:child_process';
18
+ import { existsSync, writeSync } from 'node:fs';
19
+ import path from 'node:path';
20
+
21
+ const sous = process.argv[2] ?? '';
22
+ const projet = process.env.CLAUDE_PROJECT_DIR || process.cwd();
23
+ const commande = path.join(projet, 'node_modules', '.bin', 'grillhouse');
24
+
25
+ if (existsSync(commande)) {
26
+ const r = spawnSync(commande, [sous], { stdio: 'inherit', cwd: projet });
27
+ process.exitCode = r.status ?? 1;
28
+ } else if (sous === 'session-start') {
29
+ writeSync(
30
+ 1,
31
+ "## Paquet Roomi's Grillhouse absent\nLe projet n'a pas encore installé le paquet du cadre (`node_modules/.bin/grillhouse`, @roomi-fields/grillhouse) : lance `npm install` à la racine du projet, puis rouvre la séance. La charte commune, que CLAUDE.md importe du paquet, arrive avec lui.\n"
32
+ );
33
+ }
@@ -0,0 +1,58 @@
1
+ {
2
+ "modules": [
3
+ "./register.tsx"
4
+ ],
5
+ "hooks": {
6
+ "SessionStart": [
7
+ {
8
+ "hooks": [
9
+ {
10
+ "type": "command",
11
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/crochet.mjs\" session-start"
12
+ }
13
+ ]
14
+ }
15
+ ],
16
+ "UserPromptSubmit": [
17
+ {
18
+ "hooks": [
19
+ {
20
+ "type": "command",
21
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/crochet.mjs\" structure-guard"
22
+ }
23
+ ]
24
+ }
25
+ ],
26
+ "PreToolUse": [
27
+ {
28
+ "matcher": "Agent|Task",
29
+ "hooks": [
30
+ {
31
+ "type": "command",
32
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/crochet.mjs\" ticket-du-sous-agent"
33
+ }
34
+ ]
35
+ }
36
+ ],
37
+ "SubagentStop": [
38
+ {
39
+ "hooks": [
40
+ {
41
+ "type": "command",
42
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/crochet.mjs\" registre"
43
+ }
44
+ ]
45
+ }
46
+ ],
47
+ "SessionEnd": [
48
+ {
49
+ "hooks": [
50
+ {
51
+ "type": "command",
52
+ "command": "node \"${CLAUDE_PLUGIN_ROOT}/hooks/crochet.mjs\" registre"
53
+ }
54
+ ]
55
+ }
56
+ ]
57
+ }
58
+ }