appydave-tools 0.75.0 → 0.76.0
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 +12 -0
- data/CLAUDE.md +5 -26
- data/bin/dam +2 -4
- data/bin/gpt_context.rb +64 -21
- data/docs/backlog.md +1 -1
- data/docs/code-quality/README.md +15 -16
- data/docs/planning/AGENTS.md +245 -0
- data/docs/planning/BACKLOG.md +186 -0
- data/docs/planning/fr2-gpt-context-help/AGENTS.md +256 -0
- data/docs/planning/fr2-gpt-context-help/IMPLEMENTATION_PLAN.md +24 -0
- data/docs/planning/next-round-brief.md +55 -0
- data/lib/appydave/tools/gpt_context/file_collector.rb +13 -20
- data/lib/appydave/tools/version.rb +1 -1
- data/package.json +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 39c3338d4f56e9b453669e54150db39c4449b667fa347a2634b2741fbd272235
|
|
4
|
+
data.tar.gz: 5949d3218ac0ca10376e9307ee981fd88a9505d876ba88178a7a6647447b8077
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9b52b37eb3e5ebda0eb8508f054b53cf607b208e2ba2c227418381bc77940720741c7feea5e9edc47ca8942da0c5bb4e20d79034d8b3e345ad10f0823bedd76a
|
|
7
|
+
data.tar.gz: 6aed7f6c4d2d16b7706d6449ba3759e5b24cc08d3ac602c979485babc72625d632588ebf070211e9b68a11d5af5a75151d4b6a92729c50a8335a59a1040d919d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [0.75.0](https://github.com/appydave/appydave-tools/compare/v0.74.1...v0.75.0) (2026-02-08)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* fix RuboCop violations in jump report commands ([261404e](https://github.com/appydave/appydave-tools/commit/261404ed5cc9e3b93c64db30548728992b353355))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add --limit and --skip-unassigned flags to jump report commands ([d0ff2ae](https://github.com/appydave/appydave-tools/commit/d0ff2aeae4edffc81448e62502c3974a0942559f))
|
|
12
|
+
|
|
1
13
|
## [0.74.1](https://github.com/appydave/appydave-tools/compare/v0.74.0...v0.74.1) (2026-02-04)
|
|
2
14
|
|
|
3
15
|
|
data/CLAUDE.md
CHANGED
|
@@ -2,34 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## ✅ COMPLETE: DAM Enhancement Sprint QA (2025-01-22)
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Two-phase validation for the 75-commit DAM enhancement sprint (9e49668 → 4228b51) is complete.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **
|
|
12
|
-
- **Commit Range:** `9e49668` (baseline - known working) → `4228b51` (current - unknown state)
|
|
13
|
-
- **Purpose:** Verify core functionality unchanged except for intentional UX improvements
|
|
14
|
-
- **Method:** Two-snapshot comparison (not 75 individual commits)
|
|
15
|
-
- **5 Phases:** Change inventory → Critical path → Behavioral testing → Logic diff → Spot-check
|
|
16
|
-
- **Output:** `docs/code-quality/behavioral-audit-2025-01-22.md`
|
|
17
|
-
- **Status:** Ready to execute - awaiting user confirmation
|
|
18
|
-
- **Priority:** CRITICAL - Must complete before UAT
|
|
19
|
-
|
|
20
|
-
### Phase 2: User Acceptance Testing (RUN AFTER REGRESSION AUDIT)
|
|
21
|
-
|
|
22
|
-
- **UAT Plan:** [docs/code-quality/uat-plan-2025-01-22.md](./docs/code-quality/uat-plan-2025-01-22.md)
|
|
23
|
-
- **Test Suites:** 4 suites, 20 tests (Core functionality, New features, Edge cases, Performance)
|
|
24
|
-
- **Purpose:** Validate final state after regression fixes
|
|
25
|
-
- **Status:** Ready to execute - run after Phase 1 completes
|
|
26
|
-
- **Priority:** High - Final validation before release
|
|
27
|
-
|
|
28
|
-
### Execution Order
|
|
29
|
-
|
|
30
|
-
1. **Behavioral Regression Audit** → Identify and fix any breaking changes
|
|
31
|
-
2. **User Acceptance Testing** → Validate everything works as designed
|
|
32
|
-
3. **Ship it** → Merge/release with confidence
|
|
9
|
+
- **Phase 1 — Behavioral Regression Audit:** ✅ SAFE — 0 regressions, 15+ UX improvements validated. See [docs/code-quality/behavioral-audit-2025-01-22.md](./docs/code-quality/behavioral-audit-2025-01-22.md)
|
|
10
|
+
- **Phase 2 — UAT:** ✅ PASSED — 20/20 tests passed, 4 minor formatting issues found and fixed inline. See [docs/code-quality/uat-report-2025-01-22.md](./docs/code-quality/uat-report-2025-01-22.md)
|
|
11
|
+
- **Current baseline:** 748 examples, 0 failures, 84.88% line coverage
|
|
33
12
|
|
|
34
13
|
**Also Available:** Code quality retrospective analysis guide at [docs/ai-instructions/code-quality-retrospective.md](./docs/ai-instructions/code-quality-retrospective.md)
|
|
35
14
|
|
data/bin/dam
CHANGED
|
@@ -297,8 +297,7 @@ class VatCLI
|
|
|
297
297
|
puts '📋 Summary - Generated Manifests:'
|
|
298
298
|
puts ''
|
|
299
299
|
|
|
300
|
-
successful = results.
|
|
301
|
-
failed = results.reject { |r| r[:success] }
|
|
300
|
+
successful, failed = results.partition { |r| r[:success] }
|
|
302
301
|
|
|
303
302
|
successful.each do |result|
|
|
304
303
|
brand_display = result[:brand].ljust(15)
|
|
@@ -1567,8 +1566,7 @@ class VatCLI
|
|
|
1567
1566
|
puts '📋 Summary - S3 Scans:'
|
|
1568
1567
|
puts ''
|
|
1569
1568
|
|
|
1570
|
-
successful = results.
|
|
1571
|
-
failed = results.reject { |r| r[:success] }
|
|
1569
|
+
successful, failed = results.partition { |r| r[:success] }
|
|
1572
1570
|
|
|
1573
1571
|
successful.each do |result|
|
|
1574
1572
|
brand_display = result[:brand].ljust(15)
|
data/bin/gpt_context.rb
CHANGED
|
@@ -19,52 +19,95 @@ options = Appydave::Tools::GptContext::Options.new(
|
|
|
19
19
|
)
|
|
20
20
|
|
|
21
21
|
OptionParser.new do |opts|
|
|
22
|
-
opts.banner =
|
|
22
|
+
opts.banner = <<~BANNER
|
|
23
|
+
GPT Context Gatherer - Collect project files for AI context
|
|
23
24
|
|
|
24
|
-
|
|
25
|
+
SYNOPSIS
|
|
26
|
+
gpt_context [options]
|
|
27
|
+
|
|
28
|
+
DESCRIPTION
|
|
29
|
+
Collects and packages codebase files for AI assistant context.
|
|
30
|
+
Outputs to clipboard (default), file, or stdout.
|
|
31
|
+
|
|
32
|
+
BANNER
|
|
33
|
+
|
|
34
|
+
opts.separator 'OPTIONS'
|
|
35
|
+
opts.separator ''
|
|
36
|
+
|
|
37
|
+
opts.on('-i', '--include PATTERN',
|
|
38
|
+
'Glob pattern for files to include (repeatable)',
|
|
39
|
+
'Example: -i "lib/**/*.rb" -i "bin/**/*.rb"') do |pattern|
|
|
25
40
|
options.include_patterns << pattern
|
|
26
41
|
end
|
|
27
42
|
|
|
28
|
-
opts.on('-e', '--exclude PATTERN',
|
|
43
|
+
opts.on('-e', '--exclude PATTERN',
|
|
44
|
+
'Glob pattern for files to exclude (repeatable)',
|
|
45
|
+
'Example: -e "spec/**/*" -e "node_modules/**/*"') do |pattern|
|
|
29
46
|
options.exclude_patterns << pattern
|
|
30
47
|
end
|
|
31
48
|
|
|
32
|
-
opts.on('-f', '--format
|
|
49
|
+
opts.on('-f', '--format FORMATS',
|
|
50
|
+
'Output format(s): tree, content, json, aider, files',
|
|
51
|
+
'Comma-separated. Default: content',
|
|
52
|
+
'Example: -f tree,content') do |format|
|
|
33
53
|
options.format = format
|
|
34
54
|
end
|
|
35
55
|
|
|
36
|
-
opts.on('-l', '--line-limit
|
|
37
|
-
|
|
56
|
+
opts.on('-l', '--line-limit N', Integer,
|
|
57
|
+
'Limit lines per file (default: unlimited)') do |n|
|
|
58
|
+
options.line_limit = n
|
|
38
59
|
end
|
|
39
60
|
|
|
40
|
-
|
|
41
|
-
|
|
61
|
+
opts.on('-b', '--base-dir DIRECTORY',
|
|
62
|
+
'Set the base directory to gather files from') do |directory|
|
|
42
63
|
options.working_directory = directory
|
|
43
64
|
end
|
|
44
65
|
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
opts.on('-d', '--debug [MODE]', 'Enable debug mode [none, info, params, debug]',
|
|
67
|
+
'none', 'info', 'params', 'debug') do |debug|
|
|
47
68
|
options.debug = debug || 'info'
|
|
48
69
|
end
|
|
49
70
|
|
|
50
|
-
|
|
51
|
-
|
|
71
|
+
opts.on('-o', '--output TARGET',
|
|
72
|
+
'Output target: clipboard, filename, or stdout',
|
|
73
|
+
'Default: clipboard. Repeatable for multiple targets.') do |target|
|
|
52
74
|
options.output_target << target
|
|
53
75
|
end
|
|
54
76
|
|
|
55
|
-
opts.on('-p', '--prompt
|
|
77
|
+
opts.on('-p', '--prompt TEXT',
|
|
78
|
+
'Prompt text for aider format output') do |message|
|
|
56
79
|
options.prompt = message
|
|
57
80
|
end
|
|
58
81
|
|
|
59
|
-
opts.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
82
|
+
opts.separator ''
|
|
83
|
+
opts.separator 'OUTPUT FORMATS'
|
|
84
|
+
opts.separator ' tree - Directory tree structure'
|
|
85
|
+
opts.separator ' content - File contents with headers (default)'
|
|
86
|
+
opts.separator ' json - Structured JSON output'
|
|
87
|
+
opts.separator ' aider - Aider CLI command format (requires -p)'
|
|
88
|
+
opts.separator ' files - File paths only'
|
|
89
|
+
opts.separator ''
|
|
90
|
+
opts.separator 'EXAMPLES'
|
|
91
|
+
opts.separator ' # Gather Ruby library code for AI context'
|
|
92
|
+
opts.separator " gpt_context -i 'lib/**/*.rb' -e 'spec/**/*' -d"
|
|
93
|
+
opts.separator ''
|
|
94
|
+
opts.separator ' # Project structure overview'
|
|
95
|
+
opts.separator " gpt_context -i '**/*' -f tree -e 'node_modules/**/*'"
|
|
96
|
+
opts.separator ''
|
|
97
|
+
opts.separator ' # Save to file with tree and content'
|
|
98
|
+
opts.separator " gpt_context -i 'src/**/*.ts' -f tree,content -o context.txt"
|
|
99
|
+
opts.separator ''
|
|
100
|
+
opts.separator ' # Generate aider command'
|
|
101
|
+
opts.separator " gpt_context -i 'lib/**/*.rb' -f aider -p 'Add logging'"
|
|
102
|
+
opts.separator ''
|
|
103
|
+
|
|
104
|
+
opts.on('-v', '--version', 'Show version') do
|
|
105
|
+
puts "gpt_context version #{Appydave::Tools::VERSION}"
|
|
106
|
+
exit
|
|
107
|
+
end
|
|
64
108
|
|
|
65
|
-
|
|
66
|
-
puts
|
|
67
|
-
puts " #{File.basename($PROGRAM_NAME)} -i '**/*gather*.rb'"
|
|
109
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
110
|
+
puts opts
|
|
68
111
|
exit
|
|
69
112
|
end
|
|
70
113
|
end.parse!
|
data/docs/backlog.md
CHANGED
|
@@ -10,7 +10,7 @@ Requirements tracking for AppyDave Tools development.
|
|
|
10
10
|
|---|-------------|-------|--------|
|
|
11
11
|
| 1 | FR-1: GPT Context token counting (see below) | 2025-12-06 | Pending |
|
|
12
12
|
| 2 | FR-2: GPT Context AI-friendly help system (see below) | 2025-12-07 | Pending |
|
|
13
|
-
| 3 | NFR-1: Improve test coverage for DAM commands | 2025-12-06 |
|
|
13
|
+
| 3 | NFR-1: Improve test coverage for DAM commands | 2025-12-06 | ✅ Addressed in DAM sprint (Jan 2025) — +648 lines, 5 new spec files |
|
|
14
14
|
| 4 | FR-3: Jump Location Tool (see spec) | 2025-12-13 | ✅ Implemented 2025-12-13 |
|
|
15
15
|
| 5 | NFR-2: Claude Code Skill for Jump Tool (see below) | 2025-12-14 | ✅ Implemented 2025-12-14 |
|
|
16
16
|
| 6 | BUG-1: Jump CLI get/remove commands fail to find entries (see below) | 2025-12-15 | Pending |
|
data/docs/code-quality/README.md
CHANGED
|
@@ -34,22 +34,21 @@ This directory contains code quality retrospective analyses and improvement plan
|
|
|
34
34
|
|
|
35
35
|
---
|
|
36
36
|
|
|
37
|
-
## Current Status
|
|
38
|
-
|
|
39
|
-
###
|
|
40
|
-
1.
|
|
41
|
-
2.
|
|
42
|
-
3.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
3. **Low Priority** - Documentation, minor cleanups
|
|
37
|
+
## Current Status (updated 2026-03-19)
|
|
38
|
+
|
|
39
|
+
### ✅ Resolved in DAM Enhancement Sprint (Jan 2025)
|
|
40
|
+
1. ✅ **Git Operations Duplication** → extracted to `lib/appydave/tools/dam/git_helper.rb`
|
|
41
|
+
2. ✅ **Brand Resolution Logic** → centralized in `lib/appydave/tools/dam/brand_resolver.rb`
|
|
42
|
+
3. ✅ **Error Handling Inconsistency** → exception hierarchy in `lib/appydave/tools/dam/errors.rb`
|
|
43
|
+
4. ✅ **Directory Utils Duplication** → extracted to `lib/appydave/tools/dam/file_helper.rb`
|
|
44
|
+
5. ✅ **Test Pattern Inconsistency** → `project_listing_spec.rb` refactored to use shared filesystem context
|
|
45
|
+
|
|
46
|
+
### ⏳ Still Outstanding (Low Priority)
|
|
47
|
+
1. ⏳ **Configuration Loading Redundancy** — `Config.configure` called ~7x in config.rb (memoized, safe, but noisy). See BACKLOG.md B011.
|
|
48
|
+
2. ⏳ **CLI Argument Parsing** — `bin/dam` has multiple 200+ line methods. See BACKLOG.md B011.
|
|
49
|
+
3. ⏳ **Integration Tests** — Brand resolution tested unit-only, no end-to-end cross-layer specs. See BACKLOG.md B012.
|
|
50
|
+
|
|
51
|
+
**Baseline:** 748 examples, 0 failures, 84.88% coverage
|
|
53
52
|
|
|
54
53
|
---
|
|
55
54
|
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
# AGENTS.md — AppyDave Tools
|
|
2
|
+
|
|
3
|
+
> Operational knowledge for every background agent. Self-contained — you receive only this file + your work unit prompt.
|
|
4
|
+
> Last updated: 2026-03-19 (derived from actual files, not guesswork)
|
|
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
|
+
**Active area:** DAM (Digital Asset Management) — `lib/appydave/tools/dam/` — is the primary focus of recent campaigns.
|
|
13
|
+
**Commits:** Trigger automated semantic versioning via GitHub Actions. Always use `kfeat`/`kfix` — never `git commit`.
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Build & Run Commands
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# Initialize rbenv (required if rbenv not in PATH)
|
|
21
|
+
eval "$(rbenv init -)"
|
|
22
|
+
|
|
23
|
+
# Run tests
|
|
24
|
+
bundle exec rspec # All tests
|
|
25
|
+
bundle exec rspec spec/path/to/file_spec.rb # Single file
|
|
26
|
+
RUBYOPT="-W0" bundle exec rspec # Suppress Ruby 3.4 platform warnings
|
|
27
|
+
|
|
28
|
+
# Lint
|
|
29
|
+
bundle exec rubocop --format clang # Standard lint check (matches CI)
|
|
30
|
+
|
|
31
|
+
# Commit (never use git commit directly)
|
|
32
|
+
kfeat "add feature description" # Minor version bump
|
|
33
|
+
kfix "fix bug description" # Patch version bump
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
**Baseline (2026-03-19):** 748 examples, 0 failures, 84.88% line coverage (7680/9048)
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
## Directory Structure
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
bin/ CLI scripts (development, .rb extension)
|
|
44
|
+
exe/ Thin wrappers for gem installation (no .rb extension)
|
|
45
|
+
lib/appydave/tools/
|
|
46
|
+
dam/ Digital Asset Management — main active area
|
|
47
|
+
brand_resolver.rb Centralizes ALL brand name transformations (appydave ↔ v-appydave)
|
|
48
|
+
errors.rb Custom exception hierarchy (DamError, BrandNotFoundError, etc.)
|
|
49
|
+
fuzzy_matcher.rb Levenshtein distance for "did you mean?" suggestions
|
|
50
|
+
git_helper.rb Extracted git command wrappers (current_branch, commits_ahead, etc.)
|
|
51
|
+
file_helper.rb File utility methods (directory size, format_size)
|
|
52
|
+
config.rb Delegates brand resolution to BrandResolver; memoized Config loading
|
|
53
|
+
project_resolver.rb Project name resolution with regex pattern matching
|
|
54
|
+
project_listing.rb Table display for `dam list` command (format() for headers + data)
|
|
55
|
+
s3_operations.rb S3 upload/download/status with MD5 comparison
|
|
56
|
+
status.rb Project git/S3 status display
|
|
57
|
+
manifest_generator.rb Video project manifest
|
|
58
|
+
sync_from_ssd.rb SSD sync operations
|
|
59
|
+
ssd_status.rb SSD backup status
|
|
60
|
+
repo_push.rb, repo_status.rb, repo_sync.rb, share_operations.rb, config_loader.rb, s3_scanner.rb
|
|
61
|
+
configuration/ Config file management (settings.json, channels.json)
|
|
62
|
+
gpt_context/ File collection for AI context gathering
|
|
63
|
+
subtitle_processor/ SRT file cleaning and joining
|
|
64
|
+
youtube_manager/ YouTube API integration
|
|
65
|
+
name_manager/ Jump location tool (fuzzy search, CRUD, alias generation)
|
|
66
|
+
types/ BaseModel, ArrayType, HashType, IndifferentAccessHash
|
|
67
|
+
spec/
|
|
68
|
+
appydave/tools/dam/ 14 spec files (one per dam/ class)
|
|
69
|
+
support/
|
|
70
|
+
dam_filesystem_helpers.rb Shared contexts for DAM filesystem testing
|
|
71
|
+
jump_test_helpers.rb Jump tool test helpers
|
|
72
|
+
docs/
|
|
73
|
+
backlog.md Legacy requirements (BACKLOG.md in this folder supersedes)
|
|
74
|
+
code-quality/ Audit reports (behavioral-audit-2025-01-22, uat-report-2025-01-22)
|
|
75
|
+
planning/ Ralphy campaign artifacts (this folder)
|
|
76
|
+
architecture/ CLI patterns, testing patterns, configuration systems
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
## Success Criteria
|
|
82
|
+
|
|
83
|
+
Every work unit must satisfy ALL of the following before marking `[x]`:
|
|
84
|
+
|
|
85
|
+
- [ ] `bundle exec rspec` — 748+ examples, 0 failures
|
|
86
|
+
- [ ] `bundle exec rubocop --format clang` — 0 offenses
|
|
87
|
+
- [ ] Line coverage stays ≥ 84.88%
|
|
88
|
+
- [ ] Any new functionality has ≥ 1 spec covering it
|
|
89
|
+
- [ ] All new `.rb` files start with `# frozen_string_literal: true`
|
|
90
|
+
- [ ] No hardcoded brand transformation strings (always use BrandResolver)
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Reference Patterns
|
|
95
|
+
|
|
96
|
+
### Shared Context for DAM Specs — THE STANDARD PATTERN
|
|
97
|
+
|
|
98
|
+
```ruby
|
|
99
|
+
# spec/appydave/tools/dam/some_class_spec.rb
|
|
100
|
+
# frozen_string_literal: true
|
|
101
|
+
|
|
102
|
+
require 'spec_helper'
|
|
103
|
+
|
|
104
|
+
RSpec.describe Appydave::Tools::Dam::SomeClass do
|
|
105
|
+
include_context 'with vat filesystem and brands', brands: %w[appydave voz]
|
|
106
|
+
|
|
107
|
+
before do
|
|
108
|
+
FileUtils.mkdir_p(File.join(appydave_path, 'b65-test-project'))
|
|
109
|
+
FileUtils.mkdir_p(File.join(voz_path, 'boy-baker'))
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe '.some_method' do
|
|
113
|
+
it 'does the thing' do
|
|
114
|
+
expect(described_class.some_method('appydave')).to eq('expected')
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
**Available from shared context:**
|
|
121
|
+
- `temp_folder` — temp root (auto-cleaned after each example)
|
|
122
|
+
- `projects_root` — `/path/to/temp/video-projects`
|
|
123
|
+
- `appydave_path`, `voz_path`, etc. — brand dirs (created on demand)
|
|
124
|
+
- `SettingsConfig#video_projects_root` is mocked to return `projects_root`
|
|
125
|
+
|
|
126
|
+
### BrandResolver — All Brand Name Transformations
|
|
127
|
+
|
|
128
|
+
```ruby
|
|
129
|
+
BrandResolver.expand('appydave') # => 'v-appydave'
|
|
130
|
+
BrandResolver.expand('ad') # => 'v-appydave' (shortcut)
|
|
131
|
+
BrandResolver.expand('joy') # => 'v-beauty-and-joy'
|
|
132
|
+
BrandResolver.normalize('v-appydave') # => 'appydave'
|
|
133
|
+
BrandResolver.to_config_key('ad') # => 'appydave'
|
|
134
|
+
BrandResolver.to_display('voz') # => 'v-voz'
|
|
135
|
+
BrandResolver.validate('appydave') # => 'appydave' or raises BrandNotFoundError
|
|
136
|
+
BrandResolver.exists?('appydave') # => true/false
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
### Typed Exception Pattern
|
|
140
|
+
|
|
141
|
+
```ruby
|
|
142
|
+
# Use errors from lib/appydave/tools/dam/errors.rb
|
|
143
|
+
raise ProjectNotFoundError, 'Project name is required' if project_hint.nil?
|
|
144
|
+
raise BrandNotFoundError.new(brand, available_brands, fuzzy_suggestions)
|
|
145
|
+
|
|
146
|
+
# Exception hierarchy:
|
|
147
|
+
# DamError < StandardError
|
|
148
|
+
# BrandNotFoundError < DamError
|
|
149
|
+
# ProjectNotFoundError < DamError
|
|
150
|
+
# ConfigurationError < DamError
|
|
151
|
+
# S3OperationError < DamError
|
|
152
|
+
# GitOperationError < DamError
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### Table Display — Headers Must Use format()
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
# CORRECT — headers and data use same format string
|
|
159
|
+
header = format('%-45s %12s %15s %10s', 'PROJECT', 'SIZE', 'AGE', 'GIT')
|
|
160
|
+
row = format('%-45s %12s %15s %10s', name, size, age, git_status)
|
|
161
|
+
|
|
162
|
+
# WRONG — hardcoded header string causes misalignment
|
|
163
|
+
header = 'PROJECT SIZE AGE GIT'
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Anti-Patterns to Avoid
|
|
169
|
+
|
|
170
|
+
- ❌ Inline brand transformations — never write `"v-#{brand}"` or `.sub(/^v-/, '')` outside BrandResolver
|
|
171
|
+
- ❌ Mocking Config class methods in DAM specs — use `include_context 'with vat filesystem and brands'` instead
|
|
172
|
+
- ❌ `raise 'string error'` in DAM module — use typed exceptions from `errors.rb`
|
|
173
|
+
- ❌ Duplicating git command methods — use `GitHelper` module
|
|
174
|
+
- ❌ Duplicating file size calculations — use `FileHelper` module
|
|
175
|
+
- ❌ `include FileUtils` (conflicts with Ruby stdlib) — use dam's `FileHelper`
|
|
176
|
+
- ❌ Hardcoded header strings for table output — always use `format()` with same format string as data rows
|
|
177
|
+
|
|
178
|
+
---
|
|
179
|
+
|
|
180
|
+
## Mock Patterns
|
|
181
|
+
|
|
182
|
+
### External Services — DO Mock
|
|
183
|
+
|
|
184
|
+
```ruby
|
|
185
|
+
# S3 calls — use WebMock or VCR cassettes
|
|
186
|
+
stub_request(:get, /s3\.amazonaws\.com/).to_return(body: '...')
|
|
187
|
+
|
|
188
|
+
# YouTube API — VCR cassettes in spec/fixtures/vcr_cassettes/
|
|
189
|
+
VCR.use_cassette('youtube/get_video') do
|
|
190
|
+
# make API call
|
|
191
|
+
end
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### Internal DAM Classes — DON'T Mock
|
|
195
|
+
|
|
196
|
+
Use real temp filesystem via shared context instead. The only acceptable mock inside DAM specs:
|
|
197
|
+
- `SettingsConfig#video_projects_root` — already mocked by the shared context
|
|
198
|
+
- `Config.available_brands` — acceptable when testing "no brands found" edge case
|
|
199
|
+
|
|
200
|
+
### Config.configure — Safe to Call Multiple Times
|
|
201
|
+
|
|
202
|
+
```ruby
|
|
203
|
+
# Config.configure is memoized — idempotent, no-op after first call
|
|
204
|
+
# Called in multiple places across DAM module; this is known/acceptable technical debt
|
|
205
|
+
Appydave::Tools::Configuration::Config.configure
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
---
|
|
209
|
+
|
|
210
|
+
## Quality Gates
|
|
211
|
+
|
|
212
|
+
- **Tests:** `bundle exec rspec` — 748 examples, 0 failures (do not ship if any fail)
|
|
213
|
+
- **Lint:** `bundle exec rubocop --format clang` — 0 offenses (CI will reject)
|
|
214
|
+
- **Coverage:** ≥ 84.88% line coverage
|
|
215
|
+
- **frozen_string_literal:** Required on every new `.rb` file
|
|
216
|
+
- **Commit format:** `kfeat`/`kfix` only — triggers semantic versioning + CI wait
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Learnings
|
|
221
|
+
|
|
222
|
+
### From DAM Enhancement Sprint (Jan 2025 — 75 commits, 9e49668 → 4228b51)
|
|
223
|
+
|
|
224
|
+
- **BrandResolver is the critical path.** All `dam` commands flow through it. Any change to brand resolution must be tested with all shortcuts (ad, joy, ss, voz, aitldr, kiros) and case variations (APPYDAVE, AppyDave).
|
|
225
|
+
- **`Regexp.last_match` is reset by `.sub()` calls.** Always capture regex groups BEFORE any string transformation: `project = ::Regexp.last_match(2)` then `brand_key = BrandResolver.normalize(brand_with_prefix)`.
|
|
226
|
+
- **`Config.configure` is memoized but called redundantly.** ~7 calls in config.rb, plus more in other files. Known issue, not worsened. Don't add new calls; reference existing ones.
|
|
227
|
+
- **FuzzyMatcher threshold is 3 (Levenshtein distance).** Wired via `Config#brand_path` → `FuzzyMatcher.find_matches(brand_key, all_brand_identifiers, threshold: 3)`. Works for "appydav" → "appydave".
|
|
228
|
+
- **Performance: ~2s per project** for git/S3 checks during `dam list`. 13 projects = ~26s total. Acceptable. Grows linearly — flag if brand has > 20 projects.
|
|
229
|
+
- **Table format() pattern is non-obvious.** Headers misaligned 3 times in UAT before fix. Always verify with real data that has long names (e.g., "beauty-and-joy" = 14 chars).
|
|
230
|
+
- **Test strategy:** 5 new spec files (+648 lines) added for DAM helper classes. `project_listing_spec.rb` refactored from 20 Config mocks to shared filesystem context. Task 3.1 complete.
|
|
231
|
+
|
|
232
|
+
### From Jump Location Tool (Dec 2025)
|
|
233
|
+
|
|
234
|
+
- **Dependency injection for path validators** is required for CI compatibility. Path existence checks fail in CI — inject via parameter, not hardcoded.
|
|
235
|
+
- **BUG-1 status (as of 2026-03-19 audit):** Static analysis shows `Jump::Config#find` and `Commands::Remove` both have correct dual-key guards (`loc.key == key` on Location objects; `loc['key'] == key || loc[:key] == key` on raw hashes). The bug may be environmental or already fixed. Always verify live before writing fix code.
|
|
236
|
+
- **Jump Commands layer is undertested:** `Commands::Remove`, `Commands::Add`, `Commands::Update` have zero dedicated specs. Auto-regenerate CLI spec does not substitute for command-layer unit tests verifying `--force` guards, error codes, and suggestion logic (see B018).
|
|
237
|
+
- **Jump report commands** got `--limit` and `--skip-unassigned` flags after initial implementation. Jump tool scope grows incrementally.
|
|
238
|
+
|
|
239
|
+
### From Three-Lens Audit (2026-03-19)
|
|
240
|
+
|
|
241
|
+
- **`file_collector.rb` has two landmines before FR-2:** `puts @working_directory` at line 15 pollutes stdout; `FileUtils.cd` without `ensure` leaves process in wrong directory on exception. Fix both before adding any code to this class.
|
|
242
|
+
- **ManifestGenerator and SyncFromSsd produce incompatible range strings (B016).** `determine_range('b65')` returns `"b50-b99"` in one and `"60-69"` in the other. This is a data integrity bug for SSD archive path construction. Do not add new archive features before this is resolved.
|
|
243
|
+
- **`ssl_verify_peer: false` is set unconditionally in S3Operations and ShareOperations (B017).** Not safe despite the comment. Remove before adding any new S3 functionality.
|
|
244
|
+
- **`Config.configure` fires inside nested call chains** (e.g., `brand_path` → `BrandResolver.to_config_key` → `configure` = 3 calls for one operation). Memoized, so no performance cost, but pattern will spread if not watched. Do not add new `Config.configure` calls; reference from the existing top-level call.
|
|
245
|
+
- **BUG-1 is NOT in `name_manager/`.** Jump's `name_manager/project_name.rb` is a different unrelated class. BUG-1 root is in `lib/appydave/tools/jump/` (Config, Search, Commands).
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
# Project Backlog — AppyDave Tools
|
|
2
|
+
|
|
3
|
+
**Last updated**: 2026-03-19 (updated after three-lens audit)
|
|
4
|
+
**Total**: 20 | Pending: 14 | Done: 6 | Deferred: 0 | Rejected: 0
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Pending
|
|
9
|
+
|
|
10
|
+
### High Priority
|
|
11
|
+
- [ ] 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
|
+
- [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
|
+
|
|
17
|
+
### Medium Priority
|
|
18
|
+
- [ ] B018 — Tests: add specs for Jump Commands::Remove, Commands::Add, Commands::Update | Priority: medium
|
|
19
|
+
- [ ] B019 — Fix: remove debug puts @working_directory from gpt_context/file_collector.rb | Priority: medium
|
|
20
|
+
- [ ] B001 — FR-1: GPT Context token counting | Priority: medium
|
|
21
|
+
- [ ] B012 — Arch: add integration tests for brand resolution end-to-end | Priority: medium
|
|
22
|
+
|
|
23
|
+
### Low Priority
|
|
24
|
+
- [ ] B007 — Performance: parallel git/S3 status checks for dam list | Priority: low
|
|
25
|
+
- [ ] B008 — Performance: cache git/S3 status with 5-min TTL | Priority: low
|
|
26
|
+
- [ ] B009 — UX: progress indicators for dam operations > 5s | Priority: low
|
|
27
|
+
- [ ] B010 — UX: auto-adjust dam table column widths to terminal width | Priority: low
|
|
28
|
+
- [ ] B011 — Arch: extract VatCLI business logic from bin/dam (1,600-line God class) | Priority: low
|
|
29
|
+
- [ ] B020 — Arch: split S3Operations (1,030 lines, mixed I/O + logic) | Priority: low
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Done
|
|
34
|
+
|
|
35
|
+
- [x] B003 — NFR-1: Improve DAM test coverage | Completed: dam-enhancement-sprint (Jan 2025)
|
|
36
|
+
- [x] B004 — FR-3: Jump Location Tool | Completed: 2025-12-13
|
|
37
|
+
- [x] B005 — NFR-2: Jump Claude Code Skill | Completed: 2025-12-14
|
|
38
|
+
- [x] B013 — Arch: Extract GitHelper module (90 lines duplication) | Completed: dam-enhancement-sprint (Jan 2025)
|
|
39
|
+
- [x] B014 — Arch: Create BrandResolver to centralize brand transformation | Completed: dam-enhancement-sprint (Jan 2025)
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Item Details
|
|
44
|
+
|
|
45
|
+
### B001 — FR-1: GPT Context Token Counting
|
|
46
|
+
|
|
47
|
+
**User Story**: As a developer using GPT Context, I want to see estimated token counts so I can ensure my context fits within LLM limits.
|
|
48
|
+
|
|
49
|
+
**Acceptance Criteria:**
|
|
50
|
+
- [ ] Display estimated token count in output
|
|
51
|
+
- [ ] Support common tokenizers (cl100k for GPT-4, claude for Claude)
|
|
52
|
+
- [ ] Show warning when exceeding common thresholds (100k, 200k)
|
|
53
|
+
- [ ] Optional via `--tokens` flag
|
|
54
|
+
|
|
55
|
+
**Notes:** Consider tiktoken gem for OpenAI tokenization. May need to estimate for Claude (no official Ruby tokenizer).
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
### B002 — FR-2: GPT Context AI-Friendly Help System
|
|
60
|
+
|
|
61
|
+
**Spec:** `docs/specs/fr-002-gpt-context-help-system.md`
|
|
62
|
+
|
|
63
|
+
**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.
|
|
64
|
+
|
|
65
|
+
**Notes:** Full spec exists. High priority — enables AI skill integration.
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
### B006 — BUG-1: Jump CLI get/remove Key Lookup Bug
|
|
70
|
+
|
|
71
|
+
**Priority:** High — but verify live first
|
|
72
|
+
|
|
73
|
+
**⚠️ 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.**
|
|
74
|
+
|
|
75
|
+
**Steps to Reproduce:**
|
|
76
|
+
```bash
|
|
77
|
+
bin/jump.rb search awb-team # ✅ finds entry
|
|
78
|
+
bin/jump.rb get awb-team # ❌ "Location not found" ← confirm this still fails
|
|
79
|
+
bin/jump.rb remove test-minimal --force # ❌ "No locations found."
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
**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.
|
|
83
|
+
|
|
84
|
+
**Acceptance Criteria:**
|
|
85
|
+
- [ ] Confirm bug still exists live (if not, write regression spec and close)
|
|
86
|
+
- [ ] `get <key>` finds entry when `search <key>` finds it
|
|
87
|
+
- [ ] `remove <key>` finds entry when `search <key>` finds it
|
|
88
|
+
- [ ] Regression tests for key lookup consistency
|
|
89
|
+
- [ ] Root cause documented in commit message
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
### B007 — Performance: Parallel git/S3 Status Checks
|
|
94
|
+
|
|
95
|
+
**Context:** `dam list appydave` with 13 projects takes ~26s (sequential git+S3 check per project).
|
|
96
|
+
**Suggested:** Parallel status checks using Ruby threads or concurrent-ruby.
|
|
97
|
+
**Source:** UAT report 2025-01-22 post-release recommendations.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
### B008 — Performance: Cache git/S3 Status
|
|
102
|
+
|
|
103
|
+
**Context:** Same sequential bottleneck as B007. Complementary approach.
|
|
104
|
+
**Suggested:** Cache git/S3 status per project with 5-minute TTL.
|
|
105
|
+
**Source:** UAT report 2025-01-22 post-release recommendations.
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
### B009 — UX: Progress Indicators
|
|
110
|
+
|
|
111
|
+
**Context:** Operations taking > 5s show no feedback.
|
|
112
|
+
**Suggested:** Spinner or "checking project 3/13..." output for long-running dam commands.
|
|
113
|
+
**Source:** UAT report 2025-01-22 post-release recommendations.
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
### B010 — UX: Auto-Adjust Table Column Widths
|
|
118
|
+
|
|
119
|
+
**Context:** Column widths are hardcoded (e.g., KEY column = 15 chars). Terminal resizing or very long names cause misalignment.
|
|
120
|
+
**Suggested:** Detect terminal width and/or measure data to set column widths dynamically.
|
|
121
|
+
**Source:** UAT report 2025-01-22 post-release recommendations.
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
### B011 — Arch: Extract VatCLI Business Logic from bin/dam
|
|
126
|
+
|
|
127
|
+
**Context:** `bin/dam` is 1,600 lines. Methods `scan_single_brand_s3`, `add_local_sync_status!`, `display_s3_scan_table`, `parse_s3_args`, `format_bytes` are business/display logic that belongs in library classes. 20+ rubocop-disable comments are symptoms.
|
|
128
|
+
**Suggested:** Extract to library classes before adding DAM parallelism (B007/B008) — those features cannot be built cleanly in VatCLI.
|
|
129
|
+
**Source:** Architectural review 2026-03-19, Critical concern #1.
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
### B012 — Arch: Integration Tests for Brand Resolution
|
|
134
|
+
|
|
135
|
+
**Context:** BrandResolver, Config, ProjectResolver interact across layers. Unit tests cover each individually but no end-to-end test catches cross-layer bugs.
|
|
136
|
+
**Suggested:** Integration specs that test brand → project resolution across the full call chain.
|
|
137
|
+
**Source:** Code quality report 2025-01-21 + architectural review 2026-03-19.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
### B015 — BUG-2: FileCollector FileUtils.cd Without ensure
|
|
142
|
+
|
|
143
|
+
**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.
|
|
144
|
+
**Fix:** Wrap in block form: `FileUtils.cd(@working_directory) { ... }` — Ruby handles restore automatically. Or add `ensure FileUtils.cd(Dir.home)`.
|
|
145
|
+
**Blocker for:** FR-2 — fix this before adding more code paths to `file_collector.rb`.
|
|
146
|
+
**Source:** Code quality audit 2026-03-19, MAJOR issue #2.
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
### B016 — BUG-3: ManifestGenerator vs SyncFromSsd Incompatible Range Strings
|
|
151
|
+
|
|
152
|
+
**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.
|
|
153
|
+
**Fix:** Standardise both methods on one format. Decide which format matches actual SSD folder structure on disk, then update the other method to match.
|
|
154
|
+
**Source:** Code quality audit 2026-03-19, MAJOR issue #1.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
### B017 — Security: ssl_verify_peer Disabled in S3Operations + ShareOperations
|
|
159
|
+
|
|
160
|
+
**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.
|
|
161
|
+
**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.
|
|
162
|
+
**Source:** Code quality audit 2026-03-19, MAJOR issue #3.
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### B018 — Tests: Jump Commands Layer Has No Dedicated Specs
|
|
167
|
+
|
|
168
|
+
**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.
|
|
169
|
+
**Fix:** Add `spec/appydave/tools/jump/commands/remove_spec.rb`, `add_spec.rb`, `update_spec.rb`. Use `JumpTestLocations` factory + `with jump filesystem` context.
|
|
170
|
+
**Source:** Test quality audit 2026-03-19, RISK-1.
|
|
171
|
+
|
|
172
|
+
---
|
|
173
|
+
|
|
174
|
+
### B019 — Fix: Remove Debug puts From file_collector.rb
|
|
175
|
+
|
|
176
|
+
**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.
|
|
177
|
+
**Fix:** Delete line 15.
|
|
178
|
+
**Source:** Code quality audit 2026-03-19, MINOR issue #4.
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
### B020 — Arch: Split S3Operations (1,030 lines)
|
|
183
|
+
|
|
184
|
+
**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).
|
|
185
|
+
**Suggested:** Split into at minimum `S3Uploader`, `S3Downloader`, `S3StatusChecker`, `S3Archiver` with I/O separated from computation. Required before B007 (parallelism) can be built.
|
|
186
|
+
**Source:** Architectural review 2026-03-19, Critical concern #2.
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# AGENTS.md — fr2-gpt-context-help
|
|
2
|
+
|
|
3
|
+
> Operational knowledge for this campaign's background agents.
|
|
4
|
+
> Inherited from docs/planning/AGENTS.md (2026-03-19). Campaign-specific additions below.
|
|
5
|
+
> Self-contained — you receive only this file + your work unit prompt.
|
|
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:** FR-2 — enhance `bin/gpt_context.rb` OptionParser with structured help system. One file. No lib/ changes.
|
|
14
|
+
**Commits:** Always use `kfeat`/`kfix` — never `git commit`.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Build & Run Commands
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# Initialize rbenv (required if rbenv not in PATH)
|
|
22
|
+
eval "$(rbenv init -)"
|
|
23
|
+
|
|
24
|
+
# Run tests
|
|
25
|
+
bundle exec rspec # All tests
|
|
26
|
+
bundle exec rspec spec/appydave/tools/gpt_context/ # GPT context specs only
|
|
27
|
+
RUBYOPT="-W0" bundle exec rspec # Suppress Ruby 3.4 platform warnings
|
|
28
|
+
|
|
29
|
+
# Lint
|
|
30
|
+
bundle exec rubocop --format clang # Standard lint check (matches CI)
|
|
31
|
+
|
|
32
|
+
# Manual verification
|
|
33
|
+
bin/gpt_context.rb --help # Should show structured help
|
|
34
|
+
bin/gpt_context.rb --version # Should show version
|
|
35
|
+
bin/gpt_context.rb -v # Short version flag
|
|
36
|
+
bin/gpt_context.rb --help | grep -E "^(SYNOPSIS|DESCRIPTION|OPTIONS|OUTPUT FORMATS|EXAMPLES)"
|
|
37
|
+
|
|
38
|
+
# Commit (never use git commit directly)
|
|
39
|
+
kfeat "add AI-friendly help system to GPT Context" # Use this exact message
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Baseline (2026-03-19):** 748 examples, 0 failures, 84.88% line coverage (7680/9048)
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Directory Structure
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
bin/gpt_context.rb ← THE ONLY FILE TO CHANGE
|
|
50
|
+
lib/appydave/tools/gpt_context/
|
|
51
|
+
file_collector.rb Read-only reference (DO NOT MODIFY)
|
|
52
|
+
options.rb Read-only reference (DO NOT MODIFY)
|
|
53
|
+
output_handler.rb Read-only reference (DO NOT MODIFY)
|
|
54
|
+
lib/appydave/tools/version.rb Read-only — VERSION constant lives here
|
|
55
|
+
spec/appydave/tools/gpt_context/
|
|
56
|
+
cli_spec.rb ← CREATE THIS (new file)
|
|
57
|
+
file_collector_spec.rb Existing — do not modify
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
---
|
|
61
|
+
|
|
62
|
+
## Success Criteria
|
|
63
|
+
|
|
64
|
+
Every work unit must satisfy ALL before marking `[x]`:
|
|
65
|
+
|
|
66
|
+
- [ ] `bundle exec rspec` — 748+ examples, 0 failures (new specs add to this count)
|
|
67
|
+
- [ ] `bundle exec rubocop --format clang` — 0 offenses
|
|
68
|
+
- [ ] Line coverage stays ≥ 84.88%
|
|
69
|
+
- [ ] `bin/gpt_context.rb --help` output includes SYNOPSIS, DESCRIPTION, OPTIONS, OUTPUT FORMATS, EXAMPLES sections
|
|
70
|
+
- [ ] `bin/gpt_context.rb --version` outputs `gpt_context version X.Y.Z`
|
|
71
|
+
- [ ] `spec/appydave/tools/gpt_context/cli_spec.rb` exists with ≥ 3 passing tests
|
|
72
|
+
- [ ] Banner no longer says `gather_content.rb` — it says `gpt_context`
|
|
73
|
+
- [ ] `# frozen_string_literal: true` at top of new spec file
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
## Work Unit Spec
|
|
78
|
+
|
|
79
|
+
### fr2-gpt-context-help — Implement AI-friendly help system
|
|
80
|
+
|
|
81
|
+
**File to modify:** `bin/gpt_context.rb`
|
|
82
|
+
|
|
83
|
+
**What to do:**
|
|
84
|
+
|
|
85
|
+
1. Replace the `opts.banner` line with a heredoc banner containing Synopsis and Description sections
|
|
86
|
+
2. Add `opts.separator` calls for OUTPUT FORMATS and EXAMPLES sections after the options
|
|
87
|
+
3. Add `--version` / `-v` flag before the `--help` flag
|
|
88
|
+
4. Enhance each option's description to include defaults and examples (multi-line array format)
|
|
89
|
+
5. Fix the banner script name: currently `gather_content.rb` → should be `gpt_context`
|
|
90
|
+
|
|
91
|
+
**Full implementation pattern** (from spec, Option A):
|
|
92
|
+
|
|
93
|
+
```ruby
|
|
94
|
+
OptionParser.new do |opts|
|
|
95
|
+
opts.banner = <<~BANNER
|
|
96
|
+
GPT Context Gatherer - Collect project files for AI context
|
|
97
|
+
|
|
98
|
+
SYNOPSIS
|
|
99
|
+
gpt_context [options]
|
|
100
|
+
|
|
101
|
+
DESCRIPTION
|
|
102
|
+
Collects and packages codebase files for AI assistant context.
|
|
103
|
+
Outputs to clipboard (default), file, or stdout.
|
|
104
|
+
|
|
105
|
+
BANNER
|
|
106
|
+
|
|
107
|
+
opts.separator "OPTIONS"
|
|
108
|
+
opts.separator ""
|
|
109
|
+
|
|
110
|
+
opts.on('-i', '--include PATTERN',
|
|
111
|
+
'Glob pattern for files to include (repeatable)',
|
|
112
|
+
'Example: -i "lib/**/*.rb" -i "bin/**/*.rb"') do |pattern|
|
|
113
|
+
options.include_patterns << pattern
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
opts.on('-e', '--exclude PATTERN',
|
|
117
|
+
'Glob pattern for files to exclude (repeatable)',
|
|
118
|
+
'Example: -e "spec/**/*" -e "node_modules/**/*"') do |pattern|
|
|
119
|
+
options.exclude_patterns << pattern
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
opts.on('-f', '--format FORMATS',
|
|
123
|
+
'Output format(s): tree, content, json, aider, files',
|
|
124
|
+
'Comma-separated. Default: content',
|
|
125
|
+
'Example: -f tree,content') do |format|
|
|
126
|
+
options.format = format
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
opts.on('-o', '--output TARGET',
|
|
130
|
+
'Output target: clipboard, filename, or stdout',
|
|
131
|
+
'Default: clipboard. Repeatable for multiple targets.') do |target|
|
|
132
|
+
options.output_target << target
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
opts.on('-d', '--debug [MODE]', 'Enable debug mode [none, info, params, debug]',
|
|
136
|
+
'none', 'info', 'params', 'debug') do |debug|
|
|
137
|
+
options.debug = debug || 'info'
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
opts.on('-l', '--line-limit N', Integer,
|
|
141
|
+
'Limit lines per file (default: unlimited)') do |n|
|
|
142
|
+
options.line_limit = n
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
opts.on('-b', '--base-dir DIRECTORY',
|
|
146
|
+
'Set the base directory to gather files from') do |directory|
|
|
147
|
+
options.working_directory = directory
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
opts.on('-p', '--prompt TEXT',
|
|
151
|
+
'Prompt text for aider format output') do |message|
|
|
152
|
+
options.prompt = message
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
opts.separator ""
|
|
156
|
+
opts.separator "OUTPUT FORMATS"
|
|
157
|
+
opts.separator " tree - Directory tree structure"
|
|
158
|
+
opts.separator " content - File contents with headers (default)"
|
|
159
|
+
opts.separator " json - Structured JSON output"
|
|
160
|
+
opts.separator " aider - Aider CLI command format (requires -p)"
|
|
161
|
+
opts.separator " files - File paths only"
|
|
162
|
+
opts.separator ""
|
|
163
|
+
opts.separator "EXAMPLES"
|
|
164
|
+
opts.separator " # Gather Ruby library code for AI context"
|
|
165
|
+
opts.separator " gpt_context -i 'lib/**/*.rb' -e 'spec/**/*' -d"
|
|
166
|
+
opts.separator ""
|
|
167
|
+
opts.separator " # Project structure overview"
|
|
168
|
+
opts.separator " gpt_context -i '**/*' -f tree -e 'node_modules/**/*'"
|
|
169
|
+
opts.separator ""
|
|
170
|
+
opts.separator " # Save to file with tree and content"
|
|
171
|
+
opts.separator " gpt_context -i 'src/**/*.ts' -f tree,content -o context.txt"
|
|
172
|
+
opts.separator ""
|
|
173
|
+
opts.separator " # Generate aider command"
|
|
174
|
+
opts.separator " gpt_context -i 'lib/**/*.rb' -f aider -p 'Add logging'"
|
|
175
|
+
opts.separator ""
|
|
176
|
+
|
|
177
|
+
opts.on('-v', '--version', 'Show version') do
|
|
178
|
+
puts "gpt_context version #{Appydave::Tools::VERSION}"
|
|
179
|
+
exit
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
opts.on_tail('-h', '--help', 'Show this help') do
|
|
183
|
+
puts opts
|
|
184
|
+
exit
|
|
185
|
+
end
|
|
186
|
+
end.parse!
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**New spec file** `spec/appydave/tools/gpt_context/cli_spec.rb`:
|
|
190
|
+
|
|
191
|
+
```ruby
|
|
192
|
+
# frozen_string_literal: true
|
|
193
|
+
|
|
194
|
+
RSpec.describe 'gpt_context CLI help' do
|
|
195
|
+
let(:script) { File.expand_path('../../../../bin/gpt_context.rb', __dir__) }
|
|
196
|
+
|
|
197
|
+
describe '--help' do
|
|
198
|
+
subject(:output) { `ruby #{script} --help 2>&1` }
|
|
199
|
+
|
|
200
|
+
it 'includes SYNOPSIS section' do
|
|
201
|
+
expect(output).to include('SYNOPSIS')
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it 'includes EXAMPLES section' do
|
|
205
|
+
expect(output).to include('EXAMPLES')
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it 'includes OUTPUT FORMATS section' do
|
|
209
|
+
expect(output).to include('OUTPUT FORMATS')
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
describe '--version' do
|
|
214
|
+
it 'shows version number' do
|
|
215
|
+
output = `ruby #{script} --version 2>&1`
|
|
216
|
+
expect(output).to match(/gpt_context version \d+\.\d+\.\d+/)
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Anti-Patterns to Avoid
|
|
225
|
+
|
|
226
|
+
- ❌ Do NOT modify any file in `lib/` — this campaign is bin/ only
|
|
227
|
+
- ❌ Do NOT use `opts.on_tail` for `--version` (use `opts.on` so it appears before `--help` in output)
|
|
228
|
+
- ❌ Do NOT leave the banner saying `gather_content.rb`
|
|
229
|
+
- ❌ Do NOT require spec_helper explicitly — it's auto-required via `.rspec` config
|
|
230
|
+
- ❌ Do NOT use `system()` or backticks in specs to call the script with a path that includes spaces
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
## Quality Gates
|
|
235
|
+
|
|
236
|
+
- **Tests:** `bundle exec rspec` — 748+ examples, 0 failures
|
|
237
|
+
- **Lint:** `bundle exec rubocop --format clang` — 0 offenses
|
|
238
|
+
- **Coverage:** ≥ 84.88% line coverage
|
|
239
|
+
- **Manual:** `bin/gpt_context.rb --help` and `--version` work as expected
|
|
240
|
+
- **Commit format:** `kfeat "add AI-friendly help system to GPT Context"`
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Learnings (inherited)
|
|
245
|
+
|
|
246
|
+
### From Three-Lens Audit (2026-03-19)
|
|
247
|
+
- `file_collector.rb` pre-conditions (B015, B019) already fixed in commit 13d5f87 — do not re-fix
|
|
248
|
+
- BUG-1 already verified fixed — do not re-investigate
|
|
249
|
+
|
|
250
|
+
### From DAM Enhancement Sprint (Jan 2025)
|
|
251
|
+
- `Config.configure` is memoized — idempotent
|
|
252
|
+
- Table format() pattern: always use same format string for headers and data rows
|
|
253
|
+
|
|
254
|
+
### From Jump Location Tool (Dec 2025)
|
|
255
|
+
- Dependency injection for path validators required for CI compatibility
|
|
256
|
+
- Jump Commands layer is undertested — not relevant to this campaign
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# IMPLEMENTATION_PLAN.md — fr2-gpt-context-help
|
|
2
|
+
|
|
3
|
+
**Goal**: Enhance GPT Context CLI with AI-friendly help system (FR-2)
|
|
4
|
+
**Started**: 2026-03-19
|
|
5
|
+
**Target**: `--help` shows structured sections; `--version` works; specs pass; rubocop clean
|
|
6
|
+
|
|
7
|
+
## Summary
|
|
8
|
+
- Total: 1 | Complete: 0 | In Progress: 0 | Pending: 1 | Failed: 0
|
|
9
|
+
|
|
10
|
+
## Pending
|
|
11
|
+
|
|
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
|
+
|
|
15
|
+
## Complete
|
|
16
|
+
|
|
17
|
+
## Failed / Needs Retry
|
|
18
|
+
|
|
19
|
+
## Notes & Decisions
|
|
20
|
+
- Pre-conditions already satisfied: B015 (FileUtils.cd) and B019 (debug puts) fixed in commit 13d5f87
|
|
21
|
+
- Implementation is Option A from spec: enhanced OptionParser only — no changes to lib/
|
|
22
|
+
- Fix banner script name while in there (currently says gather_content.rb, should say gpt_context)
|
|
23
|
+
- New spec file: spec/appydave/tools/gpt_context/cli_spec.rb (3 tests minimum)
|
|
24
|
+
- Commit with: kfeat "add AI-friendly help system to GPT Context"
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Next Round Brief
|
|
2
|
+
|
|
3
|
+
**Created:** 2026-03-19
|
|
4
|
+
**Updated:** 2026-03-19 (after three-lens audit)
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Recommended Next Campaign: gpt_context Fixes + FR-2 + Jump Verification
|
|
9
|
+
|
|
10
|
+
### Goal
|
|
11
|
+
|
|
12
|
+
Fix the two small blockers in `gpt_context/file_collector.rb` (B015, B019), then implement FR-2 (GPT Context AI help system). In parallel, verify whether BUG-1 (Jump get/remove) is still live before planning a Jump campaign.
|
|
13
|
+
|
|
14
|
+
### Background
|
|
15
|
+
|
|
16
|
+
**Three-lens audit findings changed the priority order:**
|
|
17
|
+
|
|
18
|
+
1. FR-2 has two small pre-conditions in `file_collector.rb` that must be fixed first:
|
|
19
|
+
- `puts @working_directory` at line 15 (B019 — 1 line delete)
|
|
20
|
+
- `FileUtils.cd` without `ensure` (B015 — wrap in block form)
|
|
21
|
+
Both are ~5 minutes of work. Do them as the first commit of the FR-2 campaign.
|
|
22
|
+
|
|
23
|
+
2. BUG-1 (Jump get/remove) is mislabeled in the original backlog. Static analysis shows `Jump::Config#find` and `Commands::Remove` have correct dual-key guards. The bug may already be fixed or may be environmental. **Verify live before planning any Jump campaign.**
|
|
24
|
+
|
|
25
|
+
3. New high-priority bugs found by the audit (B016, B017) should be assessed for inclusion in the next campaign or scheduled shortly after.
|
|
26
|
+
|
|
27
|
+
### Suggested Work Units (FR-2 Campaign)
|
|
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)
|
|
48
|
+
|
|
49
|
+
- B016 — ManifestGenerator vs SyncFromSsd range string mismatch (data integrity — schedule next)
|
|
50
|
+
- B017 — ssl_verify_peer: false in S3Operations (security — schedule next)
|
|
51
|
+
- B018 — Jump Commands layer specs (no specs for Remove/Add/Update)
|
|
52
|
+
|
|
53
|
+
### Mode Recommendation
|
|
54
|
+
|
|
55
|
+
**Extend** — stack, patterns, and quality gates are known from prior campaigns. Use Extend, not Plan.
|
|
@@ -12,36 +12,29 @@ module Appydave
|
|
|
12
12
|
@exclude_patterns = options.exclude_patterns
|
|
13
13
|
@format = options.format
|
|
14
14
|
@working_directory = File.expand_path(options.working_directory)
|
|
15
|
-
puts @working_directory
|
|
16
15
|
@line_limit = options.line_limit
|
|
17
16
|
end
|
|
18
17
|
|
|
19
18
|
def build
|
|
20
|
-
|
|
19
|
+
return build_formats unless @working_directory && Dir.exist?(@working_directory)
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
FileUtils.cd(@working_directory) { build_formats }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def build_formats
|
|
27
|
+
@format.split(',').map do |fmt|
|
|
24
28
|
case fmt
|
|
25
|
-
when 'tree'
|
|
26
|
-
|
|
27
|
-
when '
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
build_json
|
|
31
|
-
when 'aider'
|
|
32
|
-
build_aider
|
|
33
|
-
else
|
|
34
|
-
''
|
|
29
|
+
when 'tree' then build_tree
|
|
30
|
+
when 'content' then build_content
|
|
31
|
+
when 'json' then build_json
|
|
32
|
+
when 'aider' then build_aider
|
|
33
|
+
else ''
|
|
35
34
|
end
|
|
36
35
|
end.join("\n\n")
|
|
37
|
-
|
|
38
|
-
FileUtils.cd(Dir.home) if @working_directory
|
|
39
|
-
|
|
40
|
-
result
|
|
41
36
|
end
|
|
42
37
|
|
|
43
|
-
private
|
|
44
|
-
|
|
45
38
|
def build_content
|
|
46
39
|
concatenated_content = []
|
|
47
40
|
|
data/package.json
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: appydave-tools
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.76.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Cruwys
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-03-19 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activemodel
|
|
@@ -295,6 +295,11 @@ files:
|
|
|
295
295
|
- docs/guides/tools/video-file-namer.md
|
|
296
296
|
- docs/guides/tools/youtube-automation.md
|
|
297
297
|
- docs/guides/tools/youtube-manager.md
|
|
298
|
+
- docs/planning/AGENTS.md
|
|
299
|
+
- docs/planning/BACKLOG.md
|
|
300
|
+
- docs/planning/fr2-gpt-context-help/AGENTS.md
|
|
301
|
+
- docs/planning/fr2-gpt-context-help/IMPLEMENTATION_PLAN.md
|
|
302
|
+
- docs/planning/next-round-brief.md
|
|
298
303
|
- docs/specs/fr-002-gpt-context-help-system.md
|
|
299
304
|
- docs/specs/fr-003-jump-location-tool.md
|
|
300
305
|
- docs/specs/zsh-history-tool.md
|