Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Interactive hypothesis-driven debugging with documented exploration, understanding evolution, and analysis-assisted correction.
.claude/skills/catlog22-debug-with-file/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-16 | ✗→✓ | ▲ Improved | 175% | 0% |
| case-17 | ✗→✓ | ▲ Improved | 140% | 0% |
| case-08 | ✗→✓ | ▲ Improved | 85% | 0% |
| case-09 | ✗→✓ | ▲ Improved | 193% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 56% | 0% |
Enhanced evidence-based debugging with documented exploration process. Records understanding evolution, consolidates insights, and uses analysis to correct misunderstandings.
Core workflow: Explore → Document → Log → Analyze → Correct Understanding → Fix → Verify
Key enhancements over /prompts:debug:
$BUG
Run ccw spec load --category debug for known issues, workarounds, and root-cause notes.
Session Detection:
├─ Check if debug session exists for this bug
├─ EXISTS + understanding.md exists → Continue mode
└─ NOT_FOUND → Explore mode
Explore Mode:
├─ Locate error source in codebase
├─ Document initial understanding in understanding.md
├─ Generate testable hypotheses with analysis validation
├─ Add NDJSON logging instrumentation
└─ Output: Hypothesis list + await user reproduction
Analyze Mode:
├─ Parse debug.log, validate each hypothesis
├─ Use analysis to evaluate hypotheses and correct understanding
├─ Update understanding.md with:
│ ├─ New evidence
│ ├─ Corrected misunderstandings (strikethrough + correction)
│ └─ Consolidated current understanding
└─ Decision:
├─ Confirmed → Fix root cause
├─ Inconclusive → Add more logging, iterate
└─ All rejected → Assisted new hypotheses
Fix & Cleanup:
├─ Apply fix based on confirmed hypothesis
├─ User verifies
├─ Document final understanding + lessons learned
├─ Remove debug instrumentation
└─ If not fixed → Return to Analyze mode##### Step 0: Determine Project Root
检测项目根目录,确保 .workflow/ 产物位置正确:
bashPROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
优先通过 git 获取仓库根目录;非 git 项目回退到 pwd 取当前绝对路径。 存储为 {projectRoot},后续所有 .workflow/ 路径必须以此为前缀。
javascriptconst getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString() const projectRoot = bash('git rev-parse --show-toplevel 2>/dev/null || pwd').trim() const bugSlug = "$BUG".toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 30) const dateStr = getUtc8ISOString().substring(0, 10) const sessionId = `DBG-${dateStr}-${bugSlug}` const sessionFolder = `${projectRoot}/.workflow/.debug/${sessionId}` const debugLogPath = `${sessionFolder}/debug.log` const understandingPath = `${sessionFolder}/understanding.md` const hypothesesPath = `${sessionFolder}/hypotheses.json` // Auto-detect mode const sessionExists = fs.existsSync(sessionFolder) const hasUnderstanding = sessionExists && fs.existsSync(understandingPath) const logHasContent = sessionExists && fs.existsSync(debugLogPath) && fs.statSync(debugLogPath).size > 0 const mode = logHasContent ? 'analyze' : (hasUnderstanding ? 'continue' : 'explore') if (!sessionExists) { bash(`mkdir -p ${sessionFolder}`) }
javascript// Extract keywords from bug description const keywords = extractErrorKeywords("$BUG") // Search codebase for error locations const searchResults = [] for (const keyword of keywords) { const results = Grep({ pattern: keyword, path: ".", output_mode: "content", "-C": 3 }) searchResults.push({ keyword, results }) } // Identify affected files and functions const affectedLocations = analyzeSearchResults(searchResults)
Create understanding.md:
markdown# Understanding Document **Session ID**: ${sessionId} **Bug Description**: $BUG **Started**: ${getUtc8ISOString()} --- ## Exploration Timeline ### Iteration 1 - Initial Exploration (${timestamp}) #### Current Understanding Based on bug description and initial code search: - Error pattern: ${errorPattern} - Affected areas: ${affectedLocations.map(l => l.file).join(', ')} - Initial hypothesis: ${initialThoughts} #### Evidence from Code Search ${searchResults.map(r => ` **Keyword: "${r.keyword}"** - Found in: ${r.results.files.join(', ')} - Key findings: ${r.insights} `).join('\n')} #### Next Steps - Generate testable hypotheses - Add instrumentation - Await reproduction --- ## Current Consolidated Understanding ${initialConsolidatedUnderstanding}
Analyze the bug and generate 3-5 testable hypotheses:
javascript// Hypothesis generation based on error pattern const HYPOTHESIS_PATTERNS = { "not found|missing|undefined|未找到": "data_mismatch", "0|empty|zero|registered": "logic_error", "timeout|connection|sync": "integration_issue", "type|format|parse": "type_mismatch" } function generateHypotheses(bugDescription, affectedLocations) { // Generate targeted hypotheses based on error analysis // Each hypothesis includes: // - id: H1, H2, ... // - description: What might be wrong // - testable_condition: What to log // - logging_point: Where to add instrumentation // - evidence_criteria: What confirms/rejects it return hypotheses }
Save to hypotheses.json:
json{ "iteration": 1, "timestamp": "2025-01-21T10:00:00+08:00", "hypotheses": [ { "id": "H1", "description": "Data structure mismatch - expected key not present", "testable_condition": "Check if target key exists in dict", "logging_point": "file.py:func:42", "evidence_criteria": { "confirm": "data shows missing key", "reject": "key exists with valid value" }, "likelihood": 1, "status": "pending" } ] }
For each hypothesis, add logging at the specified location:
Python template:
python# region debug [H{n}] try: import json, time _dbg = { "sid": "{sessionId}", "hid": "H{n}", "loc": "{file}:{line}", "msg": "{testable_condition}", "data": { # Capture relevant values here }, "ts": int(time.time() * 1000) } with open(r"{debugLogPath}", "a", encoding="utf-8") as _f: _f.write(json.dumps(_dbg, ensure_ascii=False) + "\n") except: pass # endregion
JavaScript/TypeScript template:
javascript// region debug [H{n}] try { require('fs').appendFileSync("{debugLogPath}", JSON.stringify({ sid: "{sessionId}", hid: "H{n}", loc: "{file}:{line}", msg: "{testable_condition}", data: { /* Capture relevant values */ }, ts: Date.now() }) + "\n"); } catch(_) {} // endregion
## Hypotheses Generated
Based on error "$BUG", generated {n} hypotheses:
{hypotheses.map(h => `
### ${h.id}: ${h.description}
- Logging at: ${h.logging_point}
- Testing: ${h.testable_condition}
- Evidence to confirm: ${h.evidence_criteria.confirm}
- Evidence to reject: ${h.evidence_criteria.reject}
`).join('')}
**Debug log**: ${debugLogPath}
**Next**: Run reproduction steps, then come back for analysis.javascript// Parse NDJSON log const entries = Read(debugLogPath).split('\n') .filter(l => l.trim()) .map(l => JSON.parse(l)) // Group by hypothesis const byHypothesis = groupBy(entries, 'hid') // Validate each hypothesis for (const [hid, logs] of Object.entries(byHypothesis)) { const hypothesis = hypotheses.find(h => h.id === hid) const latestLog = logs[logs.length - 1] // Check if evidence confirms or rejects hypothesis const verdict = evaluateEvidence(hypothesis, latestLog.data) // Returns: 'confirmed' | 'rejected' | 'inconclusive' }
Review the debug log and evaluate each hypothesis:
Append new iteration to understanding.md:
markdown### Iteration ${n} - Evidence Analysis (${timestamp}) #### Log Analysis Results ${results.map(r => ` **${r.id}**: ${r.verdict.toUpperCase()} - Evidence: ${JSON.stringify(r.evidence)} - Reasoning: ${r.reason} `).join('\n')} #### Corrected Understanding Previous misunderstandings identified and corrected: ${corrections.map(c => ` - ~~${c.wrong}~~ → ${c.corrected} - Why wrong: ${c.reason} - Evidence: ${c.evidence} `).join('\n')} #### New Insights ${newInsights.join('\n- ')} ${confirmedHypothesis ? ` #### Root Cause Identified **${confirmedHypothesis.id}**: ${confirmedHypothesis.description} Evidence supporting this conclusion: ${confirmedHypothesis.supportingEvidence} ` : ` #### Next Steps ${nextSteps} `} --- ## Current Consolidated Understanding (Updated) ${consolidatedUnderstanding}
json{ "iteration": 2, "timestamp": "2025-01-21T10:15:00+08:00", "hypotheses": [ { "id": "H1", "status": "rejected", "verdict_reason": "Evidence shows key exists with valid value", "evidence": {...} }, { "id": "H2", "status": "confirmed", "verdict_reason": "Log data confirms timing issue", "evidence": {...} } ], "corrections": [ { "wrong_assumption": "...", "corrected_to": "...", "reason": "..." } ] }
Based on confirmed hypothesis, implement the fix in the affected files.
Append to understanding.md:
markdown### Iteration ${n} - Resolution (${timestamp}) #### Fix Applied - Modified files: ${modifiedFiles.join(', ')} - Fix description: ${fixDescription} - Root cause addressed: ${rootCause} #### Verification Results ${verificationResults} #### Lessons Learned What we learned from this debugging session: 1. ${lesson1} 2. ${lesson2} 3. ${lesson3} #### Key Insights for Future - ${insight1} - ${insight2}
Remove debug instrumentation by searching for region markers:
javascriptconst instrumentedFiles = Grep({ pattern: "# region debug|// region debug", output_mode: "files_with_matches" }) for (const file of instrumentedFiles) { // Remove content between region markers removeDebugRegions(file) }
{projectRoot}/.workflow/.debug/DBG-{date}-{slug}/
├── debug.log # NDJSON log (execution evidence)
├── understanding.md # Exploration timeline + consolidated understanding
└── hypotheses.json # Hypothesis history with verdictsmarkdown# Understanding Document **Session ID**: DBG-xxx-2025-01-21 **Bug Description**: [original description] **Started**: 2025-01-21T10:00:00+08:00 --- ## Exploration Timeline ### Iteration 1 - Initial Exploration (2025-01-21 10:00) #### Current Understanding ... #### Evidence from Code Search ... #### Hypotheses Generated ... ### Iteration 2 - Evidence Analysis (2025-01-21 10:15) #### Log Analysis Results ... #### Corrected Understanding - ~~[wrong]~~ → [corrected] #### Analysis Results ... --- ## Current Consolidated Understanding ### What We Know - [valid understanding points] ### What Was Disproven - ~~[disproven assumptions]~~ ### Current Investigation Focus [current focus] ### Remaining Questions - [open questions]
Each line is a JSON object:
json{"sid":"DBG-xxx-2025-01-21","hid":"H1","loc":"file.py:func:42","msg":"Check dict keys","data":{"keys":["a","b"],"target":"c","found":false},"ts":1734567890123}
| Field | Description | |-------|-------------| | sid | Session ID | | hid | Hypothesis ID (H1, H2, ...) | | loc | Code location | | msg | What's being tested | | data | Captured values | | ts | Timestamp (ms) |
First Call (BUG="error"):
├─ No session exists → Explore mode
├─ Extract error keywords, search codebase
├─ Document initial understanding in understanding.md
├─ Generate hypotheses
├─ Add logging instrumentation
└─ Await user reproduction
After Reproduction (BUG="error"):
├─ Session exists + debug.log has content → Analyze mode
├─ Parse log, evaluate hypotheses
├─ Update understanding.md with:
│ ├─ Evidence analysis results
│ ├─ Corrected misunderstandings (strikethrough)
│ ├─ New insights
│ └─ Updated consolidated understanding
├─ Update hypotheses.json with verdicts
└─ Decision:
├─ Confirmed → Fix → Document resolution
├─ Inconclusive → Add logging, document next steps
└─ All rejected → Assisted new hypotheses
Output:
├─ {projectRoot}/.workflow/.debug/DBG-{date}-{slug}/debug.log
├─ {projectRoot}/.workflow/.debug/DBG-{date}-{slug}/understanding.md (evolving document)
└─ {projectRoot}/.workflow/.debug/DBG-{date}-{slug}/hypotheses.json (history)| Situation | Action | |-----------|--------| | Empty debug.log | Verify reproduction triggered the code path | | All hypotheses rejected | Generate new hypotheses based on disproven assumptions | | Fix doesn't work | Document failed fix attempt, iterate with refined understanding | | >5 iterations | Review consolidated understanding, escalate with full context | | Understanding too long | Consolidate aggressively, archive old iterations to separate file |
When updating "Current Consolidated Understanding":
Bad (cluttered):
markdown## Current Consolidated Understanding In iteration 1 we thought X, but in iteration 2 we found Y, then in iteration 3... Also we checked A and found B, and then we checked C...
Good (consolidated):
markdown## Current Consolidated Understanding ### What We Know - Error occurs during runtime update, not initialization - Config value is None (not missing key) ### What Was Disproven - ~~Initialization error~~ (Timing evidence) - ~~Missing key hypothesis~~ (Key exists) ### Current Investigation Focus Why is config value None during update?
| Feature | Description | |---------|-------------| | NDJSON logging | Structured debug log with hypothesis tracking | | Hypothesis generation | Analysis-assisted hypothesis creation | | Exploration documentation | understanding.md with timeline | | Understanding evolution | Timeline + corrections tracking | | Error correction | Strikethrough + reasoning for wrong assumptions | | Consolidated learning | Current understanding section | | Hypothesis history | hypotheses.json with verdicts | | Analysis validation | At key decision points |
Best suited for:
Now execute the debug-with-file workflow for bug: $BUG
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-22 | pass→pass | 12,129 | 6,577 | -46% | 1 | 1 | 0% | 1,977 | 5,380 | +172% | 0 | 0 | — |
case-15 | pass→pass | 11,990 | 7,156 | -40% | 1 | 1 | 0% | 1,899 | 5,379 | +183% | 0 | 0 | — |
case-16 | fail→pass | 11,938 | 7,381 | -38% | 1 | 1 | 0% | 1,933 | 5,324 | +175% | 0 | 0 | — |
case-01 | fail→fail | 5,321 | 10,850 | +104% | 1 | 1 | 0% | 290 | 4,666 | +1509% | 0 | 0 | — |
case-02 | fail→fail | 4,768 | 4,792 | +1% | 1 | 1 | 0% | 231 | 4,480 | +1839% | 0 | 0 | — |
case-03 | fail→fail | 17,303 | 9,825 | -43% | 1 | 1 | 0% | 285 | 4,515 | +1484% | 0 | 0 | — |
case-04 | pass→fail | 19,846 | 5,056 | -75% | 1 | 1 | 0% | 3,232 | 4,571 | +41% | 0 | 0 | — |
case-17 | fail→pass | 15,357 | 5,370 | -65% | 1 | 1 | 0% | 2,128 | 5,105 | +140% | 0 | 0 | — |
case-05 | pass→fail | 13,559 | 10,496 | -23% | 1 | 1 | 0% | 2,762 | 4,593 | +66% | 0 | 0 | — |
case-06 | pass→fail | 11,762 | 4,549 | -61% | 1 | 1 | 0% | 2,435 | 4,484 | +84% | 0 | 0 | — |
case-07 | pass→pass | 14,438 | 10,021 | -31% | 1 | 1 | 0% | 2,852 | 6,255 | +119% | 0 | 0 | — |
case-08 | fail→pass | 16,718 | 7,429 | -56% | 1 | 1 | 0% | 2,949 | 5,463 | +85% | 0 | 0 | — |
case-09 | fail→pass | 11,445 | 5,000 | -56% | 1 | 1 | 0% | 1,812 | 5,308 | +193% | 0 | 0 | — |
case-10 | fail→pass | 17,140 | 6,420 | -63% | 1 | 1 | 0% | 3,538 | 5,536 | +56% | 0 | 0 | — |
case-11 | fail→pass | 12,178 | 5,996 | -51% | 1 | 1 | 0% | 1,964 | 5,341 | +172% | 0 | 0 | — |
case-12 | pass→fail | 11,801 | 5,882 | -50% | 1 | 1 | 0% | 1,728 | 4,463 | +158% | 0 | 0 | — |
case-13 | fail→pass | 12,371 | 8,787 | -29% | 1 | 1 | 0% | 2,290 | 6,125 | +167% | 0 | 0 | — |
case-14 | pass→pass | 15,769 | 6,835 | -57% | 1 | 1 | 0% | 2,627 | 5,308 | +102% | 0 | 0 | — |
case-18 | fail→pass | 10,347 | 6,772 | -35% | 1 | 1 | 0% | 1,763 | 5,205 | +195% | 0 | 0 | — |
case-19 | pass→fail | 24,619 | 7,628 | -69% | 1 | 1 | 0% | 1,598 | 5,260 | +229% | 0 | 0 | — |
case-20 | fail→pass | 9,598 | 2,848 | -70% | 1 | 1 | 0% | 1,526 | 4,665 | +206% | 0 | 0 | — |
case-21 | fail→pass | 10,383 | 6,144 | -41% | 1 | 1 | 0% | 1,754 | 5,223 | +198% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted, and 15 counted toward the lift figure. The other 7 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +23 percentage points is the difference between those two pass rates over the 15 comparable cases. 5 cases got worse with the skill loaded, and they are included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.