Same-day changes¶
Tomorrow's schedule is published. In the morning someone tells you they slept badly, or that they are ill and need the day off. Same-day mode re-solves the day around that, moving as few people as it can, and tells you exactly who has to be told something new.
The two things that change¶
Both go on the Adjustments tab of the config spreadsheet, one row per person per date. They are facts about a person for one day, not requests, so they leave the Skills sheet alone and expire on their own.
| Column | Meaning |
|---|---|
date |
The day it applies to. |
staff |
Who, as named on the Skills sheet. |
resting |
all day, morning or afternoon. Blank leaves them working the whole day. |
RAL_penalty |
How many levels to take off their usual RAL for the day. Blank takes off none. |
note |
Why, for the record: sick, short sleep. |
A row must give a resting or a RAL_penalty, otherwise it does nothing and the loader
says so. One row can do both, for someone who is short of sleep and resting the afternoon.
Resting takes them off that part of the day. No clinics, and no breaks either, since a
category such as staff stops offering anyone who is resting all day. That is why a
rest belongs here rather than in a FREE request, which would collide with the
mandatory break rule and report a conflict every time somebody was ill.
A block belongs to the half of the day it starts in, split at midday under [day] in
config.toml, which is noon unless you change it. So a 12:00 lunch block counts as
afternoon.
A RAL penalty narrows what they may run. Camp's sleep agreement costs one level, so a
penalty of 1 takes a RAL 5 down to 4 for the day. They stay on the day and keep
everything their new level allows, and come off whatever it does not. A penalty large
enough to reach 0 rules out every clinic, since every position asks for at least RAL 1.
For an absence that is neither half a day nor all of it, write an ordinary request instead, which can name the blocks:
REQUEST staff.dylan FREE DURING ALL {blocks.clinic_3 + blocks.clinic_4} ON dates.target
Re-solving¶

In the app, Same-day changes in the toolbar becomes available once the day on screen is published. Switching it on reveals two buttons:
- Sleep agreement: pick the person, and their RAL drops by one for the day.
- Sickness: pick the person and whether they are resting all day, the morning or the afternoon.
Both write the same Adjustments row and both list what is already in effect, so one person can be short of sleep and resting the afternoon without either recording wiping the other. Put back to usual clears someone's row. Then press Solve. The schedule window opens with a Changes tab listing what moved. Publish writes the day again, along with a Changes tab in that day's spreadsheet.
From the command line:
puppet-strings solve --same-day
puppet-strings solve --same-day --publish
--same-day works on today by default rather than tomorrow, and refuses a day that has
never been published, since there would be nothing to hold on to. Publishing over the day
needs no --force, because replacing it is the point.
What the solver holds on to¶
Same-day mode adds one tier between staffing the clinics and everything else:
MUST_HAPPENrequests, as always.CLINIC: staff as many offered clinics as possible.- Stability: keep as many published assignments as possible.
HIGH,MEDIUM,LOW: the usual preferences.
So the day never loses a clinic in order to stay still, and it never moves anyone to chase a preference. Anyone the change does not touch keeps their morning exactly as printed.
On the sample data, taking one lifeguard off the day and lowering another person's RAL gives this:
| Clinics staffed | Published rows kept | |
|---|---|---|
| Plain re-solve | 19 of 24 | 41 of 76 |
| Same-day re-solve | 19 of 24 | 68 of 76 |
Both staff the same number of clinics. The plain re-solve happens to rearrange 35 people who had no reason to move.
The change log¶
The Changes tab has one row per staff member and block that is not what was published:
| Staff | Block | Was | Now |
|---|---|---|---|
| Alesa | Clinic 1 | Canoe 1 & 2 (1st) | free |
| Alesa | Clinic 2 | break 10:45-11:15 | free |
| Vic | Clinic 3 | Secret Pool (1st) | free |
A block somebody is left with nothing in says resting instead of free when they are
resting through it, or when they are short of sleep: a sleep agreement may still move them
to a clinic their lower RAL allows, but any block it leaves empty is rest. The staff and
clinic views say the same, with the resting grouped in their own row rather than under
DYOW/WPs.
A half-day rest, or a mandatory request the rest makes impossible, is worth knowing about:
if a counselor rests all morning and a MUST_HAPPEN request gives every counselor a
morning counselor hour, the two cannot both hold. The solve stops and the report names
that request, which is the signal to relax it or to rest them all day instead.
Anyone missing from it is unaffected. Times appear for a task that takes only part of its block, so a break that moved shows where it moved to.