SDEG Kernel — le code comme modèle du domaine
Description fidèle de l'état actuel du noyau de software development engineering generative — sans proposition, sans correction.
1. Intention
Le projet vise un système de développement logiciel génératif. Son postulat : le besoin utile n'est jamais donné à l'avance — il se découvre par itération. Le logiciel n'est pas la réponse à une spécification ; il est le moyen d'éprouver une hypothèse de valeur.
La posture épistémique est herméneutique : chaque cycle de conception est une lecture du besoin, qui modifie la compréhension du besoin lui-même. L'objectif n'est pas la conformité à un cahier des charges, mais l'obtention rapide d'une solution minimale utilisable et utile, dont l'usage révèle la prochaine question.
Pour soutenir cette démarche, le noyau sdeg-kernel fait trois choses :
- Il matérialise le domaine en code. La machine d'états (
schema.js) est la définition exécutable du cycle de décision. Lire le code, c'est lire le modèle. - Il sépare strictement ce qui est décidé de ce qui est en cours. Tout artefact est soit LIVING (mutable), soit COLD (figé). Une porte franchie gèle le passé ; on n'y revient pas, on ouvre un nouveau grain.
- Il délègue la production à l'IA, garde la décision à l'humain. Les agents produisent les artefacts, le CLI fait avancer les états. Seul un humain déclenche une transition.
Hypothèse centrale du modèle
La connaissance utile émerge du cycle mesurable hypothèse → artefact minimal → mise en usage → mesure → décision. Le rôle du kernel est de rendre ce cycle court, traçable et non-destructif.
2. Vue d'ensemble du kernel
Le kernel est un petit outil Node.js (~1 200 lignes, sans dépendance externe) qui combine trois briques :
Déterministe
Un CLI (sdlc/sdlc.js), une machine d'états (sdlc/schema.js), un évaluateur de portes (sdlc/evaluator.js), une bibliothèque de validateurs (sdlc/validators.js). Aucune IA dans cette couche. C'est elle qui garde la mémoire et la forme.
Génératif
1 agent orchestrateur (.github/agents/coach-emergent) + 16 assistants spécialisés (.github/prompts/*). Chacun produit un artefact précis — EHS, LBC, OKR, feature spec, user story, code TDD. C'est eux qui portent le contenu et l'exploration.
Rituel
Hooks PowerShell (scripts/*.ps1) et hook git pre-commit (sdlc/install-hooks.js). Ils déclenchent les bons chargements au bon moment : démarrage de session, protection mémoire, refus de registre corrompu au commit.
Journal
Deux sources de vérité vivantes : le registre .product/sdlc-registry.json (état courant + historique) et le dossier d'événements .product/.events/*.md (un fichier markdown par transition, commité avec le registre).
Arborescence
sdeg-kernel/
├── sdlc/ ← noyau déterministe
│ ├── schema.js machine d'états (SSOT)
│ ├── validators.js 12 validateurs purs
│ ├── evaluator.js moteur de verdict (GO / NEEDS-REVIEW / NO-GO)
│ ├── sdlc.js CLI — seul mutateur d'état
│ ├── frontmatter.js parser YAML minimal
│ ├── install-hooks.js installeur git pre-commit
│ ├── SDLC.md doc humaine de la machine
│ └── __tests__/ 58 tests (node:test)
├── .github/
│ ├── agents/ ← 1 mode agent "Coach"
│ └── prompts/ ← 16 assistants spécialisés
├── meta/
│ └── template-eo.md modèle d'Étude d'Opportunité
├── scripts/ ← hooks PowerShell (session, safety)
├── docs/
│ ├── specs/ specs d'implémentation (ex : vague 3)
│ └── as-is/ cette description (modèle as-is)
├── README.md · GUIDE.html · LICENSE
3. Le domaine, tel qu'il est nommé
Le kernel distingue trois types d'objets et cinq méta-états. C'est la totalité du vocabulaire formel.
Types d'objets (schema.js:TYPES)
| Code | Nom | Granularité | Parent requis |
|---|---|---|---|
be | Business Epic | ≥ 2 trimestres, impact multi-équipes | — |
fe | Feature | 1 PI (programme increment) | une BE |
us | Récit (User Story) | 1 sprint | une FE |
La filiation est obligatoire descendante et vérifiée à la création par le CLI (sdlc.js:PARENT_RULES, ligne 276). Un objet en statut terminal (TERMINE, PIVOTED, LIVRE, ARCHIVED, VALIDE) ne peut plus servir de parent à un nouvel objet.
Méta-états (schema.js:META)
| Méta | Heat | Sens | Badge |
|---|---|---|---|
| NOT_STARTED | cold | Ambition non engagée | ○ |
| IN_PROGRESS | living | Artefact mutable — la décision n'est pas prise | ● |
| BLOCKED | living-frozen | Gelé par dépendance externe, pas abandonné | ◐ |
| DONE | cold | Décision prise, artefacts figés | ✓ |
| ARCHIVED | cold | Déprioritisé, historique préservé | ✕ |
Principe LIVING / COLD
Le heat est dérivé du méta-état. Un artefact LIVING est librement modifiable ; un artefact COLD est considéré gelé — si on doit le changer, on ouvre un nouveau cycle (pivot, persévère). Cette règle est la pierre angulaire du modèle : elle interdit la réécriture silencieuse du passé.
4. La machine d'états
Chaque type a son propre graphe de statuts. Les arêtes (transitions) portent le nom de la porte décisionnelle, les prérequis humains, les artefacts gelés, et — optionnellement — des invariants et checks exécutables.
Business Epic — 10 statuts
NOT_STARTED ──P1──▶ REVUE_BUSINESS ──P2──▶ CADRAGE_EN_COURS ──P3──▶ FABRICATION_MVP
│
▼
REVUE_MVP ──P10──▶ TERMINE
├─────────▶ PERSEVERE ──▶ (nouveau cycle)
└─────────▶ PIVOTED
BLOCKED et ARCHIVED accessibles depuis la plupart des statuts intermédiaires.
Feature — 8 statuts
NOT_STARTED ──P4──▶ ANALYSE ──P4-DOR──▶ PRET_FABRICATION ──Sprint──▶ FABRICATION
│
▼
VALIDATION ──P8──▶ PRET_LIVRAISON
│
▼
DEPLOIEMENT ──P9──▶ LIVRE
Récit — 8 statuts
NOT_STARTED ──P5-start──▶ AFFINAGE ──P5-DOR──▶ PRET_DOR ──▶ DEV ──P6-PR──▶ DEV_TERMINE
│
▼ Démo PO
VALIDATION ──P6-DoD──▶ VALIDE
│
└───▶ DEV (defect)
La liste complète se trouve en annexe. Les transitions sont définies dans schema.js:TRANSITIONS (lignes 105-536). Chaque entrée a la forme :
{
gate: "P4-DOR — DOR Feature",
preconditions: [ ... liste humaine ... ], // checklist affichée au move
freeze: [ ... ], // libellés des artefacts gelés
invariants: [ { kind, id, ...params } ], // vérifications parent-enfant
checks: [ { kind, id, path, ... } ], // vérifications fichiers
}
5. Portes et verdicts
Une transition est évaluée en trois temps par evaluator.js:evaluateGate :
- Construire le contexte (
buildContext) : résoudre parent et enfants dans le registre. - Exécuter les invariants puis les checks dans l'ordre, chacun via son validateur (
runOne). - Agréger les résultats et calculer un verdict (
computeVerdict).
Règle de verdict
| Composition | Verdict | Effet sur move |
|---|---|---|
| 0 fail, 0 warn | GO | Checklist humaine puis transition. |
| 0 fail, ≥ 1 warn | NEEDS-REVIEW | Checklist humaine avec prompt d'arbitrage explicite. |
| ≥ 1 fail | NO-GO | Refus, sauf --force (tracé dans l'historique). |
État de couverture (après vague 3)
| Entité | Portes automatisées | Portes encore descriptives |
|---|---|---|
| BE | P2, P3, P10 3 | P1, P10-term/persévère/pivot, blocages, archives (15) |
| FE | P4, P4-DOR, P7, P8, P9-init, P9-term 6 | Sprint-start, archives (3) |
| US | P5-start, P5-DOR, sprint-dev, P6-PR, P6-DoD 5 | PO-demo, defect, archives (4) |
14 / 42 portes automatisées à ce jour.
Observation (description, pas correction)
Le vocabulaire des portes (P1 → P10) et des prérequis reflète une gouvernance de grande entreprise (COMEX, homologation, PI planning). Ce lexique est hérité et apparaît en clair dans schema.js et dans les preconditions. Voir §10 — Perspectives.
6. La bibliothèque de validateurs
Les validateurs sont des fonctions pures (spec, ctx) → CheckResult. Ils ne mutent rien, ne font pas d'appel réseau, lisent uniquement le système de fichiers. Ils sont enregistrés dans l'objet VALIDATORS (validators.js:246).
Checks fichier
| Kind | Paramètres | Rôle |
|---|---|---|
fileExists | path | Le fichier existe au chemin interpolé. |
fileNotEmpty | path, minBytes? | Le fichier fait ≥ N octets. |
fileContains | path, pattern, flags? | Le contenu match une regex. |
Checks frontmatter (YAML en tête de fichier)
| Kind | Paramètres | Rôle |
|---|---|---|
frontmatterHas | path, keys[] | Toutes les clés présentes et non vides. |
frontmatterIn | path, key, allowed[] | Valeur dans une liste close. |
frontmatterRegex | path, key, pattern | Valeur match une regex (ex. ^\d+$). |
Invariants parent-enfant
| Kind | Paramètres | Rôle |
|---|---|---|
parentExists | — | L'objet a bien un parent référencé. |
parentStatusIn | allowed[] | Le parent est dans un statut compatible. |
allChildrenStatusIn | allowed[] | Tous les enfants sont dans la liste (warn si 0 enfant). |
anyChildStatusIn | allowed[] | Au moins un enfant satisfait. |
noChildInStatus | forbidden[] | Aucun enfant dans les statuts interdits. |
minChildCount | min | Au moins N enfants. |
Deux utilitaires clés
interpolate(template, obj)— substitue{id},{type}… dans un chemin, l'id étant forcé en minuscule.safeResolve(projectRoot, relPath)— résout un chemin relatif et renvoie{ abs, inside, relPath }. Depuis la vague 3, un chemin hors projet ne jette plus d'erreur : les validateurs retournentwarn(verdictNEEDS-REVIEW), l'humain arbitre viamove --force.
7. CLI et registre
sdlc/sdlc.js est le seul mutateur d'état autorisé. Toute modification directe de sdlc-registry.json est une violation (le hook git pre-commit détecte les incohérences).
Commandes
| Commande | Effet |
|---|---|
status | Tableau de bord : tous les objets du registre, regroupés par type, avec statut, porte, heat. |
init <type> <id> <titre> [--parent X] | Crée un objet en NOT_STARTED. Refuse si parent absent / mauvais type / terminal. |
check <id> | Liste les transitions possibles depuis le statut courant ; affiche pour chacune prérequis, artefacts à geler, et évaluation automatisée avec verdict. |
move <id> <statut> [--force] [--message "..."] [--no-git] | Transitionne : évalue la porte, demande confirmation interactive de la checklist humaine (sauf --force), met à jour le registre, écrit l'événement, commite. |
log <id> | Historique chronologique des transitions d'un objet, avec notes et artefacts gelés. |
validate | Vérifie la cohérence globale : types, statuts, filiation, alignement meta_status. |
Traces persistées
.product/
├── sdlc-registry.json état courant + history[] par objet
└── .events/
└── YYYY-MM-DD-sdlc-<id>-<to>.md un fichier par transition, commité
Chaque entrée d'history contient : from, to, date, gate, message, frozen[], forced, et — si la porte était automatisée — un checks_snapshot[] complet avec le verdict.
Propriété recherchée : auditabilité totale
À tout moment on peut rejouer la logique : sdlc-registry.json donne l'état, les commits donnent la chronologie, les événements donnent le détail narratif. Rien n'est effacé, seulement gelé.
8. La boucle IA / déterministe
Le kernel orchestre deux régimes de travail qui ne se remplacent pas :
┌──────────────── DÉTERMINISTE ─────────────────┐
│ sdlc.js (état) schema.js (forme) │
│ evaluator.js (verdict) hooks (rituels) │
│ │
│ · impose la forme │
│ · garde la mémoire │
│ · bloque si incohérence │
└────────────────────┬──────────────────────────┘
│ fournit le contexte
▼
┌──────────────── GÉNÉRATIF (IA) ───────────────┐
│ coach-emergent (orchestrateur) │
│ 16 #assistants (producteurs d'artefacts) │
│ │
│ · explore le besoin │
│ · rédige l'artefact LIVING │
│ · ne fait JAMAIS avancer un état │
└───────────────────────────────────────────────┘
Conséquence pratique : l'IA écrit dans les fichiers .md du projet (EHS, LBC, story…). Le CLI lit ces fichiers via les validateurs, calcule un verdict, et seul un humain décide de faire bouger le statut.
Ce partage est intentionnel. La génération rapide par l'IA crée la matière de l'hypothèse ; la machine d'états crée la forme de la décision. L'un sans l'autre, ça dérape vers soit un bureaucratie sans substance, soit un flot d'idées sans traçabilité.
9. Lecture pour audit et conformité
Cette section est un parcours de revue. Chaque étape identifie un fichier, ce qu'on y cherche, et un critère de conformité.
sdlc/schema.js
Lire META (ligne 23), TYPES (32), STATES (46). Critère : les termes utilisés sont compréhensibles sans jargon d'entreprise, ou explicitement documentés dans SDLC.md.
schema.js:TRANSITIONS (ligne 105)
Vérifier que chaque arête a un gate, des preconditions et — si la porte est critique — des checks ou invariants. Critère : aucune transition n'a de prérequis humain vide qui masque une vraie exigence.
sdlc/validators.js
Chaque validateur est pur (pas de mutation, pas de réseau, fs en lecture seule). Critère : signature homogène (spec, ctx) → CheckResult ; enregistrement unique dans VALIDATORS (ligne 246) ; pas d'exception non attrapée qui remonterait en NO-GO trompeur.
sdlc/evaluator.js:computeVerdict (ligne 71)
Trois branches : fail > 0 → NO-GO, warn > 0 → NEEDS-REVIEW, sinon GO. Critère : la priorité fail > warn > pass est explicite et testée (evaluator.test.js lignes 18-26).
sdlc/sdlc.js:cmdMove (ligne 358) et executeTransition (450)
Toute écriture dans sdlc-registry.json passe par saveRegistry. Critère : aucune autre partie du code n'écrit ce fichier ; l'--force est tracé dans history[].forced = true.
sdlc.js:PARENT_RULES (ligne 276) et cmdValidate (553)
Critère : FE exige un parent BE, US exige un parent FE ; un parent en statut terminal est refusé. validate rejoue ces règles sur tout le registre.
sdlc.js:executeTransition (ligne 450) + writeEvent (509)
Chaque transition produit (a) une entrée history, (b) un fichier .product/.events/*.md, (c) un commit git. Critère : les trois sont alignés et reproductibles.
sdlc/__tests__/
node --test sdlc/__tests__/*.test.js doit passer à vert (58 tests actuellement). Critère : chaque porte automatisée a au moins un test NO-GO et un test GO ; le chemin hors projet donne NEEDS-REVIEW.
sdlc/install-hooks.js
Critère : le hook pre-commit refuse un registre incohérent ; l'installation est idempotente.
Critère : pas de package.json avec dépendances runtime ; le kernel tourne avec Node ≥ 18 standard. Zéro surface d'attaque supply-chain, zéro node_modules.
10. Perspectives — ce qu'on observe, sans rien changer
Cette section décrit les tensions visibles dans le code tel qu'il est. Elle ne propose pas de correction ; elle rend lisible ce que le modèle actuel fait vivre.
10.1 — Héritage lexical d'une gouvernance d'entreprise
Les portes s'appellent P1 à P10, avec des prérequis comme « Décision COMEX tracée », « Enveloppe budgétaire confirmée par sponsor », « PI planning », « accord homologation ». Ce vocabulaire suppose un contexte d'organisation structuré (sponsor, COMEX, filière pilote, architecture d'entreprise). Dans un contexte différent — équipe autonome, produit émergent, cycle court — certaines portes sont vides de sens, d'autres manquent.
10.2 — Granularité fixe BE / FE / US
La hiérarchie est imposée à 3 niveaux obligatoires avec filiation stricte (PARENT_RULES). Pour un produit naissant où la valeur n'est pas encore découpée en PIs, cette structure force un habillage artificiel. À l'inverse, pour un système complexe, elle peut être trop plate (pas de notion de composant, de capability, de thème).
10.3 — 10 portes, ~42 transitions, 14 automatisées
Le ratio est significatif : un tiers des portes sont réellement exécutables. Les deux autres tiers sont des checklists humaines, utiles pour guider mais sans garde-fou machine. Ce déséquilibre reflète une hypothèse implicite : la plupart des décisions ne sont pas mécanisables. C'est peut-être vrai, peut-être le signe qu'il manque des invariants encore non formulés.
10.4 — Tension entre « minimal utile » et « 10 portes »
L'intention du système est d'aboutir vite à une solution minimale utilisable. Le chemin le plus court dans la machine d'états pour livrer une FE est :
BE.NOT_STARTED → REVUE_BUSINESS → CADRAGE_EN_COURS → FABRICATION_MVP
puis pour une FE : NOT_STARTED → ANALYSE → PRET_FABRICATION → FABRICATION → VALIDATION → PRET_LIVRAISON → DEPLOIEMENT → LIVRE,
soit 10+ transitions humaines avant un premier déploiement. La rapidité recherchée est donc pour l'instant tributaire de la discipline humaine à ne pas sur-instrumenter les premières itérations.
10.5 — L'IA produit, l'humain décide, mais le modèle du besoin est à l'humain
Les assistants IA (16 prompts spécialisés) couvrent la production (rédiger une EHS, découper en features, écrire une story TDD). Aucun n'est chargé de remettre en cause l'hypothèse, de proposer un grain différent, ou de détecter une incohérence épistémique. La boucle herméneutique — lecture du besoin qui modifie la compréhension du besoin — repose entièrement sur l'humain et sur le Coach.
10.6 — COLD irréversible, donc tout nouveau cycle est coûteux
La règle LIVING/COLD est forte : un artefact gelé ne se modifie pas. Si la compréhension du besoin change, il faut ouvrir un nouveau grain (pivot, persévère, nouvelle BE). Cela protège la traçabilité, mais rend chaque pivot coûteux en fichiers, en références, en registre. Un mode fork d'artefact ou un mécanisme de cycle N+1 explicite n'existe pas aujourd'hui ailleurs que dans la transition REVUE_MVP → PERSEVERE → FABRICATION_MVP.
Observation de synthèse
Le kernel actuel est un outil solide de gouvernance déterministe greffé sur un atelier IA de production d'artefacts. Sa forme reflète une organisation d'entreprise structurée. Son intention (génératif, herméneutique, minimal utile) est plus ambitieuse que ce que la forme actuelle facilite. Cette section ne conclut rien, elle constate.
Annexe A — Fichiers du kernel
| Fichier | LOC | Rôle |
|---|---|---|
sdlc/schema.js | 559 | SSOT : META, TYPES, STATES, TRANSITIONS + helpers. |
sdlc/validators.js | 279 | 12 validateurs purs + interpolate et safeResolve. |
sdlc/evaluator.js | 117 | Moteur de verdict evaluateGate + buildContext. |
sdlc/sdlc.js | 658 | CLI, seul mutateur ; commandes status, init, check, move, log, validate. |
sdlc/frontmatter.js | — | Parser YAML minimal (scalaires, listes inline, objets). |
sdlc/install-hooks.js | — | Installe .git/hooks/pre-commit (cohérence registre). |
sdlc/SDLC.md | — | Documentation humaine de la machine d'états. |
sdlc/__tests__/validators.test.js | — | 22 tests validateurs. |
sdlc/__tests__/evaluator.test.js | — | 29 tests évaluateur + portes. |
sdlc/__tests__/frontmatter.test.js | — | 7 tests parser. |
Annexe B — Toutes les transitions
BE — Business Epic
| De | Vers | Porte | Auto |
|---|---|---|---|
| NOT_STARTED | REVUE_BUSINESS | P1 — Réception EO | humain |
| NOT_STARTED | ARCHIVED | Déprioritisation portfolio | humain |
| REVUE_BUSINESS | CADRAGE_EN_COURS | P2 — GO Cadrage (COMEX) | checks |
| REVUE_BUSINESS | BLOCKED / ARCHIVED | Blocage / NO-GO Cadrage | humain |
| CADRAGE_EN_COURS | FABRICATION_MVP | P3 — GO Fabrication | checks |
| CADRAGE_EN_COURS | BLOCKED / ARCHIVED | Blocage / NO-GO Fabrication | humain |
| FABRICATION_MVP | REVUE_MVP | P10 — Fin MVP | inv+checks |
| FABRICATION_MVP | BLOCKED / ARCHIVED | Blocage / Abandon MVP | humain |
| REVUE_MVP | TERMINE / PERSEVERE / PIVOTED / ARCHIVED | P10 — Décision terminale | humain |
| PERSEVERE | FABRICATION_MVP | Relancement cycle MVP | humain |
| BLOCKED | (retour 3 statuts) / ARCHIVED | Déblocage | humain |
FE — Feature
| De | Vers | Porte | Auto |
|---|---|---|---|
| NOT_STARTED | ANALYSE | P4 — Engagement PI Planning | invariants |
| NOT_STARTED | ARCHIVED | Déprioritisation backlog | humain |
| ANALYSE | PRET_FABRICATION | P4-DOR — DOR Feature | inv+checks |
| ANALYSE | ARCHIVED | Déprioritisation en analyse | humain |
| PRET_FABRICATION | FABRICATION | Sprint Start | humain |
| FABRICATION | VALIDATION | P7 — Validation intégration | invariants |
| VALIDATION | PRET_LIVRAISON | P8 — Homologation | checks |
| PRET_LIVRAISON | DEPLOIEMENT | P9-init — Déploiement initié | checks |
| DEPLOIEMENT | LIVRE | P9-term — Feature livrée | inv+checks |
US — Récit
| De | Vers | Porte | Auto |
|---|---|---|---|
| NOT_STARTED | AFFINAGE | P5-start — Entrée sprint backlog | invariants |
| NOT_STARTED | ARCHIVED | Archivage backlog | humain |
| AFFINAGE | PRET_DOR | P5-DOR — DOR Récit | inv+checks |
| AFFINAGE | ARCHIVED | Récit refusé en affinage | humain |
| PRET_DOR | DEV | Sprint — Dev start | invariants |
| DEV | DEV_TERMINE | P6-PR — PR mergé | inv+checks |
| DEV_TERMINE | VALIDATION | Démo PO | humain |
| VALIDATION | VALIDE | P6-DoD — DoD Récit | checks |
| VALIDATION | DEV | Retour dev (defect) | humain |