cwicr-rate-updater
Update CWICR resource rates with current market prices. Integrate external price data, apply inflation adjustments, and maintain rate history.
Install / Use
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill cwicr-rate-updaterInstalls into whichever agent you are using.
SKILL.md
Installable skill definition
Quality Score
Category
Development & EngineeringSupported Platforms
Our assessment of cwicr-rate-updater
cwicr-rate-updater scores 91/100 on our quality scale, 1215th of 4,644 Development & Engineering skills we index (top 27%).
Its SKILL.md is 16 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-rate-updater 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-rate-updater compared with similar skills
All 4 of these similar skills score higher than cwicr-rate-updater; compare them before choosing.
| Skill | Score | Stars | Updated | Format |
|---|---|---|---|---|
| cwicr-rate-updater (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-rate-updater?
- Run
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill cwicr-rate-updater. The install tabs above show the steps for each supported agent. - Which AI agents does cwicr-rate-updater 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-rate-updater 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-rate-updater still maintained?
- The repository was last updated 44 days ago, so cwicr-rate-updater is actively maintained.
Skill content
View source on GitHubname: "cwicr-rate-updater" description: "Update CWICR resource rates with current market prices. Integrate external price data, apply inflation adjustments, and maintain rate history." homepage: "https://datadrivenconstruction.io" metadata: {"openclaw": {"emoji": "🗄️", "os": ["darwin", "linux", "win32"], "homepage": "https://datadrivenconstruction.io", "requires": {"bins": ["python3"]}}}
CWICR Rate Updater
Business Case
Problem Statement
Resource rates become outdated:
- Material prices fluctuate with market
- Labor rates change annually
- Equipment costs vary by region
- Historical rates need adjustment
Solution
Systematic rate updates integrating market data, inflation indices, and regional factors while maintaining audit trail.
Business Value
- Accuracy - Current market pricing
- Flexibility - Update specific resources or categories
- Audit trail - Track rate changes over time
- Automation - Integrate with price APIs
Technical Implementation
import pandas as pd
import numpy as np
from typing import Dict, Any, List, Optional, Tuple, Callable
from dataclasses import dataclass, field
from datetime import datetime, date
from enum import Enum
import json
class RateType(Enum):
"""Types of rates."""
LABOR = "labor"
MATERIAL = "material"
EQUIPMENT = "equipment"
SUBCONTRACT = "subcontract"
class AdjustmentMethod(Enum):
"""Methods for rate adjustment."""
FIXED_AMOUNT = "fixed_amount"
PERCENTAGE = "percentage"
MULTIPLIER = "multiplier"
REPLACEMENT = "replacement"
@dataclass
class RateChange:
"""Record of rate change."""
resource_code: str
rate_type: RateType
old_rate: float
new_rate: float
change_percent: float
change_date: datetime
reason: str
source: str
@dataclass
class RateUpdateResult:
"""Result of rate update operation."""
total_items: int
updated: int
unchanged: int
errors: int
changes: List[RateChange]
summary: Dict[str, Any]
class CWICRRateUpdater:
"""Update resource rates in CWICR data."""
def __init__(self, cwicr_data: pd.DataFrame):
self.data = cwicr_data.copy()
self.change_log: List[RateChange] = []
self.original_data = cwicr_data.copy()
def get_current_rates(self,
rate_type: RateType = None,
category: str = None) -> pd.DataFrame:
"""Get current rates, optionally filtered."""
df = self.data.copy()
# Filter by category if specified
if category and 'category' in df.columns:
df = df[df['category'].str.contains(category, case=False, na=False)]
# Select relevant columns based on rate type
rate_columns = {
RateType.LABOR: ['work_item_code', 'description', 'labor_rate', 'labor_cost'],
RateType.MATERIAL: ['work_item_code', 'description', 'material_cost'],
RateType.EQUIPMENT: ['work_item_code', 'description', 'equipment_cost', 'equipment_rate']
}
if rate_type and rate_type in rate_columns:
cols = [c for c in rate_columns[rate_type] if c in df.columns]
return df[cols]
return df
def update_rate(self,
work_item_code: str,
rate_type: RateType,
new_rate: float,
reason: str = "Manual update",
source: str = "User") -> Optional[RateChange]:
"""Update single rate."""
rate_column = self._get_rate_column(rate_type)
if rate_column not in self.data.columns:
return None
mask = self.data['work_item_code'] == work_item_code
if not mask.any():
return None
old_rate = float(self.data.loc[mask, rate_column].iloc[0])
self.data.loc[mask, rate_column] = new_rate
change_percent = ((new_rate - old_rate) / old_rate * 100) if old_rate > 0 else 0
change = RateChange(
resource_code=work_item_code,
rate_type=rate_type,
old_rate=old_rate,
new_rate=new_rate,
change_percent=round(change_percent, 2),
change_date=datetime.now(),
reason=reason,
source=source
)
self.change_log.append(change)
return change
def _get_rate_column(self, rate_type: RateType) -> str:
"""Get column name for rate type."""
mapping = {
RateType.LABOR: 'labor_rate',
RateType.MATERIAL: 'material_cost',
RateType.EQUIPMENT: 'equipment_cost',
RateType.SUBCONTRACT: 'subcontract_cost'
}
return mapping.get(rate_type, 'labor_rate')
def apply_percentage_adjustment(self,
rate_type: RateType,
percentage: float,
category: str = None,
reason: str = "Percentage adjustment") -> RateUpdateResult:
"""Apply percentage adjustment to rates."""
rate_column = self._get_rate_column(rate_type)
if rate_column not in self.data.columns:
return RateUpdateResult(0, 0, 0, 1, [], {})
# Build mask
mask = pd.Series([True] * len(self.data))
if category and 'category' in self.data.columns:
mask = self.data['category'].str.contains(category, case=False, na=False)
# Store old values
old_values = self.data.loc[mask, rate_column].copy()
# Apply adjustment
multiplier = 1 + (percentage / 100)
self.data.loc[mask, rate_column] = old_values * multiplier
# Record changes
changes = []
for idx in self.data[mask].index:
old_rate = float(old_values.loc[idx])
new_rate = float(self.data.loc[idx, rate_column])
if old_rate != new_rate:
change = RateChange(
resource_code=str(self.data.loc[idx, 'work_item_code']),
rate_type=rate_type,
old_rate=old_rate,
new_rate=new_rate,
change_percent=percentage,
change_date=datetime.now(),
reason=reason,
source=f"Bulk {percentage}%"
)
changes.append(change)
self.change_log.append(change)
return RateUpdateResult(
total_items=len(self.data[mask]),
updated=len(changes),
unchanged=len(self.data[mask]) - len(changes),
errors=0,
changes=changes,
summary={
'rate_type': rate_type.value,
'adjustment_percent': percentage,
'category': category,
'average_new_rate': self.data.loc[mask, rate_column].mean()
}
)
def apply_inflation_index(self,
base_year: int,
current_year: int,
inflation_rates: Dict[int, float],
rate_types: List[RateType] = None) -> RateUpdateResult:
"""Apply inflation index from base year to current."""
if rate_types is None:
rate_types = [RateType.LABOR, RateType.MATERIAL, RateType.EQUIPMENT]
# Calculate cumulative multiplier
cumulative_multiplier = 1.0
for year in range(base_year, current_year):
rate = inflation_rates.get(year, 0.02) # Default 2%
cumulative_multiplier *= (1 + rate)
total_changes = []
for rate_type in rate_types:
result = self.apply_percentage_adjustment(
rate_type=rate_type,
percentage=(cumulative_multiplier - 1) * 100,
reason=f"Inflation {base_year}-{current_year}"
)
total_changes.extend(result.changes)
return RateUpdateResult(
total_items=len(self.data),
updated=len(total_changes),
unchanged=len(self.data) - len(total_changes),
errors=0,
changes=total_changes,
summary={
'base_year': base_year,
'current_year': current_year,
'cumulative_multiplier': round(cumulative_multiplier, 4),
'total_adjustment_percent': round((cumulative_multiplier - 1) * 100, 2)
}
)
def import_external_rates(self,
external_data: pd.DataFrame,
code_column: str,
rate_column: str,
rate_type: RateType,
match_on: str = 'work_item_code') -> RateUpdateResult:
"""Import rates from external data source."""
changes = []
errors = 0
target_column = self._get_rate_column(rate_type)
for _, row in external_data.iterrows():
code = row[code_column]
new_rate = row[rate_column]
try:
change = self.update_rate(
work_item_code=code,
rate_type=rate_type,
new_rate=new_rate,
reason="External import",
source="External data"
)
if change:
changes.append(change)
except Exception:
errors += 1
return RateUpdateResult(
total_items=len(external_data),
updated=len(changes),
unchanged=len(external_data) - len(changes) - errors,
errors=errors,
changes=changes,
summary={
'source': 'External import',
'rate_type': rate_type.value
}
)
def apply_regional_factors(self,
region_factors: Dict[str, float],
default_factor: float = 1.0) -> RateUpdateResult:
"""Apply regional adjustment factors."""
# This assumes region column exists or applies uniformly
factor = region_factors.get('default', default_factor)
labor_result = self.apply_percentage_adjustment(
RateType.LABOR,
(region_factors.get('labor', factor) - 1) * 100,
reason="Regional adjustment"
)
material_result = self.apply_percentage_adjustment(
RateType.MATERIAL,
(region_factors.get('material', factor) - 1) * 100,
reason="Regional adjustment"
)
equipment_result = self.apply_percentage_adjustment(
RateType.EQUIPMENT,
(region_factors.get('equipment', factor) - 1) * 100,
reason="Regional adjustment"
)
all_changes = (labor_result.changes + material_result.changes +
equipment_result.changes)
return RateUpdateResult(
total_items=len(self.data),
updated=len(all_changes),
unchanged=len(self.data) * 3 - len(all_changes),
errors=0,
changes=all_changes,
summary={
'region_factors': region_factors,
'labor_adjusted': len(labor_result.changes),
'material_adjusted': len(material_result.changes),
'equipment_adjusted': len(equipment_result.changes)
}
)
def get_change_log(self,
start_date: datetime = None,
rate_type: RateType = None) -> List[RateChange]:
"""Get change log, optionally filtered."""
changes = self.change_log
if start_date:
changes = [c for c in changes if c.change_date >= start_date]
if rate_type:
changes = [c for c in changes if c.rate_type == rate_type]
retu
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.
