---
name: circular-dependency-resolver
description: This skill should be used when build fails with circular import warnings, user mentions "circular dependencies" or "dependency cycles", or fixing A→B→C→A import cycles. Detects and resolves circular dependencies using graph algorithms with DI, interface extraction, and shared code fix strategies.
---

# Circular Dependency Resolver

## Overview

Detect and resolve circular dependencies using graph analysis, multiple fix strategies, and automated validation. Prevents runtime and build issues caused by dependency cycles.

## When to Use This Skill

Invoke when user:
- Mentions "circular dependencies"
- Has import cycle errors
- Requests dependency analysis
- Build fails with circular import warnings

## Resolution Workflow

### Step 1: Detect Circular Dependencies

**Using Nx:**
```bash
npx nx run-many --target=lint --all 2>&1 | grep -i "circular"
```

**Using madge (if installed):**
```bash
npm install -g madge
madge --circular --extensions ts libs/
madge --circular --image circular-deps.svg libs/
```

**Using TypeScript:**
```bash
npx tsc --noEmit --strict 2>&1 | grep -i "circular\|cycle"
```

### Step 2: Analyze Each Cycle

For each cycle found:
```
📍 Circular Dependency Detected

Cycle Path:
1. libs/oms/data-access/src/lib/services/order.service.ts
   → imports OrderValidator
2. libs/oms/data-access/src/lib/validators/order.validator.ts
   → imports OrderService
3. Back to order.service.ts

Type: Service-Validator circular reference
Severity: 🔴 Critical
Files Involved: 2
```

### Step 3: Categorize by Severity

**🔴 Critical (Must Fix):**
- Service-to-service cycles
- Data-access layer cycles
- Store dependencies creating cycles

**⚠️ Warning (Should Fix):**
- Component-to-component cycles
- Model cross-references
- Utility function cycles

**ℹ️ Info (Review):**
- Type-only circular references (may be acceptable)
- Test file circular imports

### Step 4: Choose Fix Strategy

**Strategy 1: Extract to Shared Utility**
```typescript
// BEFORE (Circular)
// order.service.ts imports validator.ts
// validator.ts imports order.service.ts

// AFTER (Fixed)
// Create @isa/oms/util/types.ts
export interface OrderData { id: string; }

// order.service.ts imports types
// validator.ts imports types
// No more cycle
```

**Strategy 2: Dependency Injection (Lazy)**
```typescript
// BEFORE
import { ServiceB } from './service-b';
export class ServiceA {
  constructor(private serviceB: ServiceB) {}
}

// AFTER
import { Injector } from '@angular/core';
export class ServiceA {
  private serviceB!: ServiceB;

  constructor(private injector: Injector) {
    setTimeout(() => {
      this.serviceB = this.injector.get(ServiceB);
    });
  }
}
```

**Strategy 3: Interface Extraction**
```typescript
// BEFORE (Models with circular reference)
// order.ts ↔ customer.ts

// AFTER
// order.interface.ts - no imports
export interface IOrder { customerId: string; }

// customer.interface.ts - no imports
export interface ICustomer { orderIds: string[]; }

// order.ts imports only ICustomer
// customer.ts imports only IOrder
```

**Strategy 4: Move Shared Code**
```typescript
// BEFORE
// feature-a imports feature-b
// feature-b imports feature-a

// AFTER
// Extract to @isa/shared/[name]
// Both features import from shared
```

**Strategy 5: Forward References (Angular)**
```typescript
// Use forwardRef for components
import { forwardRef } from '@angular/core';

@Component({
  imports: [forwardRef(() => ChildComponent)]
})
```

### Step 5: Implement Fix

Apply chosen strategy:
1. Create new files if needed (util library, interfaces)
2. Update imports in both files
3. Remove circular import

### Step 6: Validate Fix

```bash
# Check cycle resolved
madge --circular --extensions ts libs/

# TypeScript compilation
npx tsc --noEmit

# Run tests
npx nx affected:test --skip-nx-cache

# Lint
npx nx affected:lint
```

### Step 7: Generate Report

```
Circular Dependency Resolution
===============================

Analysis Date: [timestamp]

📊 Summary
----------
Circular dependencies found: XX
🔴 Critical: XX
⚠️ Warning: XX
Fixed: XX

🔍 Detected Cycles
------------------

🔴 Critical Cycle #1 (FIXED)
Path: order.service → validator → order.service
Strategy Used: Extract to Util Library
Created: @isa/oms/util/order-types.ts
Files Modified: 2
Status: ✅ Resolved

⚠️ Warning Cycle #2 (FIXED)
Path: component-a → component-b → component-a
Strategy Used: Move Shared to @isa/ui
Created: @isa/ui/shared-component
Files Modified: 3
Status: ✅ Resolved

💡 Fix Strategies Applied
--------------------------
1. Extract to Util: XX cycles
2. Interface Extraction: XX cycles
3. Move Shared Code: XX cycles
4. Dependency Injection: XX cycles

✅ Validation
-------------
- madge check: ✅ No cycles
- TypeScript: ✅ Compiles
- Tests: ✅ XX/XX passing
- Lint: ✅ Passed

🎯 Prevention Tips
------------------
1. Add ESLint rule: import/no-cycle
2. Pre-commit hook for cycle detection
3. Regular architecture reviews
```

## Prevention

**ESLint Configuration:**
```json
{
  "import/no-cycle": ["error", { "maxDepth": 1 }]
}
```

**Pre-commit Hook:**
```bash
#!/bin/bash
madge --circular --extensions ts libs/
if [ $? -ne 0 ]; then
  echo "❌ Circular dependencies detected"
  exit 1
fi
```

## References

- Madge: https://github.com/pahen/madge
- Nx dependency graph: https://nx.dev/features/explore-graph
- ESLint import plugin: https://github.com/import-js/eslint-plugin-import
