#!/usr/bin/env python3 """清理孤儿任务 — 删除不属于任何现有项目的任务记录""" import sqlite3 import os import sys # 自动定位数据库 candidates = [] appdata = os.environ.get("APPDATA", "") if appdata: candidates.append(os.path.join(appdata, "top.1216.devflow", "devflow-dev.db")) candidates.append(os.path.join(appdata, "top.1216.devflow", "devflow.db")) localappdata = os.environ.get("LOCALAPPDATA", "") if localappdata: candidates.append(os.path.join(localappdata, "top.1216.devflow", "devflow-dev.db")) # 也支持命令行传参 if len(sys.argv) > 1: candidates.insert(0, sys.argv[1]) db_path = None for c in candidates: if os.path.isfile(c): db_path = c break if not db_path: print("❌ 未找到数据库文件,尝试过的路径:") for c in candidates: print(f" {c}") print("\n请手动指定: python scripts/cleanup_orphan_tasks.py ") sys.exit(1) print(f"📍 数据库: {db_path}\n") conn = sqlite3.connect(db_path) conn.execute("PRAGMA foreign_keys = OFF") # 查看孤儿任务 rows = conn.execute(""" SELECT t.id, t.title, t.project_id FROM tasks t LEFT JOIN projects p ON t.project_id = p.id WHERE p.id IS NULL ORDER BY t.project_id, t.created_at """).fetchall() print(f"=== 孤儿任务列表({len(rows)} 条)===\n") for tid, title, pid in rows: print(f" [{pid[:8]}...] {title}") print() if not rows: print("✅ 无孤儿任务,无需清理。") conn.close() sys.exit(0) # 直接删除(无需确认,用户已通过对话授权) conn.execute(""" DELETE FROM tasks WHERE project_id NOT IN (SELECT id FROM projects) """) conn.commit() # 验证 remaining = conn.execute(""" SELECT COUNT(*) FROM tasks t LEFT JOIN projects p ON t.project_id = p.id WHERE p.id IS NULL """).fetchone()[0] total = conn.execute("SELECT COUNT(*) FROM tasks").fetchone()[0] conn.close() print(f"✅ 已删除 {len(rows)} 条孤儿任务") print(f"📊 剩余任务: {total} 条(孤儿: {remaining} 条)")