.claude/skills/review-domain/SKILL.md
Review a domain PR
npx skillsauth add viqueen/claude-go-playground .claude/skills/review-domainInstall 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 domain PR. Answer the question: "Is the logic 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 being added and read the full files (not just the diff).
Check every item below. For each, report PASS or FAIL with a brief explanation.
internal/domain/<domain>/errors.go exists with domain-specific sentinel errorsevents.go exists with event type constants (Event*) for all outbox eventsservice.go exists with Service interface, Dependencies struct, and New() constructorop_<operation>.go file per operation (create, get, list, update, delete)Service interface is exportedservice struct is unexported (lowercase)Dependencies struct is exportedNew() constructor takes Dependencies and returns Service (the interface, not the struct)Dependencies)Scan all imports in the domain package:
gen/db/<domain> — ALLOWEDpkg/cache — ALLOWEDpkg/outbox — ALLOWEDpkg/pagination — ALLOWEDgen/sdk/ (proto/connect generated code)internal/api/internal/outbox/cmd/For each write op_*.go, verify the transactional outbox pattern:
pool.Begin(ctx)defer tx.Rollback(ctx) immediately afterqueries.WithTx(tx)outbox.Emit(ctx, tx, ...)tx.Commit(ctx)For each read op_*.go, verify the cache-first pattern:
op_get.go checks cache before querying the databaseop_get.go populates cache on cache missop_get.go maps pgx.ErrNoRows to ErrNotFoundop_list.go uses pkg/pagination (no local pagination helpers)op_list.go returns a nextPageToken when more results existop_delete.go checks affected rows and returns ErrNotFound if zeroop_delete.go invalidates cache after successful deleteop_delete.go emits outbox event within transactionspace.content_deleted) so consumers can invalidate related cacheserrors.go using errors.New()ErrNotFound existsErrAlreadyExists exists (if SQL schema has unique constraints) — check the migration for unique indexespgerrcode.UniqueViolation via pgconn.PgError to ErrAlreadyExists — no hardcoded postgres error codeserrors.Is() matchingevents.go (e.g., EventCreated = "<domain>.created")events.go — no hardcoded event type strings<domain>.<action> naming (e.g., content.created)## Domain PR Audit — <domain>
### Summary
<one sentence: pass or issues found>
### Operation Matrix
| Operation | File | Tx | Outbox | Cache | Errors | Status |
|-----------|------|----|--------|-------|--------|--------|
| Create | op_create.go | yes | yes | set after commit | — | PASS |
| Get | op_get.go | — | — | check first | ErrNotFound | PASS |
| ... | ... | ... | ... | ... | ... | ... |
### Import Audit
| Import | Allowed | Status |
|--------|---------|--------|
| gen/db/<domain> | yes | PASS |
| gen/sdk/... | NO | FAIL |
| ... | ... | ... |
### 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 search indexing PR
tools
Review a scaffold PR
tools
Review a proto PR