Coaching eligibility blocks proposed edits to an existing lesson as already booked by that same lesson
Why
Delivery reproduced a production failure while an operator edited the lesson type of an upcoming lesson. Delivery correctly rechecked the proposed coach, location, and effective lesson window before writing. Coaching returned why: already_booked with detail.conflictingLessonId equal to the lesson being edited. The Workbench POST therefore failed with HTTP 500 rather than saving the proposed details.
The failure is deterministic for any proposed edit that requires a fresh eligibility decision. eligibility-by-description loads the active booking projection and evaluates every overlapping booking, including the current lesson. The route ignores an exclude_lesson_id query parameter. eligibility-by-lesson is not a substitute for proposed edits because it reads the currently stored facts rather than the proposed duration or location. Its production read for the reproduced lesson also returned lesson_fetch_failed.
Delivery shipped a narrow consumer correction for same-window lesson-type changes. When coach, location, start, and end are unchanged, the existing assignment decision remains applicable and no redundant eligibility call is made. Duration, coach, and location changes remain blocked because Delivery will not bypass Coaching-owned availability, travel, band, certification, or market predicates.
Ask
Please add a producer-owned way to evaluate proposed facts for an existing lesson while excluding only that lesson's current booking from conflict and travel composition. Delivery proposes an optional exclude_lesson_id on GET /api/v2/coaching/eligibility/by-description. Coaching should verify the excluded booking belongs to the requested organization, remove only that booking from the effective booking set, and then run the existing full predicate chain against the proposed window, locator, certifications, and preferred coach.
If Coaching prefers a by-lesson override shape, it must accept the proposed window and locator rather than re-reading only the old Delivery facts. Either shape needs explicit contract semantics so Delivery does not invent producer behavior.
Please patch the coach-availability v2 contract, add regression coverage for a same-lesson edit plus a real second-booking conflict, deploy the producer change, and reply with the accepted request shape and production evidence. Delivery will then serialize the accepted field and remove the temporary blocked-edit message.
Production evidence
At 2026-08-02T22:05:02Z, deployment dpl_GC8UnG5jpPYTCDtu2qXR1DVkhtao returned HTTP 500 from POST /workbench. Coaching's response identified the edited lesson itself as conflictingLessonId.
At 2026-08-02T22:16:56Z, after Delivery deployed commit 671578a, deployment dpl_DrXC57QSzwuUAgdCsbDuFHSijVtT returned the same already_booked error for an edit that changed an eligibility-relevant field. A direct production request with exclude_lesson_id still returned the same lesson as the conflict, confirming that the current producer ignores the proposed exclusion.
References
- ADR-0018:
adrs/ADR-0018-continuous-availability-bands-and-lesson-projection.md - Coach availability v2:
contracts/coach-availability/README.v2.md - Coaching composer:
coaching/modules/availability/service.ts - Coaching by-description route:
coaching/modules/availability/routes/eligibility-by-description.routes.ts - Delivery consumer:
delivery/lib/coaching/eligibility-client.ts - Delivery Workbench action:
delivery/app/workbench/actions.ts