videonut 1.2.8 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +272 -272
  2. package/USER_GUIDE.md +90 -90
  3. package/agents/core/eic.md +771 -771
  4. package/agents/creative/director.md +246 -246
  5. package/agents/creative/scriptwriter.md +207 -207
  6. package/agents/research/investigator.md +394 -394
  7. package/agents/technical/archivist.md +288 -288
  8. package/agents/technical/scavenger.md +247 -247
  9. package/config.yaml +61 -61
  10. package/docs/scriptwriter.md +42 -42
  11. package/file_validator.py +186 -186
  12. package/memory/short_term/asset_manifest.md +64 -64
  13. package/memory/short_term/investigation_dossier.md +31 -31
  14. package/memory/short_term/master_script.md +51 -51
  15. package/package.json +61 -64
  16. package/requirements.txt +8 -8
  17. package/tools/check_env.py +76 -76
  18. package/tools/downloaders/caption_reader.py +237 -237
  19. package/tools/downloaders/clip_grabber.py +82 -82
  20. package/tools/downloaders/image_grabber.py +105 -105
  21. package/tools/downloaders/pdf_reader.py +163 -163
  22. package/tools/downloaders/screenshotter.py +58 -58
  23. package/tools/downloaders/web_reader.py +69 -69
  24. package/tools/validators/link_checker.py +45 -45
  25. package/workflow_orchestrator.py +336 -336
  26. package/.claude/commands/archivist.toml +0 -12
  27. package/.claude/commands/director.toml +0 -12
  28. package/.claude/commands/eic.toml +0 -12
  29. package/.claude/commands/investigator.toml +0 -12
  30. package/.claude/commands/prompt.toml +0 -12
  31. package/.claude/commands/scavenger.toml +0 -12
  32. package/.claude/commands/scout.toml +0 -12
  33. package/.claude/commands/scriptwriter.toml +0 -12
  34. package/.claude/commands/seo.toml +0 -12
  35. package/.claude/commands/thumbnail.toml +0 -12
  36. package/.claude/commands/topic_scout.toml +0 -12
  37. package/.gemini/commands/archivist.toml +0 -12
  38. package/.gemini/commands/director.toml +0 -12
  39. package/.gemini/commands/eic.toml +0 -12
  40. package/.gemini/commands/investigator.toml +0 -12
  41. package/.gemini/commands/prompt.toml +0 -12
  42. package/.gemini/commands/scavenger.toml +0 -12
  43. package/.gemini/commands/scout.toml +0 -12
  44. package/.gemini/commands/scriptwriter.toml +0 -12
  45. package/.gemini/commands/seo.toml +0 -12
  46. package/.gemini/commands/thumbnail.toml +0 -12
  47. package/.gemini/commands/topic_scout.toml +0 -12
  48. package/.qwen/commands/archivist.toml +0 -12
  49. package/.qwen/commands/director.toml +0 -12
  50. package/.qwen/commands/eic.toml +0 -12
  51. package/.qwen/commands/investigator.toml +0 -12
  52. package/.qwen/commands/prompt.toml +0 -12
  53. package/.qwen/commands/scavenger.toml +0 -12
  54. package/.qwen/commands/scout.toml +0 -12
  55. package/.qwen/commands/scriptwriter.toml +0 -12
  56. package/.qwen/commands/seo.toml +0 -12
  57. package/.qwen/commands/thumbnail.toml +0 -12
  58. package/.qwen/commands/topic_scout.toml +0 -12
@@ -1,337 +1,337 @@
1
- #!/usr/bin/env python3
2
- """
3
- VideoNut Workflow Orchestrator
4
- Automates the agent workflow while maintaining manual control options
5
- """
6
- import os
7
- import sys
8
- import subprocess
9
- import argparse
10
- import json
11
- from datetime import datetime
12
- import shutil
13
-
14
- class VideoNutOrchestrator:
15
- def __init__(self, project_path):
16
- self.project_path = project_path
17
- self.checkpoint_file = os.path.join(project_path, ".workflow_checkpoint.json")
18
- self.checkpoints = self.load_checkpoints()
19
-
20
- def load_checkpoints(self):
21
- """Load workflow progress from checkpoint file"""
22
- if os.path.exists(self.checkpoint_file):
23
- with open(self.checkpoint_file, 'r') as f:
24
- return json.load(f)
25
- return {
26
- "investigation_complete": False,
27
- "scriptwriting_complete": False,
28
- "direction_complete": False,
29
- "scavenging_complete": False,
30
- "archiving_complete": False,
31
- "last_step": "none"
32
- }
33
-
34
- def save_checkpoints(self):
35
- """Save workflow progress to checkpoint file"""
36
- with open(self.checkpoint_file, 'w') as f:
37
- json.dump(self.checkpoints, f, indent=2)
38
-
39
- def run_command(self, cmd, description):
40
- """Execute a command with error handling"""
41
- print(f"\nšŸš€ {description}")
42
- print(f"Command: {cmd}")
43
-
44
- try:
45
- result = subprocess.run(
46
- cmd,
47
- shell=True,
48
- capture_output=True,
49
- text=True,
50
- cwd=self.project_path
51
- )
52
-
53
- if result.returncode == 0:
54
- print(f"āœ… {description} completed successfully")
55
- return True
56
- else:
57
- print(f"āŒ {description} failed:")
58
- print(f"STDOUT: {result.stdout}")
59
- print(f"STDERR: {result.stderr}")
60
- return False
61
-
62
- except Exception as e:
63
- print(f"āŒ Error running {description}: {str(e)}")
64
- return False
65
-
66
- def check_prerequisites(self):
67
- """Check if required files exist for each step"""
68
- files_needed = {
69
- "investigation": [],
70
- "scriptwriting": [os.path.join(self.project_path, "truth_dossier.md")],
71
- "direction": [os.path.join(self.project_path, "narrative_script.md")],
72
- "scavenging": [os.path.join(self.project_path, "master_script.md")],
73
- "archiving": [os.path.join(self.project_path, "asset_manifest.md")]
74
- }
75
-
76
- for step, required_files in files_needed.items():
77
- for file_path in required_files:
78
- if not os.path.exists(file_path):
79
- print(f"āŒ Prerequisite missing for {step}: {file_path}")
80
- return False
81
- return True
82
-
83
- def run_investigation(self):
84
- """Run investigation phase"""
85
- if self.checkpoints["investigation_complete"]:
86
- print("ā­ļø Investigation already completed, skipping...")
87
- return True
88
-
89
- print("\nšŸ” Starting Investigation Phase...")
90
- # This would typically require user input, so we'll note this step
91
- print("Please run: /investigator and complete the investigation")
92
- print("When complete, mark investigation as done by creating truth_dossier.md")
93
-
94
- # For automation, we'd need to implement the actual investigator call
95
- # For now, we'll just check if the output file exists
96
- dossier_path = os.path.join(self.project_path, "truth_dossier.md")
97
- if os.path.exists(dossier_path):
98
- self.checkpoints["investigation_complete"] = True
99
- self.checkpoints["last_step"] = "investigation"
100
- self.save_checkpoints()
101
- print("āœ… Investigation step marked as complete")
102
- return True
103
- else:
104
- print("āŒ Investigation output not found. Please complete investigation manually.")
105
- return False
106
-
107
- def run_scriptwriting(self):
108
- """Run scriptwriting phase"""
109
- if self.checkpoints["scriptwriting_complete"]:
110
- print("ā­ļø Scriptwriting already completed, skipping...")
111
- return True
112
-
113
- print("\nāœļø Starting Scriptwriting Phase...")
114
-
115
- # Check if prerequisite exists
116
- dossier_path = os.path.join(self.project_path, "truth_dossier.md")
117
- if not os.path.exists(dossier_path):
118
- print("āŒ Prerequisite file missing: truth_dossier.md")
119
- return False
120
-
121
- # Run the scriptwriter
122
- cmd = f'python -c "import sys; sys.path.append(\'..\'); from tools.downloaders.caption_reader import *; exec(open(\'agents/creative/scriptwriter.md\').read())" 2>/dev/null || echo "Scriptwriter needs manual execution"'
123
- # More realistic approach - just check if output exists
124
- script_path = os.path.join(self.project_path, "narrative_script.md")
125
-
126
- if os.path.exists(script_path):
127
- self.checkpoints["scriptwriting_complete"] = True
128
- self.checkpoints["last_step"] = "scriptwriting"
129
- self.save_checkpoints()
130
- print("āœ… Scriptwriting step marked as complete")
131
- return True
132
- else:
133
- print("āŒ Narrative script not found. Please run scriptwriter manually.")
134
- return False
135
-
136
- def run_direction(self):
137
- """Run direction phase"""
138
- if self.checkpoints["direction_complete"]:
139
- print("ā­ļø Direction already completed, skipping...")
140
- return True
141
-
142
- print("\nšŸŽ¬ Starting Direction Phase...")
143
-
144
- # Check if prerequisite exists
145
- script_path = os.path.join(self.project_path, "narrative_script.md")
146
- if not os.path.exists(script_path):
147
- print("āŒ Prerequisite file missing: narrative_script.md")
148
- return False
149
-
150
- # Check for output
151
- master_script_path = os.path.join(self.project_path, "master_script.md")
152
- if os.path.exists(master_script_path):
153
- self.checkpoints["direction_complete"] = True
154
- self.checkpoints["last_step"] = "direction"
155
- self.save_checkpoints()
156
- print("āœ… Direction step marked as complete")
157
- return True
158
- else:
159
- print("āŒ Master script not found. Please run director manually.")
160
- return False
161
-
162
- def run_scavenging(self):
163
- """Run scavenging phase"""
164
- if self.checkpoints["scavenging_complete"]:
165
- print("ā­ļø Scavenging already completed, skipping...")
166
- return True
167
-
168
- print("\nšŸ¦… Starting Scavenging Phase...")
169
-
170
- # Check if prerequisite exists
171
- master_script_path = os.path.join(self.project_path, "master_script.md")
172
- if not os.path.exists(master_script_path):
173
- print("āŒ Prerequisite file missing: master_script.md")
174
- return False
175
-
176
- # Check for output
177
- manifest_path = os.path.join(self.project_path, "asset_manifest.md")
178
- if os.path.exists(manifest_path):
179
- self.checkpoints["scavenging_complete"] = True
180
- self.checkpoints["last_step"] = "scavenging"
181
- self.save_checkpoints()
182
- print("āœ… Scavenging step marked as complete")
183
- return True
184
- else:
185
- print("āŒ Asset manifest not found. Please run scavenger manually.")
186
- return False
187
-
188
- def run_archiving(self):
189
- """Run archiving phase"""
190
- if self.checkpoints["archiving_complete"]:
191
- print("ā­ļø Archiving already completed, skipping...")
192
- return True
193
-
194
- print("\nšŸ’¾ Starting Archiving Phase...")
195
-
196
- # Check if prerequisite exists
197
- manifest_path = os.path.join(self.project_path, "asset_manifest.md")
198
- if not os.path.exists(manifest_path):
199
- print("āŒ Prerequisite file missing: asset_manifest.md")
200
- return False
201
-
202
- # Run archivist
203
- cmd = f'python -c "import sys; sys.path.append(\'..\'); exec(open(\'agents/technical/archivist.md\').read())" 2>/dev/null || echo "Archivist needs manual execution"'
204
-
205
- # Check for output directory
206
- assets_path = os.path.join(self.project_path, "assets")
207
- if os.path.exists(assets_path):
208
- self.checkpoints["archiving_complete"] = True
209
- self.checkpoints["last_step"] = "archiving"
210
- self.save_checkpoints()
211
- print("āœ… Archiving step marked as complete")
212
- return True
213
- else:
214
- print("āŒ Assets directory not found. Please run archivist manually.")
215
- return False
216
-
217
- def run_full_workflow(self):
218
- """Run the complete VideoNut workflow"""
219
- print("šŸŽ¬ Starting VideoNut Video Production Workflow")
220
- print(f"Project Path: {self.project_path}")
221
- print(f"Last completed step: {self.checkpoints['last_step']}")
222
-
223
- steps = [
224
- ("Investigation", self.run_investigation),
225
- ("Scriptwriting", self.run_scriptwriting),
226
- ("Direction", self.run_direction),
227
- ("Scavenging", self.run_scavenging),
228
- ("Archiving", self.run_archiving)
229
- ]
230
-
231
- for step_name, step_func in steps:
232
- print(f"\n--- {step_name.upper()} PHASE ---")
233
- if not step_func():
234
- print(f"āŒ {step_name} phase failed. Workflow stopped.")
235
- return False
236
-
237
- print("\nšŸŽ‰ All workflow phases completed successfully!")
238
- print("Your video assets are ready for editing!")
239
- return True
240
-
241
- def main():
242
- parser = argparse.ArgumentParser(description="VideoNut Workflow Orchestrator")
243
- parser.add_argument("--project", required=True, help="Path to project directory")
244
- parser.add_argument("--resume", action="store_true", help="Resume from last checkpoint")
245
- parser.add_argument("--status", action="store_true", help="Show current workflow status")
246
- parser.add_argument("--next", action="store_true", help="Show what to do next")
247
-
248
- args = parser.parse_args()
249
-
250
- if not os.path.exists(args.project):
251
- print(f"āŒ Project directory does not exist: {args.project}")
252
- sys.exit(1)
253
-
254
- orchestrator = VideoNutOrchestrator(args.project)
255
-
256
- # Status command - show current progress
257
- if args.status:
258
- print("šŸ“Š VideoNut Workflow Status")
259
- print("=" * 50)
260
- print(f"Project: {args.project}")
261
- print(f"Last step: {orchestrator.checkpoints['last_step']}")
262
- print()
263
-
264
- status_icons = {True: "āœ…", False: "ā³"}
265
- steps = [
266
- ("Investigation", "investigation_complete", "truth_dossier.md"),
267
- ("Scriptwriting", "scriptwriting_complete", "narrative_script.md"),
268
- ("Direction", "direction_complete", "master_script.md"),
269
- ("Scavenging", "scavenging_complete", "asset_manifest.md"),
270
- ("Archiving", "archiving_complete", "assets/"),
271
- ]
272
-
273
- for step_name, checkpoint_key, output_file in steps:
274
- is_complete = orchestrator.checkpoints[checkpoint_key]
275
- icon = status_icons[is_complete]
276
- status = "Complete" if is_complete else "Pending"
277
- print(f" {icon} {step_name}: {status} → {output_file}")
278
-
279
- print()
280
- sys.exit(0)
281
-
282
- # Next command - show what to do next
283
- if args.next:
284
- print("šŸŽÆ What to Do Next")
285
- print("=" * 50)
286
-
287
- next_steps = {
288
- "none": ("Investigation", "/investigator", "Create truth_dossier.md with research findings"),
289
- "investigation": ("Scriptwriting", "/scriptwriter", "Create narrative_script.md from the dossier"),
290
- "scriptwriting": ("Direction", "/director", "Create master_script.md with visual directions"),
291
- "direction": ("Scavenging", "/scavenger", "Create asset_manifest.md with URLs"),
292
- "scavenging": ("Archiving", "/archivist", "Download all assets to assets/ folder"),
293
- "archiving": ("Complete", None, "šŸŽ‰ All done! Your video assets are ready for editing."),
294
- }
295
-
296
- last_step = orchestrator.checkpoints['last_step']
297
- step_name, command, description = next_steps.get(last_step, next_steps["none"])
298
-
299
- print(f"šŸ“ Current position: After '{last_step}'")
300
- print(f"šŸ‘‰ Next step: {step_name}")
301
- if command:
302
- print(f"šŸ”§ Command: {command}")
303
- print(f"šŸ“ What to do: {description}")
304
- print()
305
-
306
- # Check for missing files
307
- expected_files = {
308
- "none": [],
309
- "investigation": [("truth_dossier.md", "Run /investigator to create this file")],
310
- "scriptwriting": [("narrative_script.md", "Run /scriptwriter to create this file")],
311
- "direction": [("master_script.md", "Run /director to create this file")],
312
- "scavenging": [("asset_manifest.md", "Run /scavenger to create this file")],
313
- }
314
-
315
- for filename, hint in expected_files.get(last_step, []):
316
- filepath = os.path.join(args.project, filename)
317
- if not os.path.exists(filepath):
318
- print(f"āš ļø Missing: {filename}")
319
- print(f" Fix: {hint}")
320
-
321
- sys.exit(0)
322
-
323
- if args.resume:
324
- print("šŸ”„ Resuming workflow from last checkpoint...")
325
-
326
- success = orchestrator.run_full_workflow()
327
-
328
- if success:
329
- print(f"\nāœ… Workflow completed! Checkpoint file: {orchestrator.checkpoint_file}")
330
- else:
331
- print(f"\nāŒ Workflow failed. Checkpoint file: {orchestrator.checkpoint_file}")
332
- print("\nšŸ’” TIP: Run with --next to see what to do next")
333
- print("šŸ’” TIP: Run with --status to see full progress")
334
- sys.exit(1)
335
-
336
- if __name__ == "__main__":
1
+ #!/usr/bin/env python3
2
+ """
3
+ VideoNut Workflow Orchestrator
4
+ Automates the agent workflow while maintaining manual control options
5
+ """
6
+ import os
7
+ import sys
8
+ import subprocess
9
+ import argparse
10
+ import json
11
+ from datetime import datetime
12
+ import shutil
13
+
14
+ class VideoNutOrchestrator:
15
+ def __init__(self, project_path):
16
+ self.project_path = project_path
17
+ self.checkpoint_file = os.path.join(project_path, ".workflow_checkpoint.json")
18
+ self.checkpoints = self.load_checkpoints()
19
+
20
+ def load_checkpoints(self):
21
+ """Load workflow progress from checkpoint file"""
22
+ if os.path.exists(self.checkpoint_file):
23
+ with open(self.checkpoint_file, 'r') as f:
24
+ return json.load(f)
25
+ return {
26
+ "investigation_complete": False,
27
+ "scriptwriting_complete": False,
28
+ "direction_complete": False,
29
+ "scavenging_complete": False,
30
+ "archiving_complete": False,
31
+ "last_step": "none"
32
+ }
33
+
34
+ def save_checkpoints(self):
35
+ """Save workflow progress to checkpoint file"""
36
+ with open(self.checkpoint_file, 'w') as f:
37
+ json.dump(self.checkpoints, f, indent=2)
38
+
39
+ def run_command(self, cmd, description):
40
+ """Execute a command with error handling"""
41
+ print(f"\nšŸš€ {description}")
42
+ print(f"Command: {cmd}")
43
+
44
+ try:
45
+ result = subprocess.run(
46
+ cmd,
47
+ shell=True,
48
+ capture_output=True,
49
+ text=True,
50
+ cwd=self.project_path
51
+ )
52
+
53
+ if result.returncode == 0:
54
+ print(f"āœ… {description} completed successfully")
55
+ return True
56
+ else:
57
+ print(f"āŒ {description} failed:")
58
+ print(f"STDOUT: {result.stdout}")
59
+ print(f"STDERR: {result.stderr}")
60
+ return False
61
+
62
+ except Exception as e:
63
+ print(f"āŒ Error running {description}: {str(e)}")
64
+ return False
65
+
66
+ def check_prerequisites(self):
67
+ """Check if required files exist for each step"""
68
+ files_needed = {
69
+ "investigation": [],
70
+ "scriptwriting": [os.path.join(self.project_path, "truth_dossier.md")],
71
+ "direction": [os.path.join(self.project_path, "narrative_script.md")],
72
+ "scavenging": [os.path.join(self.project_path, "master_script.md")],
73
+ "archiving": [os.path.join(self.project_path, "asset_manifest.md")]
74
+ }
75
+
76
+ for step, required_files in files_needed.items():
77
+ for file_path in required_files:
78
+ if not os.path.exists(file_path):
79
+ print(f"āŒ Prerequisite missing for {step}: {file_path}")
80
+ return False
81
+ return True
82
+
83
+ def run_investigation(self):
84
+ """Run investigation phase"""
85
+ if self.checkpoints["investigation_complete"]:
86
+ print("ā­ļø Investigation already completed, skipping...")
87
+ return True
88
+
89
+ print("\nšŸ” Starting Investigation Phase...")
90
+ # This would typically require user input, so we'll note this step
91
+ print("Please run: /investigator and complete the investigation")
92
+ print("When complete, mark investigation as done by creating truth_dossier.md")
93
+
94
+ # For automation, we'd need to implement the actual investigator call
95
+ # For now, we'll just check if the output file exists
96
+ dossier_path = os.path.join(self.project_path, "truth_dossier.md")
97
+ if os.path.exists(dossier_path):
98
+ self.checkpoints["investigation_complete"] = True
99
+ self.checkpoints["last_step"] = "investigation"
100
+ self.save_checkpoints()
101
+ print("āœ… Investigation step marked as complete")
102
+ return True
103
+ else:
104
+ print("āŒ Investigation output not found. Please complete investigation manually.")
105
+ return False
106
+
107
+ def run_scriptwriting(self):
108
+ """Run scriptwriting phase"""
109
+ if self.checkpoints["scriptwriting_complete"]:
110
+ print("ā­ļø Scriptwriting already completed, skipping...")
111
+ return True
112
+
113
+ print("\nāœļø Starting Scriptwriting Phase...")
114
+
115
+ # Check if prerequisite exists
116
+ dossier_path = os.path.join(self.project_path, "truth_dossier.md")
117
+ if not os.path.exists(dossier_path):
118
+ print("āŒ Prerequisite file missing: truth_dossier.md")
119
+ return False
120
+
121
+ # Run the scriptwriter
122
+ cmd = f'python -c "import sys; sys.path.append(\'..\'); from tools.downloaders.caption_reader import *; exec(open(\'agents/creative/scriptwriter.md\').read())" 2>/dev/null || echo "Scriptwriter needs manual execution"'
123
+ # More realistic approach - just check if output exists
124
+ script_path = os.path.join(self.project_path, "narrative_script.md")
125
+
126
+ if os.path.exists(script_path):
127
+ self.checkpoints["scriptwriting_complete"] = True
128
+ self.checkpoints["last_step"] = "scriptwriting"
129
+ self.save_checkpoints()
130
+ print("āœ… Scriptwriting step marked as complete")
131
+ return True
132
+ else:
133
+ print("āŒ Narrative script not found. Please run scriptwriter manually.")
134
+ return False
135
+
136
+ def run_direction(self):
137
+ """Run direction phase"""
138
+ if self.checkpoints["direction_complete"]:
139
+ print("ā­ļø Direction already completed, skipping...")
140
+ return True
141
+
142
+ print("\nšŸŽ¬ Starting Direction Phase...")
143
+
144
+ # Check if prerequisite exists
145
+ script_path = os.path.join(self.project_path, "narrative_script.md")
146
+ if not os.path.exists(script_path):
147
+ print("āŒ Prerequisite file missing: narrative_script.md")
148
+ return False
149
+
150
+ # Check for output
151
+ master_script_path = os.path.join(self.project_path, "master_script.md")
152
+ if os.path.exists(master_script_path):
153
+ self.checkpoints["direction_complete"] = True
154
+ self.checkpoints["last_step"] = "direction"
155
+ self.save_checkpoints()
156
+ print("āœ… Direction step marked as complete")
157
+ return True
158
+ else:
159
+ print("āŒ Master script not found. Please run director manually.")
160
+ return False
161
+
162
+ def run_scavenging(self):
163
+ """Run scavenging phase"""
164
+ if self.checkpoints["scavenging_complete"]:
165
+ print("ā­ļø Scavenging already completed, skipping...")
166
+ return True
167
+
168
+ print("\nšŸ¦… Starting Scavenging Phase...")
169
+
170
+ # Check if prerequisite exists
171
+ master_script_path = os.path.join(self.project_path, "master_script.md")
172
+ if not os.path.exists(master_script_path):
173
+ print("āŒ Prerequisite file missing: master_script.md")
174
+ return False
175
+
176
+ # Check for output
177
+ manifest_path = os.path.join(self.project_path, "asset_manifest.md")
178
+ if os.path.exists(manifest_path):
179
+ self.checkpoints["scavenging_complete"] = True
180
+ self.checkpoints["last_step"] = "scavenging"
181
+ self.save_checkpoints()
182
+ print("āœ… Scavenging step marked as complete")
183
+ return True
184
+ else:
185
+ print("āŒ Asset manifest not found. Please run scavenger manually.")
186
+ return False
187
+
188
+ def run_archiving(self):
189
+ """Run archiving phase"""
190
+ if self.checkpoints["archiving_complete"]:
191
+ print("ā­ļø Archiving already completed, skipping...")
192
+ return True
193
+
194
+ print("\nšŸ’¾ Starting Archiving Phase...")
195
+
196
+ # Check if prerequisite exists
197
+ manifest_path = os.path.join(self.project_path, "asset_manifest.md")
198
+ if not os.path.exists(manifest_path):
199
+ print("āŒ Prerequisite file missing: asset_manifest.md")
200
+ return False
201
+
202
+ # Run archivist
203
+ cmd = f'python -c "import sys; sys.path.append(\'..\'); exec(open(\'agents/technical/archivist.md\').read())" 2>/dev/null || echo "Archivist needs manual execution"'
204
+
205
+ # Check for output directory
206
+ assets_path = os.path.join(self.project_path, "assets")
207
+ if os.path.exists(assets_path):
208
+ self.checkpoints["archiving_complete"] = True
209
+ self.checkpoints["last_step"] = "archiving"
210
+ self.save_checkpoints()
211
+ print("āœ… Archiving step marked as complete")
212
+ return True
213
+ else:
214
+ print("āŒ Assets directory not found. Please run archivist manually.")
215
+ return False
216
+
217
+ def run_full_workflow(self):
218
+ """Run the complete VideoNut workflow"""
219
+ print("šŸŽ¬ Starting VideoNut Video Production Workflow")
220
+ print(f"Project Path: {self.project_path}")
221
+ print(f"Last completed step: {self.checkpoints['last_step']}")
222
+
223
+ steps = [
224
+ ("Investigation", self.run_investigation),
225
+ ("Scriptwriting", self.run_scriptwriting),
226
+ ("Direction", self.run_direction),
227
+ ("Scavenging", self.run_scavenging),
228
+ ("Archiving", self.run_archiving)
229
+ ]
230
+
231
+ for step_name, step_func in steps:
232
+ print(f"\n--- {step_name.upper()} PHASE ---")
233
+ if not step_func():
234
+ print(f"āŒ {step_name} phase failed. Workflow stopped.")
235
+ return False
236
+
237
+ print("\nšŸŽ‰ All workflow phases completed successfully!")
238
+ print("Your video assets are ready for editing!")
239
+ return True
240
+
241
+ def main():
242
+ parser = argparse.ArgumentParser(description="VideoNut Workflow Orchestrator")
243
+ parser.add_argument("--project", required=True, help="Path to project directory")
244
+ parser.add_argument("--resume", action="store_true", help="Resume from last checkpoint")
245
+ parser.add_argument("--status", action="store_true", help="Show current workflow status")
246
+ parser.add_argument("--next", action="store_true", help="Show what to do next")
247
+
248
+ args = parser.parse_args()
249
+
250
+ if not os.path.exists(args.project):
251
+ print(f"āŒ Project directory does not exist: {args.project}")
252
+ sys.exit(1)
253
+
254
+ orchestrator = VideoNutOrchestrator(args.project)
255
+
256
+ # Status command - show current progress
257
+ if args.status:
258
+ print("šŸ“Š VideoNut Workflow Status")
259
+ print("=" * 50)
260
+ print(f"Project: {args.project}")
261
+ print(f"Last step: {orchestrator.checkpoints['last_step']}")
262
+ print()
263
+
264
+ status_icons = {True: "āœ…", False: "ā³"}
265
+ steps = [
266
+ ("Investigation", "investigation_complete", "truth_dossier.md"),
267
+ ("Scriptwriting", "scriptwriting_complete", "narrative_script.md"),
268
+ ("Direction", "direction_complete", "master_script.md"),
269
+ ("Scavenging", "scavenging_complete", "asset_manifest.md"),
270
+ ("Archiving", "archiving_complete", "assets/"),
271
+ ]
272
+
273
+ for step_name, checkpoint_key, output_file in steps:
274
+ is_complete = orchestrator.checkpoints[checkpoint_key]
275
+ icon = status_icons[is_complete]
276
+ status = "Complete" if is_complete else "Pending"
277
+ print(f" {icon} {step_name}: {status} → {output_file}")
278
+
279
+ print()
280
+ sys.exit(0)
281
+
282
+ # Next command - show what to do next
283
+ if args.next:
284
+ print("šŸŽÆ What to Do Next")
285
+ print("=" * 50)
286
+
287
+ next_steps = {
288
+ "none": ("Investigation", "/investigator", "Create truth_dossier.md with research findings"),
289
+ "investigation": ("Scriptwriting", "/scriptwriter", "Create narrative_script.md from the dossier"),
290
+ "scriptwriting": ("Direction", "/director", "Create master_script.md with visual directions"),
291
+ "direction": ("Scavenging", "/scavenger", "Create asset_manifest.md with URLs"),
292
+ "scavenging": ("Archiving", "/archivist", "Download all assets to assets/ folder"),
293
+ "archiving": ("Complete", None, "šŸŽ‰ All done! Your video assets are ready for editing."),
294
+ }
295
+
296
+ last_step = orchestrator.checkpoints['last_step']
297
+ step_name, command, description = next_steps.get(last_step, next_steps["none"])
298
+
299
+ print(f"šŸ“ Current position: After '{last_step}'")
300
+ print(f"šŸ‘‰ Next step: {step_name}")
301
+ if command:
302
+ print(f"šŸ”§ Command: {command}")
303
+ print(f"šŸ“ What to do: {description}")
304
+ print()
305
+
306
+ # Check for missing files
307
+ expected_files = {
308
+ "none": [],
309
+ "investigation": [("truth_dossier.md", "Run /investigator to create this file")],
310
+ "scriptwriting": [("narrative_script.md", "Run /scriptwriter to create this file")],
311
+ "direction": [("master_script.md", "Run /director to create this file")],
312
+ "scavenging": [("asset_manifest.md", "Run /scavenger to create this file")],
313
+ }
314
+
315
+ for filename, hint in expected_files.get(last_step, []):
316
+ filepath = os.path.join(args.project, filename)
317
+ if not os.path.exists(filepath):
318
+ print(f"āš ļø Missing: {filename}")
319
+ print(f" Fix: {hint}")
320
+
321
+ sys.exit(0)
322
+
323
+ if args.resume:
324
+ print("šŸ”„ Resuming workflow from last checkpoint...")
325
+
326
+ success = orchestrator.run_full_workflow()
327
+
328
+ if success:
329
+ print(f"\nāœ… Workflow completed! Checkpoint file: {orchestrator.checkpoint_file}")
330
+ else:
331
+ print(f"\nāŒ Workflow failed. Checkpoint file: {orchestrator.checkpoint_file}")
332
+ print("\nšŸ’” TIP: Run with --next to see what to do next")
333
+ print("šŸ’” TIP: Run with --status to see full progress")
334
+ sys.exit(1)
335
+
336
+ if __name__ == "__main__":
337
337
  main()