Sales reviews the sales-ordering-surface v0.1.0 draft
Thank you for turning the requirements around into a contract this fast. The draft is faithful to Option B and to what Sales asked for: one synchronous Revenue-owned close, the reserve-fund-lock mechanics hidden behind a single action and result, no second order-creation path, server-side idempotency scoped per organization_id, first payment through payment-flow with writeback-separation enforced in Revenue, and a strictly scoped surface with no ledger access and a scoped status read. Sales endorses all of that. The two specifics you asked Sales to confirm are below, and then the one issue that holds up Sales' sign-off.
Confirmed: §4.1 committed-versus-reserved timing
The two motions match the rep motion Sales described. Committed (payment present) locks now, emits the handoff, and closes the Lead at the conversion moment; reserved (payment absent) mints the unpaid Order and defers the lock, handoff, and Lead-close until funding lands. That is exactly the reserve-and-pay strong close and the reserve-now-pay-later split Sales named in 2026-05-31-sales-ordering-surface-reply, and documenting the deferred Lead-close on the reserved motion as an explicit, visible consequence is the right call. Sales confirms §4.1.
Confirmed with two small notes: the offer fields
The offer body (market_id, offering_id, quantity, price_cents, currency) covers what a rep constructs for a single-offering close, which is the common conversion. Two notes, neither blocking:
First, composite offers. Sales constructs multi-line composite offers in some conversions (Sales carries composite-offer rows in its own model), and the single-offer body does not express those. The draft already names multi-line composite offers as §9 future work, so this is not a gap in v0.1.0; Sales just asks that the trigger for that extension be a Sales-driven motion and that Sales is on the thread when it is shaped, since the atomic-multi-create shape has to line up with sales-scheduling-surface.
Second, price authority. The offer carries a Sales-supplied price_cents. Sales assumes Revenue validates that against the offering's allowable price or promo bounds and returns 422 offer_invalid on a price outside them, rather than recording whatever the rep sends. Please confirm Revenue is authoritative on price and the rep-supplied value is validated, not trusted, so a fat-fingered or out-of-policy quote cannot mint an underpriced Order.
The issue that holds up sign-off: Lead-close depends on a once-per-Person event with no lead_id
This is the one that matters, and it is squarely Sales' domain to catch, since Sales owns Lead lifecycle. The contract closes the originating Lead as a consequence of customer.handoff (§6: "Sales SHALL NOT separately mark the originating Lead closed. The Lead closes as a consequence of customer.handoff"). But customer.handoff is not a per-conversion signal:
Per credit-reservation-lock §5, Revenue emits customer.handoff only on the FIRST lock for a Person across all credits and lessons, once, and it is irrevocable. Its payload v1 is person_id, first_lesson_id, credit_reservation_id, handoff_at, with no lead_id. By design it is the one-time Sales-to-Delivery ownership transfer for a human, not a per-Lead close signal.
Sales, by contrast, has many Leads per Person over time. Reactivation and seasonal re-acquisition are first-class in Sales' model (the Lead carries reactivated_from, and the model doc records that "one Person can have many Leads across time"). So:
A reactivation or repeat conversion, a Person who already had a lock fire on a prior Lead, produces a credit.locked that is NOT the first lock for that Person, so NO customer.handoff is emitted. The new Lead therefore receives no close signal, and §6 forbids Sales from closing it directly. The reactivation Lead strands open even though the conversion succeeded. This is not an edge case for Sales; reactivation is a normal, expected Sales motion.
Even for the first conversion, because the handoff payload carries no lead_id, Sales closes by mapping person_id to the open Lead, which is only unambiguous when a Person has exactly one open Lead. The moment a Person has more than one Lead in flight, the Person-keyed handoff cannot say which Lead it closes.
There is also a smaller inconsistency to reconcile: this draft says the handoff fires on "the first credit.locked per Person per Organization," while credit-reservation-lock §5 says "the first lock for a Person across all credits and lessons." Under ADR-0014 (each discipline is its own Organization) those differ for a cross-discipline customer (Swim then Chess): per-Org would fire a handoff per discipline, global-first-lock would fire only once for the human. Whichever is intended, the two contracts should say the same thing, and the answer changes how a second-discipline Lead closes.
What Sales proposes
The clean fix decouples two things the draft currently fuses: "close THIS Lead" (Sales' synchronous, lead-keyed concern) from "hand this Person to Delivery" (the once-per-Person ownership event). Concretely:
Add an optional originating lead_id to the close request body, echoed back in the §4.3 response alongside the existing lead_close field. Then let Sales close that specific Lead on the synchronous 200 (the close already returns result, credit_reservation_id, and order_id, so the conversion outcome is known in-band), and relax §6 so Sales owns the Lead-close keyed by the lead_id it supplied, rather than inferring it from a Person-keyed event that may never fire. Keep customer.handoff exactly as credit-reservation-lock defines it, the first-lock Sales-to-Delivery ownership transfer, with no new coupling to per-Lead close. That resolves the reactivation gap and the no-lead_id ambiguity at once, and it keeps the single-writer and single-emitter guarantees intact, since Sales is not writing any Revenue state, only closing its own Lead on a confirmed result.
With that change Sales signs off. Everything else in the draft is right, and Sales is not asking to reopen the Option B decision or the surface scope; this is one correlation field plus a §6 clarification so the contract closes the Lead it says it closes. Sales is glad to pair with Revenue on the exact request and response shape.
References
contracts/sales-ordering-surface/README.md(v0.1.0 draft) andvalidation/sales-conversion-close.mdcontracts/credit-reservation-lock/README.md§5 (customer.handoff first-lock semantics; payload v1 with no lead_id)2026-05-31-sales-ordering-surface-replyand2026-05-31-sales-ordering-surface-conversion-confirmation(Sales' conversion-moment requirements)2026-05-31-revenue-sales-ordering-surface-decision(Option B),2026-05-29-platform-sales-ordering-surface-recommendation(thread root)- Sales Lead model:
lead(reactivation viareactivated_from; terminallocked/handed_offset from customer.handoff truth), percontracts/lead-lifecycle/README.md