diff --git a/core/repair_worker.py b/core/repair_worker.py
index 6cb4eb75..facb4cdf 100644
--- a/core/repair_worker.py
+++ b/core/repair_worker.py
@@ -1075,6 +1075,36 @@ class RepairWorker:
if conn:
conn.close()
+ def clear_findings(self, job_id: str = None, status: str = None) -> int:
+ """Delete findings from the database. Optionally filter by job_id and/or status. Returns count deleted."""
+ conn = None
+ try:
+ conn = self.db._get_connection()
+ cursor = conn.cursor()
+ conditions = []
+ params = []
+ if job_id:
+ conditions.append("job_id = ?")
+ params.append(job_id)
+ if status:
+ conditions.append("status = ?")
+ params.append(status)
+ where = f" WHERE {' AND '.join(conditions)}" if conditions else ""
+ cursor.execute(f"SELECT COUNT(*) FROM repair_findings{where}", params)
+ count = cursor.fetchone()[0]
+ cursor.execute(f"DELETE FROM repair_findings{where}", params)
+ conn.commit()
+ logger.info("Cleared %d findings%s%s", count,
+ f" for job {job_id}" if job_id else "",
+ f" with status {status}" if status else "")
+ return count
+ except Exception as e:
+ logger.error("Error clearing findings: %s", e)
+ return 0
+ finally:
+ if conn:
+ conn.close()
+
def _get_findings_count(self, status: str = None) -> int:
"""Get count of findings by status."""
conn = None
diff --git a/web_server.py b/web_server.py
index 16a758be..131fa9d8 100644
--- a/web_server.py
+++ b/web_server.py
@@ -39031,6 +39031,23 @@ def repair_findings_bulk():
logger.error(f"Error bulk updating findings: {e}")
return jsonify({'error': str(e)}), 500
+@app.route('/api/repair/findings/clear', methods=['POST'])
+def repair_findings_clear():
+ """Clear (delete) findings, optionally filtered by job_id and/or status"""
+ try:
+ if repair_worker is None:
+ return jsonify({'error': 'Repair worker not initialized'}), 400
+
+ data = request.get_json(silent=True) or {}
+ job_id = data.get('job_id')
+ status = data.get('status')
+
+ count = repair_worker.clear_findings(job_id=job_id, status=status)
+ return jsonify({'success': True, 'deleted': count}), 200
+ except Exception as e:
+ logger.error(f"Error clearing findings: {e}")
+ return jsonify({'error': str(e)}), 500
+
@app.route('/api/repair/history', methods=['GET'])
def repair_history():
"""Get job run history"""
diff --git a/webui/index.html b/webui/index.html
index 5dcd17d8..e100db4f 100644
--- a/webui/index.html
+++ b/webui/index.html
@@ -5774,6 +5774,7 @@
+
Loading findings...
diff --git a/webui/static/script.js b/webui/static/script.js
index 6b07fc79..9cb218ac 100644
--- a/webui/static/script.js
+++ b/webui/static/script.js
@@ -52617,6 +52617,47 @@ async function bulkFixFindings() {
updateRepairStatus();
}
+async function clearRepairFindings() {
+ const jobFilter = document.getElementById('repair-findings-job-filter');
+ const statusFilter = document.getElementById('repair-findings-status-filter');
+ const jobId = jobFilter ? jobFilter.value : '';
+ const status = statusFilter ? statusFilter.value : '';
+
+ const scopeLabel = jobId ? jobId.replace(/_/g, ' ') : 'all jobs';
+ const statusLabel = status ? ` (${status})` : '';
+ if (!await showConfirmDialog({
+ title: 'Clear Findings',
+ message: `Delete all findings for ${scopeLabel}${statusLabel}? This cannot be undone.`,
+ confirmText: 'Clear',
+ destructive: true
+ })) return;
+
+ try {
+ const body = {};
+ if (jobId) body.job_id = jobId;
+ if (status) body.status = status;
+
+ const response = await fetch('/api/repair/findings/clear', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(body)
+ });
+ const result = await response.json();
+ if (result.success) {
+ showToast(`Cleared ${result.deleted} findings`, 'success');
+ } else {
+ showToast(result.error || 'Failed to clear findings', 'error');
+ }
+ _repairSelectedFindings.clear();
+ loadRepairFindingsDashboard();
+ loadRepairFindings();
+ updateRepairStatus();
+ } catch (error) {
+ console.error('Error clearing findings:', error);
+ showToast('Error clearing findings', 'error');
+ }
+}
+
async function loadRepairHistory() {
const container = document.getElementById('repair-history-list');
if (!container) return;
diff --git a/webui/static/style.css b/webui/static/style.css
index 903a761e..52fa1e26 100644
--- a/webui/static/style.css
+++ b/webui/static/style.css
@@ -40803,7 +40803,7 @@ tr.tag-diff-same {
.repair-findings-toolbar {
display: flex;
align-items: center;
- justify-content: space-between;
+ flex-wrap: wrap;
margin-bottom: 14px;
gap: 10px;
flex-wrap: wrap;
@@ -40872,6 +40872,23 @@ tr.tag-diff-same {
background: rgba(var(--accent-rgb, 99, 102, 241), 0.2);
}
+.repair-clear-btn {
+ margin-left: auto;
+ background: rgba(239, 68, 68, 0.08);
+ border: 1px solid rgba(239, 68, 68, 0.2);
+ border-radius: 6px;
+ padding: 5px 12px;
+ color: #f87171;
+ font-size: 11px;
+ cursor: pointer;
+ transition: all 0.2s ease;
+}
+
+.repair-clear-btn:hover {
+ background: rgba(239, 68, 68, 0.18);
+ border-color: rgba(239, 68, 68, 0.4);
+}
+
.repair-findings-list {
display: flex;
flex-direction: column;