aiad-sdd 1.0.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/LICENSE +21 -0
- package/README.md +146 -0
- package/bin/aiad-sdd.js +75 -0
- package/lib/governance.js +101 -0
- package/lib/init.js +176 -0
- package/lib/status.js +109 -0
- package/package.json +36 -0
- package/templates/.aiad/AGENT-GUIDE.md +116 -0
- package/templates/.aiad/ARCHITECTURE.md +96 -0
- package/templates/.aiad/CHANGELOG-ARTEFACTS.md +18 -0
- package/templates/.aiad/PRD.md +61 -0
- package/templates/.aiad/gouvernance/CLAUDE-AI-ACT.md +572 -0
- package/templates/.aiad/gouvernance/CLAUDE-RGAA.md +507 -0
- package/templates/.aiad/gouvernance/CLAUDE-RGESN.md +213 -0
- package/templates/.aiad/gouvernance/CLAUDE-RGPD.md +575 -0
- package/templates/.aiad/intents/_index.md +17 -0
- package/templates/.aiad/specs/_index.md +19 -0
- package/templates/.claude/commands/aiad-intention.md +87 -0
- package/templates/.claude/commands/aiad-retro.md +72 -0
- package/templates/.claude/commands/aiad-status.md +67 -0
- package/templates/.claude/commands/sdd-drift-check.md +60 -0
- package/templates/.claude/commands/sdd-gate.md +67 -0
- package/templates/.claude/commands/sdd-init.md +46 -0
- package/templates/.claude/commands/sdd-intent.md +66 -0
- package/templates/.claude/commands/sdd-spec.md +98 -0
- package/templates/.claude/commands/sdd-validate.md +69 -0
- package/templates/CLAUDE.md +111 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Steeve Evers — AIAD Framework
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
# aiad-sdd
|
|
2
|
+
|
|
3
|
+
**Spec Driven Development pour Claude Code** — Framework de développement spec-first avec agents IA.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npx aiad-sdd init
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Qu'est-ce que SDD Mode ?
|
|
12
|
+
|
|
13
|
+
SDD Mode (Spec Driven Development Mode) est le framework de développement d'[AIAD](https://aiad.ovh). Il définit comment les équipes transforment des intentions produit en code de qualité en faisant des SPECs le pivot entre l'humain et l'agent IA.
|
|
14
|
+
|
|
15
|
+
**3 principes fondateurs :**
|
|
16
|
+
|
|
17
|
+
1. **Spec as Living Invariant** — La SPEC reste la source de vérité entre intention et code
|
|
18
|
+
2. **Drift = Échec de processus** — Code et SPEC toujours synchronisés
|
|
19
|
+
3. **Context Budget** — Le PE gère le budget de contexte de chaque session agent
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Initialisation complète (structure + gouvernance + commandes Claude Code)
|
|
25
|
+
npx aiad-sdd init
|
|
26
|
+
|
|
27
|
+
# Sans les agents de gouvernance
|
|
28
|
+
npx aiad-sdd init --sans-gouvernance
|
|
29
|
+
|
|
30
|
+
# Mettre à jour les agents de gouvernance
|
|
31
|
+
npx aiad-sdd gouvernance
|
|
32
|
+
|
|
33
|
+
# Voir l'état du projet
|
|
34
|
+
npx aiad-sdd status
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Ce qui est installé
|
|
38
|
+
|
|
39
|
+
### Structure `.aiad/`
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
.aiad/
|
|
43
|
+
├── PRD.md ← Vision produit (template)
|
|
44
|
+
├── ARCHITECTURE.md ← Standards techniques (template)
|
|
45
|
+
├── AGENT-GUIDE.md ← Contexte permanent agent (template)
|
|
46
|
+
├── gouvernance/ ← Agents Tier 1 (droit de veto)
|
|
47
|
+
│ ├── CLAUDE-AI-ACT.md ← Conformité EU AI Act
|
|
48
|
+
│ ├── CLAUDE-RGPD.md ← Privacy by Design, RGPD
|
|
49
|
+
│ ├── CLAUDE-RGAA.md ← Accessibilité RGAA 4.1 / WCAG 2.1
|
|
50
|
+
│ └── CLAUDE-RGESN.md ← Écoconception numérique
|
|
51
|
+
├── intents/ ← Intent Statements
|
|
52
|
+
│ └── _index.md
|
|
53
|
+
├── specs/ ← SPECs techniques
|
|
54
|
+
│ └── _index.md
|
|
55
|
+
└── CHANGELOG-ARTEFACTS.md ← Historique des mises à jour
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Commandes Claude Code
|
|
59
|
+
|
|
60
|
+
| Commande | Phase | Description |
|
|
61
|
+
|----------|-------|-------------|
|
|
62
|
+
| `/sdd-init` | Cadrage | Initialiser PRD + ARCHITECTURE + AGENT-GUIDE |
|
|
63
|
+
| `/sdd-intent` | Intention | Capturer un Intent Statement (POURQUOI) |
|
|
64
|
+
| `/sdd-spec` | Spécification | Rédiger une SPEC depuis un Intent |
|
|
65
|
+
| `/sdd-gate` | Validation | Execution Gate + Spec Quality Score |
|
|
66
|
+
| `/sdd-validate` | Validation | Valider le code produit par l'agent |
|
|
67
|
+
| `/sdd-drift-check` | Intégration | Vérifier synchronisation artefacts/code |
|
|
68
|
+
| `/aiad-retro` | Amélioration | Rétrospective de fin d'itération |
|
|
69
|
+
| `/aiad-intention` | Alignement | Atelier d'Intention (rituel mensuel) |
|
|
70
|
+
| `/aiad-status` | Monitoring | État du projet SDD |
|
|
71
|
+
|
|
72
|
+
### CLAUDE.md
|
|
73
|
+
|
|
74
|
+
Un `CLAUDE.md` est créé (ou enrichi) avec le contexte SDD Mode complet : cycle de développement, hiérarchie documentaire, règles absolues, gouvernance.
|
|
75
|
+
|
|
76
|
+
## Cycle de développement
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
┌─────────────┐ ┌──────────┐ ┌──────────────┐
|
|
80
|
+
│ /sdd-intent │────▶│ /sdd-spec │────▶│ /sdd-gate │
|
|
81
|
+
│ Intention │ │ SPEC │ │ SQS ≥ 4/5 │
|
|
82
|
+
└─────────────┘ └──────────┘ └──────┬───────┘
|
|
83
|
+
│
|
|
84
|
+
┌───────────────────────────────────────┘
|
|
85
|
+
▼
|
|
86
|
+
┌──────────────┐ ┌──────────────┐ ┌────────────────┐
|
|
87
|
+
│ Développement│────▶│ /sdd-validate│────▶│/sdd-drift-check│
|
|
88
|
+
│ Agent IA │ │ Validation │ │ Drift Lock │
|
|
89
|
+
└──────────────┘ └──────────────┘ └────────────────┘
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## Démarrage rapide
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# 1. Initialiser SDD Mode
|
|
96
|
+
npx aiad-sdd init
|
|
97
|
+
|
|
98
|
+
# 2. Dans Claude Code, lancer le cadrage
|
|
99
|
+
/sdd-init
|
|
100
|
+
|
|
101
|
+
# 3. Capturer la première intention
|
|
102
|
+
/sdd-intent
|
|
103
|
+
|
|
104
|
+
# 4. Rédiger la première SPEC
|
|
105
|
+
/sdd-spec
|
|
106
|
+
|
|
107
|
+
# 5. Valider la SPEC (Execution Gate)
|
|
108
|
+
/sdd-gate
|
|
109
|
+
|
|
110
|
+
# 6. Développer (Claude Code gère l'orchestration agent)
|
|
111
|
+
|
|
112
|
+
# 7. Valider et verrouiller
|
|
113
|
+
/sdd-validate
|
|
114
|
+
/sdd-drift-check
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## Agents de gouvernance
|
|
118
|
+
|
|
119
|
+
Les 4 agents Tier 1 ont un **droit de veto** sur toute implémentation non conforme :
|
|
120
|
+
|
|
121
|
+
| Agent | Périmètre | Référentiel |
|
|
122
|
+
|-------|-----------|-------------|
|
|
123
|
+
| **CLAUDE-AI-ACT** | Composants IA | Règlement (UE) 2024/1689 |
|
|
124
|
+
| **CLAUDE-RGPD** | Données personnelles | RGPD + ePrivacy |
|
|
125
|
+
| **CLAUDE-RGAA** | Interfaces utilisateur | RGAA 4.1 / WCAG 2.1 |
|
|
126
|
+
| **CLAUDE-RGESN** | Écoconception | RGESN v2 |
|
|
127
|
+
|
|
128
|
+
## Compatibilité
|
|
129
|
+
|
|
130
|
+
SDD Mode est conçu pour Claude Code mais les artefacts sont compatibles avec :
|
|
131
|
+
- **Cursor** — `.aiad/AGENT-GUIDE.md` ↔ Memory Bank (`.cursor/rules`)
|
|
132
|
+
- **AWS Kiro** — `.aiad/` ↔ `.kiro/` (steering files)
|
|
133
|
+
- **GitHub Spec Kit** — `.aiad/specs/` ↔ Spec files
|
|
134
|
+
|
|
135
|
+
## Framework AIAD
|
|
136
|
+
|
|
137
|
+
AIAD (AI-Agent Iterative Development) est un framework open source pour le développement logiciel à l'ère des agents IA.
|
|
138
|
+
|
|
139
|
+
- **Site** : [aiad.ovh](https://aiad.ovh)
|
|
140
|
+
- **Constitution** : 6 valeurs fondatrices, gouvernance gardien/communauté
|
|
141
|
+
- **5 responsabilités** : PM, Product Engineer, Agents Engineer, QA Engineer, Tech Lead
|
|
142
|
+
- **ALIS** : Système d'évolution lunaire (mise à jour à chaque pleine lune)
|
|
143
|
+
|
|
144
|
+
## Licence
|
|
145
|
+
|
|
146
|
+
MIT — Steeve Evers — [aiad.ovh](https://aiad.ovh)
|
package/bin/aiad-sdd.js
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { argv, exit, cwd } from 'node:process';
|
|
4
|
+
import { init } from '../lib/init.js';
|
|
5
|
+
import { addGovernance } from '../lib/governance.js';
|
|
6
|
+
import { showStatus } from '../lib/status.js';
|
|
7
|
+
|
|
8
|
+
const VERSION = '1.0.0';
|
|
9
|
+
const command = argv[2];
|
|
10
|
+
const flags = argv.slice(3);
|
|
11
|
+
|
|
12
|
+
const AIDE = `
|
|
13
|
+
aiad-sdd v${VERSION} — Spec Driven Development pour Claude Code
|
|
14
|
+
https://aiad.ovh
|
|
15
|
+
|
|
16
|
+
Commandes :
|
|
17
|
+
init [options] Initialise SDD Mode dans le projet courant
|
|
18
|
+
gouvernance Ajoute/met à jour les agents de gouvernance
|
|
19
|
+
status Affiche l'état SDD du projet
|
|
20
|
+
help Affiche cette aide
|
|
21
|
+
|
|
22
|
+
Options init :
|
|
23
|
+
--sans-gouvernance Initialise sans les agents de gouvernance
|
|
24
|
+
--force Écrase les fichiers existants
|
|
25
|
+
|
|
26
|
+
Exemples :
|
|
27
|
+
npx aiad-sdd init Initialisation complète
|
|
28
|
+
npx aiad-sdd init --force Réinitialisation (écrase)
|
|
29
|
+
npx aiad-sdd gouvernance Met à jour les agents de gouvernance
|
|
30
|
+
npx aiad-sdd status État du projet SDD
|
|
31
|
+
|
|
32
|
+
Framework AIAD — AI-Agent Iterative Development — Open Source
|
|
33
|
+
`;
|
|
34
|
+
|
|
35
|
+
async function main() {
|
|
36
|
+
switch (command) {
|
|
37
|
+
case 'init':
|
|
38
|
+
await init(cwd(), {
|
|
39
|
+
sansGouvernance: flags.includes('--sans-gouvernance'),
|
|
40
|
+
force: flags.includes('--force'),
|
|
41
|
+
});
|
|
42
|
+
break;
|
|
43
|
+
|
|
44
|
+
case 'gouvernance':
|
|
45
|
+
await addGovernance(cwd(), { force: flags.includes('--force') });
|
|
46
|
+
break;
|
|
47
|
+
|
|
48
|
+
case 'status':
|
|
49
|
+
await showStatus(cwd());
|
|
50
|
+
break;
|
|
51
|
+
|
|
52
|
+
case 'help':
|
|
53
|
+
case '--help':
|
|
54
|
+
case '-h':
|
|
55
|
+
case undefined:
|
|
56
|
+
console.log(AIDE);
|
|
57
|
+
break;
|
|
58
|
+
|
|
59
|
+
case 'version':
|
|
60
|
+
case '--version':
|
|
61
|
+
case '-v':
|
|
62
|
+
console.log(`aiad-sdd v${VERSION}`);
|
|
63
|
+
break;
|
|
64
|
+
|
|
65
|
+
default:
|
|
66
|
+
console.error(`\n Commande inconnue : "${command}"\n`);
|
|
67
|
+
console.log(AIDE);
|
|
68
|
+
exit(1);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
main().catch((err) => {
|
|
73
|
+
console.error('\n Erreur :', err.message);
|
|
74
|
+
exit(1);
|
|
75
|
+
});
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname } from 'node:path';
|
|
5
|
+
|
|
6
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
7
|
+
const __dirname = dirname(__filename);
|
|
8
|
+
const TEMPLATES_DIR = join(__dirname, '..', 'templates');
|
|
9
|
+
|
|
10
|
+
const COULEURS = {
|
|
11
|
+
vert: '\x1b[32m',
|
|
12
|
+
jaune: '\x1b[33m',
|
|
13
|
+
cyan: '\x1b[36m',
|
|
14
|
+
gris: '\x1b[90m',
|
|
15
|
+
gras: '\x1b[1m',
|
|
16
|
+
reset: '\x1b[0m',
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const AGENTS = [
|
|
20
|
+
{ fichier: 'CLAUDE-AI-ACT.md', nom: 'EU AI Act', description: 'Conformité Règlement (UE) 2024/1689' },
|
|
21
|
+
{ fichier: 'CLAUDE-RGPD.md', nom: 'RGPD', description: 'Privacy by Design, conformité RGPD' },
|
|
22
|
+
{ fichier: 'CLAUDE-RGAA.md', nom: 'RGAA', description: 'Accessibilité numérique RGAA 4.1 / WCAG 2.1' },
|
|
23
|
+
{ fichier: 'CLAUDE-RGESN.md', nom: 'RGESN', description: 'Écoconception de services numériques' },
|
|
24
|
+
];
|
|
25
|
+
|
|
26
|
+
export async function addGovernance(projetDir, options = {}) {
|
|
27
|
+
const { force = false, silencieux = false } = options;
|
|
28
|
+
|
|
29
|
+
if (!silencieux) {
|
|
30
|
+
console.log(`\n${COULEURS.cyan}${COULEURS.gras} AIAD — Agents de Gouvernance${COULEURS.reset}\n`);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const gouvernanceDir = join(projetDir, '.aiad', 'gouvernance');
|
|
34
|
+
if (!existsSync(gouvernanceDir)) {
|
|
35
|
+
mkdirSync(gouvernanceDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const sourceDir = join(TEMPLATES_DIR, '.aiad', 'gouvernance');
|
|
39
|
+
|
|
40
|
+
for (const agent of AGENTS) {
|
|
41
|
+
const source = join(sourceDir, agent.fichier);
|
|
42
|
+
const dest = join(gouvernanceDir, agent.fichier);
|
|
43
|
+
|
|
44
|
+
if (!existsSync(source)) {
|
|
45
|
+
console.log(` ${COULEURS.jaune}?${COULEURS.reset} ${agent.fichier} — template non trouvé`);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (existsSync(dest) && !force) {
|
|
50
|
+
console.log(` ${COULEURS.jaune}~${COULEURS.reset} ${agent.nom} ${COULEURS.gris}(existe déjà, ignoré)${COULEURS.reset}`);
|
|
51
|
+
} else {
|
|
52
|
+
const contenu = readFileSync(source, 'utf-8');
|
|
53
|
+
writeFileSync(dest, contenu, 'utf-8');
|
|
54
|
+
console.log(` ${COULEURS.vert}+${COULEURS.reset} ${agent.nom} — ${agent.description}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Créer l'index des agents de gouvernance
|
|
59
|
+
const indexContenu = `# Agents de Gouvernance AIAD — Tier 1
|
|
60
|
+
|
|
61
|
+
> Ces agents ont un **droit de veto** sur toute implémentation non conforme.
|
|
62
|
+
> Ils sont injectés dans chaque session de développement via le CLAUDE.md.
|
|
63
|
+
|
|
64
|
+
## Agents installés
|
|
65
|
+
|
|
66
|
+
| Agent | Fichier | Périmètre |
|
|
67
|
+
|-------|---------|-----------|
|
|
68
|
+
${AGENTS.map(a => `| **${a.nom}** | \`${a.fichier}\` | ${a.description} |`).join('\n')}
|
|
69
|
+
|
|
70
|
+
## Activation
|
|
71
|
+
|
|
72
|
+
Les agents de gouvernance sont activés par défaut dans le CLAUDE.md.
|
|
73
|
+
Pour désactiver temporairement un agent, commentez la ligne correspondante dans CLAUDE.md.
|
|
74
|
+
|
|
75
|
+
## Hiérarchie
|
|
76
|
+
|
|
77
|
+
\`\`\`
|
|
78
|
+
Constitution AIAD (valeurs immuables)
|
|
79
|
+
└── Agents de Gouvernance Tier 1 (droit de veto)
|
|
80
|
+
├── CLAUDE-AI-ACT → Tout composant IA
|
|
81
|
+
├── CLAUDE-RGPD → Toute donnée personnelle
|
|
82
|
+
├── CLAUDE-RGAA → Toute interface utilisateur
|
|
83
|
+
└── CLAUDE-RGESN → Toute décision technique
|
|
84
|
+
└── AGENT-GUIDE projet (contexte permanent)
|
|
85
|
+
└── SPEC (activation par tâche)
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
## Mise à jour
|
|
89
|
+
|
|
90
|
+
Les agents de gouvernance suivent le cycle ALIS (mise à jour à chaque pleine lune).
|
|
91
|
+
Pour mettre à jour : \`npx aiad-sdd gouvernance --force\`
|
|
92
|
+
`;
|
|
93
|
+
|
|
94
|
+
const indexDest = join(gouvernanceDir, '_index.md');
|
|
95
|
+
writeFileSync(indexDest, indexContenu, 'utf-8');
|
|
96
|
+
|
|
97
|
+
if (!silencieux) {
|
|
98
|
+
console.log(`\n ${COULEURS.vert}+${COULEURS.reset} Index de gouvernance créé`);
|
|
99
|
+
console.log(`\n ${COULEURS.gris}4 agents Tier 1 installés — droit de veto actif${COULEURS.reset}\n`);
|
|
100
|
+
}
|
|
101
|
+
}
|
package/lib/init.js
ADDED
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
2
|
+
import { join, relative } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { dirname } from 'node:path';
|
|
5
|
+
import { addGovernance } from './governance.js';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
const TEMPLATES_DIR = join(__dirname, '..', 'templates');
|
|
10
|
+
|
|
11
|
+
const COULEURS = {
|
|
12
|
+
vert: '\x1b[32m',
|
|
13
|
+
jaune: '\x1b[33m',
|
|
14
|
+
cyan: '\x1b[36m',
|
|
15
|
+
gris: '\x1b[90m',
|
|
16
|
+
gras: '\x1b[1m',
|
|
17
|
+
reset: '\x1b[0m',
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
function log(symbole, message) {
|
|
21
|
+
console.log(` ${symbole} ${message}`);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function logCreation(chemin) {
|
|
25
|
+
log(`${COULEURS.vert}+${COULEURS.reset}`, chemin);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function logExiste(chemin) {
|
|
29
|
+
log(`${COULEURS.jaune}~${COULEURS.reset}`, `${chemin} ${COULEURS.gris}(existe déjà, ignoré)${COULEURS.reset}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function logEcrase(chemin) {
|
|
33
|
+
log(`${COULEURS.jaune}!${COULEURS.reset}`, `${chemin} ${COULEURS.gris}(écrasé)${COULEURS.reset}`);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function ecrireFichier(destination, contenu, force = false) {
|
|
37
|
+
if (existsSync(destination) && !force) {
|
|
38
|
+
logExiste(relative(process.cwd(), destination));
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
const dir = dirname(destination);
|
|
42
|
+
if (!existsSync(dir)) {
|
|
43
|
+
mkdirSync(dir, { recursive: true });
|
|
44
|
+
}
|
|
45
|
+
writeFileSync(destination, contenu, 'utf-8');
|
|
46
|
+
if (force && existsSync(destination)) {
|
|
47
|
+
logEcrase(relative(process.cwd(), destination));
|
|
48
|
+
} else {
|
|
49
|
+
logCreation(relative(process.cwd(), destination));
|
|
50
|
+
}
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function copierDossierRecursif(source, destination, force = false) {
|
|
55
|
+
if (!existsSync(source)) return;
|
|
56
|
+
const elements = readdirSync(source);
|
|
57
|
+
for (const element of elements) {
|
|
58
|
+
const cheminSource = join(source, element);
|
|
59
|
+
const cheminDest = join(destination, element);
|
|
60
|
+
const stat = statSync(cheminSource);
|
|
61
|
+
if (stat.isDirectory()) {
|
|
62
|
+
if (!existsSync(cheminDest)) {
|
|
63
|
+
mkdirSync(cheminDest, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
copierDossierRecursif(cheminSource, cheminDest, force);
|
|
66
|
+
} else {
|
|
67
|
+
const contenu = readFileSync(cheminSource, 'utf-8');
|
|
68
|
+
ecrireFichier(cheminDest, contenu, force);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export async function init(projetDir, options = {}) {
|
|
74
|
+
const { sansGouvernance = false, force = false } = options;
|
|
75
|
+
|
|
76
|
+
console.log(`
|
|
77
|
+
${COULEURS.cyan}${COULEURS.gras} AIAD SDD Mode — Initialisation${COULEURS.reset}
|
|
78
|
+
${COULEURS.gris} Spec Driven Development pour Claude Code${COULEURS.reset}
|
|
79
|
+
`);
|
|
80
|
+
|
|
81
|
+
// 1. Structure .aiad/
|
|
82
|
+
console.log(`${COULEURS.gras} Structure .aiad/${COULEURS.reset}\n`);
|
|
83
|
+
|
|
84
|
+
const aiadDir = join(projetDir, '.aiad');
|
|
85
|
+
const dossiers = [
|
|
86
|
+
join(aiadDir, 'intents'),
|
|
87
|
+
join(aiadDir, 'intents', 'archive'),
|
|
88
|
+
join(aiadDir, 'specs'),
|
|
89
|
+
join(aiadDir, 'specs', 'archive'),
|
|
90
|
+
];
|
|
91
|
+
|
|
92
|
+
for (const dossier of dossiers) {
|
|
93
|
+
if (!existsSync(dossier)) {
|
|
94
|
+
mkdirSync(dossier, { recursive: true });
|
|
95
|
+
logCreation(relative(projetDir, dossier) + '/');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Copier les templates .aiad/
|
|
100
|
+
copierDossierRecursif(
|
|
101
|
+
join(TEMPLATES_DIR, '.aiad'),
|
|
102
|
+
aiadDir,
|
|
103
|
+
force
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// 2. Commandes Claude Code
|
|
107
|
+
console.log(`\n${COULEURS.gras} Commandes Claude Code (.claude/commands/)${COULEURS.reset}\n`);
|
|
108
|
+
|
|
109
|
+
copierDossierRecursif(
|
|
110
|
+
join(TEMPLATES_DIR, '.claude'),
|
|
111
|
+
join(projetDir, '.claude'),
|
|
112
|
+
force
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
// 3. CLAUDE.md
|
|
116
|
+
console.log(`\n${COULEURS.gras} Configuration agent (CLAUDE.md)${COULEURS.reset}\n`);
|
|
117
|
+
|
|
118
|
+
const claudeMdSource = join(TEMPLATES_DIR, 'CLAUDE.md');
|
|
119
|
+
const claudeMdDest = join(projetDir, 'CLAUDE.md');
|
|
120
|
+
|
|
121
|
+
if (existsSync(claudeMdDest) && !force) {
|
|
122
|
+
// Append SDD section si CLAUDE.md existe déjà
|
|
123
|
+
const contenuExistant = readFileSync(claudeMdDest, 'utf-8');
|
|
124
|
+
if (!contenuExistant.includes('# SDD Mode')) {
|
|
125
|
+
const sddSection = readFileSync(claudeMdSource, 'utf-8');
|
|
126
|
+
writeFileSync(claudeMdDest, contenuExistant + '\n\n' + sddSection, 'utf-8');
|
|
127
|
+
log(`${COULEURS.vert}+${COULEURS.reset}`, 'CLAUDE.md — section SDD Mode ajoutée');
|
|
128
|
+
} else {
|
|
129
|
+
logExiste('CLAUDE.md (section SDD Mode déjà présente)');
|
|
130
|
+
}
|
|
131
|
+
} else {
|
|
132
|
+
const contenu = readFileSync(claudeMdSource, 'utf-8');
|
|
133
|
+
ecrireFichier(claudeMdDest, contenu, force);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
// 4. Gouvernance
|
|
137
|
+
if (!sansGouvernance) {
|
|
138
|
+
console.log(`\n${COULEURS.gras} Agents de gouvernance${COULEURS.reset}\n`);
|
|
139
|
+
await addGovernance(projetDir, { force, silencieux: true });
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// 5. .gitignore update
|
|
143
|
+
const gitignorePath = join(projetDir, '.gitignore');
|
|
144
|
+
if (existsSync(gitignorePath)) {
|
|
145
|
+
const gitignore = readFileSync(gitignorePath, 'utf-8');
|
|
146
|
+
if (!gitignore.includes('.aiad/intents/archive')) {
|
|
147
|
+
writeFileSync(gitignorePath, gitignore + '\n# AIAD SDD Mode\n# (aucun fichier ignoré — tout est versionné)\n', 'utf-8');
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// Résumé
|
|
152
|
+
console.log(`
|
|
153
|
+
${COULEURS.cyan}${COULEURS.gras} SDD Mode initialisé avec succès !${COULEURS.reset}
|
|
154
|
+
|
|
155
|
+
${COULEURS.gras} Prochaines étapes :${COULEURS.reset}
|
|
156
|
+
|
|
157
|
+
${COULEURS.cyan}1.${COULEURS.reset} Rédiger le PRD ${COULEURS.gris}→ .aiad/PRD.md${COULEURS.reset}
|
|
158
|
+
${COULEURS.cyan}2.${COULEURS.reset} Définir l'architecture ${COULEURS.gris}→ .aiad/ARCHITECTURE.md${COULEURS.reset}
|
|
159
|
+
${COULEURS.cyan}3.${COULEURS.reset} Configurer l'agent ${COULEURS.gris}→ .aiad/AGENT-GUIDE.md${COULEURS.reset}
|
|
160
|
+
${COULEURS.cyan}4.${COULEURS.reset} Commencer à spécifier ${COULEURS.gris}→ /sdd-intent dans Claude Code${COULEURS.reset}
|
|
161
|
+
|
|
162
|
+
${COULEURS.gras} Commandes disponibles dans Claude Code :${COULEURS.reset}
|
|
163
|
+
|
|
164
|
+
${COULEURS.cyan}/sdd-init${COULEURS.reset} Cadrage initial (PRD + ARCHITECTURE)
|
|
165
|
+
${COULEURS.cyan}/sdd-intent${COULEURS.reset} Capturer une intention (Intent Statement)
|
|
166
|
+
${COULEURS.cyan}/sdd-spec${COULEURS.reset} Rédiger une SPEC depuis un Intent
|
|
167
|
+
${COULEURS.cyan}/sdd-gate${COULEURS.reset} Valider une SPEC (Execution Gate + SQS)
|
|
168
|
+
${COULEURS.cyan}/sdd-validate${COULEURS.reset} Valider le code produit par l'agent
|
|
169
|
+
${COULEURS.cyan}/sdd-drift-check${COULEURS.reset} Vérifier la synchronisation artefacts/code
|
|
170
|
+
${COULEURS.cyan}/aiad-retro${COULEURS.reset} Rétrospective de fin d'itération
|
|
171
|
+
${COULEURS.cyan}/aiad-intention${COULEURS.reset} Atelier d'Intention (rituel mensuel)
|
|
172
|
+
${COULEURS.cyan}/aiad-status${COULEURS.reset} État du projet SDD
|
|
173
|
+
|
|
174
|
+
${COULEURS.gris}Framework AIAD v1.5 — SDD Mode v1.1 — aiad.ovh${COULEURS.reset}
|
|
175
|
+
`);
|
|
176
|
+
}
|
package/lib/status.js
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
|
|
4
|
+
const COULEURS = {
|
|
5
|
+
vert: '\x1b[32m',
|
|
6
|
+
rouge: '\x1b[31m',
|
|
7
|
+
jaune: '\x1b[33m',
|
|
8
|
+
cyan: '\x1b[36m',
|
|
9
|
+
gris: '\x1b[90m',
|
|
10
|
+
gras: '\x1b[1m',
|
|
11
|
+
reset: '\x1b[0m',
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function check(condition) {
|
|
15
|
+
return condition
|
|
16
|
+
? `${COULEURS.vert}OK${COULEURS.reset}`
|
|
17
|
+
: `${COULEURS.rouge}--${COULEURS.reset}`;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function compterFichiersMd(dir) {
|
|
21
|
+
if (!existsSync(dir)) return 0;
|
|
22
|
+
return readdirSync(dir).filter(f => f.endsWith('.md') && !f.startsWith('_')).length;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function showStatus(projetDir) {
|
|
26
|
+
const aiadDir = join(projetDir, '.aiad');
|
|
27
|
+
|
|
28
|
+
if (!existsSync(aiadDir)) {
|
|
29
|
+
console.log(`
|
|
30
|
+
${COULEURS.rouge} SDD Mode non initialisé dans ce projet.${COULEURS.reset}
|
|
31
|
+
Lancez : ${COULEURS.cyan}npx aiad-sdd init${COULEURS.reset}
|
|
32
|
+
`);
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const hasPrd = existsSync(join(aiadDir, 'PRD.md'));
|
|
37
|
+
const hasArchi = existsSync(join(aiadDir, 'ARCHITECTURE.md'));
|
|
38
|
+
const hasGuide = existsSync(join(aiadDir, 'AGENT-GUIDE.md'));
|
|
39
|
+
const hasClaude = existsSync(join(projetDir, 'CLAUDE.md'));
|
|
40
|
+
const hasCommands = existsSync(join(projetDir, '.claude', 'commands'));
|
|
41
|
+
|
|
42
|
+
const nbIntents = compterFichiersMd(join(aiadDir, 'intents'));
|
|
43
|
+
const nbSpecs = compterFichiersMd(join(aiadDir, 'specs'));
|
|
44
|
+
const nbGouv = compterFichiersMd(join(aiadDir, 'gouvernance'));
|
|
45
|
+
|
|
46
|
+
// Vérifier le contenu du PRD (non-template)
|
|
47
|
+
let prdRempli = false;
|
|
48
|
+
if (hasPrd) {
|
|
49
|
+
const contenu = readFileSync(join(aiadDir, 'PRD.md'), 'utf-8');
|
|
50
|
+
prdRempli = !contenu.includes('[Titre fonctionnel court]');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
let archiRempli = false;
|
|
54
|
+
if (hasArchi) {
|
|
55
|
+
const contenu = readFileSync(join(aiadDir, 'ARCHITECTURE.md'), 'utf-8');
|
|
56
|
+
archiRempli = !contenu.includes('[max 5 principes]');
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let guideRempli = false;
|
|
60
|
+
if (hasGuide) {
|
|
61
|
+
const contenu = readFileSync(join(aiadDir, 'AGENT-GUIDE.md'), 'utf-8');
|
|
62
|
+
guideRempli = !contenu.includes('[Nom du projet]');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
console.log(`
|
|
66
|
+
${COULEURS.cyan}${COULEURS.gras} AIAD SDD Mode — État du projet${COULEURS.reset}
|
|
67
|
+
${COULEURS.gris} ${projetDir}${COULEURS.reset}
|
|
68
|
+
|
|
69
|
+
${COULEURS.gras} Artefacts fondamentaux${COULEURS.reset}
|
|
70
|
+
|
|
71
|
+
${check(hasPrd)} PRD.md ${prdRempli ? COULEURS.vert + 'rédigé' : hasPrd ? COULEURS.jaune + 'template' : COULEURS.gris + 'absent'}${COULEURS.reset}
|
|
72
|
+
${check(hasArchi)} ARCHITECTURE.md ${archiRempli ? COULEURS.vert + 'rédigé' : hasArchi ? COULEURS.jaune + 'template' : COULEURS.gris + 'absent'}${COULEURS.reset}
|
|
73
|
+
${check(hasGuide)} AGENT-GUIDE.md ${guideRempli ? COULEURS.vert + 'rédigé' : hasGuide ? COULEURS.jaune + 'template' : COULEURS.gris + 'absent'}${COULEURS.reset}
|
|
74
|
+
|
|
75
|
+
${COULEURS.gras} Cycle SDD${COULEURS.reset}
|
|
76
|
+
|
|
77
|
+
Intent Statements ${COULEURS.cyan}${nbIntents}${COULEURS.reset} actif(s)
|
|
78
|
+
SPECs ${COULEURS.cyan}${nbSpecs}${COULEURS.reset} active(s)
|
|
79
|
+
|
|
80
|
+
${COULEURS.gras} Infrastructure${COULEURS.reset}
|
|
81
|
+
|
|
82
|
+
${check(hasClaude)} CLAUDE.md ${hasClaude ? COULEURS.vert + 'configuré' : COULEURS.gris + 'absent'}${COULEURS.reset}
|
|
83
|
+
${check(hasCommands)} Commandes Claude ${hasCommands ? COULEURS.vert + 'installées' : COULEURS.gris + 'absentes'}${COULEURS.reset}
|
|
84
|
+
${check(nbGouv >= 4)} Gouvernance ${COULEURS.cyan}${nbGouv}${COULEURS.reset} agent(s) Tier 1
|
|
85
|
+
|
|
86
|
+
${COULEURS.gras} Maturité SDD${COULEURS.reset}
|
|
87
|
+
|
|
88
|
+
${getMaturite(hasPrd, prdRempli, hasArchi, archiRempli, hasGuide, guideRempli, nbIntents, nbSpecs)}
|
|
89
|
+
`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function getMaturite(hasPrd, prdRempli, hasArchi, archiRempli, hasGuide, guideRempli, nbIntents, nbSpecs) {
|
|
93
|
+
const score = [prdRempli, archiRempli, guideRempli, nbIntents > 0, nbSpecs > 0]
|
|
94
|
+
.filter(Boolean).length;
|
|
95
|
+
|
|
96
|
+
const niveaux = [
|
|
97
|
+
{ seuil: 0, label: 'Non initialisé', couleur: COULEURS.rouge },
|
|
98
|
+
{ seuil: 1, label: 'Démarrage', couleur: COULEURS.jaune },
|
|
99
|
+
{ seuil: 2, label: 'Cadrage', couleur: COULEURS.jaune },
|
|
100
|
+
{ seuil: 3, label: 'Opérationnel', couleur: COULEURS.cyan },
|
|
101
|
+
{ seuil: 4, label: 'Actif', couleur: COULEURS.vert },
|
|
102
|
+
{ seuil: 5, label: 'Complet', couleur: COULEURS.vert },
|
|
103
|
+
];
|
|
104
|
+
|
|
105
|
+
const niveau = niveaux[score];
|
|
106
|
+
const barre = '█'.repeat(score) + '░'.repeat(5 - score);
|
|
107
|
+
|
|
108
|
+
return `${niveau.couleur}${barre} ${niveau.label}${COULEURS.reset} ${COULEURS.gris}(${score}/5)${COULEURS.reset}`;
|
|
109
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aiad-sdd",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "AIAD SDD Mode — Spec Driven Development pour Claude Code. Framework de développement spec-first avec agents IA.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"aiad",
|
|
7
|
+
"sdd",
|
|
8
|
+
"spec-driven-development",
|
|
9
|
+
"claude-code",
|
|
10
|
+
"ai-agents",
|
|
11
|
+
"product-engineering",
|
|
12
|
+
"spec-first",
|
|
13
|
+
"context-engineering"
|
|
14
|
+
],
|
|
15
|
+
"author": "Steeve Evers <evers.steeve@gmail.com>",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/aiad-framework/aiad-sdd"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://aiad.ovh",
|
|
22
|
+
"bin": {
|
|
23
|
+
"aiad-sdd": "./bin/aiad-sdd.js"
|
|
24
|
+
},
|
|
25
|
+
"files": [
|
|
26
|
+
"bin/",
|
|
27
|
+
"lib/",
|
|
28
|
+
"templates/",
|
|
29
|
+
"README.md",
|
|
30
|
+
"LICENSE"
|
|
31
|
+
],
|
|
32
|
+
"engines": {
|
|
33
|
+
"node": ">=18.0.0"
|
|
34
|
+
},
|
|
35
|
+
"type": "module"
|
|
36
|
+
}
|