create-gef 1.2.0 → 1.3.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/.cursorrules +3 -0
- package/.windsurfrules +3 -0
- package/CHANGELOG.md +8 -0
- package/README.md +33 -8
- package/generator/features/scaffold-ci.js +3 -1
- package/generator/features/scaffold-gef.js +16 -0
- package/generator/features/scaffold-linter.js +40 -13
- package/generator/index.js +1 -1
- package/generator/templates/PULL_REQUEST_TEMPLATE.md +14 -0
- package/package.json +1 -1
package/.cursorrules
CHANGED
|
@@ -182,6 +182,9 @@ Ces limites sont non-négociables. L'IA ne peut JAMAIS générer du code qui les
|
|
|
182
182
|
- Commit dédié : `docs(adr): création ADR-XXX — [titre] (#ticket)`
|
|
183
183
|
- ⚠️ Ne PAS consigner les ADR dans le RESEARCH_LOG (réservé aux bugs).
|
|
184
184
|
|
|
185
|
+
### Fin d'une tâche (Avant de conclure)
|
|
186
|
+
- [ ] **Vérification Documentaire** : As-tu mis à jour le `README.md`, le `CHANGELOG.md` ou la doc Diátaxis si tes changements impactent l'architecture, l'installation ou les fonctionnalités globales ? **Tu dois toujours faire cette vérification proactivement, sans que l'utilisateur te le demande.**
|
|
187
|
+
|
|
185
188
|
---
|
|
186
189
|
|
|
187
190
|
*Ce fichier est la loi fondamentale du GEF. Il garantit un niveau d'ingénierie DORA "Elite" sur tous les projets.*
|
package/.windsurfrules
CHANGED
|
@@ -182,6 +182,9 @@ Ces limites sont non-négociables. L'IA ne peut JAMAIS générer du code qui les
|
|
|
182
182
|
- Commit dédié : `docs(adr): création ADR-XXX — [titre] (#ticket)`
|
|
183
183
|
- ⚠️ Ne PAS consigner les ADR dans le RESEARCH_LOG (réservé aux bugs).
|
|
184
184
|
|
|
185
|
+
### Fin d'une tâche (Avant de conclure)
|
|
186
|
+
- [ ] **Vérification Documentaire** : As-tu mis à jour le `README.md`, le `CHANGELOG.md` ou la doc Diátaxis si tes changements impactent l'architecture, l'installation ou les fonctionnalités globales ? **Tu dois toujours faire cette vérification proactivement, sans que l'utilisateur te le demande.**
|
|
187
|
+
|
|
185
188
|
---
|
|
186
189
|
|
|
187
190
|
*Ce fichier est la loi fondamentale du GEF. Il garantit un niveau d'ingénierie DORA "Elite" sur tous les projets.*
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.3.0](https://github.com/Gnzikoune/GEF/compare/v1.2.0...v1.3.0) (2026-07-21)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Features
|
|
7
|
+
|
|
8
|
+
* **generator:** automatisation des verrous mecaniques ([#10](https://github.com/Gnzikoune/GEF/issues/10)) ([1b92577](https://github.com/Gnzikoune/GEF/commit/1b9257770bb33ddf653ecbcb09cb4e5c50ff4826))
|
|
9
|
+
* **generator:** verrous physiques anti-contournement (Linter, PR, CI) ([fede0ce](https://github.com/Gnzikoune/GEF/commit/fede0ce4a9dfa9e4fd5de6f84108fe4aee24ea48))
|
|
10
|
+
|
|
3
11
|
## [1.2.0](https://github.com/Gnzikoune/GEF/compare/v1.1.1...v1.2.0) (2026-07-21)
|
|
4
12
|
|
|
5
13
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Un framework d'ingénierie logicielle qui transforme des règles de travail en outils automatisés. Il garantit traçabilité, sécurité et qualité sur chaque projet, dès le premier commit.
|
|
4
4
|
>
|
|
5
|
-
> **🛡️ Standards de l'Industrie Enforcés :** GitHub Flow (PRs obligatoires), OWASP Security Limits (Rate Limiting, JWT Exp),
|
|
5
|
+
> **🛡️ Standards de l'Industrie Enforcés :** GitHub Flow (PRs obligatoires), OWASP Security Limits (Rate Limiting, JWT Exp), Clean Code Metrics adaptatifs (Startup / Standard / Mission Critical), et **Garantie Anti-Contournement IA** (Crash Clause, `.cursorrules` complets, CI d'intention).
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
@@ -16,7 +16,8 @@
|
|
|
16
16
|
6. [Le Pipeline CI/CD (Brique C)](#6-le-pipeline-cicd-brique-c)
|
|
17
17
|
7. [Les Prompts IA (Brique D)](#7-les-prompts-ia-brique-d)
|
|
18
18
|
8. [Le Tech Lead Virtuel (Brique E)](#8-le-tech-lead-virtuel-brique-e)
|
|
19
|
-
9. [La
|
|
19
|
+
9. [La Garantie Anti-Contournement IA (Brique F)](#9-la-garantie-anti-contournement-ia-brique-f)
|
|
20
|
+
10. [La Source de Vérité](#10-la-source-de-vérité)
|
|
20
21
|
|
|
21
22
|
---
|
|
22
23
|
|
|
@@ -39,6 +40,8 @@ GEF/
|
|
|
39
40
|
├── PROJECT_CONFIG.template.md ← Template de configuration projet
|
|
40
41
|
├── README.md ← Ce fichier
|
|
41
42
|
├── package.json ← Package NPM (rend le GEF exécutable via npx)
|
|
43
|
+
├── .cursorrules ← Brique F : Toutes les règles GEF pour les IDEs IA (Cursor, Windsurf)
|
|
44
|
+
├── .windsurfrules ← Brique F : Alias .cursorrules pour Windsurf
|
|
42
45
|
│
|
|
43
46
|
├── generator/ ← Brique A : CLI de génération de projet
|
|
44
47
|
│ ├── index.js ← Point d'entrée (routage des commandes : help, version, update, interactif)
|
|
@@ -52,16 +55,18 @@ GEF/
|
|
|
52
55
|
│ │ ├── scaffold-linter.js ← Génération des configs Biome, ESLint, Ruff
|
|
53
56
|
│ │ ├── scaffold-docker.js ← Dockerfile, docker-compose, init.sql
|
|
54
57
|
│ │ ├── scaffold-ci.js ← Workflows GitHub Actions (CI/CD, release-please)
|
|
58
|
+
│ │ ├── scaffold-ai-rules.js ← Brique F : Copie .cursorrules dans chaque projet généré
|
|
55
59
|
│ │ └── update.js ← Mise à jour d'un projet existant
|
|
56
60
|
│ └── templates/
|
|
57
61
|
│ └── adr-template.md ← Template d'ADR prêt à l'emploi
|
|
58
62
|
│
|
|
59
|
-
├── hooks/ ← Hooks Git (installés dans le dépôt GEF lui-même)
|
|
63
|
+
├── hooks/ ← Brique B : Hooks Git (installés dans le dépôt GEF lui-même)
|
|
60
64
|
│ ├── commit-msg ← Conventional Commits + référence Kanban obligatoire (#XYZ)
|
|
61
|
-
│ └── pre-commit ← Détection secrets, lint
|
|
65
|
+
│ └── pre-commit ← Détection secrets, lint, blocage commit sur main/master
|
|
62
66
|
│
|
|
63
|
-
├── ci-templates/ ← Brique C :
|
|
64
|
-
│
|
|
67
|
+
├── ci-templates/ ← Brique C : Templates de base CI/CD
|
|
68
|
+
│ ├── main.yml ← (le générateur produit un CI adapté à la stack)
|
|
69
|
+
│ └── pr-intention-check.yml ← Brique F : Bloque les PRs sans intention métier déclarée
|
|
65
70
|
│
|
|
66
71
|
├── .github/workflows/
|
|
67
72
|
│ └── release-please.yml ← Automatisation des releases du GEF lui-même
|
|
@@ -224,7 +229,7 @@ Installés automatiquement par le générateur dans `.git/hooks/` de chaque proj
|
|
|
224
229
|
| Hook | Règle appliquée |
|
|
225
230
|
|---|---|
|
|
226
231
|
| **`commit-msg`** | Bloque tout commit dont le message ne respecte pas le format `Conventional Commits + référence Kanban`. Format : `feat: description (#42)`. |
|
|
227
|
-
| **`pre-commit`** | Détecte les secrets en clair (clés API, tokens). Vérifie le formatage (linter). Analyse la taille des fichiers selon la sévérité choisie.
|
|
232
|
+
| **`pre-commit`** | Détecte les secrets en clair (clés API, tokens). Vérifie le formatage (linter). Analyse la taille des fichiers selon la sévérité choisie. **Bloque tout commit direct sur `main` ou `master`.** |
|
|
228
233
|
| **`pre-push`** | **Dynamique** : Bloque tout push direct sur `main` si le projet est en GitHub Flow. Exécute les tests locaux si en Trunk-Based Development. |
|
|
229
234
|
|
|
230
235
|
Ces hooks sont générés à la volée par le générateur en fonction des choix de l'équipe, et installablés dans `.git/hooks/` du projet.
|
|
@@ -283,7 +288,27 @@ Avant d'écrire le code applicatif, l'IA rédige le test E2E (Playwright) qui d
|
|
|
283
288
|
|
|
284
289
|
---
|
|
285
290
|
|
|
286
|
-
## 9. La
|
|
291
|
+
## 9. La Garantie Anti-Contournement IA (Brique F)
|
|
292
|
+
|
|
293
|
+
Le GEF va au-delà des règles textuelles. Il **impose mécaniquement** aux IA les bonnes pratiques dès l'ouverture du projet, sans que l'utilisateur ait à les répéter.
|
|
294
|
+
|
|
295
|
+
### Comment ça fonctionne
|
|
296
|
+
|
|
297
|
+
| Mécanisme | Fichier | Effet |
|
|
298
|
+
|---|---|---|
|
|
299
|
+
| **Règles natives IDE** | `.cursorrules` / `.windsurfrules` | Toute IA (Cursor, Windsurf, Copilot) lit ces fichiers au démarrage et connaît instantanément les §0 à §10 du Playbook (Clean Code, Architecture, Sécurité OWASP, Git Flow, Tests, Workflows). |
|
|
300
|
+
| **Crash Clause** | `prompts/system_prompt.md` | L'IA est instruite de s'arrêter immédiatement et de signaler tout obstacle, au lieu de l'improvisation silencieuse. |
|
|
301
|
+
| **Checklist Pull Request** | `.github/PULL_REQUEST_TEMPLATE.md` | L'IA (et l'humain) doit physiquement cocher les validations (Tests, Docs, ADR) avant qu'une PR puisse être mergée. |
|
|
302
|
+
| **Blocage Linter (Hard Limits)** | `biome.json` / `.eslintrc.json` / `ruff.toml` | Le linter est configuré avec les limites (ex: 15 lignes max, 2 paramètres) et plantera si l'IA tente de bypasser le framework. |
|
|
303
|
+
| **Blocage local** | `hooks/pre-commit` | Un commit direct sur `main` est physiquement impossible, tout comme un commit qui ne passe pas le Linter. |
|
|
304
|
+
| **Validation CI (Intention & Tests)** | `ci-templates/pr-intention-check.yml` & `main.yml` | La CI rejette les PRs sans intention métier, et bloque si la couverture de tests < 80%. |
|
|
305
|
+
| **Propagation** | `generator/features/scaffold-ai-rules.js` | Chaque projet généré hérite automatiquement du `.cursorrules` complet (source unique de vérité). |
|
|
306
|
+
|
|
307
|
+
> La puissance réside ici : l'utilisateur n'a jamais à expliquer les règles à l'IA. Elles sont déjà là.
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## 10. La Source de Vérité
|
|
287
312
|
|
|
288
313
|
Toutes les règles appliquées par ce framework sont définies dans un seul document :
|
|
289
314
|
|
|
@@ -129,6 +129,8 @@ function buildTestBlock(isNode, isPython, database) {
|
|
|
129
129
|
if (isNode) {
|
|
130
130
|
return ` - name: Tests (avec couverture)
|
|
131
131
|
run: npm test -- --coverage --if-present${dbEnv}
|
|
132
|
+
# Note: Configurez Jest ou Vitest dans votre projet pour échouer si la couverture < 80%
|
|
133
|
+
# Ex Jest: "coverageThreshold": { "global": { "lines": 80 } }
|
|
132
134
|
|
|
133
135
|
- name: Upload Coverage
|
|
134
136
|
uses: codecov/codecov-action@v4
|
|
@@ -139,7 +141,7 @@ function buildTestBlock(isNode, isPython, database) {
|
|
|
139
141
|
return ` - name: Tests (pytest + coverage)
|
|
140
142
|
run: |
|
|
141
143
|
pip install pytest pytest-cov
|
|
142
|
-
pytest tests/ -v --cov=src --cov-report=xml${dbEnv}
|
|
144
|
+
pytest tests/ -v --cov=src --cov-report=xml --cov-fail-under=80${dbEnv}
|
|
143
145
|
|
|
144
146
|
- name: Upload Coverage
|
|
145
147
|
uses: codecov/codecov-action@v4
|
|
@@ -90,6 +90,20 @@ function createAdrTemplate(gefDir) {
|
|
|
90
90
|
if (fs.existsSync(templateSrc)) fs.copyFileSync(templateSrc, dest);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
+
function createPRTemplate(gefDir) {
|
|
94
|
+
const templateSrc = path.join(gefDir, 'generator', 'templates', 'PULL_REQUEST_TEMPLATE.md');
|
|
95
|
+
fs.mkdirSync('.github', { recursive: true });
|
|
96
|
+
const dest = '.github/PULL_REQUEST_TEMPLATE.md';
|
|
97
|
+
if (fs.existsSync(templateSrc)) fs.copyFileSync(templateSrc, dest);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function copyAdditionalWorkflows(gefDir) {
|
|
101
|
+
const src = path.join(gefDir, 'ci-templates', 'pr-intention-check.yml');
|
|
102
|
+
const destDir = '.github/workflows';
|
|
103
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
104
|
+
if (fs.existsSync(src)) fs.copyFileSync(src, path.join(destDir, 'pr-intention-check.yml'));
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
function createResearchLog(language) {
|
|
94
108
|
const isEn = language === 'English';
|
|
95
109
|
const dest = 'docs/research/RESEARCH_LOG.md';
|
|
@@ -148,6 +162,8 @@ export function scaffoldGef(answers, gefDir) {
|
|
|
148
162
|
createDirectories(answers.includeCI);
|
|
149
163
|
copyAndTemplateGefAssets(gefDir, answers.strictness, answers.language);
|
|
150
164
|
createAdrTemplate(gefDir);
|
|
165
|
+
createPRTemplate(gefDir);
|
|
166
|
+
if (answers.includeCI) copyAdditionalWorkflows(gefDir);
|
|
151
167
|
createResearchLog(answers.language);
|
|
152
168
|
createProjectConfig(answers, gefDir);
|
|
153
169
|
createReadme(answers);
|
|
@@ -5,16 +5,30 @@ import fs from 'fs';
|
|
|
5
5
|
import { execSync } from 'child_process';
|
|
6
6
|
import chalk from 'chalk';
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Détermine les limites métriques selon le niveau de sévérité.
|
|
10
|
+
*/
|
|
11
|
+
function getLimits(strictness) {
|
|
12
|
+
if (strictness.includes('Startup')) return { maxLines: 50, maxParams: 4, maxComplexity: 15 };
|
|
13
|
+
if (strictness.includes('Mission Critical')) return { maxLines: 15, maxParams: 2, maxComplexity: 5 };
|
|
14
|
+
return { maxLines: 30, maxParams: 3, maxComplexity: 10 }; // Standard
|
|
15
|
+
}
|
|
16
|
+
|
|
8
17
|
/**
|
|
9
18
|
* Configure ESLint et Prettier.
|
|
10
19
|
*/
|
|
11
|
-
function configureEslint(stack) {
|
|
12
|
-
console.log(chalk.yellow('🧹 Configuration de ESLint + Prettier...'));
|
|
20
|
+
function configureEslint(stack, strictness) {
|
|
21
|
+
console.log(chalk.yellow('🧹 Configuration de ESLint + Prettier avec Hard Limits...'));
|
|
22
|
+
const limits = getLimits(strictness);
|
|
13
23
|
const eslintConfig = {
|
|
14
24
|
env: { browser: true, es2021: true, node: true },
|
|
15
25
|
extends: ['eslint:recommended', 'prettier'],
|
|
16
26
|
parserOptions: { ecmaVersion: 'latest', sourceType: 'module' },
|
|
17
|
-
rules: {
|
|
27
|
+
rules: {
|
|
28
|
+
'max-lines-per-function': ['error', limits.maxLines],
|
|
29
|
+
'max-params': ['error', limits.maxParams],
|
|
30
|
+
'complexity': ['error', limits.maxComplexity]
|
|
31
|
+
},
|
|
18
32
|
};
|
|
19
33
|
fs.writeFileSync('.eslintrc.json', JSON.stringify(eslintConfig, null, 2));
|
|
20
34
|
fs.writeFileSync('.prettierrc', '{\n "semi": true,\n "singleQuote": true,\n "printWidth": 100\n}\n');
|
|
@@ -31,8 +45,9 @@ function configureEslint(stack) {
|
|
|
31
45
|
/**
|
|
32
46
|
* Configure Biome.
|
|
33
47
|
*/
|
|
34
|
-
function configureBiome() {
|
|
35
|
-
console.log(chalk.yellow('⚡ Configuration de Biome...'));
|
|
48
|
+
function configureBiome(strictness) {
|
|
49
|
+
console.log(chalk.yellow('⚡ Configuration de Biome avec Hard Limits...'));
|
|
50
|
+
const limits = getLimits(strictness);
|
|
36
51
|
const biomeConfig = {
|
|
37
52
|
$schema: "https://biomejs.dev/schemas/1.8.3/schema.json",
|
|
38
53
|
formatter: {
|
|
@@ -44,7 +59,15 @@ function configureBiome() {
|
|
|
44
59
|
},
|
|
45
60
|
linter: {
|
|
46
61
|
enabled: true,
|
|
47
|
-
rules: {
|
|
62
|
+
rules: {
|
|
63
|
+
recommended: true,
|
|
64
|
+
complexity: {
|
|
65
|
+
noExcessiveCognitiveComplexity: {
|
|
66
|
+
level: "error",
|
|
67
|
+
options: { maxAllowedComplexity: limits.maxComplexity }
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
48
71
|
}
|
|
49
72
|
};
|
|
50
73
|
fs.writeFileSync('biome.json', JSON.stringify(biomeConfig, null, 2));
|
|
@@ -61,12 +84,16 @@ function configureBiome() {
|
|
|
61
84
|
/**
|
|
62
85
|
* Configure Ruff pour Python.
|
|
63
86
|
*/
|
|
64
|
-
function configureRuff() {
|
|
65
|
-
console.log(chalk.yellow('🐍 Configuration de Ruff...'));
|
|
87
|
+
function configureRuff(strictness) {
|
|
88
|
+
console.log(chalk.yellow('🐍 Configuration de Ruff avec Hard Limits...'));
|
|
89
|
+
const limits = getLimits(strictness);
|
|
66
90
|
const ruffToml = `[lint]
|
|
67
|
-
select = ["E", "F", "I"]
|
|
91
|
+
select = ["E", "F", "I", "C90"]
|
|
68
92
|
ignore = []
|
|
69
93
|
|
|
94
|
+
[lint.mccabe]
|
|
95
|
+
max-complexity = ${limits.maxComplexity}
|
|
96
|
+
|
|
70
97
|
[format]
|
|
71
98
|
quote-style = "double"
|
|
72
99
|
indent-style = "space"
|
|
@@ -77,13 +104,13 @@ indent-style = "space"
|
|
|
77
104
|
/**
|
|
78
105
|
* Orchestre la génération de la configuration du linter.
|
|
79
106
|
*/
|
|
80
|
-
export function scaffoldLinter(linterChoice, stack) {
|
|
107
|
+
export function scaffoldLinter(linterChoice, stack, strictness) {
|
|
81
108
|
if (linterChoice === 'Aucun' || !linterChoice) return;
|
|
82
109
|
|
|
83
110
|
try {
|
|
84
|
-
if (linterChoice.includes('ESLint')) configureEslint(stack);
|
|
85
|
-
else if (linterChoice.includes('Biome')) configureBiome();
|
|
86
|
-
else if (linterChoice.includes('Ruff')) configureRuff();
|
|
111
|
+
if (linterChoice.includes('ESLint')) configureEslint(stack, strictness);
|
|
112
|
+
else if (linterChoice.includes('Biome')) configureBiome(strictness);
|
|
113
|
+
else if (linterChoice.includes('Ruff')) configureRuff(strictness);
|
|
87
114
|
console.log(chalk.green('✅ Linter configuré.'));
|
|
88
115
|
} catch (err) {
|
|
89
116
|
console.log(chalk.red('Erreur lors de la configuration du linter.'));
|
package/generator/index.js
CHANGED
|
@@ -44,7 +44,7 @@ async function run() {
|
|
|
44
44
|
process.chdir(projectPath);
|
|
45
45
|
|
|
46
46
|
scaffoldStack(answers, projectPath);
|
|
47
|
-
scaffoldLinter(answers.linter, answers.stack);
|
|
47
|
+
scaffoldLinter(answers.linter, answers.stack, answers.strictness);
|
|
48
48
|
scaffoldGef(answers, GEF_DIR);
|
|
49
49
|
scaffoldAiRules(GEF_DIR, projectPath);
|
|
50
50
|
if (answers.includeDocker) scaffoldDocker(answers.stack, answers.database, answers.projectName);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
## Intention
|
|
2
|
+
*Décrivez ici le "Pourquoi" de cette Pull Request. Quel problème résout-elle ou quelle valeur métier apporte-t-elle ?*
|
|
3
|
+
|
|
4
|
+
## Changements
|
|
5
|
+
*Liste des fichiers majeurs ou composants modifiés.*
|
|
6
|
+
|
|
7
|
+
## Checklist Qualité GEF (Obligatoire)
|
|
8
|
+
Avant de fusionner, vous DEVEZ valider ces éléments :
|
|
9
|
+
|
|
10
|
+
- [ ] J'ai vérifié que le code respecte les Hard Limits du niveau de sévérité du projet.
|
|
11
|
+
- [ ] J'ai écrit ou mis à jour le test unitaire / E2E associé (la CI bloquera si coverage < 80%).
|
|
12
|
+
- [ ] J'ai créé un rapport ADR dans `docs/explanation/adr/` s'il y a un ajout de dépendance majeure ou une nouvelle architecture.
|
|
13
|
+
- [ ] J'ai mis à jour le README.md / CHANGELOG.md si nécessaire.
|
|
14
|
+
- [ ] La pipeline CI/CD de validation est verte.
|