Community程式設計與開發github.com

erikvallow-qt/別讓我滑倒

在使用AI解決問題後,進行會話回顧,記錄人類與AI學到的經驗,並透過終端機問答測驗關鍵要點。

別讓我滑倒 是什麼?

這項技能旨在於開發者與AI協作解決問題後,自動化地進行結構化回顧與學習強化。它會辨識出解決該問題的相關會話(若屬於專案則會包含該專案的所有歷程),並完整閱讀整個會話紀錄,不僅摘要,而是深入分析人類與AI各自在問題解決前遺漏的環節,以及人類可能抱持疑問或理解錯誤的概念。接著,它會針對每個學到的教訓,透過網路搜尋與擷取驗證,提供至少一個(通常更多)來自官方文件、供應商手冊或權威教程的深度連結,以確保資訊可靠。最後,它會產出兩個檔案:LEARNED.md(結構化報告)與 learned_quiz.py(終端機互動測驗),前者包含事件經過、分類的經驗教訓(人類、AI、共享)、測驗問題與解答鍵,後者則根據所有教訓與深度概念產生豐富的選擇題庫。此技能支援 Claude Code 等工具,透過檔案輸出與命令列執行,確保學習成果能被記錄與反覆練習。

相容平台~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 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

回顧解決問題的會話。產出兩個檔案:LEARNED.md 和 learned_quiz.py(一個終端機測驗)。

  1. 識別會話。使用最近的對話來找出與問題相符的對話。如果有多個合理的對話,請詢問使用者是哪一個。如果該會話屬於某個專案,也要回顧該專案中的其他對話。
  2. 閱讀整個會話,而不只是摘要。記錄在問題解決前,人類和 AI 各自遺漏了什麼。同時記錄人類必須憑信心接受、問過不止一次、或理解錯誤的概念:這些需要深入探討。
  3. 在撰寫之前先研究連結。為每個教訓找到至少一個連結。對於每個人類教訓,以及步驟 2 中的任何概念,找到 1 到 3 個深入探討的鏈接,從基本原理解釋背景。優先選擇(依序):官方文件或規格、供應商應用說明或手冊、知名教程或教科書,然後是信譽良好的部落格或問答。使用 WebSearch,然後使用 WebFetch 打開每個鏈接以確認其載入並涵蓋要點。放棄任何失敗或離題的鏈接。切勿編造 URL。
  4. 依序撰寫具有以下章節的 LEARNED.md:
    • 發生什麼事:3 到 5 個句子,加上狀態(已解決或未解決)。如果未解決,列出未完成事項。
    • 學到的教訓:分為人類、AI 和共享。對於每個教訓,給出要點、遺漏了什麼、用一句話總結教訓,以及一個連結(指名來源)。在每個需要背景知識的人類教訓下,添加一個「深入探討」子列表:每個條目為 標題、來源,以及一行關於它教導了什麼以及為何在此處有幫助的說明。
    • 測驗問題:3 到 5 個關鍵問題,標題為「測驗問題」,後面接著解答鍵。請注意,完整的問題集在 learned_quiz.py 中。
    • 連結:所使用的每個連結,按教訓分組,並指名來源。說明鏈接已在執行日期檢查,使用前應再次驗證。
    • 建議的一次性提示:一個簡潔的提示,可以避免本次會話中的問題。
  5. 標註聲明。將未經證實的聲明標記為未經證實。將來自搜尋結果的聲明標記為已報告,並連結來源。
  6. 不要將猜測呈現為發現。如果問題的原因未經確認,請這樣說。
  7. 根據下面的模板撰寫 learned_quiz.py。規則:
    • 僅使用 Python 3 標準庫。必須能在 macOS、Linux 和 Windows 終端機上執行。沒有 GUI。
    • 涵蓋每個概念,而不僅僅是 3 到 5 個測驗問題:每個人類教訓至少 2 個問題,每個 AI 和共享教訓至少 1 個問題,加上每個深入探討概念至少 1 個問題。通常為 10 到 25 個問題。混合記憶題、「你會先檢查什麼」題,以及「找出錯誤」題。
    • 每個問題:主題(人類、AI、共享或簡短的概念名稱)、4 個選項(包含合理的干擾項)、正確索引、1 到 2 句解釋原因,以及最相關的已驗證連結。
    • 只填入 TITLE、SOURCE 和 QUESTIONS。不要更改引擎。
    • 在發送前,執行 python3 -c "import ast,sys;ast.parse(open(sys.argv[1]).read())" learned_quiz.py,然後執行 python3 learned_quiz.py --list,並修正任何錯誤。檢查每個答案索引是否指向正確的選項。
  8. 保持 LEARNED.md 簡潔。不要在任一檔案中使用 em dash。
  9. 使用 SendUserFile 發送兩個檔案。在回覆中提供執行命令:python3 learned_quiz.py(選項:-r 快閃卡複習,-t TOPIC 過濾,-n N 限制,--list 列印全部,--seed N 固定順序)。

測驗模板(完全複製,替換佔位符和範例問題):

#!/usr/bin/env python3
"""LEARNED 問答:<主題>。執行:python3 learned_quiz.py [-r] [-t 主題] [-n N] [--list]"""
import argparse, random, sys, textwrap

TITLE = "<主題>"
SOURCE = "LEARNED.md, <日期>"
QUESTIONS = [
    {"topic": "Human", "q": "範例問題?",
     "choices": ["正確答案", "錯誤答案1", "錯誤答案2", "錯誤答案3"], "answer": 0,
     "why": "一兩句解釋原因。", "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("   按 Enter 揭示,按 q 離開:", {"", "q"}) == "q":
                sys.exit(0)
            ok = True
        else:
            a = ask(f"   答案 [{letters}],按 q 離開:", set(letters) | {"q"})
            if a == "q":
                break
            ok = a == right
            print("   正確。" if ok else f"   不對。答案:{right}")
        if review or not ok:
            print(wrap(f"{right}) {q['choices'][q['answer']]}"))
        print(wrap(q["why"]))
        if q.get("link"):
            print(wrap("更多資訊:" + q["link"]))
        if not ok:
            missed.append(q)
    return missed

def main():
    p = argparse.ArgumentParser(description=f"問答:{TITLE}")
    p.add_argument("-r", "--review", action="store_true", help="快閃卡模式,不計分")
    p.add_argument("-t", "--topic", help="僅限此主題(Human, AI, Shared, ...)")
    p.add_argument("-n", type=int, help="最多提問 N 個問題")
    p.add_argument("--list", action="store_true", help="列印所有問答並退出")
    p.add_argument("--seed", type=int, help="固定隨機順序")
    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"沒有主題為 {a.topic!r} 的問題。")
    if a.list:
        for i, q in enumerate(qs, 1):
            print(f"{i}. ({q['topic']}) {q['q']}\n{wrap('A: ' + q['choices'][q['answer']])}\n{wrap(q['why'])}")
            if q.get("link"):
                print(wrap("更多資訊:" + q["link"]))
        return
    random.shuffle(qs)
    qs = qs[:a.n] if a.n else qs
    print(f"{TITLE}\n來源:{SOURCE}\n共 {len(qs)} 個問題。")
    while qs:
        missed = run(qs, a.review)
        if a.review:
            break
        print(f"\n分數:{len(qs) - len(missed)}/{len(qs)}")
        if not missed or ask("重練答錯的題目?[y/n]:", {"y", "n"}) == "n":
            for q in missed:
                print(wrap(f"複習:{q['q']}", "- ") + ("\n" + wrap(q["link"]) if q.get("link") else ""))
            break
        qs = missed

if __name__ == "__main__":
    main()

相關技能