appydave-tools 0.76.2 → 0.76.4

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e0809dc40e0f4940381134c70a57833d755df47f01f8e327a04b278e4d87c5a
4
- data.tar.gz: a1aa1d00b87481b371edda22ed5f7f0fa63a895358002cbc330b4d4e8cbf1ae8
3
+ metadata.gz: 63d45ba7b83fca823b63a907473c424701e50c117ccac57cccdc1d31f2ae277c
4
+ data.tar.gz: 1dff3941a4d00ecc51b84b5b955c7640c955ee0037f52040e4469f5d9b007c4f
5
5
  SHA512:
6
- metadata.gz: 8ef02094f475fc3df1b6b346158dce9596cbc4898c4a5da60e573ae48ddb8ff10663d2b19be0da582adea9b47597a14926e7e55358d33e742762d8cf7b53bf6f
7
- data.tar.gz: 1c96b7e36178f5f0ec3426934a88686fb23e19d890858c1825264bb3a33e67d6054ed520cd4157ff60906f468a91cd25d2c319696b6a1ae936baaca8a013f627
6
+ metadata.gz: fa0a3525cae67422cde5aa4cc880362fbeb24b6ee5d914ece224965daa07ce61878da662aec431edf3c10d9feae53cc8ec3e383bc10fa6c8267f92ade321a8ff
7
+ data.tar.gz: d36d104f67799d434b592effa0e6a029b92ec1e1005216c68269ea0637f67c5fdd2867505c42b900f497d16218a425f480503c6d18cffc6afc3d64b3c9313774
data/CHANGELOG.md CHANGED
@@ -1,3 +1,22 @@
1
+ ## [0.76.3](https://github.com/appydave/appydave-tools/compare/v0.76.2...v0.76.3) (2026-03-19)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add field isolation assertions to update_spec non-updated fields ([da678f6](https://github.com/appydave/appydave-tools/commit/da678f68f5ff0384020639069b459d98e0558968))
7
+
8
+ ## [0.76.2](https://github.com/appydave/appydave-tools/compare/v0.76.1...v0.76.2) (2026-03-19)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * add dedicated specs for Jump Commands layer ([8eec40c](https://github.com/appydave/appydave-tools/commit/8eec40cb60b08b1ca7901f288cff8c9a70783fe2))
14
+ * add determine_range edge cases and fix stale comment ([6e97390](https://github.com/appydave/appydave-tools/commit/6e97390e135ac452a364bfac45fcbc4679b5a26d))
15
+ * add functional CLI tests for -i -e -f -o flags to gpt_context cli_spec ([feed9c7](https://github.com/appydave/appydave-tools/commit/feed9c70abfbec83c6bdb0fcba45fce0ec528657))
16
+ * fix no-args cli spec assertion to avoid false positive on Linux clipboard error ([a50b68e](https://github.com/appydave/appydave-tools/commit/a50b68ea57e2d989b35da2c5f1172181cf825438))
17
+ * fix no-args clipboard assertion to avoid false failure from clipboard gem warning on Linux CI ([197b9de](https://github.com/appydave/appydave-tools/commit/197b9dea84fc12c14b03c39333593f430542228a))
18
+ * strengthen gpt_context no-args spec to verify collection does not proceed ([972d617](https://github.com/appydave/appydave-tools/commit/972d617b2241326a6b4beca53d520ebcb1051530))
19
+
1
20
  ## [0.76.1](https://github.com/appydave/appydave-tools/compare/v0.76.0...v0.76.1) (2026-03-19)
2
21
 
3
22
 
data/README.md CHANGED
@@ -43,7 +43,6 @@ ad_config -c
43
43
  This creates empty configuration files at `~/.config/appydave/`:
44
44
  - `settings.json` - Paths and preferences
45
45
  - `channels.json` - YouTube channel definitions
46
- - `youtube-automation.json` - Automation workflows
47
46
 
48
47
  **2. Option A: Copy example files**
49
48
 
@@ -276,38 +275,6 @@ prompt_tools completion -f prompt_template.md -k topic=Ruby,style=tutorial -c
276
275
 
277
276
  ---
278
277
 
279
- ### ⚡ YouTube Automation *(Internal/Experimental)*
280
-
281
- **The problem:** Video content creation workflows involve multiple steps: research → scripting → production.
282
-
283
- **The solution:** Run predefined prompt sequences against OpenAI API to automate research and content generation steps.
284
-
285
- ```bash
286
- # Run automation sequence (requires configuration)
287
- youtube_automation -s 01-1
288
-
289
- # With debug output
290
- youtube_automation -s 01-1 -d
291
- ```
292
-
293
- **What it does:**
294
- - Loads sequence configuration from `~/.config/appydave/youtube_automation.json`
295
- - Reads prompt templates from Dropbox (`_common/raw_prompts/`)
296
- - Executes OpenAI API calls for each sequence step
297
- - Saves responses to output files
298
-
299
- **Configuration required:**
300
- - Sequence definitions in `youtube_automation.json`
301
- - Prompt template files in configured Dropbox path
302
- - `OPENAI_ACCESS_TOKEN` environment variable
303
-
304
- **Current status:** ⚠️ **Internal tool** - Hardcoded Dropbox paths, uses deprecated Completion API, not documented for external use.
305
-
306
- **Relationship to other tools:** This is separate from **Move Images** tool (which organizes downloaded images into video project asset folders).
307
-
308
- **Use cases:** Automated content research, script outline generation, multi-step prompt workflows.
309
-
310
- ---
311
278
 
312
279
  ### ⚙️ Configuration Manager
313
280
 
@@ -338,7 +305,6 @@ ad_config -p
338
305
  |------|---------|-------------------------|
339
306
  | `settings.json` | Paths and preferences (video-projects-root, download folders, etc.) | ✅ Yes (after removing personal paths) |
340
307
  | `channels.json` | YouTube channel definitions (code, name, youtube_handle, locations) | ✅ Yes (share structure, customize paths locally) |
341
- | `youtube_automation.json` | Automation workflow configurations | ✅ Yes (if no sensitive data) |
342
308
  | `.env` | **Secrets and API keys** | ❌ **NEVER** (gitignored) |
343
309
 
344
310
  **Key Settings:**
@@ -1,30 +1,20 @@
1
1
  # Project Backlog — AppyDave Tools
2
2
 
3
- **Last updated**: 2026-03-19 (bugfix-and-security assessment + 4 new items from quality audit)
4
- **Total**: 27 | Pending: 17 | Done: 10 | Deferred: 0 | Rejected: 0
3
+ **Last updated**: 2026-03-19 (final-test-gaps campaign complete; B031/B032/B033 added from quality audit)
4
+ **Total**: 33 | Pending: 11 | Done: 22 | Deferred: 0 | Rejected: 0
5
5
 
6
6
  ---
7
7
 
8
8
  ## Pending
9
9
 
10
- ### High Priority
11
- - [ ] B024 — Tests: add configure_ssl_options unit tests to s3_operations_spec + share_operations_spec (protects B017 security fix) | Priority: high
12
- - [ ] B015 — BUG-2: FileCollector uses FileUtils.cd without ensure (process dir not restored on exception) | Priority: high
13
- - [x] B006 — BUG-1: Jump CLI get/remove key lookup | Completed: verified fixed 2026-03-19, regression spec added
14
-
15
10
  ### Medium Priority
16
- - [ ] B022 — Tests: expand cli_spec.rb with functional tests (-i, -e, -f, -o flags, exit codes) | Priority: medium
17
- - [ ] B026 — Tests: add determine_range edge cases (b00, b9, a40) to sync_from_ssd_spec + manifest_generator_spec | Priority: medium
18
- - [ ] B027 — Tests: strengthen gpt_context no-args spec to verify file collection actually stops | Priority: medium
19
- - [ ] B023 — Tests: add file_collector_spec coverage for JSON format, aider format, error paths | Priority: medium
20
- - [ ] B018 — Tests: add specs for Jump Commands::Remove, Commands::Add, Commands::Update | Priority: medium
21
- - [ ] B019 — Fix: remove debug puts @working_directory from gpt_context/file_collector.rb | Priority: medium
22
11
  - [ ] B001 — FR-1: GPT Context token counting | Priority: medium
23
12
  - [ ] B012 — Arch: add integration tests for brand resolution end-to-end | Priority: medium
24
13
 
25
- - [ ] B025 — Fix: stale comment in sync_from_ssd.rb line 173 (says 60-69, should say b50-b99) | Priority: low
26
-
27
14
  ### Low Priority
15
+ - [ ] B031 — Tests: add_spec.rb assert `type` field in location data integrity test | Priority: low
16
+ - [ ] B032 — Tests: cli_spec.rb add subprocess test for `-f json` flag | Priority: low
17
+ - [ ] B033 — Fix: file_collector.rb line 19 return `''` directly when working_directory doesn't exist | Priority: low
28
18
  - [ ] B007 — Performance: parallel git/S3 status checks for dam list | Priority: low
29
19
  - [ ] B008 — Performance: cache git/S3 status with 5-min TTL | Priority: low
30
20
  - [ ] B009 — UX: progress indicators for dam operations > 5s | Priority: low
@@ -45,6 +35,19 @@
45
35
  - [x] B016 — BUG-3: ManifestGenerator + SyncFromSsd incompatible SSD range strings | Completed: bugfix-and-security (2026-03-19)
46
36
  - [x] B017 — Security: ssl_verify_peer disabled unconditionally in S3Operations + ShareOperations + S3Scanner | Completed: bugfix-and-security (2026-03-19)
47
37
  - [x] B021 — Fix: gpt_context no-args guard had dead format.nil? condition | Completed: bugfix-and-security (2026-03-19)
38
+ - [x] B024 — Tests: configure_ssl_options unit tests (protects B017 fix) | Completed: test-coverage-gaps (2026-03-19)
39
+ - [x] B022 — Tests: functional cli_spec tests for -i -e -f -o flags | Completed: test-coverage-gaps (2026-03-19)
40
+ - [x] B026 — Tests: determine_range edge cases (b00, b9, a40) | Completed: test-coverage-gaps (2026-03-19)
41
+ - [x] B027 — Tests: gpt_context no-args spec verifies collection stops | Completed: test-coverage-gaps (2026-03-19)
42
+ - [x] B025 — Fix: stale comment sync_from_ssd.rb:173 | Completed: test-coverage-gaps (2026-03-19)
43
+ - [x] B018 — Tests: Jump Commands::Remove, Add, Update specs | Completed: test-coverage-gaps (2026-03-19)
44
+ - [x] B015 — BUG-2: FileCollector FileUtils.cd without ensure | Completed: already fixed in commit 13d5f87; closed without campaign 2026-03-19
45
+ - [x] B019 — Fix: remove debug puts @working_directory from file_collector.rb | Completed: already removed prior to test-coverage-gaps campaign; closed without campaign 2026-03-19
46
+ - [x] B006 — BUG-1: Jump CLI get/remove key lookup | Completed: verified fixed 2026-03-19, regression spec added
47
+ - [x] B023 — Tests: file_collector_spec json/aider/error path coverage | Completed: final-test-gaps (2026-03-19)
48
+ - [x] B028 — Tests: cli_spec file body content assertions in -i/-e tests | Completed: final-test-gaps (2026-03-19)
49
+ - [x] B029 — Tests: add_spec validate all returned location data fields | Completed: final-test-gaps (2026-03-19)
50
+ - [x] B030 — Tests: update_spec verify non-updated fields unchanged | Completed: final-test-gaps (2026-03-19)
48
51
 
49
52
  ---
50
53
 
@@ -64,40 +67,6 @@
64
67
 
65
68
  ---
66
69
 
67
- ### B002 — FR-2: GPT Context AI-Friendly Help System
68
-
69
- **Spec:** `docs/specs/fr-002-gpt-context-help-system.md`
70
-
71
- **User Story**: As an AI agent using GPT Context via skills, I want structured, comprehensive help output so I can understand all options and use the tool correctly.
72
-
73
- **Notes:** Full spec exists. High priority — enables AI skill integration.
74
-
75
- ---
76
-
77
- ### B006 — BUG-1: Jump CLI get/remove Key Lookup Bug
78
-
79
- **Priority:** High — but verify live first
80
-
81
- **⚠️ Three-lens audit (2026-03-19) found:** Static analysis of `Jump::Config#find`, `Config#remove`, and `Search#get` shows correct dual-key guards. Bug may be environmental (stale config file format) or already fixed in a prior commit. **Run `bin/jump.rb get <key>` live before writing any code.**
82
-
83
- **Steps to Reproduce:**
84
- ```bash
85
- bin/jump.rb search awb-team # ✅ finds entry
86
- bin/jump.rb get awb-team # ❌ "Location not found" ← confirm this still fails
87
- bin/jump.rb remove test-minimal --force # ❌ "No locations found."
88
- ```
89
-
90
- **If bug confirmed:** Failure site is in `Jump::Config#find` (`loc.key == key`) or the memoization of `@locations` — NOT in `name_manager/`. The `Commands::Remove#run` → `config.find(key)` → `locations.find { |loc| loc.key == key }` path is the call chain to trace.
91
-
92
- **Acceptance Criteria:**
93
- - [ ] Confirm bug still exists live (if not, write regression spec and close)
94
- - [ ] `get <key>` finds entry when `search <key>` finds it
95
- - [ ] `remove <key>` finds entry when `search <key>` finds it
96
- - [ ] Regression tests for key lookup consistency
97
- - [ ] Root cause documented in commit message
98
-
99
- ---
100
-
101
70
  ### B007 — Performance: Parallel git/S3 Status Checks
102
71
 
103
72
  **Context:** `dam list appydave` with 13 projects takes ~26s (sequential git+S3 check per project).
@@ -146,47 +115,6 @@ bin/jump.rb remove test-minimal --force # ❌ "No locations found."
146
115
 
147
116
  ---
148
117
 
149
- ### B015 — BUG-2: FileCollector FileUtils.cd Without ensure
150
-
151
- **Context:** `lib/appydave/tools/gpt_context/file_collector.rb` line 20 calls `FileUtils.cd(@working_directory)`. If an exception fires inside `build`, the process working directory is never restored to `Dir.home`. Affects any subsequent operation in the same process.
152
- **Fix:** Wrap in block form: `FileUtils.cd(@working_directory) { ... }` — Ruby handles restore automatically. Or add `ensure FileUtils.cd(Dir.home)`.
153
- **Blocker for:** FR-2 — fix this before adding more code paths to `file_collector.rb`.
154
- **Source:** Code quality audit 2026-03-19, MAJOR issue #2.
155
-
156
- ---
157
-
158
- ### B016 — BUG-3: ManifestGenerator vs SyncFromSsd Incompatible Range Strings
159
-
160
- **Context:** `ManifestGenerator.determine_range('b65')` returns `"b50-b99"`. `SyncFromSsd.determine_range('b65')` returns `"60-69"`. Both are used to construct SSD archive folder paths. Projects archived via SSD sync won't be found by the manifest generator, and vice versa. A `find_ssd_project_path` fallback scan may paper over this in practice.
161
- **Fix:** Standardise both methods on one format. Decide which format matches actual SSD folder structure on disk, then update the other method to match.
162
- **Source:** Code quality audit 2026-03-19, MAJOR issue #1.
163
-
164
- ---
165
-
166
- ### B017 — Security: ssl_verify_peer Disabled in S3Operations + ShareOperations
167
-
168
- **Context:** `lib/appydave/tools/dam/s3_operations.rb` lines 110-113 and `share_operations.rb` lines 97-100 set `ssl_verify_peer: false` unconditionally. Comment claims "safe for AWS S3" — this is incorrect. Disabling peer verification removes MITM protection on all S3 operations including AWS credential transmission.
169
- **Fix:** Remove the `ssl_verify_peer: false` override entirely. AWS SDK handles SSL correctly by default. If there was a historical reason (corporate proxy, dev cert issue), document it and scope to `ENV['AWS_SKIP_SSL'] == 'true'` only.
170
- **Source:** Code quality audit 2026-03-19, MAJOR issue #3.
171
-
172
- ---
173
-
174
- ### B018 — Tests: Jump Commands Layer Has No Dedicated Specs
175
-
176
- **Context:** `Commands::Remove`, `Commands::Add`, `Commands::Update` have zero unit specs. The CLI spec only tests auto-regenerate side effects. `--force` guard, error codes, suggestion-on-not-found logic, and key nil-handling in these commands are entirely untested.
177
- **Fix:** Add `spec/appydave/tools/jump/commands/remove_spec.rb`, `add_spec.rb`, `update_spec.rb`. Use `JumpTestLocations` factory + `with jump filesystem` context.
178
- **Source:** Test quality audit 2026-03-19, RISK-1.
179
-
180
- ---
181
-
182
- ### B019 — Fix: Remove Debug puts From file_collector.rb
183
-
184
- **Context:** `lib/appydave/tools/gpt_context/file_collector.rb` line 15: `puts @working_directory`. Prints working directory on every `gpt_context` invocation. Pollutes captured output. Must be removed before FR-2 adds help system output.
185
- **Fix:** Delete line 15.
186
- **Source:** Code quality audit 2026-03-19, MINOR issue #4.
187
-
188
- ---
189
-
190
118
  ### B020 — Arch: Split S3Operations (1,030 lines)
191
119
 
192
120
  **Context:** `S3Operations` handles upload, download, status, cleanup, archive to SSD, MD5 comparison, content type detection, file formatting, and time formatting — all in one class with direct `puts` throughout. No result objects returned from upload/download/cleanup (void methods with side effects).
@@ -0,0 +1,333 @@
1
+ # AGENTS.md — final-test-gaps
2
+
3
+ > Inherited from test-coverage-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:** Test-only gap closure. No lib/ production code changes.
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/gpt_context/file_collector_spec.rb
24
+ bundle exec rspec spec/appydave/tools/gpt_context/cli_spec.rb
25
+ bundle exec rspec spec/appydave/tools/jump/commands/add_spec.rb
26
+ bundle exec rspec spec/appydave/tools/jump/commands/update_spec.rb
27
+ bundle exec rubocop --format clang
28
+ ```
29
+
30
+ **Baseline:** 817 examples, 0 failures, 85.61% line coverage
31
+
32
+ ---
33
+
34
+ ## Directory Structure
35
+
36
+ ```
37
+ lib/appydave/tools/gpt_context/
38
+ file_collector.rb READ ONLY — formats: content, tree, json, aider
39
+ options.rb READ ONLY — Struct with: include_patterns, exclude_patterns,
40
+ format, line_limit, debug, output_target,
41
+ working_directory, prompt (all keyword_init)
42
+
43
+ spec/appydave/tools/gpt_context/
44
+ file_collector_spec.rb ADD json format, aider format, error path tests
45
+ cli_spec.rb ADD body content assertions to -i and -e describe blocks
46
+
47
+ spec/appydave/tools/jump/commands/
48
+ add_spec.rb ADD location data integrity assertions (path, jump, tags, description)
49
+ update_spec.rb ADD field isolation assertions (non-updated fields unchanged)
50
+ ```
51
+
52
+ ---
53
+
54
+ ## Work Unit Details
55
+
56
+ ---
57
+
58
+ ### fix-b023 — file_collector_spec: json, aider, error paths
59
+
60
+ **Read first:** `lib/appydave/tools/gpt_context/file_collector.rb` and
61
+ `spec/appydave/tools/gpt_context/file_collector_spec.rb`
62
+
63
+ **What `build_json` produces:**
64
+ ```ruby
65
+ {
66
+ 'tree' => {}, # nested hash matching tree structure
67
+ 'content' => [ # array of hashes, one per file
68
+ { 'file' => 'path/to/file.txt', 'content' => '...' }
69
+ ]
70
+ }
71
+ ```
72
+ Returns `JSON.pretty_generate(json_output)` — a valid JSON string.
73
+
74
+ **What `build_aider` produces:**
75
+ - With `prompt` set: `aider --message "my prompt" path/to/file1.rb path/to/file2.rb`
76
+ - Without `prompt` (nil): returns `''`
77
+
78
+ **Add these describe blocks to file_collector_spec.rb:**
79
+
80
+ ```ruby
81
+ describe '#build with json format' do
82
+ let(:format) { 'json' }
83
+ let(:include_patterns) { ['**/*.txt'] }
84
+ let(:exclude_patterns) { [] }
85
+
86
+ it 'returns valid JSON' do
87
+ result = subject.build
88
+ expect { JSON.parse(result) }.not_to raise_error
89
+ end
90
+
91
+ it 'includes a tree key in the JSON output' do
92
+ result = JSON.parse(subject.build)
93
+ expect(result).to have_key('tree')
94
+ end
95
+
96
+ it 'includes a content key in the JSON output' do
97
+ result = JSON.parse(subject.build)
98
+ expect(result).to have_key('content')
99
+ end
100
+
101
+ it 'includes file paths and content in the content array' do
102
+ result = JSON.parse(subject.build)
103
+ files = result['content'].map { |f| f['file'] }
104
+ expect(files).to include('included/file1.txt')
105
+
106
+ entry = result['content'].find { |f| f['file'] == 'included/file1.txt' }
107
+ expect(entry['content']).to include('File 1 content')
108
+ end
109
+
110
+ it 'excludes files matching exclude patterns from content' do
111
+ result = JSON.parse(subject.build)
112
+ files = result['content'].map { |f| f['file'] }
113
+ expect(files).not_to include('excluded/excluded_file.txt')
114
+ end
115
+ end
116
+
117
+ describe '#build with aider format' do
118
+ let(:format) { 'aider' }
119
+ let(:include_patterns) { ['**/*.txt'] }
120
+ let(:exclude_patterns) { [] }
121
+
122
+ context 'when prompt is set' do
123
+ let(:options) do
124
+ Appydave::Tools::GptContext::Options.new(
125
+ include_patterns: include_patterns,
126
+ exclude_patterns: exclude_patterns,
127
+ format: format,
128
+ line_limit: nil,
129
+ working_directory: temp_dir,
130
+ prompt: 'fix the bug'
131
+ )
132
+ end
133
+
134
+ it 'returns an aider command string' do
135
+ expect(subject.build).to start_with('aider --message')
136
+ end
137
+
138
+ it 'includes the prompt in the command' do
139
+ expect(subject.build).to include('fix the bug')
140
+ end
141
+
142
+ it 'includes collected file paths in the command' do
143
+ result = subject.build
144
+ expect(result).to include('included/file1.txt')
145
+ end
146
+ end
147
+
148
+ context 'when prompt is not set' do
149
+ it 'returns an empty string' do
150
+ expect(subject.build).to eq('')
151
+ end
152
+ end
153
+ end
154
+
155
+ describe '#build with nonexistent working directory' do
156
+ let(:options) do
157
+ Appydave::Tools::GptContext::Options.new(
158
+ include_patterns: ['**/*.txt'],
159
+ exclude_patterns: [],
160
+ format: 'content',
161
+ line_limit: nil,
162
+ working_directory: '/tmp/does-not-exist-12345'
163
+ )
164
+ end
165
+
166
+ it 'returns empty string without raising an error' do
167
+ expect { subject.build }.not_to raise_error
168
+ expect(subject.build).to eq('')
169
+ end
170
+ end
171
+ ```
172
+
173
+ **Note:** The existing `before` block creates files under `temp_dir`. The aider context with `prompt` needs its own `let(:options)` that overrides the parent — this is fine in RSpec because the inner let shadows the outer.
174
+
175
+ **Commit:** `kfix "add json, aider, and error path tests to file_collector_spec"`
176
+
177
+ ---
178
+
179
+ ### fix-b028 — cli_spec: add file body content assertions to -i and -e tests
180
+
181
+ **Read first:** `spec/appydave/tools/gpt_context/cli_spec.rb`
182
+
183
+ **The gap:** `-i` tests write known content to temp files but only assert on `# file: test.rb` headers. File body content (`# test content`, `# ruby file`) is never asserted. File truncation or body corruption would pass silently.
184
+
185
+ **Find the `-i include pattern` describe block (lines 43-68). Add body assertions to each existing `it` block:**
186
+
187
+ In the first `-i` example (`'collects files matching the include pattern'`):
188
+ ```ruby
189
+ # After the existing assertion, add:
190
+ expect(File.read(outfile)).to include('# test content')
191
+ ```
192
+
193
+ In the second `-i` example (`'does not include files that do not match the pattern'`):
194
+ ```ruby
195
+ # The file 'test.rb' has content '# ruby file'
196
+ # After the existing assertions, add:
197
+ expect(content).to include('# ruby file')
198
+ expect(content).not_to include('# markdown file')
199
+ ```
200
+
201
+ **Find the `-e exclude pattern` describe block (lines 70-95). Add body assertions:**
202
+
203
+ In the first `-e` example (`'excludes files matching the exclude pattern'`):
204
+ ```ruby
205
+ # 'keep.rb' has content '# keep'
206
+ # After existing assertions, add:
207
+ expect(content).to include('# keep')
208
+ ```
209
+
210
+ In the second `-e` example (`'keeps all files when exclude pattern matches nothing'`):
211
+ ```ruby
212
+ # 'keep.rb' has content '# keep'
213
+ # After existing assertion, add:
214
+ expect(File.read(outfile)).to include('# keep')
215
+ ```
216
+
217
+ **Do NOT modify the `-f`, `-o`, or `no arguments` describe blocks** — those are not in scope.
218
+
219
+ **Commit:** `kfix "add file body content assertions to cli_spec -i and -e tests"`
220
+
221
+ ---
222
+
223
+ ### fix-b029 — add_spec: validate all returned location data fields
224
+
225
+ **Read first:** `spec/appydave/tools/jump/commands/add_spec.rb`
226
+
227
+ **The gap:** The `'returns the created location data'` example (lines 35-41) only asserts `result[:location][:key]`. The path, jump, tags, description are never verified — data corruption or field mapping bugs would pass silently.
228
+
229
+ **Add a new `it` block** in the `'with valid attributes and existing path'` context, immediately after the existing `'returns the created location data'` block:
230
+
231
+ ```ruby
232
+ it 'returns location data matching all input attrs' do
233
+ cmd = described_class.new(config, valid_attrs, path_validator: path_validator)
234
+ result = cmd.run
235
+
236
+ location = result[:location]
237
+ expect(location[:key]).to eq('new-project')
238
+ expect(location[:path]).to eq('~/dev/new-project')
239
+ expect(location[:jump]).to eq('jnew')
240
+ expect(location[:tags]).to eq(%w[ruby])
241
+ expect(location[:description]).to eq('A new project')
242
+ end
243
+ ```
244
+
245
+ **Do NOT modify the existing `'returns the created location data'` example** — add alongside it.
246
+
247
+ **Commit:** `kfix "add data integrity assertions to add_spec returned location data"`
248
+
249
+ ---
250
+
251
+ ### fix-b030 — update_spec: verify non-updated fields remain unchanged
252
+
253
+ **Read first:** `spec/appydave/tools/jump/commands/update_spec.rb`
254
+ **Also read:** `spec/support/jump_test_locations.rb` to get the exact field values for `JumpTestLocations.ad_tools` and `JumpTestLocations.flivideo`
255
+
256
+ **Gap 1:** `'leaves unmodified locations intact'` (lines 48-53) only checks `config.key_exists?('flivideo')`. The flivideo record's fields (path, jump, tags, description) could be corrupted and the test would still pass.
257
+
258
+ **Gap 2:** When updating `ad-tools` description, the key/path/jump/tags of the `ad-tools` record itself are never verified to be unchanged.
259
+
260
+ **Add two new `it` blocks** in the `'when location exists and update is valid'` context:
261
+
262
+ ```ruby
263
+ it 'does not modify non-updated fields on the updated record' do
264
+ original = config.find('ad-tools')
265
+ original_path = original.path
266
+ original_jump = original.jump
267
+ original_tags = original.tags
268
+
269
+ cmd = described_class.new(config, 'ad-tools', { description: 'Changed' }, path_validator: path_validator)
270
+ cmd.run
271
+
272
+ updated = config.find('ad-tools')
273
+ expect(updated.path).to eq(original_path)
274
+ expect(updated.jump).to eq(original_jump)
275
+ expect(updated.tags).to eq(original_tags)
276
+ end
277
+
278
+ it 'does not modify the sibling record fields' do
279
+ original_flivideo = config.find('flivideo')
280
+ original_path = original_flivideo.path
281
+ original_jump = original_flivideo.jump
282
+
283
+ cmd = described_class.new(config, 'ad-tools', { description: 'Changed' }, path_validator: path_validator)
284
+ cmd.run
285
+
286
+ flivideo = config.find('flivideo')
287
+ expect(flivideo.path).to eq(original_path)
288
+ expect(flivideo.jump).to eq(original_jump)
289
+ end
290
+ ```
291
+
292
+ **Do NOT modify existing examples** — add alongside them.
293
+
294
+ **Note:** Read jump_test_locations.rb to understand what fields `JumpTestLocations.flivideo` has before assuming field names.
295
+
296
+ **Commit:** `kfix "add field isolation assertions to update_spec non-updated fields"`
297
+
298
+ ---
299
+
300
+ ## Success Criteria
301
+
302
+ - [ ] `RUBYOPT="-W0" bundle exec rspec` — 817+ examples, 0 failures
303
+ - [ ] `bundle exec rubocop --format clang` — 0 offenses
304
+ - [ ] Line coverage stays ≥ 85.61%
305
+ - [ ] All new `it` blocks use descriptive behaviour names
306
+ - [ ] No `require 'spec_helper'` added (auto-required)
307
+ - [ ] All new spec files start with `# frozen_string_literal: true` (if any new files created)
308
+
309
+ ---
310
+
311
+ ## Anti-Patterns to Avoid
312
+
313
+ - ❌ Do NOT use `$?` — use `$CHILD_STATUS` (rubocop Style/SpecialGlobalVars)
314
+ - ❌ Do NOT modify existing passing examples — add new ones alongside
315
+ - ❌ Do NOT require spec_helper explicitly
316
+ - ❌ Do NOT change production lib/ code
317
+ - ❌ Do NOT use multiple separate `before` blocks on the same context — rubocop RSpec/ScatteredSetup; merge into one
318
+ - ❌ Do NOT assume field names on JumpTestLocations — read the file first
319
+
320
+ ---
321
+
322
+ ## Learnings (inherited from test-coverage-gaps)
323
+
324
+ - **`$CHILD_STATUS` not `$?`** — rubocop Special/GlobalVars cop
325
+ - **`exit` with no code exits 0** — specs asserting no-args exit should expect 0
326
+ - **`options.format` defaults to `'tree,content'`** — never nil
327
+ - **Grep full codebase before writing scope** — actual files may differ from brief
328
+ - **ENV stubbing:** `allow(ENV).to receive(:[]).and_call_original` then targeted override — no climate_control gem
329
+ - **Merge `before` blocks** — multiple separate `before` blocks on same context trigger RSpec/ScatteredSetup
330
+ - **`options.prompt` defaults to nil** — aider format returns `''` when prompt is nil
331
+ - **Parallel wave had zero merge conflicts across 5 agents** — all different files
332
+ - **B023 `build_json`:** returns `JSON.pretty_generate` — must `JSON.parse(result)` before asserting on keys
333
+ - **B028 body assertions:** file content is written in Dir.mktmpdir blocks; check the `File.write` call to know what body text to assert
@@ -0,0 +1,31 @@
1
+ # IMPLEMENTATION_PLAN.md — final-test-gaps
2
+
3
+ **Goal**: Close remaining test quality gaps surfaced by the test-quality-audit: file_collector json/aider/error paths, cli_spec body assertions, add_spec data integrity, update_spec field isolation
4
+ **Started**: 2026-03-19
5
+ **Target**: All 4 work units complete; 817+ examples passing; rubocop clean; no regressions; regression catch rate meaningfully above 55%
6
+
7
+ ## Summary
8
+ - Total: 4 | Complete: 4 | In Progress: 0 | Pending: 0 | Failed: 0
9
+
10
+ ## Pending
11
+
12
+ ## In Progress
13
+
14
+ ## Complete
15
+ - [x] fix-b023 — file_collector_spec: +10 examples (5 json, 4 aider, 1 error path). Key fix: json exclusion test needed `exclude_patterns: ['excluded/**/*']` not `[]`. Nonexistent dir test used non-matching glob to avoid false positives. 830 examples, 85.92% coverage.
16
+ - [x] fix-b028 — cli_spec: +6 body assertions across -i (3) and -e (3) blocks. No new example count (assertions added to existing `it` blocks). 830 examples, v0.76.3 released.
17
+ - [x] fix-b029 — add_spec: +1 example asserting path/jump/tags/description. Confirmed `location.to_h` uses symbol keys and `.compact`. 830 examples.
18
+ - [x] fix-b030 — update_spec: +2 examples (non-updated fields on updated record; sibling record field isolation). 11→13 examples. 830 examples.
19
+
20
+ ## Complete
21
+
22
+ ## Failed / Needs Retry
23
+
24
+ ## Notes & Decisions
25
+ - All 4 work units are independent — parallel wave
26
+ - Test-only campaign: no lib/ production code changes
27
+ - B019 and B015 already fixed in prior commits — closed without campaign
28
+ - B028 scope: -i tests check `# file: test.rb` header but not body; -e tests same gap. Add body content assertions only (do NOT rewrite existing assertions)
29
+ - B029 scope: "returns the created location data" test at line 35-41 of add_spec.rb — extend it to assert path/jump/tags/description. Add as a new 'it' block rather than modifying existing example.
30
+ - B030 scope: two gaps — (1) updated record: non-updated fields stay the same; (2) sibling record: not just key_exists? but fields are identical
31
+ - B023 scope: Options struct has :prompt field (keyword_init). Aider tests need `prompt: 'my prompt'` in options.
@@ -0,0 +1,74 @@
1
+ # Assessment: final-test-gaps
2
+
3
+ **Campaign**: final-test-gaps
4
+ **Date**: 2026-03-19 → 2026-03-19
5
+ **Results**: 4 complete, 0 failed
6
+ **Version shipped**: v0.76.3
7
+ **Quality audit**: code-quality-audit + test-quality-audit run post-campaign
8
+
9
+ ---
10
+
11
+ ## Results Summary
12
+
13
+ | Work Unit | Examples Added | Notes |
14
+ |-----------|---------------|-------|
15
+ | fix-b023 | +10 | file_collector_spec: 5 json + 4 aider + 1 error path. Agent fixed json exclusion test (needed `exclude_patterns: ['excluded/**/*']` not `[]`) |
16
+ | fix-b028 | +0 new examples, +6 assertions | Body content assertions added to existing -i/-e `it` blocks in cli_spec |
17
+ | fix-b029 | +1 | add_spec: location data integrity (path/jump/tags/description) |
18
+ | fix-b030 | +2 | update_spec: non-updated fields on updated record + sibling record isolation |
19
+
20
+ **817 → 830 examples (+13). 85.61% → 85.92% coverage.**
21
+
22
+ ---
23
+
24
+ ## What Worked Well
25
+
26
+ - **B023 agent self-corrected the json exclusion test.** Plan specified `exclude_patterns: []` for the json exclusion test — agent recognised this would not actually test exclusion and changed to `exclude_patterns: ['excluded/**/*']`. Agents reading source before writing improved test quality.
27
+ - **B023 agent handled the nonexistent-dir edge case correctly.** Used a pattern that matches nothing in CWD (`['**/*.nonexistent_xyz_12345']`) to avoid false positives when `build_formats` falls through to current directory.
28
+ - **Parallel wave, zero merge conflicts.** 4 agents, all different files.
29
+ - **Regression catch rate measurably improved.** C (55%) → B (70-75%). All major gaps from the prior audit are closed.
30
+
31
+ ---
32
+
33
+ ## What Didn't Work
34
+
35
+ **Code quality MINOR — `file_collector.rb:19` silent collection from CWD:**
36
+ When `working_directory` doesn't exist, `build_formats` runs without `FileUtils.cd`, meaning `Dir.glob` runs in the current process directory. The spec confirms "returns empty string" only because the test uses a non-matching glob — not because the code guarantees it.
37
+
38
+ **Test gap — `type` field missing from add_spec data integrity test:**
39
+ `valid_attrs` includes `type: 'tool'` but the new B029 integrity test doesn't assert `location[:type]`. Field mapping bug for `type` would still pass silently.
40
+
41
+ **Test gap — no CLI-level test for `-f json` or `-f aider` format flags:**
42
+ These formats are unit-tested in file_collector_spec but not via subprocess in cli_spec. A regression in CLI flag parsing for these formats would pass.
43
+
44
+ ---
45
+
46
+ ## Key Learnings — Application
47
+
48
+ - **`build_formats` fallthrough is a silent failure mode.** When `Dir.exist?` is false, the code returns `build_formats` result — not `''`. The guard at line 19 should probably return `''` directly rather than calling `build_formats` without cd.
49
+ - **`exclude_patterns: []` tests exclusion vacuously.** An empty exclude list means no exclusion test is happening. Always use a real pattern when testing that something is excluded.
50
+ - **`build_aider` embeds unsanitised prompt and file paths.** Prompts with quotes or paths with spaces produce malformed aider command output. Low severity now, worth capturing.
51
+ - **Agent pre-read + source verification pattern is working.** Both b029 and b030 agents read the source files and confirmed field accessor names before writing assertions — zero failures from wrong field names.
52
+
53
+ ---
54
+
55
+ ## New Backlog Items from Quality Audit
56
+
57
+ - **B031** — Tests: add_spec.rb assert `type` field in data integrity test | Priority: low
58
+ - **B032** — Tests: cli_spec.rb add subprocess test for `-f json` flag | Priority: low
59
+ - **B033** — Fix: file_collector.rb line 19 — return `''` directly when working_directory doesn't exist (don't delegate to build_formats) | Priority: low
60
+
61
+ ---
62
+
63
+ ## Suggestions for Next Campaign
64
+
65
+ **Test debt is largely cleared.** The suite is at B grade (70-75% regression catch rate). The remaining gaps (B031/B032/B033) are low severity.
66
+
67
+ **Recommended next move: architectural work.**
68
+
69
+ - **B011** — Extract VatCLI business logic from `bin/dam` (1,600 lines). This is the prerequisite for any parallelism or performance work. 20+ rubocop-disable comments are the symptom.
70
+ - **B020** — Split `S3Operations` (1,030 lines). Required before B007 (parallel S3 checks) can be built cleanly.
71
+
72
+ These are larger than any prior campaign. Recommend scoping carefully — one of the two per campaign, not both. B011 first (it's the CLI entry point and larger structural problem).
73
+
74
+ Or, if David wants a quick win: B031/B032/B033 as a micro-campaign (3 test items, 1 production fix, one wave).
@@ -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,27 @@
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: 0 | In Progress: 3 | Pending: 0 | Failed: 0
9
+
10
+ ## Pending
11
+
12
+ ## In Progress
13
+ - [~] fix-b031 — add_spec: add `type` field assertion to location data integrity test
14
+ - [~] fix-b032 — cli_spec: add subprocess test for `-f json` flag
15
+ - [~] fix-b033 — file_collector.rb: return `''` directly when working_directory doesn't exist (line 19)
16
+
17
+ ## Complete
18
+
19
+ ## Failed / Needs Retry
20
+
21
+ ## Notes & Decisions
22
+ - All 3 work units are independent — parallel wave
23
+ - B033 is a production code change (1 line) — needs a spec update to confirm the behaviour
24
+ - B031 and B032 are test-only
25
+ - B033 fix: change `return build_formats unless` to `return '' unless` on line 19 of file_collector.rb
26
+ - B031 fix: add `expect(location[:type]).to eq('tool')` to the existing 'returns location data matching all input attrs' it block
27
+ - 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,75 @@
1
+ # Assessment: test-coverage-gaps
2
+
3
+ **Campaign**: test-coverage-gaps
4
+ **Date**: 2026-03-19 → 2026-03-19
5
+ **Results**: 5 complete, 0 failed
6
+ **Version shipped**: v0.76.2
7
+ **Quality audit**: code-quality-audit + test-quality-audit run post-campaign
8
+
9
+ ---
10
+
11
+ ## Results Summary
12
+
13
+ | Work Unit | Examples Added | Notes |
14
+ |-----------|---------------|-------|
15
+ | fix-b024-ssl-tests | +6 | configure_ssl_options protected in s3_operations + share_operations |
16
+ | fix-b022-cli-tests | +10 | -i/-e/-f/-o functional tests with real file I/O |
17
+ | fix-b026-b025 | +6 + comment | b00/b9/a40 edge cases; stale comment fixed |
18
+ | fix-b027-noargs | +1 | No-file-collection assertion added |
19
+ | fix-b018-jump | +36 | Remove/Add/Update fully covered + fixed clipboard assertion |
20
+
21
+ **759 → 817 examples (+58). 85.0% → 85.61% coverage.**
22
+
23
+ ---
24
+
25
+ ## What Worked Well
26
+
27
+ - **36 Jump Commands specs landed cleanly.** The accumulated AGENTS.md (JumpTestLocations, `with jump filesystem` context, TestPathValidator) meant agents could write correct specs without scaffolding guidance.
28
+ - **B018 agent fixed the B027 clipboard CI failure.** Unblocked itself and the other agents.
29
+ - **ENV stubbing pattern worked without climate_control.** `allow(ENV).to receive(:[]).and_call_original` + targeted override — captured in AGENTS.md.
30
+ - **Parallel wave had zero merge conflicts.** 5 agents, all different files, clean.
31
+
32
+ ---
33
+
34
+ ## What Didn't Work
35
+
36
+ **Test quality is C overall (test audit finding).**
37
+
38
+ Specific gaps the audit surfaced:
39
+ - **cli_spec.rb (-i/-o tests):** Assert `# file:` header present but never check file body content. File truncation or body corruption would not be caught.
40
+ - **add_spec.rb:** After a successful add, only checks `key_exists?` — never validates returned location data matches input attrs (key, path, jump, tags).
41
+ - **update_spec.rb:** Tests verify the updated field changed but never verify other fields were NOT changed.
42
+ - **s3_operations_spec.rb:** Some output format checks use soft regex.
43
+
44
+ Regression catch rate: ~55%. Would catch code path breaks and guard logic. Would miss data integrity and content corruption.
45
+
46
+ ---
47
+
48
+ ## Key Learnings — Application
49
+
50
+ - **B015 is already fixed.** BACKLOG.md lists B015 as pending but file_collector.rb already uses block form `FileUtils.cd(@working_directory) { build_formats }` from commit 13d5f87. Close it.
51
+ - **`allow(ENV).to receive(:[]).and_call_original`** is the correct ENV stub pattern when climate_control is absent. Must call `and_call_original` first, then override specific key.
52
+ - **Merge `before` blocks** to avoid `RSpec/ScatteredSetup` — multiple separate `before` blocks on same context trigger the cop.
53
+ - **Jump Commands layer is now tested.** base.rb/generate.rb/validate.rb already had specs; Remove/Add/Update are now covered.
54
+
55
+ ---
56
+
57
+ ## New Backlog Items from Quality Audit
58
+
59
+ - **B028** — Tests: cli_spec.rb add file body content assertions to -i/-o tests | Priority: medium
60
+ - **B029** — Tests: add_spec.rb validate returned location data matches input attrs exactly | Priority: medium
61
+ - **B030** — Tests: update_spec.rb verify non-updated fields remain unchanged | Priority: low
62
+
63
+ ---
64
+
65
+ ## Suggestions for Next Campaign
66
+
67
+ **B015 should be closed immediately** — the fix is already in the code. Update BACKLOG.md, don't plan a campaign for it.
68
+
69
+ Next meaningful work:
70
+ 1. **B023** — file_collector_spec: JSON, aider, error paths (last test-coverage gap)
71
+ 2. **B028** — cli_spec file body assertions (from this audit)
72
+ 3. **B029** — add_spec data integrity assertions
73
+ 4. These are small — could bundle into one campaign with B030
74
+
75
+ Or pivot to **architectural** items (B011 — extract VatCLI, B020 — split S3Operations) which are larger but unblock performance work (B007/B008).
@@ -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.2'
5
+ VERSION = '0.76.4'
6
6
  end
7
7
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "appydave-tools",
3
- "version": "0.76.2",
3
+ "version": "0.76.4",
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.2
4
+ version: 0.76.4
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/final-test-gaps/AGENTS.md
304
+ - docs/planning/final-test-gaps/IMPLEMENTATION_PLAN.md
305
+ - docs/planning/final-test-gaps/assessment.md
303
306
  - docs/planning/fr2-gpt-context-help/AGENTS.md
304
307
  - docs/planning/fr2-gpt-context-help/IMPLEMENTATION_PLAN.md
305
308
  - docs/planning/fr2-gpt-context-help/assessment.md
306
- - docs/planning/next-round-brief.md
309
+ - docs/planning/micro-cleanup/AGENTS.md
310
+ - docs/planning/micro-cleanup/IMPLEMENTATION_PLAN.md
307
311
  - docs/planning/test-coverage-gaps/AGENTS.md
308
312
  - docs/planning/test-coverage-gaps/IMPLEMENTATION_PLAN.md
313
+ - docs/planning/test-coverage-gaps/assessment.md
309
314
  - docs/specs/fr-002-gpt-context-help-system.md
310
315
  - docs/specs/fr-003-jump-location-tool.md
311
316
  - docs/specs/zsh-history-tool.md
@@ -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