@@ -334,9 +334,29 @@ def run_expert_review(state: WorkflowState) -> WorkflowState:
334334
335335 # Check if we should skip this phase (resume mode)
336336 resume_config = state .get ("_resume_config" , {})
337- if resume_config and resume_config .get ("reuse_stages" , {}).get ("expert_review" ):
338- print (" ⏭️ Skipping (reusing from previous run)" )
339- return state
337+ if resume_config :
338+ reuse_stages = resume_config .get ("reuse_stages" , {})
339+ if reuse_stages .get ("expert_review" ):
340+ print (" ⏭️ Reusing expert_review from previous run" )
341+ # Copy all files related to expert_review to new directory
342+ resume_run_dir = Path (resume_config ["run_dir" ])
343+ prev_run = RunInfo (resume_run_dir )
344+ debug = get_debug_manager (config )
345+ if debug .enabled :
346+ import shutil
347+ # Copy all expert_review related files
348+ expert_review_files = prev_run .get_stage_files ("expert_review" )
349+ if expert_review_files :
350+ for file_info in expert_review_files :
351+ try :
352+ dest = debug .run_dir / file_info ["filename" ]
353+ shutil .copy2 (file_info ["path" ], dest )
354+ print (f" 💾 Copied: { file_info ['filename' ]} " )
355+ except Exception as e :
356+ print (f" ⚠ Failed to copy { file_info ['filename' ]} : { e } " )
357+ else :
358+ print (" ⚠ No expert_review files found in previous run" )
359+ return state
340360
341361 debug = get_debug_manager (config )
342362
@@ -382,9 +402,29 @@ def run_full_discussion(state: WorkflowState) -> WorkflowState:
382402
383403 # Check if we should skip this phase (resume mode)
384404 resume_config = state .get ("_resume_config" , {})
385- if resume_config and resume_config .get ("reuse_stages" , {}).get ("full_discussion" ):
386- print (" ⏭️ Skipping (reusing from previous run)" )
387- return state
405+ if resume_config :
406+ reuse_stages = resume_config .get ("reuse_stages" , {})
407+ if reuse_stages .get ("full_discussion" ):
408+ print (" ⏭️ Reusing full_discussion from previous run" )
409+ # Copy all files related to full_discussion to new directory
410+ resume_run_dir = Path (resume_config ["run_dir" ])
411+ prev_run = RunInfo (resume_run_dir )
412+ debug = get_debug_manager (config )
413+ if debug .enabled :
414+ import shutil
415+ # Copy all full_discussion related files
416+ discussion_files = prev_run .get_stage_files ("full_discussion" )
417+ if discussion_files :
418+ for file_info in discussion_files :
419+ try :
420+ dest = debug .run_dir / file_info ["filename" ]
421+ shutil .copy2 (file_info ["path" ], dest )
422+ print (f" 💾 Copied: { file_info ['filename' ]} " )
423+ except Exception as e :
424+ print (f" ⚠ Failed to copy { file_info ['filename' ]} : { e } " )
425+ else :
426+ print (" ⚠ No full_discussion files found in previous run" )
427+ return state
388428
389429 debug = get_debug_manager (config )
390430
@@ -426,10 +466,79 @@ def run_consensus(state: WorkflowState) -> WorkflowState:
426466
427467 # Check if we should skip this phase (resume mode)
428468 resume_config = state .get ("_resume_config" , {})
429- if resume_config and resume_config .get ("reuse_stages" , {}).get ("consensus" ):
430- print (" ⏭️ Skipping (reusing from previous run)" )
431- # Consensus should already be loaded in initialize()
432- return state
469+ if resume_config :
470+ reuse_stages = resume_config .get ("reuse_stages" , {})
471+
472+ resume_run_dir = Path (resume_config ["run_dir" ])
473+ prev_run = RunInfo (resume_run_dir )
474+
475+ # If explicitly marked to reuse, load it
476+ if reuse_stages .get ("consensus" ):
477+ print (" ⏭️ Reusing consensus from previous run" )
478+ # Consensus should already be loaded in initialize()
479+ # Copy all consensus files to new directory
480+ debug = get_debug_manager (config )
481+ if debug .enabled :
482+ import shutil
483+ # Copy all consensus related files
484+ consensus_files = prev_run .get_stage_files ("consensus" )
485+ if consensus_files :
486+ for file_info in consensus_files :
487+ try :
488+ dest = debug .run_dir / file_info ["filename" ]
489+ shutil .copy2 (file_info ["path" ], dest )
490+ print (f" 💾 Copied: { file_info ['filename' ]} " )
491+ except Exception as e :
492+ print (f" ⚠ Failed to copy { file_info ['filename' ]} : { e } " )
493+ # Also save consensus data if available in state
494+ if "consensus_result" in state :
495+ consensus_result = state ["consensus_result" ]
496+ consensus_data = {
497+ "adopted" : consensus_result .adopted ,
498+ "rejected" : consensus_result .rejected ,
499+ "vote_counts" : consensus_result .vote_counts ,
500+ "threshold" : consensus_threshold ,
501+ "_reused_from" : prev_run .run_id ,
502+ }
503+ debug .save_consensus (consensus_data )
504+ return state
505+
506+ # If not in reuse list but output exists, ask user
507+ if prev_run .has_stage_output ("consensus" ) and "consensus" not in reuse_stages :
508+ from ..resume import ask_reuse_stage
509+ should_reuse = ask_reuse_stage ("consensus" , prev_run )
510+ if should_reuse :
511+ consensus_data = load_consensus_from_run (prev_run )
512+ if consensus_data :
513+ from .consensus import ConsensusResult
514+ state ["consensus_result" ] = ConsensusResult (
515+ adopted = consensus_data .get ("adopted" , []),
516+ rejected = consensus_data .get ("rejected" , []),
517+ vote_counts = consensus_data .get ("vote_counts" , {}),
518+ required_votes = 0 ,
519+ num_experts = 0 ,
520+ )
521+ print (" ✓ Loaded consensus from previous run" )
522+ # Copy all consensus files to new directory
523+ debug = get_debug_manager (config )
524+ if debug .enabled :
525+ import shutil
526+ # Copy all consensus related files
527+ consensus_files = prev_run .get_stage_files ("consensus" )
528+ if consensus_files :
529+ for file_info in consensus_files :
530+ try :
531+ dest = debug .run_dir / file_info ["filename" ]
532+ shutil .copy2 (file_info ["path" ], dest )
533+ print (f" 💾 Copied: { file_info ['filename' ]} " )
534+ except Exception as e :
535+ print (f" ⚠ Failed to copy { file_info ['filename' ]} : { e } " )
536+ # Also save consensus data
537+ consensus_data ["_reused_from" ] = prev_run .run_id
538+ debug .save_consensus (consensus_data )
539+ # Mark as reused so we don't ask again
540+ reuse_stages ["consensus" ] = True
541+ return state
433542
434543 debug = get_debug_manager (config )
435544
@@ -483,17 +592,65 @@ def run_writer(state: WorkflowState) -> WorkflowState:
483592
484593 # Check if we should reuse writer output (resume mode)
485594 resume_config = state .get ("_resume_config" , {})
486- if resume_config and resume_config . get ( "reuse_stages" , {}). get ( "writer" ) :
487- print ( " ⏭️ Reusing writer output from previous run" )
595+ if resume_config :
596+ reuse_stages = resume_config . get ( "reuse_stages" , {} )
488597 resume_run_dir = Path (resume_config ["run_dir" ])
489- writer_output = load_writer_output_from_run (RunInfo (resume_run_dir ))
490- if writer_output :
491- state ["final_markmap" ] = writer_output
492- state ["writer_outputs" ]["general_en" ] = writer_output
493- print (f" ✓ Loaded writer output ({ len (writer_output )} chars)" )
598+ prev_run = RunInfo (resume_run_dir )
599+
600+ # If explicitly marked to reuse, load it
601+ if reuse_stages .get ("writer" ):
602+ print (" ⏭️ Reusing writer from previous run" )
603+ # Copy all writer related files to new directory
604+ debug = get_debug_manager (config )
605+ if debug .enabled :
606+ import shutil
607+ # Copy all writer related files (LLM input/output, writer output)
608+ writer_files = prev_run .get_stage_files ("writer" )
609+ if writer_files :
610+ for file_info in writer_files :
611+ try :
612+ dest = debug .run_dir / file_info ["filename" ]
613+ shutil .copy2 (file_info ["path" ], dest )
614+ print (f" 💾 Copied: { file_info ['filename' ]} " )
615+ except Exception as e :
616+ print (f" ⚠ Failed to copy { file_info ['filename' ]} : { e } " )
617+ # Load writer output content for state
618+ writer_output = load_writer_output_from_run (prev_run )
619+ if writer_output :
620+ state ["final_markmap" ] = writer_output
621+ state ["writer_outputs" ]["general_en" ] = writer_output
622+ print (f" ✓ Loaded writer output ({ len (writer_output )} chars)" )
623+ else :
624+ print (" ⚠ Could not load writer output content" )
494625 return state
495- else :
496- print (" ⚠ Could not load writer output, regenerating..." )
626+
627+ # If not in reuse list but output exists, ask user
628+ elif prev_run .has_stage_output ("writer" ) and "writer" not in reuse_stages :
629+ from ..resume import ask_reuse_stage
630+ should_reuse = ask_reuse_stage ("writer" , prev_run )
631+ if should_reuse :
632+ writer_output = load_writer_output_from_run (prev_run )
633+ if writer_output :
634+ state ["final_markmap" ] = writer_output
635+ state ["writer_outputs" ]["general_en" ] = writer_output
636+ print (f" ✓ Loaded writer output ({ len (writer_output )} chars)" )
637+ # Copy all writer files to new directory
638+ debug = get_debug_manager (config )
639+ if debug .enabled :
640+ import shutil
641+ # Copy all writer related files
642+ writer_files = prev_run .get_stage_files ("writer" )
643+ if writer_files :
644+ for file_info in writer_files :
645+ try :
646+ dest = debug .run_dir / file_info ["filename" ]
647+ shutil .copy2 (file_info ["path" ], dest )
648+ print (f" 💾 Copied: { file_info ['filename' ]} " )
649+ except Exception as e :
650+ print (f" ⚠ Failed to copy { file_info ['filename' ]} : { e } " )
651+ # Mark as reused
652+ reuse_stages ["writer" ] = True
653+ return state
497654
498655 debug = get_debug_manager (config )
499656
@@ -540,6 +697,17 @@ def run_translations(state: WorkflowState) -> WorkflowState:
540697 return state
541698
542699 print ("\n [Phase 5] Translating outputs..." )
700+
701+ # Check if we should skip this phase (resume mode)
702+ resume_config = state .get ("_resume_config" , {})
703+ if resume_config :
704+ reuse_stages = resume_config .get ("reuse_stages" , {})
705+ if reuse_stages .get ("translate" ):
706+ print (" ⏭️ Skipping (reusing from previous run)" )
707+ # Translation outputs should be loaded from previous run
708+ # TODO: Load translation outputs if needed
709+ return state
710+
543711 debug = get_debug_manager (config )
544712
545713 writer_outputs = state .get ("writer_outputs" , {})
0 commit comments