Getting it into your agent
One page per mod, every tool's command on it. A separate URL per tool would split the same page into five that compete with each other.
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill delay-analysisgit clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_ConstructionWrote this? Show the measurements
A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.
[](https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/delay-analysis)<a href="https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/delay-analysis"><img src="https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/delay-analysis/github.svg" alt="Measured on agentmods" height="20"></a>Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.
<a href="https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/delay-analysis"><img src="https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/delay-analysis.svg" alt="Reviewed on agentmods" width="80" height="20"></a>- NVIDIA SkillSpector pass
What it costs to keep this loaded
Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.
| Model | Per session | Once invoked |
|---|---|---|
| Fable 5.1 | $0.00029 | $0.04175 |
| Opus 5 | $0.00015 | $0.02087 |
| Sonnet 5 | $0.00006 | $0.00835 |
| Haiku 4.5 | $0.00003 | $0.00417 |
Grade A, and why
delay-analysis scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured 7d ago.
A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.
Nothing flagged
None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.
Copies of this mod
1 near-identical copy found in the catalogue:
- delay-analysis — 100% identical, 0 lines differ
How it starts
The opening of the file, as written. The whole thing — 537 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Delay Analysis
Overview
Analyze construction schedule delays for project recovery and claims. Perform time impact analysis (TIA), identify concurrent delays, calculate delay damages, and prepare documentation for dispute resolution.
"Proper delay analysis is essential for fair resolution of construction disputes" — DDC Community
Delay Analysis Methods
┌─────────────────────────────────────────────────────────────────┐
│ DELAY ANALYSIS METHODS │
├─────────────────────────────────────────────────────────────────┤
│ │
│ As-Planned vs As-Built │ Time Impact Analysis (TIA) │
│ ───────────────────── │ ──────────────────────────── │
│ Compare original to │ Insert delay events into │
│ actual schedule │ schedule to measure impact │
│ │ │
│ Windows Analysis │ Collapsed As-Built │
│ ──────────────── │ ───────────────── │
│ Divide project into │ Remove delays from as-built │
│ time periods │ to find "but-for" completion │
│ │
└─────────────────────────────────────────────────────────────────┘
Technical Implementation
from dataclasses import dataclass, field
from typing import List, Dict, Optional, Tuple
from datetime import datetime, timedelta
from enum import Enum
from collections import defaultdict
class DelayType(Enum):
EXCUSABLE_COMPENSABLE = "excusable_compensable" # Owner caused - time + money
EXCUSABLE_NON_COMPENSABLE = "excusable_non_compensable" # Neither party - time only
NON_EXCUSABLE = "non_excusable" # Contractor caused - no relief
CONCURRENT = "concurrent" # Both parties - complex
class DelayCause(Enum):
OWNER_CHANGE = "owner_change"
LATE_INFORMATION = "late_information"
DIFFERING_CONDITIONS = "differing_conditions"
PERMIT_DELAY = "permit_delay"
WEATHER = "weather"
LABOR_SHORTAGE = "labor_shortage"
MATERIAL_DELAY = "material_delay"
SUBCONTRACTOR = "subcontractor"
COORDINATION = "coordination"
ACCESS = "access"
FORCE_MAJEURE = "force_majeure"
@dataclass
class DelayEvent:
id: str
description: str
cause: DelayCause
delay_type: DelayType
start_date: datetime
end_date: datetime
affected_activities: List[str]
responsible_party: str
documented: bool = True
supporting_docs: List[str] = field(default_factory=list)
calculated_impact: int = 0 # days
concurrent_with: List[str] = field(default_factory=list)
@dataclass
class ScheduleVersion:
version_id: str
version_type: str # baseline, update, as-built
data_date: datetime
completion_date: datetime
activities: Dict[str, Dict] # activity_id -> {start, finish, duration}
@dataclass
class WindowPeriod:
window_id: str
start_date: datetime
end_date: datetime
planned_progress: float
actual_progress: float
delay_days: int
delay_events: List[str]
responsible_parties: Dict[str, int] # party -> delay days
@dataclass
class DelayAnalysisReport:
project_name: str
analysis_date: datetime
original_completion: datetime
actual_completion: datetime
total_delay: int
excusable_delay: int
non_excusable_delay: int
concurrent_delay: int
delay_events: List[DelayEvent]
delay_by_cause: Dict[str, int]
delay_by_party: Dict[str, int]
recommended_extension: int
potential_damages: float
class DelayAnalyzer:
"""Analyze construction schedule delays."""
# Daily delay costs by project size
DEFAULT_DAILY_COSTS = {
"small": 5000, # < $10M
"medium": 15000, # $10M - $50M
"large": 40000, # $50M - $200M
"mega": 100000 # > $200M
}
def __init__(self, project_name: str, contract_completion: datetime):
self.project_name = project_name
self.contract_completion = contract_completion
self.delay_events: Dict[str, DelayEvent] = {}
self.schedule_versions: Dict[str, ScheduleVersion] = {}
self.window_periods: List[WindowPeriod] = []
self.daily_cost = self.DEFAULT_DAILY_COSTS["medium"]
def set_daily_delay_cost(self, cost: float):
"""Set daily delay cost for damages calculation."""
self.daily_cost = cost
def add_schedule_version(self, version_id: str, version_type: str,
data_date: datetime, completion_date: datetime,
activities: Dict[str, Dict]) -> ScheduleVersion:
"""Add schedule version for analysis."""
version = ScheduleVersion(
version_id=version_id,
version_type=version_type,
data_date=data_date,
completion_date=completion_date,
activities=activities
)
self.schedule_versions[version_id] = version
return version
def add_delay_event(self, id: str, description: str,
cause: DelayCause, delay_type: DelayType,
start_date: datetime, end_date: datetime,
affected_activities: List[str],
responsible_party: str,
supporting_docs: List[str] = None) -> DelayEvent:
"""Add delay event for analysis."""
event = DelayEvent(
id=id,
description=description,
cause=cause,
delay_type=delay_type,
start_date=start_date,
end_date=end_date,
affected_activities=affected_activities,
responsible_party=responsible_party,
supporting_docs=supporting_docs or []
)
self.delay_events[id] = event
return event
def perform_as_planned_vs_as_built(self) -> Dict:
"""Perform As-Planned vs As-Built analysis."""
baseline = self.schedule_versions.get("baseline")
as_built = self.schedule_versions.get("as_built")
if not baseline or not as_built:
raise ValueError("Need baseline and as-built schedules")
total_delay = (as_built.completion_date - baseline.completion_date).days
# Analyze each activity
activity_delays = []
for act_id, baseline_act in baseline.activities.items():
if act_id in as_built.activities:
as_built_act = as_built.activities[act_id]
baseline_finish = baseline_act['finish']
actual_finish = as_built_act['finish']
if isinstance(baseline_finish, str):
baseline_finish = datetime.fromisoformat(baseline_finish)
if isinstance(actual_finish, str):
actual_finish = datetime.fromisoformat(actual_finish)
delay = (actual_finish - baseline_finish).days
if delay > 0:
activity_delays.append({
'activity_id': act_id,
'planned_finish': baseline_finish,
'actual_finish': actual_finish,
'delay_days': delay
})
return {
'method': 'As-Planned vs As-Built',
'baseline_completion': baseline.completion_date,
'actual_completion': as_built.completion_date,
'total_delay': total_delay,
'activity_delays': sorted(activity_delays, key=lambda x: -x['delay_days'])
}
def perform_time_impact_analysis(self, delay_event_id: str) -> Dict:
"""Perform Time Impact Analysis for specific delay event."""
if delay_event_id not in self.delay_events:
raise ValueError(f"Delay event {delay_event_id} not found")
event = self.delay_events[delay_event_id]
# Find schedule version just before delay
pre_delay_schedule = None
for version in sorted(self.schedule_versions.values(),
key=lambda v: v.data_date, reverse=True):
if version.data_date < event.start_date:
pre_delay_schedule = version
break
if not pre_delay_schedule:
pre_delay_schedule = self.schedule_versions.get("baseline")
if not pre_delay_schedule:
raise ValueError("No pre-delay schedule found")
# Calculate impact
original_completion = pre_delay_schedule.completion_date
delay_duration = (event.end_date - event.start_date).days
# Check if delay is on critical path
critical_impact = False
for act_id in event.affected_activities:
if act_id in pre_delay_schedule.activities:
act = pre_delay_schedule.activities[act_id]
if act.get('is_critical', False):
critical_impact = True
break
if critical_impact:
impact_days = delay_duration
new_completion = original_completion + timedelta(days=delay_duration)
else:
# Need to check float
impact_days = max(0, delay_duration - 5) # Simplified - assume 5 days float
new_completion = original_completion + timedelta(days=impact_days)
event.calculated_impact = impact_days
return {
'method': 'Time Impact Analysis',
'delay_event': event.id,
'delay_description': event.description,
'delay_duration': delay_duration,
'critical_path_impact': critical_impact,
'schedule_impact_days': impact_days,
'original_completion': original_completion,
'impacted_completion': new_completion,
'delay_type': event.delay_type.value,
'responsible_party': event.responsible_party
}
def identify_concurrent_delays(self) -> List[Tuple[str, str, int]]:
"""Identify concurrent delay events."""
concurrent = []
events = list(self.delay_events.values())
for i, event1 in enumerate(events):
for event2 in events[i+1:]:
# Check for overlap
overlap_start = max(event1.start_date, event2.start_date)
overlap_end = min(event1.end_date, event2.end_date)
if overlap_start < overlap_end:
overlap_days = (overlap_end - overlap_start).days
concurrent.append((event1.id, event2.id, overlap_days))
event1.concurrent_with.append(event2.id)
event2.concurrent_with.append(event1.id)
return concurrent
def perform_windows_analysis(self, window_days: int = 30) -> List[WindowPeriod]:
"""Perform windows analysis by dividing project into periods."""
baseline = self.schedule_versions.get("baseline")
as_built = self.schedule_versions.get("as_built")
if not baseline or not as_built:
raise ValueError("Need baseline and as-built schedules")
windows = []
current_start = baseline.data_date
window_num = 1
while current_start < as_built.completion_date:
window_end = min(
current_start + timedelta(days=window_days),
as_built.completion_date
)
# Find delay events in this window
window_events = [
e.id for e in self.delay_events.values()
if e.start_date < window_end and e.end_date > current_start
]
# Calculate delay by party
party_delays = defaultdict(int)
for event_id in window_events:
event = self.delay_events[event_id]
overlap_start = max(event.start_date, current_start)
overlap_end = min(event.end_date, window_end)
days = (overlap_end - overlap_start).days
party_delays[event.responsible_party] += days
window = WindowPeriod(
window_id=f"W{window_num:02d}",
start_date=current_start,
end_date=window_end,
planned_progress=0.0, # Would calculate from schedule
actual_progress=0.0,
delay_days=sum(party_delays.values()),
delay_events=window_events,
responsible_parties=dict(party_delays)
)
windows.append(window)
current_start = window_end
window_num += 1
self.window_periods = windows
return windows
def calculate_delay_damages(self) -> Dict:
"""Calculate potential delay damages."""
# Summarize delays by type
excusable_compensable = 0
excusable_non_compensable = 0
non_excusable = 0
for event in self.delay_events.values():
impact = event.calculated_impact or (event.end_date - event.start_date).days
# Adjust for concurrency
if event.concurrent_with:
impact = impact // 2 # Simplified concurrency handling
if event.delay_type == DelayType.EXCUSABLE_COMPENSABLE:
excusable_compensable += impact
elif event.delay_type == DelayType.EXCUSABLE_NON_COMPENSABLE:
excusable_non_compensable += impact
elif event.delay_type == DelayType.NON_EXCUSABLE:
non_excusable += impact
# Calculate damages
contractor_damages = excusable_compensable * self.daily_cost
owner_ld = non_excusable * self.daily_cost
return {
'excusable_compensable_days': excusable_compensable,
'excusable_non_compensable_days': excusable_non_compensable,
'non_excusable_days': non_excusable,
'recommended_time_extension': excusable_compensable + excusable_non_compensable,
'contractor_delay_damages': contractor_damages,
'owner_liquidated_damages': owner_ld,
'daily_rate_used': self.daily_cost
}
def generate_analysis_report(self, actual_completion: datetime) -> DelayAnalysisReport:
"""Generate comprehensive delay analysis report."""
total_delay = (actual_completion - self.contract_completion).days
# Categorize delays
delay_by_cause = defaultdict(int)
delay_by_party = defaultdict(int)
excusable = 0
non_excusable = 0
concurrent = 0
for event in self.delay_events.values():
impact = event.calculated_impact or (event.end_date - event.start_date).days
delay_by_cause[event.cause.value] += impact
delay_by_party[event.responsible_party] += impact
if event.concurrent_with:
concurrent += impact // 2
elif event.delay_type in [DelayType.EXCUSABLE_COMPENSABLE,
DelayType.EXCUSABLE_NON_COMPENSABLE]:
excusable += impact
else:
non_excusable += impact
damages = self.calculate_delay_damages()
return DelayAnalysisReport(
project_name=self.project_name,
analysis_date=datetime.now(),
original_completion=self.contract_completion,
actual_completion=actual_completion,
total_delay=total_delay,
excusable_delay=excusable,
non_excusable_delay=non_excusable,
concurrent_delay=concurrent,
delay_events=list(self.delay_events.values()),
delay_by_cause=dict(delay_by_cause),
delay_by_party=dict(delay_by_party),
recommended_extension=damages['recommended_time_extension'],
potential_damages=damages['contractor_delay_damages']
)
def generate_report_markdown(self, report: DelayAnalysisReport) -> str:
"""Generate markdown report."""
lines = [
"# Delay Analysis Report",
"",
f"**Project:** {report.project_name}",
f"**Analysis Date:** {report.analysis_date.strftime('%Y-%m-%d')}",
"",
"## Schedule Summary",
"",
f"| Milestone | Date |",
f"|-----------|------|",
f"| Contract Completion | {report.original_completion.strftime('%Y-%m-%d')} |",
f"| Actual Completion | {report.actual_completion.strftime('%Y-%m-%d')} |",
f"| **Total Delay** | **{report.total_delay} days** |",
"",
"## Delay Classification",
"",
f"| Category | Days |",
f"|----------|------|",
f"| Excusable Delay | {report.excusable_delay} |",
f"| Non-Excusable Delay | {report.non_excusable_delay} |",
f"| Concurrent Delay | {report.concurrent_delay} |",
"",
"## Delay by Cause",
""
]
for cause, days in sorted(report.delay_by_cause.items(), key=lambda x: -x[1]):
lines.append(f"- **{cause}**: {days} days")
lines.extend([
"",
"## Delay by Responsible Party",
""
])
for party, days in sorted(report.delay_by_party.items(), key=lambda x: -x[1]):
lines.append(f"- **{party}**: {days} days")
lines.extend([
"",
"## Recommendations",
"",
f"- **Recommended Time Extension:** {report.recommended_extension} days",
f"- **Potential Delay Damages:** ${report.potential_damages:,.0f}",
""
])
return "\n".join(lines)
What ships with it
2 files beside SKILL.md in the same directory: the scripts, references and assets a skill reads on demand. Not counted in the per-session cost; read them before you install if any of them is executable.
What this file has done since we first saw it
Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.
- 7d ago First seen · 537 lines · 29 tokens per session scan A ea3dcdae90be
delay-analysis is a skill published in the GitHub repository datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction (308 stars, last pushed 19d ago), licensed MIT. It adds 29 tokens to every session and 4,175 once invoked, about $0.0001 per session on Opus 5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-09-03.
Other skills, from other repositories
grant-writer
Audit a grant management system for proposal workflow efficiency, deadline tracking, budget-narrative alignment, outcome reporting, compliance readiness, and win rate optimization. Use when reviewing nonprofit grant software, building a grants CRM, analyzing proposal pipelines, or evaluating funder reporting tools.
disability-services
Analyze disability services software — IEP and ISP management, person-centered planning workflows, HCBS Settings Rule compliance, accommodation tracking, assistive technology integration, EVV (Electronic Visit Verification), caregiver and DSP scheduling, and outcome measurement.
grant-management
Analyze grant management and sponsored research operations including proposal lifecycle tracking, pre-award routing and budget development, post-award expenditure monitoring and burn rate analysis, 2 CFR 200 Uniform Guidance cost allowability enforcement.
rehab-scheduling
Audit a rehabilitation scheduling system -- evaluate therapist productivity and utilization rates, PTA/COTA supervision compliance, patient flow and no-show management, equipment and treatment room allocation, insurance authorization tracking with expiration alerts.
safety-training
Audit OSHA training compliance, certification expirations, competency tracking, and LMS integration. Triggers: you need to evaluate safety training programs, check ANSI Z490.
catchup
Summarize and review what changed while you were away. Use after a weekend, vacation, or flight to check missed PRs, git commits, Linear tickets, and meetings — one prioritized brief, not a firehose.