appydave-tools 0.83.0 → 0.84.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/docs/planning/query-location-feature/IMPLEMENTATION_PLAN.md +142 -0
- data/docs/planning/query-location-feature/system-context-gap-analysis.md +107 -0
- data/lib/appydave/tools/jump/cli.rb +78 -0
- data/lib/appydave/tools/jump/commands/query.rb +112 -0
- data/lib/appydave/tools/version.rb +1 -1
- data/lib/appydave/tools.rb +1 -0
- data/package.json +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bbde49937db92444ee47416c1fbd53d0cd3ca6c99bc65b30e30a58cf2490facc
|
|
4
|
+
data.tar.gz: 1807239701f53c00bd7e692c51e6792056b2e951d0b71720059fdd5c5fbd4414
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: be1b84a9fb1b45b7377c8cc0e0371f234b5b56e96f23a44f1733e6face17c489a288bd3f8128a5e8548eb09247ff3deffd38144eb6480214b5ba8401406bf022
|
|
7
|
+
data.tar.gz: e3cffdedb85686158bc251361f04b0b2ea44f354f472968efd92bf84c165dd1aa69ca37aa0e1105c191b5f84d70ccccbf0ed7e9418e0e194dbf1a1dceca0bfd8
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
# [0.83.0](https://github.com/appydave/appydave-tools/compare/v0.82.0...v0.83.0) (2026-04-04)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* rename format_tokens param n to count to satisfy Naming/MethodParameterName ([e49d615](https://github.com/appydave/appydave-tools/commit/e49d61517a89b05f6c21bd4c5852a3ec59a74a55))
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* add --smart flag for auto-routing output by token size ([a9466e0](https://github.com/appydave/appydave-tools/commit/a9466e059b5164a83902580bbfac5031e3a2dfe3))
|
|
12
|
+
|
|
1
13
|
# [0.82.0](https://github.com/appydave/appydave-tools/compare/v0.81.0...v0.82.0) (2026-04-04)
|
|
2
14
|
|
|
3
15
|
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# FR-NEW: Query Location & App Registry Integration
|
|
2
|
+
|
|
3
|
+
**Status**: Proposed
|
|
4
|
+
**Priority**: Medium
|
|
5
|
+
**Created**: 2026-04-05
|
|
6
|
+
**Relates to**: `query_brain`, `llm_context` pipeline; `locations.json`, `apps.json`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Problem
|
|
11
|
+
|
|
12
|
+
`query_brain` and `llm_context` work well for brain files but have no way to resolve project paths from the existing registries. When a user says "package the FliVideo project for LLM research", there is no single command that:
|
|
13
|
+
1. Looks up the project path from `locations.json` or `apps.json`
|
|
14
|
+
2. Knows which file groupings are relevant (docs, code, prompts, tests)
|
|
15
|
+
3. Feeds those paths directly into `llm_context`
|
|
16
|
+
|
|
17
|
+
Instead, the user must manually look up the path and write the `llm_context` invocation by hand every time.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Proposed Solution
|
|
22
|
+
|
|
23
|
+
### Option A — `query_location` CLI (preferred)
|
|
24
|
+
|
|
25
|
+
New binary `bin/query_location.rb` that queries `~/.config/appydave/locations.json` and `~/.config/appydave/apps.json` by key, name, type, or brand.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Find a project by key or name
|
|
29
|
+
query_location --find flivideo
|
|
30
|
+
query_location --find ss-prompt
|
|
31
|
+
|
|
32
|
+
# List all products
|
|
33
|
+
query_location --type product
|
|
34
|
+
|
|
35
|
+
# Get path only (for piping)
|
|
36
|
+
query_location --find flivideo --path-only
|
|
37
|
+
|
|
38
|
+
# Get JSON metadata
|
|
39
|
+
query_location --find flivideo --meta
|
|
40
|
+
|
|
41
|
+
# List all apps from apps.json
|
|
42
|
+
query_location --apps
|
|
43
|
+
query_location --apps --status active
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Output modes:
|
|
47
|
+
- Default: path on a single line (pipeable to `llm_context`)
|
|
48
|
+
- `--meta`: JSON with key, path, description, type, status
|
|
49
|
+
- `--path-only`: bare path string
|
|
50
|
+
|
|
51
|
+
### Option B — Extend `jump.rb` with a query subcommand
|
|
52
|
+
|
|
53
|
+
Add `jump.rb query --find flivideo` rather than a new binary. Lower overhead, shares existing location-loading code.
|
|
54
|
+
|
|
55
|
+
**Recommendation**: Option B — reuse `jump.rb` infrastructure, add a `query` subcommand that outputs path/meta. Less surface area, same capability.
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## File Groupings (Phase 2)
|
|
60
|
+
|
|
61
|
+
Once location lookup works, the second gap is "which files within a project are relevant for LLM research?" Today the user must specify patterns manually.
|
|
62
|
+
|
|
63
|
+
**Proposed**: A `.llm-groups.yaml` sidecar file at the project root declaring named groupings:
|
|
64
|
+
|
|
65
|
+
```yaml
|
|
66
|
+
# .llm-groups.yaml
|
|
67
|
+
groups:
|
|
68
|
+
docs:
|
|
69
|
+
- "docs/**/*.md"
|
|
70
|
+
- "README.md"
|
|
71
|
+
- "CLAUDE.md"
|
|
72
|
+
code:
|
|
73
|
+
- "lib/**/*.rb"
|
|
74
|
+
- "bin/**/*.rb"
|
|
75
|
+
tests:
|
|
76
|
+
- "spec/**/*.rb"
|
|
77
|
+
prompts:
|
|
78
|
+
- "poem/**/*.json"
|
|
79
|
+
- "poem/**/*.yaml"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Then:
|
|
83
|
+
```bash
|
|
84
|
+
# Package docs group for LLM
|
|
85
|
+
query_location --find appydave-tools --path-only | xargs -I{} llm_context -b {} --groups docs
|
|
86
|
+
|
|
87
|
+
# Or inline
|
|
88
|
+
llm_context -b ~/dev/ad/appydave-tools --groups docs,code
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
`llm_context` would read `.llm-groups.yaml` if present and expand the named groupings into `-i` patterns.
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
## Pipeline Vision (Full)
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
# Today (manual, fragile)
|
|
99
|
+
llm_context -b ~/dev/ad/flivideo -i 'lib/**/*.rb' -i 'docs/**/*.md' -f content -o clipboard
|
|
100
|
+
|
|
101
|
+
# After this feature (location-aware)
|
|
102
|
+
query_location --find flivideo --path-only | xargs -I{} llm_context -b {} --groups docs,code -f content -o clipboard
|
|
103
|
+
|
|
104
|
+
# Or shorthand once groups file exists
|
|
105
|
+
llm_context --project flivideo --groups docs -o clipboard
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Acceptance Criteria
|
|
111
|
+
|
|
112
|
+
- [ ] `jump.rb query --find <term>` returns matching location path(s)
|
|
113
|
+
- [ ] `jump.rb query --find <term> --meta` returns JSON with key, path, description, type
|
|
114
|
+
- [ ] `jump.rb query --type product` lists all product locations
|
|
115
|
+
- [ ] Output is pipeable to `llm_context -b`
|
|
116
|
+
- [ ] Apps from `apps.json` are also queryable (or a separate `--apps` flag)
|
|
117
|
+
- [ ] Spec coverage for new query subcommand
|
|
118
|
+
|
|
119
|
+
### Phase 2 (separate backlog item)
|
|
120
|
+
- [ ] `llm_context` reads `.llm-groups.yaml` and expands `--groups` flag into `-i` patterns
|
|
121
|
+
- [ ] `.llm-groups.yaml` standard defined and documented
|
|
122
|
+
- [ ] At least 3 projects have `.llm-groups.yaml` files (appydave-tools, flivideo, ss-prompt)
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Related Systems
|
|
127
|
+
|
|
128
|
+
- `~/.config/appydave/locations.json` — 70+ project locations (source of truth for `jump`)
|
|
129
|
+
- `~/.config/appydave/apps.json` — app registry with ports, start scripts, status
|
|
130
|
+
- `query_brain` — parallel tool for brain files; this is the project equivalent
|
|
131
|
+
- `llm_context` — the consumer; needs paths to operate
|
|
132
|
+
- `system-comprehension-pattern.md` — the pattern that produces the mental model; needs groupings to be useful at scale
|
|
133
|
+
- `appydave:system-context` skill — MISSING skill that generates `CONTEXT.md` per project; relates to Phase 2 groupings
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Notes
|
|
138
|
+
|
|
139
|
+
- Do NOT create a separate JSON registry — `locations.json` is already the source of truth
|
|
140
|
+
- The `jump` skill already knows about `locations.json`; extending `jump.rb` keeps things consistent
|
|
141
|
+
- Phase 2 (`.llm-groups.yaml`) is the real value unlock — Phase 1 is just plumbing
|
|
142
|
+
- This feature is what enables the "package project X for LLM research" workflow without manual path lookup every time
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Gap Analysis: system-context vs system-comprehension-pattern
|
|
2
|
+
|
|
3
|
+
**Context**: The `CONTEXT.md` file in this repo was generated by `/appydave:system-context` — a skill
|
|
4
|
+
that doesn't yet exist in appydave-plugins. This note compares what that skill *produced* (the output)
|
|
5
|
+
against the `system-comprehension-pattern.md` in the prompt-patterns brain to assess the gap.
|
|
6
|
+
|
|
7
|
+
**Created**: 2026-04-05
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What system-context Produced (CONTEXT.md output)
|
|
12
|
+
|
|
13
|
+
Looking at `CONTEXT.md` (generated 2026-04-03), the skill produced:
|
|
14
|
+
|
|
15
|
+
```yaml
|
|
16
|
+
# Frontmatter
|
|
17
|
+
generated: 2026-04-03
|
|
18
|
+
generator: system-context
|
|
19
|
+
status: snapshot
|
|
20
|
+
sources: [README.md, gemspec, lib/tools.rb, brand_resolver.rb, project_resolver.rb, jump/commands/generate.rb, docs/dam/batch-s3-listing-requirements.md, CHANGELOG.md (versions 0.76.0-0.77.7)]
|
|
21
|
+
regenerate: "Run /appydave:system-context in the repo root"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Sections produced:
|
|
25
|
+
1. **Purpose** — one sentence
|
|
26
|
+
2. **Domain Concepts** — key vocabulary (Brand, Project, DAM, Project Naming, Configuration, Multi-channel)
|
|
27
|
+
3. **Design Decisions** — 6 decisions with rationale
|
|
28
|
+
4. **Scope Limits** — 6 explicit "does NOT" statements
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## What system-comprehension-pattern Produces (Level 1)
|
|
33
|
+
|
|
34
|
+
The 8-dimension Level 1 prompt produces:
|
|
35
|
+
|
|
36
|
+
1. REAL PURPOSE — pain solved, world without it
|
|
37
|
+
2. MENTAL MODEL — central metaphor or abstraction
|
|
38
|
+
3. CORE ABSTRACTIONS — 3-5 building blocks and how they relate
|
|
39
|
+
4. KEY WORKFLOWS — 2-4 end-to-end workflows (intent → outcome, not API calls)
|
|
40
|
+
5. DESIGN DECISIONS — why it's built this way, alternatives considered
|
|
41
|
+
6. NON-OBVIOUS CONSTRAINTS — things that look like they should work but don't
|
|
42
|
+
7. EXPERT VS BEGINNER — mental shift from competent to expert
|
|
43
|
+
8. SCOPE LIMITS — explicit non-scope + what handles those things instead
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Gap Analysis
|
|
48
|
+
|
|
49
|
+
| Dimension | system-context | system-comprehension Level 1 |
|
|
50
|
+
|-----------|---------------|------------------------------|
|
|
51
|
+
| Purpose / Real problem | ✅ One sentence | ✅ Full explanation + "world without it" |
|
|
52
|
+
| Domain concepts / Core abstractions | ✅ Reasonable depth | ✅ Richer — explains relationships between concepts |
|
|
53
|
+
| Mental model / Central metaphor | ❌ Not present | ✅ The central "how does the system think?" question |
|
|
54
|
+
| Key workflows | ❌ Not present | ✅ End-to-end workflows (intent → outcome) |
|
|
55
|
+
| Design decisions | ✅ Good — 6 decisions with rationale | ✅ Same coverage + alternatives considered |
|
|
56
|
+
| Non-obvious constraints | ❌ Not present | ✅ The "looks like it should work but doesn't" list |
|
|
57
|
+
| Expert vs beginner mental shift | ❌ Not present | ✅ The hardest thing to get from docs |
|
|
58
|
+
| Scope limits | ✅ Good — 6 explicit "does NOT" statements | ✅ Same + what handles those things instead |
|
|
59
|
+
|
|
60
|
+
**Score: system-context covers ~4/8 dimensions well. Missing the 4 that are hardest to get from docs.**
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## The Core Gap
|
|
65
|
+
|
|
66
|
+
`system-context` is essentially an **automated documentation snapshot** — it reads source files and
|
|
67
|
+
produces a structured summary. It does this well and efficiently (no LLM needed, or minimal).
|
|
68
|
+
|
|
69
|
+
`system-comprehension-pattern` Level 1 is a **mental model prompt** — it produces reasoning about the
|
|
70
|
+
system, not just facts about it. The 4 missing dimensions (mental model, key workflows, non-obvious
|
|
71
|
+
constraints, expert vs beginner) are precisely the things that make a reasoning partner vs a fact retriever.
|
|
72
|
+
|
|
73
|
+
**Practical implication**: `CONTEXT.md` is useful as orientation context for an LLM session. But an LLM
|
|
74
|
+
given only `CONTEXT.md` would produce competent-but-generic answers. An LLM given the Level 1
|
|
75
|
+
comprehension output would produce expert-level, system-aware answers.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## What This Means for the system-context Skill (when built)
|
|
80
|
+
|
|
81
|
+
When `/appydave:system-context` is built as a proper skill, it should:
|
|
82
|
+
|
|
83
|
+
1. **Keep what works**: automated extraction of purpose, domain concepts, design decisions, scope limits
|
|
84
|
+
(these come from README, gemspec, source files — no deep reasoning needed)
|
|
85
|
+
|
|
86
|
+
2. **Add what's missing**: either
|
|
87
|
+
- Prompt the LLM to produce the missing 4 dimensions as part of the generation
|
|
88
|
+
- Or leave a `## Pending Comprehension` section flagging that Level 1 comprehension hasn't been run
|
|
89
|
+
|
|
90
|
+
3. **Add a query_brain groupings block** — this is the new gap not in either system:
|
|
91
|
+
```yaml
|
|
92
|
+
llm_groups:
|
|
93
|
+
docs: ["docs/**/*.md", "README.md", "CLAUDE.md"]
|
|
94
|
+
code: ["lib/**/*.rb", "bin/**/*.rb"]
|
|
95
|
+
tests: ["spec/**/*.rb"]
|
|
96
|
+
```
|
|
97
|
+
So that `llm_context --project appydave-tools --groups docs` works without manual pattern entry.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Recommendation
|
|
102
|
+
|
|
103
|
+
- **`system-context` as-is**: Good for quick onboarding context. Use it.
|
|
104
|
+
- **Before deep work**: Also run Level 1 comprehension from `system-comprehension-pattern.md` and append
|
|
105
|
+
the output to `CONTEXT.md` or keep it in a separate `COMPREHENSION.md`.
|
|
106
|
+
- **Long-term**: Build the `system-context` skill to include LLM-driven comprehension + groupings block.
|
|
107
|
+
The skill that produces `CONTEXT.md` should be the same skill that makes the project queryable.
|
|
@@ -54,6 +54,8 @@ module Appydave
|
|
|
54
54
|
run_remove(args)
|
|
55
55
|
when 'validate'
|
|
56
56
|
run_validate(args)
|
|
57
|
+
when 'query'
|
|
58
|
+
run_query(args)
|
|
57
59
|
when 'report'
|
|
58
60
|
run_report(args)
|
|
59
61
|
when 'generate'
|
|
@@ -128,6 +130,35 @@ module Appydave
|
|
|
128
130
|
exit_code_for(result)
|
|
129
131
|
end
|
|
130
132
|
|
|
133
|
+
def run_query(args)
|
|
134
|
+
meta_mode = args.delete('--meta')
|
|
135
|
+
|
|
136
|
+
find_terms = extract_multi_option(args, '--find')
|
|
137
|
+
type_filter = extract_option(args, '--type')
|
|
138
|
+
brand_filter = extract_option(args, '--brand')
|
|
139
|
+
args.delete('--path-only')
|
|
140
|
+
|
|
141
|
+
cmd = Commands::Query.new(
|
|
142
|
+
load_config,
|
|
143
|
+
find: find_terms,
|
|
144
|
+
type: type_filter,
|
|
145
|
+
brand: brand_filter
|
|
146
|
+
)
|
|
147
|
+
result = cmd.run
|
|
148
|
+
|
|
149
|
+
if result[:success]
|
|
150
|
+
if meta_mode
|
|
151
|
+
format_output(result, 'json')
|
|
152
|
+
else
|
|
153
|
+
format_output(result, 'paths')
|
|
154
|
+
end
|
|
155
|
+
else
|
|
156
|
+
warn result[:error]
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
exit_code_for(result)
|
|
160
|
+
end
|
|
161
|
+
|
|
131
162
|
def run_get(args)
|
|
132
163
|
format = format_option(args)
|
|
133
164
|
key = args.first
|
|
@@ -350,6 +381,20 @@ module Appydave
|
|
|
350
381
|
attrs
|
|
351
382
|
end
|
|
352
383
|
|
|
384
|
+
def extract_multi_option(args, flag)
|
|
385
|
+
values = []
|
|
386
|
+
loop do
|
|
387
|
+
index = args.index(flag)
|
|
388
|
+
break unless index
|
|
389
|
+
|
|
390
|
+
value = args[index + 1]
|
|
391
|
+
args.delete_at(index + 1)
|
|
392
|
+
args.delete_at(index)
|
|
393
|
+
values << value if value
|
|
394
|
+
end
|
|
395
|
+
values
|
|
396
|
+
end
|
|
397
|
+
|
|
353
398
|
def extract_option(args, flag)
|
|
354
399
|
index = args.index(flag)
|
|
355
400
|
return nil unless index
|
|
@@ -407,6 +452,7 @@ module Appydave
|
|
|
407
452
|
search <terms> Fuzzy search across all location metadata
|
|
408
453
|
get <key> Get location by exact key
|
|
409
454
|
list List all locations
|
|
455
|
+
query Scriptable location lookup (pipeline-friendly)
|
|
410
456
|
|
|
411
457
|
CRUD Operations:
|
|
412
458
|
add Add a new location
|
|
@@ -445,6 +491,8 @@ module Appydave
|
|
|
445
491
|
topic = args.first
|
|
446
492
|
|
|
447
493
|
case topic
|
|
494
|
+
when 'query'
|
|
495
|
+
show_query_help
|
|
448
496
|
when 'search'
|
|
449
497
|
show_search_help
|
|
450
498
|
when 'add'
|
|
@@ -464,6 +512,36 @@ module Appydave
|
|
|
464
512
|
end
|
|
465
513
|
end
|
|
466
514
|
|
|
515
|
+
def show_query_help
|
|
516
|
+
output.puts <<~HELP
|
|
517
|
+
jump query - Scriptable location lookup (pipeline-friendly)
|
|
518
|
+
|
|
519
|
+
Usage: jump query [--find <term>] [--type <type>] [--brand <brand>] [--path-only|--meta]
|
|
520
|
+
|
|
521
|
+
Filters (all are AND-combined):
|
|
522
|
+
--find <term> Match term against key, name, brand, type, tags, description
|
|
523
|
+
Repeat for AND logic: --find appydave --find ruby
|
|
524
|
+
--type <type> Filter by location type (e.g. tool, gem, product)
|
|
525
|
+
--brand <brand> Filter by brand (e.g. appydave, flivideo)
|
|
526
|
+
|
|
527
|
+
Output modes:
|
|
528
|
+
(default) One path per line — pipeable (same as --path-only)
|
|
529
|
+
--path-only Explicit path-per-line mode
|
|
530
|
+
--meta JSON array with key, path, description, type, brand, status
|
|
531
|
+
|
|
532
|
+
Exit codes:
|
|
533
|
+
0 Matches found
|
|
534
|
+
1 No matches (NOT_FOUND)
|
|
535
|
+
|
|
536
|
+
Examples:
|
|
537
|
+
jump query --find flivideo
|
|
538
|
+
jump query --find flivideo --meta
|
|
539
|
+
jump query --type tool
|
|
540
|
+
jump query --find appydave --type tool
|
|
541
|
+
jump query --find flivideo | xargs llm_context -b
|
|
542
|
+
HELP
|
|
543
|
+
end
|
|
544
|
+
|
|
467
545
|
def show_search_help
|
|
468
546
|
output.puts <<~HELP
|
|
469
547
|
jump search - Fuzzy search locations
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Appydave
|
|
4
|
+
module Tools
|
|
5
|
+
module Jump
|
|
6
|
+
module Commands
|
|
7
|
+
# Query command provides scriptable location lookup
|
|
8
|
+
#
|
|
9
|
+
# Designed for pipeline use — default output is bare paths, one per line.
|
|
10
|
+
# Use --meta for structured JSON output.
|
|
11
|
+
#
|
|
12
|
+
# @example Find by term
|
|
13
|
+
# cmd = Commands::Query.new(config, find: ['flivideo'])
|
|
14
|
+
# result = cmd.run
|
|
15
|
+
# result[:results] # => Array of matching location hashes
|
|
16
|
+
#
|
|
17
|
+
# @example Filter by type
|
|
18
|
+
# cmd = Commands::Query.new(config, type: 'product')
|
|
19
|
+
# result = cmd.run
|
|
20
|
+
class Query < Base
|
|
21
|
+
attr_reader :find_terms, :type_filter, :brand_filter
|
|
22
|
+
|
|
23
|
+
def initialize(config, **options)
|
|
24
|
+
super
|
|
25
|
+
@find_terms = Array(options[:find]).map { |t| t.to_s.downcase.strip }.reject(&:empty?)
|
|
26
|
+
@type_filter = normalize_option(options[:type])
|
|
27
|
+
@brand_filter = normalize_option(options[:brand])
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def run
|
|
31
|
+
matches = config.locations.select { |loc| matches?(loc) }
|
|
32
|
+
|
|
33
|
+
if matches.empty?
|
|
34
|
+
return error_result(
|
|
35
|
+
'No locations found matching the given criteria',
|
|
36
|
+
code: 'NOT_FOUND'
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
results = matches.map.with_index(1) do |location, index|
|
|
41
|
+
location_to_result(location, index)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
success_result(
|
|
45
|
+
count: results.size,
|
|
46
|
+
results: results
|
|
47
|
+
)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
private
|
|
51
|
+
|
|
52
|
+
def matches?(location)
|
|
53
|
+
return false if type_filter && location.type&.downcase != type_filter
|
|
54
|
+
return false if brand_filter && location.brand&.downcase != brand_filter
|
|
55
|
+
return false unless find_terms_match?(location)
|
|
56
|
+
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def find_terms_match?(location)
|
|
61
|
+
return true if find_terms.empty?
|
|
62
|
+
|
|
63
|
+
# All find terms must match (AND logic) — each term matches if it appears
|
|
64
|
+
# in any of the searchable fields of the location
|
|
65
|
+
find_terms.all? { |term| term_matches_location?(term, location) }
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def term_matches_location?(term, location)
|
|
69
|
+
fields = [
|
|
70
|
+
location.key,
|
|
71
|
+
location.type,
|
|
72
|
+
location.brand,
|
|
73
|
+
location.client,
|
|
74
|
+
location.description,
|
|
75
|
+
location.path
|
|
76
|
+
].compact.map(&:downcase)
|
|
77
|
+
|
|
78
|
+
tag_fields = location.tags.map(&:downcase)
|
|
79
|
+
|
|
80
|
+
fields.any? { |f| f.include?(term) } || tag_fields.any? { |t| t.include?(term) }
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def normalize_option(value)
|
|
84
|
+
return nil unless value
|
|
85
|
+
|
|
86
|
+
value.to_s.downcase.strip
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def location_to_result(location, index)
|
|
90
|
+
{
|
|
91
|
+
index: index,
|
|
92
|
+
key: location.key,
|
|
93
|
+
path: expand_path(location.path),
|
|
94
|
+
description: location.description,
|
|
95
|
+
type: location.type,
|
|
96
|
+
brand: location.brand,
|
|
97
|
+
client: location.client,
|
|
98
|
+
tags: location.tags,
|
|
99
|
+
status: 'active'
|
|
100
|
+
}.compact
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def expand_path(path)
|
|
104
|
+
return path unless path
|
|
105
|
+
|
|
106
|
+
File.expand_path(path)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
data/lib/appydave/tools.rb
CHANGED
|
@@ -109,6 +109,7 @@ require 'appydave/tools/jump/commands/remove'
|
|
|
109
109
|
require 'appydave/tools/jump/commands/validate'
|
|
110
110
|
require 'appydave/tools/jump/commands/report'
|
|
111
111
|
require 'appydave/tools/jump/commands/generate'
|
|
112
|
+
require 'appydave/tools/jump/commands/query'
|
|
112
113
|
require 'appydave/tools/jump/cli'
|
|
113
114
|
|
|
114
115
|
require 'appydave/tools/youtube_manager/models/youtube_details'
|
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.84.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-04-
|
|
11
|
+
date: 2026-04-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activemodel
|
|
@@ -329,6 +329,8 @@ files:
|
|
|
329
329
|
- docs/planning/micro-cleanup/AGENTS.md
|
|
330
330
|
- docs/planning/micro-cleanup/IMPLEMENTATION_PLAN.md
|
|
331
331
|
- docs/planning/micro-cleanup/assessment.md
|
|
332
|
+
- docs/planning/query-location-feature/IMPLEMENTATION_PLAN.md
|
|
333
|
+
- docs/planning/query-location-feature/system-context-gap-analysis.md
|
|
332
334
|
- docs/planning/s3-operations-split/AGENTS.md
|
|
333
335
|
- docs/planning/s3-operations-split/IMPLEMENTATION_PLAN.md
|
|
334
336
|
- docs/planning/test-coverage-gaps/AGENTS.md
|
|
@@ -404,6 +406,7 @@ files:
|
|
|
404
406
|
- lib/appydave/tools/jump/commands/add.rb
|
|
405
407
|
- lib/appydave/tools/jump/commands/base.rb
|
|
406
408
|
- lib/appydave/tools/jump/commands/generate.rb
|
|
409
|
+
- lib/appydave/tools/jump/commands/query.rb
|
|
407
410
|
- lib/appydave/tools/jump/commands/remove.rb
|
|
408
411
|
- lib/appydave/tools/jump/commands/report.rb
|
|
409
412
|
- lib/appydave/tools/jump/commands/update.rb
|