One thing that helped us on the skip problem: stop pricing per cut and start pricing the season slot. We quote a season total (or a flat monthly) based on the number of scheduled visits, and the client pays that whether or not they wave us off a given week. Skips just get banked as extra visits later in the season, so we're never eating the route hole.
If you'd rather stay per-visit, two guardrails worth writing into the agreement: (1) skips require 48 hours notice or it's billed as a full visit, and (2) any cut after a skipped week is billed at 1.5x because you're double-cutting, bagging, and burning blade time. Say it as a cost fact, not a penalty — "grass past X inches takes two passes and about 40% more time, so that visit prices higher."
For the conversation itself, I'd frame it as re-quoting rather than confronting: "Looking at this season we serviced fewer visits than we scheduled, so the weekly rate doesn't fit anymore. I can move you to bi-weekly at [rate], or keep the weekly slot on a flat monthly." Gives them a real choice and gets you off the hook of chasing a mow schedule you don't control.