appydave-tools 0.76.11 → 0.76.12
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/bin/dam +0 -10
- data/docs/planning/BACKLOG.md +11 -9
- data/docs/planning/env-dead-code-cleanup/AGENTS.md +234 -0
- data/docs/planning/env-dead-code-cleanup/IMPLEMENTATION_PLAN.md +51 -0
- data/docs/planning/library-boundary-cleanup/AGENTS.md +6 -0
- data/docs/planning/library-boundary-cleanup/IMPLEMENTATION_PLAN.md +2 -2
- data/docs/planning/library-boundary-cleanup/assessment.md +109 -0
- data/lib/appydave/tools/version.rb +1 -1
- data/package.json +1 -1
- metadata +4 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9252ea22ead22d967de9096d645777ce4b65bc66e633fbf391e385e2719a839e
|
|
4
|
+
data.tar.gz: 4ea18017243a9d10dd8d0daedf060d91cf7a85fd95c3093d8e5fbeebbd7d82eb
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 863eb25208061bef821717a4b6fbf73159e299f7fc6e1fda7e79fc646ea849fe587574ed395b5d1c441238eb2bed781dd9154a5e69b4d0d27ae3c18f29fd7703
|
|
7
|
+
data.tar.gz: da1c86a72f91fa4bf8686e8c5ffb90916d84841cfc8b63189e2d7adafdb019a2c98223da79e0d1cab646c3da6a8e19182215eb2bcde23b4f517a0f1200e04db9
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## [0.76.11](https://github.com/appydave/appydave-tools/compare/v0.76.10...v0.76.11) (2026-03-19)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* use full BrandsConfig constant in s3_scan_command_spec to prevent CI verification failure ([3bd417d](https://github.com/appydave/appydave-tools/commit/3bd417d5d58dff89af736567ba7f85fd1d786fb6))
|
|
7
|
+
|
|
1
8
|
## [0.76.10](https://github.com/appydave/appydave-tools/compare/v0.76.9...v0.76.10) (2026-03-19)
|
|
2
9
|
|
|
3
10
|
|
data/bin/dam
CHANGED
|
@@ -155,7 +155,6 @@ class VatCLI
|
|
|
155
155
|
# S3 Upload
|
|
156
156
|
def s3_up_command(args)
|
|
157
157
|
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-up')
|
|
158
|
-
ENV['BRAND_PATH'] = options[:brand_path]
|
|
159
158
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
160
159
|
s3_ops.upload(dry_run: options[:dry_run])
|
|
161
160
|
rescue StandardError => e
|
|
@@ -166,7 +165,6 @@ class VatCLI
|
|
|
166
165
|
# S3 Download
|
|
167
166
|
def s3_down_command(args)
|
|
168
167
|
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-down')
|
|
169
|
-
ENV['BRAND_PATH'] = options[:brand_path]
|
|
170
168
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
171
169
|
s3_ops.download(dry_run: options[:dry_run])
|
|
172
170
|
rescue StandardError => e
|
|
@@ -177,7 +175,6 @@ class VatCLI
|
|
|
177
175
|
# S3 Status
|
|
178
176
|
def s3_status_command(args)
|
|
179
177
|
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-status')
|
|
180
|
-
ENV['BRAND_PATH'] = options[:brand_path]
|
|
181
178
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
182
179
|
s3_ops.status
|
|
183
180
|
rescue StandardError => e
|
|
@@ -188,7 +185,6 @@ class VatCLI
|
|
|
188
185
|
# S3 Cleanup Remote
|
|
189
186
|
def s3_cleanup_remote_command(args)
|
|
190
187
|
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-cleanup-remote')
|
|
191
|
-
ENV['BRAND_PATH'] = options[:brand_path]
|
|
192
188
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
193
189
|
s3_ops.cleanup(force: options[:force], dry_run: options[:dry_run])
|
|
194
190
|
rescue StandardError => e
|
|
@@ -199,7 +195,6 @@ class VatCLI
|
|
|
199
195
|
# S3 Cleanup Local
|
|
200
196
|
def s3_cleanup_local_command(args)
|
|
201
197
|
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 's3-cleanup-local')
|
|
202
|
-
ENV['BRAND_PATH'] = options[:brand_path]
|
|
203
198
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
204
199
|
s3_ops.cleanup_local(force: options[:force], dry_run: options[:dry_run])
|
|
205
200
|
rescue StandardError => e
|
|
@@ -210,7 +205,6 @@ class VatCLI
|
|
|
210
205
|
# Share file via pre-signed URL
|
|
211
206
|
def s3_share_command(args)
|
|
212
207
|
options = Appydave::Tools::Dam::S3ArgParser.parse_share(args)
|
|
213
|
-
ENV['BRAND_PATH'] = options[:brand_path]
|
|
214
208
|
share_ops = Appydave::Tools::Dam::ShareOperations.new(options[:brand], options[:project])
|
|
215
209
|
share_ops.generate_links(files: options[:file], expires: options[:expires], download: options[:download])
|
|
216
210
|
rescue StandardError => e
|
|
@@ -221,7 +215,6 @@ class VatCLI
|
|
|
221
215
|
# Discover files in S3 for a project
|
|
222
216
|
def s3_discover_command(args)
|
|
223
217
|
options = Appydave::Tools::Dam::S3ArgParser.parse_discover(args)
|
|
224
|
-
ENV['BRAND_PATH'] = options[:brand_path]
|
|
225
218
|
files = fetch_s3_files(options[:brand_key], options[:project_id])
|
|
226
219
|
|
|
227
220
|
return if handle_empty_files?(files, options[:brand_key], options[:project_id])
|
|
@@ -235,7 +228,6 @@ class VatCLI
|
|
|
235
228
|
# Archive project to SSD
|
|
236
229
|
def archive_command(args)
|
|
237
230
|
options = Appydave::Tools::Dam::S3ArgParser.parse_s3(args, 'archive')
|
|
238
|
-
ENV['BRAND_PATH'] = options[:brand_path]
|
|
239
231
|
s3_ops = Appydave::Tools::Dam::S3Operations.new(options[:brand], options[:project])
|
|
240
232
|
s3_ops.archive(force: options[:force], dry_run: options[:dry_run])
|
|
241
233
|
rescue StandardError => e
|
|
@@ -282,7 +274,6 @@ class VatCLI
|
|
|
282
274
|
|
|
283
275
|
def generate_single_manifest(brand_arg, verbose: false)
|
|
284
276
|
Appydave::Tools::Dam::Config.expand_brand(brand_arg)
|
|
285
|
-
ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand_arg)
|
|
286
277
|
|
|
287
278
|
generator = Appydave::Tools::Dam::ManifestGenerator.new(brand_arg)
|
|
288
279
|
generator.generate(verbose: verbose)
|
|
@@ -329,7 +320,6 @@ class VatCLI
|
|
|
329
320
|
if brand_arg
|
|
330
321
|
# Sync specific brand
|
|
331
322
|
Appydave::Tools::Dam::Config.expand_brand(brand_arg)
|
|
332
|
-
ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand_arg)
|
|
333
323
|
|
|
334
324
|
syncer = Appydave::Tools::Dam::SyncFromSsd.new(brand_arg)
|
|
335
325
|
syncer.sync(dry_run: dry_run)
|
data/docs/planning/BACKLOG.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Project Backlog — AppyDave Tools
|
|
2
2
|
|
|
3
|
-
**Last updated**: 2026-03-19 (
|
|
4
|
-
**Total**:
|
|
3
|
+
**Last updated**: 2026-03-19 (library-boundary-cleanup campaign complete)
|
|
4
|
+
**Total**: 40 | Pending: 9 | Done: 30 | Deferred: 0 | Rejected: 0
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
@@ -10,16 +10,13 @@
|
|
|
10
10
|
### Medium Priority
|
|
11
11
|
- [ ] B001 — FR-1: GPT Context token counting | Priority: medium
|
|
12
12
|
- [ ] B012 — Arch: add integration tests for brand resolution end-to-end | Priority: medium
|
|
13
|
-
- [ ] B007 — Performance: parallel git/S3 status checks for dam list | Priority: low
|
|
13
|
+
- [ ] B007 — Performance: parallel git/S3 status checks for dam list | Priority: low (now unblocked)
|
|
14
14
|
- [ ] B008 — Performance: cache git/S3 status with 5-min TTL | Priority: low
|
|
15
15
|
- [ ] B009 — UX: progress indicators for dam operations > 5s | Priority: low
|
|
16
16
|
- [ ] B010 — UX: auto-adjust dam table column widths to terminal width | Priority: low
|
|
17
|
-
- [
|
|
18
|
-
- [ ]
|
|
19
|
-
- [ ]
|
|
20
|
-
- [ ] B035 — Fix: remove ENV['BRAND_PATH'] side effect from S3ArgParser | Priority: high (blocks B007 parallelism)
|
|
21
|
-
- [ ] B036 — Tests: improve S3ScanCommand spec from D to B (depends on B034) | Priority: medium
|
|
22
|
-
- [ ] B037 — Tests: LocalSyncStatus :partial case, local_file_count assertion, Zone.Identifier exclusion | Priority: medium
|
|
17
|
+
- [ ] B020 — Arch: split S3Operations (1,030 lines, mixed I/O + logic) | Priority: low (now unblocked)
|
|
18
|
+
- [ ] B038 — Cleanup: remove ENV['BRAND_PATH'] dead code from bin/dam (10 assignments, never read in lib/) | Priority: low
|
|
19
|
+
- [ ] B039 — Tests: strengthen s3_scan_command_spec data-value assertions + remove LocalSyncStatus stub | Priority: low
|
|
23
20
|
|
|
24
21
|
---
|
|
25
22
|
|
|
@@ -50,6 +47,11 @@
|
|
|
50
47
|
- [x] B031 — Tests: add_spec `type` field assertion | Completed: already in commit 8eec40c; closed micro-cleanup (2026-03-19)
|
|
51
48
|
- [x] B032 — Tests: cli_spec `-f json` subprocess test | Completed: micro-cleanup (2026-03-19), v0.76.4
|
|
52
49
|
- [x] B033 — Fix: file_collector.rb return `''` when working_directory missing | Completed: already in commit 13d5f87; closed micro-cleanup (2026-03-19)
|
|
50
|
+
- [x] B011 — Arch: extract VatCLI business logic from bin/dam (1,600-line God class) | Completed: extract-vat-cli (2026-03-19)
|
|
51
|
+
- [x] B034 — Fix: replace exit 1 with typed exceptions in S3ScanCommand + S3ArgParser; add UsageError | Completed: library-boundary-cleanup (2026-03-19), v0.76.8
|
|
52
|
+
- [x] B035 — Fix: remove ENV['BRAND_PATH'] side effect from S3ArgParser; return brand_path: in result hash | Completed: library-boundary-cleanup (2026-03-19), v0.76.9
|
|
53
|
+
- [x] B036 — Tests: rebuild S3ScanCommand spec from D to B (10 behaviour examples) | Completed: library-boundary-cleanup (2026-03-19), v0.76.10
|
|
54
|
+
- [x] B037 — Tests: LocalSyncStatus :partial, local_file_count, Zone.Identifier exclusion, unknown format | Completed: library-boundary-cleanup (2026-03-19), v0.76.11
|
|
53
55
|
|
|
54
56
|
---
|
|
55
57
|
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
# AGENTS.md — AppyDave Tools / env-dead-code-cleanup campaign
|
|
2
|
+
|
|
3
|
+
> Operational knowledge for every background agent. Self-contained — you receive only this file + your work unit prompt.
|
|
4
|
+
> Inherited from: library-boundary-cleanup campaign (2026-03-20)
|
|
5
|
+
> Updated for: env-dead-code-cleanup campaign (2026-03-20)
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Project Overview
|
|
10
|
+
|
|
11
|
+
**What:** Ruby gem providing CLI productivity tools for AppyDave's YouTube content creation workflow.
|
|
12
|
+
**Stack:** Ruby 3.4.2, Bundler 2.6.2, RSpec, RuboCop, semantic-release CI/CD.
|
|
13
|
+
**Active campaign:** env-dead-code-cleanup — remove confirmed dead ENV code and strengthen one test assertion.
|
|
14
|
+
**Commits:** Always use `kfeat`/`kfix` — never `git commit` directly.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## ⚠️ Pre-Commit Check (Mandatory Every Commit)
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
git status
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Confirm ONLY the files you intentionally changed are staged. **Stage by file name — never `git add .` or `git add -A`.**
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Correct:
|
|
28
|
+
git add bin/dam
|
|
29
|
+
kfix "..."
|
|
30
|
+
|
|
31
|
+
# Wrong — stages everything including planning files:
|
|
32
|
+
git add .
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Why:** Three prior campaigns have had accidental staging from `git add .`. It is the single most common failure mode in this repo.
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Build & Run Commands
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
eval "$(rbenv init -)"
|
|
43
|
+
|
|
44
|
+
RUBYOPT="-W0" bundle exec rspec # Full suite
|
|
45
|
+
bundle exec rspec spec/appydave/tools/dam/s3_scan_command_spec.rb # Single file
|
|
46
|
+
bundle exec rubocop --format clang # Lint (matches CI)
|
|
47
|
+
|
|
48
|
+
kfeat "description" # Minor version bump
|
|
49
|
+
kfix "description" # Patch version bump
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**Baseline (start of env-dead-code-cleanup):** 861 examples, 0 failures, 86.43% line coverage
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Directory Structure
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
bin/
|
|
60
|
+
dam Main DAM CLI — target of B038 (10 ENV removals)
|
|
61
|
+
lib/appydave/tools/dam/
|
|
62
|
+
errors.rb UsageError, ConfigurationError, etc.
|
|
63
|
+
s3_scan_command.rb S3 scan orchestration
|
|
64
|
+
s3_arg_parser.rb CLI arg parsing — ENV side-effect already removed
|
|
65
|
+
local_sync_status.rb Local s3-staging sync status
|
|
66
|
+
manifest_generator.rb ManifestGenerator — confirmed does NOT read ENV['BRAND_PATH']
|
|
67
|
+
sync_from_ssd.rb SyncFromSsd — confirmed does NOT read ENV['BRAND_PATH']
|
|
68
|
+
spec/
|
|
69
|
+
appydave/tools/dam/
|
|
70
|
+
s3_scan_command_spec.rb Target of B039 (strengthen assertions)
|
|
71
|
+
local_sync_status_spec.rb Already updated in library-boundary-cleanup
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## This Campaign
|
|
77
|
+
|
|
78
|
+
### B038 — remove-env-dead-code
|
|
79
|
+
|
|
80
|
+
**File:** `bin/dam` only.
|
|
81
|
+
|
|
82
|
+
Remove all 10 `ENV['BRAND_PATH'] =` lines. Confirmed dead:
|
|
83
|
+
- `grep -rn "BRAND_PATH" lib/ spec/` → 0 results
|
|
84
|
+
- ManifestGenerator, SyncFromSsd: grep confirmed no reads
|
|
85
|
+
|
|
86
|
+
**10 lines to delete** (line numbers approximate after prior edits — grep to find exact):
|
|
87
|
+
|
|
88
|
+
| Method | Pattern to remove |
|
|
89
|
+
|--------|------------------|
|
|
90
|
+
| s3_up_command | `ENV['BRAND_PATH'] = options[:brand_path]` |
|
|
91
|
+
| s3_down_command | `ENV['BRAND_PATH'] = options[:brand_path]` |
|
|
92
|
+
| s3_status_command | `ENV['BRAND_PATH'] = options[:brand_path]` |
|
|
93
|
+
| s3_cleanup_remote_command | `ENV['BRAND_PATH'] = options[:brand_path]` |
|
|
94
|
+
| s3_cleanup_local_command | `ENV['BRAND_PATH'] = options[:brand_path]` |
|
|
95
|
+
| s3_archive_command | `ENV['BRAND_PATH'] = options[:brand_path]` |
|
|
96
|
+
| s3_share_command | `ENV['BRAND_PATH'] = options[:brand_path]` |
|
|
97
|
+
| s3_discover_command | `ENV['BRAND_PATH'] = options[:brand_path]` |
|
|
98
|
+
| generate_single_manifest | `ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand_arg)` |
|
|
99
|
+
| sync_ssd_command | `ENV['BRAND_PATH'] = Appydave::Tools::Dam::Config.brand_path(brand_arg)` |
|
|
100
|
+
|
|
101
|
+
After removing, also check if `options[:brand_path]` was the ONLY use of `options` in any method. If so, the `options =` assignment itself may now be unused. Grep the method body before removing.
|
|
102
|
+
|
|
103
|
+
**Done when:**
|
|
104
|
+
- `grep -n "BRAND_PATH" bin/dam` → 0 results
|
|
105
|
+
- `RUBYOPT="-W0" bundle exec rspec` → 861 examples, 0 failures
|
|
106
|
+
- `bundle exec rubocop --format clang` → 0 offenses
|
|
107
|
+
- `git status` clean (only bin/dam staged)
|
|
108
|
+
|
|
109
|
+
**Commit:** `kfix "remove ENV BRAND_PATH dead code from bin/dam (10 assignments, never read in lib)"`
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### B039 — strengthen-s3-scan-spec
|
|
114
|
+
|
|
115
|
+
**File:** `spec/appydave/tools/dam/s3_scan_command_spec.rb` only.
|
|
116
|
+
|
|
117
|
+
**Read the current spec file in full before making any changes.**
|
|
118
|
+
|
|
119
|
+
Two specific improvements:
|
|
120
|
+
|
|
121
|
+
**1. Replace `not_to be_empty` with field-value assertion**
|
|
122
|
+
|
|
123
|
+
Find the test that checks `project[:storage][:s3]` and replace the weak emptiness check:
|
|
124
|
+
```ruby
|
|
125
|
+
# Before (weak):
|
|
126
|
+
expect(project[:storage][:s3]).not_to be_empty
|
|
127
|
+
|
|
128
|
+
# After (catches wrong values):
|
|
129
|
+
expect(project[:storage][:s3]).to include(
|
|
130
|
+
file_count: 3,
|
|
131
|
+
total_bytes: 1_500_000,
|
|
132
|
+
last_modified: '2025-01-01T00:00:00Z'
|
|
133
|
+
)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Match the values to whatever the mock `scan_all_projects` returns in that context.
|
|
137
|
+
|
|
138
|
+
**2. Remove LocalSyncStatus stub, let integration run**
|
|
139
|
+
|
|
140
|
+
Find:
|
|
141
|
+
```ruby
|
|
142
|
+
allow(Appydave::Tools::Dam::LocalSyncStatus).to receive(:enrich!)
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Remove this line. `LocalSyncStatus.enrich!` uses the filesystem — it needs the s3-staging directory to exist (or it sets `:no_project`/:no_files`). The test doesn't need to assert on `:local_status` — just ensure it doesn't raise.
|
|
146
|
+
|
|
147
|
+
If removing the stub causes failures because LocalSyncStatus can't find the brand path, add an `s3-staging` folder to the fixture:
|
|
148
|
+
```ruby
|
|
149
|
+
FileUtils.mkdir_p(File.join(appydave_path, 'b65-test-project', 's3-staging'))
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Done when:**
|
|
153
|
+
- `bundle exec rspec spec/appydave/tools/dam/s3_scan_command_spec.rb` → all pass
|
|
154
|
+
- `RUBYOPT="-W0" bundle exec rspec` → 861 examples, 0 failures (count unchanged — no new specs)
|
|
155
|
+
- `bundle exec rubocop --format clang` → 0 offenses
|
|
156
|
+
- `git status` clean (only spec file staged)
|
|
157
|
+
|
|
158
|
+
**Commit:** `kfix "strengthen s3_scan_command_spec field assertions; remove LocalSyncStatus stub"`
|
|
159
|
+
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## Success Criteria (Every Work Unit)
|
|
163
|
+
|
|
164
|
+
- [ ] `RUBYOPT="-W0" bundle exec rspec` — 861+ examples, 0 failures
|
|
165
|
+
- [ ] `bundle exec rubocop --format clang` — 0 offenses
|
|
166
|
+
- [ ] Line coverage ≥ 86.43%
|
|
167
|
+
- [ ] `git status` clean, specific files staged (NOT `git add .`)
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
## Reference Patterns
|
|
172
|
+
|
|
173
|
+
### Shared Context for DAM Specs
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
RSpec.describe Appydave::Tools::Dam::SomeClass do
|
|
177
|
+
include_context 'with vat filesystem and brands', brands: %w[appydave voz]
|
|
178
|
+
# Provides: temp_folder, projects_root, appydave_path, voz_path
|
|
179
|
+
# SettingsConfig#video_projects_root mocked to return projects_root
|
|
180
|
+
end
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### instance_double — Always Use Full Constant
|
|
184
|
+
|
|
185
|
+
```ruby
|
|
186
|
+
# Correct:
|
|
187
|
+
instance_double(Appydave::Tools::Configuration::Models::BrandsConfig)
|
|
188
|
+
|
|
189
|
+
# Wrong — fails CI on Ubuntu:
|
|
190
|
+
instance_double('BrandsConfig')
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Typed Exception Pattern
|
|
194
|
+
|
|
195
|
+
```ruby
|
|
196
|
+
raise Appydave::Tools::Dam::ConfigurationError, 'Manifest not found: /path'
|
|
197
|
+
raise Appydave::Tools::Dam::UsageError, 'Usage: dam s3-up <brand> <project>'
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
---
|
|
201
|
+
|
|
202
|
+
## Anti-Patterns to Avoid
|
|
203
|
+
|
|
204
|
+
- ❌ `git add .` or `git add -A` — always stage specific files by name
|
|
205
|
+
- ❌ `exit 1` in library code — use typed exceptions (already fixed in library-boundary-cleanup)
|
|
206
|
+
- ❌ `ENV['BRAND_PATH'] =` in any file — confirmed dead, being removed in B038
|
|
207
|
+
- ❌ `instance_double('StringForm')` — use full constant always
|
|
208
|
+
- ❌ Inline brand transformations — use BrandResolver
|
|
209
|
+
- ❌ Multiple `before` blocks in same RSpec context — merge them (RSpec/ScatteredSetup)
|
|
210
|
+
- ❌ `$?` for subprocess status — use `$CHILD_STATUS`
|
|
211
|
+
|
|
212
|
+
---
|
|
213
|
+
|
|
214
|
+
## Learnings
|
|
215
|
+
|
|
216
|
+
### From library-boundary-cleanup (2026-03-20)
|
|
217
|
+
|
|
218
|
+
- **`instance_double` string form fails CI on Ubuntu.** Always use full constant: `instance_double(Fully::Qualified::ClassName)`.
|
|
219
|
+
- **`git add .` is the recurring staging bug.** Stage specific files by name. Always. Every commit.
|
|
220
|
+
- **`ENV['BRAND_PATH']` in bin/dam is dead code.** 10 assignments, 0 reads. Being removed in B038.
|
|
221
|
+
- **VatCLI rescue blocks catch DamError correctly.** `UsageError < DamError < StandardError` — all 17 rescue blocks catch it without modification.
|
|
222
|
+
|
|
223
|
+
### From extract-vat-cli (2026-03-19)
|
|
224
|
+
|
|
225
|
+
- **Dirty working tree + kfix = accidental staging.** Run `git status` before every commit.
|
|
226
|
+
- **rubocop-disable directives become redundant when methods move.** Check for orphaned disable/enable pairs after extraction.
|
|
227
|
+
- **valid_brand? needs Config.brands mock.** Shared filesystem context only mocks SettingsConfig; Config.brands needs a separate mock.
|
|
228
|
+
- **S3ScanCommand#scan_all already rescues per-brand.** Per-brand exceptions are isolated by design.
|
|
229
|
+
|
|
230
|
+
### From DAM Enhancement Sprint (Jan 2025)
|
|
231
|
+
|
|
232
|
+
- **BrandResolver is the critical path.** All dam commands flow through it.
|
|
233
|
+
- **`Config.configure` is memoized but called redundantly.** Don't add new calls.
|
|
234
|
+
- **Table format() pattern is non-obvious.** Headers misaligned 3× in UAT. Always verify with real data.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# IMPLEMENTATION_PLAN.md — env-dead-code-cleanup
|
|
2
|
+
|
|
3
|
+
**Goal**: Remove confirmed dead code (10× `ENV['BRAND_PATH']` in bin/dam) and strengthen s3_scan_command_spec data-value assertions. Closes B038 + B039 from the library-boundary-cleanup audit.
|
|
4
|
+
**Started**: 2026-03-20
|
|
5
|
+
**Target**: Both items complete; 861+ examples passing; rubocop 0 offenses; no regressions
|
|
6
|
+
|
|
7
|
+
## Summary
|
|
8
|
+
- Total: 2 | Complete: 0 | In Progress: 2 | Pending: 0 | Failed: 0
|
|
9
|
+
|
|
10
|
+
## Pending
|
|
11
|
+
|
|
12
|
+
## In Progress
|
|
13
|
+
- [~] B038 — remove-env-dead-code — Remove all 10 `ENV['BRAND_PATH'] =` assignments from bin/dam
|
|
14
|
+
- [~] B039 — strengthen-s3-scan-spec — Replace `not_to be_empty` with field-value assertions; remove LocalSyncStatus stub
|
|
15
|
+
|
|
16
|
+
## Complete
|
|
17
|
+
|
|
18
|
+
## Failed / Needs Retry
|
|
19
|
+
|
|
20
|
+
## Notes & Decisions
|
|
21
|
+
|
|
22
|
+
### Wave Plan
|
|
23
|
+
|
|
24
|
+
**Wave 1 — B038 + B039 in parallel**
|
|
25
|
+
- B038 touches `bin/dam` only
|
|
26
|
+
- B039 touches `spec/appydave/tools/dam/s3_scan_command_spec.rb` only
|
|
27
|
+
- No shared files — safe to run in parallel
|
|
28
|
+
|
|
29
|
+
### B038: All 10 ENV assignments confirmed dead (2026-03-20)
|
|
30
|
+
|
|
31
|
+
| Line | Method | Form |
|
|
32
|
+
|------|--------|------|
|
|
33
|
+
| 158 | s3_up_command | `options[:brand_path]` |
|
|
34
|
+
| 169 | s3_down_command | `options[:brand_path]` |
|
|
35
|
+
| 180 | s3_status_command | `options[:brand_path]` |
|
|
36
|
+
| 191 | s3_cleanup_remote_command | `options[:brand_path]` |
|
|
37
|
+
| 202 | s3_cleanup_local_command | `options[:brand_path]` |
|
|
38
|
+
| 213 | s3_archive_command | `options[:brand_path]` |
|
|
39
|
+
| 224 | s3_share_command | `options[:brand_path]` |
|
|
40
|
+
| 238 | s3_discover_command | `options[:brand_path]` |
|
|
41
|
+
| 285 | generate_single_manifest | `Config.brand_path(brand_arg)` |
|
|
42
|
+
| 332 | sync_ssd_command | `Config.brand_path(brand_arg)` |
|
|
43
|
+
|
|
44
|
+
- `grep -rn "BRAND_PATH" lib/ spec/` → 0 results (confirmed 2026-03-20)
|
|
45
|
+
- ManifestGenerator and SyncFromSsd do not read ENV['BRAND_PATH'] (confirmed 2026-03-20)
|
|
46
|
+
|
|
47
|
+
### B039: What to strengthen in s3_scan_command_spec
|
|
48
|
+
|
|
49
|
+
- Replace `expect(project[:storage][:s3]).not_to be_empty` with `include(file_count: 3, total_bytes: 1_500_000)`
|
|
50
|
+
- Remove `allow(Appydave::Tools::Dam::LocalSyncStatus).to receive(:enrich!)` stub — let it run for real
|
|
51
|
+
- If LocalSyncStatus.enrich! needs the s3-staging path to exist, create it in the fixture setup
|
|
@@ -645,6 +645,12 @@ end
|
|
|
645
645
|
- **`ENV['BRAND_PATH']` is set in 5 places in bin/dam.** Three are in parse methods (being extracted to B035). Two remain in `generate_single_manifest` and `sync_ssd_command` — out of scope for this campaign.
|
|
646
646
|
- **Do NOT attempt B020 (split S3Operations) in this campaign.** Different class, different risk profile.
|
|
647
647
|
|
|
648
|
+
### From library-boundary-cleanup (2026-03-20)
|
|
649
|
+
|
|
650
|
+
- **`instance_double` string form fails CI on Ubuntu.** Always use full constant: `instance_double(Fully::Qualified::ClassName)`. String form passes locally but Ubuntu CI enforces constant lookup. A CI failure after a green local run is almost always this.
|
|
651
|
+
- **`git add .` is the recurring staging bug.** Three campaigns have had accidental staging from `git add .`. Stage specific files by name: `git add lib/appydave/tools/dam/local_sync_status.rb spec/...`. Never `git add .` or `git add -A` in this repo.
|
|
652
|
+
- **`ENV['BRAND_PATH']` in bin/dam is dead code.** 10 assignments in bin/dam, 0 reads in lib/. S3Operations receives brand_path as a constructor parameter. Tracked as B038 for cleanup.
|
|
653
|
+
|
|
648
654
|
### From extract-vat-cli (2026-03-19)
|
|
649
655
|
|
|
650
656
|
- **valid_brand? needs Config.brands mock.** The shared filesystem context only mocks `SettingsConfig`. When testing code that calls `Config.brands`, mock it separately: `allow(Appydave::Tools::Configuration::Config).to receive(:brands).and_return(...)`.
|
|
@@ -5,13 +5,13 @@
|
|
|
5
5
|
**Target**: 4 items complete; 847+ examples passing; rubocop 0 offenses; no regressions
|
|
6
6
|
|
|
7
7
|
## Summary
|
|
8
|
-
- Total: 4 | Complete:
|
|
8
|
+
- Total: 4 | Complete: 4 | In Progress: 0 | Pending: 0 | Failed: 0
|
|
9
9
|
|
|
10
10
|
## Pending
|
|
11
11
|
|
|
12
12
|
## In Progress
|
|
13
13
|
- [x] B036 — tests-s3-scan-command — 10 behaviour examples replacing 2 smoke tests (happy path, manifest missing, empty results, orphaned projects, scan_all partial). 861 examples, 0 failures. 86.43% coverage. v0.76.10. Commit: de9d118.
|
|
14
|
-
- [
|
|
14
|
+
- [x] B037 — tests-local-sync-status — 6 new examples: :partial (2), local_file_count in :synced (1), Zone.Identifier exclusion (2), unknown format guard (1). Source already had both features — tests only. CI fix: replaced string instance_double with full constant. v0.76.11. Commits: 3fddeff, 3bd417d.
|
|
15
15
|
|
|
16
16
|
## Complete
|
|
17
17
|
- [x] B034 — extract-exit-calls — UsageError added to errors.rb; exit 1 replaced in s3_scan_command.rb (1) and s3_arg_parser.rb (4); show_share_usage_and_exit renamed. 847 examples, 0 failures. v0.76.8. Commit: 87bb43a.
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Assessment: library-boundary-cleanup
|
|
2
|
+
|
|
3
|
+
**Campaign**: library-boundary-cleanup
|
|
4
|
+
**Date**: 2026-03-19 → 2026-03-19
|
|
5
|
+
**Results**: 4 complete, 0 failed
|
|
6
|
+
**Final version**: v0.76.11 (from v0.76.7 baseline)
|
|
7
|
+
**Quality audits**: code-quality-audit ✅ | test-quality-audit ✅
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Results Summary
|
|
12
|
+
|
|
13
|
+
| Work Unit | Description | Result | Version |
|
|
14
|
+
|-----------|-------------|--------|---------|
|
|
15
|
+
| B034 | extract-exit-calls | ✅ Complete | v0.76.8 |
|
|
16
|
+
| B035 | extract-env-side-effect | ✅ Complete | v0.76.9 |
|
|
17
|
+
| B036 | tests-s3-scan-command | ✅ Complete | v0.76.10 |
|
|
18
|
+
| B037 | tests-local-sync-status | ✅ Complete | v0.76.11 |
|
|
19
|
+
|
|
20
|
+
**Test baseline:** 847 → 861+ examples (net +14), 0 failures, 86.43% line coverage
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## What Worked Well
|
|
25
|
+
|
|
26
|
+
1. **Wave plan held perfectly.** B034 → B035 → B036+B037 (parallel) ran with zero merge conflicts. Pre-reading the files before planning meant the sequencing constraints were exact.
|
|
27
|
+
|
|
28
|
+
2. **B035 rubocop self-corrected.** Agent caught a `Lint/UselessAssignment` for the now-redundant `brand =` local variable that was only there to support the ENV assignment. Removed cleanly in the same commit.
|
|
29
|
+
|
|
30
|
+
3. **LocalSyncStatus source already had the hard bits.** Zone.Identifier exclusion and `format` else-branch were already implemented — B037 only needed tests. Pre-reading confirmed this before writing any spec code.
|
|
31
|
+
|
|
32
|
+
4. **VatCLI rescue chain worked exactly as predicted.** No rescue changes needed in bin/dam — `UsageError < DamError < StandardError` was caught by all 17 existing `rescue StandardError` blocks.
|
|
33
|
+
|
|
34
|
+
5. **Code quality audit grade: HIGH.** 0 rubocop offenses, exception messages are actionable, ENV pattern in bin/dam is consistent across all 8 sites.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## What Didn't Work
|
|
39
|
+
|
|
40
|
+
1. **B037 agent used `git add .` instead of staging specific files.** Accidentally included the B036 spec and IMPLEMENTATION_PLAN.md in its commit. Required a follow-up fix commit. (Recurring issue — pre-commit check needs to be more prominent in AGENTS.md.)
|
|
41
|
+
|
|
42
|
+
2. **B036 CI failure on Ubuntu.** `instance_double('BrandsConfig')` (string form) failed double verification in CI but passed locally. Required a second `kfix` commit to replace with full constant `instance_double(Appydave::Tools::Configuration::Models::BrandsConfig)`. Ubuntu CI is stricter about constant resolution in instance_doubles.
|
|
43
|
+
|
|
44
|
+
3. **ENV['BRAND_PATH'] is dead code.** The 10 `ENV['BRAND_PATH'] =` assignments in bin/dam (8 new from B035, 2 pre-existing) are never read anywhere in `lib/`. S3Operations receives `brand_path` as a constructor parameter. The ENV assignments preserved the original behaviour faithfully but the env var itself appears unused. Should be investigated and removed in a future cleanup.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Key Learnings — Application
|
|
49
|
+
|
|
50
|
+
1. **`instance_double` string form fails CI on Ubuntu.** Always use full constant form: `instance_double(Fully::Qualified::ClassName)`. The string form passes locally (RSpec doesn't resolve it) but Ubuntu CI enforces constant lookup.
|
|
51
|
+
|
|
52
|
+
2. **`git add .` is the recurring staging bug.** Three campaigns now have had accidental staging from `git add .`. The AGENTS.md pre-commit rule needs to be in a more prominent position — not buried at the top, but repeated immediately before the commit step.
|
|
53
|
+
|
|
54
|
+
3. **`ENV['BRAND_PATH']` may be vestigial.** Check whether any external consumers (config_loader, shell scripts, `.video-tools.env` loading) depend on it before removing. If confirmed unused: clean up the 10 assignments in bin/dam.
|
|
55
|
+
|
|
56
|
+
4. **Read source before writing tests.** B037 avoided writing a Zone.Identifier exclusion to the source (it was already there) because AGENTS.md said to read the source first. Saved one unnecessary commit.
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Key Learnings — Ralph Loop
|
|
61
|
+
|
|
62
|
+
1. **Extend mode is fast when the brief is complete.** The next-round-brief had exact file line numbers, precise changes, and confirmed dependency order. Planning took minutes, not a full session.
|
|
63
|
+
|
|
64
|
+
2. **Wave 3 parallel worked cleanly.** B036 and B037 touched different spec files with no shared state. Both committed independently with no conflicts. The wave 3 parallel pattern is reliable for spec-only work.
|
|
65
|
+
|
|
66
|
+
3. **Quality audit found real things.** ENV dead code finding and the B-grade test gaps (data-value assertions, LocalSyncStatus integration stub) are both actionable. Running audits before assessment is the right order.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Code Quality Audit Findings
|
|
71
|
+
|
|
72
|
+
**Grade: HIGH / Production-ready**
|
|
73
|
+
|
|
74
|
+
- Exception hierarchy correct (`UsageError < DamError < StandardError`)
|
|
75
|
+
- Exception messages user-friendly and actionable with recovery steps
|
|
76
|
+
- ENV['BRAND_PATH'] pattern in VatCLI is consistent across all 8 call sites
|
|
77
|
+
- 0 rubocop offenses
|
|
78
|
+
- **One finding:** `ENV['BRAND_PATH']` set in 10 locations in bin/dam but never read in lib/ — dead code, low risk, cleanup candidate
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Test Quality Audit Findings
|
|
83
|
+
|
|
84
|
+
**Grade: B (80% regression catch rate)**
|
|
85
|
+
|
|
86
|
+
**s3_scan_command_spec — Grade B-:**
|
|
87
|
+
- Manifest file write verified via real I/O ✅
|
|
88
|
+
- Missing manifest raises ConfigurationError ✅
|
|
89
|
+
- Empty S3 results handled gracefully ✅
|
|
90
|
+
- Weakness: data-value assertions only check non-empty, not specific field values
|
|
91
|
+
- Weakness: LocalSyncStatus mocked in scan_single tests — integration gap
|
|
92
|
+
|
|
93
|
+
**local_sync_status_spec — Grade A-:**
|
|
94
|
+
- Zone.Identifier exclusion test is strong (real files, would catch regression) ✅
|
|
95
|
+
- All 4 status transitions tested ✅
|
|
96
|
+
- format method covers all branches ✅
|
|
97
|
+
- Weakness: nested directory traversal not tested; local_file_count = 0 edge case
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Suggestions for Next Campaign
|
|
102
|
+
|
|
103
|
+
1. **Promote to BACKLOG:** `ENV['BRAND_PATH']` dead code cleanup — verify no consumers, then remove 10 assignments from bin/dam (1 work unit, low risk)
|
|
104
|
+
|
|
105
|
+
2. **Promote to BACKLOG:** Strengthen s3_scan_command_spec data-value assertions + remove LocalSyncStatus stub to test integration (could fold into B020 S3Operations split campaign)
|
|
106
|
+
|
|
107
|
+
3. **AGENTS.md update for next campaign:** Add `instance_double` rule ("always use full constant, never string form"). Move pre-commit `git status` check to a repeated callout immediately before commit instructions.
|
|
108
|
+
|
|
109
|
+
4. **Next logical work:** B007 (parallel git/S3 status checks) and B020 (split S3Operations) are now unblocked — library boundaries are clean.
|
data/package.json
CHANGED
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.
|
|
4
|
+
version: 0.76.12
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cruwys
|
|
@@ -300,6 +300,8 @@ files:
|
|
|
300
300
|
- docs/planning/bugfix-and-security/AGENTS.md
|
|
301
301
|
- docs/planning/bugfix-and-security/IMPLEMENTATION_PLAN.md
|
|
302
302
|
- docs/planning/bugfix-and-security/assessment.md
|
|
303
|
+
- docs/planning/env-dead-code-cleanup/AGENTS.md
|
|
304
|
+
- docs/planning/env-dead-code-cleanup/IMPLEMENTATION_PLAN.md
|
|
303
305
|
- docs/planning/extract-vat-cli/AGENTS.md
|
|
304
306
|
- docs/planning/extract-vat-cli/IMPLEMENTATION_PLAN.md
|
|
305
307
|
- docs/planning/extract-vat-cli/assessment.md
|
|
@@ -312,6 +314,7 @@ files:
|
|
|
312
314
|
- docs/planning/fr2-gpt-context-help/assessment.md
|
|
313
315
|
- docs/planning/library-boundary-cleanup/AGENTS.md
|
|
314
316
|
- docs/planning/library-boundary-cleanup/IMPLEMENTATION_PLAN.md
|
|
317
|
+
- docs/planning/library-boundary-cleanup/assessment.md
|
|
315
318
|
- docs/planning/micro-cleanup/AGENTS.md
|
|
316
319
|
- docs/planning/micro-cleanup/IMPLEMENTATION_PLAN.md
|
|
317
320
|
- docs/planning/micro-cleanup/assessment.md
|