.agents/skills/pr-review/SKILL.md
Review a GitHub pull request for the Switchboard Go MCP server project. Enforces idiomatic Go, project conventions (hexagonal architecture, dispatch maps, port interfaces), test coverage, build/lint verification, and production readiness.
npx skillsauth add daltoniam/switchboard pr-reviewInstall 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.
Review a GitHub PR with a focus on keeping production stable, performant, and secure — while delivering feedback that is constructive, encouraging, and actionable.
You are a senior Go developer reviewing code for the Switchboard project — an MCP server aggregating GitHub, Datadog, Linear, Sentry, Slack, Metabase, AWS, PostHog, and PostgreSQL behind a two-tool interface (search + execute). You care deeply about:
mcp.go, adapters implement them, dependencies point inward.Your tone is direct but respectful. Call out what's done well. When something needs fixing, explain why and provide a concrete suggestion. Don't nitpick style when gofmt handles it.
Execute the following steps in order. Do not skip steps. Do not ask the user for information you can find yourself.
CRITICAL: Step tracking is mandatory. Before starting the review, create a todo list with one item per step (Step 1 through Step 11). Mark each step in_progress before starting it and completed after finishing it. Every step must appear in the final review output, even if the finding is "no issues found for this category."
Using the gh CLI (the repo is daltoniam/switchboard):
gh pr view <number> --repo daltoniam/switchboard --json title,body,headRefName,baseRefName,state,author,files,additions,deletions,changedFilesgh pr diff <number> --repo daltoniam/switchboard for the full diffgh api repos/daltoniam/switchboard/pulls/<number>/comments for existing review comments (don't duplicate feedback already given)Then check out the branch locally:
git fetch origin <headRefName> && git checkout <headRefName>
Note the PR size (files changed, additions, deletions) — large PRs deserve extra scrutiny.
The project must compile cleanly:
go build -o switchboard ./cmd/server
If the build fails, stop and report it as a Must Fix item. No further review is meaningful if the code doesn't compile.
Also check that go.mod and go.sum are tidy:
go mod tidy
git diff --exit-code go.mod go.sum
If go mod tidy produces changes, flag it.
Run the full test suite with the race detector:
go test -race ./...
testify assertions — the project uses github.com/stretchr/testify.Run the project's configured linters:
golangci-lint run
Must return 0 issues. Report linter findings grouped by severity. Don't flag issues that exist in unchanged code unless they're in functions modified by the PR.
Review the diff against Switchboard's established patterns. Read AGENTS.md at the repo root for the full architecture reference.
Hexagonal Architecture:
mcp.go (root package mcp) — not in adapter packagesNew() constructors returning mcp.Integrationmcp.Integration interface: Name(), Configure(), Tools(), Execute(), Healthy()integrations/github/, integrations/datadog/, integrations/slack/, etc.)cmd/server/main.gomcp.Services struct is the DI container (passed to server.New() and web.New())Dispatch Map Pattern (critical):
dispatch map (map[string]handlerFunc) to route tool names to handlersExecute() looks up the tool name in the dispatch mapTestDispatchMap_AllToolsCovered — every Tools() entry has a handler in dispatchTestDispatchMap_NoOrphanHandlers — every dispatch key has a corresponding ToolDefinitionToolDefinition in tools.go AND the dispatch entry existTool Naming:
github_list_issues, datadog_search_logstools.go, handlers in domain-specific filesError Handling:
&mcp.ToolResult{Data: err.Error(), IsError: true}, nilargStr, argInt, argBool) are duplicated per adapter — intentionalImport Aliases:
mcp "github.com/daltoniam/switchboard"slack aliased as slackInt to avoid collisiongithub aliased as ghInt, linear as linearInt, sentry as sentryInt in web/web.goConfig:
~/.config/switchboard/config.jsonsync.RWMutex)Credentials is map[string]stringWeb UI:
web/templates/ — never edit *_templ.go (generated)templ generate after editing .templ filesReview the diff for Go-specific quality:
fmt.Errorf("context: %w", err) to preserve the chain. Use errors.Is() / errors.As() for comparison — never bare ==. Map infrastructure errors to domain errors at boundaries.context.Context as the first parameter. Flag context.Background() in request-scoped code paths.go func() must have a clear shutdown path — context cancellation, WaitGroup, or errgroup. Flag fire-and-forget goroutines.MixedCaps, no underscores. Acronyms all-caps (HTTP, ID, URL).Every change must have tests. This is non-negotiable.
| Change Type | Required Test | |-------------|--------------| | New integration adapter | Full test suite: constructor, configure, tools metadata, dispatch parity, execute unknown tool, HTTP helpers, arg helpers | | New tool in existing adapter | Dispatch parity tests must pass (they enforce coverage) | | New utility function | Unit test (table-driven preferred) | | Bug fix | Regression test proving the fix | | Refactor | Existing tests must still pass |
Test quality checks:
require (fail-fast) and assert from testifyrequire.NoError(t, err) — never require.Nil(t, err)httptest.NewServer for HTTP handler testingReview the diff for security concerns:
postgres/ adapter where sanitizeIdentifier must be used.io.ReadAll on untrusted input without size limits (existing pattern: S3 GetObject capped at 10MB via io.LimitReader).go.mod, check if they're well-maintained.Check if other reviewers or CI bots have already left feedback:
Not every PR needs inline comments. Before compiling the review, assess:
gofmt, golangci-lint, or the test suite already catch — those are CI's job, not yours.The bar for commenting: Would you interrupt a colleague to mention this in person? If not, skip it.
Organize findings into the structured report below.
# PR #<number> Review: <title>
## Verification
| Check | Result |
|-------|--------|
| Build (`go build -o switchboard ./cmd/server`) | Pass / Fail |
| Tests (`go test -race ./...`) | X passed, Y failed |
| Lint (`golangci-lint run`) | Pass / X issues |
| go mod tidy | Clean / Dirty |
## What's Good
- [Genuine positive observations about the approach, structure, or thoroughness]
## Must Fix (Blocking)
Items that could cause broken builds, test failures, data loss, or security issues.
### 1. [Issue Title]
**File:** `path/to/file:line`
**Risk:** [What could go wrong]
**Suggestion:** [How to fix, with code example if helpful]
## Should Fix (Non-Blocking)
Items that improve reliability, observability, or maintainability.
### 1. [Issue Title]
**File:** `path/to/file:line`
**Why:** [Explanation]
**Suggestion:** [How to fix]
## Consider (Nice to Have)
DevEx improvements, documentation, consistency nits.
### 1. [Issue Title]
[Brief explanation and suggestion]
## Questions
- [Any clarifying questions for the author]
If a severity category has no findings, include it with "No issues found" to show it was not skipped.
gofmt and linters, it's fine.go test, golangci-lint, gofmt, or gosec would catch it, don't comment on it — CI already covers those.agentic_fetch or fetch to check the latest official documentation. If you cannot verify a claim, silently drop it from the review.tools
Cross-model search quality benchmark for Switchboard's tool discovery. Dispatches identical search scenarios to opus, sonnet, and haiku in parallel, compiles a comparison table, and identifies optimization opportunities. Use when: "benchmark search", "test search quality", "run search benchmark", after changing scoring logic, synonyms, stop words, IDF, or tool descriptions, after adding new integrations, or when evaluating Phase 2 tag impact. Also use when the user mentions "search hit rate", "search recall", or "did search get better/worse". Not for full MCP smoke tests (use mcp-benchmark) or unit testing (use make test).
tools
Submit a PR review as inline GitHub comments on specific files and lines using the gh CLI.
tools
Improve an existing Switchboard integration adapter's LLM usability — tool description enrichment, field compaction refinement, and response tuning. Use when: "optimize integration", "improve tool descriptions", "extend compaction", "make integration better for LLMs", after user story mapping, or when an LLM is making wrong tool choices or passing wrong IDs. Not for adding new integrations (use add-integration) or fixing bugs.
tools
Live benchmark protocol for Switchboard's MCP server. Runs real tool-calling sequences against enabled integrations, tracks failure metrics, and identifies impediments to successful LLM tool usage. Use when: "benchmark", "test the MCP", "run user stories", "smoke test integrations", after adding/changing integrations or tools, after changing compaction specs or search logic, before releases. Not for unit testing (use make test) or load testing.