1+ #!/usr/bin/env python3
2+ """
3+ Direct cleanup script to archive old tasks from the database.
4+ """
5+
6+ import sqlite3
7+ import datetime
8+ from pathlib import Path
9+ import json
10+
11+ def cleanup_old_tasks (db_path , age_days = 2 ):
12+ """Archive tasks older than specified days."""
13+
14+ conn = sqlite3 .connect (db_path )
15+ cursor = conn .cursor ()
16+
17+ # Calculate cutoff date
18+ cutoff_date = datetime .datetime .now () - datetime .timedelta (days = age_days )
19+
20+ print (f"Archiving tasks older than { age_days } days (before { cutoff_date .strftime ('%Y-%m-%d' )} )" )
21+ print ("=" * 80 )
22+
23+ # Find old active/pending tasks
24+ cursor .execute ("""
25+ SELECT task_id, title, status, specialist_type, created_at
26+ FROM subtasks
27+ WHERE status IN ('active', 'pending')
28+ AND created_at < ?
29+ ORDER BY created_at
30+ """ , (cutoff_date .isoformat (),))
31+
32+ old_tasks = cursor .fetchall ()
33+
34+ if not old_tasks :
35+ print ("No old tasks found to archive." )
36+ return
37+
38+ print (f"\n Found { len (old_tasks )} tasks to archive:" )
39+
40+ # Create archive record
41+ archive_data = {
42+ 'archived_at' : datetime .datetime .now ().isoformat (),
43+ 'reason' : f'Tasks older than { age_days } days' ,
44+ 'tasks' : []
45+ }
46+
47+ for task in old_tasks :
48+ task_id , title , status , specialist_type , created_at = task
49+ print (f"\n - { task_id } " )
50+ print (f" Title: { title } " )
51+ print (f" Status: { status } " )
52+ print (f" Created: { created_at } " )
53+
54+ archive_data ['tasks' ].append ({
55+ 'task_id' : task_id ,
56+ 'title' : title ,
57+ 'status' : status ,
58+ 'specialist_type' : specialist_type ,
59+ 'created_at' : created_at
60+ })
61+
62+ # Save archive
63+ archive_dir = Path ("archives/task_cleanup" )
64+ archive_dir .mkdir (parents = True , exist_ok = True )
65+
66+ archive_file = archive_dir / f"archived_tasks_{ datetime .datetime .now ().strftime ('%Y%m%d_%H%M%S' )} .json"
67+ with open (archive_file , 'w' ) as f :
68+ json .dump (archive_data , f , indent = 2 )
69+
70+ print (f"\n \n Archive saved to: { archive_file } " )
71+
72+ # Ask for confirmation
73+ response = input ("\n Proceed with archiving these tasks? (yes/no): " )
74+
75+ if response .lower () == 'yes' :
76+ # Update tasks to completed with archive note
77+ for task in old_tasks :
78+ cursor .execute ("""
79+ UPDATE subtasks
80+ SET status = 'completed',
81+ results = 'Archived due to age (auto-cleanup)',
82+ completed_at = ?
83+ WHERE task_id = ?
84+ """ , (datetime .datetime .now ().isoformat (), task [0 ]))
85+
86+ conn .commit ()
87+ print (f"\n ✓ Successfully archived { len (old_tasks )} tasks" )
88+ else :
89+ print ("\n Archiving cancelled." )
90+
91+ conn .close ()
92+
93+ if __name__ == "__main__" :
94+ db_path = Path ("task_orchestrator.db" )
95+
96+ if not db_path .exists ():
97+ print ("Database not found!" )
98+ exit (1 )
99+
100+ cleanup_old_tasks (db_path )
0 commit comments