@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.
- package/.claude-plugin/plugin.json +9 -0
- package/METACADRE.md +41 -0
- package/agents/developpeur.md +10 -0
- package/agents/explorateur.md +9 -0
- package/agents/questionneur.md +11 -0
- package/agents/referent-technique.md +9 -0
- package/agents/regulateur.md +11 -0
- package/agents/relecteur.md +9 -0
- package/agents/testwriter.md +10 -0
- package/bin/grillhouse.mjs +125 -0
- package/cadre/templates/projet/.claude/settings.json +30 -0
- package/cadre/templates/projet/.editorconfig +47 -0
- package/cadre/templates/projet/.env.example +57 -0
- package/cadre/templates/projet/.eslintrc.cjs +56 -0
- package/cadre/templates/projet/.github/workflows/ci.yml +66 -0
- package/cadre/templates/projet/.mcp.json +13 -0
- package/cadre/templates/projet/.prettierrc +11 -0
- package/cadre/templates/projet/CHANGELOG.md +61 -0
- package/cadre/templates/projet/CLAUDE.md +46 -0
- package/cadre/templates/projet/CONTRIBUTING.md +243 -0
- package/cadre/templates/projet/CREDITS.md +41 -0
- package/cadre/templates/projet/README.md +152 -0
- package/cadre/templates/projet/_gitignore +91 -0
- package/cadre/templates/projet/_npmignore +46 -0
- package/cadre/templates/projet/deployment/README.md +98 -0
- package/cadre/templates/projet/deployment/docs/01-INSTALL.md +145 -0
- package/cadre/templates/projet/deployment/docs/02-CONFIGURATION.md +117 -0
- package/cadre/templates/projet/deployment/docs/03-API.md +264 -0
- package/cadre/templates/projet/deployment/docs/04-TROUBLESHOOTING.md +262 -0
- package/cadre/templates/projet/deployment/scripts/install.ps1 +100 -0
- package/cadre/templates/projet/deployment/scripts/start.ps1 +61 -0
- package/cadre/templates/projet/deployment/scripts/stop.ps1 +37 -0
- package/cadre/templates/projet/deployment/scripts/test.ps1 +118 -0
- package/cadre/templates/projet/docs/agents/issue-tracker.md +44 -0
- package/cadre/templates/projet/ecosystem.config.cjs +73 -0
- package/cadre/templates/projet/package.json +90 -0
- package/cadre/templates/projet/pitmaster/SUIVI.md +22 -0
- package/cadre/templates/projet/src/config.ts +68 -0
- package/cadre/templates/projet/src/errors.ts +102 -0
- package/cadre/templates/projet/src/index.ts +46 -0
- package/cadre/templates/projet/src/services/.gitkeep +8 -0
- package/cadre/templates/projet/src/types/index.ts +24 -0
- package/cadre/templates/projet/src/utils/logger.ts +106 -0
- package/cadre/templates/projet/tests/integration/.gitkeep +7 -0
- package/cadre/templates/projet/tests/unit/config.spec.ts +68 -0
- package/cadre/templates/projet/tests/unit/errors.spec.ts +132 -0
- package/cadre/templates/projet/tests/unit/types.spec.ts +73 -0
- package/cadre/templates/projet/tsconfig.eslint.json +9 -0
- package/cadre/templates/projet/tsconfig.json +41 -0
- package/cadre/templates/projet/tsdoc.json +6 -0
- package/cadre/templates/projet/vitest.config.ts +44 -0
- package/cadre/templates/turbo/paquets.json +29 -0
- package/cadre/templates/turbo/sans-paquets.json +28 -0
- package/charte.md +107 -0
- package/docs/ARCHITECTURE.md +90 -0
- package/hooks/crochet.mjs +33 -0
- package/hooks/hooks.json +58 -0
- package/hooks/register.tsx +558 -0
- package/package.json +75 -4
- package/scripts/avancement.mjs +244 -0
- package/scripts/bilan.mjs +523 -0
- package/scripts/branche-de-nuit.mjs +59 -0
- package/scripts/cadre.mjs +109 -0
- package/scripts/circuit.mjs +4375 -0
- package/scripts/code-mort.mjs +371 -0
- package/scripts/composants-affectes.mjs +598 -0
- package/scripts/consommateurs-arbitres.mjs +192 -0
- package/scripts/consommateurs.mjs +310 -0
- package/scripts/crochet.mjs +24 -0
- package/scripts/crochets.mjs +135 -0
- package/scripts/dernier-vert.mjs +208 -0
- package/scripts/dette.mjs +181 -0
- package/scripts/droits.mjs +354 -0
- package/scripts/enveloppe/codes.mjs +17 -0
- package/scripts/enveloppe/composant.mjs +11 -0
- package/scripts/enveloppe/enveloppe.mjs +628 -0
- package/scripts/enveloppe/lancer.sh +311 -0
- package/scripts/etapes.mjs +323 -0
- package/scripts/etat-du-circuit.mjs +104 -0
- package/scripts/frontieres.mjs +456 -0
- package/scripts/gardes-du-cadre.mjs +72 -0
- package/scripts/greffons.mjs +338 -0
- package/scripts/grillhouse-maj.mjs +514 -0
- package/scripts/index-interfaces.mjs +293 -0
- package/scripts/init.mjs +117 -0
- package/scripts/integration/file-attente.mjs +61 -0
- package/scripts/integration/file.mjs +494 -0
- package/scripts/integration/integrer.mjs +381 -0
- package/scripts/integration/rejeu.mjs +139 -0
- package/scripts/integration/verdict.mjs +13 -0
- package/scripts/interfaces-contre-code.mjs +547 -0
- package/scripts/ligne-etat/defaut.sh +110 -0
- package/scripts/ligne-etat/ligne-etat.mjs +93 -0
- package/scripts/migrations/0.23.0-charte-importee.mjs +47 -0
- package/scripts/migrations/0.23.0-config-vitest.mjs +105 -0
- package/scripts/migrations/0.23.0-crochets-de-seance.mjs +55 -0
- package/scripts/migrations/0.23.0-marche-du-projet.mjs +82 -0
- package/scripts/migrations.mjs +43 -0
- package/scripts/nuit.sh +269 -0
- package/scripts/paquets.mjs +79 -0
- package/scripts/poussee-cles.mjs +46 -0
- package/scripts/preparation.mjs +84 -0
- package/scripts/references-par-les-types.mjs +420 -0
- package/scripts/registre.mjs +336 -0
- package/scripts/resultats.mjs +580 -0
- package/scripts/resumes.mjs +57 -0
- package/scripts/retirer-copie.sh +127 -0
- package/scripts/session-start.sh +203 -0
- package/scripts/sortie.mjs +155 -0
- package/scripts/sous-modules.sh +316 -0
- package/scripts/structure-guard.sh +27 -0
- package/scripts/superviseur.mjs +102 -0
- package/scripts/tableau.mjs +1886 -0
- package/scripts/tests.mjs +236 -0
- package/scripts/ticket.sh +23 -0
- package/scripts/turbo-des-paquets.mjs +899 -0
- package/scripts/un-commit-par-ticket.mjs +212 -0
- package/scripts/verifier.mjs +469 -0
- package/scripts/verrou-de-fichier.mjs +130 -0
- package/scripts/verrou-de-machine.mjs +211 -0
- package/scripts/verrous/commande.mjs +180 -0
- package/scripts/verrous/ticket-du-sous-agent.mjs +39 -0
- package/scripts/verrous/verrou.mjs +165 -0
- package/scripts/vitest-config/avancement.mjs +39 -0
- package/scripts/vitest-config/avancement.reporter.mjs +56 -0
- package/scripts/vitest-config/base-de-passe.mjs +128 -0
- package/scripts/vitest-config/base.d.ts +6 -0
- package/scripts/vitest-config/base.mjs +87 -0
- package/scripts/vitest-config/changements.mjs +173 -0
- package/scripts/vitest-config/cibles.mjs +207 -0
- package/scripts/vitest-config/duree.reporter.mjs +98 -0
- package/scripts/vitest-config/machine.setup.mjs +14 -0
- package/scripts/vitest-config/mesure.d.ts +6 -0
- package/scripts/vitest-config/mesure.mjs +13 -0
- package/scripts/vitest-config/mesure.setup.mjs +12 -0
- package/scripts/vitest-config/pression.mjs +90 -0
- package/scripts/vitest-config/resultats.mjs +23 -0
- package/scripts/vitest-config/resultats.setup.mjs +19 -0
- package/scripts/vitest.nuit.config.mjs +26 -0
- package/skills/developpeur/SKILL.md +175 -0
- package/skills/explorateur/SKILL.md +84 -0
- package/skills/grill/SKILL.md +238 -0
- package/skills/grill/references/releve-structurel.md +38 -0
- package/skills/mesure/SKILL.md +168 -0
- package/skills/pitmaster/SKILL.md +382 -0
- package/skills/pitmaster/references/cadre.md +119 -0
- package/skills/pitmaster/references/consigne-agent.md +308 -0
- package/skills/pitmaster/references/erreurs.md +25 -0
- package/skills/pitmaster/references/tour.md +124 -0
- package/skills/questionneur/SKILL.md +64 -0
- package/skills/redacteur/SKILL.md +84 -0
- package/skills/redacteur/references/documents-d-un-composant.md +105 -0
- package/skills/referent-technique/SKILL.md +145 -0
- package/skills/regulateur/SKILL.md +220 -0
- package/skills/release/SKILL.md +134 -0
- package/skills/release/scripts/update-version.cjs +92 -0
- package/skills/relecteur/SKILL.md +152 -0
- package/skills/relecteur/references/LICENSE-MIT +30 -0
- package/skills/relecteur/references/SOURCE.md +8 -0
- package/skills/relecteur/references/claims-check.md +14 -0
- package/skills/relecteur/references/deletion-check.md +14 -0
- package/skills/relecteur/references/edge-case-hunter.md +80 -0
- package/skills/relecteur/references/verification-gap.md +113 -0
- package/skills/testwriter/SKILL.md +187 -0
- package/types/index.d.ts +56 -0
- 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,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
|
+
}
|
package/hooks/hooks.json
ADDED
|
@@ -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
|
+
}
|