appydave-tools 0.76.0 → 0.76.2
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 +21 -0
- data/bin/gpt_context.rb +1 -1
- data/docs/planning/BACKLOG.md +13 -5
- data/docs/planning/bugfix-and-security/AGENTS.md +329 -0
- data/docs/planning/bugfix-and-security/IMPLEMENTATION_PLAN.md +26 -0
- data/docs/planning/bugfix-and-security/assessment.md +94 -0
- data/docs/planning/fr2-gpt-context-help/IMPLEMENTATION_PLAN.md +2 -2
- data/docs/planning/fr2-gpt-context-help/assessment.md +70 -0
- data/docs/planning/next-round-brief.md +23 -36
- data/docs/planning/test-coverage-gaps/AGENTS.md +317 -0
- data/docs/planning/test-coverage-gaps/IMPLEMENTATION_PLAN.md +29 -0
- data/lib/appydave/tools/dam/s3_operations.rb +2 -10
- data/lib/appydave/tools/dam/s3_scanner.rb +1 -2
- data/lib/appydave/tools/dam/share_operations.rb +2 -10
- data/lib/appydave/tools/dam/sync_from_ssd.rb +10 -7
- data/lib/appydave/tools/version.rb +1 -1
- data/package.json +1 -1
- metadata +7 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9e0809dc40e0f4940381134c70a57833d755df47f01f8e327a04b278e4d87c5a
|
|
4
|
+
data.tar.gz: a1aa1d00b87481b371edda22ed5f7f0fa63a895358002cbc330b4d4e8cbf1ae8
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 8ef02094f475fc3df1b6b346158dce9596cbc4898c4a5da60e573ae48ddb8ff10663d2b19be0da582adea9b47597a14926e7e55358d33e742762d8cf7b53bf6f
|
|
7
|
+
data.tar.gz: 1c96b7e36178f5f0ec3426934a88686fb23e19d890858c1825264bb3a33e67d6054ed520cd4157ff60906f468a91cd25d2c319696b6a1ae936baaca8a013f627
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## [0.76.1](https://github.com/appydave/appydave-tools/compare/v0.76.0...v0.76.1) (2026-03-19)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* align SyncFromSsd#determine_range with ManifestGenerator format; add specs ([3f8cb37](https://github.com/appydave/appydave-tools/commit/3f8cb37a78bd3d9720eace21cf1abbbca285cd66))
|
|
7
|
+
* remove unconditional ssl_verify_peer: false from S3 clients; keep env override ([f49efb1](https://github.com/appydave/appydave-tools/commit/f49efb1c4a97ba904f3f3fc7d4292139a5e6c3fd))
|
|
8
|
+
|
|
9
|
+
# [0.76.0](https://github.com/appydave/appydave-tools/compare/v0.75.0...v0.76.0) (2026-03-19)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Bug Fixes
|
|
13
|
+
|
|
14
|
+
* fix pre-existing rubocop offenses in bin/dam and split jump test helpers to avoid OneClassPerFile ([491b980](https://github.com/appydave/appydave-tools/commit/491b980c335b7e3d205a5368cd0a7b96e5b5a82f))
|
|
15
|
+
* remove debug puts and fix unguarded FileUtils.cd in FileCollector; close BUG-1 ([13d5f87](https://github.com/appydave/appydave-tools/commit/13d5f8793d5185cb9795cab86a5270726763c30e))
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* add AI-friendly help system to GPT Context ([c0b8843](https://github.com/appydave/appydave-tools/commit/c0b884323654a248d660ea137712e7c0e5fc172c))
|
|
21
|
+
|
|
1
22
|
# [0.75.0](https://github.com/appydave/appydave-tools/compare/v0.74.1...v0.75.0) (2026-02-08)
|
|
2
23
|
|
|
3
24
|
|
data/bin/gpt_context.rb
CHANGED
|
@@ -112,7 +112,7 @@ OptionParser.new do |opts|
|
|
|
112
112
|
end
|
|
113
113
|
end.parse!
|
|
114
114
|
|
|
115
|
-
if options.include_patterns.empty? && options.exclude_patterns.empty?
|
|
115
|
+
if options.include_patterns.empty? && options.exclude_patterns.empty?
|
|
116
116
|
script_name = File.basename($PROGRAM_NAME, File.extname($PROGRAM_NAME))
|
|
117
117
|
|
|
118
118
|
puts 'No options provided to GPT Context. Please specify patterns to include or exclude.'
|
data/docs/planning/BACKLOG.md
CHANGED
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
# Project Backlog — AppyDave Tools
|
|
2
2
|
|
|
3
|
-
**Last updated**: 2026-03-19 (
|
|
4
|
-
**Total**:
|
|
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
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
8
|
## Pending
|
|
9
9
|
|
|
10
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
|
|
11
12
|
- [ ] B015 — BUG-2: FileCollector uses FileUtils.cd without ensure (process dir not restored on exception) | Priority: high
|
|
12
|
-
- [ ] B016 — BUG-3: ManifestGenerator + SyncFromSsd produce incompatible SSD range strings (data integrity) | Priority: high
|
|
13
|
-
- [ ] B002 — FR-2: GPT Context AI-friendly help system | Priority: high
|
|
14
13
|
- [x] B006 — BUG-1: Jump CLI get/remove key lookup | Completed: verified fixed 2026-03-19, regression spec added
|
|
15
|
-
- [ ] B017 — Security: ssl_verify_peer disabled unconditionally in S3Operations + ShareOperations | Priority: high
|
|
16
14
|
|
|
17
15
|
### 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
|
|
18
20
|
- [ ] B018 — Tests: add specs for Jump Commands::Remove, Commands::Add, Commands::Update | Priority: medium
|
|
19
21
|
- [ ] B019 — Fix: remove debug puts @working_directory from gpt_context/file_collector.rb | Priority: medium
|
|
20
22
|
- [ ] B001 — FR-1: GPT Context token counting | Priority: medium
|
|
21
23
|
- [ ] B012 — Arch: add integration tests for brand resolution end-to-end | Priority: medium
|
|
22
24
|
|
|
25
|
+
- [ ] B025 — Fix: stale comment in sync_from_ssd.rb line 173 (says 60-69, should say b50-b99) | Priority: low
|
|
26
|
+
|
|
23
27
|
### Low Priority
|
|
24
28
|
- [ ] B007 — Performance: parallel git/S3 status checks for dam list | Priority: low
|
|
25
29
|
- [ ] B008 — Performance: cache git/S3 status with 5-min TTL | Priority: low
|
|
@@ -37,6 +41,10 @@
|
|
|
37
41
|
- [x] B005 — NFR-2: Jump Claude Code Skill | Completed: 2025-12-14
|
|
38
42
|
- [x] B013 — Arch: Extract GitHelper module (90 lines duplication) | Completed: dam-enhancement-sprint (Jan 2025)
|
|
39
43
|
- [x] B014 — Arch: Create BrandResolver to centralize brand transformation | Completed: dam-enhancement-sprint (Jan 2025)
|
|
44
|
+
- [x] B002 — FR-2: GPT Context AI-friendly help system | Completed: fr2-gpt-context-help (2026-03-19)
|
|
45
|
+
- [x] B016 — BUG-3: ManifestGenerator + SyncFromSsd incompatible SSD range strings | Completed: bugfix-and-security (2026-03-19)
|
|
46
|
+
- [x] B017 — Security: ssl_verify_peer disabled unconditionally in S3Operations + ShareOperations + S3Scanner | Completed: bugfix-and-security (2026-03-19)
|
|
47
|
+
- [x] B021 — Fix: gpt_context no-args guard had dead format.nil? condition | Completed: bugfix-and-security (2026-03-19)
|
|
40
48
|
|
|
41
49
|
---
|
|
42
50
|
|
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
# AGENTS.md — bugfix-and-security
|
|
2
|
+
|
|
3
|
+
> Inherited from docs/planning/AGENTS.md + fr2-gpt-context-help campaign learnings.
|
|
4
|
+
> Self-contained — you receive only this file + your work unit prompt.
|
|
5
|
+
> Last updated: 2026-03-19
|
|
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
|
+
**This campaign:** 3 independent bug fixes — security (B017), data integrity (B016), dead code (B021).
|
|
14
|
+
**Commits:** Always use `kfeat`/`kfix` — never `git commit`.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Build & Run Commands
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
eval "$(rbenv init -)"
|
|
22
|
+
|
|
23
|
+
# Run all tests
|
|
24
|
+
RUBYOPT="-W0" bundle exec rspec
|
|
25
|
+
|
|
26
|
+
# Run specific spec files
|
|
27
|
+
bundle exec rspec spec/appydave/tools/dam/s3_operations_spec.rb
|
|
28
|
+
bundle exec rspec spec/appydave/tools/dam/sync_from_ssd_spec.rb
|
|
29
|
+
bundle exec rspec spec/appydave/tools/dam/manifest_generator_spec.rb
|
|
30
|
+
bundle exec rspec spec/appydave/tools/gpt_context/cli_spec.rb
|
|
31
|
+
|
|
32
|
+
# Lint
|
|
33
|
+
bundle exec rubocop --format clang
|
|
34
|
+
|
|
35
|
+
# Commit (never use git commit directly)
|
|
36
|
+
kfix "description of what you fixed"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
**Baseline (2026-03-19):** 754 examples, 0 failures, 84.92% line coverage
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Directory Structure
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
lib/appydave/tools/dam/
|
|
47
|
+
s3_operations.rb B017 — configure_ssl_options method (~line 102)
|
|
48
|
+
share_operations.rb B017 — configure_ssl_options method (~line 89)
|
|
49
|
+
s3_scanner.rb B017 — inline ssl_verify_peer in Aws::S3::Client.new (~line 111)
|
|
50
|
+
sync_from_ssd.rb B016 — determine_range method (~line 185)
|
|
51
|
+
manifest_generator.rb B016 — determine_range method (~line 332) — canonical format
|
|
52
|
+
spec/appydave/tools/dam/
|
|
53
|
+
s3_operations_spec.rb Existing spec — do not break
|
|
54
|
+
share_operations_spec.rb Existing spec — do not break
|
|
55
|
+
sync_from_ssd_spec.rb B016 — update determine_range examples (~line 277)
|
|
56
|
+
manifest_generator_spec.rb B016 — add determine_range examples (currently none)
|
|
57
|
+
bin/gpt_context.rb B021 — guard at line 115
|
|
58
|
+
spec/appydave/tools/gpt_context/
|
|
59
|
+
cli_spec.rb B021 — add/update no-args spec
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## Work Unit Details
|
|
65
|
+
|
|
66
|
+
### fix-b017-ssl
|
|
67
|
+
|
|
68
|
+
**Problem:** `ssl_verify_peer: false` is set unconditionally in 3 files, disabling MITM protection on all S3 operations including AWS credential transmission. The comment "safe for AWS S3" is incorrect — HTTPS encryption alone does not protect against a MITM attack without peer verification.
|
|
69
|
+
|
|
70
|
+
**Files to change:**
|
|
71
|
+
|
|
72
|
+
**1. `lib/appydave/tools/dam/s3_operations.rb` (~line 102):**
|
|
73
|
+
```ruby
|
|
74
|
+
# BEFORE:
|
|
75
|
+
def configure_ssl_options
|
|
76
|
+
if ENV['AWS_SDK_RUBY_SKIP_SSL_VERIFICATION'] == 'true'
|
|
77
|
+
puts '⚠️ WARNING: SSL verification is disabled (development mode)'
|
|
78
|
+
return { ssl_verify_peer: false }
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# Disable SSL peer verification to work around OpenSSL 3.4.x CRL checking issues
|
|
82
|
+
# This is safe for AWS S3 connections as we're still using HTTPS (encrypted connection)
|
|
83
|
+
{
|
|
84
|
+
ssl_verify_peer: false
|
|
85
|
+
}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# AFTER:
|
|
89
|
+
def configure_ssl_options
|
|
90
|
+
return { ssl_verify_peer: false } if ENV['AWS_SDK_RUBY_SKIP_SSL_VERIFICATION'] == 'true'
|
|
91
|
+
|
|
92
|
+
{}
|
|
93
|
+
end
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
**2. `lib/appydave/tools/dam/share_operations.rb` (~line 89):**
|
|
97
|
+
Same pattern as s3_operations.rb — same fix.
|
|
98
|
+
|
|
99
|
+
**3. `lib/appydave/tools/dam/s3_scanner.rb` (~line 111):**
|
|
100
|
+
```ruby
|
|
101
|
+
# BEFORE (inline in Aws::S3::Client.new):
|
|
102
|
+
Aws::S3::Client.new(
|
|
103
|
+
credentials: credentials,
|
|
104
|
+
region: brand_info.aws.region,
|
|
105
|
+
http_wire_trace: false,
|
|
106
|
+
ssl_verify_peer: false
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
# AFTER:
|
|
110
|
+
Aws::S3::Client.new(
|
|
111
|
+
credentials: credentials,
|
|
112
|
+
region: brand_info.aws.region,
|
|
113
|
+
http_wire_trace: false
|
|
114
|
+
)
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Commit:** `kfix "remove unconditional ssl_verify_peer: false from S3 clients; keep env override"`
|
|
118
|
+
|
|
119
|
+
**Note on WARNING puts:** The original had `puts '⚠️ WARNING...'` in the env-guard branch. You may keep or remove it — if you keep it, ensure rubocop doesn't flag it (it shouldn't). If RuboCop complains about the `puts`, use `warn` instead.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### fix-b016-range
|
|
124
|
+
|
|
125
|
+
**Problem:** Two methods both named `determine_range` produce incompatible folder path strings:
|
|
126
|
+
- `ManifestGenerator#determine_range('b65')` → `"b50-b99"` (letter + 50-number range)
|
|
127
|
+
- `SyncFromSsd#determine_range('b65')` → `"60-69"` (no letter, 10-number range)
|
|
128
|
+
|
|
129
|
+
Both are used to construct `archived/[range]/[project_id]` paths. A project archived via SyncFromSsd lands in `archived/60-69/b65-project/`. ManifestGenerator then looks for it at `archived/b50-b99/b65-project/` — misses it (though glob fallback saves it in practice).
|
|
130
|
+
|
|
131
|
+
**ManifestGenerator format is canonical** — it handles any letter prefix (a*, b*, c*, ...) and uses 50-number ranges which are less granular and more stable.
|
|
132
|
+
|
|
133
|
+
**Fix: Update `SyncFromSsd#determine_range` to match ManifestGenerator's algorithm:**
|
|
134
|
+
|
|
135
|
+
```ruby
|
|
136
|
+
# lib/appydave/tools/dam/sync_from_ssd.rb
|
|
137
|
+
|
|
138
|
+
# BEFORE (~line 185):
|
|
139
|
+
def determine_range(project_id)
|
|
140
|
+
# FliVideo pattern: b40, b41, ... b99
|
|
141
|
+
if project_id =~ /^b(\d+)/
|
|
142
|
+
tens = (Regexp.last_match(1).to_i / 10) * 10
|
|
143
|
+
"#{tens}-#{tens + 9}"
|
|
144
|
+
else
|
|
145
|
+
'000-099'
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
# AFTER (match ManifestGenerator exactly):
|
|
150
|
+
def determine_range(project_id)
|
|
151
|
+
if project_id =~ /^([a-z])(\d+)/
|
|
152
|
+
letter = Regexp.last_match(1)
|
|
153
|
+
number = Regexp.last_match(2).to_i
|
|
154
|
+
range_start = (number / 50) * 50
|
|
155
|
+
range_end = range_start + 49
|
|
156
|
+
format("#{letter}%02d-#{letter}%02d", range_start, range_end)
|
|
157
|
+
else
|
|
158
|
+
'000-099'
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
**Update `spec/appydave/tools/dam/sync_from_ssd_spec.rb` — the existing determine_range examples (~line 277) must be updated to the new format:**
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
describe '#determine_range' do
|
|
167
|
+
it 'determines range for FliVideo pattern b40' do
|
|
168
|
+
range = sync_from_ssd.send(:determine_range, 'b40-test-project')
|
|
169
|
+
expect(range).to eq('b00-b49')
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
it 'determines range for FliVideo pattern b65' do
|
|
173
|
+
range = sync_from_ssd.send(:determine_range, 'b65-guy-monroe')
|
|
174
|
+
expect(range).to eq('b50-b99')
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
it 'determines range for FliVideo pattern b99' do
|
|
178
|
+
range = sync_from_ssd.send(:determine_range, 'b99-final-project')
|
|
179
|
+
expect(range).to eq('b50-b99')
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'returns default range for non-FliVideo pattern' do
|
|
183
|
+
range = sync_from_ssd.send(:determine_range, 'boy-baker')
|
|
184
|
+
expect(range).to eq('000-099')
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Add to `spec/appydave/tools/dam/manifest_generator_spec.rb` — currently zero specs for determine_range:**
|
|
190
|
+
|
|
191
|
+
Look at the existing manifest_generator_spec.rb for the describe block structure and shared context, then add:
|
|
192
|
+
```ruby
|
|
193
|
+
describe '#determine_range' do
|
|
194
|
+
it 'determines range for b40' do
|
|
195
|
+
range = manifest_generator.send(:determine_range, 'b40-test-project')
|
|
196
|
+
expect(range).to eq('b00-b49')
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it 'determines range for b65' do
|
|
200
|
+
range = manifest_generator.send(:determine_range, 'b65-guy-monroe')
|
|
201
|
+
expect(range).to eq('b50-b99')
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it 'determines range for b99' do
|
|
205
|
+
range = manifest_generator.send(:determine_range, 'b99-final-project')
|
|
206
|
+
expect(range).to eq('b50-b99')
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it 'returns default range for non-FliVideo pattern' do
|
|
210
|
+
range = manifest_generator.send(:determine_range, 'boy-baker')
|
|
211
|
+
expect(range).to eq('000-099')
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
Read `manifest_generator_spec.rb` first to understand how the `manifest_generator` subject is set up before adding these examples.
|
|
217
|
+
|
|
218
|
+
**Commit:** `kfix "align SyncFromSsd#determine_range with ManifestGenerator format; add specs"`
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
### fix-b021-guard
|
|
223
|
+
|
|
224
|
+
**Problem:** `bin/gpt_context.rb` line 115:
|
|
225
|
+
```ruby
|
|
226
|
+
if options.include_patterns.empty? && options.exclude_patterns.empty? && options.format.nil?
|
|
227
|
+
```
|
|
228
|
+
`options.format` defaults to `'content'` in the Options class — it is never nil. The third AND condition is always false, making the whole guard dead when only format is set. In practice the guard fires on empty include+exclude (which is the normal "no args" path), but the dead condition is confusing and could mask future bugs.
|
|
229
|
+
|
|
230
|
+
**Fix:** Remove `&& options.format.nil?` from line 115:
|
|
231
|
+
```ruby
|
|
232
|
+
# BEFORE:
|
|
233
|
+
if options.include_patterns.empty? && options.exclude_patterns.empty? && options.format.nil?
|
|
234
|
+
|
|
235
|
+
# AFTER:
|
|
236
|
+
if options.include_patterns.empty? && options.exclude_patterns.empty?
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
**Add/update spec in `spec/appydave/tools/gpt_context/cli_spec.rb`:**
|
|
240
|
+
|
|
241
|
+
Add a context for no-args behavior:
|
|
242
|
+
```ruby
|
|
243
|
+
describe 'no arguments' do
|
|
244
|
+
it 'exits with an error message when no patterns provided' do
|
|
245
|
+
output = `ruby #{script} 2>&1`
|
|
246
|
+
expect(output).to include('No options provided')
|
|
247
|
+
expect($?.exitstatus).to_not eq(0)
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Note: The script currently calls `exit` (no code) on this path — check the actual exit status. If it exits 0, adjust the expectation or leave exit code assertion out and just check the message.
|
|
253
|
+
|
|
254
|
+
**Commit:** `kfix "remove dead format.nil? guard in gpt_context no-args check"`
|
|
255
|
+
|
|
256
|
+
---
|
|
257
|
+
|
|
258
|
+
## Success Criteria
|
|
259
|
+
|
|
260
|
+
Every work unit must satisfy ALL before marking `[x]`:
|
|
261
|
+
|
|
262
|
+
- [ ] `RUBYOPT="-W0" bundle exec rspec` — 754+ examples, 0 failures
|
|
263
|
+
- [ ] `bundle exec rubocop --format clang` — 0 offenses
|
|
264
|
+
- [ ] Line coverage stays ≥ 84.92%
|
|
265
|
+
- [ ] All new `.rb` file additions start with `# frozen_string_literal: true`
|
|
266
|
+
- [ ] Commit uses `kfix` (not `git commit`)
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## Anti-Patterns to Avoid
|
|
271
|
+
|
|
272
|
+
- ❌ Do NOT remove the `ENV['AWS_SDK_RUBY_SKIP_SSL_VERIFICATION']` dev escape hatch — only remove the unconditional fallback below it
|
|
273
|
+
- ❌ Do NOT mock S3 clients when testing ssl options — check what the existing specs do and follow the pattern
|
|
274
|
+
- ❌ Do NOT change ManifestGenerator#determine_range — it is the canonical implementation, SyncFromSsd is the one to fix
|
|
275
|
+
- ❌ Do NOT use `puts` in lib/ code without checking if it violates rubocop (use `warn` for warnings)
|
|
276
|
+
- ❌ Do NOT inline brand transformations — always use BrandResolver
|
|
277
|
+
- ❌ Do NOT use `require 'spec_helper'` in new spec files — auto-required via .rspec
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Mock Patterns
|
|
282
|
+
|
|
283
|
+
### S3 Tests — Check Existing Specs First
|
|
284
|
+
|
|
285
|
+
Before writing any new S3-related test, read the existing spec file for the class you're touching. The existing patterns use WebMock or stub the S3 client at a higher level. Do NOT add new S3 network stubs — just verify the existing test suite still passes after your change.
|
|
286
|
+
|
|
287
|
+
### DAM Filesystem Tests — Shared Context
|
|
288
|
+
|
|
289
|
+
```ruby
|
|
290
|
+
include_context 'with vat filesystem and brands', brands: %w[appydave]
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
---
|
|
294
|
+
|
|
295
|
+
## Quality Gates
|
|
296
|
+
|
|
297
|
+
- **Tests:** 754+ examples, 0 failures
|
|
298
|
+
- **Lint:** 0 rubocop offenses
|
|
299
|
+
- **Coverage:** ≥ 84.92%
|
|
300
|
+
- **Commit:** `kfix` only
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## Learnings (inherited)
|
|
305
|
+
|
|
306
|
+
### From Three-Lens Audit (2026-03-19)
|
|
307
|
+
- `format.nil?` in gpt_context is always false — do not re-introduce
|
|
308
|
+
- `ssl_verify_peer: false` is not safe for AWS — HTTPS alone doesn't prevent MITM without peer verification
|
|
309
|
+
- ManifestGenerator `determine_range` is the canonical format; SyncFromSsd must match it
|
|
310
|
+
|
|
311
|
+
### From bugfix-and-security (2026-03-19)
|
|
312
|
+
- **`options.format` defaults to `'tree,content'`** in GptContext::Options — not `'content'`. It is never nil. Do not use `options.format.nil?` as a guard.
|
|
313
|
+
- **Use `$CHILD_STATUS` not `$?` in specs** — RuboCop flags `$?` as a special global variable. Use `$CHILD_STATUS` (from the English module, auto-available in RSpec) for exit status assertions.
|
|
314
|
+
- **`exit` with no code exits 0** — Ruby's bare `exit` call produces exit status 0. Write specs accordingly.
|
|
315
|
+
|
|
316
|
+
### From fr2-gpt-context-help (2026-03-19)
|
|
317
|
+
- `opts.on_tail` vs `opts.on` matters for option ordering in OptionParser
|
|
318
|
+
- Subprocess specs (`ruby #{script} --flag`) are correct for CLI integration tests
|
|
319
|
+
- Pre-conditions from prior commits — always verify live before planning
|
|
320
|
+
|
|
321
|
+
### From DAM Enhancement Sprint (Jan 2025)
|
|
322
|
+
- BrandResolver is the critical path — all dam commands flow through it
|
|
323
|
+
- `Regexp.last_match` is reset by `.sub()` calls — capture groups BEFORE any string transformation
|
|
324
|
+
- `Config.configure` is memoized — do not add new calls
|
|
325
|
+
- Table format() pattern: always use same format string for headers and data rows
|
|
326
|
+
|
|
327
|
+
### From Jump Location Tool (Dec 2025)
|
|
328
|
+
- Dependency injection for path validators required for CI compatibility
|
|
329
|
+
- Jump Commands layer has zero dedicated specs (B018 — scheduled separately)
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# IMPLEMENTATION_PLAN.md — bugfix-and-security
|
|
2
|
+
|
|
3
|
+
**Goal**: Fix 3 blockers: ssl_verify_peer security hole (B017), range string mismatch (B016), dead format guard (B021)
|
|
4
|
+
**Started**: 2026-03-19
|
|
5
|
+
**Target**: All 3 fixes committed; tests pass; 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-b017-ssl — ssl_verify_peer: false removed from s3_operations.rb, share_operations.rb, s3_scanner.rb. s3_operations_spec stub updated. 755 examples, 0 failures. v0.76.0 published.
|
|
16
|
+
- [x] fix-b021-guard — Removed dead format.nil? condition (format defaults to 'tree,content', never nil). Added no-args spec asserting exit 0 + error message. Used $CHILD_STATUS not $? (rubocop). 755 examples, 0 failures.
|
|
17
|
+
- [x] fix-b016-range — SyncFromSsd#determine_range aligned to ManifestGenerator format (any letter, 50-number ranges). Updated 4 unit specs + 4 integration path assertions in sync_from_ssd_spec. Added 4 new specs to manifest_generator_spec. 759 examples, 0 failures. v0.76.1 published.
|
|
18
|
+
|
|
19
|
+
## Failed / Needs Retry
|
|
20
|
+
|
|
21
|
+
## Notes & Decisions
|
|
22
|
+
- All 3 fixes are independent — run as parallel agents in one wave
|
|
23
|
+
- B017: s3_scanner.rb has ssl_verify_peer inline with NO env guard — remove entirely. s3_operations.rb and share_operations.rb have env guard + unconditional fallback — keep env guard, remove unconditional fallback. Return {} (empty hash) instead.
|
|
24
|
+
- B016: ManifestGenerator format is canonical (letter+50-range, e.g. b50-b99). SyncFromSsd format is wrong (10-range, no letter, e.g. 60-69). Fix SyncFromSsd to match. ManifestGenerator#determine_range has zero specs — add them.
|
|
25
|
+
- B021: options.format defaults to 'content' in Options class — format.nil? is always false. Remove the third AND condition. Update cli_spec or add spec to verify no-args exits with message.
|
|
26
|
+
- Discovered: s3_scanner.rb also affected by B017 (not in original brief)
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Assessment: bugfix-and-security
|
|
2
|
+
|
|
3
|
+
**Campaign**: bugfix-and-security
|
|
4
|
+
**Date**: 2026-03-19 → 2026-03-19
|
|
5
|
+
**Results**: 3 complete, 0 failed
|
|
6
|
+
**Version shipped**: v0.76.1
|
|
7
|
+
**Quality audit**: code-quality-audit + test-quality-audit run post-campaign
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Results Summary
|
|
12
|
+
|
|
13
|
+
| Work Unit | Status | Notes |
|
|
14
|
+
|-----------|--------|-------|
|
|
15
|
+
| fix-b017-ssl | ✅ Complete | ssl_verify_peer: false removed from s3_operations.rb, share_operations.rb, s3_scanner.rb. ENV escape hatch preserved. s3_operations_spec stub updated. |
|
|
16
|
+
| fix-b016-range | ✅ Complete | SyncFromSsd#determine_range now matches ManifestGenerator (letter prefix, 50-number ranges). 4 unit specs + 4 integration path assertions updated. 4 new specs added to manifest_generator_spec. |
|
|
17
|
+
| fix-b021-guard | ✅ Complete | Dead `&& options.format.nil?` condition removed. format defaults to 'tree,content', never nil. No-args spec added. Used $CHILD_STATUS not $? (rubocop requirement). |
|
|
18
|
+
|
|
19
|
+
**Test baseline:** 754 → 759 examples (+5). Coverage: 84.92% → 85.0%.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## What Worked Well
|
|
24
|
+
|
|
25
|
+
- **Parallel wave was clean.** 3 independent fixes in 3 different files — no conflicts, all completed without intervention.
|
|
26
|
+
- **B016 agent caught integration test debt.** sync_from_ssd_spec had 4 integration path assertions using the old `60-69` format. Agent found and fixed all of them without being told. A lesser agent would have only updated the unit tests and left the integration tests broken.
|
|
27
|
+
- **B021 agent discovered accurate default.** `options.format` defaults to `'tree,content'` (not `'content'` as AGENTS.md said). Corrected understanding.
|
|
28
|
+
- **$CHILD_STATUS vs $?.** Rubocop flags `$?` — must use `$CHILD_STATUS`. Captured in AGENTS.md learnings during campaign.
|
|
29
|
+
- **s3_scanner.rb surprise.** Brief only mentioned 2 files for B017, but grep found a third (s3_scanner.rb with inline ssl_verify_peer, no env guard). Agent fixed it correctly.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## What Didn't Work
|
|
34
|
+
|
|
35
|
+
**Critical: B017 SSL fix has no regression test (Grade C+ from test audit).**
|
|
36
|
+
The most important security fix in the campaign — removing unconditional `ssl_verify_peer: false` — is unprotected. `configure_ssl_options` is not tested in isolation. If someone accidentally adds `ssl_verify_peer: false` unconditionally back, all tests would still pass. This is the #1 priority for the next campaign.
|
|
37
|
+
|
|
38
|
+
**B016 determine_range has edge case gaps.**
|
|
39
|
+
Tests cover b40, b65, b99, boy-baker. Missing: b00 (boundary), b9 (single digit), a40 (non-b letter prefix). The regex `/^([a-z])(\d+)/` handles all of these correctly, but if the regex ever changes, these gaps won't catch it.
|
|
40
|
+
|
|
41
|
+
**cli_spec no-args test is shallow (Grade D+).**
|
|
42
|
+
Verifies the message is printed and exit is 0. Does not verify that file collection actually stops — if the guard is removed and replaced with something that prints the message but continues, the spec would still pass.
|
|
43
|
+
|
|
44
|
+
**Stale comment in sync_from_ssd.rb.**
|
|
45
|
+
Line 173 still says `b65 → 60-69 range` (old format). Code is correct; comment is wrong. 1-line fix.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Key Learnings — Application
|
|
50
|
+
|
|
51
|
+
- **`options.format` defaults to `'tree,content'`** — not `'content'`. Any guard checking `format.nil?` is dead. Updated AGENTS.md.
|
|
52
|
+
- **`$CHILD_STATUS` not `$?`** — Rubocop Special/GlobalVars cop flags `$?`. Use `$CHILD_STATUS` (English module, auto-available in RSpec). Updated AGENTS.md.
|
|
53
|
+
- **`exit` with no code exits 0** in Ruby — specs asserting exit status for "no-args" path should expect 0.
|
|
54
|
+
- **Grep the full codebase before writing the brief** — B017 brief named 2 files; actual codebase had 3. Always grep for the pattern before writing work unit scope.
|
|
55
|
+
- **Integration path assertions in specs** — when changing a path-construction algorithm, search specs for the old path strings, not just the method name. Agent found 4 integration assertions that grep on method name alone would miss.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Key Learnings — Ralph Loop
|
|
60
|
+
|
|
61
|
+
- **Parallel waves are fast when fixes are independent.** All 3 agents ran simultaneously, completed in one wave, zero coordination needed. Right call.
|
|
62
|
+
- **Quality audit surfaced a critical gap the code audit didn't.** Code looks correct (A grade). But test audit showed the SSL fix has no regression protection — an entirely separate risk dimension.
|
|
63
|
+
- **Brief scope can undercount files.** Next time, grep before writing the brief, not just inspect known files.
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## New Backlog Items from Quality Audit
|
|
68
|
+
|
|
69
|
+
- **B024** — 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 on ENV override path | Priority: **high** (protects B017 fix)
|
|
70
|
+
- **B025** — Fix: stale comment in sync_from_ssd.rb line 173 (says 60-69, should say b50-b99) | Priority: **low**
|
|
71
|
+
- **B026** — Tests: add determine_range edge cases (b00, b9, a40) to sync_from_ssd_spec and manifest_generator_spec | Priority: **medium**
|
|
72
|
+
- **B027** — Tests: strengthen gpt_context no-args spec to verify file collection actually stops (not just message printed) | Priority: **medium**
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Suggestions for Next Campaign
|
|
77
|
+
|
|
78
|
+
**Recommended next campaign: `test-coverage-gaps`**
|
|
79
|
+
|
|
80
|
+
Priority order:
|
|
81
|
+
1. **B024** — configure_ssl_options unit tests (high — protects the security fix)
|
|
82
|
+
2. **B022** — expand cli_spec with functional tests (-i, -e, -f, -o flags, exit codes)
|
|
83
|
+
3. **B026** — determine_range edge cases
|
|
84
|
+
4. **B027** — gpt_context no-args guard behavioral test
|
|
85
|
+
5. **B018** — Jump Commands layer specs (Remove/Add/Update)
|
|
86
|
+
6. **B025** — stale comment fix (bundle with B026, same file)
|
|
87
|
+
7. **B023** — file_collector_spec: JSON, aider, error paths
|
|
88
|
+
|
|
89
|
+
These are all test-only changes (except B025 which is a 1-line comment fix) — agents can run in parallel safely.
|
|
90
|
+
|
|
91
|
+
**AGENTS.md updates for next campaign:**
|
|
92
|
+
- Add: "configure_ssl_options test pattern: use ClimateControl gem or stub ENV to test conditional SSL logic"
|
|
93
|
+
- Add: "determine_range edge cases: b00, single-digit b9, non-b letter a40 — always test boundaries"
|
|
94
|
+
- Add: "gpt_context no-args test: verify file collection does NOT proceed, not just message output"
|
|
@@ -5,14 +5,14 @@
|
|
|
5
5
|
**Target**: `--help` shows structured sections; `--version` works; specs pass; rubocop clean
|
|
6
6
|
|
|
7
7
|
## Summary
|
|
8
|
-
- Total: 1 | Complete:
|
|
8
|
+
- Total: 1 | Complete: 1 | In Progress: 0 | Pending: 0 | Failed: 0
|
|
9
9
|
|
|
10
10
|
## Pending
|
|
11
11
|
|
|
12
12
|
## In Progress
|
|
13
|
-
- [~] fr2-gpt-context-help — Implement AI-friendly help system in bin/gpt_context.rb per docs/specs/fr-002-gpt-context-help-system.md
|
|
14
13
|
|
|
15
14
|
## Complete
|
|
15
|
+
- [x] fr2-gpt-context-help — Implement AI-friendly help system in bin/gpt_context.rb. 754 examples, 0 failures. v0.76.0 published. Also fixed pre-existing rubocop offenses in bin/dam and split jump_test_helpers (JumpTestLocations → own file).
|
|
16
16
|
|
|
17
17
|
## Failed / Needs Retry
|
|
18
18
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Assessment: fr2-gpt-context-help
|
|
2
|
+
|
|
3
|
+
**Campaign**: fr2-gpt-context-help
|
|
4
|
+
**Date**: 2026-03-19 → 2026-03-19
|
|
5
|
+
**Results**: 1 complete, 0 failed
|
|
6
|
+
**Version shipped**: v0.76.0
|
|
7
|
+
**Quality audit**: code-quality-audit + test-quality-audit run post-campaign
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Results Summary
|
|
12
|
+
|
|
13
|
+
| Work Unit | Status | Notes |
|
|
14
|
+
|-----------|--------|-------|
|
|
15
|
+
| B002 — FR-2 GPT Context help system | ✅ Complete | 754 examples, 0 failures. Also fixed pre-existing rubocop offenses in bin/dam and split JumpTestLocations into own file. |
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## What Worked Well
|
|
20
|
+
|
|
21
|
+
- **Single-file scope held.** `bin/gpt_context.rb` only — no lib/ changes. Agent stayed in bounds.
|
|
22
|
+
- **Side-fixes landed cleanly.** Rubocop offenses in bin/dam (select/reject → partition) and JumpTestLocations split were caught and fixed without scope creep.
|
|
23
|
+
- **Test count and coverage improved.** 748 → 754 examples, 84.88% → 84.92% coverage.
|
|
24
|
+
- **Spec approach was correct.** subprocess integration testing (running the actual script) is the right pattern for CLI help/version tests.
|
|
25
|
+
- **Pre-conditions were pre-cleared.** B015 and B019 fixed in prior commit 13d5f87 meant agent could focus on FR-2 immediately.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## What Didn't Work
|
|
30
|
+
|
|
31
|
+
- **cli_spec.rb is too thin (Grade: C from test audit).** 4 tests only verify help text strings are present. No functional tests: `-i`, `-e`, `-f`, `-o` flags completely untested at CLI level. Creates false sense of security.
|
|
32
|
+
- **format.nil? guard is dead code.** `bin/gpt_context.rb` line 115 checks `options.format.nil?` as part of its "no options provided" guard. But `format` defaults to `'content'` in the Options class — it is never nil. The third AND condition is always false, meaning the guard can only trigger if both include_patterns AND exclude_patterns are empty AND format has somehow been set to nil (impossible via normal usage).
|
|
33
|
+
- **file_collector_spec missing formats.** JSON and aider format output paths in FileCollector have zero specs. Error cases also unprotected.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## Key Learnings — Application
|
|
38
|
+
|
|
39
|
+
- **OptionParser `opts.on_tail` vs `opts.on` matters for ordering.** `--version` must be `opts.on` (not `on_tail`) to appear before `--help` in output. Anti-pattern documented in AGENTS.md.
|
|
40
|
+
- **format.nil? is a dead guard.** When Options class sets a default for `format`, the nil check in bin/gpt_context.rb line 115 is always false. Any "no args provided" guard must check `include_patterns.empty?` and `exclude_patterns.empty?` only.
|
|
41
|
+
- **Subprocess specs work but need functional assertions.** Using `\`ruby #{script} --flag\`` is correct for CLI integration testing, but tests must verify actual output content and exit codes — not just documentation strings.
|
|
42
|
+
|
|
43
|
+
---
|
|
44
|
+
|
|
45
|
+
## Key Learnings — Ralph Loop
|
|
46
|
+
|
|
47
|
+
- **One work unit campaigns are fast.** 1 agent, 1 wave, done. No coordination overhead.
|
|
48
|
+
- **Pre-conditions from prior commits reduce campaign scope.** B015/B019 were in next-round-brief as work units but had already been fixed. Always verify pre-conditions live before writing the plan.
|
|
49
|
+
- **Quality audit caught 3 new backlog items.** B021 (format.nil? dead guard), B022 (cli_spec functional tests), B023 (file_collector JSON/aider/error specs). These were invisible without the audit.
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## Suggestions for Next Campaign
|
|
54
|
+
|
|
55
|
+
**Recommended next campaign: `bugfix-and-security` — B016, B017, B021**
|
|
56
|
+
|
|
57
|
+
Priority order:
|
|
58
|
+
1. **B017** — ssl_verify_peer: false (security BLOCKER — remove before adding any S3 features)
|
|
59
|
+
2. **B016** — ManifestGenerator vs SyncFromSsd range string mismatch (data integrity BLOCKER)
|
|
60
|
+
3. **B021** — fix format.nil? dead guard in gpt_context (5-minute fix, prevents silent failure)
|
|
61
|
+
|
|
62
|
+
Then schedule soon after:
|
|
63
|
+
- **B022** — expand cli_spec.rb with functional tests (-i, -e, -f, -o, exit codes)
|
|
64
|
+
- **B023** — file_collector_spec: add JSON, aider, error path coverage
|
|
65
|
+
- **B018** — Jump Commands layer specs (Remove/Add/Update)
|
|
66
|
+
|
|
67
|
+
**AGENTS.md updates needed for next campaign:**
|
|
68
|
+
- Add: "format.nil? in gpt_context is always false — do not use as a no-args guard"
|
|
69
|
+
- Add: "S3Operations ssl_verify_peer must be removed — see B017"
|
|
70
|
+
- Add: "ManifestGenerator and SyncFromSsd produce incompatible range strings — see B016 before touching SSD archive paths"
|
|
@@ -1,55 +1,42 @@
|
|
|
1
1
|
# Next Round Brief
|
|
2
2
|
|
|
3
3
|
**Created:** 2026-03-19
|
|
4
|
-
**Updated:** 2026-03-19 (after
|
|
4
|
+
**Updated:** 2026-03-19 (after bugfix-and-security assessment)
|
|
5
5
|
|
|
6
6
|
---
|
|
7
7
|
|
|
8
|
-
## Recommended Next Campaign:
|
|
8
|
+
## Recommended Next Campaign: test-coverage-gaps
|
|
9
9
|
|
|
10
10
|
### Goal
|
|
11
11
|
|
|
12
|
-
|
|
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
13
|
|
|
14
14
|
### Background
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Quality audit after bugfix-and-security found:
|
|
17
17
|
|
|
18
|
-
1.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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).
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
### Suggested Work Units (parallel — all test-only except B025)
|
|
24
26
|
|
|
25
|
-
|
|
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.
|
|
26
32
|
|
|
27
|
-
###
|
|
28
|
-
|
|
29
|
-
1. **Fix B019** — Delete `puts @working_directory` from `file_collector.rb:15` (1-line fix)
|
|
30
|
-
2. **Fix B015** — Wrap `FileUtils.cd` in block form in `file_collector.rb` (3-line fix)
|
|
31
|
-
3. **Implement FR-2** — Read `docs/specs/fr-002-gpt-context-help-system.md`. Option A from the spec (enhanced OptionParser with banner, separators, `--version`) is the correct approach. No changes to lib/ needed — this is a `bin/gpt_context.rb` enhancement.
|
|
32
|
-
4. **Verify BUG-1** — Run `bin/jump.rb get <key>` live. If broken: find actual failure site. If fixed: write regression spec for `Jump::Config#find` round-trip and close.
|
|
33
|
-
|
|
34
|
-
### Pre-Campaign Blockers: None
|
|
35
|
-
|
|
36
|
-
Neither fix requires architectural changes. FR-2 is contained to `bin/gpt_context.rb`. The Jump verification is read-only unless the bug is confirmed.
|
|
37
|
-
|
|
38
|
-
### What Agents Need to Know
|
|
39
|
-
|
|
40
|
-
- Read `docs/planning/AGENTS.md` — test/lint patterns, commit format, quality gates
|
|
41
|
-
- FR-2 spec: `docs/specs/fr-002-gpt-context-help-system.md`
|
|
42
|
-
- gpt_context source: `lib/appydave/tools/gpt_context/` + `bin/gpt_context.rb`
|
|
43
|
-
- Jump source: `lib/appydave/tools/jump/` (Config, Search, Commands/*)
|
|
44
|
-
- Jump tests: `spec/appydave/tools/jump/` + `spec/support/jump_test_helpers.rb`
|
|
45
|
-
- BUG-1 call chain: `CLI#run_get` → `Search#get` → `Config#find` → `locations.find { |loc| loc.key == key }`
|
|
46
|
-
|
|
47
|
-
### Also Schedule Soon (from audit)
|
|
33
|
+
### Mode Recommendation
|
|
48
34
|
|
|
49
|
-
|
|
50
|
-
- B017 — ssl_verify_peer: false in S3Operations (security — schedule next)
|
|
51
|
-
- B018 — Jump Commands layer specs (no specs for Remove/Add/Update)
|
|
35
|
+
**Extend** — same stack, same patterns, test-only work. Inherit AGENTS.md.
|
|
52
36
|
|
|
53
|
-
###
|
|
37
|
+
### Pre-Campaign Notes
|
|
54
38
|
|
|
55
|
-
|
|
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
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# AGENTS.md — test-coverage-gaps
|
|
2
|
+
|
|
3
|
+
> Inherited from bugfix-and-security 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 except 1-line comment fix (B025).
|
|
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/dam/s3_operations_spec.rb
|
|
24
|
+
bundle exec rspec spec/appydave/tools/dam/share_operations_spec.rb
|
|
25
|
+
bundle exec rspec spec/appydave/tools/dam/sync_from_ssd_spec.rb
|
|
26
|
+
bundle exec rspec spec/appydave/tools/dam/manifest_generator_spec.rb
|
|
27
|
+
bundle exec rspec spec/appydave/tools/gpt_context/cli_spec.rb
|
|
28
|
+
bundle exec rspec spec/appydave/tools/jump/ # All jump specs
|
|
29
|
+
bundle exec rubocop --format clang
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Baseline:** 759 examples, 0 failures, 85.0% line coverage
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Directory Structure
|
|
37
|
+
|
|
38
|
+
```
|
|
39
|
+
lib/appydave/tools/dam/
|
|
40
|
+
s3_operations.rb configure_ssl_options method (~line 102) — READ ONLY
|
|
41
|
+
share_operations.rb configure_ssl_options method (~line 89) — READ ONLY
|
|
42
|
+
sync_from_ssd.rb determine_range (~line 185); stale comment line 173 — FIX COMMENT
|
|
43
|
+
manifest_generator.rb determine_range (~line 332) — READ ONLY
|
|
44
|
+
jump/
|
|
45
|
+
commands/
|
|
46
|
+
remove.rb READ ONLY — write spec for this
|
|
47
|
+
add.rb READ ONLY — write spec for this (may be called create.rb or set.rb)
|
|
48
|
+
update.rb READ ONLY — write spec for this
|
|
49
|
+
spec/appydave/tools/dam/
|
|
50
|
+
s3_operations_spec.rb ADD configure_ssl_options tests
|
|
51
|
+
share_operations_spec.rb ADD configure_ssl_options tests
|
|
52
|
+
sync_from_ssd_spec.rb ADD determine_range edge cases
|
|
53
|
+
manifest_generator_spec.rb ADD determine_range edge cases
|
|
54
|
+
spec/appydave/tools/gpt_context/
|
|
55
|
+
cli_spec.rb ADD functional tests (-i, -e, -f, -o)
|
|
56
|
+
spec/appydave/tools/jump/
|
|
57
|
+
commands/
|
|
58
|
+
remove_spec.rb CREATE THIS
|
|
59
|
+
add_spec.rb CREATE THIS (check actual filename first)
|
|
60
|
+
update_spec.rb CREATE THIS (check actual filename first)
|
|
61
|
+
spec/support/
|
|
62
|
+
jump_test_helpers.rb Reference for shared context
|
|
63
|
+
jump_test_locations.rb Reference for test fixture data
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Work Unit Details
|
|
69
|
+
|
|
70
|
+
### fix-b024-ssl-tests
|
|
71
|
+
|
|
72
|
+
**Goal:** Protect the B017 security fix. `configure_ssl_options` must have unit tests verifying:
|
|
73
|
+
1. Default path returns `{}` (no ssl_verify_peer key at all)
|
|
74
|
+
2. ENV override path returns `{ ssl_verify_peer: false }`
|
|
75
|
+
|
|
76
|
+
**Check Gemfile first** — if `climate_control` is present, use it. Otherwise, stub ENV directly:
|
|
77
|
+
|
|
78
|
+
```ruby
|
|
79
|
+
# Direct ENV stub (works without climate_control)
|
|
80
|
+
describe '#configure_ssl_options' do
|
|
81
|
+
subject(:ssl_options) { s3_ops.send(:configure_ssl_options) }
|
|
82
|
+
|
|
83
|
+
context 'when AWS_SDK_RUBY_SKIP_SSL_VERIFICATION is not set' do
|
|
84
|
+
before { allow(ENV).to receive(:[]).and_call_original }
|
|
85
|
+
before { allow(ENV).to receive(:[]).with('AWS_SDK_RUBY_SKIP_SSL_VERIFICATION').and_return(nil) }
|
|
86
|
+
|
|
87
|
+
it 'returns empty hash (SSL verification enabled by default)' do
|
|
88
|
+
expect(ssl_options).to eq({})
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'does not include ssl_verify_peer key' do
|
|
92
|
+
expect(ssl_options).not_to have_key(:ssl_verify_peer)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
context 'when AWS_SDK_RUBY_SKIP_SSL_VERIFICATION is "true"' do
|
|
97
|
+
before { allow(ENV).to receive(:[]).and_call_original }
|
|
98
|
+
before { allow(ENV).to receive(:[]).with('AWS_SDK_RUBY_SKIP_SSL_VERIFICATION').and_return('true') }
|
|
99
|
+
|
|
100
|
+
it 'returns ssl_verify_peer: false' do
|
|
101
|
+
expect(ssl_options).to eq({ ssl_verify_peer: false })
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Read the existing spec to find how `s3_ops` subject is set up. Add these examples within the existing describe block structure. Same pattern for `share_operations_spec.rb`.
|
|
108
|
+
|
|
109
|
+
**Commit:** `kfix "add configure_ssl_options unit tests to protect B017 security fix"`
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
### fix-b022-cli-tests
|
|
114
|
+
|
|
115
|
+
**Goal:** Functional subprocess tests for gpt_context CLI. Test that the actual flags work end-to-end.
|
|
116
|
+
|
|
117
|
+
**Pattern — write to Tempfile, verify content:**
|
|
118
|
+
|
|
119
|
+
```ruby
|
|
120
|
+
describe '-i include pattern' do
|
|
121
|
+
it 'collects files matching the include pattern' do
|
|
122
|
+
Dir.mktmpdir do |tmpdir|
|
|
123
|
+
# Create a test file
|
|
124
|
+
File.write(File.join(tmpdir, 'test.rb'), '# test content')
|
|
125
|
+
outfile = File.join(tmpdir, 'output.txt')
|
|
126
|
+
|
|
127
|
+
`ruby #{script} -i '*.rb' -b #{tmpdir} -o #{outfile} 2>&1`
|
|
128
|
+
|
|
129
|
+
expect(File.read(outfile)).to include('# file: test.rb')
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
describe '-e exclude pattern' do
|
|
135
|
+
it 'excludes files matching the exclude pattern' do
|
|
136
|
+
Dir.mktmpdir do |tmpdir|
|
|
137
|
+
File.write(File.join(tmpdir, 'keep.rb'), '# keep')
|
|
138
|
+
File.write(File.join(tmpdir, 'exclude.rb'), '# exclude')
|
|
139
|
+
outfile = File.join(tmpdir, 'output.txt')
|
|
140
|
+
|
|
141
|
+
`ruby #{script} -i '*.rb' -e 'exclude.rb' -b #{tmpdir} -o #{outfile} 2>&1`
|
|
142
|
+
|
|
143
|
+
content = File.read(outfile)
|
|
144
|
+
expect(content).to include('# file: keep.rb')
|
|
145
|
+
expect(content).not_to include('# file: exclude.rb')
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
describe '-f format' do
|
|
151
|
+
it 'outputs tree format when -f tree specified' do
|
|
152
|
+
Dir.mktmpdir do |tmpdir|
|
|
153
|
+
File.write(File.join(tmpdir, 'test.rb'), '# test')
|
|
154
|
+
outfile = File.join(tmpdir, 'output.txt')
|
|
155
|
+
|
|
156
|
+
`ruby #{script} -i '*.rb' -f tree -b #{tmpdir} -o #{outfile} 2>&1`
|
|
157
|
+
|
|
158
|
+
expect(File.read(outfile)).to include('test.rb')
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
Note: `-b` sets the base directory, `-o` writes to file. Read the existing cli_spec.rb first for the `script` let binding.
|
|
165
|
+
|
|
166
|
+
**Commit:** `kfix "add functional CLI tests for -i -e -f -o flags to cli_spec"`
|
|
167
|
+
|
|
168
|
+
---
|
|
169
|
+
|
|
170
|
+
### fix-b026-b025-range-tests
|
|
171
|
+
|
|
172
|
+
**Goal:** Add edge case tests for `determine_range` + fix 1-line stale comment.
|
|
173
|
+
|
|
174
|
+
**In `sync_from_ssd_spec.rb`** — add to the existing `describe '#determine_range'` block:
|
|
175
|
+
```ruby
|
|
176
|
+
it 'determines range for boundary b00' do
|
|
177
|
+
range = sync_from_ssd.send(:determine_range, 'b00-first-project')
|
|
178
|
+
expect(range).to eq('b00-b49')
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it 'determines range for single-digit b9' do
|
|
182
|
+
range = sync_from_ssd.send(:determine_range, 'b9-project')
|
|
183
|
+
expect(range).to eq('b00-b49')
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it 'determines range for non-b letter prefix a40' do
|
|
187
|
+
range = sync_from_ssd.send(:determine_range, 'a40-test-project')
|
|
188
|
+
expect(range).to eq('a00-a49')
|
|
189
|
+
end
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**In `manifest_generator_spec.rb`** — add same 3 examples to the `describe '#determine_range'` block.
|
|
193
|
+
|
|
194
|
+
**In `sync_from_ssd.rb` line 173** — update comment:
|
|
195
|
+
```ruby
|
|
196
|
+
# Determine local destination path (archived structure)
|
|
197
|
+
# Extract range from project ID (e.g., b65 → b50-b99 range)
|
|
198
|
+
```
|
|
199
|
+
(Was: `b65 → 60-69 range`)
|
|
200
|
+
|
|
201
|
+
**Commit:** `kfix "add determine_range edge cases and fix stale comment"`
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
### fix-b027-noargs-test
|
|
206
|
+
|
|
207
|
+
**Goal:** Strengthen the no-args gpt_context spec to verify file collection stops — not just message output.
|
|
208
|
+
|
|
209
|
+
The subprocess approach can't easily stub FileCollector. Use a stronger output assertion instead:
|
|
210
|
+
|
|
211
|
+
```ruby
|
|
212
|
+
describe 'no arguments' do
|
|
213
|
+
it 'prints an error message when no patterns provided' do
|
|
214
|
+
output = `ruby #{script} 2>&1`
|
|
215
|
+
expect(output).to include('No options provided')
|
|
216
|
+
expect($CHILD_STATUS.exitstatus).to eq(0)
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it 'does not produce file content output when no patterns provided' do
|
|
220
|
+
output = `ruby #{script} 2>&1`
|
|
221
|
+
expect(output).not_to include('# file:')
|
|
222
|
+
expect(output).not_to include('clipboard')
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
The second test verifies file collection output markers are absent — catches regressions where the guard is removed but the script continues to run.
|
|
228
|
+
|
|
229
|
+
Read existing cli_spec.rb first — update the existing no-args describe block rather than adding a duplicate.
|
|
230
|
+
|
|
231
|
+
**Commit:** `kfix "strengthen gpt_context no-args spec to verify collection does not proceed"`
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
### fix-b018-jump-specs
|
|
236
|
+
|
|
237
|
+
**Goal:** Add dedicated unit specs for Jump Commands::Remove, Commands::Add (or Create), Commands::Update.
|
|
238
|
+
|
|
239
|
+
**Step 1:** Read the source files first:
|
|
240
|
+
```
|
|
241
|
+
lib/appydave/tools/jump/commands/
|
|
242
|
+
```
|
|
243
|
+
List what files exist — the command names may differ from Remove/Add/Update.
|
|
244
|
+
|
|
245
|
+
**Step 2:** Read an existing jump spec (e.g., `spec/appydave/tools/jump/`) for setup patterns.
|
|
246
|
+
|
|
247
|
+
**Step 3:** For each command, create a spec file covering:
|
|
248
|
+
- Happy path: command executes with valid key
|
|
249
|
+
- `--force` guard: command without --force prompts/refuses where applicable
|
|
250
|
+
- Not-found path: key does not exist — shows suggestion or error
|
|
251
|
+
- Error codes / output messages
|
|
252
|
+
|
|
253
|
+
**Pattern (based on jump_test_helpers.rb):**
|
|
254
|
+
```ruby
|
|
255
|
+
# frozen_string_literal: true
|
|
256
|
+
|
|
257
|
+
RSpec.describe Appydave::Tools::Jump::Commands::Remove do
|
|
258
|
+
include_context 'with jump filesystem'
|
|
259
|
+
|
|
260
|
+
describe '#run' do
|
|
261
|
+
context 'when location exists' do
|
|
262
|
+
before { setup_jump_config([JumpTestLocations.ad_tools]) }
|
|
263
|
+
|
|
264
|
+
it 'removes the location with --force' do
|
|
265
|
+
# ...
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it 'refuses to remove without --force' do
|
|
269
|
+
# ...
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
context 'when location does not exist' do
|
|
274
|
+
it 'shows not-found error' do
|
|
275
|
+
# ...
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
**Commit:** `kfix "add dedicated specs for Jump Commands Remove Add Update"`
|
|
283
|
+
|
|
284
|
+
---
|
|
285
|
+
|
|
286
|
+
## Success Criteria
|
|
287
|
+
|
|
288
|
+
- [ ] `RUBYOPT="-W0" bundle exec rspec` — 759+ examples, 0 failures
|
|
289
|
+
- [ ] `bundle exec rubocop --format clang` — 0 offenses
|
|
290
|
+
- [ ] Line coverage stays ≥ 85.0%
|
|
291
|
+
- [ ] `configure_ssl_options` default path verified to NOT include ssl_verify_peer
|
|
292
|
+
- [ ] All new spec files start with `# frozen_string_literal: true`
|
|
293
|
+
- [ ] No `require 'spec_helper'` in new spec files (auto-required)
|
|
294
|
+
|
|
295
|
+
---
|
|
296
|
+
|
|
297
|
+
## Anti-Patterns to Avoid
|
|
298
|
+
|
|
299
|
+
- ❌ Do NOT use `$?` in specs — use `$CHILD_STATUS` (rubocop)
|
|
300
|
+
- ❌ Do NOT use `options.format.nil?` — format defaults to 'tree,content', never nil
|
|
301
|
+
- ❌ Do NOT mock internal DAM classes — use shared filesystem context
|
|
302
|
+
- ❌ Do NOT require spec_helper explicitly
|
|
303
|
+
- ❌ Do NOT modify production lib/ code (except 1-line comment fix in sync_from_ssd.rb)
|
|
304
|
+
- ❌ Do NOT use `puts` in lib/ — use `warn` for warnings
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## Learnings (inherited)
|
|
309
|
+
|
|
310
|
+
- **`$CHILD_STATUS` not `$?`** — rubocop Special/GlobalVars cop
|
|
311
|
+
- **`exit` with no code exits 0** — specs asserting no-args exit should expect 0
|
|
312
|
+
- **`options.format` defaults to `'tree,content'`** — never nil
|
|
313
|
+
- **Grep full codebase before writing scope** — actual files may differ from brief
|
|
314
|
+
- **Integration path assertions** — when changing path algorithms, search specs for old path strings
|
|
315
|
+
- **BrandResolver is critical path** — all dam commands flow through it
|
|
316
|
+
- **`Regexp.last_match` reset by `.sub()`** — capture groups before string transformation
|
|
317
|
+
- **Dependency injection for path validators** — required for CI compatibility in Jump tests
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# IMPLEMENTATION_PLAN.md — test-coverage-gaps
|
|
2
|
+
|
|
3
|
+
**Goal**: Close critical test gaps: protect B017 SSL fix, expand gpt_context CLI coverage, range edge cases, Jump Commands specs
|
|
4
|
+
**Started**: 2026-03-19
|
|
5
|
+
**Target**: All gaps addressed; 759+ examples passing; rubocop clean; no regressions
|
|
6
|
+
|
|
7
|
+
## Summary
|
|
8
|
+
- Total: 5 | Complete: 0 | In Progress: 5 | Pending: 0 | Failed: 0
|
|
9
|
+
|
|
10
|
+
## Pending
|
|
11
|
+
|
|
12
|
+
## In Progress
|
|
13
|
+
- [~] fix-b024-ssl-tests — Add configure_ssl_options unit tests to s3_operations_spec + share_operations_spec
|
|
14
|
+
- [~] fix-b022-cli-tests — Add functional subprocess tests to gpt_context cli_spec.rb (-i, -e, -f, -o)
|
|
15
|
+
- [~] fix-b018-jump-specs — Add specs for Jump Commands::Remove, Add, Update
|
|
16
|
+
|
|
17
|
+
## Complete
|
|
18
|
+
- [x] fix-b027-noargs-test — Added second no-args example: verifies output does NOT include '# file:' or 'clipboard'. 766 examples, 0 failures. Note: B024 agent had RSpec/ScatteredSetup rubocop issue (multiple before hooks) — fixed in subsequent commit.
|
|
19
|
+
- [x] fix-b026-b025-range-tests — Edge cases (b00, b9, a40) added to sync_from_ssd_spec + manifest_generator_spec. Stale comment fixed in sync_from_ssd.rb:173. ⚠️ CI ISSUE: cli_spec.rb:39 failing — 'not_to include clipboard' assertion is fragile (no-args output may mention clipboard on some platforms). B022 agent touching cli_spec.rb may resolve this.
|
|
20
|
+
|
|
21
|
+
## Failed / Needs Retry
|
|
22
|
+
|
|
23
|
+
## Notes & Decisions
|
|
24
|
+
- All 5 work units are independent — parallel wave
|
|
25
|
+
- Test-only campaign except B025 (1-line comment fix in sync_from_ssd.rb)
|
|
26
|
+
- ENV stubbing: use allow(ENV).to receive(:[]) — check Gemfile for climate_control first
|
|
27
|
+
- B022 functional tests: write to Tempfile, verify # file: headers in output
|
|
28
|
+
- B027: stub GptContext::FileCollector at class level before subprocess call won't work — use integration assertion instead (verify output does NOT contain file collection output)
|
|
29
|
+
- B018: read existing jump CLI spec before writing command-layer specs
|
|
@@ -100,17 +100,9 @@ module Appydave
|
|
|
100
100
|
end
|
|
101
101
|
|
|
102
102
|
def configure_ssl_options
|
|
103
|
-
|
|
104
|
-
if ENV['AWS_SDK_RUBY_SKIP_SSL_VERIFICATION'] == 'true'
|
|
105
|
-
puts '⚠️ WARNING: SSL verification is disabled (development mode)'
|
|
106
|
-
return { ssl_verify_peer: false }
|
|
107
|
-
end
|
|
103
|
+
return { ssl_verify_peer: false } if ENV['AWS_SDK_RUBY_SKIP_SSL_VERIFICATION'] == 'true'
|
|
108
104
|
|
|
109
|
-
|
|
110
|
-
# This is safe for AWS S3 connections as we're still using HTTPS (encrypted connection)
|
|
111
|
-
{
|
|
112
|
-
ssl_verify_peer: false
|
|
113
|
-
}
|
|
105
|
+
{}
|
|
114
106
|
end
|
|
115
107
|
|
|
116
108
|
public
|
|
@@ -87,17 +87,9 @@ module Appydave
|
|
|
87
87
|
end
|
|
88
88
|
|
|
89
89
|
def configure_ssl_options
|
|
90
|
-
|
|
91
|
-
if ENV['AWS_SDK_RUBY_SKIP_SSL_VERIFICATION'] == 'true'
|
|
92
|
-
puts '⚠️ WARNING: SSL verification is disabled (development mode)'
|
|
93
|
-
return { ssl_verify_peer: false }
|
|
94
|
-
end
|
|
90
|
+
return { ssl_verify_peer: false } if ENV['AWS_SDK_RUBY_SKIP_SSL_VERIFICATION'] == 'true'
|
|
95
91
|
|
|
96
|
-
|
|
97
|
-
# This is safe for AWS S3 connections as we're still using HTTPS (encrypted connection)
|
|
98
|
-
{
|
|
99
|
-
ssl_verify_peer: false
|
|
100
|
-
}
|
|
92
|
+
{}
|
|
101
93
|
end
|
|
102
94
|
|
|
103
95
|
public
|
|
@@ -170,7 +170,7 @@ module Appydave
|
|
|
170
170
|
return { skipped: 1, files: 0, bytes: 0, reason: 'Flat folder exists (stale manifest?)' } if Dir.exist?(flat_path)
|
|
171
171
|
|
|
172
172
|
# Determine local destination path (archived structure)
|
|
173
|
-
# Extract range from project ID (e.g., b65 →
|
|
173
|
+
# Extract range from project ID (e.g., b65 → b50-b99 range)
|
|
174
174
|
range = determine_range(project_id)
|
|
175
175
|
local_dir = File.join(brand_path, 'archived', range, project_id)
|
|
176
176
|
|
|
@@ -181,14 +181,17 @@ module Appydave
|
|
|
181
181
|
sync_light_files(ssd_path, local_dir, dry_run: dry_run)
|
|
182
182
|
end
|
|
183
183
|
|
|
184
|
-
# Determine range folder for project (e.g., b65 →
|
|
184
|
+
# Determine range folder for project (e.g., b65 → b50-b99)
|
|
185
185
|
def determine_range(project_id)
|
|
186
|
-
# FliVideo pattern: b40,
|
|
187
|
-
if project_id =~ /^
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
# FliVideo/Modern pattern: b40, a82, etc.
|
|
187
|
+
if project_id =~ /^([a-z])(\d+)/
|
|
188
|
+
letter = Regexp.last_match(1)
|
|
189
|
+
number = Regexp.last_match(2).to_i
|
|
190
|
+
range_start = (number / 50) * 50
|
|
191
|
+
range_end = range_start + 49
|
|
192
|
+
format("#{letter}%02d-#{letter}%02d", range_start, range_end)
|
|
190
193
|
else
|
|
191
|
-
# Legacy pattern or unknown
|
|
194
|
+
# Legacy pattern or unknown
|
|
192
195
|
'000-099'
|
|
193
196
|
end
|
|
194
197
|
end
|
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.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cruwys
|
|
@@ -297,9 +297,15 @@ files:
|
|
|
297
297
|
- docs/guides/tools/youtube-manager.md
|
|
298
298
|
- docs/planning/AGENTS.md
|
|
299
299
|
- docs/planning/BACKLOG.md
|
|
300
|
+
- docs/planning/bugfix-and-security/AGENTS.md
|
|
301
|
+
- docs/planning/bugfix-and-security/IMPLEMENTATION_PLAN.md
|
|
302
|
+
- docs/planning/bugfix-and-security/assessment.md
|
|
300
303
|
- docs/planning/fr2-gpt-context-help/AGENTS.md
|
|
301
304
|
- docs/planning/fr2-gpt-context-help/IMPLEMENTATION_PLAN.md
|
|
305
|
+
- docs/planning/fr2-gpt-context-help/assessment.md
|
|
302
306
|
- docs/planning/next-round-brief.md
|
|
307
|
+
- docs/planning/test-coverage-gaps/AGENTS.md
|
|
308
|
+
- docs/planning/test-coverage-gaps/IMPLEMENTATION_PLAN.md
|
|
303
309
|
- docs/specs/fr-002-gpt-context-help-system.md
|
|
304
310
|
- docs/specs/fr-003-jump-location-tool.md
|
|
305
311
|
- docs/specs/zsh-history-tool.md
|