punch-list-manager
Manage construction punch lists for project closeout. Track deficiencies, assign corrections, and monitor completion status.
git clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction /tmp/punch-list-manager && cp -r /tmp/punch-list-manager/1_DDC_Toolkit/Project-Closeout/punch-list-manager ~/.claude/skills/punch-list-managerSKILL.md
# Punch List Manager
## Business Case
### Problem Statement
Project closeout challenges:
- Tracking hundreds of items
- Assigning responsibility
- Monitoring completion
- Documentation for handover
### Solution
Systematic punch list management to track deficiencies, assignments, and completion through project closeout.
## Technical Implementation
```python
import pandas as pd
from typing import Dict, Any, List, Optional
from dataclasses import dataclass, field
from datetime import date, timedelta
from enum import Enum
class PunchItemStatus(Enum):
OPEN = "open"
IN_PROGRESS = "in_progress"
COMPLETED = "completed"
VERIFIED = "verified"
REJECTED = "rejected"
class PunchItemPriority(Enum):
CRITICAL = "critical" # Life safety, code violation
HIGH = "high" # Functionality impaired
MEDIUM = "medium" # Cosmetic/minor
LOW = "low" # Nice to have
class PunchItemCategory(Enum):
STRUCTURAL = "structural"
ARCHITECTURAL = "architectural"
MECHANICAL = "mechanical"
ELECTRICAL = "electrical"
PLUMBING = "plumbing"
FIRE_PROTECTION = "fire_protection"
EXTERIOR = "exterior"
SITE = "site"
GENERAL = "general"
@dataclass
class PunchItem:
item_id: str
location: str
description: str
category: PunchItemCategory
priority: PunchItemPriority
status: PunchItemStatus
assigned_to: str
created_date: date
due_date: date
completed_date: Optional[date] = None
verified_date: Optional[date] = None
verified_by: str = ""
photos: List[str] = field(default_factory=list)
notes: str = ""
@dataclass
class PunchListSummary:
total_items: int
open_items: int
in_progress: int
completed: int
verified: int
rejected: int
completion_rate: float
by_category: Dict[str, int]
by_priority: Dict[str, int]
by_assignee: Dict[str, int]
overdue_count: int
class PunchListManager:
"""Manage construction punch lists."""
def __init__(self, project_name: str, target_closeout_date: date):
self.project_name = project_name
self.target_date = target_closeout_date
self.items: Dict[str, PunchItem] = {}
self._next_id = 1
def add_item(self,
location: str,
description: str,
category: PunchItemCategory,
priority: PunchItemPriority,
assigned_to: str,
due_date: date = None,
notes: str = "") -> PunchItem:
"""Add punch list item."""
item_id = f"PL-{self._next_id:04d}"
self._next_id += 1
if due_date is None:
# Default based on priority
if priority == PunchItemPriority.CRITICAL:
due_date = date.today() + timedelta(days=3)
elif priority == PunchItemPriority.HIGH:
due_date = date.today() + timedelta(days=7)
else:
due_date = date.today() + timedelta(days=14)
item = PunchItem(
item_id=item_id,
location=location,
description=description,
category=category,
priority=priority,
status=PunchItemStatus.OPEN,
assigned_to=assigned_to,
created_date=date.today(),
due_date=due_date,
notes=notes
)
self.items[item_id] = item
return item
def update_status(self,
item_id: str,
status: PunchItemStatus,
verified_by: str = ""):
"""Update item status."""
if item_id not in self.items:
return
item = self.items[item_id]
item.status = status
if status == PunchItemStatus.COMPLETED:
item.completed_date = date.today()
elif status == PunchItemStatus.VERIFIED:
item.verified_date = date.today()
item.verified_by = verified_by
def reassign_item(self, item_id: str, new_assignee: str, new_due_date: date = None):
"""Reassign item to different contractor."""
if item_id not in self.items:
return
item = self.items[item_id]
item.assigned_to = new_assignee
if new_due_date:
item.due_date = new_due_date
item.status = PunchItemStatus.OPEN
def add_note(self, item_id: str, note: str):
"""Add note to item."""
if item_id in self.items:
self.items[item_id].notes += f"\n{date.today()}: {note}"
def add_photo(self, item_id: str, photo_path: str):
"""Add photo reference to item."""
if item_id in self.items:
self.items[item_id].photos.append(photo_path)
def get_summary(self) -> PunchListSummary:
"""Get punch list summary."""
items = list(self.items.values())
today = date.today()
# Status counts
open_items = sum(1 for i in items if i.status == PunchItemStatus.OPEN)
in_progress = sum(1 for i in items if i.status == PunchItemStatus.IN_PROGRESS)
completed = sum(1 for i in items if i.status == PunchItemStatus.COMPLETED)
verified = sum(1 for i in items if i.status == PunchItemStatus.VERIFIED)
rejected = sum(1 for i in items if i.status == PunchItemStatus.REJECTED)
# Completion rate (verified / total)
completion_rate = (verified / len(items) * 100) if items else 0
# By category
by_category = {}
for cat in PunchItemCategory:
count = sum(1 for i in items if i.category == cat and i.status != PunchItemStatus.VERIFIED)
if count > 0:
by_category[cat.value] = count
# By priority
by_priority = {}
for pri in PunchItemPriority:
count = sum(1 for i in items if i.priority == pri and i.status != PunchItemStatus.VERIFIED)
if count > 0:
by_priority[pri.value] = cGenerate automated daily progress reports from site data. Track work completed, labor hours, equipment usage, and weather conditions.
Analyze labor productivity from site data. Compare planned vs actual, identify trends, benchmark against industry standards.
Create interactive KPI dashboards for construction projects. Track schedule, cost, quality, and safety metrics in real-time.
Detect and analyze geometric clashes in BIM models. Identify MEP, structural, and architectural conflicts before construction.
Classify BIM elements using AI and standard classification systems. Map elements to UniFormat, MasterFormat, OmniClass, and CWICR codes.
Generate comprehensive BIM model validation reports. Check data quality, completeness, and compliance with standards.
Calculate CO2 emissions and carbon footprint from BIM model data. Analyze embodied carbon by material, element, and building system.
Extract quantities from IFC/Revit models for quantity takeoff. Uses DDC converters to get element counts, areas, volumes, lengths with grouping and reporting.