Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Analyze schedule delays, identify causes, and calculate time impacts using delay analysis methods.
.claude/skills/datadrivenconstruction-schedule-delay-analyzer/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-19 | ✗→✓ | ▲ Improved | 205% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 45% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 57% | 0% |
| case-03 | ✗→✓ | ▲ Improved | 79% | 0% |
| case-20 | ✗→✓ | ▲ Improved | 21% | 0% |
pythonimport pandas as pd from datetime import date, timedelta from typing import Dict, Any, List, Optional from dataclasses import dataclass, field from enum import Enum class DelayType(Enum): EXCUSABLE_COMPENSABLE = "excusable_compensable" EXCUSABLE_NON_COMPENSABLE = "excusable_non_compensable" NON_EXCUSABLE = "non_excusable" CONCURRENT = "concurrent" class DelayCause(Enum): OWNER_CHANGE = "owner_change" DESIGN_ERROR = "design_error" WEATHER = "weather" DIFFERING_CONDITIONS = "differing_conditions" CONTRACTOR_ISSUE = "contractor_issue" MATERIAL_DELAY = "material_delay" LABOR_SHORTAGE = "labor_shortage" PERMIT_DELAY = "permit_delay" OTHER = "other" @dataclass class DelayEvent: delay_id: str activity_id: str activity_name: str delay_type: DelayType cause: DelayCause start_date: date end_date: date delay_days: int on_critical_path: bool description: str documentation: List[str] = field(default_factory=list) cost_impact: float = 0.0 @dataclass class ScheduleBaseline: baseline_date: date planned_completion: date activities: Dict[str, Dict[str, date]] # activity_id: {start, end} class ScheduleDelayAnalyzer: def __init__(self, project_name: str, contract_completion: date): self.project_name = project_name self.contract_completion = contract_completion self.baselines: List[ScheduleBaseline] = [] self.delays: Dict[str, DelayEvent] = {} self._counter = 0 def add_baseline(self, baseline_date: date, planned_completion: date, activities: Dict[str, Dict[str, date]]): baseline = ScheduleBaseline(baseline_date, planned_completion, activities) self.baselines.append(baseline) def record_delay(self, activity_id: str, activity_name: str, delay_type: DelayType, cause: DelayCause, start_date: date, end_date: date, on_critical_path: bool, description: str, cost_impact: float = 0) -> DelayEvent: self._counter += 1 delay_id = f"DLY-{self._counter:04d}" delay = DelayEvent( delay_id=delay_id, activity_id=activity_id, activity_name=activity_name, delay_type=delay_type, cause=cause, start_date=start_date, end_date=end_date, delay_days=(end_date - start_date).days, on_critical_path=on_critical_path, description=description, cost_impact=cost_impact ) self.delays[delay_id] = delay return delay def calculate_project_delay(self) -> int: """Calculate total critical path delay.""" critical_delays = [d for d in self.delays.values() if d.on_critical_path] return sum(d.delay_days for d in critical_delays) def analyze_by_type(self) -> Dict[str, Dict[str, Any]]: analysis = {} for delay in self.delays.values(): dtype = delay.delay_type.value if dtype not in analysis: analysis[dtype] = {'count': 0, 'days': 0, 'cost': 0} analysis[dtype]['count'] += 1 analysis[dtype]['days'] += delay.delay_days analysis[dtype]['cost'] += delay.cost_impact return analysis def analyze_by_cause(self) -> Dict[str, int]: by_cause = {} for delay in self.delays.values(): cause = delay.cause.value by_cause[cause] = by_cause.get(cause, 0) + delay.delay_days return by_cause def calculate_time_extension_claim(self) -> Dict[str, Any]: """Calculate basis for time extension claim.""" excusable = [d for d in self.delays.values() if d.delay_type in [DelayType.EXCUSABLE_COMPENSABLE, DelayType.EXCUSABLE_NON_COMPENSABLE] and d.on_critical_path] compensable = [d for d in excusable if d.delay_type == DelayType.EXCUSABLE_COMPENSABLE] return { 'excusable_delays': len(excusable), 'excusable_days': sum(d.delay_days for d in excusable), 'compensable_delays': len(compensable), 'compensable_days': sum(d.delay_days for d in compensable), 'total_cost_impact': sum(d.cost_impact for d in compensable), 'recommended_extension': sum(d.delay_days for d in excusable) } def get_summary(self) -> Dict[str, Any]: critical_delay = self.calculate_project_delay() projected_completion = self.contract_completion + timedelta(days=critical_delay) return { 'project': self.project_name, 'contract_completion': self.contract_completion, 'projected_completion': projected_completion, 'total_delays': len(self.delays), 'critical_path_delays': sum(1 for d in self.delays.values() if d.on_critical_path), 'total_delay_days': critical_delay, 'by_type': self.analyze_by_type(), 'by_cause': self.analyze_by_cause() } def export_analysis(self, output_path: str): data = [{ 'ID': d.delay_id, 'Activity': d.activity_name, 'Type': d.delay_type.value, 'Cause': d.cause.value, 'Start': d.start_date, 'End': d.end_date, 'Days': d.delay_days, 'Critical': d.on_critical_path, 'Cost Impact': d.cost_impact, 'Description': d.description } for d in self.delays.values()] pd.DataFrame(data).to_excel(output_path, index=False)
pythonanalyzer = ScheduleDelayAnalyzer("Office Tower", date(2024, 12, 31)) delay = analyzer.record_delay( activity_id="A-300", activity_name="Foundation Work", delay_type=DelayType.EXCUSABLE_COMPENSABLE, cause=DelayCause.OWNER_CHANGE, start_date=date(2024, 3, 1), end_date=date(2024, 3, 15), on_critical_path=True, description="Owner requested additional scope", cost_impact=50000 ) summary = analyzer.get_summary() print(f"Project delayed by {summary['total_delay_days']} days") claim = analyzer.calculate_time_extension_claim() print(f"Recommended extension: {claim['recommended_extension']} days")
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-19 | fail→pass | 4,497 | 2,803 | -38% | 1 | 1 | 0% | 769 | 2,346 | +205% | 0 | 0 | — |
case-01 | fail→pass | 17,914 | 15,336 | -14% | 1 | 1 | 0% | 3,328 | 4,822 | +45% | 0 | 0 | — |
case-02 | fail→pass | 14,917 | 10,653 | -29% | 1 | 1 | 0% | 2,758 | 4,320 | +57% | 0 | 0 | — |
case-03 | fail→pass | 13,834 | 14,351 | +4% | 1 | 1 | 0% | 2,882 | 5,146 | +79% | 0 | 0 | — |
case-04 | pass→pass | 6,416 | 4,563 | -29% | 1 | 1 | 0% | 1,445 | 2,885 | +100% | 0 | 0 | — |
case-05 | pass→pass | 13,321 | 11,714 | -12% | 1 | 1 | 0% | 3,279 | 4,627 | +41% | 0 | 0 | — |
case-06 | pass→pass | 18,179 | 22,156 | +22% | 1 | 1 | 0% | 3,700 | 6,401 | +73% | 0 | 0 | — |
case-07 | pass→pass | 4,327 | 5,008 | +16% | 1 | 1 | 0% | 839 | 2,822 | +236% | 0 | 0 | — |
case-08 | pass→pass | 7,751 | 4,030 | -48% | 1 | 1 | 0% | 1,466 | 2,715 | +85% | 0 | 0 | — |
case-09 | pass→pass | 12,534 | 9,960 | -21% | 1 | 1 | 0% | 2,181 | 4,029 | +85% | 0 | 0 | — |
case-10 | pass→pass | 3,354 | 2,432 | -27% | 1 | 1 | 0% | 649 | 2,392 | +269% | 0 | 0 | — |
case-20 | fail→pass | 10,379 | 2,377 | -77% | 1 | 1 | 0% | 1,984 | 2,391 | +21% | 0 | 0 | — |
case-11 | pass→pass | 5,208 | 4,811 | -8% | 1 | 1 | 0% | 988 | 2,660 | +169% | 0 | 0 | — |
case-12 | pass→pass | 5,516 | 5,397 | -2% | 1 | 1 | 0% | 950 | 2,839 | +199% | 0 | 0 | — |
case-13 | pass→pass | 5,198 | 3,149 | -39% | 1 | 1 | 0% | 992 | 2,471 | +149% | 0 | 0 | — |
case-14 | pass→pass | 8,792 | 4,538 | -48% | 1 | 1 | 0% | 1,365 | 2,683 | +97% | 0 | 0 | — |
case-15 | fail→pass | 7,063 | 4,138 | -41% | 1 | 1 | 0% | 1,160 | 2,563 | +121% | 0 | 0 | — |
case-16 | pass→pass | 6,402 | 3,520 | -45% | 1 | 1 | 0% | 1,015 | 2,472 | +144% | 0 | 0 | — |
case-17 | pass→pass | 6,621 | 6,112 | -8% | 1 | 1 | 0% | 1,210 | 3,124 | +158% | 0 | 0 | — |
case-18 | pass→pass | 6,154 | 4,796 | -22% | 1 | 1 | 0% | 1,202 | 2,847 | +137% | 0 | 0 | — |
case-21 | pass→pass | 2,827 | 2,982 | +5% | 1 | 1 | 0% | 479 | 2,532 | +429% | 0 | 0 | — |
case-22 | pass→pass | 2,485 | 8,314 | +235% | 1 | 1 | 0% | 398 | 2,388 | +500% | 0 | 0 | — |
case-23 | pass→pass | 4,540 | 4,976 | +10% | 1 | 1 | 0% | 776 | 2,744 | +254% | 0 | 0 | — |
case-24 | pass→pass | 6,575 | 4,538 | -31% | 1 | 1 | 0% | 1,140 | 2,749 | +141% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 24 cases were attempted. The headline lift of +25 percentage points is the difference between those two pass rates over the 24 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.