cwicr-work-breakdown
Break down CWICR work items into component resources. Decompose aggregate items, analyze resource composition, and generate detailed bills of resources.
Install / Use
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill cwicr-work-breakdownInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of cwicr-work-breakdown
cwicr-work-breakdown scores 91/100 on our quality scale, 1221st of 4,644 Development & Engineering skills we index (top 27%).
Its SKILL.md is 17 KB long, well organised into 16 sections with 6 code examples: a thorough specification that gives an agent plenty to work with.
It has 333 GitHub stars, a meaningful sign that others use it.
Maintenance, license and trust
- The repository was last updated 44 days ago, so cwicr-work-breakdown is actively maintained.
- It is released under the MIT license, a permissive license that allows use, modification and commercial use with attribution.
- Its trust signals score 100/100, with no cautions. These come from repository metadata, not a code audit — read the skill file before letting an agent act on it.
cwicr-work-breakdown compared with similar skills
All 4 of these similar skills score higher than cwicr-work-breakdown; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| cwicr-work-breakdown (this skill)by datadrivenconstruction | 91 | 333 | 44d ago | SKILL.md |
| Agent-Reachby Panniantong | 100 | 91.2k | 19d ago | CLAUDE.md |
| headroomby headroomlabs-ai | 100 | 74.4k | today | CLAUDE.md |
| ai-job-searchby MadsLorentzen | 100 | 45.0k | 1d ago | CLAUDE.md |
| claude-howtoby luongnv89 | 100 | 41.7k | 5d ago | CLAUDE.md |
Frequently asked questions
- How do I install cwicr-work-breakdown?
- Run
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill cwicr-work-breakdown. The install tabs above show the steps for each supported agent. - Which AI agents does cwicr-work-breakdown work with?
- It is written for Universal, as a SKILL.md file. Other agents that read the same format can often use it too.
- Is cwicr-work-breakdown safe to use?
- It is MIT-licensed and scores 100/100 on trust signals. Skills are instructions an agent will follow, so read the file before installing it and do not approve commands you do not understand.
- Is cwicr-work-breakdown still maintained?
- The repository was last updated 44 days ago, so cwicr-work-breakdown is actively maintained.
Skill content
View source on GitHubname: "cwicr-work-breakdown" description: "Break down CWICR work items into component resources. Decompose aggregate items, analyze resource composition, and generate detailed bills of resources." homepage: "https://datadrivenconstruction.io" metadata: {"openclaw": {"emoji": "🗄️", "os": ["darwin", "linux", "win32"], "homepage": "https://datadrivenconstruction.io", "requires": {"bins": ["python3"]}}}
CWICR Work Breakdown
Business Case
Problem Statement
Work items in CWICR contain aggregated resources:
- What materials make up a concrete work item?
- What labor categories are needed?
- What equipment is involved?
- How to generate detailed resource bills?
Solution
Decompose CWICR work items into their constituent resources (labor, materials, equipment) with quantities and costs.
Business Value
- Transparency - See inside aggregated items
- Procurement - Generate material lists
- Scheduling - Identify resource needs
- Cost control - Track resource consumption
Technical Implementation
import pandas as pd
import numpy as np
from typing import Dict, Any, List, Optional, Tuple
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from collections import defaultdict
class ResourceType(Enum):
"""Types of resources in work items."""
LABOR = "labor"
MATERIAL = "material"
EQUIPMENT = "equipment"
OVERHEAD = "overhead"
@dataclass
class ResourceComponent:
"""Single resource component of a work item."""
resource_code: str
resource_type: ResourceType
description: str
unit: str
quantity_per_unit: float # Per unit of work item
unit_rate: float
cost_per_unit: float # Per unit of work item
@dataclass
class WorkItemBreakdown:
"""Complete breakdown of a work item."""
work_item_code: str
work_item_description: str
work_item_unit: str
components: List[ResourceComponent]
labor_cost_per_unit: float
material_cost_per_unit: float
equipment_cost_per_unit: float
total_cost_per_unit: float
@dataclass
class BillOfResources:
"""Bill of resources for multiple work items."""
project_name: str
total_labor_cost: float
total_material_cost: float
total_equipment_cost: float
total_cost: float
labor_resources: List[Dict[str, Any]]
material_resources: List[Dict[str, Any]]
equipment_resources: List[Dict[str, Any]]
class CWICRWorkBreakdown:
"""Break down work items into resources."""
def __init__(self, cwicr_data: pd.DataFrame,
resources_data: pd.DataFrame = None):
self.work_items = cwicr_data
self.resources = resources_data
self._index_data()
def _index_data(self):
"""Index data for fast lookup."""
if 'work_item_code' in self.work_items.columns:
self._work_index = self.work_items.set_index('work_item_code')
else:
self._work_index = None
if self.resources is not None and 'resource_code' in self.resources.columns:
self._resource_index = self.resources.set_index('resource_code')
else:
self._resource_index = None
def breakdown_work_item(self, work_item_code: str) -> Optional[WorkItemBreakdown]:
"""Break down single work item into components."""
if self._work_index is None or work_item_code not in self._work_index.index:
return None
item = self._work_index.loc[work_item_code]
components = []
# Extract labor component
labor_norm = float(item.get('labor_norm', 0) or 0)
labor_rate = float(item.get('labor_rate', 35) or 35)
labor_cost = float(item.get('labor_cost', labor_norm * labor_rate) or labor_norm * labor_rate)
if labor_norm > 0:
components.append(ResourceComponent(
resource_code=f"{work_item_code}-LABOR",
resource_type=ResourceType.LABOR,
description=f"Labor for {item.get('description', '')}",
unit="hr",
quantity_per_unit=labor_norm,
unit_rate=labor_rate,
cost_per_unit=labor_cost
))
# Extract material component
material_norm = float(item.get('material_norm', 1) or 1)
material_cost = float(item.get('material_cost', 0) or 0)
if material_cost > 0:
components.append(ResourceComponent(
resource_code=f"{work_item_code}-MAT",
resource_type=ResourceType.MATERIAL,
description=str(item.get('material_description', 'Materials')),
unit=str(item.get('material_unit', item.get('unit', 'ea'))),
quantity_per_unit=material_norm,
unit_rate=material_cost / material_norm if material_norm > 0 else material_cost,
cost_per_unit=material_cost
))
# Extract equipment component
equipment_norm = float(item.get('equipment_norm', 0) or 0)
equipment_rate = float(item.get('equipment_rate', 0) or 0)
equipment_cost = float(item.get('equipment_cost', equipment_norm * equipment_rate) or 0)
if equipment_norm > 0 or equipment_cost > 0:
components.append(ResourceComponent(
resource_code=f"{work_item_code}-EQUIP",
resource_type=ResourceType.EQUIPMENT,
description=str(item.get('equipment_description', 'Equipment')),
unit="hr",
quantity_per_unit=equipment_norm,
unit_rate=equipment_rate,
cost_per_unit=equipment_cost
))
return WorkItemBreakdown(
work_item_code=work_item_code,
work_item_description=str(item.get('description', '')),
work_item_unit=str(item.get('unit', '')),
components=components,
labor_cost_per_unit=labor_cost,
material_cost_per_unit=material_cost,
equipment_cost_per_unit=equipment_cost,
total_cost_per_unit=labor_cost + material_cost + equipment_cost
)
def generate_bill_of_resources(self,
items: List[Dict[str, Any]],
project_name: str = "Project") -> BillOfResources:
"""Generate bill of resources from work items."""
labor_agg = defaultdict(lambda: {'hours': 0, 'cost': 0, 'work_items': []})
material_agg = defaultdict(lambda: {'quantity': 0, 'cost': 0, 'unit': '', 'work_items': []})
equipment_agg = defaultdict(lambda: {'hours': 0, 'cost': 0, 'work_items': []})
for item in items:
code = item.get('work_item_code', item.get('code'))
qty = item.get('quantity', 0)
breakdown = self.breakdown_work_item(code)
if not breakdown:
continue
for component in breakdown.components:
scaled_qty = component.quantity_per_unit * qty
scaled_cost = component.cost_per_unit * qty
if component.resource_type == ResourceType.LABOR:
key = 'General Labor' # Could be more specific with skill data
labor_agg[key]['hours'] += scaled_qty
labor_agg[key]['cost'] += scaled_cost
labor_agg[key]['work_items'].append(code)
elif component.resource_type == ResourceType.MATERIAL:
key = component.description
material_agg[key]['quantity'] += scaled_qty
material_agg[key]['cost'] += scaled_cost
material_agg[key]['unit'] = component.unit
material_agg[key]['work_items'].append(code)
elif component.resource_type == ResourceType.EQUIPMENT:
key = component.description
equipment_agg[key]['hours'] += scaled_qty
equipment_agg[key]['cost'] += scaled_cost
equipment_agg[key]['work_items'].append(code)
# Convert to lists
labor_resources = [
{
'resource': name,
'hours': round(data['hours'], 1),
'cost': round(data['cost'], 2),
'work_items': len(set(data['work_items']))
}
for name, data in labor_agg.items()
]
material_resources = [
{
'resource': name,
'quantity': round(data['quantity'], 2),
'unit': data['unit'],
'cost': round(data['cost'], 2),
'work_items': len(set(data['work_items']))
}
for name, data in material_agg.items()
]
equipment_resources = [
{
'resource': name,
'hours': round(data['hours'], 1),
'cost': round(data['cost'], 2),
'work_items': len(set(data['work_items']))
}
for name, data in equipment_agg.items()
]
total_labor = sum(r['cost'] for r in labor_resources)
total_material = sum(r['cost'] for r in material_resources)
total_equipment = sum(r['cost'] for r in equipment_resources)
return BillOfResources(
project_name=project_name,
total_labor_cost=round(total_labor, 2),
total_material_cost=round(total_material, 2),
total_equipment_cost=round(total_equipment, 2),
total_cost=round(total_labor + total_material + total_equipment, 2),
labor_resources=labor_resources,
material_resources=material_resources,
equipment_resources=equipment_resources
)
def get_resource_composition(self, work_item_code: str) -> Dict[str, float]:
"""Get percentage composition of work item by resource type."""
breakdown = self.breakdown_work_item(work_item_code)
if not breakdown or breakdown.total_cost_per_unit == 0:
return {'labor': 0, 'material': 0, 'equipment': 0}
total = breakdown.total_cost_per_unit
return {
'labor': round(breakdown.labor_cost_per_unit / total * 100, 1),
'material': round(breakdown.material_cost_per_unit / total * 100, 1),
'equipment': round(breakdown.equipment_cost_per_unit / total * 100, 1)
}
def analyze_labor_intensity(self,
work_items: List[str]) -> pd.DataFrame:
"""Analyze labor intensity of work items."""
data = []
for code in work_items:
breakdown = self.breakdown_work_item(code)
if breakdown:
composition = self.get_resource_composition(code)
labor_components = [c for c in breakdown.components if c.resource_type == ResourceType.LABOR]
labor_hours = sum(c.quantity_per_unit for c in labor_components)
data.append({
'work_item_code': code,
'description': breakdown.work_item_description,
'labor_hours_per_unit': labor_hours,
'labor_cost_pct': composition['labor'],
'material_cost_pct': composition['material'],
'equipment_cost_pct': composition['equipment'],
'labor_intensive': composition['labor'] > 50
})
return pd.DataFrame(data).sort_values('labor_cost_pct', ascending=False)
def export_breakdown(self,
breakdown: WorkItemBreakdown,
output_path: str) -> str:
"""Export single work item breakdown."""
df = pd.DataFrame([
{
'Resource Code': c.resource_code,
'Type': c.resource_type.value,
'Description': c.description,
'Unit': c.unit,
'Quantity/Unit': c.quant
Truncated for display — read the full file on GitHub.
Related Skills
Agent-Reach
91.2kGive your AI agent eyes to see the entire internet. Read & search Twitter, Reddit, YouTube, GitHub, Bilibili, XiaoHongShu — one CLI, zero API fees.
headroom
74.4kCompress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.
ai-job-search
45.0kThe job search that runs on your machine. AI job application framework built on Claude Code: evaluate postings, tailor CVs, write cover letters, prep interviews. Fork it and own it.
claude-howto
41.7kA visual, example-driven guide to Claude Code — from basic concepts to advanced agents, with copy-paste templates that bring immediate value.
Languages
Trust signals
From repository metadata: license, adoption, age and documentation. Not a code audit — see the Safety scan above for what the skill file itself contains.
