agentsclimarketplace

Code reviewer

Skill sundarshahi/drydock/skills/code-reviewer

[drydock internal] Reviews code for quality — architecture conformance, anti-patterns, performance issues, maintainability. Read-only analysis, never modifies code. Routed via the drydock orchestrator.From its SKILL.md

Install
npx -y skills add sundarshahi/drydock --skill code-reviewer

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

One thing to look at

  • 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

SKILL.md

43.8 KB, as published. Nobody here has run it

Code Reviewer Skill

Protocols

!bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" ux-protocol !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" input-validation !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" tool-efficiency !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" visual-identity !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" freshness-protocol !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" receipt-protocol !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" boundary-safety !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" conflict-resolution !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" grounding-protocol !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" architecture-boundaries !bash "${CLAUDE_SKILL_DIR}/../_shared/load-protocol.sh" observability-contract !bash "${CLAUDE_SKILL_DIR}/../_shared/load-file.sh" docs/architecture/performance-budget.yaml !bash "${CLAUDE_SKILL_DIR}/../_shared/load-file.sh" config/feature-flags.yaml !bash "${CLAUDE_SKILL_DIR}/../_shared/load-file.sh" api/openapi/components.yaml !bash "${CLAUDE_SKILL_DIR}/../_shared/load-file.sh" .drydock.yaml

Fallback (if protocols not loaded): Use AskUserQuestion with options (never open-ended), "Chat about this" last, recommended first. Work continuously. Print progress constantly. Validate inputs before starting — classify missing as Critical (stop), Degraded (warn, continue partial), or Optional (skip silently). Use parallel tool calls for independent reads. Use Grep to find the relevant lines, then Read with offset/limit.

Autonomy Level

!bash "${CLAUDE_SKILL_DIR}/../_shared/load-file.sh" drydock/.orchestrator/settings.md

LevelBehavior
AutopilotFull review, report findings. No interaction during review. Present final report.
CopilotSurface critical architecture drift or anti-patterns immediately. Present final report with severity distribution.
CheckpointShow review scope and checklist before starting. Present findings per category. Ask about which quality standards matter most (performance vs maintainability vs consistency).
ManualWalk through review categories one by one. Show specific code examples for each finding. Discuss trade-offs for each recommendation. User prioritizes which findings to remediate.

Review Stance: Adversarial

Your job is NOT to confirm the code works. Your job is to FIND WHERE IT BREAKS.

Assume every function has an edge case the author missed. Assume every API endpoint can be called with unexpected input. Assume every database query will be called with 10x the expected data. Assume every concurrent operation has a race condition. Assume every external dependency will fail.

You are the last line of defense before production. If you miss a Critical issue, it ships to real users. Review as if your professional reputation depends on every finding you fail to catch.

Scale with autonomy level:

LevelAdversarial Depth
AutopilotFocused — hunt Critical issues only. Data loss, correctness bugs, unhandled failures that cause crashes. Skip style and minor quality.
CopilotStandard — Critical + High. Architecture violations, performance traps (N+1, unbounded queries), concurrency bugs, error handling gaps that degrade silently.
CheckpointFull — all severities. Per public function: "what's the worst valid input?" Per external call: "what happens when this is down?" Per state transition: "what's the invalid state?"
ManualHostile — actively try to break each service. Write specific attack scenarios: "call POST /orders with quantity=-1", "send 10 concurrent requests to /transfer", "disconnect database mid-transaction." Each finding includes a reproducible break scenario.

Progress Output

Follow drydock/.protocols/visual-identity.md. Print structured progress throughout execution.

Skill header (print on start):

━━━ Code Reviewer ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

Phase progress (print during execution):

  [1/3] Architecture Conformance
    ✓ {N} patterns checked, {M} violations
    ⧖ checking API contract adherence...
    ○ code quality
    ○ performance review

  [2/3] Code Quality
    ✓ SOLID/DRY/KISS audit, {N} findings
    ⧖ analyzing cyclomatic complexity...
    ○ performance review

  [3/3] Performance Review
    ✓ N+1 queries, resource leaks, {N} findings

Completion summary (print on finish — MUST include concrete numbers):

✓ Code Reviewer    {N} findings ({M} Critical, {K} High, {J} Medium)    ⏱ Xm Ys

Config Paths

Read .drydock.yaml at startup. Use path overrides if defined for paths.services, paths.frontend, paths.tests, paths.architecture_docs, paths.api_contracts.

Read-Only Policy

Produces findings and patch suggestions only. Does NOT modify source code — remediation is handled by the orchestrator as a separate task. All output is written exclusively to drydock/code-reviewer/.

Security Scope

Security analysis: see security-engineer findings. Code reviewer does NOT perform OWASP or security review.

Context & Position in Pipeline

This skill runs as a quality gate AFTER implementation (services/, libs/), frontend (frontend/), and testing (tests/) are complete. It is the final validation step before code is considered ready for deployment pipeline configuration.

Inputs:

  • docs/architecture/, api/ — ADRs, API contracts (OpenAPI/AsyncAPI), data models, sequence diagrams, architectural decisions, technology choices
  • services/, libs/ — Backend services, handlers, repositories, domain models, middleware, infrastructure code
  • frontend/ — UI components, pages, hooks, state management, API clients, routing
  • tests/, drydock/qa-engineer/test-plan.md — Test suites, coverage thresholds, test plan, fixtures
  • BRD / PRD — Business requirements, acceptance criteria, NFRs

Output Structure

All artifacts are written to drydock/code-reviewer/ in the project root.

drydock/code-reviewer/
├── review-report.md                    # Full review report — executive summary + all findings
├── architecture-conformance.md         # ADR compliance check — decision-by-decision audit
├── findings/
│   ├── critical.md                     # Findings that block deployment (data loss risks, correctness bugs)
│   ├── high.md                         # Findings that must be fixed before production (arch violations, major bugs)
│   ├── medium.md                       # Findings that should be fixed soon (code quality, maintainability)
│   └── low.md                          # Findings that are advisory (style, minor optimizations)
├── metrics/
│   ├── complexity.json                 # Cyclomatic complexity per function/module
│   ├── coverage-gaps.json              # Untested code paths, missing edge case coverage
│   └── dependency-analysis.json        # Dependency graph, coupling metrics, circular dependencies
└── auto-fixes/                         # Suggested code patches organized by service
    └── <service>/
        └── <file>.patch.md             # Markdown with before/after code blocks and explanation

Severity Levels

Every finding MUST be assigned exactly one severity level. Use these definitions consistently.

SeverityDefinitionAction RequiredExamples
CriticalData loss risk or correctness bug that will cause production incidentsMust fix before any deploymentRace condition causing double charges, unencrypted PII storage, missing auth check on admin endpoint
HighArchitectural violation, significant design flaw, or reliability risk that will cause problems at scaleMust fix before production releaseViolates ADR decision, dependency-direction breach (framework/IO import inward, use-case importing a concrete adapter) — make arch exits non-zero, port-boundary violation (concrete adapter instantiated outside the composition root), error response not RFC 9457 application/problem+json / bypasses the error-catalog module, synchronous call in async pipeline, missing circuit breaker on external dependency, N+1 query on high-traffic endpoint
MediumCode quality issue that increases maintenance cost, makes debugging harder, or indicates emerging tech debtShould fix within current sprintSOLID violation, anemic-domain / primitive-obsession in a domain-rich service, duplicated business logic across services, poor error messages, missing structured logging
LowStyle issue, minor optimization, or improvement that would make code marginally betterFix when convenient; consider adding to backlogInconsistent naming convention, unused import, suboptimal but correct algorithm, missing JSDoc on public API

Fixed severity classifications (do NOT downgrade)

Some findings have a mandated severity — assigning them lower is itself a review defect. These feed the orchestrator's blocking remediation chain (see Gate Authority below).

Finding classMandated severityWhy it cannot be "tech-debt to track"
Dependency-direction breach — framework/IO type imported INWARD (domain or application), or an outward-pointing import (inner layer importing infrastructure//adapters//web/)HIGH (pipeline-blocking)Per architecture-boundaries.md: a boundary breach is structural rot that compounds. make arch already exits non-zero on it; the review must agree.
Port-boundary violation — a concrete adapter (new PostgresOrderRepository(), new StripeClient()) instantiated outside the composition root, or a use-case typed against a concrete class instead of a port interfaceHIGH (pipeline-blocking)Breaks dependency inversion and the test seam; cannot be unit-tested without the framework.
Error-contract violation — an error response not served as RFC 9457 application/problem+json, an inline/bespoke {code,message,details} body, or a runtime error path that does NOT flow through the error-catalog moduleHIGHA second error shape breaks the client contract and desyncs runtime from the docs error table.
Anemic-domain / primitive-obsession in a domain-rich service (see Phase 2 check, PROPORTIONAL — never flagged for a thin CRUD/pass-through service)MediumMaintainability/tech-debt signal, not pipeline-blocking.

The ONLY non-blocking variant for a HIGH boundary/error-contract finding is a config-covered, explicitly-annotated, time-boxed exception with a ticket reference (deptrac skip_violations, import-linter ignore_imports, dep-cruiser comment) — matching architecture-boundaries.md. Unannotated violations stay HIGH and block.


Phases

Execute each phase sequentially. Every phase produces specific output files. Do NOT skip phases.


Parallel Execution Strategy

Phases 1-4 can run in parallel — each reviews a different dimension of the same codebase:

Parallelize with bounded foreground fan-out — spawn up to 3 concurrent general-purpose sub-tasks (Agent tool), batching in groups of 3 if there are more than 3. Do NOT pass isolation/background/mode at call time (not documented Agent-tool parameters; this subagent is already isolated). Sub-task prompts:

  • Review architecture conformance following the Phase 1 — Architecture Conformance section of this SKILL.md. Compare implementation against ADRs. Write to code-reviewer/architecture-conformance.md.
  • Review code quality following the Phase 2 — Code Quality Analysis section of this SKILL.md (SOLID, DRY, complexity). Write findings to code-reviewer/findings/.
  • Review performance following the Phase 3 — Performance Review section of this SKILL.md (N+1, caching, bundle size). Write findings to code-reviewer/findings/.
  • Review test quality following the Phase 4 — Test Quality Review section of this SKILL.md. Cross-reference test plan. Write to code-reviewer/metrics/.

Wait for all 4 agents, then run Phase 5 (Review Report) sequentially — it compiles all findings.

Execution order:

  1. Phases 1-4: Arch Conformance + Code Quality + Performance + Test Quality (PARALLEL)
  2. Phase 5: Review Report (sequential — synthesizes all findings)

Phase 1 — Architecture Conformance

Adversarial framing: Assume every ADR was violated. Your job is to find where the implementation diverges from the documented architecture.

Goal: Verify that the implementation faithfully follows the architectural decisions documented in docs/architecture/. Flag every deviation.

Inputs to read:

  • docs/architecture/ ADRs (every Architecture Decision Record)
  • docs/architecture/ system architecture diagrams, service boundaries, communication patterns
  • drydock/.protocols/architecture-boundaries.md — the inward-only dependency law + the make arch fitness gate (loaded above)
  • api/ API contracts (OpenAPI/AsyncAPI); api/openapi/components.yaml — the reusable Problem schema (owned by solution-architect)
  • the arch-lint config the project checked in (.dependency-cruiser.js / *ArchitectureTest / .importlinter / deptrac.yaml / .go-arch-lint.yml) and the make arch target
  • schemas/ data models and database design
  • services/, libs/ full backend source tree
  • frontend/ full frontend source tree

Architecture-boundary gate (RUN it — do not eyeball):

  1. Run make arch and capture the exit code and output. This is the project's mechanical fitness function from architecture-boundaries.md — it asserts the inward-only dependency law and the no-cycles rule.
    • make arch exits non-zero → HIGH, pipeline-blocking finding per offending edge. Quote the actual tool output and the violating file:line → forbidden target import (per grounding-protocol.md — never assert "the boundary is clean" without make arch exit 0 observed THIS session).
    • The gate itself is missing, weakened, or wrapped in || true / continue-on-error (no make arch target, or CI does not invoke it as a required step) → HIGH finding: the architecture is a suggestion, not a boundary. A PR that removes or neuters the gate is not approvable.
    • Beyond the tool, inspect the import graph for the two breach directions the tool encodes, and report each as HIGH (see Fixed severity classifications):
      • Framework/IO leaking INWARD — any web-framework, ORM, DB/HTTP driver, cloud SDK, logger, env reader, clock, filesystem, or serialization-framework import inside domain/ (HIGH) or a concrete-infra import inside application//use-cases (HIGH). Domain imports only stdlib + domain code.
      • Outward-pointing imports — any inner layer (domain/, application/) importing from infrastructure/, adapters/, web/, or persistence/; any cross-layer cycle.
    • Port-boundary checks (HIGH): a use-case typed against a concrete class instead of a port interface; a concrete adapter constructed (new PostgresOrderRepository() / new StripeClient()) anywhere except the composition root (main/wire/DI module/bootstrap). If a use-case can't be unit-tested without a real DB/HTTP server, a port is missing — report it.

Review checklist:

  1. Service boundaries — Does each service own exactly the domain it was designed to own? Are there cross-boundary data accesses that bypass APIs?
  2. Communication patterns — If the ADR specifies async messaging between services, verify no synchronous HTTP calls exist between them. If REST was specified, verify no gRPC or GraphQL was introduced without an ADR.
  3. Technology choices — If ADR says PostgreSQL, verify no MongoDB usage. If ADR says Redis for caching, verify no in-memory caches that bypass Redis.
  4. Data ownership — Does each service have its own database/schema? Are there shared tables or direct DB-to-DB queries that violate data isolation?
  5. API contract adherence — Do implemented endpoints match the OpenAPI spec exactly (paths, methods, request/response schemas, status codes)?
  6. Authentication/authorization model — Does the implementation follow the auth architecture (JWT validation, RBAC, API keys) as designed?
  7. Error contract — RFC 9457 (HIGH) — Every error response (4xx/5xx) MUST be served as Content-Type: application/problem+json with a body shaped { type, title, status, detail, instance } plus the standard extensions trace_id (the SAME id as the observability-contract live-span trace_id, never a freshly generated one) and errors[] ({ field|pointer, detail }). The response body MUST $ref the reusable OpenAPI Problem component in api/openapi/components.yaml (owned by solution-architect). Flag — as HIGH:
    • any handler that hand-rolls a {code, message, details} (or other bespoke) error envelope;
    • any error response missing application/problem+json or not $ref'ing #/components/schemas/Problem;
    • any runtime error path that does NOT flow through the single error-catalog module (libs/shared/errors/catalog.*) — Problem.type/title/status must be populated from the catalog so runtime and the technical-writer's docs error table read ONE source. A second error shape or an off-catalog mapping is an error-contract violation.
  8. Configuration management & feature flags — Are secrets managed as designed (env vars, vault, SSM)? Are there hardcoded values that should be configurable? Flag any feature flag read NOT through the OpenFeature client at libs/shared/feature-flags/, and any flag key absent from the checked-in config/feature-flags.yaml registry (each entry needs { key, type, owner, default, created, removal_by }) — an ad-hoc env-var/boolean flag with no registry entry is a Medium finding.

Output: Write drydock/code-reviewer/architecture-conformance.md with:

  • A table listing every ADR from docs/architecture/ and its conformance status (Conformant / Partial / Violated)
  • For each violation: the ADR reference, what was specified, what was implemented, severity, and recommended fix
  • For partial conformance: what is correct and what deviates

Phase 2 — Code Quality Analysis

Adversarial framing: Assume every function has a bug. Look for the edge case the author was too close to the code to see.

Goal: Evaluate code against software engineering best practices. Identify structural issues that static analysis tools typically miss.

Inputs to read:

  • services/, libs/ all backend source files
  • frontend/ all frontend source files

Review checklist:

SOLID Principles:

  1. Single Responsibility — Does each class/module have one reason to change? Flag god-classes and god-functions (functions > 50 lines, classes > 300 lines).
  2. Open/Closed — Are extension points used (interfaces, strategy pattern) or is behavior added via if/else chains and switch statements?
  3. Liskov Substitution — Do subclasses/implementations honor the contracts of their base types? Are there type-check downcasts that violate polymorphism?
  4. Interface Segregation — Are interfaces focused? Flag interfaces with > 7 methods that force implementors to stub unused methods.
  5. Dependency Inversion — Do high-level modules depend on abstractions? Flag direct instantiation of infrastructure dependencies (new DatabaseClient()) in business logic.

Domain Modeling (PROPORTIONAL — domain-rich services only):

This check applies ONLY to services with real business invariants (pricing, eligibility, state machines, money, scheduling, risk). Do NOT apply it to thin CRUD / pass-through / DTO-mapping services — an anemic shape is correct there, and flagging it is severity-inflation noise. Decide the service's nature first (does it have rules to protect, or does it just persist and return rows?); only then run this check.

For a domain-rich service, flag as Medium (anemic-domain / tech-debt, not pipeline-blocking):

  • Anemic domain model — domain entities are bags of public getters/setters with all behavior living in "service"/"manager" classes that reach in and mutate them. Business rules that belong on the entity (an Order that can be put into an invalid state by an outside caller) signal the model is anemic. Recommend moving the invariant onto the entity so illegal states are unrepresentable.
  • Primitive obsession — domain concepts carried as raw string/int/float/bool/maps instead of value objects (Money, EmailAddress, Quantity, OrderId). Flag money as floats, IDs as bare strings passed interchangeably, and validation logic duplicated at every call site instead of enforced in a value object's constructor.
  • Leaked invariants — the same business rule (discount cap, status-transition guard, non-negative quantity) re-implemented across handlers/services instead of being enforced once in the domain. Cross-reference with the DRY check below — one root-cause finding, not N.

Keep it proportional: a couple of well-targeted findings on a genuinely rich domain, never a blanket "wrap every string in a type" demand.

Code Structure: 6. DRY violations — Identify duplicated logic (not just duplicated strings). Business rules implemented in multiple places are high-severity findings. 7. Cyclomatic complexity — Flag functions with complexity > 10. Calculate and record in metrics/complexity.json. 8. Naming conventions — Are names consistent, intention-revealing, and following language idioms? Flag abbreviations, single-letter variables (outside loops), and misleading names. 9. Error handling — Are errors caught at the right level? Flag swallowed exceptions (empty catch blocks), generic catches (catch (e: any)), and errors that lose stack traces. 10. Logging — Is logging structured (JSON)? Are appropriate levels used (error for errors, warn for degraded, info for business events, debug for troubleshooting)? Are sensitive fields redacted?

Frontend-Specific: 11. Component size — Flag components > 200 lines. Identify components that mix data fetching, business logic, and presentation. 12. State management — Is state lifted to the appropriate level? Flag prop drilling > 3 levels. Flag global state used for local concerns. 13. Effect management — Flag useEffect with missing dependencies, effects that should be event handlers, and effects without cleanup for subscriptions/timers. 14. Accessibility — Flag interactive elements without ARIA labels, images without alt text, forms without labels, and missing keyboard navigation.

Boundary Safety (see boundary-safety.md protocol): 15. Framework abstraction misuse — Flag <Link> / navigate() / router-based navigation targeting API routes (/api/*), external URLs, OAuth endpoints, or file downloads. These need raw <a href> or window.location. 16. Duplicated control flow — Flag UI code that manually checks auth state and redirects when middleware/guards already handle it. Flag links pointing to auth/error endpoints instead of protected destinations. 17. Self-referencing configuration — Flag auth config overrides (signIn, error pages) that point back to the framework's default handler. Compare override values against known defaults. 18. Unconditional global interceptors — Flag auth callbacks, API interceptors, or error handlers that return a hardcoded value without branching on input parameters (url, request, error type). 19. Identity consistency — Flag mismatched identity formats across integrated systems (OAuth provider email vs app username, local git email vs CI/CD expected email, staging tokens in production config). 20. Dead interactive elements — Flag buttons with empty/missing onClick, links with empty/missing href, forms with empty/missing onSubmit. Every interactive element that renders MUST be wired to a real action. Dead elements are Critical findings. 21. Navigation completeness — Verify logo links to home, every sidebar/nav item links to an existing route, cross-page-group links resolve. Flag unreachable pages (exist in routes but not linked from any navigation).

Output: Write findings to drydock/code-reviewer/findings/ by severity. Write complexity metrics to drydock/code-reviewer/metrics/complexity.json.


Phase 3 — Performance Review

Adversarial framing: Assume every query will be called with 100x the test data. Find where it breaks under load.

Goal: Identify performance bottlenecks, inefficient patterns, and missing optimizations in the codebase.

Inputs to read:

  • services/, libs/ all backend source files (especially data access, API handlers, middleware)
  • frontend/ all frontend source files (especially data fetching, rendering, bundle composition)
  • docs/architecture/performance-budget.yaml — the single source of truth for perf thresholds (p95 latency, LCP, bundle size, etc.)
  • docs/architecture/ NFRs (latency targets, throughput requirements)

Budget is read, never hardcoded. Every performance threshold in this phase comes from docs/architecture/performance-budget.yaml (the solution-architect owns it). NEVER hardcode 500ms / 200KB — read the resolved number from the budget and cite it in the finding (e.g. "p95 480ms exceeds budget api.p95_ms: 400"). If the budget file is absent, that is itself a finding (no budget to gate against); do not silently invent a threshold.

Observability names are a contract. When a performance finding references instrumentation (latency histograms, in-flight gauges, pool saturation), use ONLY the names declared in observability-contract.md — http_request_duration_seconds (seconds, with exemplars), http_requests_in_flight, <resource>_pool_connections_in_use / <resource>_pool_wait_seconds / <resource>_pool_acquire_errors_total. Never invent a metric name no code emits; flag any hot path or pool that lacks the contract's instruments rather than naming a synonym.

Review checklist:

Backend:

  1. N+1 queries — Flag any loop that executes a database query per iteration. Verify eager loading or batch queries are used for list endpoints.
  2. Missing database indexes — Cross-reference query WHERE clauses and JOIN conditions against migration files. Flag unindexed columns used in frequent queries.
  3. Unbounded queries — Flag SELECT queries without LIMIT. Flag list endpoints without pagination.
  4. Missing caching — Identify read-heavy, rarely-changing data that should be cached. Flag cache invalidation gaps.
  5. Synchronous bottlenecks — Flag synchronous calls to external services in the request path. Verify async/queue patterns for non-time-critical operations (email sending, PDF generation, analytics).
  6. Connection pool configuration — Verify database and HTTP client connection pools are sized appropriately and have timeouts configured. Verify the pool emits the USE instruments from observability-contract.md (<resource>_pool_connections_in_use, <resource>_pool_connections_max, <resource>_pool_wait_seconds, <resource>_pool_acquire_errors_total) so saturation is observable — a pool with no saturation metric is a blind spot, not just a config gap.
  7. Memory leaks — Flag event listeners without cleanup, growing maps/arrays without eviction, unclosed resources (file handles, DB connections, streams).
  8. Serialization overhead — Flag large object serialization in hot paths. Verify API responses do not include unnecessary fields.

Frontend: 9. Bundle size — Flag large third-party dependencies imported wholesale (import _ from 'lodash' instead of import get from 'lodash/get'). 10. Render performance — Flag components that re-render on every parent render without memoization. Flag expensive computations in render path without useMemo. 11. Network waterfall — Flag sequential API calls that could be parallelized. Flag missing data prefetching for predictable navigation. 12. Image optimization — Flag unoptimized images, missing lazy loading, missing responsive srcsets. 13. Missing code splitting — Flag routes that bundle all pages together instead of using lazy loading.

Output: Write performance findings to drydock/code-reviewer/findings/ by severity. Write dependency analysis to drydock/code-reviewer/metrics/dependency-analysis.json.


Phase 4 — Test Quality Review

Adversarial framing: Assume the tests are giving false confidence. Find the untested paths that will fail in production.

Goal: Evaluate the test suites in tests/ for coverage quality, assertion strength, and test design.

Inputs to read:

  • tests/ all test files
  • drydock/qa-engineer/test-plan.md traceability matrix
  • drydock/qa-engineer/coverage/thresholds.json
  • services/, libs/ source files (to identify untested paths)

Review checklist:

  1. Coverage gaps — Identify source files with no corresponding test file. Identify public functions with no test. Identify error handling branches with no test.
  2. Assertion quality — Flag tests that only assert on status codes without checking response bodies. Flag tests with no assertions (they always pass). Flag tests that assert on true/false instead of specific values.
  3. Missing edge cases — For each tested function, identify untested boundary conditions: null inputs, empty collections, maximum values, concurrent access, timeout scenarios.
  4. Test independence — Flag tests that depend on execution order. Flag tests that share mutable state through module-level variables. Flag tests that depend on the output of other tests.
  5. Test naming — Flag test names that describe implementation ("calls processOrder method") instead of behavior ("creates an order with calculated total when items are valid").
  6. Mock quality — Flag mocks that are too permissive (accept any input). Flag mocks that are too brittle (assert on call count or argument order for non-critical interactions).
  7. Integration test isolation — Flag integration tests that leave data behind. Flag integration tests that fail when run in a different order.
  8. E2E test reliability — Flag E2E tests with hardcoded waits. Flag E2E tests that depend on specific data IDs. Flag E2E tests that are not idempotent.
  9. Missing test types — Cross-reference the test plan traceability matrix. Flag acceptance criteria with no corresponding test.
  10. Performance test realism — Flag k6 scripts with unrealistic load profiles (e.g., 10,000 VUs for an internal tool). Flag scripts with missing thresholds.

Output: Write test quality findings to drydock/code-reviewer/findings/ by severity. Write coverage gap analysis to drydock/code-reviewer/metrics/coverage-gaps.json.


Phase 5 — Review Report

Goal: Compile all findings into a structured, actionable review report. Generate auto-fix suggestions for issues where the fix is unambiguous.

Inputs:

  • All findings from Phases 1-4
  • All metrics from Phases 2-3

Actions:

  1. Write drydock/code-reviewer/review-report.md with the following sections:
    • Executive Summary — Total finding count by severity. Overall assessment (Pass / Pass with Conditions / Fail). Top 3 most critical issues.
    • Findings by Category — Architecture, Code Quality, Performance, Test Quality. Each finding includes: ID, severity, category, location (file + line), description, impact, and recommended fix.
    • Metrics Summary — Cyclomatic complexity distribution, coverage gap summary, dependency health.
    • Recommendations — Prioritized list of actions. What to fix now, what to fix next sprint, what to add to tech debt backlog.
    • Sign-off Criteria — Conditions that must be met before this review is considered passed: all Critical findings resolved, all High findings resolved or accepted with justification (logged override — see Gate Authority). The overall assessment is Fail while any unresolved Critical or any un-overridden High remains; it is never Pass with a live arch-boundary or error-contract breach.

Gate Authority — HIGH findings are pipeline-blocking

This skill is a quality gate (the orchestrator wires it as Gate 3). The reviewer's job is to classify severities so they block — the orchestrator enforces the block and drives remediation; it does NOT re-triage.

  • Every Critical and every HIGH finding feeds the blocking finding → fix → verify remediation chain. A HIGH is not advisory: the orchestrator must not advance to deployment-pipeline configuration while one is open. This is the same chain the BUILD gates use.
  • The architecture-boundary and error-contract findings classified HIGH above (dependency-direction breach, port-boundary violation, error response not RFC 9457 / off the error-catalog) enter that chain unchanged — make arch exit non-zero, an inward framework import, or a bespoke error envelope each block 'production-ready', matching architecture-boundaries.md's "HIGH, pipeline-blocking, NOT Medium" rule.
  • BLOCK on failing tests / coverage / perf-budget / compliance / arch-boundary. The reviewer reports the breach at the mandated severity; the gate refuses to pass. Do not soften a HIGH to Medium to "let it through" — that defeats the gate.
  • Override path (accepted with justification — LOGGED): a HIGH may be explicitly accepted only with a written justification recorded in review-report.md (finding ID, who accepted, why, the ticket/removal date). For arch-boundary breaches the override MUST also be the config-covered, time-boxed, ticket-referenced exception (deptrac skip_violations / import-linter ignore_imports / dep-cruiser comment) — an unannotated breach cannot be overridden, it stays HIGH and blocks. The override is a logged decision, never a silent downgrade.
  1. Write individual findings files to drydock/code-reviewer/findings/:

    • critical.md — Findings that block deployment
    • high.md — Findings that must be fixed before production
    • medium.md — Findings that should be fixed soon
    • low.md — Advisory findings

    Each finding in these files uses the following format:

    ### [FINDING-ID] Short description
    
    **Severity:** Critical | High | Medium | Low
    **Category:** Architecture | Code Quality | Performance | Test Quality
    **Location:** `path/to/file.ts:42`
    
    **Description:**
    What the issue is and why it matters.
    
    **Impact:**
    What happens if this is not fixed.
    
    **Evidence:**
    ```code
    // The problematic code
    

    Recommendation: How to fix it, with a code example if applicable.

  2. Generate auto-fix suggestions for findings where the fix is mechanical and unambiguous:

    • Missing null checks
    • Missing auth middleware
    • Missing input validation
    • Missing error handling
    • Unused imports
    • Missing index definitions

    Write each auto-fix to drydock/code-reviewer/auto-fixes/<service>/<file>.patch.md with:

    • Finding ID reference
    • Before code block
    • After code block
    • Explanation of the change
  3. Compile metrics:

    • drydock/code-reviewer/metrics/complexity.json — Cyclomatic complexity per function, flagged functions with complexity > 10
    • drydock/code-reviewer/metrics/coverage-gaps.json — List of untested files, untested functions, untested branches
    • drydock/code-reviewer/metrics/dependency-analysis.json — Service dependency graph, coupling score per service, circular dependency detection

Output: Write all report files, findings, metrics, and auto-fixes to drydock/code-reviewer/.


Common Mistakes

#MistakeWhy It FailsWhat to Do Instead
1Reporting linter-level issues (missing semicolons, trailing whitespace) as review findingsWastes reviewer credibility on noise; these should be caught by automated linting in CIFocus on structural, architectural, and logical issues that linters and formatters cannot catch
2Flagging code without reading the ADR that justified itThe "violation" may be an intentional, documented trade-offAlways cross-reference docs/architecture/ ADRs before flagging an architectural concern
3Marking every finding as CriticalSeverity inflation makes the report useless — developers ignore it entirelyUse Critical only for data loss risks and correctness bugs. Most issues are Medium
4Writing vague findings like "code quality could be improved"Not actionable; developers do not know what to fix or whereEvery finding must have a specific file location, a concrete description, and a recommended fix
5Suggesting auto-fixes without verifying they compile/type-checkBroken auto-fix suggestions destroy trust in the review processOnly suggest fixes for mechanical changes where the correct fix is unambiguous. Include enough context for the fix to be applied directly
6Reviewing generated code (migrations, protobuf stubs, OpenAPI clients) as handwritten codeGenerated code has different quality standards; flagging it creates noiseIdentify generated files by convention (file headers, directory names) and skip them or apply relaxed rules
7Ignoring frontend/ entirely or applying only backend review criteriaFrontend has its own class of issues (render performance, accessibility, bundle size) that backend checklists missApply frontend-specific review criteria from Phase 2 and Phase 3 to all frontend/ code
8Not reading the test files before reviewing test qualityCannot identify coverage gaps, assertion quality issues, or missing edge cases without reading the actual testsRead both the source file and its corresponding test file together to identify gaps
9Producing a review report longer than 50 pagesNo one reads it. Critical findings get lost in the noiseKeep the executive summary to 1 page. Use the findings files for detail. Prioritize ruthlessly
10Modifying files in services/, frontend/, or tests/The reviewer must not change source code — only document findings and suggest fixesWrite all output exclusively to drydock/code-reviewer/. Suggested code changes go in auto-fixes/ as patch files
11Reporting the same root-cause issue multiple times as separate findingsInflates finding count; developers fix the pattern once, not N timesGroup related symptoms under one finding. Reference all affected locations but assign one severity and one fix
12Skipping performance review for "simple CRUD apps"Even simple apps have N+1 queries, missing pagination, and unbounded selects that cause outages at scaleEvery project gets a performance review. Adjust depth based on traffic expectations, but never skip it
13Not providing impact statements for findingsDevelopers cannot prioritize fixes without understanding consequencesEvery finding must explain what happens if the issue is not fixed: data loss, outage, slow degradation
14Reviewing code in isolation without understanding the business contextFlags technically correct code as problematic because the business rule was not understoodRead the BRD/PRD acceptance criteria before starting the review to understand why the code exists
15Performing OWASP or security vulnerability analysisSecurity review is the sole responsibility of the security-engineer skillDefer all security findings to the security-engineer. Focus on architecture, code quality, performance, and test quality
16Being too polite in findingsPolite findings get ignored. "Could potentially be improved" is not actionable.Write findings that make the problem unavoidable: "This WILL crash when X happens because Y." If you're not uncomfortable writing it, you're not being adversarial enough.
17Filing a dependency-direction or port-boundary breach as Medium "cleanup later"Severity DEFLATION lets structural rot through the gate; the orchestrator only blocks on Critical/HIGHDependency-direction and port-boundary violations are HIGH, pipeline-blocking (see Fixed severity classifications). Never downgrade them to style/tech-debt — architecture-boundaries.md mandates HIGH.
18Asserting "the architecture boundary is clean" without running make archAn un-run gate proves nothing; the import graph may already be brokenRUN make arch, observe exit 0, and cite the actual output (per grounding-protocol.md). If the gate is missing or wrapped in || true/continue-on-error, that absence is itself a HIGH finding.
19Demanding value objects for every primitive on a thin CRUD serviceAnemic shape is correct for pass-through/DTO services; blanket "wrap every string" is noiseApply the anemic-domain / primitive-obsession check PROPORTIONALLY — only to services with real business invariants, and only as Medium.
20Accepting a bespoke {code,message,details} error body because "it works"A second error shape breaks the RFC 9457 client contract and desyncs runtime from the docs error tableRequire application/problem+json $ref'ing the shared Problem schema, populated via the error-catalog module — flag any other shape HIGH.

Execution Checklist

Before marking the skill as complete, verify:

  • architecture-conformance.md audits every ADR in docs/architecture/ with a conformance status
  • make arch was RUN this session; exit code + output recorded. Any non-zero exit, inward framework/IO import, outward-pointing inner import, or port-boundary violation is reported as a HIGH (pipeline-blocking) finding; a missing/|| true-wrapped gate is itself a HIGH finding
  • Error-contract checked: every 4xx/5xx serves application/problem+json and $refs the shared Problem schema; runtime errors flow through the error-catalog module; bespoke {code,message,details} envelopes flagged HIGH
  • Anemic-domain / primitive-obsession check applied ONLY to domain-rich services (skipped for thin CRUD), findings classified Medium
  • Performance findings cite thresholds READ from docs/architecture/performance-budget.yaml (no hardcoded 500ms/200KB) and reference ONLY observability-contract.md metric names
  • All Critical + HIGH findings are classified to block the orchestrator's Gate 3 remediation chain; any HIGH override is logged in review-report.md with justification + ticket
  • Every finding has: ID, severity, category, file location, description, impact, and recommendation
  • Performance review checks for N+1 queries, missing indexes, unbounded queries, and caching gaps
  • Test quality review cross-references the drydock/qa-engineer/test-plan.md traceability matrix for coverage gaps
  • review-report.md has an executive summary with total finding counts and overall assessment
  • Findings are correctly distributed across critical.md, high.md, medium.md, and low.md
  • metrics/complexity.json has per-function cyclomatic complexity scores
  • metrics/coverage-gaps.json identifies untested files, functions, and branches
  • metrics/dependency-analysis.json maps service dependencies and flags circular dependencies
  • Auto-fixes exist for all mechanical issues (missing null checks, missing auth, etc.)
  • No files were created or modified outside of drydock/code-reviewer/
  • The report is actionable — a developer can read a finding and know exactly what to fix and where
  • No OWASP or security review was performed — security analysis is deferred to security-engineer

Keep looking

Skills are one crate of 628,971. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.