feat: Unified PR review engine (ckb review)#137
Conversation
Implements comprehensive PR review with parallel quality gates: - Engine core (review.go): orchestrates breaking, secrets, tests, complexity, coupling, hotspots, risk, and critical-path checks - CLI command (cmd/ckb/review.go): human, markdown, github-actions formats - MCP tool (reviewPR): full InputSchema, added to PresetReview - HTTP API (POST /review/pr): GET/POST with policy overrides - Config section (ReviewConfig): repo-level policy defaults - Complexity delta (review_complexity.go): tree-sitter before/after comparison - Coupling gaps (review_coupling.go): co-change analysis for missing files - 15 tests covering integration (real git repos) and unit tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PR split suggestion via connected component analysis on module affinity + coupling graph. Change classification (new/refactor/ moved/churn/config/test/generated) with review priority. Review effort estimation based on LOC, file switches, module context switches, and critical file overhead. Per-cluster reviewer assignment from ownership data. New files: - review_split.go: BFS-based clustering, coupling edge enrichment - review_classify.go: 8 categories with confidence + priority - review_effort.go: time estimation with complexity tiers - review_reviewers.go: per-cluster reviewer scoping Wired into ReviewPR response (SplitSuggestion, ChangeBreakdown, ReviewEffort, ClusterReviewers). CLI formatters updated for human and markdown output. 16 new tests, 31 total. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… 4-7 Batch 4 — Code Health & Baseline: - 8-factor weighted health score (cyclomatic, cognitive, LOC, churn, coupling, bus factor, age, coverage) - Per-file health deltas with A-F grading, wired as parallel check - Finding baselines: save/load/list/compare with SHA256 fingerprinting - CLI: ckb review baseline save/list/diff Batch 5 — Industrial/Compliance: - Traceability check: configurable regex patterns for ticket IDs in commits/branches - Reviewer independence enforcement: author exclusion, critical-path escalation - Compliance evidence export format (--format=compliance) - Git adapter: GetCommitRange() for commit-range queries Batch 6 — CI/CD & Output Formats: - SARIF v2.1.0 output with partialFingerprints, fixes, rules - CodeClimate JSON output for GitLab Code Quality - GitHub Action (action/ckb-review/action.yml) with PR comments and SARIF upload - GitLab CI template (ci/gitlab-ckb-review.yml) with code quality job Batch 7 — Tests & Golden Files: - 6 golden-file tests for all output formats (human, markdown, sarif, codeclimate, github-actions, json) - 19 format unit tests (SARIF, CodeClimate, GitHub Actions, human, markdown, compliance) - 16 health/baseline tests, 10 traceability/independence tests - Fixed map iteration order in formatters for deterministic output Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Adds dedicated review-tests job that runs: - Review engine unit/integration tests (82 tests across batches 1-7) - Format output tests (SARIF, CodeClimate, GitHub Actions, compliance) - Golden-file tests with staleness check for testdata/review/ Build job now gates on review-tests passing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
| // getBaseComplexity gets complexity of a file at a given git ref. | ||
| func getBaseComplexity(ctx context.Context, analyzer *complexity.Analyzer, repoRoot, file, ref string) *complexity.FileComplexity { | ||
| // Use git show to get the base version content | ||
| cmd := exec.CommandContext(ctx, "git", "show", ref+":"+file) |
Check failure
Code scanning / gosec
Subprocess launched with variable Error
🔐 Security Audit Results
🛡️ SAST AnalysisFound 17 issue(s) across 1 scanner(s) DetailsGosec (17 findings)
📦 Dependency VulnerabilitiesFound 16 vulnerability(ies) across 2 scanner(s) DetailsTrivy (10 findings)
OSV-Scanner (6 findings)
📜 License IssuesFound 69 non-permissive license(s) Details
Generated by CKB Security Audit | View Details | Security Tab |
🟡 Change Impact Analysis
Blast Radius: 0 modules, 1 files, 261 unique callers 📝 Changed Symbols (747)
🎯 Affected Downstream (20)
Recommendations
Generated by CKB |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #137 +/- ##
=========================================
+ Coverage 45.6% 47.4% +1.8%
=========================================
Files 367 385 +18
Lines 61934 64484 +2550
=========================================
+ Hits 28274 30608 +2334
- Misses 31744 31794 +50
- Partials 1916 2082 +166
Flags with carried forward coverage won't be shown. Click here to find out more. 📢 Thoughts on this report? Let us know! 🚀 New features to boost your workflow:
|
CKB Analysis
Risk factors: Large PR with 60 files • High churn: 9868 lines changed • Touches 49 hotspot(s) 👥 Suggested: @lisa.welsch1985@gmail.com (100%), @talantyyr@gmail.com (38%), @lisa@tastehub.io (2%)
🎯 Change Impact Analysis · 🟡 MEDIUM · 747 changed → 20 affected
Symbols changed in this PR:
Downstream symbols affected:
Recommendations:
💣 Blast radius · 0 symbols · 8 tests · 0 consumersTests that may break:
🔥 Hotspots · 49 volatile files
📦 Modules · 4 at risk
📊 Complexity · 12 violations
💡 Quick wins · 10 suggestions
📚 Stale docs · 148 broken references
Generated by CKB · Run details |
- Serialize complexity/health/hotspots/risk checks into single goroutine to prevent go-tree-sitter cgo SIGABRT from concurrent parser use - Fix SARIF v2.1.0: use RelatedLocations for suggestions instead of non-compliant empty Fixes (requires artifactChanges) - Add path traversal prevention on baseline tags (regex validation) - Fix matchGlob silent truncation for patterns with 3+ ** wildcards - Add GHA annotation escaping (%, \r, \n) and markdown pipe escaping - Fix double file close in calculateBaseFileHealth - Fix err.Error() != "EOF" to err != io.EOF in HTTP handler - Fix errcheck violations across format tests and batch tests - Update MCP preset/budget test counts for new reviewPR tool - Reformat all files with gofmt - Add compliance golden file Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- action.yml: Pass all inputs via env vars to prevent script injection - action.yml: Generate JSON/GHA/markdown in single pass (was 3 runs) - action.yml: Use env vars for github.repository/PR number in comment step - Score: Cap per-check deductions at 20 points so noisy checks (coupling with 100+ co-change warnings) don't floor the score at 0 - Human format: Fix grade+filename concatenation (missing space) - Effort: Fix comment claiming 400 LOC/hr (code uses 300/500) - Classify: Remove dead code path (Additions==0 && Deletions==0 already caught by total==0 above), remove unreachable .github map entry - Baseline: Fix misleading "symlink" comment (it's a copy) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Health check was the main bottleneck — for each file it computed churn, coupling, bus factor, and age scores TWICE (before + after) despite these being branch-independent (identical values, zero delta). Changes: - Compute repo-level metrics once per file via repoMetrics struct, pass to both calculateFileHealth and calculateBaseFileHealth - Cap health check at 30 files (was unbounded) - Reduce coupling gap file limit from 30 to 20 - Reduce split coupling lookup limit from 30 to 20 - Add ctx.Err() checks in all per-file loops (health, complexity, coupling, split) so cancellation is respected between iterations For a 39-file PR this cuts ~156 git subprocess calls (4 metrics × 39 files that were duplicated) and caps the total file processing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add ckb review CLI examples and reviewPR MCP tool to CLAUDE.md - Fix reviewPR description: list all 14 checks, say "concurrently where safe" - Reuse single complexity.Analyzer in health check (avoids 60+ cgo allocs) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- New pr-review job in CI: runs on PRs after build, posts comment, emits GHA annotations, writes job summary - New examples/github-actions/pr-review.yml documenting full usage - Update examples README: add pr-review, mark pr-analysis as legacy - Fix action.yml misleading comment, route exit code through env var Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move Key Risks section after the checks table so the markdown flows as: checks → narrative → findings. Enable git-blame fallback in reviewer suggestions so repos without CODEOWNERS still get suggested reviewers. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- ci.yml: Move pull-requests:write from workflow-level to pr-review job only (other jobs no longer get unnecessary PR write access) - build-matrix.yml: Set cancel-in-progress:false (runs on main push only, cancelling artifact builds on rapid merges loses artifacts) - action/ckb-review: Pin upload-sarif to SHA @b1bff81...dcd061c8 (v4), was floating @V3 tag — inconsistent with all other pinned actions - Update golden for Top Risks section reorder Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- go.mod: Require Go 1.26.1 to resolve GO-2026-4599 through GO-2026-4602 (crypto/x509 cert validation, net/url IPv6 parsing, os.Root escape) - ci.yml: Align download-artifact SHA to 018cc2cf... matching nfr.yml and security-gate.yml (caught by cicheck consistency test) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The "Fail on review verdict" step referenced ${SCORE} without declaring
it in the env block. Reviewers field now omits from JSON when empty
instead of emitting "reviewers": null.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
ckb review— a comprehensive, structural PR review engine with 13 parallel checks, 7 output formats, and finding baseline managementEngine.ReviewPR()method automatically exposed via CLI, HTTP API, and MCPWhat's included
Checks (13, run in parallel)
breaking·secrets·tests·complexity·coupling·hotspots·risk·critical·generated·health·traceability·independence·splitOutput Formats (7)
human·json·markdown·github-actions·sarif·codeclimate·complianceFeatures by batch
ckb review baseline save/list/diffCI
review-testsjob in CI pipeline: engine tests, format tests, golden-file staleness checkNew files (26)
Test plan
go test ./internal/query/... -run TestReview— 15 integration tests with real git reposgo test ./internal/query/... -run "TestClassify|TestEstimate|TestSuggest|TestBFS"— 16 Batch 3 testsgo test ./internal/query/... -run "TestHealth|TestBaseline|TestFingerprint|TestSave|TestLoad|TestCompare"— 16 Batch 4 testsgo test ./internal/query/... -run "TestCheckTraceability|TestCheckIndependence"— 10 Batch 5 testsgo test ./cmd/ckb/... -run "TestFormatSARIF|TestFormatCodeClimate|TestFormatGitHubActions|TestFormatCompliance"— 19 format testsgo test ./cmd/ckb/... -run TestGolden— 6 golden-file testsgo build ./cmd/ckb— binary builds cleanly🤖 Generated with Claude Code