architecture-audit
Skill0 starsChanged 3 months agoMITView on GitHub
Audite l'architecture d'un projet web React/Hono contre l'architecture cible Caudron — structure des dossiers, isolation des couches, inférence de types Hono RPC, validation Zod, filtrage par vault, plus la rigueur du tsconfig, la stratégie de tests et l'outillage (ESLint typé, Knip, couverture, hook pre-commit). Utiliser quand on demande un audit d'architecture, une revue de structure, une vérification des conventions, ou un état des lieux de l'outillage et de la configuration du projet.
- Reads credentials
16 other projects use a version of this.
Adopted by
Most recently taken up by
- harshitsinghbhandari/domain-expansiontheir own version, first seen Nov 8, 2026
- MarieLynneBlock/arcanum-artifextheir own version, first seen Nov 1, 2026
- RBraga01/a-teamtheir own version, first seen Nov 1, 2026
- helderberto/agent-skillstheir own version, first seen Oct 11, 2026
- nelantone/cogniviatheir own version, first seen Oct 11, 2026
- Suge8/friedbuntheir own version, first seen Oct 11, 2026
Used with
Projects with it also use prototype, review and 1 more.
Other files people use alongside this one.
Files found in the same public projects as a version of this one, more often than they turn up anywhere else. Each project counts once, large collections count for less, and this file's own repository is left out.
GoogleSkillprototype
Build a throwaway prototype to answer a design question. Use when the user wants to sanity-check whether a state model or logic feels right, or explore what a UI should look like.
Also in 3 projects that use this
SentrySkillreview
Fixture review skill.
Also in 3 projects that use this
GoogleSkilltdd
Test-driven development. Use when the user wants to build features or fix bugs test-first, mentions "red-green-refactor", or wants integration tests.
Also in 3 projects that use this
Other versions16 projects use a version of this.
Word for word · 0
None found.
Edited · 0
None found.
Wrote their own version · 16
- RBraga01/a-team★ 24same name
- helderberto/agent-skills★ 19same name
- Suge8/friedbun★ 12same name
- BrentRector/claude-skills★ 6same name
- creativedeals/free-claude-skill-architecture-audit★ 4same name
- MarieLynneBlock/arcanum-artifex★ 4same name
- gootf/software-agent-sop★ 2same name
- harshitsinghbhandari/domain-expansion★ 2same name
- seikaikyo/dash-skills★ 2same name
- InsightStudio-2026/agent-assets★ 1same name
6 more not listed
How matches are found. Word for word: the exact same text. Edited: shares passages with this file (“99% same” means 99% of its five-word phrases also appear here; 10% or more counts). Their own version: similar meaning, or, weakest, the same name. We can’t tell which project had it first. Projects are counted among the 200 most-starred candidates, and mentions are links to the repository we found, up to 50 per site, so both counts are a floor.
In this repository3 other files it gives its agents.
- clean-code-auditSkill
- design-auditSkill
- diff-auditSkill
The file
Files
Skill: Architecture Audit
Analyse le code source pour détecter les écarts avec l'architecture documentée.
Objectif
Comparer l'implémentation réelle du codebase avec les règles définies dans ${CLAUDE_PLUGIN_ROOT}/blueprints/architecture/ et identifier les violations.
Prérequis
Lire les blueprints de référence embarqués dans le plugin :
${CLAUDE_PLUGIN_ROOT}/blueprints/architecture/frontend.md${CLAUDE_PLUGIN_ROOT}/blueprints/architecture/backend.md${CLAUDE_PLUGIN_ROOT}/blueprints/architecture/typing.md${CLAUDE_PLUGIN_ROOT}/blueprints/architecture/tools.md${CLAUDE_PLUGIN_ROOT}/blueprints/architecture/tests.md
Les chemins de code audités (src/, netlify/) sont relatifs à la racine du projet analysé.
Exécution
Sur un projet de taille non triviale, déléguer à l'agent architecture-auditor (read-only) plutôt que de tout lire soi-même. Il peut tourner en parallèle de design-auditor et clean-code-auditor si un audit complet est demandé.
Règles d'Audit
Frontend (FE-*)
| ID | Règle | Sévérité | Pattern de Détection |
| FE-001 | Hooks simples (TanStack Query only) | HIGH | Chercher useEffect, multiples useState, logique métier dans src/hooks/ |
| FE-002 | Contexts sans appels réseau | HIGH | Chercher fetch, honoClient dans src/contexts/ |
| FE-003 | Services isolés | MEDIUM | Chercher imports depuis components, hooks, contexts, pages dans src/services/ |
| FE-004 | honoClient pour inférence de types | HIGH | Chercher honoClient.(get|post|patch|delete)< (types génériques manuels) dans src/hooks/ |
| FE-005 | Utiliser res.ok, pas json.success | MEDIUM | Chercher json.success, !json.success, .success dans src/hooks/ |
| FE-006 | Pas d'export de types *FromApi | MEDIUM | Chercher export type \w+FromApi dans src/hooks/ |
| FE-007 | Composants sans appels réseau | HIGH | Chercher fetch, honoClient dans src/components/ |
| FE-008 | Layouts sans props | MEDIUM | Chercher export const \w+Layout = \(.*: avec paramètres dans src/layouts/ |
| FE-009 | Une page = une route | HIGH | Détecter même composant utilisé pour plusieurs routes dans src/routes/ |
| FE-010 | Pas de navigation dans les hooks data | MEDIUM | Chercher useNavigate, navigate(, toast dans src/hooks/data/ |
| FE-011 | Pas d'état local dans hooks data | MEDIUM | Chercher useState (hors queryFn) dans src/hooks/data/ |
| FE-012 | Services uniquement dans hooks/data | HIGH | Imports services/ dans src/components/, src/pages/, src/layouts/ — séparer valeur et import type, seuls les premiers couplent à l'exécution |
| FE-013 | Pas de re-export de service dans un hook | HIGH | export { … } en tête d'un hooks/data/* qui réexporte un service : déplace l'import sans découpler, et rend FE-012 aveugle |
Backend (BE-*)
| ID | Règle | Sévérité | Pattern de Détection |
| BE-001 | Method chaining pour Hono RPC | HIGH | Vérifier .get().post() vs router.get() séparé dans netlify/routes/ |
| BE-002 | Validation Zod sur chaque route POST/PATCH | HIGH | Chercher .post( ou .patch( sans zValidator dans netlify/routes/ |
| BE-003 | Pas de champ success dans réponses HTTP | MEDIUM | Chercher c.json.*success dans netlify/routes/ |
| BE-004 | Pas de return type explicite | LOW | Chercher : Promise< dans netlify/routes/ et netlify/lib/ |
| BE-005 | Filtrage par vault ID (JWT) | HIGH | Vérifier que les routes protégées utilisent c.get('auth') pour filtrer |
| BE-006 | Bons codes HTTP | MEDIUM | Vérifier 201 pour POST, 204 pour DELETE dans netlify/routes/ |
| BE-007 | Secret requis sans valeur de repli | CRITICAL | process.env.X || '…' ou ?? '…' sur un secret : une variable absente fait signer avec une valeur publique et versionnée, sans rien casser ni alerter |
Typage (TY-*)
| ID | Règle | Sévérité | Pattern de Détection |
| TY-001 | Pas de return types explicites | LOW | Chercher : Promise< dans les fonctions backend |
| TY-002 | Types inférés depuis Drizzle | MEDIUM | Interfaces dupliquant les types du schéma Drizzle |
| TY-003 | Frontend sans duplication de types DB | HIGH | Chercher interfaces d'entités DB dans src/types/ |
Code (CD-*)
| ID | Règle | Sévérité | Pattern de Détection |
| CD-001 | Named exports uniquement | LOW | Chercher export default (exception: pages pour React.lazy) |
| CD-002 | Pas d'any explicite | HIGH | Chercher : any, as any, <any> dans tous les fichiers TS |
| CD-003 | Code en anglais | LOW | Vérifier noms de variables/fonctions en français |
Configuration TypeScript (CFG-*)
strict: true n'active que huit options. Les cinq suivantes n'en font pas partie et sont celles qui attrapent ce que « strict » laisse passer. Toutes se lisent dans tsconfig.json.
| ID | Règle | Sévérité | Pattern de Détection |
| CFG-001 | strict: true | CRITICAL | compilerOptions.strict absent ou false |
| CFG-002 | noUncheckedIndexedAccess | HIGH | Option absente — arr[0] et map[clé] sont typés comme toujours présents |
| CFG-003 | verbatimModuleSyntax | MEDIUM | Option absente — les import type ne sont pas imposés |
| CFG-004 | exactOptionalPropertyTypes | MEDIUM | Option absente — prop?: T et T | undefined restent confondus |
| CFG-005 | noImplicitOverride | LOW | Option absente |
| CFG-006 | noPropertyAccessFromIndexSignature | LOW | Option absente |
| CFG-007 | noUnusedLocals + noUnusedParameters + noImplicitReturns + noFallthroughCasesInSwitch | MEDIUM | L'une des quatre absente |
| CFG-008 | Config unique à la racine | MEDIUM | Présence de tsconfig.app.json / tsconfig.node.json — deux configs divergent |
Tests (TE-*)
| ID | Règle | Sévérité | Pattern de Détection |
| TE-001 | Framework de test unitaire | HIGH | vitest absent des devDependencies — tout tester en E2E laisse la logique pure sans filet |
| TE-002 | test = unitaire, test:e2e = bout en bout | HIGH | scripts.test qui lance playwright : check embarque alors une suite lente exigeant un serveur |
| TE-003 | Outil de couverture | MEDIUM | @vitest/coverage-v8 absent des devDependencies |
| TE-004 | Seuils de couverture qui échouent | MEDIUM | coverage.thresholds absent de la config Vitest — un seuil qui n'échoue pas n'est pas un seuil. ⚠️ Sur une base existante, un seuil sous la cible 80/80/70 est conforme s'il est documenté comme cliquet ; ce qui échoue, c'est l'absence de seuil ou un seuil baissé pour faire passer un check |
| TE-005 | Couverture ciblée sur la logique pure | LOW | coverage.include absent ou couvrant src/ entier au lieu de services/ et lib/ |
| TE-006 | Tests de composants | LOW | @testing-library/react absent alors que le projet a des composants |
| TE-007 | Suite unitaire non vide | HIGH | Aucun fichier *.test.ts / *.test.tsx alors que src/services/ existe |
Outillage (TL-*)
Un outil manquant ne produit aucune erreur : le projet compile et la règle qu'il aurait fait respecter n'existe simplement pas. C'est le seul domaine où l'audit doit chercher une absence.
| ID | Règle | Sévérité | Pattern de Détection |
| TL-001 | ESLint configuré | HIGH | Absence de eslint.config.* à la racine, ou eslint absent des devDependencies |
| TL-002 | Linting TypeScript typé actif | HIGH | eslint.config.* sans typescript-eslint / tseslint — lire la config, pas le package.json : le package installé mais non branché ne lint rien |
| TL-003 | Prettier configuré | MEDIUM | Absence de .prettierrc* / clé prettier, ou prettier absent des devDependencies |
| TL-004 | Knip pour le code mort | MEDIUM | knip absent des devDependencies, ou absence de knip.json / clé knip |
| TL-005 | Script check | HIGH | scripts.check absent du package.json |
| TL-006 | check couvre lint + types + build + tests | MEDIUM | scripts.check qui n'enchaîne pas lint, typecheck, build et test |
| TL-007 | Script deep-check | MEDIUM | scripts.deep-check absent — il ajoute format et knip, que check ne lance pas |
| TL-008 | Vérification automatique avant commit | MEDIUM | Absence de .husky/pre-commit (ou équivalent), ou scripts.prepare sans husky |
| TL-009 | Formateur Tailwind | LOW | prettier-plugin-tailwindcss absent alors que le projet utilise Tailwind |
| TL-010 | Preset strictTypeChecked | HIGH | tseslint.configs.* étendu autrement qu'en strictTypeChecked. ⚠️ js.configs.recommended fait partie de la config attendue — ne pas le confondre |
| TL-011 | Garde-fou de taille outillé | MEDIUM | Absence de règle max-lines dans eslint.config.* — sans elle, PR-001 et CS-004 reposent sur la relecture |
| TL-012 | max-lines sans exemption | MEDIUM | Bloc de config qui remet 'max-lines': 'off' sur un dossier — une exemption est une règle qu'on a cessé d'appliquer |
| TL-013 | Désactivations groupées | LOW | Plus de 3 commentaires eslint-disable pour la même règle : elle se désactive une fois dans la config, avec sa raison |
| TL-014 | security hors de toute chaîne bloquante locale | MEDIUM | scripts.check ou scripts.deep-check qui contient security, ou .husky/pre-commit qui le lance : une faille non corrigeable rend la chaîne rouge en permanence, et une chaîne toujours rouge finit contournée. C'est un diagnostic — la remédiation est TL-021 |
| TL-015 | deep-check hors du hook pre-commit | LOW | .husky/pre-commit qui lance deep-check : bun install dépend du réseau, le hook doit rester rapide et hors ligne |
| TL-016 | trailingComma: "all" | LOW | .prettierrc avec "es5" — diffs plus bruyants pour rien |
| TL-017 | Knip en fichier dédié avec $schema | LOW | Config inline dans package.json au lieu de knip.json |
| TL-018 | ignore Knip justifiés | MEDIUM | Entrée dans knip.ignore / ignoreDependencies sans commentaire disant pourquoi Knip se trompe |
| TL-019 | .editorconfig | LOW | Fichier absent à la racine |
| TL-020 | Version du runtime figée | LOW | engines absent du package.json (ou pas de .nvmrc / .node-version) |
| TL-021 | Mises à jour de dépendances automatisées | MEDIUM | Ni .github/dependabot.yml ni config Renovate : c'est le canal de remédiation, pas un confort — sans lui security ne produit qu'une liste que personne ne traite. Vérifier aussi le bloc registries si le projet consomme un registre privé, sans quoi les packages internes sont ignorés en silence |
| TL-022 | CI de vérification | LOW | Aucun workflow lançant deep-check. Facultatif en solo avec build à chaque push ; utile pour valider sur un environnement propre |
Commandes de Détection
FE-001: Complexité des Hooks
grep -r "useEffect" src/hooks/ --include="*.ts" --include="*.tsx"
grep -r "useState.*useState" src/hooks/ --include="*.ts" --include="*.tsx"FE-002: Réseau dans Contexts
grep -rE "(fetch|honoClient)" src/contexts/ --include="*.ts" --include="*.tsx"FE-003: Isolation Services
grep -rE "from '.*/components|from '.*/hooks|from '.*/contexts|from '.*/pages" src/services/ --include="*.ts" --include="*.tsx"FE-004: honoClient Type Inférence
grep -rE "honoClient\.(get|post|patch|delete|upload)<" src/hooks/ --include="*.ts" --include="*.tsx"FE-005: res.ok Check
grep -rE "(json\.success|!json\.success|\.success)" src/hooks/ --include="*.ts"FE-006: Export FromApi Types
grep -rE "export type \w+FromApi" src/hooks/ --include="*.ts"FE-007: Composants sans appels réseau
grep -rE "(fetch\(|honoClient\.)" src/components/ --include="*.ts" --include="*.tsx"FE-008: Layouts sans props
grep -rE "export const \w+Layout = \(\{[^}]*\}:" src/layouts/ --include="*.tsx" | grep -v "children"FE-009: Une page = une route
grep -rE "<Route.*element=\{<\w+Page" src/routes/ --include="*.tsx"FE-010: Pas de navigation dans les hooks data
grep -rE "(useNavigate|navigate\(|toast\(|toast\.)" src/hooks/data/ --include="*.ts"FE-011: Pas d'état local dans hooks data
grep -rE "useState\(" src/hooks/data/ --include="*.ts"FE-012 / FE-013 : frontière services → composants
# Les imports de VALEUR seuls : ce sont eux qui couplent à l'exécution.
grep -rnE "from '[^']*services/" src/components/ src/pages/ src/layouts/ | grep -v ":import type"
# Le compte total, pour situer la part type-only (admissible).
grep -rnE "from '[^']*services/" src/components/ src/pages/ src/layouts/ | wc -l
# FE-013 : le re-export qui rend le grep ci-dessus aveugle.
grep -rnE "^export \{" src/hooks/⚠️ Rapporter les deux nombres. Un audit qui additionne import type et imports de valeur surestime la dette et fait rater la vraie question : d'où vient le helper, et où devrait-il vivre (cf. frontend.md, « Le discriminant utils/ ou services/ »).
BE-001: Method chaining Hono RPC
# Chercher routes séparées (perte d'inférence)
grep -rE "^\w+\.(get|post|patch|delete)\(" netlify/routes/ --include="*.ts"BE-002: Validation Zod manquante
grep -rE "\.(post|patch)\(" netlify/routes/ --include="*.ts" | grep -v "zValidator"BE-003: Champ success dans réponses HTTP
grep -rE "c\.json\(.*success" netlify/routes/ --include="*.ts"BE-004: Return types explicites
grep -rE "\): Promise<" netlify/routes/ netlify/lib/ --include="*.ts"TY-003: Duplication Types Frontend
# Chercher des interfaces qui dupliquent le schéma Drizzle dans src/types/
grep -rE "^export interface" src/types/ --include="*.ts"CD-001: Named exports uniquement
grep -rE "^export default" src/ netlify/ --include="*.ts" --include="*.tsx" | grep -v "/pages/"CD-002: Pas d'any explicite
grep -rE "(: any|as any|<any>)" src/ netlify/ --include="*.ts" --include="*.tsx"TL-001 / TL-003 / TL-004 : présence des outils
ls eslint.config.* .prettierrc* knip.json 2>/dev/null
jq -r '[.devDependencies,.dependencies|objects|keys[]]|map(select(test("eslint|prettier|knip")))|sort|join(" ")' package.jsonTL-002 : linting TypeScript réellement branché
# La config fait foi, pas la dépendance : le package peut être installé sans être utilisé
grep -E "typescript-eslint|tseslint|@typescript-eslint" eslint.config.*TL-005 / TL-006 / TL-007 / TL-008 : scripts et hook
jq -r '.scripts | to_entries[] | select(.key|test("^(check|deep-check|lint|typecheck|format|knip|test|security|prepare)$")) | "\(.key): \(.value)"' package.json
ls -la .husky/ 2>/dev/nullTL-014 : security hors des chaînes bloquantes
# Doit être défini, et n'apparaître dans AUCUNE des trois.
jq -r '.scripts | .check, .["deep-check"]' package.json | grep -n security
grep -rn "security" .husky/ 2>/dev/nullDéfini mais absent des trois = PASS. Présent dans check, deep-check ou le hook = FAIL.
BE-007 : secret avec valeur de repli
grep -rnE "process\.env\.[A-Z_]+ *(\|\||\?\?) *['\"]" netlify/ src/⚠️ Trier ce que la commande remonte : un repli sur une URL de développement (process.env.URL ?? 'http://localhost:8888') est légitime ; un repli sur un secret (signature, identifiants, clés) ne l'est jamais.
TL-010 / TL-011 / TL-012 : preset et garde-fou de taille
# Cibler tseslint uniquement : `js.configs.recommended` est attendu dans la config canonique
grep -nE "tseslint\.configs\.[a-zA-Z]+" eslint.config.*
grep -nE "max-lines" eslint.config.* # présence, seuil, et tout 'off'CFG-001 à CFG-008 : options du compilateur
jq -r '.compilerOptions | to_entries[] | select(.key|test("strict|noUnused|noImplicit|noUnchecked|exactOptional|noFallthrough|verbatim|noProperty")) | "\(.key)=\(.value)"' tsconfig.json
ls tsconfig*.json # CFG-008 : plus d'un fichier = configs séparéesTE-001 à TE-007 : tests et couverture
jq -r '[(.devDependencies//{})|keys[]|select(test("vitest|playwright|testing-library|coverage"))]|join(" ")' package.json
jq -r '.scripts|to_entries[]|select(.key|test("^test"))|"\(.key): \(.value)"' package.json
grep -nE "thresholds|coverage" vitest.config.* vite.config.* 2>/dev/null
find . -name "*.test.ts" -o -name "*.test.tsx" | grep -v node_modules | wc -lTL-013 : désactivations répétées
grep -rhoE "eslint-disable[a-z-]* +[@a-z/-]+" src/ netlify/ | sort | uniq -c | sort -rn | headFichiers qui dépassent le seuil
find src/ netlify/ -name "*.ts" -o -name "*.tsx" | xargs wc -l | sort -rn | head -20Classification des Sévérités
| Sévérité | Critères |
| CRITICAL | Risque sécurité, intégrité des données, bloque fonctionnalité core |
| HIGH | Violation architecturale impactant la maintenabilité |
| MEDIUM | Déviation mineure, dette technique |
| LOW | Convention/style, opportunité d'amélioration |
Format de Rapport
Le rapport généré doit inclure :
- Résumé — Totaux par sévérité
- Violations par catégorie — FE-, BE-, TY-, CD-, CFG-, TE-, TL-* avec fichier, ligne, description
- Tâches recommandées — Actions de remédiation priorisées
- Couverture des règles — Status PASS/FAIL par règle
Principes
- Non-destructif : Ne jamais modifier le code source
- Basé sur preuves : Chaque violation cite fichier et ligne
- Actionnable : Chaque violation a une action de remédiation claire
- Priorisé : Focus sur violations à fort impact
- Déterministe : Même codebase = même rapport
Exceptions Connues
Certains patterns sont intentionnels :
- Types
*FormData,*WithRelations,*Propssont autorisés danssrc/types/ - Les fichiers dans
src/pages/peuvent utiliserexport defaultpour React.lazy() - Le binary sync CRDT peut utiliser
fetchWithAuthdirectement (pas TanStack Query)
BE-003: Clarification success interne vs HTTP
Le champ success est interdit dans les réponses HTTP (c.json) mais autorisé en interne entre fonctions comme discriminated union pour la gestion d'erreurs type-safe :
// INTERDIT : success dans la réponse HTTP
return c.json({ success: true, data: user }) // NON!
// AUTORISÉ : success interne (fonction → route)
const result = await authenticate(credentials)
if (!result.success) {
return c.json({ error: 'Unauthorized' }, 401)
}
return c.json({ data: result.user }) // OK : pas de success dans la réponseDoes it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

