resource-allocation-optimizer

resource-allocation-optimizer is a skill for Claude Code, Codex from datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction. It costs 30 tokens per session (3,415 once invoked), scanned A, original, MIT.

A construction planning tool for balancing available workers, equipment, and materials across scheduled activities.

In plain words
What is it for?
Use it to level resources, resolve conflicts between activities, and compare workload across the project schedule.
Why use it?
It helps find over-allocated resources and reduce workload peaks that can cause delays or inefficient use of crews and equipment.

Skill for Claude CodeCodex

Which agent this was written for is unclear — built for openclaw. Also seen: built for openclaw.

Good fit Use it to level resources, resolve conflicts between activities, and compare workload across the project schedule.

Compare 6 skills from other repositories ↓
Install with agentmods
npx agentmods add skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/resource-allocation-optimizer
Install

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.

Any agent
npx skills add datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction --skill resource-allocation-optimizer
Clone the repo
git clone --depth 1 https://github.com/datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction

Made for: Claude Code, Codex.

Wrote 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.

agentmods badge for resource-allocation-optimizer

README.md
[![agentmods](https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/resource-allocation-optimizer/github.svg)](https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/resource-allocation-optimizer)
Your own site
<a href="https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/resource-allocation-optimizer"><img src="https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/resource-allocation-optimizer/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.

agentmods 80×15 button for resource-allocation-optimizer

Your own site · 80×15
<a href="https://agentmods.dev/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/resource-allocation-optimizer"><img src="https://agentmods.dev/badge/skills/datadrivenconstruction/ddc_skills_for_ai_agents_in_construction/resource-allocation-optimizer.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 30 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 3,415 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe. Third-party audits
  • NVIDIA SkillSpector pass 7 Sept 2026
How audits are shown
Origin original No closer match found in the catalogue.
Token cost

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.

ModelPer sessionOnce invoked
Fable 5.1 $0.00030 $0.03415
Opus 5 $0.00015 $0.01707
Sonnet 5 $0.00006 $0.00683
Haiku 4.5 $0.00003 $0.00342

Measured 9d ago against content hash 8e81e16ce223, method: parsed. Prices are Anthropic first-party input rates as of 2026-09-12, from the pricing page.

Security

Grade A, and why

resource-allocation-optimizer 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 9d 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.

Origin

Copies of this mod

1 near-identical copy found in the catalogue:

3_DDC_Insights/Schedule-Optimization/resource-allocation-optimizer/SKILL.md · 444 lines

How it starts

The opening of the file, as written. The whole thing — 444 lines — stays where its author put it; the contents beside it link to each section on GitHub.

Resource Allocation Optimizer

Overview

Optimize resource allocation in construction schedules. Level workforce and equipment utilization, resolve over-allocations, and balance workload across the project duration.

"Resource leveling reduces peak demand by 30% and improves productivity" — DDC Community

Resource Leveling Concept

Before Leveling:                    After Leveling:
Workers                             Workers
  20│    ████                         15│  ████████████
  15│  ████████                        10│████████████████
  10│████████████                       5│████████████████████
   5│██████████████████                 0└──────────────────────
   0└────────────────────                  Week 1  2  3  4  5  6
      Week 1  2  3  4  5
                                       Peak reduced, duration extended

Technical Implementation

from dataclasses import dataclass, field
from typing import List, Dict, Optional, Tuple
from datetime import datetime, timedelta
from collections import defaultdict
import heapq

@dataclass
class Resource:
    id: str
    name: str
    resource_type: str  # labor, equipment, material
    capacity: float  # units available per day
    cost_per_unit: float = 0.0
    skills: List[str] = field(default_factory=list)

@dataclass
class ResourceAssignment:
    activity_id: str
    resource_id: str
    units: float  # units required per day
    start_day: int
    end_day: int

@dataclass
class Activity:
    id: str
    name: str
    duration: int
    early_start: int
    late_start: int
    total_float: int
    resource_requirements: Dict[str, float] = field(default_factory=dict)
    is_critical: bool = False

@dataclass
class ResourceProfile:
    resource_id: str
    daily_usage: Dict[int, float]  # day -> units used
    peak_usage: float
    average_usage: float
    utilization_rate: float

@dataclass
class LevelingResult:
    original_duration: int
    new_duration: int
    activities_shifted: List[Tuple[str, int, int]]  # (id, old_start, new_start)
    resource_profiles: Dict[str, ResourceProfile]
    peak_reduction: Dict[str, float]

class ResourceOptimizer:
    """Optimize construction resource allocation."""

    def __init__(self):
        self.resources: Dict[str, Resource] = {}
        self.activities: Dict[str, Activity] = {}
        self.assignments: List[ResourceAssignment] = []

    def add_resource(self, id: str, name: str, resource_type: str,
                    capacity: float, cost_per_unit: float = 0.0,
                    skills: List[str] = None) -> Resource:
        """Add resource to pool."""
        resource = Resource(
            id=id,
            name=name,
            resource_type=resource_type,
            capacity=capacity,
            cost_per_unit=cost_per_unit,
            skills=skills or []
        )
        self.resources[id] = resource
        return resource

    def add_activity(self, id: str, name: str, duration: int,
                    early_start: int, late_start: int,
                    resource_requirements: Dict[str, float] = None,
                    is_critical: bool = False) -> Activity:
        """Add activity with resource requirements."""
        activity = Activity(
            id=id,
            name=name,
            duration=duration,
            early_start=early_start,
            late_start=late_start,
            total_float=late_start - early_start,
            resource_requirements=resource_requirements or {},
            is_critical=is_critical
        )
        self.activities[id] = activity

        # Create assignments
        for res_id, units in activity.resource_requirements.items():
            assignment = ResourceAssignment(
                activity_id=id,
                resource_id=res_id,
                units=units,
                start_day=early_start,
                end_day=early_start + duration
            )
            self.assignments.append(assignment)

        return activity

    def calculate_resource_profile(self, resource_id: str,
                                  activity_starts: Dict[str, int] = None) -> ResourceProfile:
        """Calculate daily resource usage profile."""
        if resource_id not in self.resources:
            raise ValueError(f"Resource {resource_id} not found")

        resource = self.resources[resource_id]
        daily_usage = defaultdict(float)

        # Use provided starts or early starts
        starts = activity_starts or {act.id: act.early_start for act in self.activities.values()}

        for assignment in self.assignments:
            if assignment.resource_id != resource_id:
                continue

            act_start = starts.get(assignment.activity_id, assignment.start_day)
            act = self.activities[assignment.activity_id]

            for day in range(act_start, act_start + act.duration):
                daily_usage[day] += assignment.units

        usage_values = list(daily_usage.values()) if daily_usage else [0]
        project_duration = max(daily_usage.keys()) + 1 if daily_usage else 0

        return ResourceProfile(
            resource_id=resource_id,
            daily_usage=dict(daily_usage),
            peak_usage=max(usage_values),
            average_usage=sum(usage_values) / len(usage_values) if usage_values else 0,
            utilization_rate=sum(usage_values) / (project_duration * resource.capacity) if project_duration else 0
        )

    def identify_overallocations(self) -> Dict[str, List[Tuple[int, float]]]:
        """Identify days where resources are over-allocated."""
        overallocations = {}

        for resource in self.resources.values():
            profile = self.calculate_resource_profile(resource.id)
            over_days = [
                (day, usage - resource.capacity)
                for day, usage in profile.daily_usage.items()
                if usage > resource.capacity
            ]
            if over_days:
                overallocations[resource.id] = over_days

        return overallocations

    def level_resources(self, resource_ids: List[str] = None,
                       allow_duration_extension: bool = True,
                       max_extension_days: int = 30) -> LevelingResult:
        """Level resources by shifting non-critical activities."""
        resource_ids = resource_ids or list(self.resources.keys())

        # Store original starts
        original_starts = {act.id: act.early_start for act in self.activities.values()}
        original_duration = max(act.early_start + act.duration for act in self.activities.values())

        # Current activity starts (will be modified)
        current_starts = dict(original_starts)

        # Sort activities by float (most float = most flexibility)
        sorted_activities = sorted(
            [a for a in self.activities.values() if not a.is_critical],
            key=lambda a: -a.total_float
        )

        activities_shifted = []

        # Iteratively resolve overallocations
        for _ in range(100):  # Max iterations
            overallocations = self._check_overallocations(current_starts, resource_ids)

            if not overallocations:
                break

            # Find activity to shift
            shifted = False
            for act in sorted_activities:
                if act.id in [o[0] for o in overallocations]:
                    # Try to shift this activity
                    new_start = self._find_valid_start(
                        act, current_starts, resource_ids,
                        allow_duration_extension, max_extension_days
                    )

                    if new_start is not None and new_start != current_starts[act.id]:
                        old_start = current_starts[act.id]
                        current_starts[act.id] = new_start
                        activities_shifted.append((act.id, old_start, new_start))
                        shifted = True
                        break

            if not shifted:
                break

        # Calculate new duration and profiles
        new_duration = max(
            current_starts[act.id] + act.duration
            for act in self.activities.values()
        )

        resource_profiles = {}
        peak_reduction = {}

        for res_id in resource_ids:
            original_profile = self.calculate_resource_profile(res_id, original_starts)
            new_profile = self.calculate_resource_profile(res_id, current_starts)
            resource_profiles[res_id] = new_profile
            peak_reduction[res_id] = original_profile.peak_usage - new_profile.peak_usage

        return LevelingResult(
            original_duration=original_duration,
            new_duration=new_duration,
            activities_shifted=activities_shifted,
            resource_profiles=resource_profiles,
            peak_reduction=peak_reduction
        )

    def _check_overallocations(self, starts: Dict[str, int],
                               resource_ids: List[str]) -> List[Tuple[str, int, str]]:
        """Check for overallocations with given starts."""
        overallocations = []

        for res_id in resource_ids:
            resource = self.resources[res_id]
            daily_usage = defaultdict(list)

            for assignment in self.assignments:
                if assignment.resource_id != res_id:
                    continue

                act = self.activities[assignment.activity_id]
                act_start = starts[assignment.activity_id]

                for day in range(act_start, act_start + act.duration):
                    daily_usage[day].append((assignment.activity_id, assignment.units))

            for day, activities in daily_usage.items():
                total = sum(units for _, units in activities)
                if total > resource.capacity:
                    for act_id, _ in activities:
                        overallocations.append((act_id, day, res_id))

        return overallocations

    def _find_valid_start(self, activity: Activity, current_starts: Dict[str, int],
                         resource_ids: List[str], allow_extension: bool,
                         max_extension: int) -> Optional[int]:
        """Find valid start day that doesn't cause overallocation."""
        min_start = activity.early_start
        max_start = activity.late_start if not allow_extension else activity.late_start + max_extension

        for start in range(min_start, max_start + 1):
            # Check if this start causes overallocation
            test_starts = dict(current_starts)
            test_starts[activity.id] = start

            overallocations = self._check_overallocations(test_starts, resource_ids)
            activity_over = [o for o in overallocations if o[0] == activity.id]

            if not activity_over:
                return start

        return None

    def optimize_for_cost(self, target_duration: int = None) -> Dict:
        """Optimize resource allocation for minimum cost."""
        # Calculate baseline cost
        baseline_cost = self._calculate_total_cost()

        # Try different allocation strategies
        strategies = []

        # Strategy 1: Minimize overtime
        overtime_result = self._minimize_overtime()
        strategies.append({
            "strategy": "Minimize Overtime",
            "cost": overtime_result["cost"],
            "duration": overtime_result["duration"]
        })

        # Strategy 2: Level resources
        level_result = self.level_resources()
        level_cost = self._calculate_total_cost(
            {act.id: act.early_start for act in self.activities.values()}
        )
        strategies.append({
            "strategy": "Level Resources",
            "cost": level_cost,
            "duration": level_result.new_duration
        })

        return {
            "baseline_cost": baseline_cost,
            "strategies": strategies,
            "recommended": min(strategies, key=lambda s: s["cost"])
        }

    def _calculate_total_cost(self, starts: Dict[str, int] = None) -> float:
        """Calculate total resource cost."""
        starts = starts or {act.id: act.early_start for act in self.activities.values()}
        total_cost = 0.0

        for res_id, resource in self.resources.items():
            profile = self.calculate_resource_profile(res_id, starts)

            for day, usage in profile.daily_usage.items():
                # Regular cost
                regular_units = min(usage, resource.capacity)
                total_cost += regular_units * resource.cost_per_unit

                # Overtime cost (1.5x)
                overtime_units = max(0, usage - resource.capacity)
                total_cost += overtime_units * resource.cost_per_unit * 1.5

        return total_cost

    def _minimize_overtime(self) -> Dict:
        """Minimize overtime by resource leveling."""
        result = self.level_resources(allow_duration_extension=True)
        cost = self._calculate_total_cost(
            {act.id: act.early_start for act in self.activities.values()}
        )
        return {"cost": cost, "duration": result.new_duration}

    def generate_resource_histogram(self, resource_id: str,
                                   starts: Dict[str, int] = None) -> str:
        """Generate ASCII histogram of resource usage."""
        profile = self.calculate_resource_profile(resource_id, starts)
        resource = self.resources[resource_id]

        if not profile.daily_usage:
            return "No usage data"

        max_day = max(profile.daily_usage.keys())
        max_usage = max(profile.daily_usage.values())

        lines = [
            f"# Resource Histogram: {resource.name}",
            f"Capacity: {resource.capacity} | Peak: {profile.peak_usage}",
            ""
        ]

        # Scale for display
        scale = 20 / max_usage if max_usage > 0 else 1

        for day in range(max_day + 1):
            usage = profile.daily_usage.get(day, 0)
            bar_len = int(usage * scale)
            over = "!" if usage > resource.capacity else " "
            lines.append(f"Day {day:3d}: {'█' * bar_len}{over} ({usage:.1f})")

        return "\n".join(lines)

Read the full file on GitHub · 444 lines

Files

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.

Changes

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.

  1. 9d ago First seen · 444 lines · 30 tokens per session scan A 8e81e16ce223

Subscribe to this mod's changes

resource-allocation-optimizer is a skill published in the GitHub repository datadrivenconstruction/DDC_Skills_for_AI_Agents_in_Construction (312 stars, last pushed 21d ago), licensed MIT. It adds 30 tokens to every session and 3,415 once invoked, about $0.0002 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.

Related

Other skills, from other repositories

catchup

Summarize and review what changed while you were away. Use after a weekend, vacation, or flight to check missed PRs, git commits, Linear tickets, and meetings — one prioritized brief, not a firehose.

oliver-kriska/claude-elixir-phoenix · 48 tokens

plan

Plan features spanning multiple domains: billing (Stripe), auth (RBAC), real-time (Presence), webhooks, jobs (Oban). Use when designing interconnected systems or converting review findings into tasks.

oliver-kriska/claude-elixir-phoenix · 42 tokens

work

Execute Elixir/Phoenix plan tasks with progress tracking. Use after /phx:plan to implement features with mix compile and mix test verification after each step, or --continue to resume interrupted work.

oliver-kriska/claude-elixir-phoenix · 43 tokens

phx-deps-update

Bump outdated Hex deps — inventory, snapshot changelogs, update, fix breaks, split reviewable PRs (patches bundled, majors solo). Use to upgrade/bump Elixir dependencies or when versions fall behind. NOT for deps.get failures (phx-investigate).

oliver-kriska/claude-elixir-phoenix · 62 tokens

timeline-creator

Create HTML timelines and project roadmaps with Gantt charts, milestones, phase groupings, and progress indicators. Use when users request timelines, roadmaps, Gantt charts, project schedules, or milestone visualizations.

mhattingpete/claude-skills-marketplace · 47 tokens

project-health

All-in-one project configuration and health management. Sets up new projects (settings.local.json, CLAUDE.md, .gitignore), audits existing projects (permissions, context quality, MCP coverage, leaked secrets, stale docs), tidies accumulated cruft, captures session learnings, and adds permission presets. Uses…

jezweb/claude-skills · 126 tokens