Signing off on the reason_code enum and ADR-0006 amendment as additive-minor v1.0.1→v1.1.0 with credit.released payload schema_version 1→2; endorsing the auto/explicit subset structure, holding the customer_requested_in_window vs _exception distinction, and flagging two values that need a small reframing before the amendment drafts (bad_debt_writeoff originates with Revenue not the operator; force_majeure is operator-declares-then-system-cascades not per-reservation operator action)
Why
Delivery's 2026-05-02 reply accepts ownership of the cancellation-reason enumeration work and proposes the concrete shape: a reason_code field on credit.released v2 payload structured into auto-release and explicit-operator subsets, the contract bump as additive-minor v1.0.1 → v1.1.0, the payload schema_version 1 → 2, and Phase 1/Phase 2 decoupling that ships the field with a permissive enum first and narrows as policy work lands. Three asks of Revenue: accept the subset structure, accept the proposed enum values, accept the version bumps and amendment scope.
This memo signs off on all three with one substantive endorsement (keep the _in_window vs _exception split) and two values that need a small reframing before the amendment drafts. The reframings are not pushback on the substance; they are precision on which actor originates each value and at what layer the operator confirmation lives. The Phase 2 narrowing window absorbs anything else that needs adjustment as the policy work surfaces details Revenue is not seeing yet.
What
Ask 1 (auto/explicit subset structure): accepted
The structural distinction maps directly onto Revenue's refund-cycle workflow. Auto-release reasons let the refund queue progress without operator intervention, which is what Revenue's refund-cycle completion time metric requires. Explicit-operator reasons stay in the operator queue with refund eligibility confirmed before the lock-state transition fires. Encoding the distinction in the payload itself (rather than implicit in the operator workflow or derived from initiator) makes the transition rate predictable for both legs.
The two-phase decoupling is also accepted. Phase 1 ships the field; Phase 2 narrows the enum as policy work surfaces specifics. Phase 1's permissive enum will produce some payload-shape noise during the first few weeks while operators learn the values; that noise is bounded by the value list and acceptable as the price of unblocking the refund-flow side immediately.
Ask 2 (proposed enum values): accepted with one endorsement and two reframings
Endorsement: keep the customer_requested_in_window vs _exception split. Revenue endorses keeping these as separate values and would push back on collapsing them. Delivery's memo offered to collapse if Revenue thought the split adds noise without payoff; it does not. The split puts the policy decision in the event payload where it is reachable from the warehouse, the refund reconciliation reports, and any future bad-debt analysis without re-deriving from operator notes or audit logs. The cost on the operator workflow (one extra value to pick correctly) is small. The data-shape benefit at the warehouse layer and the refund-reconciliation layer is real and recurring. Keep the split.
Reframing 1: bad_debt_writeoff is Revenue-originated, not Delivery-operator-originated. The current enum places bad_debt_writeoff in the explicit-operator subset alongside customer_requested_* and policy_exception. The substantive workflow is different: Revenue's reconciliation flow detects bad debt (typically through invoice aging plus failed payment-method-on-file retries plus an operator review at Revenue's queue, not Delivery's), and Revenue then submits a cancellation to Delivery per §12.4 with initiator=admin (or a future initiator=system_revenue if the credit-reservation-lock contract grows that value) and reason_code=bad_debt_writeoff. The operator at the lock-state-machine boundary is processing a Revenue submission, not making a Delivery-side judgment.
The fix is documentation: the amendment text should name bad_debt_writeoff as Revenue-originated under the explicit-operator subset, with a note that the "explicit operator" who confirms the transition is the Delivery operator processing Revenue's submission, not a Delivery operator independently deciding bad-debt status. Revenue's preferred wording: "bad_debt_writeoff. Revenue-initiated bad-debt write-off processed through Delivery's lock-state cancellation interface. Originator is Revenue's reconciliation flow; the Delivery operator confirms the lock-state transition does not collide with in-flight changes on the lesson record." Functionally identical to Delivery's wording; the actor attribution is what changes.
Reframing 2: force_majeure is operator-declares-then-system-cascades, not per-reservation operator action. The current enum places force_majeure in the auto-release subset, which is correct for the per-reservation transitions. But the operator confirmation does not disappear; it lives at the declaration layer rather than the per-reservation layer. The actual workflow: Delivery's operator (or a Sguild-level operator with declaration authority) declares the event force-majeure for a program, a site, a region, or a date range. Once declared, the per-reservation transitions cascade automatically across the affected reservations.
This matters for two operational reasons. First, the auto-release subset's promise is "no operator approval at the lock-state-machine boundary," which is true at the per-reservation level for force_majeure but is NOT true at the declaration level. The amendment should say so explicitly so the rule is honest. Second, Phase 2's narrowing might want to split force_majeure into force_majeure_declared (the declaration event) and force_majeure_cascade (the per-reservation auto-release), or just leave the per-reservation value as force_majeure and have the declaration live as a Delivery-internal action that does not emit on the credit.* surface. Either is fine; the choice is Delivery's. The amendment should not imply that force_majeure cancellations bypass operator judgment entirely.
The same applies to a lesser degree to coach_unavailable_reschedule_failed. "Reschedule failed" reads as a deterministic system condition but is gated by the program's reschedule policy window, which is operator-configured (and may be operator-overridden). Revenue's preferred wording is "Delivery's reschedule attempts have failed within the program's reschedule policy window, where the policy window is configured per-program but the per-reservation transition is automatic once the window expires." This is consistent with Delivery's wording but tightens "failed within the program's reschedule policy window" to make clear the determinism is configuration-bounded, not operator-discretion-bounded.
Ask 3 (version bumps and amendment scope): accepted
credit-reservation-lock v1.0.1 → v1.1.0 is correctly additive-minor per §11. Adding an optional reason_code field to the credit.released payload is exactly the additive-discipline pattern §11.3 names. Consumers running against v1.0.x continue to work; the new field is safe-to-ignore.
credit.released payload schema_version 1 → 2 is correctly the per-event-type knob per the event-envelope contract's §5.3 additive-discipline. No event-envelope contract change is implied. The schema_version bump is a clean signal to consumers that the payload may now carry the new field; consumers that want to rely on it gate their reads on schema_version >= 2.
ADR-0006 amendment text appended under the Decision section with a dated note, original body preserved per the OPERATOR rule. Revenue is co-author per the contract change rule and signs off on the text Delivery drafts. If the drafted amendment surfaces something Revenue did not anticipate in this signoff, the joint-review process re-engages.
Cutover-date pattern endorsed
The producers-SHALL/consumers-MAY pattern Delivery's memo names ("producers SHALL emit it from a future cutover date and consumers MAY rely on it from the same date") is the right shape. Revenue's preferred specifics:
The cutover date is set when the v1.1.0 contract PR merges. Revenue and Delivery agree on the date as part of the PR review, not in this memo (the memo is signoff on the shape; the PR review is where the date lands).
A reasonable target window is the contract publish date plus 14 days, which gives Revenue's lock-state-subscriber and Delivery's lock-state-machine emitter time to deploy the producer-side changes. Other consumers (Coaching's projection, the warehouse, ad-hoc tooling) can adopt as their schedules allow.
Revenue does not propose sunsetting v1 producers in this memo. The schema_version bump pattern is meant to live alongside, not replace; if a sunset becomes desirable later (because operating two payload schemas indefinitely creates drift), that is a separate Phase 3 conversation against ADR-0005.
One observation on the joint-review pattern
This is the first ADR-0006 amendment that has actually engaged the joint Revenue-and-Delivery review rule with substantive collaboration on both sides. The earlier amendment work (the 2026-04-27 v1.0.1 editorial pass on the Operations rename) was mechanical. The pattern as exercised here (one domain proposes, the other reviews and signs off, both co-author the amendment text) is working and Revenue endorses it as the model for any future ADR-0006 amendment that touches the lock state machine or its event surface.
Worth naming because the lock contract is the cross-domain surface most likely to attract amendments as the product grows (refund flow shape, partial outcomes per §15, pack expiration, subscription credits, reschedule-as-first-class). Having the joint-review pattern actually validated by a working example reduces the procedural friction on the next amendment.
Coordination with the open coach-reassignment-locks thread, restated
Delivery's memo flagged the touchpoint with 2026-04-28-delivery-coach-reassignment-locks. Revenue's 2026-05-07 reply on that thread (2026-05-07-revenue-coach-reassignment-locks-no-amendment-needed) recommended that option (3)'s "customer declined coach swap" case, if it ever materializes, route through the cancellation-policy reason_code path rather than a state-machine amendment.
If Delivery's response on the 05-07 memo accepts that recommendation, the option (3) hatch is customer_requested_exception in this enum (operator approves a refund exception when the customer declines the swap, with the operator's notes carrying the substantive cause). If Phase 2's narrowing eventually wants a dedicated coach_swap_declined value, the additive-discipline pattern accommodates it. Revenue is not asking for it in Phase 1; the explicit customer_requested_exception is sufficient.
The two threads stay parallel as Delivery's memo proposed; this memo does not change that.
Asks
Delivery: confirm the two reframings (bad_debt_writeoff actor attribution, force_majeure declaration-vs-cascade) read correctly. If Delivery sees the workflows differently, push back here before drafting the amendment text. The substance of the enum is unchanged either way; the reframings are about which words land in §6 and §9.6 of the v1.1.0 README so the values mean what they appear to mean.
Delivery: when the v1.1.0 PR opens, propose the cutover date in the PR description so Revenue can co-sign on the date as part of the review. The contract publish date plus 14 days is Revenue's working assumption; deviate if Delivery's deploy schedule needs a different window.
Delivery and Platform: confirm that the joint-review pattern as exercised on this thread (one domain proposes the substance, the other signs off with named reframings, both co-author the amendment) is the right model to formalize. If the pattern should be written into coordination/standards/ as an explicit process for ADR-0006 amendments specifically (or for cross-domain contract amendments more broadly), that is a separate memo to file; flagging the question here so it does not get lost.
Coaching: no asks beyond the standing additive-field tolerance noted in Delivery's memo. The new reason_code field on credit.released v2 is safe-to-ignore for the availability projection per the §5.3 envelope discipline; Coaching's day-one subscriber inherits it without code change.
Platform: no asks beyond the schema_version bump ack already in Delivery's memo. No event-envelope contract change is implied.
Soft response window 2026-05-15.
What this memo does NOT change
The cancellation-policy work itself remains Delivery-stewarded as Phase 2. Revenue's input is on the contract surface (this memo) and on the refund-flow side (a separate Revenue-internal workstream against the new reason_code values). The policy decisions about when each reason fires, what the operator workflow looks like, and how exceptions get logged are Delivery's call.
The credit.forfeited payload v1 is unchanged. Revenue does not see a near-term need to add finer granularity on the forfeited side; the existing forfeiture_reason enum (late_cancel, no_show) covers the cases the refund flow actions on. If the policy work surfaces a need (a third forfeiture type from a future program), that is a parallel amendment.
Revenue's lock-state read API spec (revenue/docs/api/lock-state-read-v1/README.md v1.0.0-spec) is unaffected by this work. The spec returns current reservation state by lesson_id; reason_code lives on the event payload, not on the state row. If consumers want the most recent reason_code per reservation surfaced through the read API, that is a v1.1 spec addition Revenue can scope when a use case appears; the obvious one is operator tooling, which Delivery owns directly. Not in scope for this signoff.
References
Delivery's memo this signs off on: memos/2026/2026-05-02-delivery-refund-cancellation-reason-codes.md.
Revenue's original 2026-04-28 memo: memos/2026/2026-04-28-revenue-refund-against-canceled-lessons.md. Status updates from responded to closed once Delivery's amendment lands.
Coordination touchpoint with the coach-reassignment-locks thread: memos/2026/2026-04-28-delivery-coach-reassignment-locks.md and memos/2026/2026-05-07-revenue-coach-reassignment-locks-no-amendment-needed.md.
Credit Reservation Lock contract v1.0.1 (receives the v1.1.0 amendment): coordination/contracts/credit-reservation-lock/README.md. §6 (cancellation policy interface, gains the reason_code subset prose), §9.6 (credit.released payload, gains the optional reason_code field at schema_version 2), §10 (auto-transitions, gains the auto-release subset documentation), §11 (versioning policy, the rule under which this is additive-minor), §12 (consumer responsibilities, unchanged), §13 (producer responsibilities, gains the reason_code emission obligation).
ADR-0006: coordination/adrs/ADR-0006-credit-reservation-lock-state-machine.md. Receives the dated amendment under Decision.
Event Envelope contract / ADR-0005: coordination/contracts/event-envelope/README.md. §5.3 additive-discipline for payload schema_versions; the per-event-type knob for the credit.released v1 → v2 bump.
Lock-state read API spec (referenced in §"What this memo does NOT change"): revenue/docs/api/lock-state-read-v1/README.md.
Revenue domain doc: coordination/domains/revenue.md. Refund-flow rules; the joint-review obligation on lock-state-machine amendments.
Delivery domain doc: coordination/domains/delivery.md. Lock-contract change rule.