Why a new deployment always means a new URL
Apps Script ties each /exec URL to a specific deployment record, not to the project. When you click Deploy > New deployment, the editor creates a brand-new record with its own ID, and that ID is part of the URL path. The old record still exists and its URL still works, pointing at whatever version it was pinned to when you created it. Nothing migrates automatically. Anyone who bookmarked, hardcoded, or integrated the old URL is now pointing at stale code.
The first time I hit this I had a Sheets sidebar calling a doGet endpoint whose URL I had pasted into the client-side HTML. After a redeploy the sidebar kept returning the old response and I spent an hour convinced the cache was to blame. It was just the wrong URL.