appydave-tools 0.16.0 → 0.17.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/AGENTS.md +22 -0
  4. data/CHANGELOG.md +12 -0
  5. data/CLAUDE.md +206 -51
  6. data/README.md +144 -11
  7. data/bin/archive_project.rb +249 -0
  8. data/bin/configuration.rb +21 -1
  9. data/bin/generate_manifest.rb +357 -0
  10. data/bin/sync_from_ssd.rb +236 -0
  11. data/bin/vat +623 -0
  12. data/docs/README.md +169 -0
  13. data/docs/configuration/.env.example +19 -0
  14. data/docs/configuration/README.md +394 -0
  15. data/docs/configuration/channels.example.json +26 -0
  16. data/docs/configuration/settings.example.json +6 -0
  17. data/docs/development/CODEX-recommendations.md +123 -0
  18. data/docs/development/README.md +100 -0
  19. data/docs/development/cli-architecture-patterns.md +1604 -0
  20. data/docs/development/pattern-comparison.md +284 -0
  21. data/docs/prd-unified-brands-configuration.md +792 -0
  22. data/docs/project-brand-systems-analysis.md +934 -0
  23. data/docs/vat/dam-vision.md +123 -0
  24. data/docs/vat/session-summary-2025-11-09.md +297 -0
  25. data/docs/vat/usage.md +508 -0
  26. data/docs/vat/vat-testing-plan.md +801 -0
  27. data/lib/appydave/tools/configuration/models/brands_config.rb +238 -0
  28. data/lib/appydave/tools/configuration/models/config_base.rb +7 -0
  29. data/lib/appydave/tools/configuration/models/settings_config.rb +4 -0
  30. data/lib/appydave/tools/vat/config.rb +153 -0
  31. data/lib/appydave/tools/vat/config_loader.rb +91 -0
  32. data/lib/appydave/tools/vat/manifest_generator.rb +239 -0
  33. data/lib/appydave/tools/vat/project_listing.rb +198 -0
  34. data/lib/appydave/tools/vat/project_resolver.rb +132 -0
  35. data/lib/appydave/tools/vat/s3_operations.rb +560 -0
  36. data/lib/appydave/tools/version.rb +1 -1
  37. data/lib/appydave/tools.rb +9 -1
  38. data/package.json +1 -1
  39. metadata +57 -3
  40. data/docs/dam/overview.md +0 -28
data/bin/vat ADDED
@@ -0,0 +1,623 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'optparse'
5
+
6
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
7
+
8
+ require 'appydave/tools'
9
+
10
+ # VAT (Video Asset Tools) - CLI for video project management
11
+ class VatCLI
12
+ def initialize
13
+ @commands = {
14
+ 'help' => method(:help_command),
15
+ 'list' => method(:list_command),
16
+ 's3-up' => method(:s3_up_command),
17
+ 's3-down' => method(:s3_down_command),
18
+ 's3-status' => method(:s3_status_command),
19
+ 's3-cleanup-remote' => method(:s3_cleanup_remote_command),
20
+ 's3-cleanup-local' => method(:s3_cleanup_local_command),
21
+ 'archive' => method(:archive_command),
22
+ 'manifest' => method(:manifest_command),
23
+ # Deprecated aliases (for backward compatibility)
24
+ 's3-cleanup' => method(:s3_cleanup_remote_command),
25
+ 'cleanup-local' => method(:s3_cleanup_local_command)
26
+ }
27
+ end
28
+
29
+ def run
30
+ command, *args = ARGV
31
+
32
+ if command.nil?
33
+ puts 'VAT - Video Asset Tools'
34
+ puts 'Usage: vat [command] [options]'
35
+ puts "Run 'vat help' for more information."
36
+ exit
37
+ end
38
+
39
+ if @commands.key?(command)
40
+ @commands[command].call(args)
41
+ else
42
+ puts "Unknown command: #{command}"
43
+ puts "Run 'vat help' for available commands."
44
+ exit 1
45
+ end
46
+ end
47
+
48
+ private
49
+
50
+ # Show help information
51
+ # rubocop:disable Metrics/CyclomaticComplexity
52
+ def help_command(args)
53
+ topic = args[0]
54
+
55
+ case topic
56
+ when 'brands'
57
+ show_brands_help
58
+ when 'workflows'
59
+ show_workflows_help
60
+ when 'config'
61
+ show_config_help
62
+ when 'list'
63
+ show_list_help
64
+ when 's3-up', 's3-down', 's3-status', 's3-cleanup-remote', 's3-cleanup-local', 'archive', 'manifest'
65
+ show_s3_help(topic)
66
+ when 's3-cleanup', 'cleanup-local'
67
+ # Deprecated command names - show deprecation notice and new help
68
+ puts "⚠️ '#{topic}' is deprecated. Use the new command name instead:\n\n"
69
+ new_name = topic == 's3-cleanup' ? 's3-cleanup-remote' : 's3-cleanup-local'
70
+ show_s3_help(new_name)
71
+ else
72
+ show_main_help
73
+ end
74
+ end
75
+ # rubocop:enable Metrics/CyclomaticComplexity
76
+
77
+ # List brands and projects
78
+ def list_command(args)
79
+ args = args.reject { |arg| arg.start_with?('--') || arg.start_with?('-') }
80
+
81
+ brand_arg = args[0]
82
+ pattern_arg = args[1]
83
+
84
+ if brand_arg.nil?
85
+ # List all brands with summary
86
+ Appydave::Tools::Vat::ProjectListing.list_brands_with_counts
87
+ elsif pattern_arg
88
+ # Pattern matching
89
+ Appydave::Tools::Vat::ProjectListing.list_with_pattern(brand_arg, pattern_arg)
90
+ else
91
+ # Specific brand
92
+ Appydave::Tools::Vat::ProjectListing.list_brand_projects(brand_arg)
93
+ end
94
+ rescue StandardError => e
95
+ puts "❌ Error: #{e.message}"
96
+ exit 1
97
+ end
98
+
99
+ # S3 Upload
100
+ def s3_up_command(args)
101
+ options = parse_s3_args(args, 's3-up')
102
+ s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
103
+ s3_ops.upload(dry_run: options[:dry_run])
104
+ rescue StandardError => e
105
+ puts "❌ Error: #{e.message}"
106
+ exit 1
107
+ end
108
+
109
+ # S3 Download
110
+ def s3_down_command(args)
111
+ options = parse_s3_args(args, 's3-down')
112
+ s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
113
+ s3_ops.download(dry_run: options[:dry_run])
114
+ rescue StandardError => e
115
+ puts "❌ Error: #{e.message}"
116
+ exit 1
117
+ end
118
+
119
+ # S3 Status
120
+ def s3_status_command(args)
121
+ options = parse_s3_args(args, 's3-status')
122
+ s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
123
+ s3_ops.status
124
+ rescue StandardError => e
125
+ puts "❌ Error: #{e.message}"
126
+ exit 1
127
+ end
128
+
129
+ # S3 Cleanup Remote
130
+ def s3_cleanup_remote_command(args)
131
+ options = parse_s3_args(args, 's3-cleanup-remote')
132
+ s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
133
+ s3_ops.cleanup(force: options[:force], dry_run: options[:dry_run])
134
+ rescue StandardError => e
135
+ puts "❌ Error: #{e.message}"
136
+ exit 1
137
+ end
138
+
139
+ # S3 Cleanup Local
140
+ def s3_cleanup_local_command(args)
141
+ options = parse_s3_args(args, 's3-cleanup-local')
142
+ s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
143
+ s3_ops.cleanup_local(force: options[:force], dry_run: options[:dry_run])
144
+ rescue StandardError => e
145
+ puts "❌ Error: #{e.message}"
146
+ exit 1
147
+ end
148
+
149
+ # Archive project to SSD
150
+ def archive_command(args)
151
+ options = parse_s3_args(args, 'archive')
152
+ s3_ops = Appydave::Tools::Vat::S3Operations.new(options[:brand], options[:project])
153
+ s3_ops.archive(force: options[:force], dry_run: options[:dry_run])
154
+ rescue StandardError => e
155
+ puts "❌ Error: #{e.message}"
156
+ exit 1
157
+ end
158
+
159
+ # Generate manifest
160
+ # rubocop:disable Metrics/MethodLength
161
+ def manifest_command(args)
162
+ all_brands = args.include?('--all')
163
+ args = args.reject { |arg| arg.start_with?('--') }
164
+ brand_arg = args[0]
165
+
166
+ if all_brands
167
+ # Generate manifest for all brands
168
+ Appydave::Tools::Configuration::Config.configure
169
+ brands_config = Appydave::Tools::Configuration::Config.brands
170
+
171
+ brands_config.brands.each do |brand_info|
172
+ brand_key = brand_info.key
173
+ puts ''
174
+ puts '=' * 60
175
+
176
+ generator = Appydave::Tools::Vat::ManifestGenerator.new(brand_key)
177
+ generator.generate
178
+ end
179
+
180
+ puts ''
181
+ puts '=' * 60
182
+ puts '✅ All brand manifests generated!'
183
+ elsif brand_arg
184
+ # Generate manifest for specific brand
185
+ brand = Appydave::Tools::Vat::Config.expand_brand(brand_arg)
186
+ ENV['BRAND_PATH'] = Appydave::Tools::Vat::Config.brand_path(brand)
187
+
188
+ generator = Appydave::Tools::Vat::ManifestGenerator.new(brand_arg)
189
+ generator.generate
190
+ else
191
+ puts 'Usage: vat manifest <brand> [--all]'
192
+ puts ''
193
+ puts 'Examples:'
194
+ puts ' vat manifest appydave # Generate manifest for AppyDave brand'
195
+ puts ' vat manifest --all # Generate manifests for all brands'
196
+ exit 1
197
+ end
198
+ rescue StandardError => e
199
+ puts "❌ Error: #{e.message}"
200
+ exit 1
201
+ end
202
+ # rubocop:enable Metrics/MethodLength
203
+
204
+ # Parse S3 command arguments
205
+ def parse_s3_args(args, command)
206
+ dry_run = args.include?('--dry-run')
207
+ force = args.include?('--force')
208
+ args = args.reject { |arg| arg.start_with?('--') }
209
+
210
+ brand_arg = args[0]
211
+ project_arg = args[1]
212
+
213
+ if brand_arg.nil?
214
+ # Auto-detect from PWD
215
+ brand, project_id = Appydave::Tools::Vat::ProjectResolver.detect_from_pwd
216
+ if brand.nil? || project_id.nil?
217
+ puts '❌ Could not auto-detect brand/project from current directory'
218
+ puts "Usage: vat #{command} <brand> <project> [--dry-run]"
219
+ exit 1
220
+ end
221
+ brand_key = brand # Already detected, use as-is
222
+ else
223
+ brand_key = brand_arg # Use the shortcut/key (e.g., 'appydave')
224
+ brand = Appydave::Tools::Vat::Config.expand_brand(brand_arg) # Expand for path resolution
225
+ project_id = Appydave::Tools::Vat::ProjectResolver.resolve(brand_arg, project_arg)
226
+ end
227
+
228
+ # Set ENV for compatibility with ConfigLoader
229
+ ENV['BRAND_PATH'] = Appydave::Tools::Vat::Config.brand_path(brand)
230
+
231
+ { brand: brand_key, project: project_id, dry_run: dry_run, force: force }
232
+ end
233
+
234
+ # Help text methods
235
+ # rubocop:disable Metrics/MethodLength
236
+ def show_main_help
237
+ puts <<~HELP
238
+ VAT (Video Asset Tools) - Unified CLI for video project management
239
+
240
+ Usage: vat [command] [options]
241
+
242
+ Available Commands:
243
+ help [command] Show help information
244
+ list [brand] [pattern] List brands/projects
245
+
246
+ S3 Sync Commands:
247
+ s3-up <brand> <project> Upload to S3 staging
248
+ s3-down <brand> <project> Download from S3 staging
249
+ s3-status <brand> [project] Check sync status
250
+ s3-cleanup-remote <brand> <project> Delete S3 files
251
+ s3-cleanup-local <brand> <project> Delete local s3-staging files
252
+
253
+ Archive Commands:
254
+ archive <brand> <project> Copy project to SSD backup
255
+ manifest <brand> [--all] Generate project manifest
256
+
257
+ List Modes:
258
+ vat list All brands with counts/sizes
259
+ vat list appydave All projects for brand
260
+ vat list appydave 'b6*' Pattern matching
261
+
262
+ Help Topics:
263
+ vat help brands List available brands
264
+ vat help workflows Explain FliVideo vs Storyline workflows
265
+ vat help config Configuration file details
266
+
267
+ Examples:
268
+ vat list
269
+ vat s3-up appydave b65
270
+ vat s3-down voz boy-baker --dry-run
271
+ vat s3-status appydave b65
272
+ vat s3-cleanup appydave b65 --force
273
+
274
+ For more information: https://github.com/appydave/appydave-tools
275
+ HELP
276
+ end
277
+
278
+ def show_brands_help
279
+ puts <<~HELP
280
+ Available Brands
281
+
282
+ VAT supports multi-tenant video project management with brand shortcuts:
283
+
284
+ Brand Shortcuts:
285
+ appydave → v-appydave (AppyDave brand videos)
286
+ voz → v-voz (VOZ client videos)
287
+ aitldr → v-aitldr (AITLDR brand videos)
288
+ kiros → v-kiros (Kiros client videos)
289
+ joy → v-beauty-and-joy (Beauty & Joy brand)
290
+ ss → v-supportsignal (SupportSignal client)
291
+
292
+ Usage:
293
+ vat list # Show all brands
294
+ vat list --summary # Show brands with project counts
295
+ vat list appydave # List all AppyDave projects
296
+ vat s3-up voz boy-baker # Upload VOZ project
297
+ HELP
298
+ end
299
+
300
+ def show_workflows_help
301
+ puts <<~HELP
302
+ Video Workflows
303
+
304
+ VAT supports two primary video content workflows:
305
+
306
+ 1. FliVideo Workflow (AppyDave)
307
+ - Sequential chapter-based recording
308
+ - Projects follow pattern: [letter][number]-[name]
309
+ - Example: b65-guy-monroe-marketing-plan
310
+ - Short name support: b65 → b65-guy-monroe-marketing-plan
311
+ - Pattern matching: b6* → all projects b60-b69
312
+
313
+ 2. Storyline Workflow (VOZ, AITLDR)
314
+ - Script-first content creation
315
+ - Projects use full descriptive names
316
+ - Example: boy-baker, the-point
317
+ - No short name expansion (exact match required)
318
+
319
+ Project Organization:
320
+ v-appydave/
321
+ ├── b40-project-name/ # FliVideo pattern
322
+ ├── b65-another-project/
323
+ └── archived/ # Completed projects
324
+
325
+ v-voz/
326
+ ├── boy-baker/ # Storyline pattern
327
+ └── the-point/
328
+
329
+ Storage Strategy:
330
+ Local → S3 (90-day collaboration) → SSD (long-term archive)
331
+ HELP
332
+ end
333
+
334
+ def show_config_help
335
+ puts <<~HELP
336
+ Configuration
337
+
338
+ VAT uses two configuration levels:
339
+
340
+ 1. System Configuration (settings.json)
341
+ Location: ~/.config/appydave/settings.json
342
+ Purpose: Define root directory for all video projects
343
+ Format:
344
+ {
345
+ "video-projects-root": "/Users/yourname/dev/video-projects"
346
+ }
347
+
348
+ Setup:
349
+ ad_config -c # Create configuration
350
+ ad_config -e # Edit configuration
351
+
352
+ 2. Brand Configuration (.video-tools.env)
353
+ Location: <brand-dir>/.video-tools.env
354
+ Purpose: AWS credentials and S3 settings per brand
355
+ Required Keys:
356
+ AWS_ACCESS_KEY_ID=xxx
357
+ AWS_SECRET_ACCESS_KEY=xxx
358
+ AWS_REGION=us-east-1
359
+ S3_BUCKET=your-bucket-name
360
+ SSD_BASE=/path/to/external/drive
361
+
362
+ Example:
363
+ v-appydave/.video-tools.env
364
+ v-voz/.video-tools.env
365
+
366
+ Directory Structure:
367
+ ~/.config/appydave/
368
+ └── settings.json # System config
369
+
370
+ /Users/yourname/dev/video-projects/
371
+ ├── v-appydave/
372
+ │ ├── .video-tools.env # Brand-specific config
373
+ │ └── b65-project/
374
+ └── v-voz/
375
+ ├── .video-tools.env
376
+ └── boy-baker/
377
+ HELP
378
+ end
379
+
380
+ def show_list_help
381
+ puts <<~HELP
382
+ List Command
383
+
384
+ Usage: vat list [brand] [pattern]
385
+
386
+ Modes:
387
+ 1. List all brands with summary:
388
+ vat list
389
+
390
+ 2. List projects for specific brand:
391
+ vat list appydave
392
+
393
+ 3. Pattern matching:
394
+ vat list appydave 'b6*' # All projects b60-b69
395
+ vat list appydave 'b4*' # All projects b40-b49
396
+
397
+ Examples:
398
+ vat list # Tabular: brand, project count, size, modified
399
+ vat list voz # Tabular: all VOZ projects with size/date
400
+ vat list appydave 'b6*' # Tabular: b60-b69 projects with size/date
401
+ HELP
402
+ end
403
+
404
+ # rubocop:disable Metrics/CyclomaticComplexity
405
+ def show_s3_help(command)
406
+ case command
407
+ when 's3-up'
408
+ puts <<~HELP
409
+ S3 Upload Command
410
+
411
+ Upload files from local s3-staging/ directory to S3 for collaboration.
412
+
413
+ Usage: vat s3-up <brand> <project> [--dry-run]
414
+
415
+ Features:
416
+ - Smart sync: Skips unchanged files (MD5 comparison)
417
+ - Progress tracking: Shows uploaded/skipped/failed counts
418
+ - Dry-run support: Preview changes without uploading
419
+
420
+ Examples:
421
+ vat s3-up appydave b65 # Upload b65 project
422
+ vat s3-up voz boy-baker --dry-run # Preview upload
423
+ vat s3-up # Auto-detect from PWD
424
+
425
+ Notes:
426
+ - Files must be in project's s3-staging/ directory
427
+ - Requires AWS credentials in .video-tools.env
428
+ - S3 path: staging/<brand>/<project>/
429
+ HELP
430
+ when 's3-down'
431
+ puts <<~HELP
432
+ S3 Download Command
433
+
434
+ Download files from S3 to local s3-staging/ directory.
435
+
436
+ Usage: vat s3-down <brand> <project> [--dry-run]
437
+
438
+ Features:
439
+ - Smart sync: Skips unchanged files (MD5 comparison)
440
+ - Progress tracking: Shows downloaded/skipped/failed counts
441
+ - Dry-run support: Preview changes without downloading
442
+
443
+ Examples:
444
+ vat s3-down appydave b65 # Download b65 project
445
+ vat s3-down voz boy-baker --dry-run # Preview download
446
+ vat s3-down # Auto-detect from PWD
447
+
448
+ Notes:
449
+ - Creates s3-staging/ directory if needed
450
+ - Requires AWS credentials in .video-tools.env
451
+ HELP
452
+ when 's3-status'
453
+ puts <<~HELP
454
+ S3 Status Command
455
+
456
+ Check sync status between local and S3 files.
457
+
458
+ Usage: vat s3-status <brand> [project]
459
+
460
+ Features:
461
+ - Shows all files (S3 and local)
462
+ - Indicates sync status: [synced], [modified], [S3 only], [local only]
463
+ - Displays file sizes and totals
464
+ - Shows file counts for both S3 and local
465
+
466
+ Examples:
467
+ vat s3-status appydave b65 # Check b65 status
468
+ vat s3-status # Auto-detect from PWD
469
+
470
+ Status Indicators:
471
+ ✓ [synced] - Local and S3 match (MD5)
472
+ ⚠️ [modified] - Files differ between local and S3
473
+ ☁️ [S3 only] - File only in S3, not present locally
474
+ 📁 [local only] - File only local, not uploaded to S3
475
+ HELP
476
+ when 's3-cleanup-remote'
477
+ puts <<~HELP
478
+ S3 Cleanup Remote Command
479
+
480
+ Delete all S3 files for a project (use with caution).
481
+
482
+ Usage: vat s3-cleanup-remote <brand> <project> --force [--dry-run]
483
+
484
+ Features:
485
+ - Requires --force flag for safety
486
+ - Dry-run support: Preview deletions
487
+ - Shows deleted/failed counts
488
+
489
+ Examples:
490
+ vat s3-cleanup-remote appydave b65 --dry-run # Preview deletion
491
+ vat s3-cleanup-remote appydave b65 --force # Actually delete
492
+ vat s3-cleanup-remote --force # Auto-detect from PWD
493
+
494
+ ⚠️ WARNING: This permanently deletes files from S3.
495
+ Ensure you have local backups before running.
496
+
497
+ Note: Old command 's3-cleanup' still works but is deprecated.
498
+ HELP
499
+ when 's3-cleanup-local'
500
+ puts <<~HELP
501
+ S3 Cleanup Local Command
502
+
503
+ Delete all local files in the s3-staging/ directory for a project.
504
+
505
+ Usage: vat s3-cleanup-local <brand> <project> --force [--dry-run]
506
+
507
+ Features:
508
+ - Requires --force flag for safety
509
+ - Dry-run support: Preview deletions
510
+ - Removes empty directories after cleanup
511
+ - Shows deleted/failed counts
512
+
513
+ Examples:
514
+ vat s3-cleanup-local appydave b65 --dry-run # Preview deletion
515
+ vat s3-cleanup-local appydave b65 --force # Actually delete
516
+ vat s3-cleanup-local --force # Auto-detect from PWD
517
+
518
+ Use Cases:
519
+ - Free up disk space after uploading to S3
520
+ - Clean up after completing collaboration
521
+ - Remove local staging files when project is archived
522
+
523
+ ⚠️ NOTE: This only deletes LOCAL files in s3-staging/.
524
+ Files in S3 are NOT affected. Use 's3-cleanup-remote' for that.
525
+
526
+ Note: Old command 'cleanup-local' still works but is deprecated.
527
+ HELP
528
+ when 'archive'
529
+ puts <<~HELP
530
+ Archive Command
531
+
532
+ Copy completed video project to SSD for long-term backup.
533
+
534
+ Usage: vat archive <brand> <project> [--force] [--dry-run]
535
+
536
+ Features:
537
+ - Copies entire project directory to SSD backup location
538
+ - Verifies SSD is mounted before archiving
539
+ - Shows project size before copying
540
+ - Optional: Delete local copy after successful archive (--force)
541
+ - Dry-run support: Preview archive operation
542
+
543
+ Examples:
544
+ vat archive appydave b63 --dry-run # Preview archive
545
+ vat archive appydave b63 # Copy to SSD only
546
+ vat archive appydave b63 --force # Copy and delete local
547
+ vat archive # Auto-detect from PWD
548
+
549
+ Storage Strategy:
550
+ Local → S3 (90-day collaboration) → SSD (long-term archive)
551
+
552
+ Use Cases:
553
+ - Archive completed and published projects
554
+ - Free up local disk space for new projects
555
+ - Long-term backup before removing from S3
556
+
557
+ ⚠️ NOTE: Without --force, the local project is NOT deleted.
558
+ Use --force only after verifying SSD copy is successful.
559
+
560
+ Configuration:
561
+ - SSD backup path configured per brand in brands.json
562
+ - Example: "ssd_backup": "/Volumes/T7/youtube-PUBLISHED/appydave"
563
+ HELP
564
+ when 'manifest'
565
+ puts <<~HELP
566
+ Manifest Command
567
+
568
+ Generate a JSON manifest of all video projects for a brand.
569
+
570
+ Usage: vat manifest <brand> [--all]
571
+
572
+ Features:
573
+ - Scans local and SSD storage locations
574
+ - Tracks project distribution (local, SSD, both)
575
+ - Identifies heavy files (video) vs light files (subtitles, images)
576
+ - Calculates disk usage statistics
577
+ - Validates project ID formats
578
+ - Outputs projects.json in brand directory
579
+
580
+ Examples:
581
+ vat manifest appydave # Generate manifest for AppyDave
582
+ vat manifest voz # Generate manifest for VOZ
583
+ vat manifest --all # Generate manifests for all brands
584
+
585
+ Output Location:
586
+ - Single brand: <brand-path>/projects.json
587
+ - All brands: Each brand gets its own manifest file
588
+
589
+ Manifest Structure:
590
+ {
591
+ "config": {
592
+ "brand": "appydave",
593
+ "local_base": "/path/to/v-appydave",
594
+ "ssd_base": "/Volumes/T7/youtube-PUBLISHED/appydave",
595
+ "last_updated": "2025-11-09T23:00:00Z",
596
+ "disk_usage": { ... }
597
+ },
598
+ "projects": [
599
+ {
600
+ "id": "b65-guy-monroe-marketing-plan",
601
+ "storage": {
602
+ "ssd": { "exists": true, "path": "b65-guy-monroe-marketing-plan" },
603
+ "local": { "exists": true, "has_heavy_files": true, "has_light_files": true }
604
+ }
605
+ }
606
+ ]
607
+ }
608
+
609
+ Use Cases:
610
+ - Track which projects are archived to SSD
611
+ - Identify projects with only light files (archived locally)
612
+ - Generate disk usage reports
613
+ - Validate project naming conventions
614
+ - Prepare for sync-ssd operations
615
+ HELP
616
+ end
617
+ end
618
+ # rubocop:enable Metrics/CyclomaticComplexity
619
+ # rubocop:enable Metrics/MethodLength
620
+ end
621
+
622
+ # Run CLI
623
+ VatCLI.new.run if $PROGRAM_NAME == __FILE__