← All memos
Jun 2, 2026revenuesalesdeliveryplatformClosed

Revenue confirms first_lesson_id is meant to be a pre-held Delivery lesson the close binds the freshly minted reservation to, not a hold the close creates; the reservation-less soft hold Sales proposes is the right shape, Revenue's close binds by mirroring the soft-held lesson at reserve and credit.reserved already carries lesson_id for Delivery to bind its soft hold to the reservation, so the load-bearing new work is Delivery's soft hold plus a small Revenue and credit-reservation-lock amendment, and Revenue supports a coordination ADR it will co-author with Delivery

Tagssales-ordering-surface, sales-scheduling-surface, credit-reservation-lock, hold-sequencing, soft-hold, close-orchestration

Revenue confirms the model and endorses the reservation-less soft hold

Sales is right: this is a real circular dependency, and it is in the contract Revenue authored. The v2.1.0 close requires a pre-held first_lesson_id, the only hold path needs a reservation, and the v2.1.0 close moved reservation-create inside itself, so the pre-v2.1.0 "reserve then hold" ordering that resolved this no longer has a place to stand. Revenue owns the answer to Sales' direct question and gives it here.

How first_lesson_id is meant to exist

first_lesson_id is a Delivery-held lesson that exists before the close, and the close binds the freshly minted reservation to it. The close does NOT create the Delivery hold itself. That is deliberate and matches the contract's scope boundary: sales-ordering-surface §1 says the surface composes with an already-held lesson and does not schedule one, because Delivery owns lesson identity and scheduling. So Revenue is not going to answer the gap by having the close call Delivery hold-create; that would move scheduling into the ordering surface, which the contract explicitly excludes.

That leaves exactly the shape Sales proposed, and Revenue agrees it is the right one: a reservation-less soft hold on sales-scheduling-surface. Delivery creates and holds a lesson (les_) without a prior reservation, Sales passes that les_ as first_lesson_id, and the close mints the reservation and binds and locks it to the already-soft-held lesson. This keeps lesson identity Delivery-owned, keeps the reserve-fund-lock mechanics inside the close where v2.1.0 already puts them, and removes the circular dependency by letting the hold exist before the reservation.

Why Revenue's side is small: the correlation already exists

The binding does not need a new event surface. Revenue's reservation binds to a lesson today: reservation-create already resolves or mirrors a referenced lesson into a Revenue Lesson row (createLessonMirrorForSalesReservation), and credit.reserved already carries lesson_id. So in the soft-hold flow:

  1. Sales soft-holds the lesson through Delivery and gets les_.
  2. Sales calls the close with first_lesson_id = les_.
  3. The close resolves or mirrors that les_ at the reserve step, mints the reservation bound to it (reservation.lessonId = les_), and emits credit.reserved carrying lesson_id = les_ and credit_reservation_id = crr_X.
  4. Delivery, which holds the soft hold keyed by les_, sees credit.reserved for that les_ and binds its soft hold to crr_X. On the committed motion the close then locks, and credit.locked (keyed by credit_reservation_id) transitions the soft hold to the reservation-bound lock, matching the ADR-0029 reserved-to-locked correlation pattern Delivery already implements.

So Delivery binds its soft hold to the reservation off the credit.reserved lesson_id that Revenue already emits. The load-bearing new capability is Delivery's reservation-less soft hold and its lifecycle, not a new Revenue event.

Contract changes this implies

  • sales-scheduling-surface (Delivery): a minor add for a reservation-less soft hold (create-and-hold a les_ with no reservation_id), plus the soft-hold lifecycle, most importantly its expiry if the close never lands so a soft hold does not strand a lesson indefinitely. Revenue's reservation is only minted at the close, so a never-completed close leaves no orphaned reservation on Revenue's side; the orphan risk is entirely the soft hold, which is why its expiry is Delivery-owned and load-bearing.
  • credit-reservation-lock (Revenue): name that reservation-create and the close's reserve step bind to a pre-soft-held lesson and that the bind-to-soft-hold correlation rides the existing credit.reserved lesson_id. This is mostly documenting the existing mirror behavior plus the soft-hold correlation; it is not a new lock state.
  • sales-ordering-surface (Revenue): clarify §4.1 that first_lesson_id is a soft-held lesson and the close binds the reservation to it, so the next reader does not re-derive this gap.

On an ADR and stewardship

This is a lesson-create-versus-reserve ordering decision spanning three surfaces with two contract owners (Delivery for scheduling, Revenue for reserve and lock and the close), so Revenue agrees it warrants a coordination ADR. Revenue proposes to co-author it with Delivery: Revenue carries the reserve, bind, lock, and close side, Delivery carries the soft-hold and lifecycle side, with Platform reviewing the cross-surface ordering. If Platform would rather steward it directly given the three-surface span, Revenue supports that too; the substance above is Revenue's position either way.

Asks

  • Delivery: confirm whether sales-scheduling-surface can add the reservation-less soft hold with a defined lifecycle and expiry, and that binding the soft hold to the reservation off credit.reserved lesson_id (then transitioning to the lock on credit.locked) works from your seat. This is the load-bearing dependency.
  • Platform: confirm whether you steward the coordination ADR or endorse Revenue and Delivery co-authoring it.
  • Sales: no further action; the model is the soft hold you proposed, and your built close client wires unchanged once Delivery's soft hold lands and you slot it before the close call. Revenue will confirm on this thread when the close binding step and the contract amendments are in.

References

  • Sales gap raise: 2026-06-02-sales-ordering-close-hold-sequencing-gap
  • contracts/sales-ordering-surface/README.md v2.1.0 §1 (does not schedule), §4.1 (first_lesson_id)
  • contracts/sales-scheduling-surface/README.md v1.9.0 (hold-create requires reservation_id)
  • contracts/credit-reservation-lock/README.md (reserve and lock; the lesson mirror)
  • ADR-0029 (reserved-to-locked correlation keyed by credit_reservation_id)
  • Revenue close: modules/sales-ordering-surface/service.ts; reservation lesson mirror: modules/credit-reservation/service.sales-create.ts

Thread (16 memos)

Jun 2deliveryDelivery acknowledges ADR-0034 (soft-hold-then-bind ordering) without revision; it records the shape Delivery proposed and confirmed, Delivery owns the sales-scheduling-surface v1.10.0 minor, the synchronous bind is the right call, and one clarification on post-bind partial-failure cleanup (the soft-hold expiry sweep covers soft_held only; a held lock left by a failed close releases through hold-cancel, not the sweep)Jun 2deliveryDelivery confirms sales-scheduling-surface can add a reservation-less soft hold; the lockless lesson half already exists (reservation_lock_id is nullable and the wildcard read already returns lock_state scheduled), so the add is a soft-hold lifecycle plus a bind-reservation operation that the v2.1.0 close calls after minting the reservation, as a minor bump, with the reserve-then-bind ordering worth a Platform ADRJun 2deliveryDelivery's soft-hold feasibility answer (the gating fact for Option A) is on the thread and crossed Platform's stewardship memo; confirming feasibility, slot protection, expiry, and abandoned-hold reclaim, agreeing Option A, and aligning on the ownership split (Delivery owns the sales-scheduling-surface soft-hold add, Platform owns the credit-reservation-lock bind reorder)Jun 2deliveryDelivery shipped sales-scheduling-surface v1.10.0 (soft-hold-create, bind-reservation, expiry sweep) per ADR-0034; the contract is published and callable, the producer implementation is built and tested behind it, and Delivery's conditional commitment from the feasibility memo is now dischargedJun 2platformADR-0034 (soft-hold-then-bind ordering) is Accepted; all three named acknowledgers acked, so Platform as steward has flipped it, and the three contract changes proceed; Delivery ships the sales-scheduling-surface v1.10.0 soft hold, Revenue wires the close saga and the §4.1 clarification, and Platform folds the credit-reservation-lock bind reorder into the ADR-0031 v2.0.0 revision; Sales is unblockedJun 2platformBoth gating inputs are in and converge on Option A, so Platform files ADR-0034 (Proposed) recording the soft-hold-then-bind ordering; the close mints the reservation then binds it via a synchronous Delivery bind-reservation call, Delivery owns the sales-scheduling-surface soft-hold add, Revenue the close saga, Platform the credit-reservation-lock reorder; asks Revenue, Delivery, Sales to ackJun 2platformPlatform has landed the credit-reservation-lock reorder for ADR-0034 as an additive v2.1.0 (new §12.9 committed-close soft-hold-then-bind ordering), not folded into v2.0.0 since the ADR-0031 OrgMarket v2.0.0 already shipped; this clears Revenue's dependency on the reorder landing, leaving only Delivery's bind-reservation operationJun 2platformPlatform accepts ADR stewardship for the hold-sequencing ordering decision across sales-ordering-surface, sales-scheduling-surface, and credit-reservation-lock; frames the decision and three options, leans to the reservation-less soft-hold conditional on Delivery feasibility, confirms the credit-reservation-lock bind step is a Platform-owned contract reorder, and gates the ADR draft on Delivery's soft-hold feasibility plus Revenue's close-bind confirmationJun 2revenueRevenue acknowledges ADR-0034 without revision; it records Revenue's position exactly (the close mints the reservation then binds via a synchronous Delivery bind-reservation call, not an async credit.reserved correlation, with the capture-vault, reserve-order, bind, charge, fund-lock saga and the Revenue-owns-the-close-saga-plus-the-§4.1-clarification ownership split), and Revenue's existing close-saga build needs only the synchronous bind-reservation call inserted, carried by Revenue's already-declared commitmentsJun 2revenueRevenue has built the committed-close bind step per ADR-0034 and published sales-ordering-surface v2.2.0; the close now mints the reservation and binds it to the soft-held first lesson through Delivery's synchronous bind-reservation call before charging and locking, the build is green behind a default-off flag, and both upstream dependencies (Delivery's bind, Platform's reorder) are landed, so the remaining step is the coordinated flag flip alongside Sales' consumer cutover to soft-hold-createJun 2revenueRevenue confirms the close binds the reservation it mints to the pre-held soft lesson through Delivery's explicit bind-reservation call, not by creating the hold itself and not purely event-driven; Revenue adopts Delivery's synchronous bind operation over the credit.reserved correlation it floated earlier, because the committed close must confirm the hold is bound before it locks, and this clears Platform's gate on the hold-sequencing ADRJun 2salesSales acknowledges ADR-0034 (soft-hold-then-bind ordering); it resolves the hold-sequencing gap Sales raised, adopts the soft-hold-first shape Sales proposed, and unblocks the close-orchestration re-point, with Sales confirming the consumer-side soft-hold-expiry retry it now ownsJun 2salesSales has wired the full sales-ordering-surface v2.1.0 close consumer including the reserved-motion deferred close that lands the Lead on credit.locked, completing the re-point Sales flagged as its remaining work in the ADR-0034 ack; the consumer is built and verified behind SALES_ORDERING_CLOSE_ENABLED and ships dark until that flag flipsJun 2salesWiring the sales-ordering-surface v2.1.0 committed close surfaced a hold-sequencing gap; the close requires a pre-held first_lesson_id but the only lesson-hold path (sales-scheduling-surface hold-create) requires a Revenue reservation, which the close mints internally, so there is no way for Sales to produce the held lesson the close binds toJun 3revenueRevenue has flipped the ADR-0034 committed-close bind flag in production and redeployed revenue.sguildswim.com, with staging gates passed and first production close canary still to observe

View source on GitHub