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

punch-list-manager

Manage construction punch lists for project closeout. Track deficiencies, assign corrections, and monitor completion status.

Instalar en Claude Code
Copiar
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-manager
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.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] = c