diff --git a/.claude/review-guidelines.md b/.claude/review-guidelines.md new file mode 100644 index 00000000..a1136af3 --- /dev/null +++ b/.claude/review-guidelines.md @@ -0,0 +1,45 @@ +# Guidelines de revue — TalkControl + +Dettes **éliminées par le plan d'amélioration 2026-07** (`docs/improvements/`). Une revue de code +sur ce repo doit empêcher leur retour. Utilisables manuellement avec `/code-review` (pas de revue +CI automatisée : la politique Actions de l'org n'autorise que les actions github-owned — voir IMP-011). + +## Bloquant (dette qui revient) + +- **Casts `as` sur les payloads du bus** : consommer via `TcEventMap`/`PayloadFor` + (`src/common/event-bus/events.ts`), jamais `data as {...}` (IMP-007). Les seuls casts tolérés + sont les casts-frontière documentés inline (socket.io, pass-through plugins, `currentSlide as +Slide` du moteur) — un nouveau cast non documenté est un défaut. +- **`any` / `as any`** : interdits (le `this as any` historique a été résolu par une interface — + faire pareil). +- **`console.*` bruts** : passer par `src/common/services/logger.ts`. Exception assumée : + `get-started.ts` (bannière CLI). +- **Secrets** : aucun token dans un fichier versionné ; `config/config.json` reste gitignored ; + token ngrok = `NGROK_AUTHTOKEN` (IMP-003). Aucune URL ngrok personnelle. +- **CORS `*`** : les 3 surfaces (Express, socket.io, Vite dev server) passent par l'allowlist + `buildCorsOptions` (`src/common/services/cors.ts`) — tout retour d'un `*` est une régression (IMP-003). +- **`innerHTML` non contrôlé** : seul usage légitime = `unsafeHTML` explicite sur contenu déjà + filtré par l'anti-SSRF (notes). Pas de nouvelle injection de HTML brut. +- **Événement bus non typé** : tout nouvel événement s'ajoute à `TcEventMap` ; pas de + `on('nouvelEvent', …)` hors map. Pas de surcharges sur `on`/`broadcast` (le fallback `string` + avale silencieusement les erreurs de payload — IMP-007). +- **Anti-SSRF contourné** : toute cible patcher/proxy passe par + `src/server/services/presentation-url.ts` (IMP-001). Pas de fetch/proxy d'URL non validée. +- **Broadcast hors room** : toute émission serveur reste dans `session:` (`io.to`), jamais + globale (IMP-002). +- **Seuils de coverage baissés** ou tests supprimés pour faire passer la CI. + +## Bloquant (contraintes de stack) + +- **Décorateurs Lit standards** : legacy uniquement (`experimentalDecorators: true`) — les + standards cassent au runtime avec oxc/Rolldown + Chromium (IMP-006). +- **Réintroduction** de webpack, babel, mocha, redux, `--legacy-peer-deps` : migration terminée. +- **e2e `workers > 1`** : interdit tant que le store serveur est global (IMP-002). +- **Action GitHub tierce** dans un workflow : la politique org n'autorise que `actions/*`. + +## À challenger (pas bloquant, mais motiver) + +- Renommage de variables/clés existantes sans nécessité fonctionnelle. +- Nouvelle dépendance (KISS : le plan en a retiré plus qu'ajouté). +- Nouvelle abstraction à un seul site d'usage (cf. IMP-009 : la dédup à un appelant unique a été + refusée). diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 00000000..b000d9a6 --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,37 @@ +{ + "permissions": { + "allow": [ + "Bash(npx tsc *)", + "Bash(npm run *)", + "Bash(npm test)", + "Bash(npm test *)", + "Bash(NODE_ENV=test npm test)", + "Bash(NODE_ENV=test npm test *)", + "Bash(NODE_ENV=test npm run *)", + "Bash(./scripts/verify.sh)", + "Bash(npm audit)", + "Bash(npm audit *)", + "Bash(npm ci)", + "Bash(npm install *)", + "Bash(npm ls *)", + "Bash(npm view *)", + "Bash(npm info *)", + "Bash(npm outdated *)", + "Bash(npx vitest *)", + "Bash(npx playwright *)", + "Bash(npx tsx *)", + "Bash(git status *)", + "Bash(git diff *)", + "Bash(git log *)", + "Bash(git show *)", + "Bash(git branch *)", + "Bash(git checkout *)", + "Bash(git add *)", + "Bash(git commit *)", + "Bash(git fetch *)", + "Bash(git pull *)", + "Bash(git stash *)", + "mcp__playwright" + ] + } +} diff --git a/.gitignore b/.gitignore index 86ccbfc3..0a0ae15a 100644 --- a/.gitignore +++ b/.gitignore @@ -71,3 +71,9 @@ test/**/__screenshots__/ # Local config: may carry the ngrok token and is rewritten at runtime with # tunnel urls — recreated from config/config.example.json by npm install config/config.json + +# Claude Code : seuls settings.json et review-guidelines.md sont versionnés, +# le reste de .claude/ est de l'état local de session +.claude/* +!.claude/settings.json +!.claude/review-guidelines.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..8172c40a --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,19 @@ +# TalkControl — instructions agents (tous outils) + +Ce fichier s'applique à tout agent de code (Gemini/Antigravity, Claude Code, autres). +**Le contexte projet complet est dans [CLAUDE.md](CLAUDE.md) — lis-le en premier**, il vaut +pour tous les outils (le nom est historique, pas une exclusivité). + +L'essentiel, si tu ne lis qu'ici : + +- Télécommande de présentations reveal.js : 3 services (tc-server :3001, controller :3000, + showcase :3002), event-bus typé `TcEventMap`, store maison (pas Redux), Lit en décorateurs + **legacy** (ne pas passer aux décorateurs standards — cassent au runtime). +- **Validation complète avant commit** : `./scripts/verify.sh` (tsc, lint:check, coverage avec + seuils, e2e, build, audit, docs). Rapide pendant le dev : `npx tsc --noEmit`, + `npm run lint:check`, `NODE_ENV=test npm test`, `npm run test:components`. +- Contrat iso-fonctionnel : `docs/migration/golden-path.md`, couvert par `e2e/golden-path/`. +- Commits Gitmoji en français, branches `feat|fix|chore|test/`, KISS/SOLID/TDD. +- Ne pas renommer l'existant sans raison fonctionnelle ; ne jamais committer + `config/config.json` ni un secret ; ne jamais baisser un seuil de coverage. +- Guidelines de revue : `.claude/review-guidelines.md`. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..2f339336 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,91 @@ +# TalkControl — contexte agent + +Télécommande de présentations reveal.js. Une instance = **un présentateur à la fois** (IMP-002). + +## Architecture (3 services) + +| Service | Port | Rôle | +| ---------------------- | ---- | -------------------------------------------------------------------------------- | +| tc-server | 3001 | Express 5 + socket.io, patcher/proxy des présentations, moteur d'état des slides | +| controller + component | 3000 | Vite dev server, layouts (presenter, on-stage…) et web components Lit | +| showcase | 3002 | Présentation reveal.js d'exemple (http-server) | + +Flux : controller ↔ serveur ↔ component via **event-bus typé** (`src/common/event-bus/`, +`TcEventMap`, 21 événements — IMP-007). Pairing par session socket.io : token UUID opaque `?s=`, +« le secret est l'id », rooms `session:` (IMP-002). Store serveur **maison** (~35 lignes, +`src/server/store/`), union discriminée `TcAction` — Redux a été retiré (IMP-008). Plugins +auto-découverts par `import.meta.glob('./input/*/index.ts')`, activation pilotée par +`config/plugins.json` (IMP-010). + +## Stack + +Node 24 (`.nvmrc`), TypeScript strict, Vite 8 (Rolldown/oxc), Vitest 4 (jsdom + browser mode +Chromium), Playwright e2e, Lit 3, Express 5, socket.io 4, Bulma 1, VitePress 2-alpha + TypeDoc. +**Plus de** webpack, babel, mocha, redux : migration v0.5.0 terminée, n'en réintroduis aucun. + +## Validation + +Pendant le dev (rapide) : + +```bash +npx tsc --noEmit # 0 erreur +npm run lint:check # 0 erreur (lint = --fix, ne pas l'utiliser pour valider) +NODE_ENV=test npm test # suite jsdom +npm run test:components # suite browser (Chromium réel) +``` + +Avant commit / PR — **validation complète, miroir de la CI** (`.github/workflows/develop.yml`) : + +```bash +./scripts/verify.sh +``` + +soit : `tsc --noEmit`, `lint:check`, `NODE_ENV=test npm run coverage` (jsdom + browser + merge — +les suites tournent DANS coverage, ne pas les relancer à part : IMP-013), `test:e2e` (Playwright +démarre lui-même les 3 services), `build`, `npm audit` (0 vulnérabilité attendu), `docs:build`. + +## Contrat iso-fonctionnel + +`docs/migration/golden-path.md` fait foi : le comportement utilisateur décrit là est le contrat, +couvert par les e2e (`e2e/golden-path/`). Refactors internes libres tant que les suites passent. + +## Conventions + +- Commits **Gitmoji, messages en français** (voir l'historique récent) ; branches `feat|fix|chore|test/`. +- KISS d'abord, SOLID, TDD quand la tâche s'y prête. +- **Ne pas renommer** les variables/clés existantes sans nécessité fonctionnelle + (ex. `config.logger.redux` est un nom de clé de config conservé exprès). +- Secrets : `config/config.json` est **gitignored** (recréé par le postinstall depuis + `config.example.json`) — ne jamais le committer, ne jamais y référencer un vrai token. + Token ngrok via `NGROK_AUTHTOKEN`. Aucune URL ngrok personnelle dans les fichiers versionnés. +- Ne jamais baisser un seuil de coverage (80/90/70/80 lignes/fonctions/branches/statements, + appliqués au merge) pour faire passer la CI. +- Revue : guidelines projet dans `.claude/review-guidelines.md` (dettes éliminées par le plan + d'amélioration — à ne pas laisser revenir). Utilisable avec `/code-review`. + +## Pièges connus (vécus, pas théoriques) + +- **Décorateurs Lit LEGACY** (`experimentalDecorators: true`), PAS standards : oxc/Rolldown ne + lowere pas les décorateurs TC39 et Chromium ne les exécute pas nativement → `SyntaxError` runtime. + `useDefineForClassFields: false` requis. Ne pas « moderniser » vers les décorateurs standards (IMP-006). +- `NODE_ENV=test` obligatoire pour `npm test` et `npm run coverage`. +- `vitest run | tail` masque le code de sortie (exit = celui de `tail`) → utiliser `PIPESTATUS`. +- e2e : `workers: 1` obligatoire (store serveur global partagé — IMP-002) ; flake connu : + `15-remote-control` « onglet restauré » peut échouer au 1er run puis repasser. +- e2e en local : `reuseExistingServer` ne sonde QUE le port 3000 — un Vite résiduel là suffit + pour que Playwright ne démarre NI tc-server (:3001) NI showcase (:3002) → ~11 échecs en masse. + Avant d'incriminer le code : `lsof -iTCP:3000,3001,3002 -sTCP:LISTEN` et tuer les résidus. +- Cache Vite pollué → e2e qui cassent en masse (`Unexpected token 'export'`) : + `rm -rf node_modules/.vite` avant de chercher plus loin. +- Alias de paths : source unique `vite.aliases.ts` (miroir de `tsconfig.json` `paths`), partagée + par les 3 configs Vite/Vitest — modifier les deux ensemble. +- `import.meta.glob` est Vite-only : le plugin-loader est client-only, ne pas l'importer côté serveur. +- Politique GitHub Actions de l'org TalkControl : **actions `actions/*` github-owned uniquement**, + aucune action tierce Marketplace ne s'exécutera (élargissement = admin org). +- Doc API : TypeDoc (via `scripts/jsdoc-build.mjs`), pas jsdoc — jsdoc ne parse pas le TypeScript (IMP-014). + +## Protocole d'exécution d'une étape du plan + +Voir `docs/improvements/README.md` (branche → lecture du step → TDD → validation → commits +Gitmoji → documentation → rollback). Décisions structurantes tracées dans +`docs/improvements/decisions.md` (`IMP-XXX`). diff --git a/docs/improvements/README.md b/docs/improvements/README.md index eefc6b39..f08440bf 100644 --- a/docs/improvements/README.md +++ b/docs/improvements/README.md @@ -16,14 +16,16 @@ Chaque étape suit ce cycle. Les fichiers `step-XX` ne le répètent pas — il 1. **Branche** : `git checkout develop && git pull && git checkout -b /step-XX-` (type = `feat|fix|chore|test` selon l'étape). 2. **Lire le fichier d'étape en entier** avant de toucher au code. Vérifier que l'état actuel décrit correspond toujours au code (le plan peut avoir vieilli — si divergence, le signaler et adapter, ne pas appliquer aveuglément). 3. **TDD quand l'étape s'y prête** : écrire/adapter les tests d'abord, les voir échouer, implémenter. -4. **Validation systématique** avant commit (en plus des validations spécifiques de l'étape) : +4. **Validation systématique** avant commit (en plus des validations spécifiques de l'étape) — + `./scripts/verify.sh` (étape 17) enchaîne le tout, miroir de la CI : ```bash - npx tsc --noEmit # 0 erreur - npm run lint # 0 erreur - NODE_ENV=test npm test # suite jsdom verte - npm run test:components # suite browser verte - npm run test:e2e # suite e2e verte - npm run build # build Vite OK + npx tsc --noEmit # 0 erreur + npm run lint:check # 0 erreur (lint = --fix, pas une validation) + NODE_ENV=test npm run coverage # suites jsdom + browser + merge, seuils 80/90/70/80 (IMP-013) + npm run test:e2e # suite e2e verte (Playwright démarre les 3 services) + npm run build # build Vite OK + npm audit # 0 vulnérabilité + npm run docs:build # doc VitePress + TypeDoc OK ``` 5. **Commits Gitmoji** (convention du repo), messages en français comme l'historique récent, un commit par unité logique. 6. **Documenter** : cocher l'étape dans ce README, compléter le `step-XX.md` avec la section « Résultats de validation » (comme dans `docs/migration/`), ajouter un `IMP-XXX` dans decisions.md si une décision a été prise. @@ -99,7 +101,7 @@ Garde-fous quel que soit le modèle : exécuter réellement les 6 commandes de v | Étape | Statut | Contenu | |---|---|---| -| [17 — Socle agentic](step-17-agentic.md) | ⬜ | CLAUDE.md, .claude/ versionné, skills de vérification, revue IA automatisée | +| [17 — Socle agentic](step-17-agentic.md) | ✅ | CLAUDE.md + AGENTS.md, `.claude/settings.json` + review-guidelines versionnés, `scripts/verify.sh` (IMP-011) — revue CI écartée (politique Actions org), `/code-review` manuel | ## Dépendances entre étapes diff --git a/docs/improvements/decisions.md b/docs/improvements/decisions.md index 59f0c7e8..7f17c177 100644 --- a/docs/improvements/decisions.md +++ b/docs/improvements/decisions.md @@ -555,11 +555,64 @@ golden-path 14 (menu plugins) vert, audit 0 vulnérabilité. ## IMP-011 — Socle agentic versionné -**Étape :** 17 | **Statut :** ⬜ +**Étape :** 17 | **Statut :** ✅ tranché et implémenté (2026-07-14, branche `chore/step-17-agentic`) -### Décision (à confirmer) -CLAUDE.md + AGENTS.md + `.claude/settings.json` propre + skill/script de vérification + revue CI automatisée -avec guidelines encodant les dettes éliminées. KISS : simple et maintenable à 6 mois. +### Contexte +Aucune configuration agentic versionnée alors que le projet est développé quasi exclusivement avec +des agents : chaque session repartait de zéro. Seul artefact : un `.claude/settings.local.json` +local pollué (139 entrées, PIDs codés en dur, chemins `/tmp`, références Mocha mortes). + +### Décision — le socle retenu (4 fichiers versionnés + 1 script) +- **`CLAUDE.md`** (racine) : contexte projet dense — architecture 3 services + event-bus, stack, + commandes de validation canoniques (celles réellement exécutées par la CI de l'étape 16), + contrat golden-path, conventions, et les **pièges réellement vécus** pendant les étapes 01-16 + (décorateurs Lit legacy IMP-006, `NODE_ENV=test`, `PIPESTATUS`, `workers: 1`, cache Vite, + `vite.aliases.ts`, politique Actions org, TypeDoc IMP-014). +- **`AGENTS.md`** minimal (interop Gemini/Antigravity et autres outils) : renvoie vers CLAUDE.md + et inline l'essentiel (validation, conventions, interdits) pour les outils qui ne suivraient pas + le lien. Pas de symlink (fragile cross-plateforme) : deux fichiers, CLAUDE.md source de vérité. +- **`.claude/settings.json`** versionné : allowlist générique (validation, git usuel, npm, npx + outillage, MCP playwright). Le `settings.local.json` (non versionné) est régénéré épuré : entrées + rtk/mempalace/gh/pkill machine-spécifiques conservées, tout le mort supprimé. `.gitignore` : + `.claude/*` ignoré sauf `settings.json` et `review-guidelines.md` (exclut scheduled_tasks.lock, + worktrees/, settings.local.json). +- **`scripts/verify.sh`** (option KISS retenue contre une skill `.claude/skills/verify-talkcontrol/`) : + enchaîne tsc, lint:check, `NODE_ENV=test coverage` (les suites tournent dedans — pas de double + exécution, cohérent IMP-013), e2e, build, audit, docs:build, avec récapitulatif et exit code + agrégé. Un script shell est lisible, testable et **utilisable par n'importe quel outil** (pas + seulement Claude Code) — c'est le choix qui reste vrai à 6 mois. Le protocole de + `docs/improvements/README.md` § 4 est harmonisé sur cette liste (il datait d'avant l'étape 16 : + `lint` au lieu de `lint:check`, pas de coverage/audit/docs). +- **`.claude/review-guidelines.md`** : encode les dettes éliminées par le plan (casts `as` de + payload, `any`, `console.*` bruts, secrets, CORS `*`, `innerHTML`, événements bus hors + `TcEventMap`, contournement anti-SSRF, broadcast hors room, baisse de seuils, décorateurs + standards, réintroduction webpack/babel/mocha/redux) pour une revue `/code-review` manuelle. + +### Revue de code automatisée en CI : écartée (option 4 du step) +La politique GitHub Actions de l'organisation TalkControl est `selected` avec uniquement +`github_owned_allowed: true` (constat étape 16) : `anthropics/claude-code-action` n'est pas +github-owned et ne s'exécuterait pas. L'autoriser exigerait un élargissement de la politique org +(`admin:org`, action manuelle de JF) **plus** un secret `ANTHROPIC_API_KEY` facturé à chaque PR. +Contre le critère KISS de l'étape (« si simple que ça reste vrai dans 6 mois »), le ratio +bénéfice/maintenance ne tient pas pour un repo à contributeur quasi unique qui revoit déjà chaque +PR. **Évolution documentée** si le besoin devient réel : élargir la politique org à l'action +Claude Code, provisionner le secret, et brancher `.claude/review-guidelines.md` (déjà écrit pour +ça) comme contexte de revue. + +### Conséquences +Une session d'agent neuve trouve dans CLAUDE.md le contexte, les commandes exactes et les pièges +sans redécouverte ; la validation complète tient en une invocation (`./scripts/verify.sh`) ; les +permissions partagées sont propres et versionnées. Validation : verify.sh exécuté en réel sur la +branche (voir step-17, « Résultats de validation »). + +### Critère pour rouvrir la question des skills (challengé et confirmé au merge) +Faits et pièges → CLAUDE.md ; séquences déterministes → script ; une skill `.claude/skills/` +seulement pour une procédure **fréquente, multi-étapes, à jugement**, trop grosse pour le contexte +permanent — aujourd'hui cette case est vide (le seul workflow répétitif, « exécuter une étape du +plan », s'éteint avec le plan). Candidats identifiés si le développement actif reprend : +`/new-plugin` (scaffold + conventions IMP-010) et `/smoke` (golden-path manuel via Playwright MCP, +pièges de l'étape 05). Déclencheur concret : réexpliquer la même procédure dans un prompt pour la +3e fois — ce prompt est le brouillon de la skill. --- diff --git a/docs/improvements/step-17-agentic.md b/docs/improvements/step-17-agentic.md index a3cde0a8..049d5cc8 100644 --- a/docs/improvements/step-17-agentic.md +++ b/docs/improvements/step-17-agentic.md @@ -84,3 +84,39 @@ l'outil, parte du même contexte. Convention commit + validation identiques. pas d'URL ngrok personnelle. - Cette étape capitalise sur tout le reste : la faire **en dernier** permet d'y encoder les leçons réelles des étapes 01-16 (les vrais pièges rencontrés, pas ceux anticipés ici). + +## Résultats de validation (2026-07-14, branche `chore/step-17-agentic`) + +### Ce qui a été livré (décision détaillée : IMP-011) + +| Action du step | Résultat | +|---|---| +| 1. `CLAUDE.md` | ✅ Racine — architecture 3 services, stack, validation (rapide vs complète), contrat golden-path, conventions, **pièges vécus** des étapes 01-16 (décorateurs Lit legacy IMP-006, `NODE_ENV=test`, `PIPESTATUS`, `workers: 1`, cache Vite, `vite.aliases.ts`, politique Actions org, TypeDoc IMP-014, port 3000 résiduel) | +| 2. `.claude/settings.json` | ✅ Versionné, allowlist générique (validation, git usuel, npm/npx outillage, MCP playwright). `settings.local.json` régénéré épuré : 139 → 37 entrées (PIDs, `/tmp`, Mocha, scratchpads de sessions mortes supprimés). `.gitignore` : `.claude/*` ignoré sauf les 2 fichiers versionnés | +| 3. Vérification projet | ✅ Option KISS retenue : `scripts/verify.sh` (pas de skill) — tsc, lint:check, coverage (suites incluses, IMP-013), e2e, build, audit, docs:build, récapitulatif + exit agrégé. Protocole du README § 4 harmonisé sur cette liste | +| 4. Revue CI automatisée | ❌ Écartée (IMP-011) : politique Actions org = github-owned uniquement, `anthropics/claude-code-action` inexécutable sans élargissement `admin:org` + secret API facturé. À la place : `.claude/review-guidelines.md` (dettes du plan encodées) pour `/code-review` manuel — prêt à brancher en CI si la politique change un jour | +| 5. `AGENTS.md` | ✅ Minimal, renvoie vers CLAUDE.md (source de vérité unique) avec l'essentiel inliné. Pas de symlink (fragile cross-plateforme) | + +### Validation exécutée en réel + +`./scripts/verify.sh` lancé sur la branche : + +- **1er run : ÉCHEC e2e — et c'était le script qui avait raison.** typecheck/lint/coverage/build/ + audit (0 vulnérabilité)/docs verts, mais e2e 24/35 : un Vite résiduel d'une session précédente + occupait le port 3000, `reuseExistingServer` (qui ne sonde que :3000) a cru l'environnement + démarré et n'a lancé ni tc-server ni showcase. Le récapitulatif a correctement signalé `e2e + ÉCHEC` et rendu exit 1 — le chemin d'échec du script est donc validé en conditions réelles. + Piège ajouté à CLAUDE.md (« Pièges connus »), port libéré, e2e relancés : **35/35 verts en 27 s**. +- **2e run complet : tout vert**, exit 0 — typecheck 0 erreur, lint:check 0 erreur, coverage + jsdom + browser + merge seuils 80/90/70/80 OK, e2e 35/35, build Vite OK, `npm audit` 0, + `docs:build` OK (TypeDoc + VitePress). +- Test mental « nouvelle session » : un agent qui ouvre le repo lit CLAUDE.md (ou AGENTS.md selon + l'outil) et y trouve les 3 services, les commandes exactes de validation, le contrat + golden-path, le protocole du plan et les pièges — sans redécouvrir l'outillage. Le scénario + vécu au 1er run (échec e2e environnemental) est précisément celui que le CLAUDE.md permet + désormais de diagnostiquer en une commande. + +### Hors scope assumé + +Pas de skill `.claude/skills/`, pas de hooks, pas de multi-agents : critère « si simple que ça +reste vrai dans 6 mois ». Le workflow de revue CI reste une évolution documentée (IMP-011). diff --git a/scripts/verify.sh b/scripts/verify.sh new file mode 100755 index 00000000..1ca7bf22 --- /dev/null +++ b/scripts/verify.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# Validation complète du projet — miroir des jobs CI (.github/workflows/develop.yml). +# Lance tout, n'échoue pas au premier raté, et termine par un récapitulatif. +# Usage : ./scripts/verify.sh +set -u +cd "$(dirname "$0")/.." + +declare -a names=() results=() + +run() { + local name="$1" + shift + echo "" + echo "═══ ${name} : $* ═══" + if "$@"; then + results+=("OK") + else + results+=("ÉCHEC") + fi + names+=("${name}") +} + +run "typecheck " npx tsc --noEmit +run "lint " npm run lint:check +# coverage exécute les suites jsdom + browser puis merge avec les seuils (IMP-013) : +# ne pas relancer `npm test` / `test:components` en plus, ce serait une double exécution. +run "coverage " env NODE_ENV=test npm run coverage +run "e2e " npm run test:e2e +run "build " npm run build +run "audit " npm audit +run "docs " npm run docs:build + +echo "" +echo "═══════════ Récapitulatif ═══════════" +failed=0 +for i in "${!names[@]}"; do + echo " ${names[$i]} ${results[$i]}" + [ "${results[$i]}" = "ÉCHEC" ] && failed=1 +done +if [ "$failed" -ne 0 ]; then + echo "✗ Validation en échec." + exit 1 +fi +echo "✓ Tout est vert."