Skip to main content
ClaudeWave
Skill173 estrellas del repoactualizado 3mo ago

contract-clause-analyzer

Analyze construction contract clauses. Identify risks, obligations, and key terms using NLP.

Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction /tmp/contract-clause-analyzer && cp -r /tmp/contract-clause-analyzer/1_DDC_Toolkit/Document-Control/contract-clause-analyzer ~/.claude/skills/contract-clause-analyzer
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Contract Clause Analyzer

## Business Case

### Problem Statement
Contract review is time-consuming and error-prone:
- Important clauses missed
- Risk provisions overlooked
- Inconsistent interpretation
- Long review cycles

### Solution
AI-assisted contract clause analysis that identifies key provisions, flags risks, and extracts critical terms.

## Technical Implementation

```python
import pandas as pd
from datetime import datetime, date
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from enum import Enum
import re


class ClauseType(Enum):
    SCOPE = "scope"
    PAYMENT = "payment"
    SCHEDULE = "schedule"
    CHANGE_ORDER = "change_order"
    TERMINATION = "termination"
    INDEMNIFICATION = "indemnification"
    INSURANCE = "insurance"
    WARRANTY = "warranty"
    DISPUTE = "dispute"
    LIABILITY = "liability"
    FORCE_MAJEURE = "force_majeure"
    SAFETY = "safety"
    COMPLIANCE = "compliance"
    OTHER = "other"


class RiskLevel(Enum):
    HIGH = "high"
    MEDIUM = "medium"
    LOW = "low"
    INFO = "info"


@dataclass
class ContractClause:
    clause_id: str
    section: str
    title: str
    text: str
    clause_type: ClauseType
    risk_level: RiskLevel
    key_terms: List[str] = field(default_factory=list)
    obligations: List[str] = field(default_factory=list)
    deadlines: List[str] = field(default_factory=list)
    amounts: List[str] = field(default_factory=list)
    notes: str = ""


@dataclass
class AnalysisResult:
    contract_name: str
    analyzed_date: datetime
    total_clauses: int
    clauses: List[ContractClause]
    risk_summary: Dict[str, int]
    key_dates: List[Dict[str, str]]
    key_amounts: List[Dict[str, str]]


class ContractClauseAnalyzer:
    """Analyze construction contract clauses."""

    RISK_KEYWORDS = {
        'high': ['indemnify', 'sole discretion', 'waive', 'forfeit', 'liquidated damages',
                 'consequential', 'unlimited liability', 'hold harmless', 'no limit'],
        'medium': ['shall', 'must', 'required', 'obligated', 'responsible', 'liable',
                   'penalty', 'default', 'breach'],
        'low': ['may', 'should', 'reasonable', 'mutual', 'consent', 'approval']
    }

    CLAUSE_PATTERNS = {
        ClauseType.PAYMENT: ['payment', 'invoice', 'retainage', 'progress payment'],
        ClauseType.SCHEDULE: ['schedule', 'completion date', 'milestone', 'time is of the essence'],
        ClauseType.CHANGE_ORDER: ['change order', 'modification', 'additional work', 'variation'],
        ClauseType.TERMINATION: ['termination', 'terminate', 'cancellation'],
        ClauseType.INDEMNIFICATION: ['indemnif', 'hold harmless', 'defend'],
        ClauseType.INSURANCE: ['insurance', 'coverage', 'policy', 'insured'],
        ClauseType.WARRANTY: ['warranty', 'guarantee', 'defect', 'workmanship'],
        ClauseType.DISPUTE: ['dispute', 'arbitration', 'mediation', 'litigation'],
        ClauseType.LIABILITY: ['liability', 'damages', 'limitation'],
        ClauseType.FORCE_MAJEURE: ['force majeure', 'act of god', 'unforeseen'],
    }

    def __init__(self):
        self.clauses: List[ContractClause] = []

    def analyze_text(self, contract_name: str, text: str) -> AnalysisResult:
        """Analyze contract text."""
        self.clauses = []

        # Split into sections/clauses
        sections = self._split_into_sections(text)

        for i, section in enumerate(sections):
            clause = self._analyze_clause(f"CL-{i+1:03d}", section)
            self.clauses.append(clause)

        # Generate summary
        risk_summary = {
            'high': sum(1 for c in self.clauses if c.risk_level == RiskLevel.HIGH),
            'medium': sum(1 for c in self.clauses if c.risk_level == RiskLevel.MEDIUM),
            'low': sum(1 for c in self.clauses if c.risk_level == RiskLevel.LOW)
        }

        key_dates = []
        key_amounts = []
        for clause in self.clauses:
            for d in clause.deadlines:
                key_dates.append({'clause': clause.clause_id, 'date': d})
            for a in clause.amounts:
                key_amounts.append({'clause': clause.clause_id, 'amount': a})

        return AnalysisResult(
            contract_name=contract_name,
            analyzed_date=datetime.now(),
            total_clauses=len(self.clauses),
            clauses=self.clauses,
            risk_summary=risk_summary,
            key_dates=key_dates,
            key_amounts=key_amounts
        )

    def _split_into_sections(self, text: str) -> List[Dict[str, str]]:
        """Split contract into sections."""
        sections = []
        # Simple split by numbered sections
        pattern = r'(\d+\.[\d\.]*\s+[A-Z][^\.]+)'
        parts = re.split(pattern, text)

        current_title = ""
        for i, part in enumerate(parts):
            if re.match(r'\d+\.[\d\.]*\s+[A-Z]', part):
                current_title = part.strip()
            elif part.strip() and current_title:
                sections.append({
                    'title': current_title,
                    'text': part.strip()
                })
                current_title = ""

        # If no sections found, treat whole text as one
        if not sections and text.strip():
            sections.append({'title': 'Contract Text', 'text': text.strip()})

        return sections

    def _analyze_clause(self, clause_id: str, section: Dict[str, str]) -> ContractClause:
        """Analyze single clause."""
        text = section.get('text', '')
        title = section.get('title', '')
        text_lower = text.lower()

        # Determine clause type
        clause_type = self._determine_type(text_lower)

        # Assess risk level
        risk_level = self._assess_risk(text_lower)

        # Extract key terms
        key_terms = self._extract_key_terms(text)

        # Extract obligations
        obligations = self._extract_obligations(text)

        # Extract dates
        deadlines = self._extract_dates(