Every constraint lives in a registry that can be toggled and tuned
from the interface, and the split between the two kinds is the whole
design.
Hard rules cannot be broken at any price: no double booking, stated
availability windows, only technicians approved for that client,
clinic operating hours, daily hour caps, and per-client limits on how
short or long a block may be. A schedule violating any of these is
not a worse schedule, it is an invalid one.
Soft rules carry weights, which is where a clinic's actual priorities
get written down. Meeting each client's required hours is weighted
roughly three hundred times more heavily than placing a tidy lunch
break. Continuity — limiting how often a client's technician changes
during a day — outranks technician preference. Travel gaps between
clinics and avoiding isolated one-off sessions are worth something,
but they lose to almost everything else.
Those weights are saved and reused on every run, so tuning them is a
policy decision the clinic makes once rather than an argument
relitigated every week. It also makes the trade-offs explicit: when a
manager disagrees with the schedule, the conversation is about a
number they can change, not about the solver being wrong.