appydave-tools 0.76.3 → 0.76.5

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,181 @@
1
+ # AGENTS.md — micro-cleanup
2
+
3
+ > Inherited from final-test-gaps AGENTS.md. Self-contained.
4
+ > Last updated: 2026-03-19
5
+
6
+ ---
7
+
8
+ ## Project Overview
9
+
10
+ **What:** Ruby gem providing CLI productivity tools for AppyDave's YouTube content creation workflow.
11
+ **Stack:** Ruby 3.4.2, Bundler 2.6.2, RSpec, RuboCop, semantic-release CI/CD.
12
+ **This campaign:** 2 test additions + 1 production fix (1 line).
13
+ **Commits:** Always use `kfix` — never `git commit`.
14
+
15
+ ---
16
+
17
+ ## Build & Run Commands
18
+
19
+ ```bash
20
+ eval "$(rbenv init -)"
21
+
22
+ RUBYOPT="-W0" bundle exec rspec # All tests
23
+ bundle exec rspec spec/appydave/tools/jump/commands/add_spec.rb
24
+ bundle exec rspec spec/appydave/tools/gpt_context/cli_spec.rb
25
+ bundle exec rspec spec/appydave/tools/gpt_context/file_collector_spec.rb
26
+ bundle exec rubocop --format clang
27
+ ```
28
+
29
+ **Baseline:** 830 examples, 0 failures, 85.92% line coverage
30
+
31
+ ---
32
+
33
+ ## Directory Structure
34
+
35
+ ```
36
+ lib/appydave/tools/gpt_context/
37
+ file_collector.rb LINE 19 — change `return build_formats unless` to `return '' unless`
38
+
39
+ spec/appydave/tools/jump/commands/
40
+ add_spec.rb ADD `type` field to existing data integrity it block
41
+
42
+ spec/appydave/tools/gpt_context/
43
+ cli_spec.rb ADD new it block for `-f json` in the `-f format` describe block
44
+ file_collector_spec.rb UPDATE nonexistent-dir test to confirm empty string (verify still passes)
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Work Unit Details
50
+
51
+ ---
52
+
53
+ ### fix-b031 — add_spec: add type field to data integrity test
54
+
55
+ **Read first:** `spec/appydave/tools/jump/commands/add_spec.rb`
56
+
57
+ **Find the `'returns location data matching all input attrs'` it block** (added in final-test-gaps). It currently asserts: key, path, jump, tags, description.
58
+
59
+ **Add one assertion** to that same it block:
60
+ ```ruby
61
+ expect(location[:type]).to eq('tool')
62
+ ```
63
+
64
+ `valid_attrs` has `type: 'tool'` so this will pass. The `location.to_h` in Location uses `.compact` — since type is set, it will be present.
65
+
66
+ **Do NOT create a new it block** — add the assertion to the existing one.
67
+
68
+ **Run:**
69
+ ```bash
70
+ bundle exec rspec spec/appydave/tools/jump/commands/add_spec.rb
71
+ ```
72
+
73
+ All 15 examples should pass. Then full suite. Then:
74
+ ```bash
75
+ kfix "add type field assertion to add_spec location data integrity test"
76
+ ```
77
+
78
+ ---
79
+
80
+ ### fix-b032 — cli_spec: subprocess test for -f json
81
+
82
+ **Read first:** `spec/appydave/tools/gpt_context/cli_spec.rb` — specifically the `-f format` describe block.
83
+
84
+ **Add a new it block** to the `-f format` describe context:
85
+
86
+ ```ruby
87
+ it 'outputs valid JSON when -f json specified' do
88
+ Dir.mktmpdir do |tmpdir|
89
+ File.write(File.join(tmpdir, 'test.rb'), '# test content')
90
+ outfile = File.join(tmpdir, 'output.txt')
91
+
92
+ `ruby #{script} -i '*.rb' -f json -b #{tmpdir} -o #{outfile} 2>&1`
93
+
94
+ content = File.read(outfile)
95
+ expect { JSON.parse(content) }.not_to raise_error
96
+ parsed = JSON.parse(content)
97
+ expect(parsed).to have_key('tree')
98
+ expect(parsed).to have_key('content')
99
+ end
100
+ end
101
+ ```
102
+
103
+ Note: `JSON` is available in the spec because Ruby stdlib is loaded. No require needed.
104
+
105
+ **Run:**
106
+ ```bash
107
+ bundle exec rspec spec/appydave/tools/gpt_context/cli_spec.rb
108
+ ```
109
+
110
+ Then full suite. Then:
111
+ ```bash
112
+ kfix "add subprocess test for -f json flag to cli_spec"
113
+ ```
114
+
115
+ ---
116
+
117
+ ### fix-b033 — file_collector.rb: fix silent CWD collection
118
+
119
+ **Read first:** `lib/appydave/tools/gpt_context/file_collector.rb` line 19.
120
+
121
+ Current code:
122
+ ```ruby
123
+ return build_formats unless @working_directory && Dir.exist?(@working_directory)
124
+ ```
125
+
126
+ **Change to:**
127
+ ```ruby
128
+ return '' unless @working_directory && Dir.exist?(@working_directory)
129
+ ```
130
+
131
+ This ensures a missing working directory always returns empty string rather than silently collecting files from the current process working directory.
132
+
133
+ **Then verify the existing spec still passes:**
134
+ ```bash
135
+ bundle exec rspec spec/appydave/tools/gpt_context/file_collector_spec.rb
136
+ ```
137
+
138
+ The `'#build with nonexistent working directory'` example already asserts `expect(subject.build).to eq('')` — this should still pass (and now it's guaranteed by the code, not by an accident of the glob pattern).
139
+
140
+ **Run rubocop:**
141
+ ```bash
142
+ bundle exec rubocop lib/appydave/tools/gpt_context/file_collector.rb --format clang
143
+ ```
144
+
145
+ Then full suite. Then:
146
+ ```bash
147
+ kfix "fix file_collector silent collection from CWD when working directory does not exist"
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Success Criteria
153
+
154
+ - [ ] `RUBYOPT="-W0" bundle exec rspec` — 831+ examples, 0 failures
155
+ - [ ] `bundle exec rubocop --format clang` — 0 offenses
156
+ - [ ] Line coverage stays ≥ 85.92%
157
+ - [ ] B031: `type` field asserted in add_spec data integrity test
158
+ - [ ] B032: json format verified via subprocess in cli_spec
159
+ - [ ] B033: `file_collector.rb:19` returns `''` not `build_formats` when dir missing
160
+
161
+ ---
162
+
163
+ ## Anti-Patterns to Avoid
164
+
165
+ - ❌ Do NOT use `$?` — use `$CHILD_STATUS`
166
+ - ❌ Do NOT use `git commit` — use `kfix`
167
+ - ❌ Do NOT add `require 'spec_helper'`
168
+ - ❌ Do NOT add multiple separate `before` blocks on same context (RSpec/ScatteredSetup)
169
+ - ❌ Do NOT create new it blocks for B031 — add assertion to existing block
170
+
171
+ ---
172
+
173
+ ## Learnings (inherited from final-test-gaps)
174
+
175
+ - **`$CHILD_STATUS` not `$?`** — rubocop Style/SpecialGlobalVars cop
176
+ - **`options.format` defaults to `'tree,content'`** — never nil
177
+ - **`options.prompt` defaults to nil** — aider format returns `''` when nil
178
+ - **`location.to_h` uses symbol keys + `.compact`** — nil fields are dropped
179
+ - **Agent pre-read pattern works** — read source files before writing assertions; zero wrong field name failures
180
+ - **Parallel wave, all different files** — no merge conflicts expected
181
+ - **JSON in subprocess test** — `JSON.parse(content)` in subprocess tests — ensure JSON output goes to outfile not stdout; use `-o outfile` flag
@@ -0,0 +1,29 @@
1
+ # IMPLEMENTATION_PLAN.md — micro-cleanup
2
+
3
+ **Goal**: Close 3 small items from the final-test-gaps quality audit: type field assertion (B031), -f json CLI test (B032), file_collector.rb silent-collection fix (B033)
4
+ **Started**: 2026-03-19
5
+ **Target**: All 3 complete; 830+ examples passing; rubocop clean; no regressions
6
+
7
+ ## Summary
8
+ - Total: 3 | Complete: 3 | In Progress: 0 | Pending: 0 | Failed: 0
9
+
10
+ ## Pending
11
+
12
+ ## In Progress
13
+
14
+ ## Complete
15
+ - [x] fix-b031 — already committed in prior pass (commit 8eec40c). Assertion `expect(location[:type]).to eq('tool')` found at add_spec.rb line 51. Closed without action.
16
+ - [x] fix-b033 — already fixed in commit 13d5f87 (`return '' unless` already in place). Closed without action.
17
+ - [x] fix-b032 — added `-f json` subprocess test to cli_spec. 831 examples, 0 failures, v0.76.4. Side issue: kfix accidentally staged pre-existing uncommitted changes to lib/appydave/tools.rb (removed youtube_automation_config require). Fixed in follow-up commit.
18
+
19
+ ## Complete
20
+
21
+ ## Failed / Needs Retry
22
+
23
+ ## Notes & Decisions
24
+ - All 3 work units are independent — parallel wave
25
+ - B033 is a production code change (1 line) — needs a spec update to confirm the behaviour
26
+ - B031 and B032 are test-only
27
+ - B033 fix: change `return build_formats unless` to `return '' unless` on line 19 of file_collector.rb
28
+ - B031 fix: add `expect(location[:type]).to eq('tool')` to the existing 'returns location data matching all input attrs' it block
29
+ - B032 fix: new it block in '-f format' describe context — subprocess with `-f json`, parse output as JSON, assert tree+content keys present
@@ -0,0 +1,68 @@
1
+ # Assessment: micro-cleanup
2
+
3
+ **Campaign**: micro-cleanup
4
+ **Date**: 2026-03-19 → 2026-03-19
5
+ **Results**: 3 complete, 0 failed
6
+ **Version shipped**: v0.76.4
7
+ **Quality audit**: code-quality-audit + test-quality-audit run post-campaign
8
+
9
+ ---
10
+
11
+ ## Results Summary
12
+
13
+ | Work Unit | Action | Notes |
14
+ |-----------|--------|-------|
15
+ | fix-b031 | Already done | `expect(location[:type]).to eq('tool')` found committed in 8eec40c — closed without action |
16
+ | fix-b033 | Already done | `return '' unless` on line 19 found committed in 13d5f87 — closed without action |
17
+ | fix-b032 | +1 example | `-f json` subprocess test added to cli_spec. 831 examples, 0 failures, v0.76.4 |
18
+
19
+ **830 → 831 examples (+1). Coverage stable at ~85.92%.**
20
+
21
+ ---
22
+
23
+ ## What Worked Well
24
+
25
+ - **Agents check before acting.** Both B031 and B033 agents read the files, found the work already done, and correctly closed without creating duplicate commits. No false-positive churn.
26
+ - **B032 json test is clean.** `Dir.mktmpdir` + subprocess + `JSON.parse` + key assertions — follows the established cli_spec pattern exactly.
27
+ - **CI caught the staging error immediately.** The accidental require removal was detected by CI on the first push — the safety net worked as intended.
28
+
29
+ ---
30
+
31
+ ## What Didn't Work
32
+
33
+ **kfix staged pre-existing uncommitted changes.**
34
+
35
+ The B032 agent's `kfix` commit accidentally included local changes to `lib/appydave/tools.rb` that deleted `require 'appydave/tools/configuration/models/youtube_automation_config'` and related lines. These were pre-existing uncommitted modifications floating in the working tree — unrelated to fix-b032. CI failed. A follow-up commit restored the requires and CI passed.
36
+
37
+ **Root cause:** A prior session left the working tree in a dirty state. The agent did not run `git status` before committing, so it didn't catch the unintended changes in the staging area.
38
+
39
+ ---
40
+
41
+ ## Key Learnings — Application
42
+
43
+ - **Run `git status` before `kfix`.** Agents must check what's actually staged before committing. If unexpected files appear, abort and investigate. Add this to AGENTS.md as a mandatory pre-commit step.
44
+ - **kfix commits everything staged** — it does not limit itself to files the agent touched. A dirty working tree is a silent risk on every campaign.
45
+ - **B033 and B031 were already closed by prior agents.** This confirms the prior campaign agents were doing thorough work — they fixed things beyond their assigned scope. Good behaviour, but worth tracking so plans don't redundantly assign already-done work.
46
+
47
+ ---
48
+
49
+ ## New Backlog Items
50
+
51
+ None. The quality audit found no new gaps. Suite is at B+ for GptContext CLI, B overall.
52
+
53
+ ---
54
+
55
+ ## Suggestions for Next Campaign
56
+
57
+ **Start B011 — extract VatCLI from bin/dam.**
58
+
59
+ The test suite is at B grade (75-80% regression catch rate). The production code is clean. The CI pipeline is reliable. All prerequisites for architectural work are met.
60
+
61
+ **Pre-campaign mandatory steps for B011:**
62
+ 1. Run `git status` — confirm working tree is clean before launching agents
63
+ 2. Read `bin/dam` in full before writing AGENTS.md — 1,600 lines, surprises expected
64
+ 3. Run rubocop on bin/dam to count current offenses (20+ rubocop-disable comments)
65
+ 4. Baseline: 831 examples, 0 failures — confirm before starting
66
+
67
+ **Add to AGENTS.md for B011:**
68
+ > Before running `kfix`, always run `git status` and confirm only the expected files appear in the staged/unstaged list. If unexpected files appear, run `git diff` to investigate before committing.
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Appydave
4
+ module Tools
5
+ module Dam
6
+ # Enriches S3 scan project data with local s3-staging sync status
7
+ module LocalSyncStatus
8
+ module_function
9
+
10
+ # Mutates matched_projects hash to add :local_status and :local_file_count keys
11
+ # @param matched_projects [Hash] Map of project_id => S3 data hash
12
+ # @param brand_key [String] Brand key (e.g., 'appydave')
13
+ def enrich!(matched_projects, brand_key)
14
+ matched_projects.each do |project_id, data|
15
+ project_path = Appydave::Tools::Dam::Config.project_path(brand_key, project_id)
16
+ s3_staging_path = File.join(project_path, 's3-staging')
17
+
18
+ if !Dir.exist?(project_path)
19
+ data[:local_status] = :no_project # Project directory doesn't exist
20
+ elsif !Dir.exist?(s3_staging_path)
21
+ data[:local_status] = :no_files # Project exists but no downloads yet
22
+ else
23
+ # Count local files in s3-staging
24
+ local_files = Dir.glob(File.join(s3_staging_path, '**', '*'))
25
+ .select { |f| File.file?(f) }
26
+ .reject { |f| File.basename(f).include?('Zone.Identifier') } # Exclude Windows metadata
27
+
28
+ s3_file_count = data[:file_count]
29
+ local_file_count = local_files.size
30
+
31
+ data[:local_status] = if local_file_count.zero?
32
+ :no_files
33
+ elsif local_file_count == s3_file_count
34
+ :synced # Fully synced
35
+ else
36
+ :partial # Some files downloaded
37
+ end
38
+
39
+ data[:local_file_count] = local_file_count
40
+ end
41
+ end
42
+ end
43
+
44
+ # Format local sync status symbol for display
45
+ # @param status [Symbol] :synced, :no_files, :partial, :no_project
46
+ # @param local_count [Integer, nil] Number of local files
47
+ # @param s3_count [Integer] Number of S3 files
48
+ # @return [String] Formatted status string
49
+ def format(status, local_count, s3_count)
50
+ case status
51
+ when :synced
52
+ '✓ Synced'
53
+ when :no_files
54
+ '⚠ None'
55
+ when :partial
56
+ "⚠ #{local_count}/#{s3_count}"
57
+ when :no_project
58
+ '✗ Missing'
59
+ else
60
+ 'Unknown'
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -16,7 +16,7 @@ module Appydave
16
16
  end
17
17
 
18
18
  def build
19
- return build_formats unless @working_directory && Dir.exist?(@working_directory)
19
+ return '' unless @working_directory && Dir.exist?(@working_directory)
20
20
 
21
21
  FileUtils.cd(@working_directory) { build_formats }
22
22
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Appydave
4
4
  module Tools
5
- VERSION = '0.76.3'
5
+ VERSION = '0.76.5'
6
6
  end
7
7
  end
@@ -78,6 +78,7 @@ require 'appydave/tools/dam/ssd_status'
78
78
  require 'appydave/tools/dam/repo_status'
79
79
  require 'appydave/tools/dam/repo_sync'
80
80
  require 'appydave/tools/dam/repo_push'
81
+ require 'appydave/tools/dam/local_sync_status'
81
82
 
82
83
  require 'appydave/tools/jump/path_validator'
83
84
  require 'appydave/tools/jump/location'
@@ -96,8 +97,6 @@ require 'appydave/tools/jump/commands/report'
96
97
  require 'appydave/tools/jump/commands/generate'
97
98
  require 'appydave/tools/jump/cli'
98
99
 
99
- require 'appydave/tools/youtube_automation/gpt_agent'
100
-
101
100
  require 'appydave/tools/youtube_manager/models/youtube_details'
102
101
  require 'appydave/tools/youtube_manager/models/captions'
103
102
  require 'appydave/tools/youtube_manager/youtube_base'
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appydave-tools",
3
- "version": "0.76.3",
3
+ "version": "0.76.5",
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.3
4
+ version: 0.76.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
@@ -300,12 +300,17 @@ 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/extract-vat-cli/AGENTS.md
304
+ - docs/planning/extract-vat-cli/IMPLEMENTATION_PLAN.md
303
305
  - docs/planning/final-test-gaps/AGENTS.md
304
306
  - docs/planning/final-test-gaps/IMPLEMENTATION_PLAN.md
307
+ - docs/planning/final-test-gaps/assessment.md
305
308
  - docs/planning/fr2-gpt-context-help/AGENTS.md
306
309
  - docs/planning/fr2-gpt-context-help/IMPLEMENTATION_PLAN.md
307
310
  - docs/planning/fr2-gpt-context-help/assessment.md
308
- - docs/planning/next-round-brief.md
311
+ - docs/planning/micro-cleanup/AGENTS.md
312
+ - docs/planning/micro-cleanup/IMPLEMENTATION_PLAN.md
313
+ - docs/planning/micro-cleanup/assessment.md
309
314
  - docs/planning/test-coverage-gaps/AGENTS.md
310
315
  - docs/planning/test-coverage-gaps/IMPLEMENTATION_PLAN.md
311
316
  - docs/planning/test-coverage-gaps/assessment.md
@@ -349,6 +354,7 @@ files:
349
354
  - lib/appydave/tools/dam/file_helper.rb
350
355
  - lib/appydave/tools/dam/fuzzy_matcher.rb
351
356
  - lib/appydave/tools/dam/git_helper.rb
357
+ - lib/appydave/tools/dam/local_sync_status.rb
352
358
  - lib/appydave/tools/dam/manifest_generator.rb
353
359
  - lib/appydave/tools/dam/project_listing.rb
354
360
  - lib/appydave/tools/dam/project_resolver.rb
@@ -1,42 +0,0 @@
1
- # Next Round Brief
2
-
3
- **Created:** 2026-03-19
4
- **Updated:** 2026-03-19 (after bugfix-and-security assessment)
5
-
6
- ---
7
-
8
- ## Recommended Next Campaign: test-coverage-gaps
9
-
10
- ### Goal
11
-
12
- Protect the B017 SSL security fix with a regression test, expand functional test coverage across gpt_context CLI and DAM range logic, and add the missing Jump Commands layer specs.
13
-
14
- ### Background
15
-
16
- Quality audit after bugfix-and-security found:
17
-
18
- 1. **B024** — `configure_ssl_options` has zero unit tests. The B017 SSL fix (removing unconditional `ssl_verify_peer: false`) has no regression protection. If reverted, all tests still pass. Must fix.
19
- 2. **B022** — `cli_spec.rb` only tests `--help`, `--version`, no-args. No functional tests for `-i`, `-e`, `-f`, `-o`. Core behaviour untested at CLI level.
20
- 3. **B026** — `determine_range` tests narrow (b40, b65, b99 only). Missing: b00, b9, a40. Both sync_from_ssd_spec and manifest_generator_spec need these.
21
- 4. **B027** — gpt_context no-args spec only checks output string. Does not verify file collection stops.
22
- 5. **B018** — Jump Commands (Remove/Add/Update) — zero dedicated specs.
23
- 6. **B025** — Stale comment sync_from_ssd.rb line 173 (says 60-69, should say b50-b99).
24
-
25
- ### Suggested Work Units (parallel — all test-only except B025)
26
-
27
- 1. **fix-b024-ssl-tests** — Add `configure_ssl_options` unit tests to s3_operations_spec and share_operations_spec. Verify empty hash on default path; `{ssl_verify_peer: false}` when ENV override set. Stub ENV directly (`allow(ENV).to receive(:[]).with('AWS_SDK_RUBY_SKIP_SSL_VERIFICATION').and_return('true')`).
28
- 2. **fix-b022-cli-tests** — Add functional subprocess tests to cli_spec.rb for -i, -e, -f, -o flags. Write to Tempfile, verify content. Use `Dir.mktmpdir` and clean up after.
29
- 3. **fix-b026-b025-range-tests** — Add edge cases (b00, b9, a40) to sync_from_ssd_spec and manifest_generator_spec. Fix stale comment sync_from_ssd.rb line 173 while in the file.
30
- 4. **fix-b027-noargs-test** — Strengthen no-args spec: `expect(Appydave::Tools::GptContext::FileCollector).not_to receive(:new)` when no patterns given.
31
- 5. **fix-b018-jump-specs** — Add spec files for Jump Commands::Remove, Commands::Add, Commands::Update. Read existing Jump CLI spec first for setup pattern. Use JumpTestLocations + `with jump filesystem` context.
32
-
33
- ### Mode Recommendation
34
-
35
- **Extend** — same stack, same patterns, test-only work. Inherit AGENTS.md.
36
-
37
- ### Pre-Campaign Notes
38
-
39
- - Check if `climate_control` gem is in Gemfile before using ClimateControl — use direct ENV stubbing if not available
40
- - For B022 functional tests: subprocess writes to file, assert content includes `# file:` headers
41
- - For B027: stub at the class level, not instance — `expect(described_class).not_to receive(:new)`
42
- - For B018: read `spec/appydave/tools/jump/` existing specs before writing new command specs