erikvallow-qt/dont-let-me-slide

Après avoir résolu un problème avec l'IA, analyse la session, consigne les leçons apprises pour l'humain et l'IA, et interroge l'utilisateur sur les points clés.

Qu'est-ce que dont-let-me-slide ?

Ce skill permet de tirer un apprentissage structuré après la résolution d'un problème avec l'aide d'une IA. Il identifie la session de chat pertinente, la relit intégralement pour repérer les oublis de l'humain et de l'IA, puis produit deux fichiers : LEARNED.md (rapport détaillé) et learned_quiz.py (quiz terminal en Python). Le rapport contient les leçons classées par catégorie (humain, IA, partagé), des liens vérifiés, des questions de test, et un prompt one-shot pour éviter les mêmes erreurs. Le quiz couvre toutes les leçons avec des questions variées (rappel, diagnostic, détection d'erreur). Fonctionne sur macOS, Linux et Windows. Utile pour les équipes de développement, les utilisateurs de Claude Code, Cursor, ou tout agent IA qui veulent capitaliser sur les incidents et éviter les répétitions.

Compatible avec~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/erikvallow-qt/dont-let-me-slide/tree/HEAD/dont-let-me-slide

Installed? Explore more Développement et programmation skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Demander à votre IA préférée

Ouvre une nouvelle conversation avec cette compétence d'agent déjà préchargée.

Documentation

Que fait dont-let-me-slide ?

Analyse la session qui a résolu le problème. Livre deux fichiers : LEARNED.md et learned_quiz.py (un quiz en terminal).

  1. Identifier la session. Utilise les conversations récentes pour trouver celle qui correspond au problème. Si plusieurs sont plausibles, demande à l'utilisateur laquelle. Si la session appartient à un projet, examine aussi les autres conversations de ce projet.
  2. Lire toute la session, pas seulement un résumé. Note là où l'humain et l'IA ont chacun oublié quelque chose avant la résolution. Note aussi les concepts que l'humain a dû accepter sans preuve, a demandés plus d'une fois, ou s'est trompés : ceux-ci nécessitent une plongée plus approfondie.
  3. Rechercher des liens avant d'écrire. Pour chaque leçon, trouve au moins un lien. Pour chaque leçon Humain et tout concept de l'étape 2, trouve 1 à 3 liens d'approfondissement qui expliquent les bases dès les premiers principes. Préfère, dans l'ordre : documentation officielle ou spécifications, notes d'application du fournisseur ou manuels, tutoriels ou manuels réputés, puis blogs ou forums respectables. Utilise WebSearch, puis ouvre chaque lien avec WebFetch pour confirmer qu'il charge et couvre le point. Supprime tout lien qui échoue ou est hors sujet. N'invente jamais d'URL.
  4. Rédiger LEARNED.md avec ces sections, dans cet ordre :
    • Ce qui s'est passé : 3 à 5 phrases, plus le statut (résolu ou non). Si non résolu, liste les éléments en suspens.
    • Leçons apprises : divisées en Humain, IA et Partagé. Pour chaque leçon, donne le point, ce qui a été oublié, la leçon en une phrase, et un lien (source nommée). Sous chaque leçon Humain qui nécessite un contexte, ajoute une sous-liste "Plongée approfondie" : chaque entrée est Titre, la source, et une ligne sur ce qu'elle enseigne et pourquoi cela aide ici.
    • Questions de test : 3 à 5 questions clés titrées "Questions de test", suivies d'un corrigé. Note que l'ensemble complet des questions se trouve dans learned_quiz.py.
    • Liens : tous les liens utilisés, regroupés par leçon, avec la source nommée. Précise que les liens ont été vérifiés à la date d'exécution et doivent être revérifiés avant utilisation.
    • Prompt one-shot suggéré : un prompt concis qui aurait évité les problèmes de cette session.
  5. Étiqueter les affirmations. Marque les affirmations non vérifiées comme non vérifiées. Marque les affirmations issues des résultats de recherche comme rapportées et lie la source.
  6. Ne pas présenter des suppositions comme des conclusions. Si la cause d'un problème n'a pas été confirmée, dis-le.
  7. Rédiger learned_quiz.py à partir du modèle ci-dessous. Règles :
    • Uniquement la bibliothèque standard Python 3. Doit fonctionner sur les terminaux macOS, Linux et Windows. Pas d'interface graphique.
    • Couvre tous les concepts, pas seulement les 3 à 5 questions de test : au moins 2 questions par leçon Humain, au moins 1 par leçon IA et Partagé, plus 1 par concept d'approfondissement. Typiquement 10 à 25 questions. Mélange des questions de rappel, "que vérifierais-tu en premier" et "repère l'erreur".
    • Chaque question : sujet (Humain, IA, Partagé, ou un nom de concept court), 4 choix avec des distracteurs plausibles, l'indice correct, une explication de 1 à 2 phrases, et le lien vérifié le plus pertinent.
    • Remplis TITLE, SOURCE et QUESTIONS uniquement. Ne modifie pas le moteur.
    • Avant d'envoyer, exécute python3 -c "import ast,sys;ast.parse(open(sys.argv[1]).read())" learned_quiz.py, puis python3 learned_quiz.py --list, et corrige toute erreur. Vérifie que chaque indice de réponse pointe vers le bon choix.
  8. Garder LEARNED.md concis. N'utilise pas de tirets cadratins dans aucun fichier.
  9. Envoyer les deux fichiers avec SendUserFile. Dans la réponse, donne la commande d'exécution : python3 learned_quiz.py (options : -r révision flashcard, -t SUJET filtre, -n N limite, --list tout afficher, --seed N ordre fixe).

Modèle du quiz (copier exactement, remplacer les espaces réservés et la question d'exemple) :

#!/usr/bin/env python3
"""Quiz LEARNED : <SUJET>. Exécution : python3 learned_quiz.py [-r] [-t SUJET] [-n N] [--list]"""
import argparse, random, sys, textwrap

TITLE = "<SUJET>"
SOURCE = "LEARNED.md, <DATE>"
QUESTIONS = [
    {"topic": "Human", "q": "Question exemple ?",
     "choices": ["Bonne réponse", "Mauvaise 1", "Mauvaise 2", "Mauvaise 3"], "answer": 0,
     "why": "Une ou deux phrases sur pourquoi.", "link": "https://example.com"},
]

def wrap(s, ind="   "):
    return textwrap.fill(s, 78, initial_indent=ind, subsequent_indent=ind)

def ask(prompt, valid):
    while True:
        try:
            a = input(prompt).strip().lower()
        except (EOFError, KeyboardInterrupt):
            print(); sys.exit(0)
        if a in valid:
            return a

def run(qs, review):
    missed = []
    for i, q in enumerate(qs, 1):
        order = list(range(len(q["choices"])))
        random.shuffle(order)
        letters = "abcdefgh"[:len(order)]
        print(f"\n[{i}/{len(qs)}] ({q['topic']})")
        print(wrap(q["q"], ""))
        for L, idx in zip(letters, order):
            print(wrap(f"{L}) {q['choices'][idx]}"))
        right = letters[order.index(q["answer"])]
        if review:
            if ask("   Entrée pour révéler, q pour quitter : ", {"", "q"}) == "q":
                sys.exit(0)
            ok = True
        else:
            a = ask(f"   Réponse [{letters}], q pour quitter : ", set(letters) | {"q"})
            if a == "q":
                break
            ok = a == right
            print("   Correct." if ok else f"   Pas tout à fait. Réponse : {right}")
        if review or not ok:
            print(wrap(f"{right}) {q['choices'][q['answer']]}"))
        print(wrap(q["why"]))
        if q.get("link"):
            print(wrap("Plus : " + q["link"]))
        if not ok:
            missed.append(q)
    return missed

def main():
    p = argparse.ArgumentParser(description=f"Quiz : {TITLE}")
    p.add_argument("-r", "--review", action="store_true", help="mode flashcard, pas de score")
    p.add_argument("-t", "--topic", help="seulement ce sujet (Human, AI, Shared, ...)")
    p.add_argument("-n", type=int, help="poser au plus N questions")
    p.add_argument("--list", action="store_true", help="afficher toutes les QA et quitter")
    p.add_argument("--seed", type=int, help="ordre fixe des questions")
    a = p.parse_args()
    random.seed(a.seed)
    qs = [q for q in QUESTIONS if not a.topic or q["topic"].lower() == a.topic.lower()]
    if not qs:
        sys.exit(f"Aucune question pour le sujet {a.topic!r}.")
    if a.list:
        for i, q in enumerate(qs, 1):
            print(f"{i}. ({q['topic']}) {q['q']}\n{wrap('R : ' + q['choices'][q['answer']])}\n{wrap(q['why'])}")
            if q.get("link"):
                print(wrap("Plus : " + q["link"]))
        return
    random.shuffle(qs)
    qs = qs[:a.n] if a.n else qs
    print(f"{TITLE}\nSource : {SOURCE}\n{len(qs)} questions.")
    while qs:
        missed = run(qs, a.review)
        if a.review:
            break
        print(f"\nScore : {len(qs)-len(missed)}/{len(qs)}")
        if not missed or ask("Reprendre les ratées ? [y/n] : ", {"y", "n"}) == "n":
            for q in missed:
                print(wrap(f"Révision : {q['q']}", "- ") + ("\n" + wrap(q["link"]) if q.get("link") else ""))
            break
        qs = missed

if __name__ == "__main__":
    main()

Skills associés