impact-analyzer

Impact Analyzer Skill v1.0

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "impact-analyzer" with this command: npx skills add monicajeon28/gmcruise/monicajeon28-gmcruise-impact-analyzer

Impact Analyzer Skill v1.0

변경 영향도 분석기 - 코드 수정 전 영향 범위를 정확히 파악하여 안전한 변경 보장

핵심 컨셉

Problem: Without_Analysis: "함수 수정 → 예상치 못한 곳에서 에러 → 롤백" Reality: "한 줄 변경이 100개 파일에 영향을 줄 수 있음"

Solution: Impact_Analysis: - "변경 대상의 역의존성 트리 추적" - "직접/간접 영향 범위 계산" - "위험도 점수 산출" - "테스트 범위 자동 제안"

Key_Metrics: Direct_Impact: "직접 호출하는 함수들" Indirect_Impact: "연쇄적으로 영향받는 범위" Risk_Score: "변경 위험도 (0-100)" Test_Coverage: "영향 범위 대비 테스트 커버리지"

자동 발동 조건

Auto_Trigger_Conditions: Before_Edit: - "Edit 도구 사용 전 자동 분석 제안" - "공유 코드(shared, utils) 수정 시" - "핵심 모듈(auth, api) 수정 시"

Keywords_KO: - "영향도 분석, 영향 범위" - "이거 바꾸면 어디 영향?" - "변경 영향, 수정 영향" - "리팩토링 영향, 리팩토링 범위" - "위험도, 얼마나 위험" - "테스트 범위, 테스트해야 할 곳"

Keywords_EN: - "impact analysis, impact scope" - "what will this affect" - "change impact, modification impact" - "refactoring scope, refactoring impact" - "risk assessment, risk score" - "test scope, what to test"

High_Risk_Patterns: - "export 변경/삭제" - "함수 시그니처 변경" - "타입 정의 변경" - "API 엔드포인트 변경" - "shared 모듈 변경"

영향도 분석 알고리즘

interface ImpactAnalysisRequest { target: string; // 변경 대상 노드 ID changeType: ChangeType; // 변경 유형 depth?: number; // 분석 깊이 (기본 3) }

type ChangeType = | 'signature' // 시그니처 변경 (파라미터, 반환타입) | 'implementation' // 구현 변경 (로직) | 'rename' // 이름 변경 | 'delete' // 삭제 | 'move' // 이동 | 'type' // 타입 변경 ;

interface ImpactResult { target: GraphNode; // 변경 대상 changeType: ChangeType; directImpact: ImpactNode[]; // 직접 영향 indirectImpact: ImpactNode[]; // 간접 영향 totalAffected: number; // 총 영향받는 노드 수 riskScore: number; // 위험도 (0-100) riskLevel: 'low' | 'medium' | 'high' | 'critical'; testSuggestions: TestSuggestion[]; // 테스트 제안 warnings: string[]; // 경고 메시지 }

interface ImpactNode { node: GraphNode; depth: number; // 영향 깊이 (1=직접, 2+=간접) impactType: 'caller' | 'type-user' | 'importer' | 'extender'; confidence: number; // 영향 확실성 (0-1) reason: string; // 영향 이유 }

영향 범위 계산

class ImpactAnalyzer { private graph: CodebaseGraph;

constructor(graph: CodebaseGraph) { this.graph = graph; }

/**

  • 영향도 분석 실행 */ analyze(request: ImpactAnalysisRequest): ImpactResult { const target = this.graph.findNode(request.target); if (!target) { throw new Error(Node not found: ${request.target}); }
// 1. 직접 영향 수집
const directImpact = this.collectDirectImpact(target, request.changeType);

// 2. 간접 영향 수집 (재귀)
const indirectImpact = this.collectIndirectImpact(
  directImpact,
  request.depth || 3
);

// 3. 위험도 계산
const riskScore = this.calculateRiskScore(target, directImpact, indirectImpact, request.changeType);

// 4. 테스트 제안 생성
const testSuggestions = this.generateTestSuggestions(target, directImpact, indirectImpact);

// 5. 경고 생성
const warnings = this.generateWarnings(target, directImpact, request.changeType);

return {
  target,
  changeType: request.changeType,
  directImpact,
  indirectImpact,
  totalAffected: directImpact.length + indirectImpact.length,
  riskScore,
  riskLevel: this.getRiskLevel(riskScore),
  testSuggestions,
  warnings,
};

}

/**

  • 직접 영향 수집 */ private collectDirectImpact(target: GraphNode, changeType: ChangeType): ImpactNode[] { const impacts: ImpactNode[] = [];
// 1. 이 노드를 호출하는 함수들
const callers = this.graph.getIncomingEdges(target.id, 'calls');
for (const edge of callers) {
  const caller = this.graph.findNode(edge.source);
  if (caller) {
    impacts.push({
      node: caller,
      depth: 1,
      impactType: 'caller',
      confidence: changeType === 'signature' ? 1.0 : 0.7,
      reason: `Calls ${target.name}`,
    });
  }
}

// 2. 이 타입을 사용하는 곳
if (target.type === 'type' || target.type === 'class') {
  const typeUsers = this.graph.getIncomingEdges(target.id, 'uses');
  for (const edge of typeUsers) {
    const user = this.graph.findNode(edge.source);
    if (user) {
      impacts.push({
        node: user,
        depth: 1,
        impactType: 'type-user',
        confidence: changeType === 'type' ? 1.0 : 0.5,
        reason: `Uses type ${target.name}`,
      });
    }
  }
}

// 3. 이 모듈을 import하는 파일들
const importers = this.graph.getIncomingEdges(target.id, 'imports');
for (const edge of importers) {
  const importer = this.graph.findNode(edge.source);
  if (importer && !impacts.some(i => i.node.id === importer.id)) {
    impacts.push({
      node: importer,
      depth: 1,
      impactType: 'importer',
      confidence: changeType === 'rename' || changeType === 'delete' ? 1.0 : 0.3,
      reason: `Imports from ${target.path}`,
    });
  }
}

// 4. 이 클래스를 상속하는 클래스들
if (target.type === 'class') {
  const extenders = this.graph.getIncomingEdges(target.id, 'extends');
  for (const edge of extenders) {
    const extender = this.graph.findNode(edge.source);
    if (extender) {
      impacts.push({
        node: extender,
        depth: 1,
        impactType: 'extender',
        confidence: 1.0,
        reason: `Extends ${target.name}`,
      });
    }
  }
}

return impacts;

}

/**

  • 간접 영향 수집 (BFS) */ private collectIndirectImpact(directImpact: ImpactNode[], maxDepth: number): ImpactNode[] { const indirect: ImpactNode[] = []; const visited = new Set<string>(directImpact.map(i => i.node.id)); const queue: ImpactNode[] = [...directImpact];
while (queue.length > 0) {
  const current = queue.shift()!;

  if (current.depth >= maxDepth) continue;

  // 현재 노드의 호출자들 수집
  const callers = this.graph.getIncomingEdges(current.node.id, 'calls');

  for (const edge of callers) {
    if (visited.has(edge.source)) continue;

    const caller = this.graph.findNode(edge.source);
    if (!caller) continue;

    visited.add(caller.id);

    const impactNode: ImpactNode = {
      node: caller,
      depth: current.depth + 1,
      impactType: 'caller',
      confidence: current.confidence * 0.7, // 깊이에 따라 감소
      reason: `Indirect via ${current.node.name}`,
    };

    indirect.push(impactNode);
    queue.push(impactNode);
  }
}

return indirect;

}

/**

  • 위험도 점수 계산 */ private calculateRiskScore( target: GraphNode, direct: ImpactNode[], indirect: ImpactNode[], changeType: ChangeType ): number { let score = 0;
// 1. 변경 유형 기본 점수
const changeTypeScores: Record&#x3C;ChangeType, number> = {
  implementation: 20,
  signature: 50,
  type: 60,
  rename: 40,
  move: 45,
  delete: 80,
};
score += changeTypeScores[changeType];

// 2. 직접 영향 수 (각 +3점, 최대 30점)
score += Math.min(direct.length * 3, 30);

// 3. 간접 영향 수 (각 +1점, 최대 20점)
score += Math.min(indirect.length, 20);

// 4. 대상 특성 보정
if (target.isExported) score += 10;           // export된 것
if (target.path.includes('shared')) score += 15; // shared 모듈
if (target.path.includes('api')) score += 10;    // API 관련
if (target.path.includes('auth')) score += 15;   // 인증 관련
if (target.type === 'type') score += 10;         // 타입 정의

// 5. 테스트 커버리지 보정
const hasTests = this.hasTestCoverage(target);
if (!hasTests) score += 10; // 테스트 없으면 위험

return Math.min(score, 100);

}

/**

  • 위험 수준 결정 */ private getRiskLevel(score: number): 'low' | 'medium' | 'high' | 'critical' { if (score < 30) return 'low'; if (score < 50) return 'medium'; if (score < 75) return 'high'; return 'critical'; }

/**

  • 테스트 제안 생성 */ private generateTestSuggestions( target: GraphNode, direct: ImpactNode[], indirect: ImpactNode[] ): TestSuggestion[] { const suggestions: TestSuggestion[] = [];
// 1. 대상 테스트
suggestions.push({
  target: target.id,
  priority: 'critical',
  reason: 'Direct change target',
  testType: 'unit',
});

// 2. 직접 영향 테스트
for (const impact of direct.slice(0, 10)) { // 상위 10개
  suggestions.push({
    target: impact.node.id,
    priority: impact.confidence > 0.8 ? 'high' : 'medium',
    reason: impact.reason,
    testType: impact.impactType === 'caller' ? 'integration' : 'unit',
  });
}

// 3. 고확신 간접 영향 테스트
const highConfidenceIndirect = indirect.filter(i => i.confidence > 0.5);
for (const impact of highConfidenceIndirect.slice(0, 5)) {
  suggestions.push({
    target: impact.node.id,
    priority: 'low',
    reason: `${impact.reason} (indirect)`,
    testType: 'integration',
  });
}

return suggestions;

}

/**

  • 경고 생성 */ private generateWarnings( target: GraphNode, direct: ImpactNode[], changeType: ChangeType ): string[] { const warnings: string[] = [];
// 1. 높은 영향 범위
if (direct.length > 20) {
  warnings.push(`HIGH IMPACT: This change affects ${direct.length} direct callers`);
}

// 2. export 삭제/변경
if (target.isExported &#x26;&#x26; (changeType === 'delete' || changeType === 'rename')) {
  warnings.push(`BREAKING: Modifying exported symbol may break external consumers`);
}

// 3. 핵심 모듈 변경
if (target.path.includes('shared') || target.path.includes('core')) {
  warnings.push(`CORE MODULE: Changes to shared/core modules require extra caution`);
}

// 4. 테스트 부족
if (!this.hasTestCoverage(target)) {
  warnings.push(`NO TESTS: Target has no test coverage - add tests before changing`);
}

// 5. 순환 참조 관련
const cycles = this.graph.detectCircularDependencies();
if (cycles.some(c => c.includes(target.id))) {
  warnings.push(`CIRCULAR: Target is part of circular dependency - changes may cascade unpredictably`);
}

return warnings;

}

private hasTestCoverage(node: GraphNode): boolean { // 테스트 파일 존재 확인 const testPatterns = [ node.path.replace('.ts', '.test.ts'), node.path.replace('.ts', '.spec.ts'), node.path.replace('/src/', '/test/'), ];

return testPatterns.some(pattern =>
  this.graph.findNode(pattern) !== null
);

} }

위험도 점수 기준

Risk_Scoring: Base_Scores_by_Change_Type: implementation: 20 # 로직만 변경 signature: 50 # 시그니처 변경 type: 60 # 타입 정의 변경 rename: 40 # 이름 변경 move: 45 # 위치 이동 delete: 80 # 삭제

Modifiers: direct_impact: "+3 per caller (max 30)" indirect_impact: "+1 per node (max 20)" is_exported: "+10" in_shared: "+15" in_api: "+10" in_auth: "+15" is_type: "+10" no_tests: "+10"

Risk_Levels: low: "0-29 (안전한 변경)" medium: "30-49 (주의 필요)" high: "50-74 (신중한 검토 필요)" critical: "75-100 (위험, 충분한 테스트 필수)"

출력 템플릿

Impact Analysis Report

Target: {{targetName}}

  • Path: {{targetPath}}:{{targetLine}}
  • Type: {{targetType}}
  • Change Type: {{changeType}}

Risk Assessment

MetricValue
Risk Score{{riskScore}}/100
Risk Level{{riskLevel}}
Direct Impact{{directCount}} nodes
Indirect Impact{{indirectCount}} nodes
Total Affected{{totalAffected}} nodes

Direct Impact ({{directCount}} nodes)

NodeTypeReasonConfidence
{{#each directImpact}}
{{node.name}}{{impactType}}{{reason}}{{confidence}}%
{{/each}}

Indirect Impact (Top 10 of {{indirectCount}})

NodeDepthReasonConfidence
{{#each indirectImpact}}
{{node.name}}{{depth}}{{reason}}{{confidence}}%
{{/each}}

Warnings

{{#each warnings}}

  • {{this}} {{/each}}

Recommended Tests

TargetPriorityTypeReason
{{#each testSuggestions}}
{{target}}{{priority}}{{testType}}{{reason}}
{{/each}}

Verdict

{{#if riskLevel === 'critical'}} CRITICAL: Do NOT proceed without comprehensive test coverage and review. {{else if riskLevel === 'high'}} HIGH RISK: Proceed with caution. Ensure all suggested tests pass. {{else if riskLevel === 'medium'}} MEDIUM RISK: Safe to proceed with standard review process. {{else}} LOW RISK: Safe to proceed. Minor change with limited impact. {{/if}}

Quick Commands

Command Action

impact <target>

기본 영향도 분석

impact signature <target>

시그니처 변경 영향도

impact delete <target>

삭제 영향도

impact rename <target>

이름 변경 영향도

impact depth <n> <target>

깊이 지정 분석

impact test <target>

테스트 제안만

impact warnings <target>

경고만

다른 스킬과의 통합

Integration: codebase-graph: type: "데이터 소스" usage: "그래프 쿼리, 역의존성 추적"

smart-context: type: "협력" usage: "영향 범위 컨텍스트 생성"

code-reviewer: type: "소비자" usage: "리뷰 시 영향도 표시"

tdd-guardian: type: "소비자" usage: "테스트 범위 제안 수신"

vibe-coding-orchestrator: type: "제공자" usage: "대규모 리팩토링 전 자동 분석"

문서 구조

impact-analyzer/ ├── SKILL.md # 이 파일 (메인) ├── core/ │ ├── impact-calculation.md # 영향도 계산 상세 │ ├── risk-scoring.md # 위험도 점수 체계 │ └── test-suggestion.md # 테스트 제안 알고리즘 ├── algorithms/ │ ├── reverse-dependency.md # 역의존성 추적 │ ├── propagation.md # 영향 전파 알고리즘 │ └── confidence.md # 확신도 계산 ├── templates/ │ ├── report-template.md # 리포트 템플릿 │ └── warning-templates.md # 경고 메시지 템플릿 └── quick-reference/ ├── commands.md # 명령어 가이드 └── risk-guide.md # 위험도 해석 가이드

Version: 1.0.0 Quality Target: 95% Required Skill: codebase-graph Related Skills: smart-context, code-reviewer, tdd-guardian

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

hwp-text-replacer

No summary provided by upstream source.

Repository SourceNeeds Review
General

supabase-connect

No summary provided by upstream source.

Repository SourceNeeds Review
General

idea-factory-orchestrator

No summary provided by upstream source.

Repository SourceNeeds Review
General

ai-model-reference

No summary provided by upstream source.

Repository SourceNeeds Review