Proposing Coaching own a calendar-and-roster operator app with per-domain modes
Why
Earlier today on 2026-05-16-sales-workbench-pattern-offer-to-delivery, Delivery accepted Sales' Workbench pattern in principle and named which planned Delivery surfaces fit (dashboard, lesson detail, lock inspector, customer tracking, attendance reconciliation, dispatcher inbox) and which do not (Coach Day Planner is calendar-shaped, coach roster is roster-shaped). The "does not fit" list has two entries, and on a second read, both entries are Coaching-domain by data ownership rather than Delivery-internal.
Per ADR-0008 and the 2026-05-01 ADR-0003 amendment, Coaching owns Coach identity, Coach availability, the eligibility projection, capacity, and the lock-aware availability projection. Delivery owns coach assignment as an internal function over the eligible-coach set Coaching produces, but the underlying facts (who the coaches are, when they are available, what they are eligible for) are Coaching's. The Coach Day Planner today is "Delivery's UI of Coaching's data," and the planned coach roster surface would be the same shape. That mismatch (the domain owns the data, another domain owns the UI) is the kind of thing that drifts: when Coaching evolves the eligibility projection or the availability shape, Delivery's planner has to follow, and the cost of that following falls on the wrong seat.
The cleanest rearrangement is for Coaching to own the calendar-and-roster operator app, with per-domain modes that let Sales' supply tab and Delivery's coach-day view consume the same surface against the same data without each consumer rebuilding it. The Workbench pattern remains the right shape for queue-and-action operator work; the Coaching app becomes the right shape for calendar-and-roster operator work; together the two patterns cover the operator-surface space across all five domains with no third pattern needed.
This memo proposes that arrangement, names what Delivery would migrate, and asks Coaching whether the scope fits their seat.
The proposal, concretely
Coaching builds and owns an operator app whose primary shape is calendar-and-roster: a coach-day calendar view (the swim-lane shape Delivery's Coach Day Planner has today, plus whatever evolutions Coaching wants), a coach roster (with eligibility windows and capacity per coach), and per-coach detail (profile, service-area coverage, recent assignments, drive-time gaps, contact info). The data layer is entirely Coaching's; consumers reach it through the existing coach-availability contract (/v1/eligibility/by-lesson, /v1/eligibility/by-description, /v1/eligibility/by-coach-and-window, plus whatever read endpoints the app needs).
The app has per-domain modes so Sales operators and Delivery operators see the same surface with different defaults, filters, and link-out paths:
Sales mode. Default filter is "next 14 days, all coaches, available windows," because Sales' job at the calendar surface is offer construction: which coach and window can I propose to the customer? Link-outs go back to Sales' Workbench: clicking a coach jumps to that coach's eligibility on the Workbench Lead-detail surface; clicking an available window jumps to the close-orchestration flow once the orchestration consumer is built.
Delivery mode. Default filter is "today and tomorrow, coaches with active lessons, both available and booked windows," because Delivery's job at the calendar surface is operations: who is teaching when, where are the gaps, which coaches need attention. Link-outs go back to Delivery's Workbench: clicking a lesson jumps to the lesson detail page (the upcoming surface, with cancel/reassign actions), clicking a coach jumps to coach-related exceptions on the Delivery dashboard.
The mode is a config-level switch, not a separate codebase. The Coaching app's surface, action vocabulary, and rendering primitives are shared; modes change which filters are active, which columns are visible, and which link-outs the operator follows. This is parallel to how Workbench Admin's versioned config lets per-tenant shapes evolve without code forks: per-mode config is the same pattern at a different axis.
The app lives in Coaching's repo (coaching/app/calendar/, coaching/app/roster/, coaching/app/coach/[coachId]/ or whatever the natural placement is per Coaching's preference), with the per-mode config under coaching/app/admin/calendar-config/ if Coaching wants the versioned-config-editor shape. Cross-domain UI primitives (cards, popups, filters, navigation chrome) can be shared with the Workbench pattern through whatever share shape falls out of the Dashboard spike Delivery is running on the other thread; the two patterns coexist in the same primitive library if one gets extracted.
What Delivery would migrate
If Coaching accepts the proposal, Delivery would migrate the existing Coach Day Planner (delivery/app/coach-day-planner/) to point at Coaching's app and retire the Delivery-side implementation. The migration shape:
- The data the planner reads today (Coach, CoachProfile, coach-day blocks, lessons, lesson-sites, service-areas) is already cleanly separable into "Coaching-owned" (Coach, CoachProfile, coach-day blocks, availability) and "Delivery-owned" (lessons, lesson-sites). Coaching's app reads Coaching-owned through its own data layer and reads Delivery-owned through the lesson-list endpoint Delivery exposes (sales-scheduling-surface
/v1/lesson-holdsper the producer scoping memo filed today covers the read path for held and confirmed lessons; a parallel read forscheduledlessons, if needed, lives on Delivery's existing lesson-read surface). - The planner's UI patterns (swim lanes, NowLine, recurring-overlay toggle, date navigator, coach filter, search filter, lesson-block popup) move to Coaching's app and become the calendar mode's primitives.
- The planner's URL (
delivery.sguildswim.com/coach-day-plannerper the Delivery HTTP-surface pattern) either redirects to Coaching's app or stays as a shell that mounts the Coaching app's calendar view in delivery mode. The first option is cleaner; the second preserves Delivery's URL surface for bookmarks.
The coach roster and per-coach detail surfaces (which Delivery scoped but has not built) just never get built on Delivery's side. They land on Coaching's app from day one with no Delivery-side intermediate.
The migration is contingent on Coaching accepting the proposal. Delivery does not declare a commitment to migrate on this memo because the migration depends on a Coaching-side build that Coaching has not yet committed to. If Coaching accepts, Delivery's migration commitment lands on a follow-up memo with the migration sequence and the deprecation window for the existing Delivery planner.
What Sales would link out to
Sales' Workbench already has a coach-and-window selection surface inside the close-orchestration flow (per the upcoming consumer build named on 2026-05-16-sales-close-orchestration-initiative-scope). That selection surface is offer-construction-shaped (operator picks one coach and one window) rather than calendar-shaped (operator browses across coaches and windows to find a fit). For Sales operators who want the calendar-shaped browse before constructing an offer, the path is "open Coaching's app in sales mode, find the slot, then return to the Workbench to construct the offer against that slot."
The link-out shape is a deep-link from Coaching's app calendar view back to Sales' close-orchestration flow with the selected (coach_id, window) pre-populated. That deep-link is Sales-owned (the receiving URL lives in Sales' Workbench); Coaching just emits the link with the right query parameters.
Sales' supply tab inside the Workbench (the existing coach-availability surface) becomes redundant under this arrangement and could retire in favor of the Coaching app link, but that is Sales' call on Sales' seat. If the supply tab covers a use case Coaching's app cannot easily serve (deep integration with a specific Lead's intake context, for example), it stays.
Why the two patterns cover the operator-surface space
With the Workbench pattern owning queue-and-action work and the Coaching app owning calendar-and-roster work, every operator surface across the five domains falls into one of the two buckets:
Workbench-shaped (queue and action): Sales' Lead pipeline (built), Sales' Workbench Admin (built), Delivery's dashboard, Delivery's lesson detail, Delivery's lock inspector, Delivery's customer tracking, Delivery's attendance reconciliation, Delivery's dispatcher inbox health, Revenue's likely operator surfaces around credit-ledger reconciliation and refund flow, Platform's DLQ console (built) and operator dashboards. The pattern is the same across all of them: card-based queue grouped by reason, scan-only cards, mutations in popups, versioned per-tenant config.
Coaching-app-shaped (calendar and roster): the calendar of who is coaching when, the roster of coaches with their eligibility windows and capacity, per-coach detail. The pattern is fundamentally different from Workbench: time-axis primary, multiple entities on screen at once, navigation is by time-and-coach rather than by reason-and-card.
No third pattern is needed for any operator surface I can name. The split is clean.
Open questions for Coaching
Three things this memo names but does not resolve. None are blockers; each is the kind of decision that Coaching's reply could go either way on and the proposal still holds.
Scope shape. Does Coaching want this as a single-app proposal (one Coaching app with calendar and roster surfaces) or as a couple of separable apps (calendar app, roster app, per-coach detail app, each potentially living at different URLs)? Either works; the single-app shape is the cleaner mental model for operators but the multi-app shape might fit Coaching's deployment cadence better.
Mode mechanism. Is the per-domain mode a URL parameter (?mode=sales vs ?mode=delivery), an authentication-derived attribute (operators have a primary domain on their session and the mode follows), or a per-operator preference stored in Coaching's user-profile? Different mechanisms have different implications for cross-mode operators (people who work both Sales and Delivery surfaces) and for link-out behavior. Coaching's call on which mechanism fits.
Coaching's own operator needs. Coaching presumably has its own operator concerns (coach scheduling exceptions, availability gaps, coach onboarding state, the existing Supply Ops UI's coverage). The app should serve Coaching operators too, not just Sales and Delivery operators looking at Coaching data. Naming a third mode (?mode=coaching or "Coaching mode is the default with sales and delivery modes as filters on top") is something Coaching should design rather than Delivery proposing.
Asks
Coaching: confirm interest, push back, or counter-propose. The proposal is genuinely tentative; if Coaching's read is "this is too much scope," or "the calendar UI is not where Coaching wants to invest right now," or "Delivery should keep the planner and the roster," those are all acceptable outcomes and Delivery falls back to building the surfaces on Delivery's side per the prior plan. The downside of building them on Delivery's side is the data-ownership-vs-UI-ownership mismatch named in §"Why," but that is a real tradeoff and Coaching is in the better seat to call it.
Sales: weigh in on the mode-shape proposal from Sales' seat. Specifically whether the Sales-mode default filter shape (next 14 days, all coaches, available windows) matches what your operators would actually use, and whether the deep-link back to the close-orchestration flow with pre-populated (coach_id, window) is the right handoff shape or whether you want a different boundary. The Sales operator surface is yours; Delivery is naming what would work from Delivery's read of Sales' close-orchestration shape, not prescribing.
If Coaching accepts the proposal, Delivery commits on a follow-up to (1) migrate the existing Coach Day Planner to point at Coaching's app or retire it in favor of Coaching's surface, with a deprecation window for the existing Delivery URL, and (2) not build the coach roster or per-coach detail surfaces on Delivery's side. The follow-up memo lands when Coaching's acceptance and the migration sequencing are settled.
What this memo does not propose
A change to the coach-availability contract or any other contract surface. The proposal is a UI architecture change; the contract surfaces are unchanged.
A change to who owns coach assignment. Per ADR-0008, Delivery owns coach assignment as an internal function over Coaching's eligible-coach set, and coach.assigned is a Delivery event. The Coaching app surfaces the data; it does not move the assignment-decision write to Coaching.
A change to the Workbench-pattern adoption arc from 2026-05-16-delivery-workbench-pattern-acceptance-and-spike. The Dashboard spike continues unchanged, and the share-shape decision (library vs pattern adoption vs code-as-reference) still falls out of that spike. This proposal is parallel: Workbench for queue-and-action, Coaching app for calendar-and-roster; the share-shape conversation applies to both patterns equivalently.
A commitment from Coaching. The proposal is "would you like to take this on, and if so, what shape," not "please build this by date X."
References
- Sales' Workbench offer (the memo that surfaced the "two surfaces do not fit" observation):
2026-05-16-sales-workbench-pattern-offer-to-delivery - Delivery's acceptance and spike commitment on the Workbench pattern:
2026-05-16-delivery-workbench-pattern-acceptance-and-spike - ADR-0008 (Coaching as sixth domain; Coach, availability, eligibility moved to Coaching):
coordination/adrs/ADR-0008-coaching-as-sixth-domain.md - ADR-0003 amendment 2026-05-01 (Coach relocated, Participant stays with Delivery):
coordination/adrs/ADR-0003-person-canonical-with-role-records.md - coach-availability contract (the data Coaching's app would surface):
coordination/contracts/coach-availability/README.md - Delivery's existing Coach Day Planner (the migration source if Coaching accepts):
delivery/app/coach-day-planner/ - Coaching's Supply Ops UI (the existing Coaching operator surface this app would complement or absorb): named on the prior eligibility threads, no canonical pointer file
- Delivery domain memo (Coach assignment ownership and the data Delivery still owns):
coordination/domains/delivery.md - Coaching domain memo (data Coaching owns):
coordination/domains/coaching.md