.claude/skills/review-integrate/SKILL.md
Review an integration PR
npx skillsauth add viqueen/claude-go-playground .claude/skills/review-integrateInstall 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 an integrate PR. Answer the question: "Is this wired correctly?"
Fetch the PR diff:
gh pr diff <number>
Identify the domain being integrated and read the full files (not just the diff).
Identify the project from the PR file paths: connect-rpc-backend/ or grpc-backend/.
Check every item below. For each, report PASS or FAIL with a brief explanation. Items marked (Connect-RPC) or (gRPC) only apply to the corresponding project.
internal/api/<domain>/v1/handler.go exists with Dependencies, constructor, and error mappingsmapper.go exists with toProto, fromProtoCreate, fromProtoUpdate functionsroute_<rpc>.go file per RPC methodinternal/api/<domain>/v1/ (matches proto package <domain>.v1)internal/api/<domain>/v1/gen/sdk/<domain>/v1/Unimplemented<Service>Server and implements the v1 gRPC service interfaceapi<domain><version> (e.g., apicontentv1)<domain>v1 for proto types (e.g., contentv1)<domain>v1connect for connect service (e.g., contentv1connect)<domain>v1grpc for gRPC service (e.g., contentv1grpc)db<domain> for sqlc types (e.g., dbcontent)<domain>domain for domain service (e.g., contentdomain)Dependencies struct has a Service field typed to the domain Service interfaceNew() returns the connect-generated handler interface (not a concrete struct)New() returns the gRPC-generated service server interface (not a concrete struct)handler struct is unexportedhandler struct has a service field (inlined, not embedded Dependencies)errorMappings maps domain errors → connect.CodeerrorMappings maps domain errors → codes.CodetoProto() maps sqlc model → proto response messagefromProtoCreate() maps proto create request → sqlc create paramsvalidateUpdateMask() rejects empty masks and unsupported field pathsfromProtoUpdate() maps proto update request → sqlc update paramspgtype.Text{String: val, Valid: true} for nullable strings (not *string)pgtype.Int4{Int32: val, Valid: true} for nullable ints (not *int32)mapper.go (no mapping in route files)route_*.go contains exactly one handler methodconnectutil.NewErrorFrom(err, errorMappings) for domain errorsgrpcutil.NewErrorFrom(err, errorMappings) for domain errorsInvalidArgument directly (not via errorMappings which falls through to Internal)InvalidArgumentvalidateUpdateMask() before fromProtoUpdate()internal/outbox/river.go exists with NewRiverOutbox constructor returning outbox.Outbox[pgx.Tx]<domain>domain for event constants, <domain>events for workersmapEvent() uses shared constants from <domain>domain.Event* (no hardcoded strings)mapEvent() has cases for all event types emitted by the domain (created, updated, deleted, etc.)internal/outbox/<domain>/event_<concern>.go per concern (index, audit, etc.)JobArgs struct with Kind() methodWorker struct embedding river.WorkerDefaultsctx context.Context (not _) and use log.Ctx(ctx) for loggingNewXxxArgs() constructor maps from outbox.EventKind() follows <domain>.<concern> namingcmd/server/setup_connections.go — new workers registered with river.AddWorker(workers, ...)setup_domains.go — Domains struct has new field for this domain's Servicesetup_domains.go — service wired with correct dependencies (pool, queries, cache, outbox)setup_gateway.go — handler created via New(Dependencies{...})setup_gateway.go — handler registered with connect.WithInterceptors(interceptors...)setup_gateway.go — handler path registered on connectapp muxsetup_gateway.go — service registered via Register<Service>Server(application.Server(), handler)internal/api/<domain>/v1/ imports: internal/domain/<domain>, gen/sdk/, gen/db/, pkg/connectutil or pkg/grpcutil — ALLOWEDinternal/outbox/river.go imports internal/domain/<domain> for event constants only — ALLOWEDinternal/outbox/<domain>/ imports: pkg/outbox, river — ALLOWEDinternal/outbox/<domain>/ does NOT import internal/domain/ or internal/api/internal/api/<domain>/v1/ does NOT import internal/outbox/## Integrate PR Audit — <domain>
### Summary
<one sentence: pass or issues found>
### Wiring Matrix
| Component | File | Registered | Dependencies | Status |
|-----------|------|------------|-------------|--------|
| Handler | setup_gateway.go | yes | Service | PASS |
| Service | setup_domains.go | yes | Pool, Queries, Cache, Outbox | PASS |
| IndexWorker | setup_connections.go | yes | — | PASS |
| AuditWorker | setup_connections.go | yes | — | PASS |
### Route Coverage
| Proto RPC | Route File | Uses Mapper | Uses ErrorMappings | Status |
|-----------|------------|-------------|-------------------|--------|
| Create | route_create.go | yes | yes | PASS |
| ... | ... | ... | ... | ... |
### Outbox Event Coverage
| Domain Event | Workers Triggered | Status |
|-------------|-------------------|--------|
| <domain>.created | index, audit | 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 search indexing PR
tools
Review a scaffold PR
tools
Review a proto PR