appydave-tools 0.76.6 → 0.76.8

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.
@@ -0,0 +1,61 @@
1
+ # IMPLEMENTATION_PLAN.md — library-boundary-cleanup
2
+
3
+ **Goal**: Fix two architectural boundary violations introduced by extract-vat-cli, then fill the test gaps they blocked. Prerequisite for B007 (parallelism) and clean library boundaries.
4
+ **Started**: 2026-03-19
5
+ **Target**: 4 items complete; 847+ examples passing; rubocop 0 offenses; no regressions
6
+
7
+ ## Summary
8
+ - Total: 4 | Complete: 0 | In Progress: 1 | Pending: 3 | Failed: 0
9
+
10
+ ## Pending
11
+ - [ ] B035 — extract-env-side-effect — Remove `ENV['BRAND_PATH']` side-effect from S3ArgParser; return `brand_path:` in result hash; update VatCLI callers (DEPENDS ON B034)
12
+ - [ ] B036 — tests-s3-scan-command — Rebuild S3ScanCommand spec from D-grade to B; 8–10 examples covering happy path, manifest missing, empty results, orphaned projects (DEPENDS ON B034)
13
+ - [ ] B037 — tests-local-sync-status — Add :partial case, local_file_count assertion, Zone.Identifier exclusion, unknown format guard
14
+
15
+ ## In Progress
16
+ - [~] B034 — extract-exit-calls — Replace `exit 1` with typed exceptions in S3ScanCommand + S3ArgParser; add `UsageError` to errors.rb
17
+
18
+ ## Complete
19
+
20
+ ## Failed / Needs Retry
21
+
22
+ ## Notes & Decisions
23
+
24
+ ### Wave Plan
25
+
26
+ **Wave 1 — B034** (alone)
27
+ - Touches: `s3_scan_command.rb`, `s3_arg_parser.rb`, `errors.rb`
28
+ - No parallel candidates — all three files must be edited together
29
+
30
+ **Wave 2 — B035** (after B034)
31
+ - Touches: `s3_arg_parser.rb`, `bin/dam`
32
+ - Cannot run with B034 (shared `s3_arg_parser.rb`)
33
+ - No behaviour change — moves ENV side-effect to CLI layer only
34
+
35
+ **Wave 3 — B036 + B037** (parallel — different spec files, no shared edits)
36
+ - B036: `spec/appydave/tools/dam/s3_scan_command_spec.rb`
37
+ - B037: `spec/appydave/tools/dam/local_sync_status_spec.rb`
38
+ - Both depend on B034 being complete (exceptions must exist before testing them)
39
+
40
+ ### Sequencing Constraints
41
+ - B034 must complete before B035 (both touch s3_arg_parser.rb)
42
+ - B034 must complete before B036 (can't test raised exceptions until they exist)
43
+ - B035 must complete before B036 + B037 (ENV side-effect removal may affect test setup)
44
+ - B036 and B037 are fully parallel once B034 + B035 are done
45
+
46
+ ### Exit Locations Confirmed (read 2026-03-19)
47
+ - `S3ScanCommand#scan_single` line 55: manifest not found → raise `ConfigurationError`
48
+ - `S3ArgParser#parse_s3` line 25: PWD auto-detect fail → raise `UsageError`
49
+ - `S3ArgParser#parse_s3` line 43: invalid brand → raise `UsageError`
50
+ - `S3ArgParser#parse_discover` line 100: missing brand/project args → raise `UsageError`
51
+ - `S3ArgParser#show_share_usage_and_exit` line 131: missing share args → raise `UsageError`
52
+
53
+ ### ENV Side-Effect Locations Confirmed (read 2026-03-19)
54
+ - `S3ArgParser#parse_s3` line 51: `ENV['BRAND_PATH'] = ...`
55
+ - `S3ArgParser#parse_share` line 82: `ENV['BRAND_PATH'] = ...`
56
+ - `S3ArgParser#parse_discover` line 108: `ENV['BRAND_PATH'] = ...`
57
+ - Fix: return `brand_path:` in each result hash; update VatCLI callers to set ENV there
58
+
59
+ ### VatCLI Rescue Blocks
60
+ - `s3_scan_command`, `s3_up_command`, etc. already rescue `StandardError => e` and `puts "❌ Error: #{e.message}"`
61
+ - No VatCLI rescue changes needed for B034 — existing rescues already catch DamError (which inherits from StandardError)
@@ -34,6 +34,9 @@ module Appydave
34
34
 
35
35
  # Raised when git operation fails
36
36
  class GitOperationError < DamError; end
37
+
38
+ # Raised when CLI arguments are invalid or missing
39
+ class UsageError < DamError; end
37
40
  end
38
41
  end
39
42
  end
@@ -0,0 +1,111 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appydave
4
+ module Tools
5
+ module Dam
6
+ # Parses and validates CLI arguments for S3-related dam commands
7
+ # Handles brand resolution, project lookup, flag extraction, and ENV setup
8
+ module S3ArgParser
9
+ module_function
10
+
11
+ def parse_s3(args, command)
12
+ dry_run = args.include?('--dry-run')
13
+ force = args.include?('--force')
14
+ args = args.reject { |arg| arg.start_with?('--') }
15
+
16
+ brand_arg = args[0]
17
+ project_arg = args[1]
18
+
19
+ if brand_arg.nil?
20
+ # Auto-detect from PWD
21
+ brand, project_id = Appydave::Tools::Dam::ProjectResolver.detect_from_pwd
22
+ if brand.nil? || project_id.nil?
23
+ raise Appydave::Tools::Dam::UsageError,
24
+ "Could not auto-detect brand/project from current directory. Usage: dam #{command} <brand> <project> [--dry-run]"
25
+ end
26
+ brand_key = brand # Already detected, use as-is
27
+ else
28
+ # Validate brand exists before trying to resolve project
29
+ unless valid_brand?(brand_arg)
30
+ raise Appydave::Tools::Dam::UsageError,
31
+ "Invalid brand: '#{brand_arg}'. Valid brands: appydave, voz, aitldr, kiros, joy, ss. Usage: dam #{command} <brand> <project> [--dry-run]"
32
+ end
33
+
34
+ brand_key = brand_arg # Use the shortcut/key (e.g., 'appydave')
35
+ brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg) # Expand for path resolution
36
+ project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
37
+ end
38
+
39
+ # Set ENV for compatibility with ConfigLoader
40
+ ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
41
+
42
+ { brand: brand_key, project: project_id, dry_run: dry_run, force: force }
43
+ end
44
+
45
+ def parse_share(args)
46
+ # Extract --expires flag
47
+ expires = '7d' # default
48
+ if (expires_index = args.index('--expires'))
49
+ expires = args[expires_index + 1]
50
+ args.delete_at(expires_index + 1)
51
+ args.delete_at(expires_index)
52
+ end
53
+
54
+ # Extract --download flag
55
+ download = args.include?('--download')
56
+
57
+ # Remove other flags
58
+ args = args.reject { |arg| arg.start_with?('--') }
59
+
60
+ brand_arg = args[0]
61
+ project_arg = args[1]
62
+ file_arg = args[2]
63
+
64
+ raise_share_usage_error if brand_arg.nil? || project_arg.nil? || file_arg.nil?
65
+
66
+ brand_key = brand_arg
67
+ brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg)
68
+ project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
69
+
70
+ # Set ENV for compatibility with ConfigLoader
71
+ ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
72
+
73
+ { brand: brand_key, project: project_id, file: file_arg, expires: expires, download: download }
74
+ end
75
+
76
+ def parse_discover(args)
77
+ shareable = args.include?('--shareable')
78
+ args = args.reject { |arg| arg.start_with?('--') }
79
+
80
+ brand_arg = args[0]
81
+ project_arg = args[1]
82
+
83
+ if brand_arg.nil? || project_arg.nil?
84
+ raise Appydave::Tools::Dam::UsageError,
85
+ 'Usage: dam s3-discover <brand> <project> [--shareable]'
86
+ end
87
+
88
+ brand_key = brand_arg
89
+ brand = Appydave::Tools::Dam::Config.expand_brand(brand_arg)
90
+ project_id = Appydave::Tools::Dam::ProjectResolver.resolve(brand_arg, project_arg)
91
+
92
+ # Set ENV for compatibility with ConfigLoader
93
+ ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand)
94
+
95
+ { brand_key: brand_key, project_id: project_id, shareable: shareable }
96
+ end
97
+
98
+ def valid_brand?(brand_key)
99
+ Appydave::Tools::Configuration::Config.configure
100
+ brands = Appydave::Tools::Configuration::Config.brands
101
+ brands.key?(brand_key) || brands.shortcut?(brand_key)
102
+ end
103
+
104
+ def raise_share_usage_error
105
+ raise Appydave::Tools::Dam::UsageError,
106
+ 'Usage: dam s3-share <brand> <project> <file> [--expires 7d] [--download]'
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -49,10 +49,8 @@ module Appydave
49
49
  manifest_path = File.join(brand_path, 'projects.json')
50
50
 
51
51
  unless File.exist?(manifest_path)
52
- puts "❌ Manifest not found: #{manifest_path}"
53
- puts " Run: dam manifest #{brand_key}"
54
- puts " Then retry: dam s3-scan #{brand_key}"
55
- exit 1
52
+ raise Appydave::Tools::Dam::ConfigurationError,
53
+ "Manifest not found: #{manifest_path}. Run: dam manifest #{brand_key}"
56
54
  end
57
55
 
58
56
  manifest = JSON.parse(File.read(manifest_path), symbolize_names: true)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Appydave
4
4
  module Tools
5
- VERSION = '0.76.6'
5
+ VERSION = '0.76.8'
6
6
  end
7
7
  end
@@ -80,6 +80,7 @@ require 'appydave/tools/dam/repo_sync'
80
80
  require 'appydave/tools/dam/repo_push'
81
81
  require 'appydave/tools/dam/local_sync_status'
82
82
  require 'appydave/tools/dam/s3_scan_command'
83
+ require 'appydave/tools/dam/s3_arg_parser'
83
84
 
84
85
  require 'appydave/tools/jump/path_validator'
85
86
  require 'appydave/tools/jump/location'
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appydave-tools",
3
- "version": "0.76.6",
3
+ "version": "0.76.8",
4
4
  "description": "AppyDave YouTube Automation Tools",
5
5
  "scripts": {
6
6
  "release": "semantic-release"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: appydave-tools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.76.6
4
+ version: 0.76.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
@@ -302,12 +302,16 @@ files:
302
302
  - docs/planning/bugfix-and-security/assessment.md
303
303
  - docs/planning/extract-vat-cli/AGENTS.md
304
304
  - docs/planning/extract-vat-cli/IMPLEMENTATION_PLAN.md
305
+ - docs/planning/extract-vat-cli/assessment.md
306
+ - docs/planning/extract-vat-cli/learnings/wave-learnings.md
305
307
  - docs/planning/final-test-gaps/AGENTS.md
306
308
  - docs/planning/final-test-gaps/IMPLEMENTATION_PLAN.md
307
309
  - docs/planning/final-test-gaps/assessment.md
308
310
  - docs/planning/fr2-gpt-context-help/AGENTS.md
309
311
  - docs/planning/fr2-gpt-context-help/IMPLEMENTATION_PLAN.md
310
312
  - docs/planning/fr2-gpt-context-help/assessment.md
313
+ - docs/planning/library-boundary-cleanup/AGENTS.md
314
+ - docs/planning/library-boundary-cleanup/IMPLEMENTATION_PLAN.md
311
315
  - docs/planning/micro-cleanup/AGENTS.md
312
316
  - docs/planning/micro-cleanup/IMPLEMENTATION_PLAN.md
313
317
  - docs/planning/micro-cleanup/assessment.md
@@ -361,6 +365,7 @@ files:
361
365
  - lib/appydave/tools/dam/repo_push.rb
362
366
  - lib/appydave/tools/dam/repo_status.rb
363
367
  - lib/appydave/tools/dam/repo_sync.rb
368
+ - lib/appydave/tools/dam/s3_arg_parser.rb
364
369
  - lib/appydave/tools/dam/s3_operations.rb
365
370
  - lib/appydave/tools/dam/s3_scan_command.rb
366
371
  - lib/appydave/tools/dam/s3_scanner.rb