No More Slop: nettoyage code IA dual-score
Livre blanc No More Slop: 22 patterns regex, score structurel, coûts, calibration de style, escalade Rocky. Open source.
Version 1.2.1 | Août 2026 Auteurs: Radjiv, hellozheat / Rocky Dépôt: github.com/hellozheat/no-more-slop Référence: Livre blanc technique public
Résumé
No More Slop (nomoreslop) est une skill agent pour Claude Code, Cursor et OpenCode. Elle retire le « slop » IA du code source pour qu'il lise comme du code d'équipe. Même idée que blader/humanizer pour la prose. Ici, ce sont les fonctions, commentaires, noms et le copier-coller structurel.
La v1.2 score deux couches: slop regex (22 patterns) et slop structurel (motion boilerplate, section factories, fichiers obèses, exports morts, patterns prototype). Les deux doivent passer. L'agent réécrit à la main selon le style voisin; un scorer Python (scripts/score.py) mesure avant/après. Quand il reste lint, tests ou architecture, escalade vers Rocky MCP.
Table des matières
- Problème
- Principes de conception
- Architecture
- Ce qui change vs l'existant
- Taxonomie regex (22)
- Taxonomie structurelle
- Algorithme de double score
- Modes
- Calibration de style
- Réécritures library-aware
- Escalade Rocky
- Breakdown coûts (score.py vs grep)
- Workflow et contrat de rapport
- Périmètre et limites
- Annexes
1. Problème
Le code IA compile souvent. Il laisse aussi des empreintes qu'un senior voit en secondes: docstrings triviaux, bannières # Step 1:, noms processUserDataList, groupBy maison alors que lodash est déjà là, catch { return null }, logs ✅, shouldReduceMotion() collé six fois, composants à 600 lignes.
Lint et formatage ne voient presque rien de ça. No More Slop comble le trou: nommer le tell, scorer, réécrire vers le style réel du repo, rescanner, et ne pas prétendre fixer ce qui relève d'un vrai gate qualité.
2. Principes de conception
| Principe | Sens |
|---|---|
| Comportement préservé par défaut | Happy path inchangé sauf FLAG explicite |
| Calibrer sur les voisins | Pas de style « clean » générique |
| Double score | Un PASS regex seul ne suffit pas |
| Réécriture manuelle | Le scorer détecte; l'agent édite |
| Pas de deps sans accord | Réécritures libs seulement si installées |
| Rapports honnêtes | Jamais « clean » si passed est false ou escalateRocky |
| Skip UI vendor | Ignore components/ui/ par défaut |
3. Architecture
Pas un SaaS: une skill (instructions + catalogues) et un scorer Python local.
Couche 1: SKILL.md : modes, gates, SAFE / CONDITIONAL / FLAG
Couche 2: PATTERNS.md, PATTERNS-STRUCTURAL.md, LIBRARIES.md, REPORT.md
Couche 3: scripts/score.py : slopScore + structuralScore + escalateRocky
Couche 4: Rocky MCP (optionnel) : lint, tests, scope, gate PR| Éditeur | Chemin |
|---|---|
| Cursor | ~/.cursor/skills/nomoreslop/ |
| Claude Code | ~/.claude/skills/nomoreslop/ |
| OpenCode | ~/.config/opencode/skills/nomoreslop/ |
git clone https://github.com/hellozheat/no-more-slop.git ~/.cursor/skills/nomoreslop4. Ce qui change vs l'existant
| Capacité | Linter / formatter | Prompt « clean this » | No More Slop |
|---|---|---|---|
| Quels tells ont tiré | Rarement | Vague | Oui (ids) |
| Scores numériques | Non | Non | Double score |
| Match style voisin | Non | Faible | Mode calibrate |
| Tells landing structurels | Non | Rate | Motion, section factories |
| Rewrite lib si dep présente | Parfois | Peut inventer des packages | Seulement si dans package.json |
| Honnêteté comportementale | N/A | Souvent silencieux | FLAG + rapport |
| Escalade gate qualité | CI seul | Non | Rocky MCP |
Produit frère prose: Humaniseur. Densités IA et réécriture de texte. Même philosophie, média différent.
5. Taxonomie regex (22)
Tiers: SAFE · CONDITIONAL · FLAG
Commentaires (1-7): docstring-trivial, comment-restates, banner-step, tutorial-voice, emoji-narration, placeholder-todo, uniform-comments.
Nommage (8-10): verbose-names, generic-names, no-idiomatic-locals.
Structure (11-14): over-engineering, single-use-helper, response-envelope, eerie-uniformity.
Erreurs (15-16): swallow-except (FLAG), redundant-null-check.
Types / idiomes (17-21): useless-types, throwaway-main, markdown-in-comments, non-idiomatic-loop, dead-imports.
Audit (22): hallucinated-api (FLAG: rapporter, ne jamais inventer le fix).
Avant / après canonique
Avant: processUserData avec steps, boucle index, logs emoji, catch qui renvoie null.
Après:
function activeUsers(users) {
return users.filter((u) => u.isActive);
}Retirer le catch large change le chemin d'échec: à dire dans le rapport.
6. Taxonomie structurelle
| Famille | Exemples |
|---|---|
| Ligne | motion-guard, should-reduce-motion, inline-schema-org, duplicate-easing |
| Agrégats | motion-copy-paste (6+), section-factory (5+ SectionHeader) |
| Fichiers | file-size-outlier (>200 LOC et >2.2× médiane du dossier) |
| Prototype v1.2 | dnd-any-type, hooks-rule-disable, duplicate-module-filename, directory-bloat |
Ces derniers restants → escalateRocky: true.
7. Double score
python scripts/score.py --repo . --base main --json| Champ | Sens |
|---|---|
slopScore | Tells regex / commentaires / noms |
structuralScore | Motion, factories, bloat, prototype |
passed | Les deux ≤ seuil (défaut 35) |
escalateRocky | FAIL restant ou patterns à risque |
FAIL global si une couche échoue. Config: .nomoresloprc (seuils, ignore, envelopeAllowlist pour les ok: MCP/health).
Chemins toujours ignorés: node_modules, .git, components/ui/, dist, build.
8. Modes
| Mode | Flag | Usage |
|---|---|---|
| calibrate | (défaut) | Matcher les voisins + structurel sûr |
| clean | --clean-only | Diff minimal avant PR |
| deep | --deep | Split blobs, dédup modules. Défaut pour prototypes vibe-coded. |
| inject | --inject-signals | Quelques commentaires why (opt-in) |
Pas de mode « entropie whitespace » en v1. C'est volontaire.
9. Calibration de style
- Lire 2-3 fichiers voisins.
- Si tout le dossier est IA-greenfield → médiane du repo.
- Aligner longueur de noms, densité de commentaires, imports, idiomes.
- Réécrire la cible vers cette distribution.
/nomoreslop
Match the style in src/users/listUsers.ts
Now humanize: src/checkout/cart.ts10. Réécritures library-aware
Ordre: util projet → natif JS (si voisins) → npm déjà installé (lodash, date-fns, dayjs, zod).
Jamais ajouter de package sans accord. Pas de suggestions UI framework.
11. Escalade Rocky
Quand escalateRocky est true: handbook → change_scope_analyzer → repo_lint / repo_test → pre_pr_quality_gate.
Ne jamais dire que le repo est clean si escalateRocky est true.
12. Breakdown coûts (score.py vs grep)
La détection doit rester bon marché. Le piège cher, c'est greper les smells IA puis lire chaque fichier touché dans le contexte.
Même idée que graphify avant grep chez Rocky.
Overhead skill + scorer (fixe)
Mesuré sur no-more-slop @ v1.2 (≈4 chars/token):
| Payload | Taille | Tokens LLM (approx.) | Quand |
|---|---|---|---|
SKILL.md | ~3,3 Ko | ~0,8k | Chaque /nomoreslop |
Refs cœur (REPORT + SCOPE + MODES) | ~5,1 Ko en plus | ~1,3k | Si l'agent les ouvre |
Tous les .md de la skill | ~31 Ko | ~7,8k | À éviter (tout lire) |
scripts/score.py | ~25 Ko | 0 | Offline (stdlib Python) |
Chemin discipliné: ~0,8k-2,1k tokens d'overhead skill, puis JSON du scorer. Ne pas coller PATTERNS.md dans le chat.
Taxe grep-and-read (mesurée)
Sur ce repo marketing (zheat-landing-main, src/):
| Pattern grep | Id nomoreslop | Fichiers |
|---|---|---|
shouldReduceMotion | should-reduce-motion | 20 |
reducedMotion | motion-guard | 18 |
SectionHeader | section-factory | 11 |
Step [0-9] | banner-step | 1 |
✅ | emoji-narration | 1 |
| Fichiers uniques | - | 26 |
| Si l'agent lit tout | - | ~141 Ko ≈ ~35k tokens |
Coût de discovery seul, avant toute réécriture. Les agrégats structurels ont besoin de compteurs, pas de 26 lectures full-file.
Comparaison de session (directionnel)
| Approche | Détection | Tokens discovery typiques | Scope du fix |
|---|---|---|---|
| Prompt « clean the AI code » + grep | Le modèle lit les hits | ~35k+ sur une landing motion-heavy | Non borné |
| nomoreslop | JSON score.py + 2-3 voisins | ~1-3k skill/refs + voisins | Findings |
+ Rocky si escalateRocky | Idem + gate lint/test | + handbook/gate (breakdown tokens) | Reste architecture |
Règle: scorer offline, calibrer localement, greper seulement pour ouvrir un chemin de finding. Ne charge pas tout l'ensemble des hits dans le contexte.
rg -l --glob '!node_modules' --glob '!dist' \
-e 'shouldReduceMotion' -e 'reducedMotion' -e 'SectionHeader' \
-e 'Step [0-9]' -e '✅' src | wc -l
python scripts/score.py --repo . --json # 0 token LLM13. Workflow et rapport
Scope → config → score → inventaire → calibrate → fix → FLAG → rescore → Rocky si besoin → rapport court et vrai.
Jamais « clean » si passed est false. Rocky non optionnel si escalateRocky. ~8 lignes max dans le chat.
14. Périmètre et limites
Inclus: slop commentaires/noms, motion copy-paste, section factories, bloat, exports morts (partiel), libs si présentes.
Hors scope: vendor shadcn, boilerplate MCP imposé par le SDK, copy marketing JSON, claim « prod-ready » sans gate Rocky.
Limites: catalogues manuels (pas de ML), seuils à calibrer, heuristiques agrégées, deep opt-in pour gros splits.
15. Annexes
A. Historique
| Version | Notes |
|---|---|
| 1.2.x | Patterns prototype + escalade Rocky |
| 1.1.0 | Double score + patterns landing |
| 1.0.0 | 22 patterns, calibration, score.py |
B. Install rapide
git clone https://github.com/hellozheat/no-more-slop.git ~/.cursor/skills/nomoreslopC. CLI score
python scripts/score.py --repo . --base main --jsonD. Liens
No More Slop v1.2.1 tel que livré sur [https://github.com/hellozheat/no-more-slop](https://github.com/hellozheat/no-more-slop). Les catalogues, poids et règles d'escalade évoluent avec le source.
