Applied Module 12 · The Nick E. Playbook

Vendor & Make-Ready Orchestrator

What you'll learn

~45 min
  • Model make-ready workflows as dependency chains (paint, clean, repair, QA)
  • Auto-schedule vendor tasks from move-out dates and target move-in dates
  • Detect bottlenecks, missed handoffs, and SLA breaches with visual alerts
  • Export ICS calendar files for vendor/team coordination

What you’re building

Unit turns are the most operationally complex task in property management. When a resident moves out, the apartment has to go through a defined sequence of work before the next resident can move in: inspect, paint, clean, repair, final QA. Each step depends on the one before it. Painters cannot start until the inspection is done. Cleaners cannot start until painters finish. The final inspection cannot happen until everything else is complete. And every day the unit sits empty is lost rent.

At The Concord Crystal City, the average unit rents for $2,500/month. That is roughly $82/day. If a unit turn takes 10 days instead of 7, that is $246 in lost revenue — per unit. In a busy turnover month, The Concord might have 15-20 units turning simultaneously. If each one runs 3 days over schedule because a vendor missed their window or a handoff fell through the cracks, that is $3,700-4,900 in avoidable vacancy loss. In a single month.

Right now, Nick’s maintenance team tracks make-readies on a whiteboard and a shared spreadsheet. Vendor scheduling happens over text messages and phone calls. There is no dependency logic — if the painting vendor finishes early, nobody tells the cleaning crew to come sooner. If a vendor is late, nobody knows until the next team shows up and finds the unit is not ready for them.

You are going to build a tool that models every unit turn as a dependency graph, auto-schedules vendor tasks based on move-out dates and target move-in dates, tracks progress with a visual Kanban board, alerts on SLA breaches and bottlenecks, calculates vacancy cost in real time, and exports ICS calendar files so every vendor has the schedule on their phone.

💬Every day counts -- literally

Bozzuto (The Concord’s management company) tracks a metric called “days to turn.” The industry benchmark for Class A luxury is 5-7 days. Every day beyond that target is a dollar figure your regional manager sees on a report. A tool that shaves even 1 day off average turn time across 150+ annual turnovers saves the community $12,000-15,000 per year in vacancy cost alone — and that does not count the reputational benefit of having units ready on time for new residents.

Software pattern: Dependency graph scheduling with constraint propagation

Model tasks as nodes in a directed acyclic graph (DAG) where edges represent dependencies. Calculate earliest start times by forward-propagating durations from the start node. Calculate latest start times by backward-propagating from the deadline. The difference (slack) identifies the critical path — tasks with zero slack are bottlenecks. This is the same algorithm used in project scheduling (CPM/PERT), CI/CD pipelines, and manufacturing workflow planning.

🔍Property management primer: Unit turns and vacancy cost

If you are new to property management, here are the concepts behind this lesson:

  • Unit turn / make-ready: The process of preparing a vacated apartment for a new resident. It starts when the old resident hands over keys and ends when the new resident can move in. The work typically includes inspection, painting, deep cleaning, repairs (appliances, fixtures, flooring), and a final quality check.
  • Dependency chain: Each make-ready task must happen in a specific order. You cannot clean a unit that has not been painted (the paint dust would undo the cleaning). You cannot do a final inspection until all other work is complete. This ordering creates a chain of dependencies.
  • Vacancy cost: Every day a unit is empty, the community loses that day’s rent. For a $2,500/month unit, that is ~$82/day. This is why turn speed matters — it is directly measurable in dollars.
  • Vendor scheduling: Most properties use third-party vendors for painting, carpet cleaning, and specialized repairs. These vendors serve multiple communities and have limited availability. Getting them scheduled into the right window is a coordination challenge.
  • SLA (Service Level Agreement): A target completion time for each task. For example, painting should take no more than 2 days. If the painter takes 3, that is an SLA breach that delays every downstream task.
  • ICS file: A standard calendar format (.ics) that can be imported into Google Calendar, Outlook, Apple Calendar, or any calendar app. Sending a vendor an ICS file with their scheduled window means the appointment is on their phone automatically.
  • Critical path: The longest chain of dependent tasks through the workflow. Any delay on the critical path delays the entire turn. Tasks not on the critical path have “slack” — they can slip without affecting the overall timeline.

Who this is for

Nick coordinates make-readies at The Concord Crystal City. His maintenance supervisor manages the on-site team (inspect, punch list, final QA) while three external vendors handle painting, cleaning, and carpet/flooring. Scheduling happens through a mix of phone calls, text messages, and a shared Google Sheet that is always out of date. When a vendor is late, Nick finds out when the next vendor shows up and calls him. By then, the unit is already a day behind.

Nick wants a tool where he enters move-out dates and target move-in dates, and the system tells him exactly when each vendor needs to be on-site, flags any scheduling conflicts, and sends calendar invites to each vendor with their specific window.


The showcase

When finished, your tool will:

  • Define make-ready workflows as configurable dependency chains with task durations and SLA targets:
    • Inspect (0.5 day) -> Paint (2 days) -> Clean (1 day) -> Repair (1 day) -> Final QA (0.5 day)
    • Total critical path: 5 days
    • Some tasks can run in parallel (repair and clean can overlap after paint if configured)
  • Accept a batch of units with move-out dates, target move-in dates, and unit-specific notes
  • Auto-schedule every task using forward propagation from the move-out date:
    • Calculate earliest start and earliest finish for each task
    • Backward-propagate from the target move-in date to find slack
    • Flag units where the critical path exceeds the available window
  • Generate an HTML Kanban board showing all active units across columns:
    • Vacant -> Inspected -> Painted -> Cleaned -> Repaired -> QA’d -> Ready
    • Each card shows: unit number, floor, days vacant, vacancy cost so far, current task assignee, SLA status (green/yellow/red)
    • Filter by floor, vendor, or SLA status
  • Track SLA breaches with countdown timers:
    • Each task has a target duration; when exceeded, the card turns red
    • Dashboard banner shows total SLA breaches and total vacancy cost across all active turns
  • Export ICS calendar files per vendor:
    • One .ics file per vendor containing all their scheduled tasks across all active units
    • Each calendar event includes: unit number, task description, start time, end time, property address
    • Vendor can import the file into any calendar app
  • Calculate vacancy cost per unit in real time:
    • Days vacant x daily rent = running cost
    • Dashboard total shows aggregate vacancy cost across all active turns
  • Multi-unit parallel tracking: handle 15-20 simultaneous turns on one dashboard

The prompt

Open your AI CLI tool in an empty directory and paste this prompt:

Build a Node.js CLI tool for managing apartment unit turn (make-ready)
workflows with dependency scheduling, vendor coordination, and visual
tracking. Use a structured project layout.
PROJECT STRUCTURE:
make-ready/
package.json
src/
cli.js (entry point, argument parsing)
workflow/
template.js (default make-ready workflow definition)
scheduler.js (dependency-aware task scheduling, CPM)
critical-path.js (critical path and slack calculation)
units/
parser.js (parse unit turn CSV input)
tracker.js (unit status tracking and updates)
vendors/
calendar.js (vendor availability and assignment)
ics-export.js (ICS calendar file generation per vendor)
output/
kanban.js (HTML Kanban board generation)
dashboard.js (summary dashboard with SLA and cost tracking)
alerts.js (SLA breach detection and alerting)
cost/
vacancy-calculator.js (daily vacancy cost per unit)
sample-data.js (generate realistic sample input)
templates/
kanban.ejs (Kanban board HTML template)
dashboard.ejs (summary dashboard HTML template)
vendor-schedule.ejs (per-vendor schedule printout)
config/
workflow.json (configurable workflow definition)
vendors.json (vendor list with contact info)
REQUIREMENTS:
1. CLI INTERFACE (src/cli.js)
- Usage: node src/cli.js [options]
- --units or -u: path to units CSV (required unless --generate-sample)
- --workflow or -w: path to workflow JSON (default: config/workflow.json)
- --vendors or -v: path to vendors JSON (default: config/vendors.json)
- --output or -o: output directory (default: ./make-ready-output)
- --date or -d: reference date (default: today)
- --generate-sample: generate sample input files
2. WORKFLOW DEFINITION (config/workflow.json)
Configurable dependency graph:
{
"name": "Standard Make-Ready",
"tasks": [
{
"id": "inspect",
"name": "Move-Out Inspection",
"duration_days": 0.5,
"sla_days": 1,
"assignee_type": "maintenance",
"dependencies": [],
"description": "Document unit condition, create punch list"
},
{
"id": "paint",
"name": "Paint",
"duration_days": 2,
"sla_days": 2.5,
"assignee_type": "vendor_paint",
"dependencies": ["inspect"],
"description": "Full paint including walls, trim, touch-up"
},
{
"id": "carpet",
"name": "Carpet Clean / Replace",
"duration_days": 1,
"sla_days": 1.5,
"assignee_type": "vendor_carpet",
"dependencies": ["paint"],
"description": "Professional carpet cleaning or replacement"
},
{
"id": "clean",
"name": "Deep Clean",
"duration_days": 1,
"sla_days": 1.5,
"assignee_type": "vendor_clean",
"dependencies": ["paint"],
"description": "Full unit deep clean including kitchen, bath, appliances"
},
{
"id": "repair",
"name": "Repairs & Appliances",
"duration_days": 1,
"sla_days": 2,
"assignee_type": "maintenance",
"dependencies": ["inspect"],
"description": "Fix punch list items, replace filters, test appliances"
},
{
"id": "final_qa",
"name": "Final QA Inspection",
"duration_days": 0.5,
"sla_days": 0.5,
"assignee_type": "maintenance",
"dependencies": ["carpet", "clean", "repair"],
"description": "Final walkthrough, photo documentation, approve for move-in"
}
]
}
Note: carpet and clean both depend on paint but are independent of
each other (can run in parallel). Repair depends only on inspect
(can run in parallel with paint). Final QA depends on carpet, clean,
AND repair all being complete.
3. SCHEDULER (src/workflow/scheduler.js)
- Implement forward-pass scheduling (Critical Path Method):
- Earliest Start (ES) = max(earliest finish of all dependencies)
- Earliest Finish (EF) = ES + duration
- Implement backward-pass scheduling:
- Latest Finish (LF) = min(latest start of all dependents),
or target move-in date for terminal tasks
- Latest Start (LS) = LF - duration
- Calculate slack: LS - ES for each task
- Identify critical path: tasks with zero slack
- If critical path duration > available window (move-out to move-in),
flag the unit as "INFEASIBLE" with the number of days over
4. UNIT INPUT (CSV format)
Columns: unit_number, floor, bedrooms, monthly_rent, move_out_date,
target_move_in_date, notes
- Parse dates flexibly (YYYY-MM-DD, MM/DD/YYYY)
- Calculate available window in days
- Flag units where window < critical path duration
5. VENDOR MANAGEMENT (config/vendors.json)
{
"vendors": [
{
"id": "vendor_paint",
"name": "ProCoat Painting",
"contact": "Mike Rivera",
"phone": "703-555-0142",
"email": "mike@procoatpainting.com",
"max_concurrent_units": 3,
"blackout_dates": ["2026-03-20", "2026-03-21"]
},
{
"id": "vendor_carpet",
"name": "Capital Carpet Care",
"contact": "Denise Park",
"phone": "703-555-0198",
"email": "denise@capitalcarpet.com",
"max_concurrent_units": 2,
"blackout_dates": []
},
{
"id": "vendor_clean",
"name": "Sparkle Clean DMV",
"contact": "Luis Morales",
"phone": "703-555-0267",
"email": "luis@sparklecleandmv.com",
"max_concurrent_units": 4,
"blackout_dates": []
}
],
"internal_team": {
"id": "maintenance",
"name": "Concord Maintenance Team",
"max_concurrent_units": 5
}
}
- Respect max_concurrent_units: if a vendor is already at capacity
for a given day, push the task to the next available day
- Respect blackout_dates: do not schedule tasks on these dates
- When a task is pushed due to capacity or blackout, cascade the
delay to all downstream dependent tasks
6. KANBAN BOARD (src/output/kanban.js)
Generate a single HTML file with an interactive Kanban board:
- Columns: Vacant | Inspected | Painted | Cleaned/Carpeted | Repaired
| QA Passed | Ready
- Each unit is a card that moves through columns based on completed tasks
- Card contents:
- Unit number and floor (bold)
- Days vacant (with color: green <= 5, yellow 6-7, red > 7)
- Vacancy cost so far: "$XXX lost" in red if > $0
- Current task and assignee
- SLA status badge: green (on track), yellow (< 1 day slack),
red (SLA breached)
- Mini progress bar showing completed vs remaining tasks
- Top summary bar: total active turns, on-track count, at-risk count,
breached count, total vacancy cost
- Filter buttons: by floor, by vendor, by SLA status
- Dark theme: bg #0f172a, cards #1e293b, text #e2e8f0, accent green
#10b981, warning yellow #f59e0b, breach red #ef4444
7. ICS CALENDAR EXPORT (src/vendors/ics-export.js)
- Generate one .ics file per vendor
- Each event:
- SUMMARY: "Make-Ready: Unit [number] - [task name]"
- DTSTART/DTEND: scheduled start and end times
(use 8:00 AM start, calculate end from duration)
- LOCATION: "The Concord Crystal City, 1201 S Clark St, Arlington VA"
- DESCRIPTION: task description + unit notes + contact info for
on-site maintenance
- Follow RFC 5545 format strictly (VCALENDAR, VEVENT, proper line
folding, UTC timestamps)
- File naming: [vendor-name]-schedule.ics
8. VACANCY COST CALCULATOR (src/cost/vacancy-calculator.js)
- Daily cost = monthly_rent / 30
- Running cost = days_vacant * daily_cost
- Include in each unit card and in the dashboard summary
- Project total cost if all active turns complete on schedule
vs. if current SLA breaches continue
9. ALERTS (src/output/alerts.js)
- SLA breach: task duration exceeds sla_days
- Scheduling conflict: vendor at max capacity, task pushed
- Infeasible window: critical path > available days
- Missed handoff: dependency not met, downstream task cannot start
- Each alert includes: unit, task, severity (warning/critical),
description, recommended action
10. SAMPLE DATA GENERATOR (src/sample-data.js)
When --generate-sample is passed, create:
- sample-units.csv: 12 units with move-out dates spread over the
next 3 weeks, varying bedroom counts and rents ($2,100-$3,800)
- Plant scenarios:
- Unit 0715: tight window (5 days), should be feasible but no slack
- Unit 1203: infeasible window (3 days for a 5-day workflow)
- Unit 0918: move-out today, vendor_paint has blackout tomorrow
- 3 units with overlapping paint schedules to trigger capacity limits
- Use the default workflow.json and vendors.json
DEPENDENCIES: commander, csv-parser, ejs, dayjs, chalk, uuid
(uuid for ICS event UIDs)
💡The workflow is configurable

The workflow.json file defines the entire make-ready process. If The Concord adds a step (like a pre-paint drywall repair for certain units), Nick adds one entry to the JSON file. If a task’s typical duration changes, he updates the number. The tool re-calculates the critical path automatically. No code changes needed.


What you get

After your AI CLI tool finishes, you will have a project folder:

make-ready/
package.json
src/
cli.js
workflow/
template.js
scheduler.js
critical-path.js
units/
parser.js
tracker.js
vendors/
calendar.js
ics-export.js
output/
kanban.js
dashboard.js
alerts.js
cost/
vacancy-calculator.js
sample-data.js
templates/
kanban.ejs
dashboard.ejs
vendor-schedule.ejs
config/
workflow.json
vendors.json

Set it up

Terminal window
cd make-ready
npm install

Try it with sample data first

Terminal window
node src/cli.js --generate-sample -o ./test-output

This creates sample-units.csv in ./test-output/ along with the default config files. Now run the scheduler:

Terminal window
node src/cli.js \
-u ./test-output/sample-units.csv \
-o ./test-output

Open ./test-output/kanban.html in your browser. You should see:

  • 12 unit cards distributed across Kanban columns based on their scheduled progress
  • Unit 0715 with a yellow SLA badge (tight window, no slack)
  • Unit 1203 flagged red as “INFEASIBLE” (3-day window for a 5-day workflow)
  • Unit 0918 with a scheduling alert (vendor paint pushed due to blackout date)
  • 3 units showing capacity-related schedule adjustments where the painting vendor hit their concurrent limit
  • Top summary bar showing total vacancy cost across all active turns

Check ./test-output/calendars/ for the ICS files:

calendars/
ProCoat-Painting-schedule.ics
Capital-Carpet-Care-schedule.ics
Sparkle-Clean-DMV-schedule.ics
Concord-Maintenance-schedule.ics

Open one in your calendar app to verify the events appear correctly with unit numbers, times, and the property address.

Common issues and fixes

ProblemFollow-up prompt
ICS files not importing into Google CalendarGoogle Calendar is rejecting the ICS file. Make sure the file starts with BEGIN:VCALENDAR, uses CRLF line endings (\\r\\n, not just \\n), includes PRODID and VERSION:2.0 headers, and each event has a unique UID. Timestamps should be in UTC format: DTSTART:20260315T120000Z.
Scheduler puts all tasks on the same dayThe scheduler is not respecting task durations. Each task's earliest start should be the maximum earliest-finish of all its dependencies. Make sure duration_days is added to the start date using dayjs.add(duration, 'day'). A 2-day task starting on Monday finishes on Wednesday, not Monday.
Vendor capacity is not enforcedThe painting vendor is scheduled for 5 units on the same day but max_concurrent_units is 3. After scheduling each task, check the vendor's load for that date range. If at capacity, push the task to the next available date where the vendor has an open slot. Then re-cascade all downstream dependencies.
Kanban board shows all units in the Vacant columnThe unit tracker is not advancing cards based on the schedule. Each unit should be placed in the column corresponding to its last completed task based on the reference date (--date). If the scheduled paint finish date is before the reference date, the unit should be in the 'Painted' column.

When things go wrong

Make-ready scheduling involves date math, dependency logic, and capacity constraints — three areas where edge cases cause the most trouble.

🔧

When Things Go Wrong

Use the Symptom → Evidence → Request pattern: describe what you see, paste the error, then ask for a fix.

Symptom
Critical path calculation returns the wrong total duration
Evidence
The workflow has 5 tasks totaling 5 days on the critical path, but the scheduler says the critical path is 7 days. Some tasks that should run in parallel are being scheduled sequentially.
What to ask the AI
"The critical path calculation is treating parallel tasks as sequential. In the workflow, 'clean' and 'carpet' both depend on 'paint' but not on each other -- they should run in parallel. 'repair' depends only on 'inspect' and should run in parallel with 'paint'. The forward pass must calculate ES = max(EF of dependencies), not sum of all predecessors. Check that the dependency graph correctly identifies which tasks can overlap."
Symptom
Vendor blackout dates cause an infinite scheduling loop
Evidence
The CLI hangs when scheduling Unit 0918 because the painting vendor has blackout dates on the only available days. The process runs for minutes without producing output.
What to ask the AI
"The scheduler enters an infinite loop when a vendor's blackout dates cover the entire available window. Add a maximum retry limit (30 days). If a task cannot be scheduled within 30 days of its earliest start, mark it as UNSCHEDULABLE with a clear error message suggesting the property manager contact the vendor directly or assign a different vendor."
Symptom
ICS events show wrong timezone -- all appointments are 4 hours off
Evidence
The ICS file shows a paint task starting at 12:00 PM UTC but it should be 8:00 AM Eastern. When imported into Google Calendar (set to Eastern Time), the event shows at noon instead of 8 AM.
What to ask the AI
"The ICS timestamps need to account for the timezone correctly. Either use TZID=America/New_York with local times (DTSTART;TZID=America/New_York:20260315T080000) or convert 8:00 AM Eastern to UTC (DTSTART:20260315T120000Z for EDT, or T130000Z for EST). Include a VTIMEZONE component in the VCALENDAR if using TZID. Eastern Daylight Time is UTC-4; Eastern Standard Time is UTC-5."
Symptom
Vacancy cost shows negative numbers for some units
Evidence
Unit 0401 shows '-$164 lost' on the Kanban card. The unit has not moved out yet -- the move-out date is in the future.
What to ask the AI
"The vacancy cost calculator is computing cost for units that have not yet vacated. Only calculate vacancy cost when the move-out date is on or before the reference date (--date). For future move-outs, show 'Scheduled' instead of a cost figure. Add a check: if move_out_date > reference_date, skip the cost calculation."
Symptom
Dashboard shows 0 active turns even though the CSV has 12 units
Evidence
The summary bar says 'Active Turns: 0' and the Kanban board is empty. The CSV is parsed correctly (I can see log output with 12 units).
What to ask the AI
"The tracker is filtering out all units because it only considers units where move_out_date <= reference_date. But some units in the sample data have future move-out dates for scheduling purposes. Show ALL units from the CSV on the dashboard. Units with future move-outs should appear in a 'Scheduled' column before the 'Vacant' column. Only calculate vacancy cost and SLA tracking for units that have already vacated."

How it works

The scheduling engine uses the Critical Path Method (CPM), the same algorithm used in construction project management, manufacturing, and software build systems.

Forward pass. Starting from the first task (inspect), calculate the Earliest Start (ES) and Earliest Finish (EF) for every task. A task’s ES is the maximum EF of all its dependencies. The EF is ES + duration. This gives you the earliest possible completion date for the entire workflow.

Backward pass. Starting from the target move-in date, work backward. Each task’s Latest Finish (LF) is the minimum Latest Start of all tasks that depend on it. The Latest Start (LS) is LF - duration. This gives you the latest each task can start without pushing the move-in date.

Slack. For each task, slack = LS - ES. Tasks with zero slack form the critical path — any delay on these tasks delays the entire turn. Tasks with positive slack have wiggle room.

Vendor constraints. After the initial schedule is calculated, the vendor calendar layer checks capacity. If a vendor is at max_concurrent_units for a given date range, the task is pushed to the next available slot. This triggers a re-cascade: all downstream dependencies are re-scheduled from the new finish date. The critical path is recalculated after every constraint adjustment.

Example for Unit 0715 (move-out: Mar 10, target move-in: Mar 15, 5-day window):
inspect [Mar 10 ----] (0.5 day) ES=0 EF=0.5 Slack=0
paint [Mar 10.5 --------] (2 days) ES=0.5 EF=2.5 Slack=0
carpet [Mar 12.5 ----] (1 day) ES=2.5 EF=3.5 Slack=0.5
clean [Mar 12.5 ----] (1 day) ES=2.5 EF=3.5 Slack=0.5
repair [Mar 10.5 ----] (1 day) ES=0.5 EF=1.5 Slack=2.5
final_qa [Mar 13.5 --] (0.5 day) ES=3.5 EF=4 Slack=1
Critical path: inspect -> paint -> carpet/clean -> final_qa (4 days)
Window: 5 days. Slack on critical path: 1 day.

In this example, the repair task has 2.5 days of slack because it only depends on inspect and does not gate the critical path. The painting task is the bottleneck — any delay to painting delays everything downstream.

🔍Why dependency graphs, not just a list of tasks

A flat task list with deadlines misses the relationships. If painting runs 1 day late, a flat list does not tell you that cleaning, carpeting, AND final QA are all now delayed. A dependency graph propagates that delay automatically and shows you exactly how it affects the move-in date.

This is the same reason CI/CD pipelines use DAGs (directed acyclic graphs) instead of sequential steps. Build, test, and deploy are not independent — they have dependency relationships. Make-ready workflows are the same concept applied to physical operations.

The CPM algorithm was invented in the 1950s for construction scheduling. It is still the foundation of every project scheduling tool from Microsoft Project to Primavera. Understanding it at the code level — forward pass, backward pass, slack, critical path — gives you deeper insight than any drag-and-drop Gantt tool can provide.


Customize it

Add progress updates via CLI

Add an --update flag that accepts a unit number and task ID to mark a task as
complete. Example: node src/cli.js --update 0715:paint
This should:
- Record the actual completion date (today)
- Compare actual vs. scheduled duration
- If the task finished early, recalculate downstream tasks to pull in
- If the task finished late, recalculate downstream tasks to push out
- Regenerate the Kanban board and dashboard with updated status
- Store progress in a local JSON file (make-ready-state.json) so state
persists between runs

Add vendor performance tracking

Add a "Vendor Scorecard" section to the dashboard. For each vendor, show:
- Total tasks assigned this month
- Average actual duration vs. SLA target
- SLA breach rate (percentage of tasks that exceeded SLA)
- On-time completion rate
- Trend over the last 3 months (requires historical data from --history flag)
This helps Nick decide which vendors to keep and which to replace.

Add photo documentation integration

Add a --photos flag that accepts a directory of unit photos organized by
unit number (e.g., photos/0715/inspect/*.jpg). For each unit on the Kanban
board, add a thumbnail gallery showing before/after photos per task phase.
The final QA card should show a side-by-side comparison of the move-out
inspection photos and the final QA photos.

Add cost-per-turn reporting

Add a "Turn Cost Analysis" section to the dashboard. For each completed unit
turn, calculate total cost:
- Vacancy cost (days vacant x daily rent)
- Vendor cost (accept a vendor-costs CSV with unit, vendor, amount)
- Internal labor estimate (hours x $35/hour blended rate)
- Total cost per turn
Show average cost per turn, cost by bedroom type, and identify which
expense category has the most variance. This gives Nick data for budget
forecasting and vendor negotiations.

Try it yourself

  1. Open your AI CLI tool in an empty folder.
  2. Paste the main prompt.
  3. Run npm install in the generated make-ready/ directory.
  4. Generate sample data with --generate-sample and run the scheduler.
  5. Open the Kanban board and verify:
    • Unit 0715 shows tight but feasible scheduling (yellow SLA badge)
    • Unit 1203 is flagged as infeasible (red)
    • Unit 0918 shows the vendor blackout delay
    • The capacity-constrained units show adjusted schedules
  6. Open the ICS files in your calendar app — do the events make sense?
  7. Check the vacancy cost totals — does the math add up (days vacant x daily rent)?
  8. Modify config/workflow.json to add a new task (e.g., “HVAC filter replacement” between repair and final_qa) and re-run. The scheduler should automatically recalculate the critical path.
  9. Pick one customization from the list above and add it with a follow-up prompt.

Key takeaways

  • Unit turns are a scheduling problem, not just a checklist. The dependency relationships between tasks determine the minimum turn time. A flat task list misses these relationships and cannot detect bottlenecks or propagate delays.
  • Every day of vacancy has a dollar value. At $82/day per unit, the financial impact of slow turns is concrete and measurable. Showing vacancy cost on the Kanban board makes the urgency visible to everyone on the team.
  • Vendor capacity is the hidden constraint. A schedule that looks perfect on paper breaks down when the painting vendor can only handle 3 units at once. Capacity-aware scheduling prevents the “scheduled but not actually available” problem that causes missed handoffs.
  • ICS calendar files close the communication loop. Sending a vendor a text saying “Can you come Tuesday?” starts a back-and-forth negotiation. Sending them an ICS file with the exact window, unit number, and property address puts the appointment directly on their phone.
  • The critical path identifies where to focus. When 15 units are turning simultaneously, you cannot watch everything. The critical path tells you which tasks have zero slack — those are the ones where a delay costs real money. Everything else has buffer.

KNOWLEDGE CHECK

Your Kanban dashboard shows Unit 0715 with a 5-day window (move-out March 10, target move-in March 15). The painting vendor is 1 day late -- they finish on March 13 instead of March 12.5. Carpet and cleaning both depend on paint. Final QA depends on carpet, clean, and repair. What happens to the move-in date?


What’s next

You have now built tools that cover the two highest-impact operational workflows at a luxury apartment community: retention (Lesson 3, renewal risk scoring and outreach) and turnover execution (Lesson 4, make-ready scheduling and vendor coordination). Together, these tools address both sides of the occupancy equation — keeping the residents you have and efficiently preparing units for the ones you need.