99
1010def load_state ():
1111 """Load workflow state"""
12- state_file = Path (' .conductor/workflow-state.json' )
12+ state_file = Path (" .conductor/workflow-state.json" )
1313 if not state_file .exists ():
1414 print ("❌ Workflow state file not found" )
1515 sys .exit (1 )
1616
1717 try :
18- with open (state_file , 'r' ) as f :
18+ with open (state_file , "r" ) as f :
1919 return json .load (f )
2020 except json .JSONDecodeError :
2121 print ("❌ Invalid workflow state file" )
@@ -24,9 +24,9 @@ def load_state():
2424
2525def save_state (state ):
2626 """Save workflow state"""
27- state_file = Path (' .conductor/workflow-state.json' )
27+ state_file = Path (" .conductor/workflow-state.json" )
2828 try :
29- with open (state_file , 'w' ) as f :
29+ with open (state_file , "w" ) as f :
3030 json .dump (state , f , indent = 2 )
3131 except Exception as e :
3232 print (f"❌ Failed to save state: { e } " )
@@ -35,8 +35,8 @@ def save_state(state):
3535
3636def archive_completed_tasks (state , max_age_days = 30 ):
3737 """Archive completed tasks older than max_age_days"""
38- if ' completed_work' not in state :
39- state [' completed_work' ] = []
38+ if " completed_work" not in state :
39+ state [" completed_work" ] = []
4040
4141 current_time = datetime .utcnow ()
4242 cutoff_date = current_time - timedelta (days = max_age_days )
@@ -45,11 +45,13 @@ def archive_completed_tasks(state, max_age_days=30):
4545 recent_completed = []
4646 archived_count = 0
4747
48- for work in state [' completed_work' ]:
49- completed_at_str = work .get (' completed_at' )
48+ for work in state [" completed_work" ]:
49+ completed_at_str = work .get (" completed_at" )
5050 if completed_at_str :
5151 try :
52- completed_at = datetime .fromisoformat (completed_at_str .replace ('Z' , '+00:00' ))
52+ completed_at = datetime .fromisoformat (
53+ completed_at_str .replace ("Z" , "+00:00" )
54+ )
5355 if completed_at >= cutoff_date :
5456 recent_completed .append (work )
5557 else :
@@ -62,10 +64,12 @@ def archive_completed_tasks(state, max_age_days=30):
6264 recent_completed .append (work )
6365
6466 # Update completed work to only include recent items
65- state [' completed_work' ] = recent_completed
67+ state [" completed_work" ] = recent_completed
6668
6769 if archived_count > 0 :
68- print (f"📦 Archived { archived_count } completed task(s) older than { max_age_days } days" )
70+ print (
71+ f"📦 Archived { archived_count } completed task(s) older than { max_age_days } days"
72+ )
6973 else :
7074 print ("ℹ️ No old completed tasks to archive" )
7175
@@ -74,23 +78,23 @@ def archive_completed_tasks(state, max_age_days=30):
7478
7579def clean_stale_active_work (state , stale_timeout_minutes = 30 ):
7680 """Move stale active work to completed with appropriate status"""
77- if ' active_work' not in state :
78- state [' active_work' ] = {}
81+ if " active_work" not in state :
82+ state [" active_work" ] = {}
7983
80- if ' completed_work' not in state :
81- state [' completed_work' ] = []
84+ if " completed_work" not in state :
85+ state [" completed_work" ] = []
8286
8387 current_time = datetime .utcnow ()
8488 stale_cutoff = current_time - timedelta (minutes = stale_timeout_minutes )
8589
86- active_work = state [' active_work' ]
90+ active_work = state [" active_work" ]
8791 stale_agents = []
8892
8993 for agent_id , work in list (active_work .items ()):
90- heartbeat_str = work .get (' heartbeat' )
94+ heartbeat_str = work .get (" heartbeat" )
9195 if heartbeat_str :
9296 try :
93- heartbeat = datetime .fromisoformat (heartbeat_str .replace ('Z' , ' +00:00' ))
97+ heartbeat = datetime .fromisoformat (heartbeat_str .replace ("Z" , " +00:00" ))
9498 if heartbeat < stale_cutoff :
9599 stale_agents .append (agent_id )
96100 except ValueError :
@@ -106,11 +110,11 @@ def clean_stale_active_work(state, stale_timeout_minutes=30):
106110 work = active_work .pop (agent_id )
107111
108112 # Mark as abandoned
109- work [' status' ] = ' abandoned'
110- work [' completed_at' ] = current_time .isoformat ()
111- work [' abandonment_reason' ] = ' stale_heartbeat'
113+ work [" status" ] = " abandoned"
114+ work [" completed_at" ] = current_time .isoformat ()
115+ work [" abandonment_reason" ] = " stale_heartbeat"
112116
113- state [' completed_work' ].append (work )
117+ state [" completed_work" ].append (work )
114118 cleaned_count += 1
115119
116120 if cleaned_count > 0 :
@@ -124,22 +128,22 @@ def clean_stale_active_work(state, stale_timeout_minutes=30):
124128def optimize_state_file (state ):
125129 """Optimize state file by removing redundant data and organizing"""
126130 # Ensure all required sections exist
127- if ' active_work' not in state :
128- state [' active_work' ] = {}
129- if ' available_tasks' not in state :
130- state [' available_tasks' ] = []
131- if ' completed_work' not in state :
132- state [' completed_work' ] = []
133- if ' system_status' not in state :
134- state [' system_status' ] = {}
131+ if " active_work" not in state :
132+ state [" active_work" ] = {}
133+ if " available_tasks" not in state :
134+ state [" available_tasks" ] = []
135+ if " completed_work" not in state :
136+ state [" completed_work" ] = []
137+ if " system_status" not in state :
138+ state [" system_status" ] = {}
135139
136140 # Sort tasks by creation date (newest first)
137- for task_list in [state [' available_tasks' ], state [' completed_work' ]]:
141+ for task_list in [state [" available_tasks" ], state [" completed_work" ]]:
138142 if isinstance (task_list , list ):
139- task_list .sort (key = lambda x : x .get (' created_at' , '' ), reverse = True )
143+ task_list .sort (key = lambda x : x .get (" created_at" , "" ), reverse = True )
140144
141145 # Update system status
142- state [' system_status' ][ ' last_cleanup' ] = datetime .utcnow ().isoformat ()
146+ state [" system_status" ][ " last_cleanup" ] = datetime .utcnow ().isoformat ()
143147
144148 print ("✨ Optimized state file structure" )
145149
@@ -150,11 +154,11 @@ def generate_cleanup_report(state, archived_count, cleaned_count):
150154 print ("=" * 30 )
151155
152156 current_metrics = {
153- ' active_agents' : len (state .get (' active_work' , {})),
154- ' available_tasks' : len (state .get (' available_tasks' , [])),
155- ' completed_tasks' : len (state .get (' completed_work' , [])),
156- ' archived_tasks' : archived_count ,
157- ' cleaned_stale' : cleaned_count
157+ " active_agents" : len (state .get (" active_work" , {})),
158+ " available_tasks" : len (state .get (" available_tasks" , [])),
159+ " completed_tasks" : len (state .get (" completed_work" , [])),
160+ " archived_tasks" : archived_count ,
161+ " cleaned_stale" : cleaned_count ,
158162 }
159163
160164 for metric , value in current_metrics .items ():
@@ -166,13 +170,26 @@ def generate_cleanup_report(state, archived_count, cleaned_count):
166170def main ():
167171 import argparse
168172
169- parser = argparse .ArgumentParser (description = "Archive completed tasks and clean up state" )
170- parser .add_argument ("--max-age" , type = int , default = 30 ,
171- help = "Maximum age in days for completed tasks (default: 30)" )
172- parser .add_argument ("--stale-timeout" , type = int , default = 30 ,
173- help = "Stale timeout in minutes for active work (default: 30)" )
174- parser .add_argument ("--dry-run" , action = "store_true" ,
175- help = "Show what would be done without making changes" )
173+ parser = argparse .ArgumentParser (
174+ description = "Archive completed tasks and clean up state"
175+ )
176+ parser .add_argument (
177+ "--max-age" ,
178+ type = int ,
179+ default = 30 ,
180+ help = "Maximum age in days for completed tasks (default: 30)" ,
181+ )
182+ parser .add_argument (
183+ "--stale-timeout" ,
184+ type = int ,
185+ default = 30 ,
186+ help = "Stale timeout in minutes for active work (default: 30)" ,
187+ )
188+ parser .add_argument (
189+ "--dry-run" ,
190+ action = "store_true" ,
191+ help = "Show what would be done without making changes" ,
192+ )
176193
177194 args = parser .parse_args ()
178195
@@ -188,7 +205,9 @@ def main():
188205 archived_count = 0 if args .dry_run else archive_completed_tasks (state , args .max_age )
189206
190207 # Clean stale active work
191- cleaned_count = 0 if args .dry_run else clean_stale_active_work (state , args .stale_timeout )
208+ cleaned_count = (
209+ 0 if args .dry_run else clean_stale_active_work (state , args .stale_timeout )
210+ )
192211
193212 # Optimize state file
194213 if not args .dry_run :
0 commit comments