.claude/skills/review-search/SKILL.md
Review a search indexing PR
npx skillsauth add viqueen/claude-go-playground .claude/skills/review-searchInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Audit a search indexing PR. Answer the question: "Is the search indexing correct?"
The PR targets one project: connect-rpc-backend/ or grpc-backend/.
Identify which project from the PR file paths.
Fetch the PR diff:
gh pr diff <number>
Identify the domain(s) being indexed and read the full files (not just the diff).
Check every item below. For each, report PASS or FAIL with a brief explanation.
pkg/embed/embed.go defines Embedder interface with Embed(ctx, text) ([]float32, error)opensearch.go)_plugins/_ml/models/<model_id>/_predict APIEmbedder interfacepkg/embed/ must NOT import gen/, internal/, or any domain-specific codepkg/search/search.go defines Search interface with Index, Delete, Find, CreateIndexIfNotExists methodsIndex and Delete accept uuid.UUID for the id parameter (not string)Find accepts typed Criteria (not raw JSON) and returns *PageCriteria struct has Filters []Filter, Matches []Match, Vector *Vector, PageSize int32, PageToken stringFilter struct has Field string and Value any (for keyword/integer exact-match)Match struct has Field string and Query string (for text full-text search)Vector struct has Field string, Values []float32, K int (for k-NN)Page struct has Hits []Hit and NextPageToken stringHit struct has ID uuid.UUID, Score float32, and Source json.RawMessageCriteria into OpenSearch query internally — no raw JSON leaksMatches and Vector are set, implementation blends scoressearch_after (not from/size offset) with opaque token encodingCreateIndexIfNotExists accepts []byte (embedded JSON), not stringpkg/search/ must NOT import gen/, internal/, or any domain-specific codeinternal/outbox/<domain>/mappings/mappings.go exists with //go:embed *.json and exported FS embed.FS<domain>.json file per domain index.json file is valid JSON (parseable by jq)internal/outbox/<domain>/ (not under pkg/search/)internal/outbox/<domain>/mappings/<domain>.jsonkeyword: unique keys, foreign keys (UUIDs), tag arraystext with analyzer: names, titles, descriptions, bodiesintegertags) mapped as keywordid is NOT in the mapping — OpenSearch _id handles document identitycreated_at / updated_at NOT indexed unless time-range search is requireddeleted_at NOT indexed<parent>_)knn_vector field"settings": { "index": { "knn": true } }embedding field has type knn_vector with dimension, method.name: "hnsw", method.space_type: "cosinesimil", method.engine: "lucene"internal/outbox/<domain>/index.goIndexName constant is plural lowercase (e.g., "contents")IndexMapping loaded from embedded FS via mappings.FS.ReadFile("<domain>.json")EmbeddingField constant matches the mapping field nameid, created_at, updated_at, or deleted_atEmbedding []float32 with json:"embedding,omitempty"New<Domain>Document() mapper accepts both entity and parent models (when applicable)EmbeddingText() method concatenates searchable text fields for embeddinginternal/outbox/<domain>/event_index.goIndexDependencies struct includes Search, Embedder, and QueriesNewIndexWorker() constructor takes IndexDependenciesembedder.Embed() with doc.EmbeddingText() before indexingdoc.Embedding with result before calling search.Index()search.Index()search.Delete() with parsed uuid.UUID (no embed, no DB fetch)ctx context.Context (not _)Scan all imports:
pkg/search/ imports ONLY standard library + opensearch-go + zerolog + uuid — no gen/, no internal/pkg/embed/ imports ONLY standard library + opensearch-go (for OpenSearch provider) — no gen/, no internal/internal/outbox/<domain>/mappings/ imports nothing — pure embedded datainternal/outbox/<domain>/ imports pkg/search/ — ALLOWEDinternal/outbox/<domain>/ imports pkg/embed/ — ALLOWEDinternal/outbox/<domain>/ imports gen/db/<domain> — ALLOWEDinternal/outbox/<domain>/ imports internal/domain/<domain> — ALLOWED (for event constants only)pkg/search/ or pkg/embed/ in internal/domain/pkg/search/ or pkg/embed/ in internal/api/cmd/server/setup_connections.goConnections struct includes SearchClient search.Search and Embedder embed.Embeddersearch.New(cfg.OpenSearchURL)CreateIndexIfNotExists called on startup using <domain>events.IndexName and <domain>events.IndexMappingNewIndexWorker with all three dependencies (Search, Embedder, Queries).json property names exactlyembedding)IndexName constant used consistently (worker, setup — same constant)EmbeddingField constant matches the mapping property nameinternal/outbox/<domain>/pkg/search/ or pkg/embed/## Search PR Audit — <domain>
### Summary
<one sentence: pass or issues found>
### Component Matrix
| Component | File | Status | Notes |
|-----------|------|--------|-------|
| Embedder interface | pkg/embed/embed.go | PASS | — |
| Search interface | pkg/search/search.go | PASS | — |
| Embedded mappings | internal/outbox/<domain>/mappings/<domain>.json | PASS | — |
| Index + document | internal/outbox/<domain>/index.go | PASS | — |
| Index worker | internal/outbox/<domain>/event_index.go | PASS | — |
| Wiring | cmd/server/setup_connections.go | PASS | — |
### Import Audit
| Package | Import | Allowed | Status |
|---------|--------|---------|--------|
| pkg/search/ | opensearch-go | yes | PASS |
| pkg/embed/ | opensearch-go | yes | PASS |
| pkg/search/ | gen/db/<domain> | NO | FAIL |
| internal/outbox/<domain>/ | pkg/search/ | yes | PASS |
| internal/outbox/<domain>/ | pkg/embed/ | yes | PASS |
| internal/domain/<domain>/ | pkg/search/ | NO | FAIL |
| ... | ... | ... | ... |
### Mapping Consistency
| Document Field | JSON Tag | Mapping Property | Mapping Type | SQL Type | Denormalized | Status |
|----------------|----------|------------------|--------------|----------|--------------|--------|
| <Parent><Field> | <parent>_<field> | <parent>_<field> | keyword | TEXT (from parent) | yes | PASS |
| Title | title | title | text | TEXT | no | PASS |
| Embedding | embedding | embedding | knn_vector | — | no | PASS |
| ... | ... | ... | ... | ... | ... | ... |
### Issues
<numbered list of FAIL items with details and suggested fixes>
gh pr diff $ARGUMENTSgh pr view $ARGUMENTS --json number,title,body,state,baseRefName,headRefName,urltesting
Review a test PR
tools
Review a scaffold PR
tools
Review a proto PR
tools
Review an integration PR