debtpilot 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.4
2
+ Name: debtpilot
3
+ Version: 0.1.0
4
+ Summary: Track technical debt before it blows up in production
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/YOUR_GITHUB_USERNAME/debtpilot
7
+ Project-URL: Issues, https://github.com/YOUR_GITHUB_USERNAME/debtpilot/issues
8
+ Keywords: technical-debt,code-quality,developer-tools,cli,linting
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Quality Assurance
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: rich>=13.0
22
+ Provides-Extra: daemon
23
+ Requires-Dist: websockets>=12.0; extra == "daemon"
24
+ Requires-Dist: watchdog>=4.0; extra == "daemon"
25
+ Provides-Extra: notify
26
+ Requires-Dist: win10toast>=0.9; platform_system == "Windows" and extra == "notify"
27
+ Requires-Dist: plyer>=2.1; extra == "notify"
28
+ Provides-Extra: full
29
+ Requires-Dist: debtpilot[daemon,notify]; extra == "full"
30
+
31
+ # DebtPilot
32
+
33
+ > Track technical debt before it blows up in production.
34
+
35
+ Every IDE catches syntax errors. DebtPilot does something no IDE can —
36
+ it knows that `payments/stripe.js` has been edited 30 times by 4 different
37
+ developers, has a TODO from 8 months ago, and a complexity score of 24.
38
+ That combination is your next production incident.
39
+
40
+ ---
41
+
42
+ ## Install
43
+
44
+ pip install debtpilot
45
+
46
+ Full install (file watcher + live notifications):
47
+
48
+ pip install "debtpilot[full]"
49
+
50
+ ---
51
+
52
+ ## Quickstart — 4 commands, done
53
+
54
+ 1. Scan your project
55
+ debtpilot scan .
56
+
57
+ 2. See the report
58
+ debtpilot report
59
+
60
+ 3. Block bad commits automatically
61
+ debtpilot hook --install
62
+
63
+ 4. Start live background watching
64
+ debtpilot start --dir .
65
+
66
+ ---
67
+
68
+ ## What it does
69
+
70
+ | Command | What happens |
71
+ |---|---|
72
+ | `debtpilot scan .` | Scores every file 0-100 for technical debt |
73
+ | `debtpilot report` | Shows top debt files in a ranked table |
74
+ | `debtpilot file <path>` | Deep breakdown of one file |
75
+ | `debtpilot ai <path>` | AI explains exactly what to fix (needs Gemini key) |
76
+ | `debtpilot predict` | Predicts which file will cause your next bug |
77
+ | `debtpilot dashboard` | Generates an HTML dashboard — open in browser |
78
+ | `debtpilot report-pdf` | Generates a print-ready PDF report |
79
+ | `debtpilot alerts` | Shows active danger alerts |
80
+ | `debtpilot todos` | Lists stale TODOs by age |
81
+ | `debtpilot hook --install` | Blocks commits above the debt threshold |
82
+ | `debtpilot start` | Starts live file watcher + WebSocket server |
83
+ | `debtpilot status` | Full health check of your DebtPilot setup |
84
+ | `debtpilot digest --send` | Sends weekly email summary to your team |
85
+
86
+ ---
87
+
88
+ ## Debt Score (0-100)
89
+
90
+ | Grade | Score | Meaning |
91
+ |-------|-------|---------|
92
+ | A | 0-25 | Healthy |
93
+ | B | 26-45 | Watch |
94
+ | C | 46-65 | Concerning |
95
+ | D | 66-80 | Dangerous |
96
+ | F | 81-100 | Critical — fix before next deploy |
97
+
98
+ Score = weighted combination of: git churn (30%) + complexity (25%) +
99
+ lint issues (20%) + stale TODOs (15%) + staleness (10%).
100
+
101
+ ---
102
+
103
+ ## AI Fix Suggestions (optional)
104
+
105
+ Get a free Gemini API key at aistudio.google.com then:
106
+
107
+ debtpilot config --gemini-key YOUR_KEY
108
+ debtpilot ai src/payments.py
109
+
110
+ DebtPilot sends the file context to Gemini and gets back exact fix
111
+ suggestions with code examples and effort estimates.
112
+
113
+ ---
114
+
115
+ ## Weekly Email Digest
116
+
117
+ debtpilot config --gmail you@gmail.com --gmail-password YOUR_APP_PASS --recipients team@company.com
118
+ debtpilot digest --send
119
+
120
+ Use a Gmail App Password from: myaccount.google.com/apppasswords
121
+
122
+ ---
123
+
124
+ ## Auto-start on Windows login
125
+
126
+ debtpilot autostart --install --dir .
127
+
128
+ DebtPilot will start silently in the background every time Windows starts.
129
+ No manual debtpilot start needed.
130
+
131
+ ---
132
+
133
+ ## Requirements
134
+
135
+ - Python 3.10 or higher
136
+ - git in PATH
137
+ - pylint / mypy / eslint — optional, for richer lint scores
138
+
139
+ ---
140
+
141
+ ## License
142
+
143
+ MIT
@@ -0,0 +1,113 @@
1
+ # DebtPilot
2
+
3
+ > Track technical debt before it blows up in production.
4
+
5
+ Every IDE catches syntax errors. DebtPilot does something no IDE can —
6
+ it knows that `payments/stripe.js` has been edited 30 times by 4 different
7
+ developers, has a TODO from 8 months ago, and a complexity score of 24.
8
+ That combination is your next production incident.
9
+
10
+ ---
11
+
12
+ ## Install
13
+
14
+ pip install debtpilot
15
+
16
+ Full install (file watcher + live notifications):
17
+
18
+ pip install "debtpilot[full]"
19
+
20
+ ---
21
+
22
+ ## Quickstart — 4 commands, done
23
+
24
+ 1. Scan your project
25
+ debtpilot scan .
26
+
27
+ 2. See the report
28
+ debtpilot report
29
+
30
+ 3. Block bad commits automatically
31
+ debtpilot hook --install
32
+
33
+ 4. Start live background watching
34
+ debtpilot start --dir .
35
+
36
+ ---
37
+
38
+ ## What it does
39
+
40
+ | Command | What happens |
41
+ |---|---|
42
+ | `debtpilot scan .` | Scores every file 0-100 for technical debt |
43
+ | `debtpilot report` | Shows top debt files in a ranked table |
44
+ | `debtpilot file <path>` | Deep breakdown of one file |
45
+ | `debtpilot ai <path>` | AI explains exactly what to fix (needs Gemini key) |
46
+ | `debtpilot predict` | Predicts which file will cause your next bug |
47
+ | `debtpilot dashboard` | Generates an HTML dashboard — open in browser |
48
+ | `debtpilot report-pdf` | Generates a print-ready PDF report |
49
+ | `debtpilot alerts` | Shows active danger alerts |
50
+ | `debtpilot todos` | Lists stale TODOs by age |
51
+ | `debtpilot hook --install` | Blocks commits above the debt threshold |
52
+ | `debtpilot start` | Starts live file watcher + WebSocket server |
53
+ | `debtpilot status` | Full health check of your DebtPilot setup |
54
+ | `debtpilot digest --send` | Sends weekly email summary to your team |
55
+
56
+ ---
57
+
58
+ ## Debt Score (0-100)
59
+
60
+ | Grade | Score | Meaning |
61
+ |-------|-------|---------|
62
+ | A | 0-25 | Healthy |
63
+ | B | 26-45 | Watch |
64
+ | C | 46-65 | Concerning |
65
+ | D | 66-80 | Dangerous |
66
+ | F | 81-100 | Critical — fix before next deploy |
67
+
68
+ Score = weighted combination of: git churn (30%) + complexity (25%) +
69
+ lint issues (20%) + stale TODOs (15%) + staleness (10%).
70
+
71
+ ---
72
+
73
+ ## AI Fix Suggestions (optional)
74
+
75
+ Get a free Gemini API key at aistudio.google.com then:
76
+
77
+ debtpilot config --gemini-key YOUR_KEY
78
+ debtpilot ai src/payments.py
79
+
80
+ DebtPilot sends the file context to Gemini and gets back exact fix
81
+ suggestions with code examples and effort estimates.
82
+
83
+ ---
84
+
85
+ ## Weekly Email Digest
86
+
87
+ debtpilot config --gmail you@gmail.com --gmail-password YOUR_APP_PASS --recipients team@company.com
88
+ debtpilot digest --send
89
+
90
+ Use a Gmail App Password from: myaccount.google.com/apppasswords
91
+
92
+ ---
93
+
94
+ ## Auto-start on Windows login
95
+
96
+ debtpilot autostart --install --dir .
97
+
98
+ DebtPilot will start silently in the background every time Windows starts.
99
+ No manual debtpilot start needed.
100
+
101
+ ---
102
+
103
+ ## Requirements
104
+
105
+ - Python 3.10 or higher
106
+ - git in PATH
107
+ - pylint / mypy / eslint — optional, for richer lint scores
108
+
109
+ ---
110
+
111
+ ## License
112
+
113
+ MIT
@@ -0,0 +1,143 @@
1
+ Metadata-Version: 2.4
2
+ Name: debtpilot
3
+ Version: 0.1.0
4
+ Summary: Track technical debt before it blows up in production
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/YOUR_GITHUB_USERNAME/debtpilot
7
+ Project-URL: Issues, https://github.com/YOUR_GITHUB_USERNAME/debtpilot/issues
8
+ Keywords: technical-debt,code-quality,developer-tools,cli,linting
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: Environment :: Console
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Topic :: Software Development :: Quality Assurance
19
+ Requires-Python: >=3.10
20
+ Description-Content-Type: text/markdown
21
+ Requires-Dist: rich>=13.0
22
+ Provides-Extra: daemon
23
+ Requires-Dist: websockets>=12.0; extra == "daemon"
24
+ Requires-Dist: watchdog>=4.0; extra == "daemon"
25
+ Provides-Extra: notify
26
+ Requires-Dist: win10toast>=0.9; platform_system == "Windows" and extra == "notify"
27
+ Requires-Dist: plyer>=2.1; extra == "notify"
28
+ Provides-Extra: full
29
+ Requires-Dist: debtpilot[daemon,notify]; extra == "full"
30
+
31
+ # DebtPilot
32
+
33
+ > Track technical debt before it blows up in production.
34
+
35
+ Every IDE catches syntax errors. DebtPilot does something no IDE can —
36
+ it knows that `payments/stripe.js` has been edited 30 times by 4 different
37
+ developers, has a TODO from 8 months ago, and a complexity score of 24.
38
+ That combination is your next production incident.
39
+
40
+ ---
41
+
42
+ ## Install
43
+
44
+ pip install debtpilot
45
+
46
+ Full install (file watcher + live notifications):
47
+
48
+ pip install "debtpilot[full]"
49
+
50
+ ---
51
+
52
+ ## Quickstart — 4 commands, done
53
+
54
+ 1. Scan your project
55
+ debtpilot scan .
56
+
57
+ 2. See the report
58
+ debtpilot report
59
+
60
+ 3. Block bad commits automatically
61
+ debtpilot hook --install
62
+
63
+ 4. Start live background watching
64
+ debtpilot start --dir .
65
+
66
+ ---
67
+
68
+ ## What it does
69
+
70
+ | Command | What happens |
71
+ |---|---|
72
+ | `debtpilot scan .` | Scores every file 0-100 for technical debt |
73
+ | `debtpilot report` | Shows top debt files in a ranked table |
74
+ | `debtpilot file <path>` | Deep breakdown of one file |
75
+ | `debtpilot ai <path>` | AI explains exactly what to fix (needs Gemini key) |
76
+ | `debtpilot predict` | Predicts which file will cause your next bug |
77
+ | `debtpilot dashboard` | Generates an HTML dashboard — open in browser |
78
+ | `debtpilot report-pdf` | Generates a print-ready PDF report |
79
+ | `debtpilot alerts` | Shows active danger alerts |
80
+ | `debtpilot todos` | Lists stale TODOs by age |
81
+ | `debtpilot hook --install` | Blocks commits above the debt threshold |
82
+ | `debtpilot start` | Starts live file watcher + WebSocket server |
83
+ | `debtpilot status` | Full health check of your DebtPilot setup |
84
+ | `debtpilot digest --send` | Sends weekly email summary to your team |
85
+
86
+ ---
87
+
88
+ ## Debt Score (0-100)
89
+
90
+ | Grade | Score | Meaning |
91
+ |-------|-------|---------|
92
+ | A | 0-25 | Healthy |
93
+ | B | 26-45 | Watch |
94
+ | C | 46-65 | Concerning |
95
+ | D | 66-80 | Dangerous |
96
+ | F | 81-100 | Critical — fix before next deploy |
97
+
98
+ Score = weighted combination of: git churn (30%) + complexity (25%) +
99
+ lint issues (20%) + stale TODOs (15%) + staleness (10%).
100
+
101
+ ---
102
+
103
+ ## AI Fix Suggestions (optional)
104
+
105
+ Get a free Gemini API key at aistudio.google.com then:
106
+
107
+ debtpilot config --gemini-key YOUR_KEY
108
+ debtpilot ai src/payments.py
109
+
110
+ DebtPilot sends the file context to Gemini and gets back exact fix
111
+ suggestions with code examples and effort estimates.
112
+
113
+ ---
114
+
115
+ ## Weekly Email Digest
116
+
117
+ debtpilot config --gmail you@gmail.com --gmail-password YOUR_APP_PASS --recipients team@company.com
118
+ debtpilot digest --send
119
+
120
+ Use a Gmail App Password from: myaccount.google.com/apppasswords
121
+
122
+ ---
123
+
124
+ ## Auto-start on Windows login
125
+
126
+ debtpilot autostart --install --dir .
127
+
128
+ DebtPilot will start silently in the background every time Windows starts.
129
+ No manual debtpilot start needed.
130
+
131
+ ---
132
+
133
+ ## Requirements
134
+
135
+ - Python 3.10 or higher
136
+ - git in PATH
137
+ - pylint / mypy / eslint — optional, for richer lint scores
138
+
139
+ ---
140
+
141
+ ## License
142
+
143
+ MIT
@@ -0,0 +1,23 @@
1
+ README.md
2
+ pyproject.toml
3
+ debtpilot.egg-info/PKG-INFO
4
+ debtpilot.egg-info/SOURCES.txt
5
+ debtpilot.egg-info/dependency_links.txt
6
+ debtpilot.egg-info/entry_points.txt
7
+ debtpilot.egg-info/requires.txt
8
+ debtpilot.egg-info/top_level.txt
9
+ debtpilot_core/__init__.py
10
+ debtpilot_core/ai_advisor.py
11
+ debtpilot_core/autostart.py
12
+ debtpilot_core/cli.py
13
+ debtpilot_core/daemon.py
14
+ debtpilot_core/dashboard.py
15
+ debtpilot_core/database.py
16
+ debtpilot_core/digest.py
17
+ debtpilot_core/hooks.py
18
+ debtpilot_core/linter.py
19
+ debtpilot_core/notifier.py
20
+ debtpilot_core/predictor.py
21
+ debtpilot_core/reporter.py
22
+ debtpilot_core/scanner.py
23
+ debtpilot_core/scorer.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ debtpilot = debtpilot_core.cli:main
@@ -0,0 +1,14 @@
1
+ rich>=13.0
2
+
3
+ [daemon]
4
+ websockets>=12.0
5
+ watchdog>=4.0
6
+
7
+ [full]
8
+ debtpilot[daemon,notify]
9
+
10
+ [notify]
11
+ plyer>=2.1
12
+
13
+ [notify:platform_system == "Windows"]
14
+ win10toast>=0.9
@@ -0,0 +1 @@
1
+ debtpilot_core
@@ -0,0 +1,6 @@
1
+ """
2
+ DebtPilot — Track technical debt before it blows up in production.
3
+ """
4
+
5
+ __version__ = "0.1.0"
6
+ __author__ = "DebtPilot"
@@ -0,0 +1,206 @@
1
+ """
2
+ DebtPilot - AI Fix Suggestions using Google Gemini (free API).
3
+ Sends risky code to Gemini and gets back exact fix suggestions.
4
+ """
5
+
6
+ import os
7
+ import json
8
+ import urllib.request
9
+ import urllib.error
10
+ from pathlib import Path
11
+ from typing import Dict, List, Optional
12
+
13
+ GEMINI_API_URL = "https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent"
14
+
15
+
16
+ def get_api_key() -> Optional[str]:
17
+ # First check environment variable
18
+ key = os.environ.get("DEBTPILOT_GEMINI_KEY")
19
+ if key:
20
+ return key
21
+ # Then check config file
22
+ config_path = Path.home() / ".debtpilot" / "config.json"
23
+ if config_path.exists():
24
+ try:
25
+ data = json.loads(config_path.read_text())
26
+ return data.get("gemini_api_key")
27
+ except Exception:
28
+ pass
29
+ return None
30
+
31
+
32
+ def save_api_key(api_key: str) -> None:
33
+ config_dir = Path.home() / ".debtpilot"
34
+ config_dir.mkdir(parents=True, exist_ok=True)
35
+ config_path = config_dir / "config.json"
36
+ data = {}
37
+ if config_path.exists():
38
+ try:
39
+ data = json.loads(config_path.read_text())
40
+ except Exception:
41
+ pass
42
+ data["gemini_api_key"] = api_key
43
+ config_path.write_text(json.dumps(data, indent=2))
44
+
45
+
46
+ def _call_gemini(prompt: str, api_key: str) -> str:
47
+ payload = json.dumps({
48
+ "contents": [{"parts": [{"text": prompt}]}],
49
+ "generationConfig": {"temperature": 0.3, "maxOutputTokens": 1500}
50
+ }).encode()
51
+
52
+ req = urllib.request.Request(
53
+ f"{GEMINI_API_URL}?key={api_key}",
54
+ data=payload,
55
+ headers={"Content-Type": "application/json"},
56
+ method="POST",
57
+ )
58
+ try:
59
+ with urllib.request.urlopen(req, timeout=30) as r:
60
+ result = json.loads(r.read())
61
+ return result["candidates"][0]["content"]["parts"][0]["text"]
62
+ except urllib.error.HTTPError as e:
63
+ body = e.read().decode()
64
+ raise RuntimeError(f"Gemini API error {e.code}: {body}")
65
+ except Exception as e:
66
+ raise RuntimeError(f"Failed to call Gemini: {e}")
67
+
68
+
69
+ def analyze_file(
70
+ filepath: str,
71
+ score_data: Dict,
72
+ lint_issues: List[Dict],
73
+ todos: List[Dict],
74
+ complexity: Dict,
75
+ ) -> Dict:
76
+ """
77
+ Send file context to Gemini and get back structured fix suggestions.
78
+ Returns dict with summary, fixes, and priority actions.
79
+ """
80
+ api_key = get_api_key()
81
+ if not api_key:
82
+ return {
83
+ "error": "No Gemini API key configured. Run: debtpilot config --gemini-key YOUR_KEY",
84
+ "summary": "AI advisor not configured. The rest of DebtPilot works without it.",
85
+ "fixes": [],
86
+ "priority_actions": ["Run: debtpilot config --gemini-key YOUR_KEY to enable AI suggestions"],
87
+ "risk_level": "UNKNOWN",
88
+ "estimated_fix_time": "N/A",
89
+ "ai_available": False,
90
+ }
91
+
92
+ # Read file content (first 150 lines to stay within token limits)
93
+ try:
94
+ lines = Path(filepath).read_text(encoding="utf-8", errors="ignore").splitlines()
95
+ code_preview = "\n".join(lines[:150])
96
+ total_lines = len(lines)
97
+ except OSError:
98
+ code_preview = "(could not read file)"
99
+ total_lines = 0
100
+
101
+ # Build lint summary
102
+ errors = [i for i in lint_issues if i.get("severity") == "error"][:5]
103
+ warnings = [i for i in lint_issues if i.get("severity") == "warning"][:5]
104
+ lint_summary = "\n".join(
105
+ [f" ERROR L{i['line']}: {i['message']}" for i in errors] +
106
+ [f" WARNING L{i['line']}: {i['message']}" for i in warnings]
107
+ ) or " None detected"
108
+
109
+ # Build TODO summary
110
+ todo_summary = "\n".join(
111
+ [f" L{t['line']} ({t.get('age_days', 0)} days old): {t.get('text', '')}" for t in todos[:5]]
112
+ ) or " None"
113
+
114
+ # Build complexity summary
115
+ funcs = complexity.get("functions", [])[:5]
116
+ complexity_summary = "\n".join(
117
+ [f" {f['name']}() at L{f['line']}: complexity {f['complexity']}" for f in funcs]
118
+ ) or f" avg={complexity.get('avg_complexity', 0)}"
119
+
120
+ prompt = f"""You are a senior software engineer doing a technical debt review.
121
+
122
+ FILE: {filepath}
123
+ TOTAL LINES: {total_lines}
124
+ DEBT SCORE: {score_data.get('total', 0)}/100 (Grade {score_data.get('grade', '?')} — {score_data.get('label', '')})
125
+
126
+ SUB-SCORES:
127
+ Churn (how often edited by many people): {score_data.get('churn_score', 0)}/100
128
+ Complexity (how hard to understand): {score_data.get('complexity_score', 0)}/100
129
+ Lint issues: {score_data.get('lint_score', 0)}/100
130
+ Stale TODOs: {score_data.get('todo_score', 0)}/100
131
+ Staleness: {score_data.get('staleness_score', 0)}/100
132
+
133
+ LINT ISSUES:
134
+ {lint_summary}
135
+
136
+ STALE TODOs:
137
+ {todo_summary}
138
+
139
+ COMPLEX FUNCTIONS:
140
+ {complexity_summary}
141
+
142
+ CODE PREVIEW (first 150 lines):
143
+ {code_preview}
144
+
145
+ Respond ONLY with a valid JSON object in this exact format, no markdown, no explanation outside the JSON:
146
+ {{
147
+ "summary": "2-3 sentence plain English summary of the main problems",
148
+ "risk_level": "LOW or MEDIUM or HIGH or CRITICAL",
149
+ "fixes": [
150
+ {{
151
+ "title": "short title of the fix",
152
+ "problem": "what is wrong and why it matters",
153
+ "solution": "exactly what to do",
154
+ "code_example": "short before/after code snippet if relevant, else empty string",
155
+ "effort": "15min or 1hr or half-day or 1day"
156
+ }}
157
+ ],
158
+ "priority_actions": [
159
+ "action 1 — most important thing to do first",
160
+ "action 2",
161
+ "action 3"
162
+ ],
163
+ "estimated_fix_time": "total estimated time to resolve all issues"
164
+ }}"""
165
+
166
+ raw = _call_gemini(prompt, api_key)
167
+
168
+ # Strip markdown code fences if present
169
+ raw = raw.strip()
170
+ if raw.startswith("```"):
171
+ raw = raw.split("```")[1]
172
+ if raw.startswith("json"):
173
+ raw = raw[4:]
174
+ raw = raw.strip()
175
+
176
+ try:
177
+ return json.loads(raw)
178
+ except json.JSONDecodeError:
179
+ return {
180
+ "summary": raw[:500],
181
+ "risk_level": "UNKNOWN",
182
+ "fixes": [],
183
+ "priority_actions": [],
184
+ "estimated_fix_time": "unknown",
185
+ "parse_error": True,
186
+ }
187
+
188
+
189
+ def quick_explain(code_snippet: str, question: str) -> str:
190
+ """Ask Gemini a quick question about a code snippet."""
191
+ api_key = get_api_key()
192
+ if not api_key:
193
+ return "No Gemini API key configured. Run: debtpilot config --gemini-key YOUR_KEY"
194
+
195
+ prompt = f"""You are a helpful senior developer. Answer concisely.
196
+
197
+ Question: {question}
198
+
199
+ Code:{code_snippet[:1000]}
200
+
201
+ Give a direct, practical answer in 3-5 sentences maximum."""
202
+
203
+ try:
204
+ return _call_gemini(prompt, api_key)
205
+ except RuntimeError as e:
206
+ return f"AI error: {e}"