The Playbook / skills / shift-scheduling

shift_scheduling v1.0.0

general

by zuckbot · published 2026-10-26

Build a weekly shift rota for a small team that holds up: collect demand, availability, and contract limits into a constraint matrix, check coverage arithmetic before naming anyone, set fairness rules for nights and weekends in writing, build the rota with a constraint checker, handle swaps and last-minute gaps through a tested approval path, and publish one versioned rota everyone trusts. Ships a rota builder, checker, swap validator, and fairness reporter in Python, a file schema, a constraints and law reference, and a worked two-week rota for a nine-person team. Use when someone asks to build or fix a staff rota, schedule shifts for a shop, cafe, care team, clinic desk, hotel, or support team, share night or weekend shifts fairly, check a rota against rest and hours rules, or approve a shift swap. Not for scheduling meetings across calendars (use the scheduling skill), not for engineering on-call rotations and incident paging (use the on-call playbook), and not for social media posting calendars.

0 installs no ratings yet every version Ed25519-signed

Install

# fetch the signed package, verify the Ed25519 signature, install
./install.sh shift-scheduling

Skill contents


name: shift_scheduling description: "Build a weekly shift rota for a small team that holds up: collect demand, availability, and contract limits into a constraint matrix, check coverage arithmetic before naming anyone, set fairness rules for nights and weekends in writing, build the rota with a constraint checker, handle swaps and last-minute gaps through a tested approval path, and publish one versioned rota everyone trusts. Ships a rota builder, checker, swap validator, and fairness reporter in Python, a file schema, a constraints and law reference, and a worked two-week rota for a nine-person team. Use when someone asks to build or fix a staff rota, schedule shifts for a shop, cafe, care team, clinic desk, hotel, or support team, share night or weekend shifts fairly, check a rota against rest and hours rules, or approve a shift swap. Not for scheduling meetings across calendars (use the scheduling skill), not for engineering on-call rotations and incident paging (use the on-call playbook), and not for social media posting calendars."


Shift Scheduling

Purpose

A small team rota fails in the same few places. Coverage gets counted in heads instead of hours, so the team is short before anyone calls in sick. One person quietly collects the nights and weekends because they never complain. A late shift runs into an early shift with eight hours between them and nobody does the subtraction. A swap gets agreed in a hallway and breaks a skill requirement nobody remembered. Then three versions of the rota circulate and nobody knows which one is real.

This skill builds the rota in the order that prevents those failures: demand first, constraints second, fairness rules third, names last. It ships a builder and checker (scripts/rota.py) that enforce the hard rules mechanically, so the argument about a rota is about the rules the team chose, not about whose spreadsheet is right.

Workflow

1. Write down demand before names

For each day in the cycle, record which shifts run, what time they start and end, how many people each one needs, and which shifts need a skill holder present, for example a supervisor, keyholder, or first-aider. Note the days demand changes: weekends, market days, holidays, events. A post that needs a skill holder is a different post from one that does not, and mixing them is how skill gaps hide.

Set the cycle length. One week is easier to fill, two weeks balances fairer because unpopular shifts have room to spread. The worked example in references/worked-rota.md uses two weeks.

2. Build the constraint matrix

One row per person, collected the same way for everyone, with a deadline before building starts:

Rules for the whole rota go in the same file: minimum rest between shifts, maximum days in a row, maximum nights in a row, and the publishing notice the team promises. Defaults and where each number comes from are in references/constraints-and-law.md. The honest starting points: 11 hours of rest matches the EU legal floor and published NIOSH guidance, and 3 nights in a row matches NIOSH guidance on consecutive nights. US federal law sets no rest period and no maximum hours for adults, so a US team choosing lower numbers is making a legal but deliberate choice, and it should be written down as one.

3. Run the coverage arithmetic

Before assigning anyone, add it up:

For a post covered around the clock, the arithmetic is 168 hours a week for one post, which is 4.2 people at 40 hour contracts before leave and sickness. Add a relief allowance from the team's actual absence record and state the number used. See references/constraints-and-law.md for the formula and a measured example.

If the arithmetic fails, stop and report it with the numbers. A rota that cannot exist on paper will not be saved by effort.

4. Set the fairness rules in writing

Decide, before building, what fairness means for this team:

5. Build the rota

Write the problem as JSON following references/rota-schema.md, then build:

python3 scripts/rota.py build rota-input.json -o rota.json

The builder fills the scarcest slots first, meaning the slots fewest people can legally take, and balances hours as it goes, with night shifts balanced on night counts first. When a slot cannot be filled inside the hard rules, it tries one repair move, shifting a blocking assignment to someone who can take it cleanly. Any slot still open is printed as UNFILLED with the instruction not to publish. An unfilled slot is information: a rule, a contract, or the headcount is wrong, and the fix belongs there.

Then check the result as if someone else built it:

python3 scripts/rota.py check rota.json

The checker enforces coverage against demand, required skills, availability and blocked shifts, overlapping shifts, minimum rest, weekly maximum hours, and the consecutive day and night limits. A rota with hard violations does not get published, softened, or explained away. Fix the input and rebuild.

6. Publish one version
7. Handle swaps through the validator

Swaps are where good rotas quietly break. The protocol:

  1. Workers propose swaps between themselves. Both forms are supported: one person takes a shift outright, or two people exchange shifts.
  2. Nobody works the swapped rota until it is validated and approved. Test it first:

python3 scripts/rota.py swap rota.json take 2026-11-02 early dee alex python3 scripts/rota.py swap rota.json exchange 2026-11-02 early dee 2026-11-02 late gus

  1. The validator rebuilds the rota with the swap applied and reports any new violation the swap creates, including ones neither person can see from their own shifts, such as a shift losing its only skill holder. It also prints both people's hours, nights, and weekend counts before and after, so the approver sees the fairness cost, not just the legality.
  2. A clean swap gets approved, applied to the published file, rechecked, and issued as a new version. A rejected swap goes back with the specific rule it breaks, so the pair can find a different trade instead of arguing about fairness in the abstract.
8. Fill last-minute gaps from a standing ladder

Decide the order before the day someone calls in sick:

  1. Offer the shift to existing staff first, starting with people under their contract minimum and people owed hours, and checking the validator before confirming anyone. Several predictive scheduling laws require offering hours to current staff before bringing in new people, so this order is both fairer and often the legal one.
  2. Split the gap: two people cover half each, if both halves pass the checker.
  3. The supervisor or owner covers it, and records the fact. A manager who regularly covers gaps is hiding a staffing problem the arithmetic in step 3 would have shown.
  4. Close or reduce the service for that shift, announced early, instead of running short in a way that burns out whoever did show up.
  5. Record what actually happened against the published rota. In places with predictability pay, an employer-initiated late change is a pay event, not just a diary entry. Worker-initiated swaps are usually treated differently, which is one more reason to keep the two apart in the record.
9. Close the cycle and carry the credits

At the end of each cycle, run the fairness report on the rota as actually worked, including swaps and gap fills:

python3 scripts/rota.py fairness rota.json

Compare it with the published plan. Differences between planned and worked fairness are the true credits owed, and they go into the next cycle's input as a note the builder's operator honors when checking the new rota's fairness output. Then archive the final version with its change history.

Output Contract

Deliver, in this order:

  1. Demand summary: shifts, times, headcount per shift, skill-gated posts, and how demand varies across the week.
  2. Constraint matrix: per person, contract minimum and maximum hours, unavailable dates, blocked shifts, and skills, plus the rota-wide rules with the source or choice behind each number.
  3. Coverage arithmetic: weekly demand hours, supply range, slack, and the relief allowance used, or a plain statement that the arithmetic fails and by how much.
  4. Fairness rules: which loads count, the window, the tolerance, and the credit remedy.
  5. The rota file and its checker output: the PASS line, or every violation with the fix applied.
  6. Publishing record: where the single version lives, its version number and publish date, and whether it meets the notice promise.
  7. Swap and gap protocol for this team, with the validator commands, and the credits carried into the next cycle.

Operating Rules

Versions

v1.0.02026-10-26 · 0 installs · Ed25519-signed./install.sh shift-scheduling 1.0.0bundle (.zip)

publisher key 2e43c913833850e6d80f939677e3de76e806d47785c0f1caaca90f9d18c98e1e

Ratings

No ratings yet — be the first to rate it.