kb-search · diff

git:20260407.c483ba7 to git:20260415.8bb444e

121 added, 23 removed. Audit A to A.

---
name: kb-search
- description: "This skill should be used when searching the knowledge base for files matching keywords across all domains."
+ description: "This skill should be used when searching the knowledge base for files matching keywords or YAML frontmatter facets (tag, category) across domains."
---
# KB Search
- Search the knowledge base across all domains. Returns title matches first (tier 1), then content matches (tier 2).
+ Search the knowledge base across all domains. Returns title matches first (tier 1), then content matches (tier 2). Optional `--tag` and `--category` flags filter `knowledge-base/project/learnings/` by YAML frontmatter before grep runs, cutting result-set noise during cross-referencing.
## Arguments
<search_query> #$ARGUMENTS </search_query>
- If the search query above is empty, ask: "What would you like to search for in the knowledge base?"
+ Accepted forms:
- ## Execution
+ - `/kb-search <keyword>` — existing behavior, unchanged.
+ - `/kb-search --tag <value>` — filter learnings by frontmatter `tags:`.
+ - `/kb-search --category <value>` — filter learnings by frontmatter `category:`.
+ - `/kb-search --tag <value> --category <value> <keyword>` — combine (AND).
- ### Phase 1: Title Search (Tier 1 — High Relevance)
+ If `$ARGUMENTS` is empty, ask: "What would you like to search for in the knowledge base?"
- Search `knowledge-base/INDEX.md` for title matches. INDEX.md contains one line per file in the format `- [Title](path)`.
+ ### Flag Semantics
- Run Grep on `knowledge-base/INDEX.md` with the search keywords. Use case-insensitive matching. Each match is a file whose title contains the query terms.
+ - Values are matched **case-insensitively** and **as literals** (fixed-string, not regex). `--tag n+1` matches the literal tag `n+1`.
+ - Duplicate flags (`--tag a --tag b`) error with usage hint.
+ - Unknown flags (`--taag`) error with usage hint listing supported flags.
+ - Faceted queries scope to `knowledge-base/project/learnings/` only; other KB subtrees are skipped for facet lookups.
+ - Tag-only or category-only queries emit `title + path` per file (no content snippet). Combined with a keyword, snippets come from the keyword match.
- Display tier 1 results:
+ ## Execution
+ ### Phase 0: Parse Arguments
+
+ Parse `$ARGUMENTS` into `$TAG`, `$CATEGORY`, and `$KEYWORD`. Track whether each flag was already seen to detect duplicates. On duplicate or unknown flag, emit:
+
```text
- ## Title Matches
+ Usage: /kb-search [--tag VALUE] [--category VALUE] [KEYWORD]
+ ```
- 1. [Title](knowledge-base/path) — title match
- 2. [Title](knowledge-base/path) — title match
+ Then exit without searching.
+
+ ### Phase 1: Facet Validation (only if `--tag` or `--category` supplied)
+
+ Validate that autocomplete artifacts exist. If missing, emit and exit:
+
+ ```bash
+ if [ ! -f knowledge-base/kb-tags.txt ] || [ ! -f knowledge-base/kb-categories.txt ]; then
+ echo "Autocomplete artifacts missing. Run: bash scripts/generate-kb-index.sh"
+ exit 1
+ fi
```
- If INDEX.md does not exist, skip to Phase 2 and note: "INDEX.md not found — run `bash scripts/generate-kb-index.sh` to generate it."
+ Validate each supplied value against its artifact (case-insensitive, fixed-string, whole-line). On miss, emit and exit:
- ### Phase 2: Content Search (Tier 2 — Lower Relevance)
+ ```bash
+ tag_lc=$(printf '%s' "$TAG" | tr '[:upper:]' '[:lower:]')
+ if [ -n "$TAG" ] && ! grep -Fxq "$tag_lc" knowledge-base/kb-tags.txt; then
+ echo "No matches. Valid values: knowledge-base/kb-tags.txt"
+ exit 0
+ fi
+ ```
- Run Grep across `knowledge-base/` for the search keywords in file contents. Use case-insensitive matching. Exclude `knowledge-base/INDEX.md` and `knowledge-base/**/archive/**` from results.
+ Same pattern for `--category` against `knowledge-base/kb-categories.txt`.
- Filter out any files already found in tier 1. Display tier 2 results:
+ ### Phase 2: Filter Learnings by Frontmatter (only if `--tag` or `--category` supplied)
- ```text
- ## Content Matches
+ Walk `knowledge-base/project/learnings/*.md`. For each file, parse YAML frontmatter with the same awk idiom the index generator uses:
- 3. [path](knowledge-base/path) — content match (line N: "...context snippet...")
- 4. [path](knowledge-base/path) — content match (line N: "...context snippet...")
+ ```awk
+ /^---$/ { c++; next }
+ c != 1 { next }
+ # then match on ^tags: or ^category:
```
- ### Phase 3: Summary
+ Accept both inline (`tags: [a, b]`) and block (`tags:\n - a`) forms. Compare values case-insensitively. Collect the surviving file paths.
- Cap total results at 20 (tier 1 + tier 2 combined). If more than 20 matches exist, note: "Showing top 20 of N matches. Narrow the query for more specific results."
+ If both flags are supplied, a file must match BOTH to survive (AND).
- If zero results, suggest:
+ ### Phase 3: Keyword Search
+ - **Facet-only (no keyword):** Emit one line per surviving file in `- [Title](path)` form (title read from frontmatter or first `# heading`).
+ - **Keyword-only (no facets):** Run the existing two-tier search:
+ 1. Grep `knowledge-base/INDEX.md` for title matches (tier 1).
+ 2. Grep `knowledge-base/` contents for the keyword (tier 2), excluding INDEX.md and archive/.
+ - **Facets + keyword:** Apply keyword grep **only** to the facet-filtered file list (not the whole KB). Use `grep -F` (fixed-string).
+
+ Missing `INDEX.md` → note and continue with content grep only.
+
+ ### Phase 4: Display Results
+
+ Title matches come first, then content matches. Cap total at 20; if truncated, append:
+
+ ```text
+ Showing top 20 of N matches. Narrow the query for more specific results.
+ ```
+
+ Zero results → suggest:
+
- Check spelling
- Try broader or alternative keywords
- - Run `bash scripts/generate-kb-index.sh` to ensure INDEX.md is current
+ - For `--tag`/`--category` misses, inspect `knowledge-base/kb-tags.txt` or `kb-categories.txt`
+ - Run `bash scripts/generate-kb-index.sh` to ensure artifacts are current
+
+ ## Examples
+
+ ### Tag filter with keyword
+
+ ```text
+ /kb-search --tag eager-loading rails
+ ```
+
+ Returns learnings tagged `eager-loading` whose content matches `rails`.
+
+ ### Category filter alone
+
+ ```text
+ /kb-search --category performance-issues
+ ```
+
+ Returns all learnings with `category: performance-issues` as title+path.
+
+ ### Combined facets
+
+ ```text
+ /kb-search --tag n+1 --category performance-issues
+ ```
+
+ Returns learnings tagged `n+1` AND categorized as `performance-issues`.
+
+ ### Miss with hint
+
+ ```text
+ /kb-search --tag nonexistent-tag
+ # Output:
+ # No matches. Valid values: knowledge-base/kb-tags.txt
+ ```
+
+ The agent can read the artifact in a follow-up round-trip to self-correct.
+
+ ## Output Format
+
+ ```text
+ ## Title Matches
+
+ 1. [Title](knowledge-base/path) — title match
+ 2. [Title](knowledge-base/path) — title match
+
+ ## Content Matches
+
+ 3. [Title](knowledge-base/path) — content match (line N: "...snippet...")
+ ```
+
+ Tag-only or category-only output uses the `## Title Matches` block only, without snippets.