סקיל Diagnosing Bugs
diagnosing-bugs הוא סקיל לקלוד קוד שמכניס משמעת לתהליך מציאת באגים קשים ובעיות ביצועים. במקום לנחש ולשנות קוד באקראי, הוא מוביל את קלוד דרך שישה שלבים מסודרים: בניית לולאת משוב שתופסת את הבאג, שחזור ומזעור, ניסוח השערות, אינסטרומנטציה ממוקדת, תיקון עם טסט רגרסיה, וניקוי. העיקרון המרכזי שלו פשוט ועוצמתי: ברגע שיש לולאה שמסמנת אדום על הבאג הספציפי, מצאת אותו כמעט בוודאות. בפרויקטי הפיתוח שאני מוביל, השיטה הזאת חוסכת שעות של חיפוש עיוור. במדריך תקבלו את ששת השלבים במלואם, ארבעה תרחישי שימוש אמיתיים, וצ'קליסט לעבודה נכונה.
פקודת התקנה
npx skills add mattpocock/skills@diagnosing-bugs -g -y
ההתקנה מתבצעת דרך מנהל החבילות הרשמי של הסקילים בפקודה אחת. הסקיל הוא קובץ Markdown פתוח מהמאגר של מאט פוקוק, ומופעל במפורש כשמבקשים לאבחן באג. אפשר להוריד ולבדוק את הקוד דרך הכפתורים שבראש העמוד.
מה הסקיל כולל?
הסקיל מתעד שיטת אבחון בת שישה שלבים, עם דגש על השלב הראשון: בניית לולאת משוב הדוקה, מהירה ודטרמיניסטית שמסמנת אדום בדיוק על הבאג.
קוד הסקיל המלא
---
name: diagnosing-bugs
description: Diagnosis loop for hard bugs and performance regressions. Use when the user says "diagnose"/"debug this", or reports something broken/throwing/failing/slow.
---
# Diagnosing Bugs
A discipline for hard bugs. Skip phases only when explicitly justified.
When exploring the codebase, read `CONTEXT.md` (if it exists) to get a clear mental model of the relevant modules, and check ADRs in the area you're touching.
## Phase 1 — Build a feedback loop
**This is the skill.** Everything else is mechanical. If you have a **tight** pass/fail signal for the bug — one that goes red on _this_ bug — you will find the cause; bisection, hypothesis-testing, and instrumentation all just consume it. If you don't have one, no amount of staring at code will save you.
Spend disproportionate effort here. **Be aggressive. Be creative. Refuse to give up.**
### Ways to construct one — try them in roughly this order
1. **Failing test** at whatever seam reaches the bug — unit, integration, e2e.
2. **Curl / HTTP script** against a running dev server.
3. **CLI invocation** with a fixture input, diffing stdout against a known-good snapshot.
4. **Headless browser script** (Playwright / Puppeteer) — drives the UI, asserts on DOM/console/network.
5. **Replay a captured trace.** Save a real network request / payload / event log to disk; replay it through the code path in isolation.
6. **Throwaway harness.** Spin up a minimal subset of the system (one service, mocked deps) that exercises the bug code path with a single function call.
7. **Property / fuzz loop.** If the bug is "sometimes wrong output", run 1000 random inputs and look for the failure mode.
8. **Bisection harness.** If the bug appeared between two known states (commit, dataset, version), automate "boot at state X, check, repeat" so you can `git bisect run` it.
9. **Differential loop.** Run the same input through old-version vs new-version (or two configs) and diff outputs.
10. **HITL bash script.** Last resort. If a human must click, drive _them_ with `scripts/hitl-loop.template.sh` so the loop is still structured. Captured output feeds back to you.
Build the right feedback loop, and the bug is 90% fixed.
### Tighten the loop
Treat the loop as a product. Once you have _a_ loop, **tighten** it:
- Can I make it faster? (Cache setup, skip unrelated init, narrow the test scope.)
- Can I make the signal sharper? (Assert on the specific symptom, not "didn't crash".)
- Can I make it more deterministic? (Pin time, seed RNG, isolate filesystem, freeze network.)
A 30-second flaky loop is barely better than no loop; a 2-second deterministic one is tight — a debugging superpower.
### Non-deterministic bugs
The goal is not a clean repro but a **higher reproduction rate**. Loop the trigger 100×, parallelise, add stress, narrow timing windows, inject sleeps. A 50%-flake bug is debuggable; 1% is not — keep raising the rate until it's debuggable.
### When you genuinely cannot build a loop
Stop and say so explicitly. List what you tried. Ask the user for: (a) access to whatever environment reproduces it, (b) a captured artifact (HAR file, log dump, core dump, screen recording with timestamps), or (c) permission to add temporary production instrumentation. Do **not** proceed to hypothesise without a loop.
### Completion criterion — a tight loop that goes red
Phase 1 is done when the loop is **tight** and **red-capable**: you can name **one command** — a script path, a test invocation, a curl — that you have **already run at least once** (paste the invocation and its output), and that is:
- [ ] **Red-capable** — it drives the actual bug code path and asserts the **user's exact symptom**, so it can go red on this bug and green once fixed. Not "runs without erroring" — it must be able to _catch this specific bug_.
- [ ] **Deterministic** — same verdict every run (flaky bugs: a pinned, high reproduction rate, per above).
- [ ] **Fast** — seconds, not minutes.
- [ ] **Agent-runnable** — you can run it unattended; a human in the loop only via `scripts/hitl-loop.template.sh`.
If you catch yourself reading code to build a theory before this command exists, **stop — jumping straight to a hypothesis is the exact failure this skill prevents.** No red-capable command, no Phase 2.
## Phase 2 — Reproduce + minimise
Run the loop. Watch it go red — the bug appears.
Confirm:
- [ ] The loop produces the failure mode the **user** described — not a different failure that happens to be nearby. Wrong bug = wrong fix.
- [ ] The failure is reproducible across multiple runs (or, for non-deterministic bugs, reproducible at a high enough rate to debug against).
- [ ] You have captured the exact symptom (error message, wrong output, slow timing) so later phases can verify the fix actually addresses it.
### Minimise
Once it's red, shrink the repro to the **smallest scenario that still goes red**. Cut inputs, callers, config, data, and steps **one at a time**, re-running the loop after each cut — keep only what's load-bearing for the failure.
Why bother: a minimal repro shrinks the hypothesis space in Phase 3 (fewer moving parts left to suspect) and becomes the clean regression test in Phase 5.
Done when **every remaining element is load-bearing** — removing any one of them makes the loop go green.
Do not proceed until you have reproduced **and** minimised.
## Phase 3 — Hypothesise
Generate **3–5 ranked hypotheses** before testing any of them. Single-hypothesis generation anchors on the first plausible idea.
Each hypothesis must be **falsifiable**: state the prediction it makes.
> Format: "If <X> is the cause, then <changing Y> will make the bug disappear / <changing Z> will make it worse."
If you cannot state the prediction, the hypothesis is a vibe — discard or sharpen it.
**Show the ranked list to the user before testing.** They often have domain knowledge that re-ranks instantly ("we just deployed a change to #3"), or know hypotheses they've already ruled out. Cheap checkpoint, big time saver. Don't block on it — proceed with your ranking if the user is AFK.
## Phase 4 — Instrument
Each probe must map to a specific prediction from Phase 3. **Change one variable at a time.**
Tool preference:
1. **Debugger / REPL inspection** if the env supports it. One breakpoint beats ten logs.
2. **Targeted logs** at the boundaries that distinguish hypotheses.
3. Never "log everything and grep".
**Tag every debug log** with a unique prefix, e.g. `[DEBUG-a4f2]`. Cleanup at the end becomes a single grep. Untagged logs survive; tagged logs die.
**Perf branch.** For performance regressions, logs are usually wrong. Instead: establish a baseline measurement (timing harness, `performance.now()`, profiler, query plan), then bisect. Measure first, fix second.
## Phase 5 — Fix + regression test
Write the regression test **before the fix** — but only if there is a **correct seam** for it.
A correct seam is one where the test exercises the **real bug pattern** as it occurs at the call site. If the only available seam is too shallow (single-caller test when the bug needs multiple callers, unit test that can't replicate the chain that triggered the bug), a regression test there gives false confidence.
**If no correct seam exists, that itself is the finding.** Note it. The codebase architecture is preventing the bug from being locked down. Flag this for the next phase.
If a correct seam exists:
1. Turn the minimised repro into a failing test at that seam.
2. Watch it fail.
3. Apply the fix.
4. Watch it pass.
5. Re-run the Phase 1 feedback loop against the original (un-minimised) scenario.
## Phase 6 — Cleanup + post-mortem
Required before declaring done:
- [ ] Original repro no longer reproduces (re-run the Phase 1 loop)
- [ ] Regression test passes (or absence of seam is documented)
- [ ] All `[DEBUG-...]` instrumentation removed (`grep` the prefix)
- [ ] Throwaway prototypes deleted (or moved to a clearly-marked debug location)
- [ ] The hypothesis that turned out correct is stated in the commit / PR message — so the next debugger learns
**Then ask: what would have prevented this bug?** If the answer involves architectural change (no good test seam, tangled callers, hidden coupling) hand off to the `/improve-codebase-architecture` skill with the specifics. Make the recommendation **after** the fix is in, not before — you have more information now than when you started.
מה זה diagnosing-bugs ולמה הסקיל הזה שונה?
diagnosing-bugs פותר את הטעות הנפוצה ביותר בדיבאג: קפיצה ישר להשערה ולשינוי קוד לפני שמבינים מה קורה. התוצאה היא שעות של ניחושים, תיקונים שלא עוזרים, ולפעמים שבירה של דברים אחרים. הסקיל מחליף את הכאוס הזה במשמעת מסודרת.
מה שמייחד אותו הוא ההתעקשות על לולאת משוב כשלב ראשון. במקום לבהות בקוד, הסקיל דורש לבנות פקודה אחת, טסט או סקריפט, שמריצה את הבאג ומסמנת אדום עליו, מהר ובאופן דטרמיניסטי. ברגע שהלולאה קיימת, כל השאר, ביסקציה, בדיקת השערות ואינסטרומנטציה, פשוט צורכים אותה ומובילים לסיבה. הסקיל אפילו אוסר להתחיל לבנות תיאוריה לפני שהפקודה הזאת קיימת.
ההבדל מורגש בזמן ובביטחון. במקום תיקון שאולי עובד, מקבלים תהליך שמסתיים בטסט רגרסיה שמוכיח שהבאג נפתר. בשילוב עם סקיל improve-codebase-architecture, כשאין תפר טוב לטסט, הסקיל יודע להצביע על הבעיה הארכיטקטונית שמונעת נעילה של הבאג, וזה הופך כל באג להזדמנות לשפר את הקוד.
מה diagnosing-bugs נותן לקלוד קוד?
הסקיל מוסיף לקלוד משמעת של חוקר באגים מנוסה: לא לנחש, אלא לבנות אמצעי מדידה שמוביל לסיבה האמיתית.
לולאת משוב כשלב ראשון
הסקיל מכריח את קלוד לבנות תחילה פקודה שמסמנת אדום על הבאג, מהירה ודטרמיניסטית. זה השלב היחיד שבאמת חשוב, וברגע שהוא קיים הבאג כמעט פתור. כל ניסיון לקפוץ להשערה לפני כן נחסם.
מזעור שיטתי
אחרי שהלולאה אדומה, הסקיל מצמצם את התרחיש למינימום שעדיין נכשל, קלט אחרי קלט. כל אלמנט שנשאר נושא משקל, וזה מקטין דרמטית את מרחב ההשערות ויוצר בסיס לטסט הרגרסיה.
השערות מדורגות ונבדקות
במקום להיתפס לרעיון הראשון, הסקיל מנסח שלוש עד חמש השערות מדורגות, כל אחת עם תחזית הניתנת להפרכה. הוא בודק אותן אחת-אחת, משתנה אחד בכל פעם, כך שהאבחון מבוסס ולא אקראי.
תיקון שמוכיח את עצמו
הסקיל כותב טסט רגרסיה לפני התיקון, מוודא שהוא נכשל, מתקן, ומוודא שהוא עובר. בסוף מגיע ניקוי מלא של לוגים מתויגים ותחקיר קצר, כך שהבאג נסגר לתמיד ולא חוזר בעתיד.
ארבע היכולות הופכות את קלוד מ"מנחש ומתקן" ל"חוקר שמודד ומוכיח". בעבודות שלי, השיטה הזאת קיצרה אבחון של באגים שהיו תקועים ימים, לכדי שעות ספורות, ועם ביטחון שהתיקון באמת אוחז.
למי הסקיל הזה מתאים?
מפתחים שנתקעים על באגים קשים: זה הקהל המובהק. הסקיל נותן שיטה מסודרת במקום תסכול, ומבטיח שגם הבאג העקשן ביותר נסגר בצורה מבוססת. השילוב עם סקיל grill-with-docs מחזק את האבחון מול התיעוד.
צוותים עם בעיות ביצועים: לרגרסיות ביצועים הסקיל מציע ענף ייעודי, מדידה לפני תיקון במקום ניחוש. כך מאתרים את צוואר הבקבוק האמיתי ולא משפרים את המקום הלא נכון.
מובילי פיתוח שאכפת להם מאיכות: הדרישה לטסט רגרסיה לכל באג בונה בהדרגה רשת ביטחון שמונעת חזרה של תקלות. זה משדרג את יציבות המוצר לאורך זמן.
סוכנויות ופרילנסרים: כשמתחזקים קוד של לקוחות שונים, שיטה אחידה לאבחון חוסכת זמן ומשדרת מקצועיות. גם בעבודות אוטומציה שלי, באג באוטומציה חי דורש אבחון מסודר לפני שנוגעים בו.
מפתחי סולו: בלי עמית להתייעץ איתו, השיטה היא בן הזוג שמונע מכם להסתבך בניחושים. היא מחליפה את "אולי זה זה" ב"בוא נבדוק".
מי שפחות יתאים: טייפו פשוט או שגיאת תחביר גלויה לא צריכים שישה שלבים. הסקיל מבריק דווקא בבאגים הקשים, הלא דטרמיניסטיים, או באלה שתקועים זמן רב.
איך diagnosing-bugs עזר לי בפרויקטים אמיתיים
באג לסירוגין שתקע פרויקט שבוע
באג שהופיע רק לפעמים תסכל את הצוות. הסקיל התעקש קודם להעלות את שיעור השחזור: הרצנו את הטריגר מאות פעמים במקביל עד שהבאג נתפס באופן עקבי. ברגע שהייתה לולאה אדומה ויציבה, הסיבה התגלתה תוך שעה.
רגרסיית ביצועים אחרי עדכון
אחרי עדכון, מסך נטען לאט. במקום לנחש, הסקיל הוביל למדידה: ביססנו בייסליין ובדקנו ביסקציה בין הגרסאות. המדידה הצביעה על השאילתה האשמה במדויק, והתיקון היה ממוקד במקום ניסוי וטעייה.
באג קצה שהצריך מזעור
באג הופיע רק בצירוף נתונים מסוים. הסקיל מיזער את התרחיש קלט אחרי קלט עד שנשאר רק מה שהכרחי. התרחיש המינימלי חשף את הסיבה והפך לטסט רגרסיה נקי שמגן מפני חזרה.
באג שחשף בעיה ארכיטקטונית
בזמן התיקון התברר שאין תפר טוב לטסט. במקום להתעלם, הסקיל סימן זאת כממצא והפנה לשיפור הארכיטקטורה. תיקנו גם את הבאג וגם את החולשה שאיפשרה לו להסתתר, וכך מנענו משפחה שלמה של תקלות עתידיות.
ארבעת המקרים מראים שהסקיל לא רק מתקן באגים, הוא משנה את הגישה אליהם: ממרוץ ניחושים מתסכל לתהליך מדיד ובטוח. כשכל באג מסתיים בטסט רגרסיה ובתחקיר, איכות הקוד עולה עם כל תקלה שנפתרת.
סיכום
סקיל diagnosing-bugs הוא כלי חובה לכל מי שמתמודד עם באגים קשים. הוא מחליף ניחושים בשיטה בת שישה שלבים, עם דגש על לולאת משוב שמסמנת אדום על הבאג, וזה ההבדל בין חיפוש עיוור לבין אבחון מדויק.
אם אתם מתחילים, בפעם הבאה שמשהו נשבר, בקשו מקלוד לאבחן עם הסקיל. הוא יתעקש קודם לבנות לולאה שתופסת את הבאג, ומשם הדרך לסיבה קצרה. תרגישו את ההבדל כבר באבחון הראשון.
בפוסטים הבאים אמשיך לסקור סקילים שמשדרגים את איכות הפיתוח. האתר של דביר נעמן מרכז את כל הכלים, השיטות והליווי שאני מציע לעסקים שרוצים לבנות תוכנה אמינה עם בינה מלאכותית.
שיתוף הסקיל
שאלות ותשובות
מה זה בעצם הסקיל diagnosing-bugs?
זה סקיל לקלוד קוד שמספק שיטת אבחון מסודרת בת שישה שלבים לבאגים קשים ולבעיות ביצועים. הוא מוביל את קלוד מבניית לולאת משוב, דרך שחזור, השערות ואינסטרומנטציה, ועד תיקון עם טסט רגרסיה וניקוי. המטרה היא אבחון מבוסס ראיות במקום ניחושים.
מה זאת לולאת משוב ולמה היא כל כך חשובה?
לולאת משוב היא פקודה אחת, טסט או סקריפט, שמריצה את הבאג ומסמנת אדום כשהוא קורה. היא חשובה כי ברגע שיש אות חד שמגיב לבאג הספציפי, אפשר לבדוק השערות במהירות ולהגיע לסיבה. הסקיל רואה בה את לב התהליך, ואוסר להתחיל לנחש לפני שהיא קיימת.
איך מתקינים את הסקיל בקלוד קוד?
בפקודה אחת דרך מנהל החבילות הרשמי של הסקילים, כפי שמופיע בקופסת ההתקנה למעלה. הסקיל הוא קובץ Markdown פתוח מהמאגר של מאט פוקוק. מפעילים אותו כשמבקשים מקלוד לאבחן באג או כשמשהו נשבר, והוא ינווט את התהליך שלב אחר שלב.
האם הסקיל מתאים גם לבאגים לא דטרמיניסטיים?
כן, ויש לו גישה ייעודית לכך. במקום לדרוש שחזור מושלם, הוא שואף להעלות את שיעור השחזור: להריץ את הטריגר פעמים רבות, במקביל ותחת עומס, עד שהבאג נתפס מספיק כדי לעבוד מולו. באג שמופיע בחצי מהפעמים ניתן לאבחון, ואחד באחוז אפשר להפוך לכזה.
האם הסקיל ישנה את הקוד שלי בעצמו?
הסקיל מנווט תהליך, והתיקון עצמו מתבצע רק בשלב מאוחר ובהיגיון ברור. קודם נבנית לולאה, מבוצע שחזור ומזעור, ונבדקות השערות. רק כשהסיבה ברורה נכתב טסט רגרסיה ומוחל תיקון, ולבסוף מתבצע ניקוי של כל האינסטרומנטציה הזמנית. אתם רואים ומבינים כל שלב.
מה ההבדל בין הסקיל הזה לדיבאג רגיל?
דיבאג רגיל נוטה לקפוץ ישר להשערה ולשינוי קוד, מה שמוביל לניחושים ולתיקונים שלא אוחזים. הסקיל הופך את הסדר: קודם אמצעי מדידה אמין, אחר כך השערות מדורגות, ורק בסוף תיקון מאומת. זו ההתמדה שהופכת באג עקשן לפתיר.
האם הסקיל מתאים גם לבעיות ביצועים?
בהחלט, ויש לו ענף ייעודי לכך. לרגרסיות ביצועים הוא ממליץ למדוד לפני שמתקנים: לבסס בייסליין עם כלי תזמון או פרופיילר, ואז לבצע ביסקציה כדי לאתר את מקור ההאטה. כך משפרים את המקום הנכון ולא מנחשים.
מה קורה אם אי אפשר לבנות לולאת משוב?
הסקיל מורה לעצור ולומר זאת במפורש, במקום להמשיך לנחש. הוא מפרט מה נוסה, ומבקש מהמשתמש גישה לסביבה ששוחזרת בה הבעיה, או ארטיפקט שנלכד כמו לוג או הקלטה. ההתעקשות הזאת מונעת בזבוז זמן על תיאוריות בלי בסיס.