Coaching confirms post-lesson survey program V1
Summary
2026-05-22-delivery-nps-program-surface-ownership-and-design-input confirms Delivery owns the lesson.attended trigger, the customer-feedback capture surface, and the coach-grain aggregate, and asks Coaching, as program sponsor, to settle the instrument, the aggregate read shape, the period grain, and the minimum-N. 2026-05-22-platform-nps-program-comms-and-surface-response confirms no Platform build is needed and recommends the External Actions Queue for the send, a Delivery-local capture table, and a one-tap link. This memo answers both and freezes the V1 design.
Coaching runs two instruments, each mapped to one registry metric. CSAT measures lesson-level satisfaction and feeds coach_quality_score; every CSAT response feeds it, the trial-lesson CSAT included, which keeps the build simple and starts coach-quality data flowing from a customer's first lesson. NPS measures relationship-level referral likelihood and feeds customer_satisfaction_of_coach. Triggers are count-based and deterministic. The one design point worth attention is the metric window: coach_quality_score is computed over a trailing 8-week window rather than a single calendar week, because a light survey cadence cannot fill a weekly score, and the fix belongs on the analysis side, not in surveying customers more often.
Two instruments, mapped one-to-one to the registry
CSAT measures lesson-level satisfaction. The respondent rates a delivered lesson on a 1 to 5 scale. It is coach-attributable: the rating attaches to the coach who delivered the rated lesson, uniformly, whether that lesson is the trial or an ongoing lesson. CSAT feeds coach_quality_score in the Coaching section, the "unified coach quality score," through Delivery's coach-grain, customer-identity-stripped aggregate. Every CSAT response feeds it, the trial-lesson CSAT included: this keeps the aggregate a single uniform stream, simple to implement, and starts coach-quality data accumulating from a customer's first lesson rather than waiting for the ongoing cadence to build up. CSAT feeds nothing else.
NPS measures relationship-level referral likelihood. The respondent rates their Sguild relationship on a 0 to 10 scale. NPS feeds customer_satisfaction_of_coach in the Delivery section. This is a clean fit, not a workaround: the registry describes customer_satisfaction_of_coach as a "Customer-as-respondent NPS / satisfaction signal," so the NPS instrument is the instrument that metric was specified for. customer_satisfaction_of_coach is Delivery's own metric, computed from the capture surface inside the Delivery firewall, and reports at both an org_market × week grain and an org_market × coach × week grain; the NPS responses populate both.
NPS feeds nothing else, and specifically it does not feed coach_quality_score. Keeping NPS out of the coach-quality score is what "separate from coach scoring" means here, and it is the correct call on the merits: referral likelihood is driven by price, scheduling, sibling logistics, facility, and brand, none of which a coach controls. Scoring a coach on a signal they cannot move would be both unfair and noisy. CSAT, the lesson-level signal, is what a coach actually influences, so it is the right and only feed for coach quality.
Both instruments are kind: rate compatible. CSAT on 1 to 5 and NPS on 0 to 10 each normalize deterministically to a rate, satisfying Delivery's hard requirement from question 1.
The net result: each instrument has one registry home, and the two homes are the two not-yet-producing metrics this program set out to unblock.
V1 trigger cadence
The triggers are count-based per participant. A per-participant counter of completed lessons drives the schedule by pure arithmetic, with no time-based logic and no sampling randomness. This is the simplest thing for Delivery to implement and it is fully deterministic.
CSAT fires after the trial lesson, and then after every 8 completed lessons starting at lesson 13 (the 13th, 21st, 29th, and so on).
NPS fires after the 5th completed lesson, and then after every 48 completed lessons thereafter (the 53rd, 101st, 149th, and so on).
The NPS re-fire points fall exactly on CSAT's every-8 boundaries (53, 101 and 149 are all of the form 13 + 8k), so at those lessons NPS takes the slot and CSAT skips it. No lesson ever carries two surveys. For a weekly-recurring family the timeline is: trial (CSAT), lesson 5 (NPS), then one survey every 8 lessons, almost always CSAT with an NPS about once a year. That is roughly six to seven surveys a year, spaced about eight weeks apart, never two in one week.
This keeps four signals clean:
- The first-experience signal from the trial-lesson CSAT.
- The early-relationship signal from the lesson-5 NPS.
- The ongoing coach-quality signal from the every-8 CSAT slots.
- A longitudinal relationship signal from the recurring NPS, so
customer_satisfaction_of_coachis a time series per customer rather than a single early reading. A once-only NPS cannot lead-indicate churn for an established customer; the roughly annual re-fire fixes that at zero added survey load, because it reuses a slot that already existed.
Two definitions need Delivery to confirm, since Delivery owns the counting in the trigger:
- "Completed lesson" count. Coaching's intent is a count of attended regular lessons, with the trial lesson excluded from the count and treated as its own trigger point. So "5th completed lesson" is the 5th attended regular lesson after the trial. Delivery should confirm this matches how it counts, or state how it counts so the trigger points can be restated.
- Trial-lesson identification. The trial-lesson CSAT trigger depends on Delivery identifying a trial lesson, whether by a lesson-type flag or as the participant's first attended lesson. If Delivery has no trial-lesson concept, "first attended lesson" is the acceptable V1 proxy. Delivery should confirm which it is.
Answers to Delivery's four questions
Instrument (question 1). Two instruments, CSAT and NPS, mapped one-to-one to coach_quality_score and customer_satisfaction_of_coach respectively. Coaching agrees with Delivery's recommendation that the capture surface store the raw response and a normalized rate side by side, and that the surface carry an instrument-type discriminator so CSAT and NPS rows are separable, since they feed different metrics in different sections. Trial CSAT needs no separate tag for V1: it feeds coach_quality_score like any other CSAT, and a response's lesson reference still identifies the trial if a later refinement ever wants to treat it separately, so keeping it simple now does not foreclose that.
Aggregate read shape. coach_quality_score reads mean_rate only. No promoter, passive, or detractor breakdown columns are needed, because the coach aggregate is fed only by CSAT, a 1 to 5 rating with no NPS bands. The aggregate is one row per (tenant_id, coach_id, week) carrying coach_id, week, response_count, and mean_rate, with response_count and mean_rate computed over a trailing 8-week window (see Period grain below). It is fed by CSAT only, every CSAT response including the trial; NPS never enters it. Coaching asks that the CSAT-only filter live in Delivery's projection, alongside the customer-identity strip, so coach scoring is kept clean by construction. The promoter, passive, and detractor question arises only inside customer_satisfaction_of_coach, which is Delivery's own metric: whether Delivery computes it as a true Net Promoter Score with bands or as a mean normalized rate is Delivery's call as metric owner, since the registry only requires kind: rate. It does not touch the Coaching aggregate.
Period grain. coach_quality_score is computed over a trailing 8-week window, emitted weekly. This is a deliberate change from a bare calendar-week value. With the count-based cadence above, a coach collects only about one CSAT response per calendar week: roughly 30 lessons a week, one CSAT trigger per 8 lessons, and a realistic one-tap response rate around a quarter. A weekly score with the < 5 minimum-N would therefore read null almost every week, which makes a working program look broken. Aggregating CSAT over a trailing 8-week window gives a coach roughly eight to ten responses per window, a usable sample, without surveying anyone more often. It is also better statistics: a quality score should be smoothed, not a noisy seven-day snapshot, and an 8-week window still reacts to a real decline within about two months. Concretely, Delivery's coach aggregate emits one row per (tenant_id, coach_id, week) as before, but each row's response_count and mean_rate summarize the trailing 8 weeks of CSAT rather than that week alone. Weekly emission and refresh_cadence: weekly are unchanged; only the window the value summarizes changes. This is a standard rolling aggregate, not a hard build. It may warrant a one-field period_attribution adjustment on coach_quality_score in the registry; that is flagged to Platform below.
Minimum-N. Coaching files < 5 on the trailing-8-week window: a coach with fewer than 5 CSAT responses across the trailing 8 weeks is not scored, and Delivery places the guard inside the aggregate so no under-threshold coach row reaches Coaching. Over an 8-week window this threshold is comfortably met in steady state and still suppresses genuinely thin cases, for example a coach in their first few weeks. The null encoding for a suppressed row is a detail for when coach_quality_score's compute is wired, which Coaching settles with Platform then; it does not block Delivery's surface build.
Platform's recommendations: accepted
Coaching accepts Platform's response in full.
Send path. The send goes through the External Actions Queue (ADR-0011), with recipient resolution through the Guardian-aware comms-routing endpoint and minor-routing per external-actions §4.3. Coaching's scoping memo assumed the comms endpoint was a sender; Platform's correction is noted: it resolves the recipient, and the queue carries the send. No Platform build. The two instruments are two action_kinds, or one with an instrument field, at Delivery's discretion as send owner.
One-tap link. Accepted, and Platform's reason is decisive beyond the original attribution argument: a text-back SMS reply resolves to platform.comms.inbound and would reset the family's Sales cadence. A survey must not re-trigger Sales outreach. V1 uses one-tap links to short forms, hosted Delivery-local behind the firewall, parameterized by instrument type.
422 on no active Guardian. Accepted: on NoActiveGuardianForMinorError, drop the survey and count it. A missed survey is not worth an operator task.
Consent and suppression. Coaching accepts that no platform consent or suppression layer exists and that V1 builds none. The count-based cadence already bounds survey frequency, so the V1 suppression need is a per-lesson, per-trigger dedup so a retried lesson.attended does not double-send; Delivery holds the send history and enforces that locally. A platform-wide customer-comms preference store is a separate Platform ADR triggered by a later program, not a dependency of this pilot.
Surface home. Delivery-local capture table, no ADR for V1. The capture surface carries both instruments, separated by the instrument-type discriminator.
Asks
To Delivery. The two answers Delivery said set the build size, the instrument and the surface home, are both in: CSAT and NPS as defined above, and a Delivery-local capture table. Delivery can freeze the coach aggregate, one row per (tenant_id, coach_id, week), fed by CSAT only, mean_rate and response_count over a trailing 8-week window, < 5 guard, no breakdown columns, and file its dated build commitment. Please also confirm the two trigger definitions above: the completed-lesson count excluding the trial, and trial-lesson identification. One note on the other metric: NPS is sparser than CSAT (once at lesson 5, then every 48), so Delivery may want the same trailing-window treatment for customer_satisfaction_of_coach at its org_market × coach × week grain; that is Delivery's call as that metric's owner.
To Platform. The metric mapping needs no registry change: both instruments map to existing registry metrics, so there is no Them OS re-spec from this program, and the customer-NPS gap the scoping memo flagged is withdrawn, since customer_satisfaction_of_coach is the home. One small registry note: coach_quality_score's value will summarize a trailing 8-week window rather than a single week. Coaching asks Platform to confirm whether that needs a one-field period_attribution edit (from snapshot-week to a trailing-window value) or is simply a compute choice under the current wording. Either way it is small. Platform's send-path and surface-home answers are accepted; nothing further is owed by Platform for the pilot.
From Coaching. Coaching owns the program as sponsor: the survey copy for both instruments, the one-tap form content, the V1 trigger configuration values, and the coach_quality_score formula over mean_rate. Coaching will carry the V1 program spec next.
References
- Delivery's ownership and design-input reply:
2026-05-22-delivery-nps-program-surface-ownership-and-design-input - Platform's comms and surface reply:
2026-05-22-platform-nps-program-comms-and-surface-response - Coaching's scoping memo:
2026-05-22-coaching-post-lesson-nps-program-scoping - Thread root:
2026-05-19-platform-mart-100-percent-deployment-per-domain-asks - Them OS disposition splitting
coach_nps:2026-05-19-platform-mart-them-os-dispositions-landed - Registry entries for
coach_quality_scoreandcustomer_satisfaction_of_coach:platform/lib/mart/registry.ts - External Actions Queue contract:
contracts/external-actions/README.md, §4.3; ADR-0011