# Harness Impact Analysis

> Graph-based impact analysis. Answers: "if I change X, what breaks?"

## When to Use

- Before merging a PR — understand the blast radius of changes
- When planning a refactoring — know what will be affected
- When a test fails — trace backwards to find what change caused it
- When `on_pr` triggers fire
- NOT for understanding code (use harness-onboarding or harness-code-review)
- NOT for finding dead code (use cleanup-dead-code)

## Prerequisites

A knowledge graph at `.harness/graph/` enables full analysis. If no graph exists,
the skill uses static analysis fallbacks (see Graph Availability section).
Run `harness scan` to enable graph-enhanced analysis.

### Graph Availability

Before starting, check if `.harness/graph/graph.json` exists.

**If graph exists:** Check staleness — compare `.harness/graph/metadata.json`
scanTimestamp against `git log -1 --format=%ct` (latest commit timestamp).
If graph is more than 2 commits behind (`git log --oneline <scanTimestamp>..HEAD | wc -l`),
run `harness scan` to refresh before proceeding. (Staleness sensitivity: **High**)

**If graph exists and is fresh (or refreshed):** Use graph tools as primary strategy.

**If no graph exists:** Output "Running without graph (run `harness scan` to
enable full analysis)" and use fallback strategies for all subsequent steps.

## Process

### Phase 1: IDENTIFY — Determine Changed Files

1. **From diff**: If a git diff is available, parse it to extract changed file paths.
2. **From input**: If file paths are provided directly, use those.
3. **From git**: If neither, use `git diff --name-only HEAD~1` to get recent changes.

### Phase 2: ANALYZE — Query Graph for Impact

Run `compute_blast_radius` on target files to simulate failure propagation and identify all downstream modules affected. Run `predict_failures` to forecast which architectural constraints are most at risk from the proposed changes.

For each changed file:

1. **Direct dependents**: Use `get_impact` MCP tool to find all files that import or call the changed file.

   ```
   get_impact(filePath="src/services/auth.ts")
   → tests: [auth.test.ts, integration.test.ts]
   → docs: [auth-guide.md]
   → code: [routes/login.ts, middleware/verify.ts, ...]
   ```

2. **Transitive dependents**: Use `query_graph` with depth 3 to find indirect consumers.

   ```
   query_graph(rootNodeIds=["file:src/services/auth.ts"], maxDepth=3, includeEdges=["imports", "calls"])
   ```

3. **Documentation impact**: Use `get_relationships` to find `documents` edges pointing to changed nodes.

4. **Test coverage**: Identify test files connected via `imports` edges. Flag changed files with no test coverage.

5. **Design token impact**: When the graph contains `DesignToken` nodes, use `query_graph` with `USES_TOKEN` edges to find components that consume changed tokens.

   ```
   query_graph(rootNodeIds=["designtoken:color.primary"], maxDepth=2, includeEdges=["uses_token"])
   → components: [Button.tsx, Card.tsx, Header.tsx, ...]
   ```

   If a changed file is `design-system/tokens.json`, identify ALL tokens that changed and trace each to its consuming components. This reveals the full design blast radius of a token change.

6. **Design constraint impact**: When the graph contains `DesignConstraint` nodes, check if changed code introduces new `VIOLATES_DESIGN` edges.

#### Fallback (without graph)

When no graph is available, use static analysis to approximate impact:

1. **Parse imports**: For each changed file, grep all source files for `import.*from.*<changed-file>` and `require.*<changed-file>` patterns to find direct dependents.
2. **Follow imports 2 levels deep**: For each direct dependent found, repeat the import grep to find second-level dependents. Stop at 2 levels (fallback cannot reliably trace deeper).
3. **Find test files by naming convention**: For each changed file `foo.ts`, search for:
   - `foo.test.ts`, `foo.spec.ts` (same directory and `__tests__/` directory)
   - `*.test.*` and `*.spec.*` files that import the changed file (from step 1)
4. **Find docs by path matching**: Grep `docs/` directory for references to the changed module name (filename without extension).
5. **Group results** the same as the graph version: tests, docs, code, other. Note the count of files found.

> Fallback completeness: ~70% — misses transitive deps beyond 2 levels.

### Phase 3: ASSESS — Risk Assessment and Report

1. **Impact score**: Calculate based on:
   - Number of direct dependents (weight: 3x)
   - Number of transitive dependents (weight: 1x)
   - Whether affected code includes entry points (weight: 5x)
   - Whether tests exist for the changed code (no tests = higher risk)
   - Whether design tokens are affected (weight: 2x — token changes cascade to all consumers)

2. **Risk tiers**:
   - **Critical** (score > 50): Changes affect entry points or >20 downstream files
   - **High** (score 20-50): Changes affect multiple modules or shared utilities
   - **Medium** (score 5-20): Changes affect a few files within the same module
   - **Low** (score < 5): Changes are isolated with minimal downstream impact

3. **Output report**:

   ```
   ## Impact Analysis Report

   ### Changed Files
   - src/services/auth.ts (modified)
   - src/types/user.ts (modified)

   ### Impact Summary
   - Direct dependents: 8 files
   - Transitive dependents: 23 files
   - Affected tests: 5 files
   - Affected docs: 2 files
   - Risk tier: HIGH

   ### Affected Tests (must run)
   1. tests/services/auth.test.ts (direct)
   2. tests/routes/login.test.ts (transitive)
   3. tests/integration/auth-flow.test.ts (transitive)

   ### Affected Documentation (may need update)
   1. docs/auth-guide.md → documents src/services/auth.ts
   2. docs/api-reference.md → documents src/types/user.ts

   ### Downstream Consumers
   1. src/routes/login.ts — imports auth.ts
   2. src/middleware/verify.ts — imports auth.ts
   3. src/routes/signup.ts — imports user.ts (transitive via auth.ts)

   ### Affected Design Tokens (when tokens change)
   1. color.primary → used by 12 components
   2. typography.body → used by 8 components
   ```

## Harness Integration

- **`harness scan`** — Recommended before this skill for full graph-enhanced analysis. If graph is missing, skill uses static analysis fallbacks.
- **`harness validate`** — Run after acting on findings to verify project health.
- **Graph tools** — This skill uses `query_graph`, `get_impact`, and `get_relationships` MCP tools.

## Success Criteria

- Impact report generated with a risk tier (Critical / High / Medium / Low)
- All affected test files listed with direct vs transitive classification
- All affected documentation files listed with relationship context
- Report follows the structured output format
- All findings are backed by graph query evidence (with graph) or systematic static analysis (without graph)

## Rationalizations to Reject

These are common rationalizations that sound reasonable but lead to incorrect results. When you catch yourself thinking any of these, stop and follow the documented process instead.

| Rationalization                                                                                    | Why It Is Wrong                                                                                                                          |
| -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| "The change is small so the blast radius must be low -- I can skip the transitive dependent check" | Small changes to shared utilities can have outsized blast radius. A one-line change to auth.ts can affect 23 transitive dependents.      |
| "The graph is a few commits behind but it is close enough for this analysis"                       | If the graph is more than 2 commits behind, the skill requires a refresh before proceeding. Recent commits may have added new consumers. |
| "No graph exists so I cannot produce a useful impact analysis"                                     | The fallback strategy using import parsing and naming conventions achieves ~70% completeness. Missing the graph does not mean stopping.  |

## Examples

### Example: Analyzing a Change to auth.ts

```
Input: git diff shows src/services/auth.ts modified

1. IDENTIFY — Extract changed file: src/services/auth.ts
2. ANALYZE  — get_impact(filePath="src/services/auth.ts")
              query_graph(rootNodeIds=["file:src/services/auth.ts"], maxDepth=3)
              Results: 8 direct dependents, 23 transitive, 5 tests, 2 docs
3. ASSESS   — Impact score: 34 (High tier)
              - Entry points affected: no
              - Tests exist: yes (5 files)

Output:
  Risk tier: HIGH
  Must-run tests: auth.test.ts, login.test.ts, auth-flow.test.ts
  Docs to update: auth-guide.md, api-reference.md
  Downstream consumers: 8 files across 3 modules
```

## Gates

- **Graph preferred, fallback available.** If no graph exists, use fallback strategies (import parsing, naming conventions, path matching). Do not stop — produce the best analysis possible with available tools.
- **No risk assessment without data.** Use graph queries when available; use import parsing and naming conventions when not. If neither approach yields data, state what is missing.

## Escalation

- **When graph is stale**: If the graph's last scan timestamp is older than the most recent commit, warn that results may be incomplete and suggest re-scanning.
- **When impact is critical**: If risk tier is Critical, recommend a thorough code review and full test suite run before merging.
