
Tech Debt Tracker
- 587 installs
- 23.5k repo stars
- Updated July 17, 2026
- alirezarezvani/claude-skills
tech-debt-tracker is a Claude skill that automatically surfaces technical debt, code smells, and security risks for developers who need structured debt inventories before refactors compound.
About
tech-debt-tracker is a Claude skill that scans project source trees and emits structured technical debt reports with severity, file paths, and health metrics. Example output shows scanner_version 1.0.0 summarizing 25 files scanned, 12,543 lines reviewed, 28 debt items found, a 68.5 health score, and 1.12 debt density across modules like user_service.py. Detected item types include large functions, duplicate code, and security-adjacent smells, each tagged with IDs such as DEBT-0001 and status fields for triage. Developers reach for tech-debt-tracker during operate and refactor cycles when they need quantified debt backlogs instead of subjective code review notes. The skill helps prioritize remediation before debt blocks feature velocity.
- Scans 25+ files and flags 28 debt items with severity levels
- Produces health score, debt density, and categorized findings (large_function, duplicate_code, security_risk, high_compl
- Outputs structured JSON report with file paths, descriptions, and remediation status
- Hard-gate: review critical and high severity items before merging
- Next-skill handoff: feed prioritized list into refactoring workflow
Tech Debt Tracker by the numbers
- 587 all-time installs (skills.sh)
- Ranked #218 of 1,356 Code Review & Quality skills by installs in the Skillselion catalog
- Security screen: LOW risk (skills.sh audit)
- Data as of Jul 31, 2026 (Skillselion catalog sync)
npx skills add https://github.com/alirezarezvani/claude-skills --skill tech-debt-trackerAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 587 |
|---|---|
| repo stars | ★ 23.5k |
| Security audit | 3 / 3 scanners passed |
| Last updated | July 17, 2026 |
| Repository | alirezarezvani/claude-skills ↗ |
How do you quantify technical debt in a codebase?
Automatically surface technical debt, code smells, and security risks before they compound.
Who is it for?
Tech leads running periodic debt scans who want numbered debt items, health scores, and file-level smell reports for sprint planning.
Skip if: Greenfield projects with no legacy code or teams that only need single-file lint fixes without portfolio-level debt metrics.
When should I use this skill?
The user asks to find code smells, measure tech debt density, or generate a refactor backlog with health scores from a source scan.
What you get
Debt item inventory with IDs, health score, debt density metrics, and severity-ranked code smell reports.
- debt item JSON report
- health score summary
By the numbers
- Example scan reports 28 debt items across 25 files and 12,543 lines
- Scanner version documented as 1.0.0 with health_score and debt_density metrics
Files
Tech Debt Tracker
Tier: POWERFUL 🔥 Category: Engineering Process Automation Expertise: Code Quality, Technical Debt Management, Software Engineering
Overview
Tech debt is one of the most insidious challenges in software development - it compounds over time, slowing down development velocity, increasing maintenance costs, and reducing code quality. This skill provides a comprehensive framework for identifying, analyzing, prioritizing, and tracking technical debt across codebases.
Tech debt isn't just about messy code - it encompasses architectural shortcuts, missing tests, outdated dependencies, documentation gaps, and infrastructure compromises. Like financial debt, it accrues "interest" through increased development time, higher bug rates, and reduced team velocity.
What This Skill Provides
This skill offers three interconnected tools that form a complete tech debt management system:
1. Debt Scanner - Automatically identifies tech debt signals in your codebase 2. Debt Prioritizer - Analyzes and prioritizes debt items using cost-of-delay frameworks 3. Debt Dashboard - Tracks debt trends over time and provides executive reporting
Together, these tools enable engineering teams to make data-driven decisions about tech debt, balancing new feature development with maintenance work.
Quick Start — scan → prioritize → dashboard
All paths relative to this skill folder. The scanner's JSON output feeds the prioritizer directly; dated inventory snapshots feed the dashboard.
1. Scan the codebase
python3 scripts/debt_scanner.py /path/to/codebase --format json --output debt_inventory.jsonEmits debt_inventory.json with scan_metadata, summary, debt_items[], file_statistics, and recommendations. Report the summary counts to the user. (Dry run: assets/sample_codebase.)
2. Prioritize the backlog
python3 scripts/debt_prioritizer.py debt_inventory.json --framework wsjf --team-size 6 --sprint-capacity 20 --format json --output debt_priorities.jsonFrameworks: cost_of_delay (default), wsjf, rice. Output contains prioritized_backlog (work top-down), sprint_allocation (paste into sprint planning), and insights.
3. Track trends over time
Keep dated snapshots (debt_YYYY-MM-DD.json), then:
python3 scripts/debt_dashboard.py --input-dir snapshots/ --period monthly --format both --output debt_dashboardOr pass files explicitly (samples: assets/historical_debt_2024-01-15.json assets/historical_debt_2024-02-01.json). The dashboard reports trend direction and executive-ready summaries — use it to verify a cleanup sprint actually reduced debt.
Verification loop
After a remediation sprint: re-run step 1, re-run step 3 with the new snapshot, and assert the targeted categories' counts dropped. A cleanup that doesn't move the dashboard is rework, not debt paydown.
Technical Debt Classification Framework
→ See references/debt-frameworks.md for details (also: references/debt-classification-taxonomy.md, references/prioritization-framework.md, references/stakeholder-communication-templates.md)
Common Pitfalls and How to Avoid Them
1. Analysis Paralysis
Problem: Spending too much time analyzing debt instead of fixing it. Solution: Set time limits for analysis, use "good enough" scoring for most items.
2. Perfectionism
Problem: Trying to eliminate all debt instead of managing it. Solution: Focus on high-impact debt, accept that some debt is acceptable.
3. Ignoring Business Context
Problem: Prioritizing technical elegance over business value. Solution: Always tie debt work to business outcomes and customer impact.
4. Inconsistent Application
Problem: Some teams adopt practices while others ignore them. Solution: Make debt tracking part of standard development workflow.
5. Tool Over-Engineering
Problem: Building complex debt management systems that nobody uses. Solution: Start simple, iterate based on actual usage patterns.
Technical debt management is not just about writing better code - it's about creating sustainable development practices that balance short-term delivery pressure with long-term system health. Use these tools and frameworks to make informed decisions about when and how to invest in debt reduction.
{
"scan_metadata": {
"directory": "/project/src",
"scan_date": "2024-01-15T09:00:00",
"scanner_version": "1.0.0"
},
"summary": {
"total_files_scanned": 25,
"total_lines_scanned": 12543,
"total_debt_items": 28,
"health_score": 68.5,
"debt_density": 1.12
},
"debt_items": [
{
"id": "DEBT-0001",
"type": "large_function",
"description": "create_user function in user_service.py is 89 lines long",
"file_path": "src/user_service.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0002",
"type": "duplicate_code",
"description": "Password validation logic duplicated in 3 locations",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0003",
"type": "security_risk",
"description": "Hardcoded API key in payment_processor.py",
"file_path": "src/payment_processor.py",
"severity": "critical",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0004",
"type": "high_complexity",
"description": "process_payment function has cyclomatic complexity of 24",
"file_path": "src/payment_processor.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0005",
"type": "missing_docstring",
"description": "PaymentProcessor class missing docstring",
"file_path": "src/payment_processor.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0006",
"type": "todo_comment",
"description": "TODO: Move this to configuration file",
"file_path": "src/user_service.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0007",
"type": "empty_catch_blocks",
"description": "Empty catch block in update_user method",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0008",
"type": "magic_numbers",
"description": "Magic number 1800 used for lock timeout",
"file_path": "src/user_service.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0009",
"type": "deep_nesting",
"description": "Deep nesting detected: 6 levels in preferences handling",
"file_path": "src/frontend.js",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0010",
"type": "long_line",
"description": "Line too long: 156 characters",
"file_path": "src/frontend.js",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0011",
"type": "commented_code",
"description": "Dead code left in comments",
"file_path": "src/frontend.js",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0012",
"type": "global_variables",
"description": "Global variable userCache should be encapsulated",
"file_path": "src/frontend.js",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0013",
"type": "synchronous_ajax",
"description": "Synchronous AJAX call blocks UI thread",
"file_path": "src/frontend.js",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0014",
"type": "hardcoded_values",
"description": "Tax rates hardcoded in payment processing logic",
"file_path": "src/payment_processor.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0015",
"type": "no_error_handling",
"description": "API calls without proper error handling",
"file_path": "src/payment_processor.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0016",
"type": "inefficient_algorithm",
"description": "O(n) user search could be optimized with indexing",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0017",
"type": "memory_leak_risk",
"description": "Event listeners attached without cleanup",
"file_path": "src/frontend.js",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0018",
"type": "sql_injection_risk",
"description": "Potential SQL injection in user query",
"file_path": "src/database.py",
"severity": "critical",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0019",
"type": "outdated_dependency",
"description": "jQuery version 2.1.4 has known security vulnerabilities",
"file_path": "package.json",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0020",
"type": "test_debt",
"description": "No unit tests for critical payment processing logic",
"file_path": "src/payment_processor.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0021",
"type": "large_class",
"description": "UserService class has 15 methods",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0022",
"type": "unused_imports",
"description": "Unused import: sys",
"file_path": "src/utils.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0023",
"type": "missing_type_hints",
"description": "Function get_user_score missing type hints",
"file_path": "src/user_service.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0024",
"type": "circular_dependency",
"description": "Circular import between user_service and auth_service",
"file_path": "src/user_service.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0025",
"type": "inconsistent_naming",
"description": "Variable name userID should be user_id",
"file_path": "src/auth.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0026",
"type": "broad_exception",
"description": "Catching generic Exception instead of specific types",
"file_path": "src/database.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0027",
"type": "deprecated_api",
"description": "Using deprecated datetime.utcnow() method",
"file_path": "src/utils.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0028",
"type": "logging_issue",
"description": "Using print() instead of proper logging",
"file_path": "src/payment_processor.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
}
]
}{
"scan_metadata": {
"directory": "/project/src",
"scan_date": "2024-02-01T14:30:00",
"scanner_version": "1.0.0"
},
"summary": {
"total_files_scanned": 27,
"total_lines_scanned": 13421,
"total_debt_items": 22,
"health_score": 74.2,
"debt_density": 0.81
},
"debt_items": [
{
"id": "DEBT-0001",
"type": "large_function",
"description": "create_user function in user_service.py is 89 lines long",
"file_path": "src/user_service.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0002",
"type": "duplicate_code",
"description": "Password validation logic duplicated in 3 locations",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0004",
"type": "high_complexity",
"description": "process_payment function has cyclomatic complexity of 24",
"file_path": "src/payment_processor.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0005",
"type": "missing_docstring",
"description": "PaymentProcessor class missing docstring",
"file_path": "src/payment_processor.py",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0007",
"type": "empty_catch_blocks",
"description": "Empty catch block in update_user method",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0009",
"type": "deep_nesting",
"description": "Deep nesting detected: 6 levels in preferences handling",
"file_path": "src/frontend.js",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0010",
"type": "long_line",
"description": "Line too long: 156 characters",
"file_path": "src/frontend.js",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0011",
"type": "commented_code",
"description": "Dead code left in comments",
"file_path": "src/frontend.js",
"severity": "low",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0012",
"type": "global_variables",
"description": "Global variable userCache should be encapsulated",
"file_path": "src/frontend.js",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0013",
"type": "synchronous_ajax",
"description": "Synchronous AJAX call blocks UI thread",
"file_path": "src/frontend.js",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0014",
"type": "hardcoded_values",
"description": "Tax rates hardcoded in payment processing logic",
"file_path": "src/payment_processor.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0015",
"type": "no_error_handling",
"description": "API calls without proper error handling",
"file_path": "src/payment_processor.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0016",
"type": "inefficient_algorithm",
"description": "O(n) user search could be optimized with indexing",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0017",
"type": "memory_leak_risk",
"description": "Event listeners attached without cleanup",
"file_path": "src/frontend.js",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0021",
"type": "large_class",
"description": "UserService class has 15 methods",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0024",
"type": "circular_dependency",
"description": "Circular import between user_service and auth_service",
"file_path": "src/user_service.py",
"severity": "high",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0026",
"type": "broad_exception",
"description": "Catching generic Exception instead of specific types",
"file_path": "src/database.py",
"severity": "medium",
"detected_date": "2024-01-15T09:00:00",
"status": "identified"
},
{
"id": "DEBT-0029",
"type": "missing_validation",
"description": "New API endpoint missing input validation",
"file_path": "src/api.py",
"severity": "high",
"detected_date": "2024-02-01T14:30:00",
"status": "identified"
},
{
"id": "DEBT-0030",
"type": "performance_issue",
"description": "N+1 query detected in user listing",
"file_path": "src/user_service.py",
"severity": "medium",
"detected_date": "2024-02-01T14:30:00",
"status": "identified"
},
{
"id": "DEBT-0031",
"type": "css_debt",
"description": "Inline styles should be moved to CSS files",
"file_path": "templates/user_profile.html",
"severity": "low",
"detected_date": "2024-02-01T14:30:00",
"status": "identified"
},
{
"id": "DEBT-0032",
"type": "accessibility_issue",
"description": "Missing alt text for images",
"file_path": "templates/dashboard.html",
"severity": "medium",
"detected_date": "2024-02-01T14:30:00",
"status": "identified"
},
{
"id": "DEBT-0033",
"type": "configuration_debt",
"description": "Environment-specific config hardcoded in application",
"file_path": "src/config.py",
"severity": "medium",
"detected_date": "2024-02-01T14:30:00",
"status": "identified"
}
]
}// Frontend JavaScript with various technical debt examples
// TODO: Move configuration to separate file
const API_BASE_URL = "https://api.example.com";
const API_KEY = "abc123def456"; // FIXME: Should be in environment
// Global variables - should be encapsulated
var userCache = {};
var authToken = null;
var currentUser = null;
// HACK: Polyfill for older browsers - should use proper build system
if (!String.prototype.includes) {
String.prototype.includes = function(search) {
return this.indexOf(search) !== -1;
};
}
class UserInterface {
constructor() {
this.components = {};
this.eventHandlers = [];
// Long parameter list in constructor
this.init(document, window, localStorage, sessionStorage, navigator, history, location);
}
// Function with too many parameters
init(doc, win, localStorage, sessionStorage, nav, hist, loc) {
this.document = doc;
this.window = win;
this.localStorage = localStorage;
this.sessionStorage = sessionStorage;
this.navigator = nav;
this.history = hist;
this.location = loc;
// Deep nesting example
if (this.localStorage) {
if (this.localStorage.getItem('user')) {
if (JSON.parse(this.localStorage.getItem('user'))) {
if (JSON.parse(this.localStorage.getItem('user')).preferences) {
if (JSON.parse(this.localStorage.getItem('user')).preferences.theme) {
if (JSON.parse(this.localStorage.getItem('user')).preferences.theme === 'dark') {
document.body.classList.add('dark-theme');
} else if (JSON.parse(this.localStorage.getItem('user')).preferences.theme === 'light') {
document.body.classList.add('light-theme');
} else {
document.body.classList.add('default-theme');
}
}
}
}
}
}
}
// Large function that does too many things
renderUserDashboard(userId, includeStats, includeRecent, includeNotifications, includeSettings, includeHelp) {
let user = this.getUser(userId);
if (!user) {
console.log("User not found"); // Should use proper logging
return;
}
let html = '<div class="dashboard">';
// Inline HTML generation - should use templates
html += '<header class="dashboard-header">';
html += '<h1>Welcome, ' + user.name + '</h1>';
html += '<div class="user-avatar">';
html += '<img src="' + user.avatar + '" alt="Avatar" />';
html += '</div>';
html += '</header>';
// Repeated validation pattern
if (includeStats && includeStats === true) {
html += '<section class="stats">';
html += '<h2>Your Statistics</h2>';
// Magic numbers everywhere
if (user.loginCount > 100) {
html += '<div class="stat-item">Frequent User (100+ logins)</div>';
} else if (user.loginCount > 50) {
html += '<div class="stat-item">Regular User (50+ logins)</div>';
} else if (user.loginCount > 10) {
html += '<div class="stat-item">Casual User (10+ logins)</div>';
} else {
html += '<div class="stat-item">New User</div>';
}
html += '</section>';
}
if (includeRecent && includeRecent === true) {
html += '<section class="recent">';
html += '<h2>Recent Activity</h2>';
// No error handling for API calls
let recentActivity = this.fetchRecentActivity(userId);
if (recentActivity && recentActivity.length > 0) {
html += '<ul class="activity-list">';
for (let i = 0; i < recentActivity.length; i++) {
let activity = recentActivity[i];
html += '<li class="activity-item">';
html += '<span class="activity-type">' + activity.type + '</span>';
html += '<span class="activity-description">' + activity.description + '</span>';
html += '<span class="activity-time">' + this.formatTime(activity.timestamp) + '</span>';
html += '</li>';
}
html += '</ul>';
} else {
html += '<p>No recent activity</p>';
}
html += '</section>';
}
if (includeNotifications && includeNotifications === true) {
html += '<section class="notifications">';
html += '<h2>Notifications</h2>';
let notifications = this.getNotifications(userId);
// Duplicate HTML generation pattern
if (notifications && notifications.length > 0) {
html += '<ul class="notification-list">';
for (let i = 0; i < notifications.length; i++) {
let notification = notifications[i];
html += '<li class="notification-item">';
html += '<span class="notification-title">' + notification.title + '</span>';
html += '<span class="notification-message">' + notification.message + '</span>';
html += '<span class="notification-time">' + this.formatTime(notification.timestamp) + '</span>';
html += '</li>';
}
html += '</ul>';
} else {
html += '<p>No notifications</p>';
}
html += '</section>';
}
html += '</div>';
// Direct DOM manipulation without cleanup
document.getElementById('main-content').innerHTML = html;
// Event handler attachment without cleanup
let buttons = document.querySelectorAll('.action-button');
for (let i = 0; i < buttons.length; i++) {
buttons[i].addEventListener('click', function(event) {
// Nested event handlers - memory leak risk
let buttonType = event.target.getAttribute('data-type');
if (buttonType === 'edit') {
// Inline event handling - should be separate methods
let modal = document.createElement('div');
modal.className = 'modal';
modal.innerHTML = '<div class="modal-content"><h3>Edit Profile</h3><button onclick="closeModal()">Close</button></div>';
document.body.appendChild(modal);
} else if (buttonType === 'delete') {
if (confirm('Are you sure?')) { // Using confirm - poor UX
// No error handling
fetch(API_BASE_URL + '/users/' + userId, {
method: 'DELETE',
headers: {'Authorization': 'Bearer ' + authToken}
});
}
} else if (buttonType === 'share') {
// Hardcoded share logic
if (navigator.share) {
navigator.share({
title: 'Check out my profile',
url: window.location.href
});
} else {
// Fallback for browsers without Web Share API
let shareUrl = 'https://twitter.com/intent/tweet?url=' + encodeURIComponent(window.location.href);
window.open(shareUrl, '_blank');
}
}
});
}
}
// Duplicate code - similar to above but for admin dashboard
renderAdminDashboard(adminId) {
let admin = this.getUser(adminId);
if (!admin) {
console.log("Admin not found");
return;
}
let html = '<div class="admin-dashboard">';
html += '<header class="dashboard-header">';
html += '<h1>Admin Panel - Welcome, ' + admin.name + '</h1>';
html += '<div class="user-avatar">';
html += '<img src="' + admin.avatar + '" alt="Avatar" />';
html += '</div>';
html += '</header>';
// Same pattern repeated
html += '<section class="admin-stats">';
html += '<h2>System Statistics</h2>';
let stats = this.getSystemStats();
if (stats) {
html += '<div class="stat-grid">';
html += '<div class="stat-item">Total Users: ' + stats.totalUsers + '</div>';
html += '<div class="stat-item">Active Users: ' + stats.activeUsers + '</div>';
html += '<div class="stat-item">New Today: ' + stats.newToday + '</div>';
html += '</div>';
}
html += '</section>';
html += '</div>';
document.getElementById('main-content').innerHTML = html;
}
getUser(userId) {
// Check cache first - but cache never expires
if (userCache[userId]) {
return userCache[userId];
}
// Synchronous AJAX - blocks UI
let xhr = new XMLHttpRequest();
xhr.open('GET', API_BASE_URL + '/users/' + userId, false);
xhr.setRequestHeader('Authorization', 'Bearer ' + authToken);
xhr.send();
if (xhr.status === 200) {
let user = JSON.parse(xhr.responseText);
userCache[userId] = user;
return user;
} else {
// Generic error handling
console.error('Failed to fetch user');
return null;
}
}
fetchRecentActivity(userId) {
// Another synchronous call
try {
let xhr = new XMLHttpRequest();
xhr.open('GET', API_BASE_URL + '/users/' + userId + '/activity', false);
xhr.setRequestHeader('Authorization', 'Bearer ' + authToken);
xhr.send();
if (xhr.status === 200) {
return JSON.parse(xhr.responseText);
} else {
return [];
}
} catch (error) {
// Swallowing errors
return [];
}
}
getNotifications(userId) {
// Yet another sync call - should be async
let xhr = new XMLHttpRequest();
xhr.open('GET', API_BASE_URL + '/users/' + userId + '/notifications', false);
xhr.setRequestHeader('Authorization', 'Bearer ' + authToken);
xhr.send();
if (xhr.status === 200) {
return JSON.parse(xhr.responseText);
} else {
return [];
}
}
formatTime(timestamp) {
// Basic time formatting - should use proper library
let date = new Date(timestamp);
return date.getMonth() + '/' + date.getDate() + '/' + date.getFullYear();
}
// XXX: This method is never used
formatCurrency(amount, currency) {
if (currency === 'USD') {
return '$' + amount.toFixed(2);
} else if (currency === 'EUR') {
return '€' + amount.toFixed(2);
} else {
return amount.toFixed(2) + ' ' + currency;
}
}
getSystemStats() {
// Hardcoded test data - should come from API
return {
totalUsers: 12534,
activeUsers: 8765,
newToday: 23
};
}
}
// Global functions - should be methods or modules
function closeModal() {
// Assumes modal exists - no error checking
document.querySelector('.modal').remove();
}
function validateEmail(email) {
// Regex without explanation - magic pattern
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
}
function validatePassword(password) {
// Duplicate validation logic from backend
if (password.length < 8) return false;
if (!/[A-Z]/.test(password)) return false;
if (!/[a-z]/.test(password)) return false;
if (!/\d/.test(password)) return false;
return true;
}
// jQuery-style utility - reinventing the wheel
function $(selector) {
return document.querySelector(selector);
}
function $all(selector) {
return document.querySelectorAll(selector);
}
// Global event handlers - should be encapsulated
document.addEventListener('DOMContentLoaded', function() {
// Inline anonymous function
let ui = new UserInterface();
// Event delegation would be better
document.body.addEventListener('click', function(event) {
if (event.target.classList.contains('login-button')) {
// Inline login logic
let username = $('#username').value;
let password = $('#password').value;
if (!username || !password) {
alert('Please enter username and password'); // Poor UX
return;
}
// No CSRF protection
fetch(API_BASE_URL + '/auth/login', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({username: username, password: password})
})
.then(response => response.json())
.then(data => {
if (data.success) {
authToken = data.token;
currentUser = data.user;
localStorage.setItem('authToken', authToken); // Storing sensitive data
localStorage.setItem('currentUser', JSON.stringify(currentUser));
window.location.reload(); // Poor navigation
} else {
alert('Login failed: ' + data.error);
}
})
.catch(error => {
console.error('Login error:', error);
alert('Login failed');
});
}
});
});
// // Old code left as comments - should be removed
// function oldRenderFunction() {
// var html = '<div>Old implementation</div>';
// document.body.innerHTML = html;
// }
// Commented out feature - should be removed or implemented
// function darkModeToggle() {
// if (document.body.classList.contains('dark-theme')) {
// document.body.classList.remove('dark-theme');
// document.body.classList.add('light-theme');
// } else {
// document.body.classList.remove('light-theme');
// document.body.classList.add('dark-theme');
// }
// }"""
Payment processing module - contains various technical debt examples.
⚠️ DISCLAIMER: This is an INTENTIONAL example of bad code patterns for
tech debt detection training. The hardcoded credentials, missing error
handling, and other issues are deliberate anti-patterns used by the
tech-debt-tracker skill to demonstrate detection capabilities.
DO NOT use this code in production.
"""
import json
import time
import requests
from decimal import Decimal
from typing import Dict, Any
class PaymentProcessor:
def __init__(self):
# TODO: These should come from environment or config
# ⚠️ INTENTIONAL BAD PATTERN — hardcoded keys for tech debt detection demo
self.stripe_key = "sk_test_EXAMPLE_NOT_REAL"
self.paypal_key = "paypal_EXAMPLE_NOT_REAL"
self.square_key = "square_EXAMPLE_NOT_REAL"
def process_payment(self, amount, currency, payment_method, customer_data, billing_address, shipping_address, items, discount_code, tax_rate, processing_fee, metadata):
"""
Process a payment - this function is too large and complex
"""
# Input validation - should be extracted to separate function
if not amount or amount <= 0:
return {"success": False, "error": "Invalid amount"}
if not currency:
return {"success": False, "error": "Currency required"}
if currency not in ["USD", "EUR", "GBP", "CAD", "AUD"]: # Hardcoded list
return {"success": False, "error": "Unsupported currency"}
if not payment_method:
return {"success": False, "error": "Payment method required"}
if not customer_data or "email" not in customer_data:
return {"success": False, "error": "Customer email required"}
# Tax calculation - complex business logic that should be separate service
tax_amount = 0
if tax_rate:
if currency == "USD":
# US tax logic - hardcoded rules
if billing_address and "state" in billing_address:
state = billing_address["state"]
if state == "CA":
tax_amount = amount * 0.08 # California tax
elif state == "NY":
tax_amount = amount * 0.085 # New York tax
elif state == "TX":
tax_amount = amount * 0.0625 # Texas tax
elif state == "FL":
tax_amount = amount * 0.06 # Florida tax
else:
tax_amount = amount * 0.05 # Default tax
elif currency == "EUR":
# EU VAT logic - also hardcoded
tax_amount = amount * 0.20 # 20% VAT
elif currency == "GBP":
tax_amount = amount * 0.20 # UK VAT
# Discount calculation - another complex block
discount_amount = 0
if discount_code:
# FIXME: This should query a discount service
if discount_code == "SAVE10":
discount_amount = amount * 0.10
elif discount_code == "SAVE20":
discount_amount = amount * 0.20
elif discount_code == "NEWUSER":
discount_amount = min(50, amount * 0.25) # Max $50 discount
elif discount_code == "LOYALTY":
# Complex loyalty discount logic
customer_tier = customer_data.get("tier", "bronze")
if customer_tier == "gold":
discount_amount = amount * 0.15
elif customer_tier == "silver":
discount_amount = amount * 0.10
elif customer_tier == "bronze":
discount_amount = amount * 0.05
# Calculate final amount
final_amount = amount - discount_amount + tax_amount + processing_fee
# Payment method routing - should use strategy pattern
if payment_method["type"] == "credit_card":
# Credit card processing
if payment_method["provider"] == "stripe":
try:
# Stripe API call - no retry logic
response = requests.post(
"https://api.stripe.com/v1/charges",
headers={"Authorization": f"Bearer {self.stripe_key}"},
data={
"amount": int(final_amount * 100), # Convert to cents
"currency": currency.lower(),
"source": payment_method["token"],
"description": f"Payment for {len(items)} items"
}
)
if response.status_code == 200:
stripe_response = response.json()
# Store transaction - should be in database
transaction = {
"id": stripe_response["id"],
"amount": final_amount,
"currency": currency,
"status": "completed",
"timestamp": time.time(),
"provider": "stripe",
"customer": customer_data["email"],
"items": items,
"tax_amount": tax_amount,
"discount_amount": discount_amount
}
# Send confirmation email - inline instead of separate service
self.send_payment_confirmation_email(customer_data["email"], transaction)
return {"success": True, "transaction": transaction}
else:
return {"success": False, "error": "Stripe payment failed"}
except Exception as e:
# Broad exception handling - should be more specific
print(f"Stripe error: {e}") # Should use proper logging
return {"success": False, "error": "Payment processing error"}
elif payment_method["provider"] == "square":
# Square processing - duplicate code structure
try:
response = requests.post(
"https://connect.squareup.com/v2/payments",
headers={"Authorization": f"Bearer {self.square_key}"},
json={
"source_id": payment_method["token"],
"amount_money": {
"amount": int(final_amount * 100),
"currency": currency
}
}
)
if response.status_code == 200:
square_response = response.json()
transaction = {
"id": square_response["payment"]["id"],
"amount": final_amount,
"currency": currency,
"status": "completed",
"timestamp": time.time(),
"provider": "square",
"customer": customer_data["email"],
"items": items,
"tax_amount": tax_amount,
"discount_amount": discount_amount
}
self.send_payment_confirmation_email(customer_data["email"], transaction)
return {"success": True, "transaction": transaction}
else:
return {"success": False, "error": "Square payment failed"}
except Exception as e:
print(f"Square error: {e}")
return {"success": False, "error": "Payment processing error"}
elif payment_method["type"] == "paypal":
# PayPal processing - more duplicate code
try:
response = requests.post(
"https://api.paypal.com/v2/checkout/orders",
headers={"Authorization": f"Bearer {self.paypal_key}"},
json={
"intent": "CAPTURE",
"purchase_units": [{
"amount": {
"currency_code": currency,
"value": str(final_amount)
}
}]
}
)
if response.status_code == 201:
paypal_response = response.json()
transaction = {
"id": paypal_response["id"],
"amount": final_amount,
"currency": currency,
"status": "completed",
"timestamp": time.time(),
"provider": "paypal",
"customer": customer_data["email"],
"items": items,
"tax_amount": tax_amount,
"discount_amount": discount_amount
}
self.send_payment_confirmation_email(customer_data["email"], transaction)
return {"success": True, "transaction": transaction}
else:
return {"success": False, "error": "PayPal payment failed"}
except Exception as e:
print(f"PayPal error: {e}")
return {"success": False, "error": "Payment processing error"}
else:
return {"success": False, "error": "Unsupported payment method"}
def send_payment_confirmation_email(self, email, transaction):
# Email sending logic - should be separate service
# HACK: Using print instead of actual email service
print(f"Sending confirmation email to {email}")
print(f"Transaction ID: {transaction['id']}")
print(f"Amount: {transaction['currency']} {transaction['amount']}")
# TODO: Implement actual email sending
pass
def refund_payment(self, transaction_id, amount=None):
# Refund logic - incomplete implementation
# TODO: Implement refund for different providers
print(f"Refunding transaction {transaction_id}")
if amount:
print(f"Partial refund: {amount}")
else:
print("Full refund")
# XXX: This doesn't actually process the refund
return {"success": True, "message": "Refund initiated"}
def get_transaction(self, transaction_id):
# Should query database, but we don't have one
# FIXME: Implement actual transaction lookup
return {"id": transaction_id, "status": "unknown"}
def validate_credit_card(self, card_number, expiry_month, expiry_year, cvv):
# Basic card validation - should use proper validation library
if not card_number or len(card_number) < 13 or len(card_number) > 19:
return False
# Luhn algorithm check - reimplemented poorly
digits = [int(d) for d in card_number if d.isdigit()]
checksum = 0
for i, digit in enumerate(reversed(digits)):
if i % 2 == 1:
digit *= 2
if digit > 9:
digit -= 9
checksum += digit
if checksum % 10 != 0:
return False
# Expiry validation
if expiry_month < 1 or expiry_month > 12:
return False
current_year = int(time.strftime("%Y"))
current_month = int(time.strftime("%m"))
if expiry_year < current_year:
return False
elif expiry_year == current_year and expiry_month < current_month:
return False
# CVV validation
if not cvv or len(cvv) < 3 or len(cvv) > 4:
return False
return True
# Module-level functions that should be in class or separate module
def calculate_processing_fee(amount, provider):
"""Calculate processing fee - hardcoded rates"""
if provider == "stripe":
return amount * 0.029 + 0.30 # Stripe rates
elif provider == "paypal":
return amount * 0.031 + 0.30 # PayPal rates
elif provider == "square":
return amount * 0.026 + 0.10 # Square rates
else:
return 0
def format_currency(amount, currency):
"""Format currency - basic implementation"""
# Should use proper internationalization
if currency == "USD":
return f"${amount:.2f}"
elif currency == "EUR":
return f"€{amount:.2f}"
elif currency == "GBP":
return f"£{amount:.2f}"
else:
return f"{currency} {amount:.2f}"
# Global state - anti-pattern
payment_processor_instance = None
def get_payment_processor():
global payment_processor_instance
if payment_processor_instance is None:
payment_processor_instance = PaymentProcessor()
return payment_processor_instance#!/usr/bin/env python3
"""
User service module with various tech debt examples
"""
import hashlib
import json
import time
import re
from typing import Dict, List, Any, Optional
# TODO: Move this to configuration file
DATABASE_URL = "postgresql://user:password123@localhost:5432/mydb"
API_KEY = "sk-1234567890abcdef" # FIXME: This should be in environment variables
class UserService:
def __init__(self):
self.users = {}
self.cache = {}
# HACK: Using dict for now, should be proper database connection
self.db_connection = None
def create_user(self, name, email, password, age, phone, address, city, state, zip_code, country, preferences, notifications, billing_info):
# Function with too many parameters - should use User dataclass
if not name:
return None
if not email:
return None
if not password:
return None
if not age:
return None
if not phone:
return None
if not address:
return None
if not city:
return None
if not state:
return None
if not zip_code:
return None
if not country:
return None
# Duplicate validation logic - should be extracted
if age < 13:
print("User must be at least 13 years old")
return None
if age > 150:
print("Invalid age")
return None
# More validation
if not self.validate_email(email):
print("Invalid email format")
return None
# Password validation - duplicated elsewhere
if len(password) < 8:
print("Password too short")
return None
if not re.search(r"[A-Z]", password):
print("Password must contain uppercase letter")
return None
if not re.search(r"[a-z]", password):
print("Password must contain lowercase letter")
return None
if not re.search(r"\d", password):
print("Password must contain digit")
return None
# Deep nesting example
if preferences:
if 'notifications' in preferences:
if preferences['notifications']:
if 'email' in preferences['notifications']:
if preferences['notifications']['email']:
if 'frequency' in preferences['notifications']['email']:
if preferences['notifications']['email']['frequency'] == 'daily':
print("Daily email notifications enabled")
elif preferences['notifications']['email']['frequency'] == 'weekly':
print("Weekly email notifications enabled")
else:
print("Invalid notification frequency")
# TODO: Implement proper user ID generation
user_id = str(hash(email)) # XXX: This is terrible for production
# Magic numbers everywhere
password_hash = hashlib.sha256((password + "salt123").encode()).hexdigest()
user_data = {
"id": user_id,
"name": name,
"email": email,
"password_hash": password_hash,
"age": age,
"phone": phone,
"address": address,
"city": city,
"state": state,
"zip_code": zip_code,
"country": country,
"preferences": preferences,
"notifications": notifications,
"billing_info": billing_info,
"created_at": time.time(),
"updated_at": time.time(),
"last_login": None,
"login_count": 0,
"is_active": True,
"is_verified": False,
"verification_token": None,
"reset_token": None,
"failed_login_attempts": 0,
"locked_until": None,
"subscription_level": "free",
"credits": 100
}
self.users[user_id] = user_data
return user_id
def validate_email(self, email):
# Duplicate validation logic - should be in utils
if not email:
return False
if "@" not in email:
return False
if "." not in email:
return False
return True
def authenticate_user(self, email, password):
# More duplicate validation
if not email:
return None
if not password:
return None
# Linear search through users - O(n) complexity
for user_id, user_data in self.users.items():
if user_data["email"] == email:
# Same password hashing logic duplicated
password_hash = hashlib.sha256((password + "salt123").encode()).hexdigest()
if user_data["password_hash"] == password_hash:
# Update login stats
user_data["last_login"] = time.time()
user_data["login_count"] += 1
user_data["failed_login_attempts"] = 0
return user_id
else:
# Failed login handling
user_data["failed_login_attempts"] += 1
if user_data["failed_login_attempts"] >= 5: # Magic number
user_data["locked_until"] = time.time() + 1800 # 30 minutes
return None
return None
def get_user(self, user_id):
# No error handling
return self.users[user_id]
def update_user(self, user_id, updates):
try:
# Empty catch block - bad practice
user = self.users[user_id]
except:
pass
# More validation duplication
if "age" in updates:
if updates["age"] < 13:
print("User must be at least 13 years old")
return False
if updates["age"] > 150:
print("Invalid age")
return False
if "email" in updates:
if not self.validate_email(updates["email"]):
print("Invalid email format")
return False
# Direct dictionary manipulation without validation
for key, value in updates.items():
user[key] = value
user["updated_at"] = time.time()
return True
def delete_user(self, user_id):
# print("Deleting user", user_id) # Commented out code
# TODO: Implement soft delete instead
del self.users[user_id]
def search_users(self, query):
results = []
# Inefficient search algorithm - O(n*m)
for user_id, user_data in self.users.items():
if query.lower() in user_data["name"].lower():
results.append(user_data)
elif query.lower() in user_data["email"].lower():
results.append(user_data)
elif query in user_data.get("phone", ""):
results.append(user_data)
return results
def export_users(self):
# Security risk - no access control
return json.dumps(self.users, indent=2)
def import_users(self, json_data):
# No validation of imported data
imported_users = json.loads(json_data)
self.users.update(imported_users)
# def old_create_user(self, name, email):
# # Old implementation kept as comment
# return {"name": name, "email": email}
def calculate_user_score(self, user_id):
user = self.users[user_id]
score = 0
# Complex scoring logic with magic numbers
if user["login_count"] > 10:
score += 50
elif user["login_count"] > 5:
score += 30
elif user["login_count"] > 1:
score += 10
if user["subscription_level"] == "premium":
score += 100
elif user["subscription_level"] == "pro":
score += 75
elif user["subscription_level"] == "basic":
score += 25
# Age-based scoring with arbitrary rules
if user["age"] >= 18 and user["age"] <= 65:
score += 20
elif user["age"] > 65:
score += 10
return score
# Global variable - should be encapsulated
user_service_instance = UserService()
def get_user_service():
return user_service_instance
# Utility function that should be in separate module
def hash_password(password, salt="salt123"):
# Hardcoded salt - security issue
return hashlib.sha256((password + salt).encode()).hexdigest()
# Another utility function with duplicate logic
def validate_password(password):
if len(password) < 8:
return False, "Password too short"
if not re.search(r"[A-Z]", password):
return False, "Password must contain uppercase letter"
if not re.search(r"[a-z]", password):
return False, "Password must contain lowercase letter"
if not re.search(r"\d", password):
return False, "Password must contain digit"
return True, "Valid password"[
{
"id": "DEBT-0001",
"type": "large_function",
"description": "create_user function in user_service.py is 89 lines long",
"file_path": "src/user_service.py",
"line_number": 13,
"severity": "high",
"metadata": {
"function_name": "create_user",
"length": 89,
"recommended_max": 50
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0002",
"type": "duplicate_code",
"description": "Password validation logic duplicated in 3 locations",
"file_path": "src/user_service.py",
"line_number": 45,
"severity": "medium",
"metadata": {
"duplicate_count": 3,
"other_files": ["src/auth.py", "src/frontend.js"]
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0003",
"type": "security_risk",
"description": "Hardcoded API key in payment_processor.py",
"file_path": "src/payment_processor.py",
"line_number": 10,
"severity": "critical",
"metadata": {
"security_issue": "hardcoded_credentials",
"exposure_risk": "high"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0004",
"type": "high_complexity",
"description": "process_payment function has cyclomatic complexity of 24",
"file_path": "src/payment_processor.py",
"line_number": 19,
"severity": "high",
"metadata": {
"function_name": "process_payment",
"complexity": 24,
"recommended_max": 10
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0005",
"type": "missing_docstring",
"description": "PaymentProcessor class missing docstring",
"file_path": "src/payment_processor.py",
"line_number": 8,
"severity": "low",
"metadata": {
"class_name": "PaymentProcessor"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0006",
"type": "todo_comment",
"description": "TODO: Move this to configuration file",
"file_path": "src/user_service.py",
"line_number": 8,
"severity": "low",
"metadata": {
"comment": "TODO: Move this to configuration file"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0007",
"type": "empty_catch_blocks",
"description": "Empty catch block in update_user method",
"file_path": "src/user_service.py",
"line_number": 156,
"severity": "medium",
"metadata": {
"method_name": "update_user",
"exception_type": "generic"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0008",
"type": "magic_numbers",
"description": "Magic number 1800 used for lock timeout",
"file_path": "src/user_service.py",
"line_number": 98,
"severity": "low",
"metadata": {
"value": 1800,
"context": "account_lockout_duration"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0009",
"type": "deep_nesting",
"description": "Deep nesting detected: 6 levels in preferences handling",
"file_path": "src/frontend.js",
"line_number": 32,
"severity": "medium",
"metadata": {
"nesting_level": 6,
"recommended_max": 4
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0010",
"type": "long_line",
"description": "Line too long: 156 characters",
"file_path": "src/frontend.js",
"line_number": 127,
"severity": "low",
"metadata": {
"length": 156,
"recommended_max": 120
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0011",
"type": "commented_code",
"description": "Dead code left in comments",
"file_path": "src/frontend.js",
"line_number": 285,
"severity": "low",
"metadata": {
"lines_of_commented_code": 8
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0012",
"type": "global_variables",
"description": "Global variable userCache should be encapsulated",
"file_path": "src/frontend.js",
"line_number": 7,
"severity": "medium",
"metadata": {
"variable_name": "userCache",
"scope": "global"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0013",
"type": "synchronous_ajax",
"description": "Synchronous AJAX call blocks UI thread",
"file_path": "src/frontend.js",
"line_number": 189,
"severity": "high",
"metadata": {
"method": "XMLHttpRequest",
"async": false
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0014",
"type": "hardcoded_values",
"description": "Tax rates hardcoded in payment processing logic",
"file_path": "src/payment_processor.py",
"line_number": 45,
"severity": "medium",
"metadata": {
"values": ["0.08", "0.085", "0.0625", "0.06"],
"context": "tax_calculation"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0015",
"type": "no_error_handling",
"description": "API calls without proper error handling",
"file_path": "src/payment_processor.py",
"line_number": 78,
"severity": "high",
"metadata": {
"api_endpoint": "stripe",
"error_scenarios": ["network_failure", "invalid_response"]
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0016",
"type": "inefficient_algorithm",
"description": "O(n) user search could be optimized with indexing",
"file_path": "src/user_service.py",
"line_number": 178,
"severity": "medium",
"metadata": {
"current_complexity": "O(n)",
"recommended_complexity": "O(log n)",
"method_name": "search_users"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0017",
"type": "memory_leak_risk",
"description": "Event listeners attached without cleanup",
"file_path": "src/frontend.js",
"line_number": 145,
"severity": "medium",
"metadata": {
"event_type": "click",
"cleanup_missing": true
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0018",
"type": "sql_injection_risk",
"description": "Potential SQL injection in user query",
"file_path": "src/database.py",
"line_number": 25,
"severity": "critical",
"metadata": {
"query_type": "dynamic",
"user_input": "unsanitized"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0019",
"type": "outdated_dependency",
"description": "jQuery version 2.1.4 has known security vulnerabilities",
"file_path": "package.json",
"line_number": 15,
"severity": "high",
"metadata": {
"package": "jquery",
"current_version": "2.1.4",
"latest_version": "3.6.4",
"vulnerabilities": ["CVE-2020-11022", "CVE-2020-11023"]
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
},
{
"id": "DEBT-0020",
"type": "test_debt",
"description": "No unit tests for critical payment processing logic",
"file_path": "src/payment_processor.py",
"line_number": 19,
"severity": "high",
"metadata": {
"coverage": 0,
"critical_paths": ["process_payment", "refund_payment"],
"risk_level": "high"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified"
}
]{
"metadata": {
"generated_date": "2026-02-16T12:59:34.530390",
"analysis_period": "monthly",
"snapshots_analyzed": 2,
"date_range": {
"start": "2024-01-15T09:00:00",
"end": "2024-02-01T14:30:00"
},
"team_size": 5
},
"executive_summary": {
"overall_status": "excellent",
"health_score": 87.3,
"status_message": "Code quality is excellent with minimal technical debt.",
"key_insights": [
"Good progress on debt reduction"
],
"total_debt_items": 22,
"estimated_effort_hours": 193.5,
"high_priority_items": 6,
"velocity_impact_percent": 12.3
},
"current_health": {
"overall_score": 87.3,
"debt_density": 0.81,
"velocity_impact": 12.3,
"quality_score": 81.8,
"maintainability_score": 72.7,
"technical_risk_score": 38.2,
"date": "2024-02-01T14:30:00"
},
"trend_analysis": {
"overall_score": {
"metric_name": "overall_score",
"trend_direction": "improving",
"change_rate": 3.7,
"correlation_strength": 0.0,
"forecast_next_period": 91.0,
"confidence_interval": [
91.0,
91.0
]
},
"debt_density": {
"metric_name": "debt_density",
"trend_direction": "improving",
"change_rate": -0.31,
"correlation_strength": 0.0,
"forecast_next_period": 0.5,
"confidence_interval": [
0.5,
0.5
]
},
"velocity_impact": {
"metric_name": "velocity_impact",
"trend_direction": "improving",
"change_rate": -2.9,
"correlation_strength": 0.0,
"forecast_next_period": 9.4,
"confidence_interval": [
9.4,
9.4
]
},
"quality_score": {
"metric_name": "quality_score",
"trend_direction": "declining",
"change_rate": -3.9,
"correlation_strength": 0.0,
"forecast_next_period": 77.9,
"confidence_interval": [
77.9,
77.9
]
},
"technical_risk_score": {
"metric_name": "technical_risk_score",
"trend_direction": "improving",
"change_rate": -47.5,
"correlation_strength": 0.0,
"forecast_next_period": -9.3,
"confidence_interval": [
-9.3,
-9.3
]
}
},
"debt_velocity": [
{
"period": "2024-01-15 to 2024-02-01",
"new_debt_items": 0,
"resolved_debt_items": 6,
"net_change": -6,
"velocity_ratio": 10.0,
"effort_hours_added": 0,
"effort_hours_resolved": 77.0,
"net_effort_change": -77.0
}
],
"forecasts": {
"health_score_3_months": 98.4,
"health_score_6_months": 100,
"debt_count_3_months": 4,
"debt_count_6_months": 0,
"risk_score_3_months": 0
},
"recommendations": [
{
"priority": "medium",
"category": "focus_area",
"title": "Focus on Other Debt",
"description": "Other represents the largest debt category (16 items). Consider targeted initiatives.",
"impact": "medium",
"effort": "medium"
}
],
"visualizations": {
"health_timeline": [
{
"date": "2024-01-15",
"overall_score": 83.6,
"quality_score": 85.7,
"technical_risk": 85.7
},
{
"date": "2024-02-01",
"overall_score": 87.3,
"quality_score": 81.8,
"technical_risk": 38.2
}
],
"debt_accumulation": [
{
"date": "2024-01-15",
"total_debt": 28,
"high_priority": 9,
"security_debt": 5
},
{
"date": "2024-02-01",
"total_debt": 22,
"high_priority": 6,
"security_debt": 2
}
],
"category_distribution": [
{
"category": "code_quality",
"count": 5
},
{
"category": "other",
"count": 16
},
{
"category": "maintenance",
"count": 1
}
],
"debt_velocity": [
{
"period": "2024-01-15 to 2024-02-01",
"new_items": 0,
"resolved_items": 6,
"net_change": -6,
"velocity_ratio": 10.0
}
],
"effort_trend": [
{
"date": "2024-01-15",
"total_effort": 270.5
},
{
"date": "2024-02-01",
"total_effort": 193.5
}
]
},
"detailed_metrics": {
"debt_breakdown": {
"large_function": 1,
"duplicate_code": 1,
"high_complexity": 1,
"missing_docstring": 1,
"empty_catch_blocks": 1,
"deep_nesting": 1,
"long_line": 1,
"commented_code": 1,
"global_variables": 1,
"synchronous_ajax": 1,
"hardcoded_values": 1,
"no_error_handling": 1,
"inefficient_algorithm": 1,
"memory_leak_risk": 1,
"large_class": 1,
"circular_dependency": 1,
"broad_exception": 1,
"missing_validation": 1,
"performance_issue": 1,
"css_debt": 1,
"accessibility_issue": 1,
"configuration_debt": 1
},
"severity_breakdown": {
"high": 6,
"medium": 12,
"low": 4
},
"category_breakdown": {
"code_quality": 5,
"other": 16,
"maintenance": 1
},
"files_analyzed": 27,
"debt_density": 0.8148148148148148,
"average_effort_per_item": 8.795454545454545
}
}{
"metadata": {
"analysis_date": "2026-02-16T12:59:31.382843",
"framework_used": "cost_of_delay",
"team_size": 5,
"sprint_capacity_hours": 80,
"total_items_analyzed": 20
},
"prioritized_backlog": [
{
"id": "DEBT-0008",
"type": "magic_numbers",
"description": "Magic number 1800 used for lock timeout",
"file_path": "src/user_service.py",
"line_number": 98,
"severity": "low",
"metadata": {
"value": 1800,
"context": "account_lockout_duration"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 1,
"hours_estimate": 5.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 2,
"revenue_impact": 2,
"team_velocity_impact": 3,
"quality_impact": 3,
"security_impact": 2
},
"interest_rate": {
"daily_cost": 2.4,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 2.1,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.8
},
{
"id": "DEBT-0010",
"type": "long_line",
"description": "Line too long: 156 characters",
"file_path": "src/frontend.js",
"line_number": 127,
"severity": "low",
"metadata": {
"length": 156,
"recommended_max": 120
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 1,
"hours_estimate": 0.375,
"risk_factor": 1.0,
"skill_level_required": "junior",
"confidence": 0.95
},
"business_impact": {
"customer_impact": 2,
"revenue_impact": 2,
"team_velocity_impact": 3,
"quality_impact": 3,
"security_impact": 2
},
"interest_rate": {
"daily_cost": 2.4,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 0.16,
"category": "code_quality",
"impact_tags": [
"quick-win"
],
"priority_score": 4.8
},
{
"id": "DEBT-0011",
"type": "commented_code",
"description": "Dead code left in comments",
"file_path": "src/frontend.js",
"line_number": 285,
"severity": "low",
"metadata": {
"lines_of_commented_code": 8
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 1,
"hours_estimate": 5.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 2,
"revenue_impact": 2,
"team_velocity_impact": 3,
"quality_impact": 3,
"security_impact": 2
},
"interest_rate": {
"daily_cost": 2.4,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 2.1,
"category": "maintenance",
"impact_tags": [
"quick-win"
],
"priority_score": 4.8
},
{
"id": "DEBT-0007",
"type": "empty_catch_blocks",
"description": "Empty catch block in update_user method",
"file_path": "src/user_service.py",
"line_number": 156,
"severity": "medium",
"metadata": {
"method_name": "update_user",
"exception_type": "generic"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
},
{
"id": "DEBT-0009",
"type": "deep_nesting",
"description": "Deep nesting detected: 6 levels in preferences handling",
"file_path": "src/frontend.js",
"line_number": 32,
"severity": "medium",
"metadata": {
"nesting_level": 6,
"recommended_max": 4
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
},
{
"id": "DEBT-0012",
"type": "global_variables",
"description": "Global variable userCache should be encapsulated",
"file_path": "src/frontend.js",
"line_number": 7,
"severity": "medium",
"metadata": {
"variable_name": "userCache",
"scope": "global"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
},
{
"id": "DEBT-0014",
"type": "hardcoded_values",
"description": "Tax rates hardcoded in payment processing logic",
"file_path": "src/payment_processor.py",
"line_number": 45,
"severity": "medium",
"metadata": {
"values": [
"0.08",
"0.085",
"0.0625",
"0.06"
],
"context": "tax_calculation"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
},
{
"id": "DEBT-0016",
"type": "inefficient_algorithm",
"description": "O(n) user search could be optimized with indexing",
"file_path": "src/user_service.py",
"line_number": 178,
"severity": "medium",
"metadata": {
"current_complexity": "O(n)",
"recommended_complexity": "O(log n)",
"method_name": "search_users"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
},
{
"id": "DEBT-0017",
"type": "memory_leak_risk",
"description": "Event listeners attached without cleanup",
"file_path": "src/frontend.js",
"line_number": 145,
"severity": "medium",
"metadata": {
"event_type": "click",
"cleanup_missing": true
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
},
{
"id": "DEBT-0001",
"type": "large_function",
"description": "create_user function in user_service.py is 89 lines long",
"file_path": "src/user_service.py",
"line_number": 13,
"severity": "high",
"metadata": {
"function_name": "create_user",
"length": 89,
"recommended_max": 50
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 15.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.7
},
"business_impact": {
"customer_impact": 4,
"revenue_impact": 6,
"team_velocity_impact": 10,
"quality_impact": 8,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 7.4,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.03
},
"cost_of_delay": 19.48,
"category": "code_quality",
"impact_tags": [
"velocity-blocker",
"quality-risk",
"quick-win"
],
"priority_score": 4.26
},
{
"id": "DEBT-0005",
"type": "missing_docstring",
"description": "PaymentProcessor class missing docstring",
"file_path": "src/payment_processor.py",
"line_number": 8,
"severity": "low",
"metadata": {
"class_name": "PaymentProcessor"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 1,
"hours_estimate": 1.25,
"risk_factor": 1.0,
"skill_level_required": "junior",
"confidence": 0.9
},
"business_impact": {
"customer_impact": 1,
"revenue_impact": 1,
"team_velocity_impact": 2,
"quality_impact": 2,
"security_impact": 1
},
"interest_rate": {
"daily_cost": 1.6,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 0.35,
"category": "code_quality",
"impact_tags": [
"quick-win"
],
"priority_score": 4.1
},
{
"id": "DEBT-0013",
"type": "synchronous_ajax",
"description": "Synchronous AJAX call blocks UI thread",
"file_path": "src/frontend.js",
"line_number": 189,
"severity": "high",
"metadata": {
"method": "XMLHttpRequest",
"async": false
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 15.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 4,
"revenue_impact": 4,
"team_velocity_impact": 7,
"quality_impact": 7,
"security_impact": 4
},
"interest_rate": {
"daily_cost": 5.6,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 14.73,
"category": "other",
"impact_tags": [
"velocity-blocker",
"quality-risk",
"quick-win"
],
"priority_score": 3.73
},
{
"id": "DEBT-0015",
"type": "no_error_handling",
"description": "API calls without proper error handling",
"file_path": "src/payment_processor.py",
"line_number": 78,
"severity": "high",
"metadata": {
"api_endpoint": "stripe",
"error_scenarios": [
"network_failure",
"invalid_response"
]
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 15.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 4,
"revenue_impact": 4,
"team_velocity_impact": 7,
"quality_impact": 7,
"security_impact": 4
},
"interest_rate": {
"daily_cost": 5.6,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 14.73,
"category": "other",
"impact_tags": [
"velocity-blocker",
"quality-risk",
"quick-win"
],
"priority_score": 3.73
},
{
"id": "DEBT-0019",
"type": "outdated_dependency",
"description": "jQuery version 2.1.4 has known security vulnerabilities",
"file_path": "package.json",
"line_number": 15,
"severity": "high",
"metadata": {
"package": "jquery",
"current_version": "2.1.4",
"latest_version": "3.6.4",
"vulnerabilities": [
"CVE-2020-11022",
"CVE-2020-11023"
]
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 15.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 4,
"revenue_impact": 4,
"team_velocity_impact": 7,
"quality_impact": 7,
"security_impact": 4
},
"interest_rate": {
"daily_cost": 5.6,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 14.73,
"category": "other",
"impact_tags": [
"velocity-blocker",
"quality-risk",
"quick-win"
],
"priority_score": 3.73
},
{
"id": "DEBT-0018",
"type": "sql_injection_risk",
"description": "Potential SQL injection in user query",
"file_path": "src/database.py",
"line_number": 25,
"severity": "critical",
"metadata": {
"query_type": "dynamic",
"user_input": "unsanitized"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 3,
"hours_estimate": 20.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 5,
"revenue_impact": 5,
"team_velocity_impact": 9,
"quality_impact": 9,
"security_impact": 5
},
"interest_rate": {
"daily_cost": 7.199999999999999,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 25.26,
"category": "other",
"impact_tags": [
"velocity-blocker",
"quality-risk",
"quick-win"
],
"priority_score": 3.24
},
{
"id": "DEBT-0006",
"type": "todo_comment",
"description": "TODO: Move this to configuration file",
"file_path": "src/user_service.py",
"line_number": 8,
"severity": "low",
"metadata": {
"comment": "TODO: Move this to configuration file"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 1,
"hours_estimate": 0.75,
"risk_factor": 1.0,
"skill_level_required": "junior",
"confidence": 0.9
},
"business_impact": {
"customer_impact": 1,
"revenue_impact": 1,
"team_velocity_impact": 1,
"quality_impact": 1,
"security_impact": 1
},
"interest_rate": {
"daily_cost": 0.8,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.01
},
"cost_of_delay": 0.11,
"category": "maintenance",
"impact_tags": [
"quick-win"
],
"priority_score": 3.1
},
{
"id": "DEBT-0002",
"type": "duplicate_code",
"description": "Password validation logic duplicated in 3 locations",
"file_path": "src/user_service.py",
"line_number": 45,
"severity": "medium",
"metadata": {
"duplicate_count": 3,
"other_files": [
"src/auth.py",
"src/frontend.js"
]
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 15.0,
"risk_factor": 1.4,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 4,
"team_velocity_impact": 6,
"quality_impact": 6,
"security_impact": 2
},
"interest_rate": {
"daily_cost": 4.8,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.08
},
"cost_of_delay": 12.69,
"category": "code_quality",
"impact_tags": [
"quick-win"
],
"priority_score": 2.39
},
{
"id": "DEBT-0020",
"type": "test_debt",
"description": "No unit tests for critical payment processing logic",
"file_path": "src/payment_processor.py",
"line_number": 19,
"severity": "high",
"metadata": {
"coverage": 0,
"critical_paths": [
"process_payment",
"refund_payment"
],
"risk_level": "high"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 6,
"hours_estimate": 36.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 7,
"revenue_impact": 7,
"team_velocity_impact": 10,
"quality_impact": 10,
"security_impact": 4
},
"interest_rate": {
"daily_cost": 8.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.04
},
"cost_of_delay": 50.82,
"category": "testing",
"impact_tags": [
"customer-facing",
"revenue-impact",
"velocity-blocker",
"quality-risk",
"quick-win"
],
"priority_score": 1.94
},
{
"id": "DEBT-0004",
"type": "high_complexity",
"description": "process_payment function has cyclomatic complexity of 24",
"file_path": "src/payment_processor.py",
"line_number": 19,
"severity": "high",
"metadata": {
"function_name": "process_payment",
"complexity": 24,
"recommended_max": 10
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 5,
"hours_estimate": 30.0,
"risk_factor": 1.4,
"skill_level_required": "senior",
"confidence": 0.5
},
"business_impact": {
"customer_impact": 6,
"revenue_impact": 7,
"team_velocity_impact": 10,
"quality_impact": 10,
"security_impact": 4
},
"interest_rate": {
"daily_cost": 8.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.05
},
"cost_of_delay": 42.36,
"category": "code_quality",
"impact_tags": [
"revenue-impact",
"velocity-blocker",
"quality-risk",
"quick-win"
],
"priority_score": 1.65
},
{
"id": "DEBT-0003",
"type": "security_risk",
"description": "Hardcoded API key in payment_processor.py",
"file_path": "src/payment_processor.py",
"line_number": 10,
"severity": "critical",
"metadata": {
"security_issue": "hardcoded_credentials",
"exposure_risk": "high"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 7,
"hours_estimate": 44.0,
"risk_factor": 1.8,
"skill_level_required": "senior",
"confidence": 0.4
},
"business_impact": {
"customer_impact": 10,
"revenue_impact": 10,
"team_velocity_impact": 10,
"quality_impact": 10,
"security_impact": 10
},
"interest_rate": {
"daily_cost": 8.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 61.91,
"category": "security",
"impact_tags": [
"security-critical",
"customer-facing",
"revenue-impact",
"velocity-blocker",
"quality-risk",
"quick-win"
],
"priority_score": 1.01
}
],
"sprint_allocation": {
"total_debt_hours": 277.4,
"debt_capacity_per_sprint": 16.0,
"total_sprints_needed": 17,
"high_priority_items": 0,
"sprint_plan": [
{
"sprint_number": 1,
"items": [
{
"id": "DEBT-0008",
"type": "magic_numbers",
"description": "Magic number 1800 used for lock timeout",
"file_path": "src/user_service.py",
"line_number": 98,
"severity": "low",
"metadata": {
"value": 1800,
"context": "account_lockout_duration"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 1,
"hours_estimate": 5.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 2,
"revenue_impact": 2,
"team_velocity_impact": 3,
"quality_impact": 3,
"security_impact": 2
},
"interest_rate": {
"daily_cost": 2.4,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 2.1,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.8
},
{
"id": "DEBT-0010",
"type": "long_line",
"description": "Line too long: 156 characters",
"file_path": "src/frontend.js",
"line_number": 127,
"severity": "low",
"metadata": {
"length": 156,
"recommended_max": 120
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 1,
"hours_estimate": 0.375,
"risk_factor": 1.0,
"skill_level_required": "junior",
"confidence": 0.95
},
"business_impact": {
"customer_impact": 2,
"revenue_impact": 2,
"team_velocity_impact": 3,
"quality_impact": 3,
"security_impact": 2
},
"interest_rate": {
"daily_cost": 2.4,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 0.16,
"category": "code_quality",
"impact_tags": [
"quick-win"
],
"priority_score": 4.8
},
{
"id": "DEBT-0011",
"type": "commented_code",
"description": "Dead code left in comments",
"file_path": "src/frontend.js",
"line_number": 285,
"severity": "low",
"metadata": {
"lines_of_commented_code": 8
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 1,
"hours_estimate": 5.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 2,
"revenue_impact": 2,
"team_velocity_impact": 3,
"quality_impact": 3,
"security_impact": 2
},
"interest_rate": {
"daily_cost": 2.4,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 2.1,
"category": "maintenance",
"impact_tags": [
"quick-win"
],
"priority_score": 4.8
}
],
"total_hours": 10.375,
"capacity_used": 0.6484375
},
{
"sprint_number": 2,
"items": [
{
"id": "DEBT-0007",
"type": "empty_catch_blocks",
"description": "Empty catch block in update_user method",
"file_path": "src/user_service.py",
"line_number": 156,
"severity": "medium",
"metadata": {
"method_name": "update_user",
"exception_type": "generic"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
}
],
"total_hours": 10.0,
"capacity_used": 0.625
},
{
"sprint_number": 3,
"items": [
{
"id": "DEBT-0009",
"type": "deep_nesting",
"description": "Deep nesting detected: 6 levels in preferences handling",
"file_path": "src/frontend.js",
"line_number": 32,
"severity": "medium",
"metadata": {
"nesting_level": 6,
"recommended_max": 4
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
}
],
"total_hours": 10.0,
"capacity_used": 0.625
},
{
"sprint_number": 4,
"items": [
{
"id": "DEBT-0012",
"type": "global_variables",
"description": "Global variable userCache should be encapsulated",
"file_path": "src/frontend.js",
"line_number": 7,
"severity": "medium",
"metadata": {
"variable_name": "userCache",
"scope": "global"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
}
],
"total_hours": 10.0,
"capacity_used": 0.625
},
{
"sprint_number": 5,
"items": [
{
"id": "DEBT-0014",
"type": "hardcoded_values",
"description": "Tax rates hardcoded in payment processing logic",
"file_path": "src/payment_processor.py",
"line_number": 45,
"severity": "medium",
"metadata": {
"values": [
"0.08",
"0.085",
"0.0625",
"0.06"
],
"context": "tax_calculation"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
}
],
"total_hours": 10.0,
"capacity_used": 0.625
},
{
"sprint_number": 6,
"items": [
{
"id": "DEBT-0016",
"type": "inefficient_algorithm",
"description": "O(n) user search could be optimized with indexing",
"file_path": "src/user_service.py",
"line_number": 178,
"severity": "medium",
"metadata": {
"current_complexity": "O(n)",
"recommended_complexity": "O(log n)",
"method_name": "search_users"
},
"detected_date": "2024-02-10T10:30:00",
"status": "identified",
"effort_estimate": {
"size_points": 2,
"hours_estimate": 10.0,
"risk_factor": 1.0,
"skill_level_required": "mid",
"confidence": 0.6
},
"business_impact": {
"customer_impact": 3,
"revenue_impact": 3,
"team_velocity_impact": 5,
"quality_impact": 5,
"security_impact": 3
},
"interest_rate": {
"daily_cost": 4.0,
"frequency_multiplier": 1.0,
"team_impact_multiplier": 1.0,
"compound_rate": 0.02
},
"cost_of_delay": 7.01,
"category": "other",
"impact_tags": [
"quick-win"
],
"priority_score": 4.72
}
],
"total_hours": 10.0,
"capacity_used": 0.625
}
],
"recommendations": [
"Allocate 16.0 hours per sprint to tech debt",
"Focus on 0 high-priority items first",
"Estimated 17 sprints to clear current backlog"
]
},
"insights": {
"category_distribution": {
"other": 11,
"code_quality": 5,
"maintenance": 2,
"testing": 1,
"security": 1
},
"total_effort_hours": 277.4,
"effort_by_category": {
"other": 130.0,
"code_quality": 61.6,
"maintenance": 5.8,
"testing": 36.0,
"security": 44.0
},
"priority_distribution": {
"medium": 17,
"low": 3
},
"high_risk_items_count": 1,
"quick_wins_count": 5,
"total_cost_of_delay": 303.6,
"average_daily_interest_rate": 4.69,
"top_categories_by_effort": [
[
"other",
130.0
],
[
"code_quality",
61.625
],
[
"security",
44.0
]
]
},
"charts_data": {
"priority_effort_scatter": [
{
"x": 5.0,
"y": 4.8,
"label": "Magic number 1800 used for lock timeout",
"category": "other",
"size": 2.1
},
{
"x": 0.375,
"y": 4.8,
"label": "Line too long: 156 characters",
"category": "code_quality",
"size": 0.16
},
{
"x": 5.0,
"y": 4.8,
"label": "Dead code left in comments",
"category": "maintenance",
"size": 2.1
},
{
"x": 10.0,
"y": 4.72,
"label": "Empty catch block in update_user method",
"category": "other",
"size": 7.01
},
{
"x": 10.0,
"y": 4.72,
"label": "Deep nesting detected: 6 levels in preferences han",
"category": "other",
"size": 7.01
},
{
"x": 10.0,
"y": 4.72,
"label": "Global variable userCache should be encapsulated",
"category": "other",
"size": 7.01
},
{
"x": 10.0,
"y": 4.72,
"label": "Tax rates hardcoded in payment processing logic",
"category": "other",
"size": 7.01
},
{
"x": 10.0,
"y": 4.72,
"label": "O(n) user search could be optimized with indexing",
"category": "other",
"size": 7.01
},
{
"x": 10.0,
"y": 4.72,
"label": "Event listeners attached without cleanup",
"category": "other",
"size": 7.01
},
{
"x": 15.0,
"y": 4.26,
"label": "create_user function in user_service.py is 89 line",
"category": "code_quality",
"size": 19.48
},
{
"x": 1.25,
"y": 4.1,
"label": "PaymentProcessor class missing docstring",
"category": "code_quality",
"size": 0.35
},
{
"x": 15.0,
"y": 3.73,
"label": "Synchronous AJAX call blocks UI thread",
"category": "other",
"size": 14.73
},
{
"x": 15.0,
"y": 3.73,
"label": "API calls without proper error handling",
"category": "other",
"size": 14.73
},
{
"x": 15.0,
"y": 3.73,
"label": "jQuery version 2.1.4 has known security vulnerabil",
"category": "other",
"size": 14.73
},
{
"x": 20.0,
"y": 3.24,
"label": "Potential SQL injection in user query",
"category": "other",
"size": 25.26
},
{
"x": 0.75,
"y": 3.1,
"label": "TODO: Move this to configuration file",
"category": "maintenance",
"size": 0.11
},
{
"x": 15.0,
"y": 2.39,
"label": "Password validation logic duplicated in 3 location",
"category": "code_quality",
"size": 12.69
},
{
"x": 36.0,
"y": 1.94,
"label": "No unit tests for critical payment processing logi",
"category": "testing",
"size": 50.82
},
{
"x": 30.0,
"y": 1.65,
"label": "process_payment function has cyclomatic complexity",
"category": "code_quality",
"size": 42.36
},
{
"x": 44.0,
"y": 1.01,
"label": "Hardcoded API key in payment_processor.py",
"category": "security",
"size": 61.91
}
],
"category_effort_distribution": [
{
"category": "other",
"effort": 130.0
},
{
"category": "code_quality",
"effort": 61.6
},
{
"category": "maintenance",
"effort": 5.8
},
{
"category": "testing",
"effort": 36.0
},
{
"category": "security",
"effort": 44.0
}
],
"priority_timeline": [
{
"item_rank": 1,
"description": "Magic number 1800 used for loc",
"effort": 5.0,
"cumulative_effort": 5.0,
"priority_score": 4.8
},
{
"item_rank": 2,
"description": "Line too long: 156 characters",
"effort": 0.375,
"cumulative_effort": 5.4,
"priority_score": 4.8
},
{
"item_rank": 3,
"description": "Dead code left in comments",
"effort": 5.0,
"cumulative_effort": 10.4,
"priority_score": 4.8
},
{
"item_rank": 4,
"description": "Empty catch block in update_us",
"effort": 10.0,
"cumulative_effort": 20.4,
"priority_score": 4.72
},
{
"item_rank": 5,
"description": "Deep nesting detected: 6 level",
"effort": 10.0,
"cumulative_effort": 30.4,
"priority_score": 4.72
},
{
"item_rank": 6,
"description": "Global variable userCache shou",
"effort": 10.0,
"cumulative_effort": 40.4,
"priority_score": 4.72
},
{
"item_rank": 7,
"description": "Tax rates hardcoded in payment",
"effort": 10.0,
"cumulative_effort": 50.4,
"priority_score": 4.72
},
{
"item_rank": 8,
"description": "O(n) user search could be opti",
"effort": 10.0,
"cumulative_effort": 60.4,
"priority_score": 4.72
},
{
"item_rank": 9,
"description": "Event listeners attached witho",
"effort": 10.0,
"cumulative_effort": 70.4,
"priority_score": 4.72
},
{
"item_rank": 10,
"description": "create_user function in user_s",
"effort": 15.0,
"cumulative_effort": 85.4,
"priority_score": 4.26
},
{
"item_rank": 11,
"description": "PaymentProcessor class missing",
"effort": 1.25,
"cumulative_effort": 86.6,
"priority_score": 4.1
},
{
"item_rank": 12,
"description": "Synchronous AJAX call blocks U",
"effort": 15.0,
"cumulative_effort": 101.6,
"priority_score": 3.73
},
{
"item_rank": 13,
"description": "API calls without proper error",
"effort": 15.0,
"cumulative_effort": 116.6,
"priority_score": 3.73
},
{
"item_rank": 14,
"description": "jQuery version 2.1.4 has known",
"effort": 15.0,
"cumulative_effort": 131.6,
"priority_score": 3.73
},
{
"item_rank": 15,
"description": "Potential SQL injection in use",
"effort": 20.0,
"cumulative_effort": 151.6,
"priority_score": 3.24
},
{
"item_rank": 16,
"description": "TODO: Move this to configurati",
"effort": 0.75,
"cumulative_effort": 152.4,
"priority_score": 3.1
},
{
"item_rank": 17,
"description": "Password validation logic dupl",
"effort": 15.0,
"cumulative_effort": 167.4,
"priority_score": 2.39
},
{
"item_rank": 18,
"description": "No unit tests for critical pay",
"effort": 36.0,
"cumulative_effort": 203.4,
"priority_score": 1.94
},
{
"item_rank": 19,
"description": "process_payment function has c",
"effort": 30.0,
"cumulative_effort": 233.4,
"priority_score": 1.65
},
{
"item_rank": 20,
"description": "Hardcoded API key in payment_p",
"effort": 44.0,
"cumulative_effort": 277.4,
"priority_score": 1.01
}
],
"interest_rate_trend": [
{
"item_index": 0,
"daily_cost": 2.4,
"category": "other"
},
{
"item_index": 1,
"daily_cost": 2.4,
"category": "code_quality"
},
{
"item_index": 2,
"daily_cost": 2.4,
"category": "maintenance"
},
{
"item_index": 3,
"daily_cost": 4.0,
"category": "other"
},
{
"item_index": 4,
"daily_cost": 4.0,
"category": "other"
},
{
"item_index": 5,
"daily_cost": 4.0,
"category": "other"
},
{
"item_index": 6,
"daily_cost": 4.0,
"category": "other"
},
{
"item_index": 7,
"daily_cost": 4.0,
"category": "other"
},
{
"item_index": 8,
"daily_cost": 4.0,
"category": "other"
},
{
"item_index": 9,
"daily_cost": 7.4,
"category": "code_quality"
},
{
"item_index": 10,
"daily_cost": 1.6,
"category": "code_quality"
},
{
"item_index": 11,
"daily_cost": 5.6,
"category": "other"
},
{
"item_index": 12,
"daily_cost": 5.6,
"category": "other"
},
{
"item_index": 13,
"daily_cost": 5.6,
"category": "other"
},
{
"item_index": 14,
"daily_cost": 7.199999999999999,
"category": "other"
},
{
"item_index": 15,
"daily_cost": 0.8,
"category": "maintenance"
},
{
"item_index": 16,
"daily_cost": 4.8,
"category": "code_quality"
},
{
"item_index": 17,
"daily_cost": 8.0,
"category": "testing"
},
{
"item_index": 18,
"daily_cost": 8.0,
"category": "code_quality"
},
{
"item_index": 19,
"daily_cost": 8.0,
"category": "security"
}
]
},
"recommendations": [
"Start with 5 quick wins to build momentum and demonstrate immediate value from tech debt reduction efforts.",
"Focus initial efforts on 'other' category debt, which represents the largest effort investment (130.0 hours)."
]
}Tech Debt Tracker
A comprehensive technical debt management system that helps engineering teams identify, prioritize, and track technical debt across codebases. This skill provides three interconnected tools for a complete debt management workflow.
Overview
Technical debt is like financial debt - it compounds over time and reduces team velocity if not managed systematically. This skill provides:
- Automated Debt Detection: Scan codebases to identify various types of technical debt
- Intelligent Prioritization: Use proven frameworks to prioritize debt based on business impact
- Trend Analysis: Track debt evolution over time with executive-friendly dashboards
Tools
1. Debt Scanner (debt_scanner.py)
Scans codebases to automatically detect technical debt signals using AST parsing for Python and regex patterns for other languages.
Features:
- Detects 15+ types of technical debt (large functions, complexity, duplicates, security issues, etc.)
- Multi-language support (Python, JavaScript, Java, C#, Go, etc.)
- Configurable thresholds and rules
- Dual output: JSON for tools, human-readable for reports
Usage:
# Basic scan
python scripts/debt_scanner.py /path/to/codebase
# With custom config and output
python scripts/debt_scanner.py /path/to/codebase --config config.json --output report.json
# Different output formats
python scripts/debt_scanner.py /path/to/codebase --format both2. Debt Prioritizer (debt_prioritizer.py)
Takes debt inventory and creates prioritized backlog using proven prioritization frameworks.
Features:
- Multiple prioritization frameworks (Cost of Delay, WSJF, RICE)
- Business impact analysis with ROI calculations
- Sprint allocation recommendations
- Effort estimation with risk adjustment
- Executive and engineering reports
Usage:
# Basic prioritization
python scripts/debt_prioritizer.py debt_inventory.json
# Custom framework and team size
python scripts/debt_prioritizer.py inventory.json --framework wsjf --team-size 8
# Sprint capacity planning
python scripts/debt_prioritizer.py inventory.json --sprint-capacity 80 --output backlog.json3. Debt Dashboard (debt_dashboard.py)
Analyzes historical debt data to provide trend analysis, health scoring, and executive reporting.
Features:
- Health score trending over time
- Debt velocity analysis (accumulation vs resolution)
- Executive summary with business impact
- Forecasting based on current trends
- Strategic recommendations
Usage:
# Single directory of scans
python scripts/debt_dashboard.py --input-dir ./debt_scans/
# Multiple specific files
python scripts/debt_dashboard.py scan1.json scan2.json scan3.json
# Custom analysis period
python scripts/debt_dashboard.py data.json --period quarterly --team-size 6Quick Start
1. Scan Your Codebase
# Scan your project
python scripts/debt_scanner.py ~/my-project --output initial_scan.json
# Review the results
python scripts/debt_scanner.py ~/my-project --format text2. Prioritize Your Debt
# Create prioritized backlog
python scripts/debt_prioritizer.py initial_scan.json --output backlog.json
# View sprint recommendations
python scripts/debt_prioritizer.py initial_scan.json --format text3. Track Over Time
# After multiple scans, analyze trends
python scripts/debt_dashboard.py scan1.json scan2.json scan3.json --output dashboard.json
# Generate executive report
python scripts/debt_dashboard.py --input-dir ./scans/ --format textConfiguration
Scanner Configuration
Create config.json to customize detection rules:
{
"max_function_length": 50,
"max_complexity": 10,
"max_nesting_depth": 4,
"ignore_patterns": ["*.test.js", "build/", "node_modules/"],
"file_extensions": {
"python": [".py"],
"javascript": [".js", ".jsx", ".ts", ".tsx"]
}
}Team Configuration
Adjust tools for your team size and sprint capacity:
# 8-person team with 2-week sprints
python scripts/debt_prioritizer.py inventory.json --team-size 8 --sprint-capacity 160Sample Data
The assets/ directory contains sample data for testing:
sample_codebase/: Example codebase with various debt typessample_debt_inventory.json: Example debt inventoryhistorical_debt_*.json: Sample historical data for trending
Try the tools on sample data:
# Test scanner
python scripts/debt_scanner.py assets/sample_codebase
# Test prioritizer
python scripts/debt_prioritizer.py assets/sample_debt_inventory.json
# Test dashboard
python scripts/debt_dashboard.py assets/historical_debt_*.jsonUnderstanding the Output
Health Score (0-100)
- 85-100: Excellent - Minimal debt, sustainable practices
- 70-84: Good - Manageable debt level, some attention needed
- 55-69: Fair - Debt accumulating, requires focused effort
- 40-54: Poor - High debt level, impacts productivity
- 0-39: Critical - Immediate action required
Priority Levels
- Critical: Security issues, blocking problems (fix immediately)
- High: Significant impact on quality or velocity (next sprint)
- Medium: Moderate impact, plan for upcoming work (next quarter)
- Low: Minor issues, fix opportunistically (when convenient)
Debt Categories
- Code Quality: Large functions, complexity, duplicates
- Architecture: Design issues, coupling problems
- Security: Vulnerabilities, hardcoded secrets
- Testing: Missing tests, poor coverage
- Documentation: Missing or outdated docs
- Dependencies: Outdated packages, license issues
Integration with Development Workflow
CI/CD Integration
Add debt scanning to your CI pipeline:
# In your CI script
python scripts/debt_scanner.py . --output ci_scan.json
# Compare with baseline, fail build if critical issues foundSprint Planning
1. Weekly: Run scanner to detect new debt 2. Sprint Planning: Use prioritizer for debt story sizing 3. Monthly: Generate dashboard for trend analysis 4. Quarterly: Executive review with strategic recommendations
Code Review Integration
Use scanner output to focus code reviews:
# Scan PR branch
python scripts/debt_scanner.py . --output pr_scan.json
# Compare with main branch baseline
# Focus review on areas with new debtBest Practices
Debt Management Strategy
1. Prevention: Use scanner in CI to catch debt early 2. Prioritization: Always use business impact for priority 3. Allocation: Reserve 15-20% sprint capacity for debt work 4. Measurement: Track health score and velocity impact 5. Communication: Use dashboard reports for stakeholders
Common Pitfalls to Avoid
- Analysis Paralysis: Don't spend too long on perfect prioritization
- Technical Focus Only: Always consider business impact
- Inconsistent Application: Ensure all teams use same approach
- Ignoring Trends: Pay attention to debt accumulation rate
- All-or-Nothing: Incremental debt reduction is better than none
Success Metrics
- Health Score Improvement: Target 5+ point quarterly improvement
- Velocity Impact: Keep debt velocity impact below 20%
- Team Satisfaction: Survey developers on code quality satisfaction
- Incident Reduction: Track correlation between debt and production issues
Advanced Usage
Custom Debt Types
Extend the scanner for organization-specific debt patterns:
1. Add patterns to config.json 2. Modify detection logic in scanner 3. Update categorization in prioritizer
Integration with External Tools
- Jira/GitHub: Import debt items as tickets
- SonarQube: Combine with static analysis metrics
- APM Tools: Correlate debt with performance metrics
- Chat Systems: Send debt alerts to team channels
Automated Reporting
Set up automated debt reporting:
#!/bin/bash
# Daily debt monitoring script
python scripts/debt_scanner.py . --output daily_scan.json
python scripts/debt_dashboard.py daily_scan.json --output daily_report.json
# Send report to stakeholdersTroubleshooting
Common Issues
Scanner not finding files: Check ignore_patterns in config Prioritizer giving unexpected results: Verify business impact scoring Dashboard shows flat trends: Need more historical data points
Performance Tips
- Use
.gitignorepatterns to exclude irrelevant files - Limit scan depth for large monorepos
- Run dashboard analysis on subset for faster iteration
Getting Help
1. Check the references/ directory for detailed documentation 2. Review sample data and expected outputs 3. Examine the tool source code for customization ideas
Contributing
This skill is designed to be customized for your organization's needs:
1. Add Detection Rules: Extend scanner patterns for your tech stack 2. Custom Prioritization: Modify scoring algorithms for your business context 3. New Report Formats: Add output formats for your stakeholders 4. Integration Hooks: Add connectors to your existing tools
The codebase is designed with extensibility in mind - each tool is modular and can be enhanced independently.
---
Remember: Technical debt management is a journey, not a destination. These tools help you make informed decisions about balancing new feature development with technical excellence. Start small, measure impact, and iterate based on what works for your team.
Related skills
How it compares
Use tech-debt-tracker for portfolio debt inventories and health scores; use ESLint or language linters when you need rule-by-rule style enforcement on each commit.
FAQ
What metrics does tech-debt-tracker report?
tech-debt-tracker reports total files scanned, lines scanned, total debt items, health_score, and debt_density. An example scan of 25 files and 12,543 lines found 28 debt items with a 68.5 health score and 1.12 debt density.
What debt types does tech-debt-tracker detect?
tech-debt-tracker detects items such as large functions and duplicate code, assigning IDs like DEBT-0001 with severity, file_path, and status fields. Output is structured JSON suitable for sprint backlog import and prioritization.
Is Tech Debt Tracker safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.