# Impact Analysis **Core feature since v5.1 | Enhanced in v7.5-v7.6 | Test mapping in v7.5** Impact Analysis answers three critical questions before every code change: 1. **"What downstream code might break?"** — Blast radius analysis 2. **"Which tests should I run?"** — Targeted test selection 3. **"Who needs to review this?"** — Affected owners identification This is something LLMs fundamentally cannot do without tooling — they can't reason about the full dependency graph, test mappings, or cross-file relationships at scale. --- ## Table of Contents - [Prerequisites](#prerequisites) - [Quick Start](#quick-start) - [prepareChange Tool (v8.0)](#preparechange-tool-v80) - [Single Symbol Impact Analysis](#single-symbol-impact-analysis) - [Git Diff Impact Analysis](#git-diff-impact-analysis) - [Affected Tests (v7.5)](#affected-tests-v75) - [Reviewer Suggestions](#reviewer-suggestions) - [Configuration](#configuration) - [CI/CD Integration](#cicd-integration) - [Best Practices](#best-practices) - [Limitations](#limitations) --- ## prepareChange Tool (v8.0) **New in v8.0:** The `prepareChange` compound tool combines multiple impact analysis queries into a single call, reducing AI tool invocations by 60-70%. ```json { "tool": "prepareChange", "params": { "target": "ckb:repo:sym:abc123", "changeType": "modify" } } ``` **Change types:** `modify` | `rename` | `delete` | `extract` **What it returns:** - Direct dependents from `analyzeImpact` - Affected tests from `getAffectedTests` - Co-change files from `analyzeCoupling` - Risk assessment with severity and mitigation suggestions **Example response:** ```json { "impact": { "directCallers": 8, "transitiveCallers": 23, "blastRadius": { "level": "medium", "modules": 3, "files": 12 } }, "tests": { "affected": ["auth_test.go", "handler_test.go"], "runCommand": "go test ./internal/auth/..." }, "coupling": { "coChangeFiles": ["config.go", "middleware.go"], "correlation": 0.72 }, "risk": { "level": "medium", "factors": ["public API", "multiple callers"], "suggestions": ["Add tests before modifying", "Review callers in api module"] } } ``` **When to use prepareChange vs granular tools:** - Use `prepareChange` for most pre-modification analysis (recommended) - Use `analyzeImpact` alone when you only need caller information - Use `getAffectedTests` alone when you just need test selection --- ## Prerequisites Impact analysis quality depends on your indexing setup. Here's what you need for each level of accuracy: ### Minimum: Tree-sitter (Fast Tier) Works out of the box with no additional setup. - **Provides:** Basic symbol detection, file-level analysis - **Limitations:** No cross-file references, confidence scores are low (0.3) - **Best for:** Quick checks, unsupported languages ### Recommended: SCIP Index (Standard Tier) Full semantic analysis with cross-file references. ```bash # Install SCIP indexer for your language go install github.com/sourcegraph/scip-go/cmd/scip-go@latest # Go npm install -g @anthropic/scip-typescript # TypeScript # Generate index ckb index ``` **Provides:** - Exact symbol definitions and references - Call graph traversal (callers and callees) - Transitive impact analysis (depth 2-4) - High confidence scores (0.85-1.0) **Language support for SCIP:** | Language | Indexer | Quality | |----------|---------|---------| | Go | scip-go | Tier 1 (full) | | TypeScript/JS | scip-typescript | Tier 2 (full, minor edge cases) | | Python | scip-python | Tier 2 | | Rust | rust-analyzer | Tier 3 | | Java/Kotlin | scip-java | Tier 3 | See [[Language-Support]] for full compatibility matrix. ### Enhanced: Telemetry Integration (Full Tier) Add runtime observability for production-aware impact analysis. ```json { "telemetry": { "enabled": true, "serviceMap": { "my-api-service": "my-repo" } } } ``` **Provides:** - Observed callers from production traffic - `blendedConfidence` combining static + runtime analysis - Detection of dynamic dispatch and reflection calls - "Observed only" callers that static analysis misses See [[Telemetry]] for setup instructions. ### Test Mapping: Coverage Files (v7.5) For precise test selection, provide coverage data: **Go:** ```bash # Generate coverage file go test -coverprofile=coverage.out ./... # CKB will auto-detect coverage.out in the project root ``` **JavaScript/TypeScript (Jest):** ```bash # Generate lcov coverage jest --coverage --coverageReporters=lcov # Coverage will be at coverage/lcov.info ``` **Python (pytest):** ```bash # Generate coverage pytest --cov=. --cov-report=lcov # Coverage will be at coverage.lcov or lcov.info ``` **Dart (flutter/dart test):** ```bash # Generate coverage (Flutter) flutter test --coverage # Coverage will be at coverage/lcov.info ``` **Rust (cargo-tarpaulin):** ```bash # Install tarpaulin cargo install cargo-tarpaulin # Generate coverage cargo tarpaulin --out Lcov # Coverage will be at lcov.info ``` **Java (JaCoCo):** ```bash # Maven with JaCoCo plugin mvn test jacoco:report # Coverage will be at target/site/jacoco/jacoco.xml # Or configure for lcov output ``` **Provides:** - Precise line-level test mapping - `affectedTests` field in impact analysis - `ckb affected-tests` command **Fallback strategies** (when no coverage file): 1. Naming convention: `foo.go` → `foo_test.go` 2. Import analysis: tests importing changed package 3. Package-level: all tests in affected directories See [Configuration](#configuration) for custom coverage file locations. ### Reviewer Suggestions: CODEOWNERS For automated reviewer routing, add a CODEOWNERS file: ```bash # .github/CODEOWNERS (GitHub) or CODEOWNERS (GitLab) # Default owner * @default-team # Module-specific owners /internal/api/ @api-team /internal/auth/ @security-team /internal/payments/ @payments-team @finance-team # File-specific owners /go.mod @platform-team ``` **Provides:** - `affectedOwners` in impact analysis - `ckb reviewers` command - Suggested reviewers in `ckb pr-summary` Without CODEOWNERS, CKB falls back to git blame for ownership signals. ### Keeping the Index Fresh Impact analysis is only as accurate as your index. Stale indexes produce stale results. ```bash # Check freshness ckb status # Manual refresh ckb index # Watch mode (auto-refresh on file changes) ckb index --watch # MCP with watch mode ckb mcp --watch ``` Use `--strict` mode to fail when the index is stale: ```bash ckb impact diff --strict # Fails if index is behind HEAD ``` ### Checking Your Setup Use `ckb status` to verify impact analysis prerequisites: ``` $ ckb status Repository: /Users/lisa/code/myproject Index: ✓ Fresh (indexed 5 minutes ago, 8,432 symbols) Language: Go Change Impact Analysis: Coverage: ✓ Found (coverage.out, 2 hours old) CODEOWNERS: ✓ Found (.github/CODEOWNERS, 15 patterns) ``` Missing components show actionable guidance: ``` Change Impact Analysis: Coverage: ⚠ Not found (test mapping will use heuristics) Generate: go test -coverprofile=coverage.out ./... CODEOWNERS: ⚠ Not found (reviewer suggestions unavailable) Create: .github/CODEOWNERS ``` --- ## Quick Start ```bash # 1. Initialize and index cd /your/project ckb init ckb index # 2. (Optional) Generate coverage for test mapping go test -coverprofile=coverage.out ./... # 3. Analyze impact of your changes ckb impact diff # Uncommitted changes ckb impact diff --staged # Staged changes only ckb impact diff --base=main # Compare to branch # 4. Get affected tests ckb affected-tests # Tests to run for your changes ckb affected-tests --output=command # Ready-to-run command # 5. Get suggested reviewers ckb reviewers # Who should review this? ``` --- ## Single Symbol Impact Analysis Analyze what depends on a specific symbol before changing it. ### CLI ```bash # Basic impact analysis ckb impact "UserService.Authenticate" # With transitive callers (depth 2-4) ckb impact "Engine.Start" --depth=3 # Include telemetry data ckb impact "HandleRequest" --include-telemetry ``` ### MCP Tool: `analyzeImpact` ```json { "name": "analyzeImpact", "arguments": { "symbolId": "scip-go gomod example.com/api internal/auth/user.go/UserService#Authenticate", "depth": 2, "includeTelemetry": true, "telemetryPeriod": "90d" } } ``` ### Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `symbolId` | string | required | Symbol ID or qualified name | | `depth` | number | 2 | Transitive depth (1-4). Depth 1 = direct callers only | | `includeTelemetry` | boolean | true | Include runtime observability data | | `telemetryPeriod` | string | "90d" | Telemetry window: "7d", "30d", "90d", "all" | ### Response ```json { "symbol": { "stableId": "scip-go gomod example.com/api ...", "name": "Authenticate", "kind": "function" }, "visibility": { "visibility": "public", "confidence": 0.9 }, "riskScore": { "score": 0.72, "level": "high", "explanation": "High risk: 15 direct caller(s) across 4 module(s).", "factors": [ { "name": "visibility", "value": 0.9, "weight": 0.3 }, { "name": "direct-callers", "value": 0.8, "weight": 0.35 }, { "name": "module-spread", "value": 0.6, "weight": 0.25 }, { "name": "impact-kind", "value": 0.7, "weight": 0.1 } ] }, "blastRadius": { "moduleCount": 4, "fileCount": 12, "uniqueCallerCount": 18, "riskLevel": "medium" }, "directImpact": [ { "stableId": "...", "name": "LoginHandler", "kind": "direct-caller", "distance": 1, "confidence": 0.95 } ], "transitiveImpact": [ { "stableId": "...", "name": "ServeHTTP", "kind": "transitive-caller", "distance": 2, "confidence": 0.85 } ], "modulesAffected": [ { "moduleId": "internal/api", "name": "api", "impactCount": 8 }, { "moduleId": "internal/auth", "name": "auth", "impactCount": 5 } ], "observedUsage": { "hasTelemetry": true, "totalCalls": 1250, "trend": "stable" }, "blendedConfidence": 0.89, "relatedDecisions": [...], "docsToUpdate": [...] } ``` ### Blast Radius (v7.6) The `blastRadius` field provides a quick summary of impact spread: | Risk Level | Criteria | |------------|----------| | **Low** | ≤2 modules AND ≤5 callers | | **Medium** | 3-5 modules OR 6-20 callers | | **High** | >5 modules OR >20 callers | ### Transitive Impact (v7.6) When `depth > 1` and SCIP is available, CKB traces callers-of-callers: | Depth | Confidence | Use Case | |-------|------------|----------| | 1 | 0.95 | Direct callers only | | 2 | 0.85 | Default, catches most impact | | 3 | 0.75 | For high-risk refactors | | 4 | 0.65 | Maximum coverage, more noise | ### Risk Score Calculation Risk is computed from 4 weighted factors: | Factor | Weight | Description | |--------|--------|-------------| | `visibility` | 30% | Public symbols are riskier | | `direct-callers` | 35% | More callers = higher risk | | `module-spread` | 25% | Cross-module impact is riskier | | `impact-kind` | 10% | Breaking changes vs additive | Risk levels: - **Low** < 0.4 - **Medium** 0.4-0.6 - **High** 0.6-0.8 - **Critical** > 0.8 ### Cross-Repo Outgoing Impact (v9.2) `analyzeImpact` answers "who depends on this symbol *inside this repo*". `analyzeOutgoingImpact` extends that across federated repos by routing through LIP's `query_outgoing_impact` RPC. **MCP tool:** `analyzeOutgoingImpact` ```json { "symbol": "ckb:repo-a:sym:abc123", "depth": 2 } ``` Returns per-repo caller counts, aggregated risk, and the LIP edges traversed. Only meaningful when LIP v2.3+ is running across multiple federated repos. Degrades silently to single-repo `analyzeImpact` semantics if no remote LIPs are reachable. ### Symbol Existence Probe (v9.2) `symbolExists` is a cheap pre-flight check: returns `{ exists, confidence, alias_chain? }` without loading the full symbol record. Use it in agent planning loops before expensive `analyzeImpact` or `findReferences` calls. --- ## Git Diff Impact Analysis Analyze the impact of pending code changes from git diffs. ### CLI ```bash # Analyze current working tree changes ckb impact diff # Analyze only staged changes ckb impact diff --staged # Compare against a different branch ckb impact diff --base=main # Analyze a commit range (for CI) ckb impact --range=main..HEAD # Deeper transitive analysis ckb impact diff --depth=3 # Strict mode (fail if index is stale) ckb impact diff --strict # Output formats ckb impact diff --format=json # Machine-readable JSON ckb impact diff --format=markdown # PR comment-ready markdown ``` ### Output Formats | Format | Use Case | |--------|----------| | `text` | Human-readable terminal output (default) | | `json` | Machine-readable, for scripting and CI | | `markdown` | PR comments, GitHub/GitLab integration | #### Markdown Output (`--format=markdown`) Generates formatted markdown suitable for PR comments: ```bash ckb impact --range=origin/main..HEAD --format=markdown > comment.md ``` **Example output:** ```markdown ## 🟡 Change Impact Analysis | Metric | Value | |--------|------:| | Risk Level | **medium** | | Symbols Changed | 12 | | Directly Affected | 28 | | Transitively Affected | 45 | | Modules in Blast Radius | 3 | ### Changed Symbols - `UserService.Authenticate` (internal/auth/user.go) - `LoginHandler` (internal/api/login.go) ### Affected Modules | Module | Impact Count | |--------|-------------:| | internal/api | 15 | | internal/auth | 8 | | internal/session | 5 | ### Recommendations - ⚠️ High-risk change affecting 3 modules. Consider additional code review. - ⚠️ Run tests for affected modules before merging. ``` This output is designed for the `sticky-pull-request-comment` GitHub Action pattern. ### MCP Tool: `analyzeChange` ```json { "name": "analyzeChange", "arguments": { "staged": false, "baseBranch": "HEAD", "depth": 2, "includeTests": false, "strict": false } } ``` ### Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `diffContent` | string | - | Raw diff (if empty, uses git diff) | | `staged` | boolean | false | Analyze staged changes only | | `baseBranch` | string | HEAD | Base for comparison | | `depth` | number | 2 | Transitive depth (1-4) | | `includeTests` | boolean | false | Include test files | | `strict` | boolean | false | Fail if index is stale | ### How It Works ``` Git Diff → Parse Hunks → Map to Symbols → Analyze Impact → Aggregate Results ``` 1. **Parse Diff**: Uses `sourcegraph/go-diff` to parse unified diffs 2. **Map to Symbols**: Matches changed lines to SCIP symbol definitions 3. **Analyze Impact**: Runs single-symbol impact analysis on each changed symbol 4. **Aggregate Results**: Deduplicates, computes module spread, calculates risk ### Response ```json { "summary": { "filesChanged": 5, "symbolsChanged": 23, "directlyAffected": 12, "transitivelyAffected": 45, "estimatedRisk": "medium" }, "changedSymbols": [ { "symbolId": "scip-go gomod example.com/api Handler().", "name": "Handler", "file": "internal/api/handler.go", "changeType": "modified", "lines": [45, 46, 47], "confidence": 1.0 } ], "affectedSymbols": [ { "stableId": "...", "name": "ServeHTTP", "kind": "direct-caller", "distance": 1, "moduleId": "internal/server", "confidence": 0.9 } ], "blastRadius": { "moduleCount": 3, "fileCount": 8, "uniqueCallerCount": 15, "riskLevel": "medium" }, "recommendations": [ { "type": "review", "severity": "warning", "message": "High-risk change affecting 5 modules. Consider additional code review.", "action": "Request review from module owners" }, { "type": "test", "severity": "warning", "message": "Significant transitive impact (45 symbols). Run comprehensive test suite.", "action": "Run full test suite before merging" } ], "indexStaleness": { "isStale": false, "commitsBehind": 0, "indexedCommit": "abc123", "headCommit": "abc123" } } ``` ### Confidence Scoring Symbol mapping confidence based on match precision: | Confidence | Meaning | |------------|---------| | 1.0 | Exact definition line match | | 0.8 | Change within symbol body | | 0.7 | Reference on changed line | | 0.3 | File-level only (no SCIP data) | ### Aggregated Risk Scoring Four weighted factors determine overall risk: | Factor | Weight | Thresholds | |--------|--------|------------| | `symbols_changed` | 20% | >5 = 0.5, >10 = 0.7, >20 = 1.0 | | `direct_impact` | 30% | >10 = 0.5, >20 = 0.7, >50 = 1.0 | | `transitive_impact` | 20% | >20 = 0.5, >50 = 0.7, >100 = 1.0 | | `module_spread` | 30% | >1 = 0.4, >3 = 0.7, >5 = 1.0 | Risk levels: `low` (<0.4), `medium` (0.4-0.6), `high` (0.6-0.8), `critical` (>0.8) --- ## Affected Tests (v7.5) Get a list of tests to run based on your code changes. Dramatically reduces CI time by running only relevant tests. ### CLI ```bash # Get tests for uncommitted changes ckb affected-tests # Output as runnable command ckb affected-tests --output=command # → go test -run 'TestAuth|TestLogin|TestSession' ./... # Output as simple list (one test per line) ckb affected-tests --format=list # → TestAuth # → TestLogin # → TestSession # Specify coverage file location ckb affected-tests --coverage=./coverage/lcov.info # Strategy options ckb affected-tests --strategy=precise # Only tests directly covering changes ckb affected-tests --strategy=safe # Include transitive tests (default) ckb affected-tests --strategy=full # All tests in affected packages ``` ### MCP Tool: `getAffectedTests` ```json { "name": "getAffectedTests", "arguments": { "commit": "HEAD", "strategy": "safe" } } ``` ### Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `files` | string[] | - | Changed file paths | | `symbols` | string[] | - | Changed symbol IDs | | `commit` | string | - | Git commit SHA | | `commitRange` | string | - | "base..head" format | | `strategy` | string | "safe" | Test selection strategy | ### Test Selection Strategies | Strategy | Description | Use Case | |----------|-------------|----------| | `precise` | Only tests that directly cover changed lines | Fast feedback, may miss edge cases | | `safe` | Include tests for transitive callers (1 level) | Default, good balance | | `full` | All tests in affected packages | Pre-merge, paranoid mode | ### Response ```json { "strategy": "safe", "confidence": 0.92, "tests": [ { "name": "TestUserAuthenticate", "path": "internal/auth/user_test.go", "reason": "Directly covers changed symbol UserService.Authenticate", "priority": 1 }, { "name": "TestLoginHandler", "path": "internal/api/login_test.go", "reason": "Tests caller of changed symbol", "priority": 2 } ], "commands": { "go": "go test -run 'TestUserAuthenticate|TestLoginHandler' ./internal/..." }, "warnings": { "uncoveredSymbols": ["internal/legacy/handler.go:OldFunc"], "staleData": false } } ``` ### Confidence Scoring Confidence reflects data quality: | Confidence | Data Source | |------------|-------------| | 0.95+ | Coverage file with line-level mapping | | 0.80-0.94 | Naming convention + import analysis | | 0.60-0.79 | Package-level mapping only | | < 0.60 | Heuristics, consider running full suite | ### CI Integration Example ```yaml - name: Run Affected Tests run: | # Get test command CMD=$(ckb affected-tests --output=command --strategy=safe) CONFIDENCE=$(ckb affected-tests --format=json | jq '.confidence') if (( $(echo "$CONFIDENCE < 0.7" | bc -l) )); then echo "Low confidence, running full suite" go test ./... else echo "Running: $CMD" eval "$CMD" fi ``` --- ## Reviewer Suggestions Identify who should review changes based on CODEOWNERS and git history. ### CLI ```bash # Get reviewers for uncommitted changes ckb reviewers # Include owners of affected (not just changed) code ckb reviewers --include-affected # JSON output for scripting ckb reviewers --format=json ``` ### MCP Tool: `getChangeOwners` ```json { "name": "getChangeOwners", "arguments": { "commit": "HEAD", "includeSecondary": true } } ``` ### Parameters | Parameter | Type | Default | Description | |-----------|------|---------|-------------| | `files` | string[] | - | Changed file paths | | `symbols` | string[] | - | Changed symbol IDs | | `commit` | string | - | Git commit SHA | | `includeSecondary` | boolean | false | Include owners of affected (not changed) code | ### Response ```json { "primary": [ { "owner": "@security-team", "source": "codeowners", "pattern": "/internal/auth/*", "confidence": 1.0 }, { "owner": "@alice", "source": "git-blame", "files": ["internal/auth/user.go"], "confidence": 0.85 } ], "secondary": [ { "owner": "@api-team", "source": "codeowners", "reason": "Owns caller of changed symbol", "confidence": 0.7 } ], "reviewStrategy": { "minimum": ["@security-team"], "recommended": ["@security-team", "@alice", "@api-team"] } } ``` ### Review Strategy | Category | Description | |----------|-------------| | `minimum` | Must approve — CODEOWNERS with full match | | `recommended` | Should approve — includes secondary owners and git contributors | ### CI Integration Example ```yaml - name: Request Reviews run: | REVIEWERS=$(ckb reviewers --format=json | jq -r '.reviewStrategy.recommended | join(",")') gh pr edit --add-reviewer "$REVIEWERS" ``` --- ## Configuration Configure impact analysis behavior in `.ckb/config.json`: ```json { "coverage": { "paths": [ "coverage.out", "coverage/lcov.info", "coverage.lcov" ], "autoDetect": true, "maxAge": "168h" }, "ownership": { "paths": [ ".github/CODEOWNERS", "CODEOWNERS" ] }, "impact": { "defaultDepth": 2, "strict": false, "includeTests": true } } ``` | Field | Description | |-------|-------------| | `coverage.paths` | Checked in order, first found wins | | `coverage.autoDetect` | Also check common locations (default: true) | | `coverage.maxAge` | Warn if older than this (default: 168h / 7 days) | | `ownership.paths` | CODEOWNERS file locations | | `impact.defaultDepth` | Transitive depth 1-4 (default: 2) | | `impact.strict` | Fail on stale index (default: false) | | `impact.includeTests` | Include test files in analysis (default: true) | ### Environment Variables | Variable | Description | |----------|-------------| | `CKB_COVERAGE_PATH` | Override coverage file location | | `CKB_IMPACT_DEPTH` | Default transitive depth | | `CKB_IMPACT_STRICT` | Set to `1` to fail on stale index | --- ## CI/CD Integration Impact analysis integrates with CI pipelines for automated risk assessment and PR comments. ### GitHub Actions: PR Comment Widget The simplest integration — post impact analysis as a PR comment: ```yaml # .github/workflows/impact-comment.yml name: Impact Comment on: pull_request: types: [opened, synchronize] permissions: contents: read pull-requests: write jobs: comment: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup CKB run: npm install -g @tastehub/ckb - name: Generate Impact Report run: | ckb index --if-stale=24h ckb impact \ --range="${{ github.event.pull_request.base.sha }}..${{ github.sha }}" \ --format=markdown \ > impact.md - name: Post Comment uses: marocchino/sticky-pull-request-comment@v2 with: header: ckb-impact path: impact.md ``` The `sticky-pull-request-comment` action updates the same comment on each push (via `header: ckb-impact`) instead of creating duplicates. ### GitHub Actions: Full Workflow Complete workflow with risk gates, reviewer assignment, and affected tests: ```yaml # .github/workflows/impact-analysis.yml name: Change Impact Analysis on: pull_request: types: [opened, synchronize, reopened] permissions: contents: read pull-requests: write checks: write jobs: impact: name: Analyze Impact runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0 # Full history for commit range analysis - name: Setup CKB run: npm install -g @tastehub/ckb - name: Index Repository run: ckb index --if-stale=24h - name: Analyze PR Impact id: impact run: | ckb impact \ --range="${{ github.event.pull_request.base.sha }}..${{ github.sha }}" \ --format=json \ > impact.json echo "risk=$(jq -r '.summary.estimatedRisk' impact.json)" >> $GITHUB_OUTPUT echo "affected=$(jq -r '.summary.transitivelyAffected' impact.json)" >> $GITHUB_OUTPUT echo "files=$(jq -r '.summary.filesChanged' impact.json)" >> $GITHUB_OUTPUT - name: Generate PR Comment run: | ckb impact \ --range="${{ github.event.pull_request.base.sha }}..${{ github.sha }}" \ --format=markdown \ > comment.md - name: Post Impact Summary uses: marocchino/sticky-pull-request-comment@v2 with: header: impact-analysis path: comment.md - name: Get Suggested Reviewers id: reviewers run: | reviewers=$(ckb reviewers \ --range="${{ github.event.pull_request.base.sha }}..${{ github.sha }}" \ --format=gh) echo "list=$reviewers" >> $GITHUB_OUTPUT - name: Request Reviewers if: steps.reviewers.outputs.list != '' run: | gh pr edit ${{ github.event.pull_request.number }} \ --add-reviewer "${{ steps.reviewers.outputs.list }}" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - name: Risk Gate if: steps.impact.outputs.risk == 'critical' run: | echo "::error::Critical risk detected. Manual review required." echo "## ⛔ Critical Risk Detected" >> $GITHUB_STEP_SUMMARY echo "This PR affects critical paths. Please review carefully." >> $GITHUB_STEP_SUMMARY exit 1 outputs: risk: ${{ steps.impact.outputs.risk }} affected: ${{ steps.impact.outputs.affected }} ``` ### Risk-Based Test Strategy Run different test suites based on impact risk: ```yaml - name: Determine Test Strategy run: | RISK=$(jq -r '.summary.estimatedRisk' impact.json) MODULES=$(jq '.blastRadius.moduleCount' impact.json) if [ "$RISK" = "critical" ] || [ "$MODULES" -gt 5 ]; then echo "Running full test suite" go test ./... else echo "Running affected tests only" ckb affected-tests --strategy=safe --output=command | bash fi ``` ### Pre-commit Hook Block critical-risk commits locally: ```bash #!/bin/bash # .git/hooks/pre-commit # Check if CKB is installed if ! command -v ckb &> /dev/null; then exit 0 fi RESULT=$(ckb impact diff --staged --format=json 2>/dev/null || echo '{}') RISK=$(echo "$RESULT" | jq -r '.summary.estimatedRisk // "unknown"') if [ "$RISK" = "critical" ]; then echo "" echo "⛔ CRITICAL RISK DETECTED" echo " Review the impact before committing:" echo " $ ckb impact diff --staged" echo "" echo " To bypass: git commit --no-verify" exit 1 elif [ "$RISK" = "high" ]; then echo "⚠️ HIGH RISK CHANGE - consider running full test suite" fi exit 0 ``` Make executable: `chmod +x .git/hooks/pre-commit` ### Ready-to-Use Templates | Template | Description | |----------|-------------| | [`examples/github-actions/impact-comment.yml`](examples/github-actions/impact-comment.yml) | Simple PR comment widget | | [`examples/github-actions/impact-analysis.yml`](examples/github-actions/impact-analysis.yml) | Full workflow with risk gates | | [`examples/gitlab-ci/ckb.yml`](examples/gitlab-ci/ckb.yml) | GitLab CI template | | [`examples/hooks/pre-commit`](examples/hooks/pre-commit) | Git pre-commit hook | | [`examples/hooks/husky/`](examples/hooks/husky/) | Husky integration for JS/TS | See [[CI-CD-Integration]] for more CI templates and [[examples/README]] for installation instructions. --- ## Best Practices ### When to Use Each Tool | Scenario | Tool | Flags | |----------|------|-------| | "What breaks if I change this function?" | `ckb impact ` | `--depth=2` | | "Is this refactor safe?" | `ckb impact diff` | `--staged` | | "Should I merge this PR?" | `ckb impact diff` | `--base=main` | | "What tests should I run?" | `ckb affected-tests` | `--strategy=safe` | | "Who needs to review this?" | `ckb reviewers` | `--include-affected` | ### Keeping Coverage Fresh Coverage data can become stale as tests change. Regenerate periodically: ```bash # In CI: regenerate before impact analysis - name: Generate Coverage run: go test -coverprofile=coverage.out ./... - name: Analyze Impact run: ckb affected-tests --strategy=safe ``` CKB warns when coverage is older than `max_age` (default: 7 days). ### Handling Large Diffs For changes with >20 symbols changed: 1. **Break into smaller PRs**: Use the `split` recommendation 2. **Use shallow depth**: `--depth=1` for faster analysis 3. **Focus on high confidence**: Filter by `confidence >= 0.7` 4. **Check staleness**: Ensure index is fresh with `--strict` ### Interpreting Low Confidence Low confidence (< 0.7) means: - The changed file isn't in the SCIP index - The language isn't fully supported - The index is stale **Actions:** 1. Regenerate index: `ckb index` 2. Check language support: `ckb doctor --tier=standard` 3. For unsupported languages, use file-level analysis --- ## Limitations 1. **Go has best support**: Full SCIP with incremental indexing 2. **Static analysis only**: Can't detect runtime-only dependencies (use telemetry) 3. **New files**: Added files not in the index get low-confidence entries 4. **Deleted symbols**: Deletion detection limited to what was indexed 5. **Dynamic dispatch**: Interface implementations may be missed 6. **Single-repo only**: Cross-repo impact requires federation (planned for future) 7. **Local coverage files**: CKB uses local coverage files, not Codecov/Coveralls APIs For dynamic dispatch and reflection, use `--depth=3` or enable telemetry for observed callers. ### Why Local Coverage, Not Codecov API? CKB uses local coverage files (`coverage.out`, `lcov.info`) rather than cloud coverage APIs because: 1. **No API tokens required** — Works immediately without setup 2. **Precise line-level mapping** — Local files contain exact line coverage 3. **Offline capable** — No network dependency for test mapping 4. **Codecov's "Impact Analysis" is different** — Codecov's feature uses OpenTelemetry production telemetry, not test coverage Generate coverage locally in your CI pipeline before running CKB impact analysis. --- ## Example Prompts > "What will break if I rename `UserService`?" > "Analyze the risk of my current changes" > "Is it safe to refactor `LegacyHandler`?" > "Show me the blast radius of changing `ProcessPayment`" > "What tests should I run for my changes?" > "Who should review this PR?" > "Give me the affected tests as a runnable command" --- ## Related Pages - [[MCP-Tools#analyzeImpact]] - MCP tool reference - [[MCP-Tools#analyzeChange]] - MCP tool reference - [[CI-CD-Integration]] - Full CI/CD workflows - [[Telemetry]] - Runtime observability setup - [[Language-Support]] - SCIP indexer compatibility - [[Features#impact-analysis--safety]] - Feature overview