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 incident-reportinggit 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/incident-reporting)<a href="https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/incident-reporting"><img src="https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/incident-reporting/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/incident-reporting"><img src="https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/incident-reporting.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.00027 | $0.03524 |
| Opus 5 | $0.00014 | $0.01762 |
| Sonnet 5 | $0.00005 | $0.00705 |
| Haiku 4.5 | $0.00003 | $0.00352 |
Grade A, and why
incident-reporting 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 8d 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:
- incident-reporting — 100% identical, 0 lines differ
How it starts
The opening of the file, as written. The whole thing — 464 lines — stays where its author put it; the contents beside it link to each section on GitHub.
Incident Reporting System
Overview
Comprehensive incident reporting system for construction safety. Capture near-misses, injuries, and property damage. Conduct root cause analysis and track corrective actions to prevent recurrence.
"Near-miss reporting prevents 90% of future serious incidents" — DDC Community
Incident Pyramid
△
/│\ Fatality (1)
/ │ \
/ │ \ Serious Injury (10)
/ │ \
/ │ \ Minor Injury (30)
/ │ \
/ │ \ Near Miss (300)
/ │ \
/ │ \ Unsafe Acts (3000)
──────────┴──────────
Technical Implementation
from dataclasses import dataclass, field
from typing import List, Dict, Optional
from enum import Enum
from datetime import datetime, timedelta
import json
class IncidentType(Enum):
NEAR_MISS = "near_miss"
FIRST_AID = "first_aid"
MEDICAL_TREATMENT = "medical_treatment"
LOST_TIME = "lost_time"
FATALITY = "fatality"
PROPERTY_DAMAGE = "property_damage"
ENVIRONMENTAL = "environmental"
class IncidentCategory(Enum):
FALL = "fall"
STRUCK_BY = "struck_by"
CAUGHT_IN = "caught_in"
ELECTROCUTION = "electrocution"
VEHICLE = "vehicle"
MATERIAL_HANDLING = "material_handling"
TOOL_EQUIPMENT = "tool_equipment"
SLIP_TRIP = "slip_trip"
FIRE = "fire"
CHEMICAL = "chemical"
OTHER = "other"
class InvestigationStatus(Enum):
REPORTED = "reported"
UNDER_INVESTIGATION = "under_investigation"
ROOT_CAUSE_IDENTIFIED = "root_cause_identified"
CORRECTIVE_ACTIONS_ASSIGNED = "corrective_actions_assigned"
IN_REMEDIATION = "in_remediation"
CLOSED = "closed"
@dataclass
class Person:
name: str
company: str
role: str
contact: str
years_experience: int = 0
@dataclass
class CorrectiveAction:
id: str
description: str
assigned_to: str
due_date: datetime
status: str = "open"
completed_date: Optional[datetime] = None
verification_notes: str = ""
@dataclass
class Incident:
id: str
incident_type: IncidentType
category: IncidentCategory
date_time: datetime
location: str
project_id: str
project_name: str
# Description
description: str
immediate_actions: str
# People involved
injured_person: Optional[Person] = None
witnesses: List[Person] = field(default_factory=list)
reported_by: str = ""
# Investigation
status: InvestigationStatus = InvestigationStatus.REPORTED
root_causes: List[str] = field(default_factory=list)
contributing_factors: List[str] = field(default_factory=list)
corrective_actions: List[CorrectiveAction] = field(default_factory=list)
# Documentation
photos: List[str] = field(default_factory=list)
weather_conditions: str = ""
equipment_involved: List[str] = field(default_factory=list)
# Metrics
days_lost: int = 0
property_damage_cost: float = 0.0
osha_recordable: bool = False
class IncidentManager:
"""Manage construction incident reporting and investigation."""
# 5 Whys root cause categories
ROOT_CAUSE_CATEGORIES = [
"Training/Competency",
"Procedures/Work Instructions",
"Equipment/Tools",
"Supervision",
"Communication",
"Housekeeping",
"PPE",
"Work Environment",
"Physical/Mental State",
"Management System"
]
def __init__(self):
self.incidents: Dict[str, Incident] = {}
self.corrective_actions: Dict[str, CorrectiveAction] = {}
def report_incident(self, incident_type: IncidentType,
category: IncidentCategory,
date_time: datetime,
location: str,
project_id: str,
project_name: str,
description: str,
immediate_actions: str,
reported_by: str,
injured_person: Dict = None) -> Incident:
"""Report new incident."""
incident_id = f"INC-{datetime.now().strftime('%Y%m%d%H%M%S')}"
injured = None
if injured_person:
injured = Person(**injured_person)
incident = Incident(
id=incident_id,
incident_type=incident_type,
category=category,
date_time=date_time,
location=location,
project_id=project_id,
project_name=project_name,
description=description,
immediate_actions=immediate_actions,
reported_by=reported_by,
injured_person=injured
)
# Auto-flag OSHA recordable
if incident_type in [IncidentType.MEDICAL_TREATMENT,
IncidentType.LOST_TIME,
IncidentType.FATALITY]:
incident.osha_recordable = True
self.incidents[incident_id] = incident
return incident
def add_witness(self, incident_id: str, witness: Dict) -> Incident:
"""Add witness to incident."""
if incident_id not in self.incidents:
raise ValueError(f"Incident {incident_id} not found")
self.incidents[incident_id].witnesses.append(Person(**witness))
return self.incidents[incident_id]
def conduct_investigation(self, incident_id: str,
root_causes: List[str],
contributing_factors: List[str]) -> Incident:
"""Record investigation findings."""
if incident_id not in self.incidents:
raise ValueError(f"Incident {incident_id} not found")
incident = self.incidents[incident_id]
incident.root_causes = root_causes
incident.contributing_factors = contributing_factors
incident.status = InvestigationStatus.ROOT_CAUSE_IDENTIFIED
return incident
def five_whys_analysis(self, incident_id: str, whys: List[str]) -> Dict:
"""Conduct 5 Whys analysis."""
if incident_id not in self.incidents:
raise ValueError(f"Incident {incident_id} not found")
analysis = {
"incident_id": incident_id,
"analysis_date": datetime.now().isoformat(),
"whys": []
}
for i, why in enumerate(whys):
analysis["whys"].append({
"level": i + 1,
"question": f"Why #{i+1}?",
"answer": why
})
# The last "why" is typically the root cause
if whys:
self.incidents[incident_id].root_causes.append(whys[-1])
return analysis
def assign_corrective_action(self, incident_id: str,
description: str,
assigned_to: str,
due_days: int = 7) -> CorrectiveAction:
"""Assign corrective action."""
if incident_id not in self.incidents:
raise ValueError(f"Incident {incident_id} not found")
action_id = f"CA-{datetime.now().strftime('%Y%m%d%H%M%S')}"
action = CorrectiveAction(
id=action_id,
description=description,
assigned_to=assigned_to,
due_date=datetime.now() + timedelta(days=due_days)
)
self.incidents[incident_id].corrective_actions.append(action)
self.incidents[incident_id].status = InvestigationStatus.CORRECTIVE_ACTIONS_ASSIGNED
self.corrective_actions[action_id] = action
return action
def complete_corrective_action(self, action_id: str,
verification_notes: str) -> CorrectiveAction:
"""Mark corrective action complete."""
if action_id not in self.corrective_actions:
raise ValueError(f"Corrective action {action_id} not found")
action = self.corrective_actions[action_id]
action.status = "completed"
action.completed_date = datetime.now()
action.verification_notes = verification_notes
return action
def get_incident_metrics(self, project_id: str = None,
start_date: datetime = None,
end_date: datetime = None) -> Dict:
"""Calculate incident metrics."""
incidents = list(self.incidents.values())
if project_id:
incidents = [i for i in incidents if i.project_id == project_id]
if start_date:
incidents = [i for i in incidents if i.date_time >= start_date]
if end_date:
incidents = [i for i in incidents if i.date_time <= end_date]
# Calculate metrics
total = len(incidents)
near_misses = len([i for i in incidents if i.incident_type == IncidentType.NEAR_MISS])
first_aid = len([i for i in incidents if i.incident_type == IncidentType.FIRST_AID])
recordables = len([i for i in incidents if i.osha_recordable])
lost_time = len([i for i in incidents if i.incident_type == IncidentType.LOST_TIME])
total_days_lost = sum(i.days_lost for i in incidents)
# Category breakdown
by_category = {}
for cat in IncidentCategory:
count = len([i for i in incidents if i.category == cat])
if count > 0:
by_category[cat.value] = count
return {
"total_incidents": total,
"near_misses": near_misses,
"first_aid_cases": first_aid,
"osha_recordables": recordables,
"lost_time_incidents": lost_time,
"total_days_lost": total_days_lost,
"by_category": by_category,
"near_miss_ratio": near_misses / recordables if recordables else 0
}
def calculate_trir(self, hours_worked: int, project_id: str = None) -> float:
"""Calculate Total Recordable Incident Rate."""
incidents = list(self.incidents.values())
if project_id:
incidents = [i for i in incidents if i.project_id == project_id]
recordables = len([i for i in incidents if i.osha_recordable])
if hours_worked == 0:
return 0
# TRIR = (Recordables × 200,000) / Hours Worked
return (recordables * 200000) / hours_worked
def calculate_dart(self, hours_worked: int, project_id: str = None) -> float:
"""Calculate Days Away, Restricted, or Transferred rate."""
incidents = list(self.incidents.values())
if project_id:
incidents = [i for i in incidents if i.project_id == project_id]
dart_cases = len([i for i in incidents
if i.incident_type in [IncidentType.LOST_TIME]])
if hours_worked == 0:
return 0
return (dart_cases * 200000) / hours_worked
def get_trend_analysis(self, months: int = 6) -> List[Dict]:
"""Analyze incident trends over time."""
trends = []
now = datetime.now()
for i in range(months):
month_start = datetime(now.year, now.month - i, 1) if now.month > i else datetime(now.year - 1, 12 - (i - now.month), 1)
month_end = month_start.replace(day=28) + timedelta(days=4)
month_end = month_end - timedelta(days=month_end.day)
month_incidents = [inc for inc in self.incidents.values()
if month_start <= inc.date_time <= month_end]
trends.append({
"month": month_start.strftime("%Y-%m"),
"total": len(month_incidents),
"near_misses": len([i for i in month_incidents if i.incident_type == IncidentType.NEAR_MISS]),
"recordables": len([i for i in month_incidents if i.osha_recordable])
})
return list(reversed(trends))
def generate_incident_report(self, incident_id: str) -> str:
"""Generate detailed incident report."""
if incident_id not in self.incidents:
return "Incident not found"
inc = self.incidents[incident_id]
lines = [
f"# Incident Report",
f"",
f"**Incident ID:** {inc.id}",
f"**Type:** {inc.incident_type.value}",
f"**Category:** {inc.category.value}",
f"**Date/Time:** {inc.date_time.strftime('%Y-%m-%d %H:%M')}",
f"**Location:** {inc.location}",
f"**Project:** {inc.project_name}",
f"**Status:** {inc.status.value}",
f"**OSHA Recordable:** {'Yes' if inc.osha_recordable else 'No'}",
f"",
f"## Description",
f"{inc.description}",
f"",
f"## Immediate Actions Taken",
f"{inc.immediate_actions}",
f"",
]
if inc.injured_person:
lines.extend([
f"## Injured Person",
f"- Name: {inc.injured_person.name}",
f"- Company: {inc.injured_person.company}",
f"- Role: {inc.injured_person.role}",
f"- Experience: {inc.injured_person.years_experience} years",
f""
])
if inc.root_causes:
lines.extend([
f"## Root Causes",
*[f"- {rc}" for rc in inc.root_causes],
f""
])
if inc.corrective_actions:
lines.extend([
f"## Corrective Actions",
f"| Action | Assigned To | Due | Status |",
f"|--------|-------------|-----|--------|"
])
for ca in inc.corrective_actions:
lines.append(f"| {ca.description} | {ca.assigned_to} | {ca.due_date.strftime('%Y-%m-%d')} | {ca.status} |")
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.
- 8d ago First seen · 464 lines · 27 tokens per session scan A 04306f07b487
incident-reporting is a skill published in the GitHub repository datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction (308 stars, last pushed 20d ago), licensed MIT. It adds 27 tokens to every session and 3,524 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
compliance-audit
Audits codebases against compliance frameworks (SOC2, HIPAA, PCI-DSS, GDPR, ISO27001, etc.) using parallel agents per subdirectory/sub-repo. Produces a detailed markdown report with line-level code references. Use when you need to check a directory or monorepo for compliance violations before an audit or review.
legal-discovery
Audit e-discovery and litigation document review systems -- data collection pipelines (PST, MBOX, SharePoint, Slack), document processing (OCR via Tesseract/ABBYY, metadata extraction, deduplication), Technology Assisted Review (TAR 1.0/2.0/CAL with recall/precision tracking).
litigation-predictor
Audit litigation analytics and case outcome prediction systems -- ML outcome models (logistic regression, gradient boosting, neural nets with temporal train/test splits), settlement range modeling (Monte Carlo simulation, comparable case matching, BATNA analysis).
sales-readiness
Audit whether a product is ready for enterprise sales. Use when you need to assess SSO/SAML/SCIM support, RBAC maturity, multi-tenancy data isolation, audit logging coverage, public API quality, SLA operational readiness, SOC2/ISO27001 certification gaps, GDPR data residency controls.
audit-support
Analyzes audit readiness systems for internal control testing, evidence collection workflows, statistical sampling methodology, audit finding documentation, and remediation tracking using PCAOB, ISA, and SOX compliance frameworks..
case-outcome-predictor
Audit legal case prediction systems for bias, fairness, accuracy, and ethical guardrails. Use when: 'check my prediction model for bias', 'audit case outcome fairness', 'evaluate legal ML model', 'review sentencing prediction ethics', 'analyze bail risk algorithm', 'fairness metrics for justice system AI'.