Coach no-show ledger treatment: route to released, the coach no-show reason-code gap, and recognition of service-recovery credits
Why
A coach no-showed for a scheduled lesson. Delivery ran a make-up lesson the next day and presented it to the customer as free, with the operator intent that the customer's credit balance is not net reduced across the whole episode (the customer keeps the credits they bought, and the make-up costs them nothing).
Working the ledger choreography for that intent surfaced two things worth a cross-domain decision rather than a one-off operator action. First, the credit-reservation-lock contract models a customer no-show cleanly (forfeited, net minus N) but has no clean, named treatment for a coach no-show discovered at attendance reconciliation. Second, the make-the-customer-whole-plus-a-free-lesson pattern grants credits that are not cash-backed, and how those are recognized is a Finance call, not something Delivery or Revenue should decide implicitly in operator workflow.
Filing this now, while volume is low, so the policy is enumerated before this becomes a reconciliation-drift class of incident. This is the same shape of gap that 2026-04-28-revenue-refund-against-canceled-lessons opened for the customer-initiated cancellation side; this memo is the coach-caused-failure analogue.
What
1. The no-show lesson is a Sguild-side cancellation, not a consumption
A coach no-show means the lesson was not delivered. The contract's terminal state for a Sguild-caused cancellation is released, net account impact zero. If the reservation was locked (it will be, since the lesson time arrived), the lock dissolution invariant posts one Adjustment of plus N with reason Credits Released and no paired debit. The customer keeps the N credits.
The tempting shortcut, consuming the credits and then posting a plus N Adjustment to hand them back, is wrong and Delivery will not do it. Consuming credits emits credit.consumed, which asserts delivery to every consumer (Revenue recognizes revenue on it, Coaching and the warehouse record a delivered lesson). The lesson was not delivered. The follow-up plus N Adjustment then re-creates the liability, so the result is revenue recognized once on a lesson that did not happen plus N unfunded credits that recognize revenue a second time when later consumed. The released path reaches the correct end state (net zero, customer holds their credits) with no adjustment gymnastics.
Operationally, Delivery marks the no-show lesson outcome Canceled, not No-Show. In the lesson-lifecycle contract No-Show is the customer no-show outcome and carries its credit consequence through credit.forfeited, which would wrongly debit the customer. Canceled fires lesson.cancelled. Delivery does not emit credit.released directly; per the credit-reservation-lock contract §13, Delivery submits a cancellation request to Revenue with initiator and reason_code, and Revenue runs the state machine.
Ask to Revenue: confirm a coach no-show routes locked to released at net zero, and confirm the cancellation-request surface is the correct entry point for a Delivery-originated coach no-show.
2. The reason-code gap: coach no-show is not coach_unavailable_reschedule_failed
credit.forfeited and its forfeiture_reason enum (late_cancel, no_show) are customer-side only, per the event-types registry note and the contract. So "no-show" already has a meaning in the contract, and it is the customer's no-show. A coach no-show is a different event with the opposite ledger sign and needs a different surface.
The coach no-show routes through released, but the only coach-flavored auto-release reason code in §6.1 is coach_unavailable_reschedule_failed, defined as Delivery's reschedule attempts failing within the program's reschedule policy window, with the transition firing automatically once that window expires. That is a planned-ahead unavailability known before the lesson. A genuine day-of no-show is not known in advance, no reschedule window runs, and it is discovered at attendance reconciliation after T-0.
Delivery's lean is a distinct coach_no_show value in the §6.1 auto-release subset rather than overloading coach_unavailable_reschedule_failed. The operator workflow differs (no reschedule attempt happened), and folding day-of no-shows into the reschedule-failed code muddies any metric built on reschedule-policy performance. Per the contract's versioning rules a new auto-release reason_code value and a new Adjustment reason code are both additive-minor, so this does not disturb the state machine.
Ask to Revenue: decide reuse of coach_unavailable_reschedule_failed versus a new coach_no_show auto-release reason code. If a new code, it lands as a minor ADR-0006 amendment under the joint-review rule, and Delivery will co-author since the cancellation reason-code policy is Delivery-stewarded per the 2026-04-28-revenue-refund-against-canceled-lessons thread.
3. Timing: a release that fires after T-0
A coach no-show is discovered at attendance reconciliation, after T-0 and after the lesson window has passed. The §6.1 auto-release subset cascades through the existing reserved to released and locked to released transitions, but the auto-release reasons are otherwise evaluated around the cancellation deadline. The Forfeit Job already has post-T-0 machinery (it runs after Delivery records a no-show). The release path needs the equivalent.
Ask to Revenue: confirm a Delivery coach-no-show signal raised post-T-0 can trigger a locked to released transition, or name what job or surface carries it.
4. Service-recovery credits: a recognition decision Finance owns
Making the customer whole for the no-show (item 1) costs nothing extra: the released credits were never spent, and the make-up lesson then consumes them normally, recognizing revenue correctly on the make-up at delivery. The customer paid for one lesson and received one lesson.
The operator intent here goes one step further: the customer's balance is not net reduced at all, meaning they keep the N credits and the make-up is free on top. The make-up lesson is still genuinely delivered, so it is consumed normally (Adjustment plus N, Lesson Debit minus N, revenue recognized, all correct). To leave the balance whole, Revenue then posts a separate non-lock Adjustment of plus N. The contract sanctions this in §7.1, which allows additional reason codes for goodwill and extenuating-circumstance credits without a contract bump.
The recognition question is real. Those plus N credits carry no Purchase Credit entry and no cash. If their later consumption recognizes revenue the normal way, revenue is overstated by the value of credits that were never sold. This is the user's earned-revenue concern and it is well founded.
Asks to Finance, with Revenue input:
- Should the cost of a non-cash-backed service-recovery credit grant be booked at grant time as a service-recovery or retention expense, or should the later consumption of granted credits be excluded from revenue recognition?
- Either treatment requires telling granted credits apart from sold credits at consumption time. Does this need the ledger to track credit provenance or lots? ADR-0006 already names lot-level accounting as a revisit trigger (for pack expiration); service-recovery grants raise the same question. Booking the cost at grant time would sidestep lot tracking, which is why Delivery raises it as the likely-simpler option, but the call is Finance's.
Ask to Revenue: name a reason code for this grant, for example service_recovery_credit, distinct from generic goodwill so Finance's recognition view and any cost reporting can key on the service-recovery cause specifically.
Asks
Revenue: confirm the net-zero released routing (item 1); decide the reason-code question, reuse versus a new coach_no_show (item 2); confirm post-T-0 release timing (item 3); name the service-recovery adjustment reason code (item 4). If a new reason code is agreed, Delivery will file a follow-up memo and co-author the ADR-0006 minor amendment.
Finance: the recognition treatment for non-cash-backed service-recovery credits, and whether it requires credit provenance or lot tracking in the ledger (item 4).
No deadline. The episode that prompted this is already handled operationally; this memo is to settle the policy so the next one is mechanical and drift-free.
What does not change
Customer no-show stays forfeited at net minus N with forfeiture_reason no_show. The five-state machine, the lock dissolution invariant, the funding sub-state, and the customer.handoff coupling are all untouched. Everything proposed here is reason-code and recognition-policy work that is additive under the contract's versioning rules.
References
- ADR-0006 (credit reservation lock state machine):
coordination/adrs/ADR-0006-credit-reservation-lock-state-machine.md - Credit reservation lock contract, §6.1 auto-release reason codes, §7.1 Adjustment reason codes, §13 cancellation-request surface:
coordination/contracts/credit-reservation-lock/README.md - Delivery state vocabulary mapping:
coordination/contracts/credit-reservation-lock/delivery-state-vocabulary.md - Lesson lifecycle contract (Completed, Canceled, No-Show outcomes):
coordination/contracts/lesson-lifecycle/README.md - Refund-against-canceled-lessons, the customer-side analogue thread:
2026-04-28-revenue-refund-against-canceled-lessons - Refund and cancellation reason codes, Delivery proposal:
2026-05-02-delivery-refund-cancellation-reason-codes - Refund reason codes, Revenue signoff:
2026-05-08-revenue-refund-reason-codes-signoff - Reason codes signoff accepted, Phase-1 closeout:
2026-05-08-delivery-reason-codes-signoff-accepted - Revenue domain doc (ledger ownership, append-only rule):
coordination/domains/revenue.md - Finance domain doc (revenue recognition rollups, reconciliation):
coordination/domains/finance.md - Delivery domain doc:
coordination/domains/delivery.md