---
name: debug
description: Interactive hypothesis-driven debugging with NDJSON logging, iterative until resolved
argument-hint: "\"bug description or error message\""
allowed-tools: TodoWrite(*), Task(*), AskUserQuestion(*), Read(*), Grep(*), Glob(*), Bash(*), Edit(*), Write(*)
---

# Workflow Debug Command (/workflow:debug)

## Overview

Evidence-based interactive debugging command. Systematically identifies root causes through hypothesis-driven logging and iterative verification.

**Core workflow**: Explore → Add Logging → Reproduce → Analyze Log → Fix → Verify

## Usage

```bash
/workflow:debug <BUG_DESCRIPTION>

# Arguments
<bug-description>          Bug description, error message, or stack trace (required)
```

## Execution Process

```
Session Detection:
   ├─ Check if debug session exists for this bug
   ├─ EXISTS + debug.log has content → Analyze mode
   └─ NOT_FOUND or empty log → Explore mode

Explore Mode:
   ├─ Locate error source in codebase
   ├─ Generate testable hypotheses (dynamic count)
   ├─ Add NDJSON logging instrumentation
   └─ Output: Hypothesis list + await user reproduction

Analyze Mode:
   ├─ Parse debug.log, validate each hypothesis
   └─ Decision:
       ├─ Confirmed → Fix root cause
       ├─ Inconclusive → Add more logging, iterate
       └─ All rejected → Generate new hypotheses

Fix & Cleanup:
   ├─ Apply fix based on confirmed hypothesis
   ├─ User verifies
   ├─ Remove debug instrumentation
   └─ If not fixed → Return to Analyze mode
```

## Implementation

### Session Setup & Mode Detection

```javascript
const getUtc8ISOString = () => new Date(Date.now() + 8 * 60 * 60 * 1000).toISOString()

const bugSlug = bug_description.toLowerCase().replace(/[^a-z0-9]+/g, '-').substring(0, 30)
const dateStr = getUtc8ISOString().substring(0, 10)

const sessionId = `DBG-${bugSlug}-${dateStr}`
const sessionFolder = `.workflow/.debug/${sessionId}`
const debugLogPath = `${sessionFolder}/debug.log`

// Auto-detect mode
const sessionExists = fs.existsSync(sessionFolder)
const logHasContent = sessionExists && fs.existsSync(debugLogPath) && fs.statSync(debugLogPath).size > 0

const mode = logHasContent ? 'analyze' : 'explore'

if (!sessionExists) {
  bash(`mkdir -p ${sessionFolder}`)
}
```

---

### Explore Mode

**Step 1.1: Locate Error Source**

```javascript
// Extract keywords from bug description
const keywords = extractErrorKeywords(bug_description)
// e.g., ['Stack Length', '未找到', 'registered 0']

// Search codebase for error locations
for (const keyword of keywords) {
  Grep({ pattern: keyword, path: ".", output_mode: "content", "-C": 3 })
}

// Identify affected files and functions
const affectedLocations = [...]  // from search results
```

**Step 1.2: Generate Hypotheses (Dynamic)**

```javascript
// Hypothesis categories based on error pattern
const HYPOTHESIS_PATTERNS = {
  "not found|missing|undefined|未找到": "data_mismatch",
  "0|empty|zero|registered 0": "logic_error",
  "timeout|connection|sync": "integration_issue",
  "type|format|parse": "type_mismatch"
}

// Generate hypotheses based on actual issue (NOT fixed count)
function generateHypotheses(bugDescription, affectedLocations) {
  const hypotheses = []

  // Analyze bug and create targeted hypotheses
  // Each hypothesis has:
  // - id: H1, H2, ... (dynamic count)
  // - description: What might be wrong
  // - testable_condition: What to log
  // - logging_point: Where to add instrumentation

  return hypotheses  // Could be 1, 3, 5, or more
}

const hypotheses = generateHypotheses(bug_description, affectedLocations)
```

**Step 1.3: Add NDJSON Instrumentation**

For each hypothesis, add logging at the relevant 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
```

**Output to user**:
```
## Hypotheses Generated

Based on error "{bug_description}", generated {n} hypotheses:

{hypotheses.map(h => `
### ${h.id}: ${h.description}
- Logging at: ${h.logging_point}
- Testing: ${h.testable_condition}
`).join('')}

**Debug log**: ${debugLogPath}

**Next**: Run reproduction steps, then come back for analysis.
```

---

### Analyze Mode

```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'
}
```

**Output**:
```
## Evidence Analysis

Analyzed ${entries.length} log entries.

${results.map(r => `
### ${r.id}: ${r.description}
- **Status**: ${r.verdict}
- **Evidence**: ${JSON.stringify(r.evidence)}
- **Reason**: ${r.reason}
`).join('')}

${confirmedHypothesis ? `
## Root Cause Identified

**${confirmedHypothesis.id}**: ${confirmedHypothesis.description}

Ready to fix.
` : `
## Need More Evidence

Add more logging or refine hypotheses.
`}
```

---

### Fix & Cleanup

```javascript
// Apply fix based on confirmed hypothesis
// ... Edit affected files

// After user verifies fix works:

// Remove debug instrumentation (search for region markers)
const instrumentedFiles = Grep({
  pattern: "# region debug|// region debug",
  output_mode: "files_with_matches"
})

for (const file of instrumentedFiles) {
  // Remove content between region markers
  removeDebugRegions(file)
}

console.log(`
## Debug Complete

- Root cause: ${confirmedHypothesis.description}
- Fix applied to: ${modifiedFiles.join(', ')}
- Debug instrumentation removed
`)
```

---

## Debug Log Format (NDJSON)

Each line is a JSON object:

```json
{"sid":"DBG-xxx-2025-12-18","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) |

## Session Folder

```
.workflow/.debug/DBG-{slug}-{date}/
├── debug.log          # NDJSON log (main artifact)
└── resolution.md      # Summary after fix (optional)
```

## Iteration Flow

```
First Call (/workflow:debug "error"):
   ├─ No session exists → Explore mode
   ├─ Extract error keywords, search codebase
   ├─ Generate hypotheses, add logging
   └─ Await user reproduction

After Reproduction (/workflow:debug "error"):
   ├─ Session exists + debug.log has content → Analyze mode
   ├─ Parse log, evaluate hypotheses
   └─ Decision:
       ├─ Confirmed → Fix → User verify
       │   ├─ Fixed → Cleanup → Done
       │   └─ Not fixed → Add logging → Iterate
       ├─ Inconclusive → Add logging → Iterate
       └─ All rejected → New hypotheses → Iterate

Output:
   └─ .workflow/.debug/DBG-{slug}-{date}/debug.log
```

## Error Handling

| Situation | Action |
|-----------|--------|
| Empty debug.log | Verify reproduction triggered the code path |
| All hypotheses rejected | Generate new hypotheses with broader scope |
| Fix doesn't work | Iterate with more granular logging |
| >5 iterations | Escalate to `/workflow:lite-fix` with evidence |
