import%20marimo%0A%0A__generated_with%20%3D%20%220.25.0%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%0A%20%20%20%20from%20increment%20import%20Analysis%2C%20AnalysisPlan%2C%20InferenceSpec%2C%20MetricSpec%0A%20%20%20%20from%20increment.semantics.design%20import%20Encouragement%2C%20ExclusionRestriction%2C%20UptakeSpec%0A%20%20%20%20from%20increment.tables%20import%20estimates_to_readout%2C%20readout_table%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20Analysis%2C%0A%20%20%20%20%20%20%20%20AnalysisPlan%2C%0A%20%20%20%20%20%20%20%20Encouragement%2C%0A%20%20%20%20%20%20%20%20ExclusionRestriction%2C%0A%20%20%20%20%20%20%20%20InferenceSpec%2C%0A%20%20%20%20%20%20%20%20MetricSpec%2C%0A%20%20%20%20%20%20%20%20UptakeSpec%2C%0A%20%20%20%20%20%20%20%20estimates_to_readout%2C%0A%20%20%20%20%20%20%20%20mo%2C%0A%20%20%20%20%20%20%20%20np%2C%0A%20%20%20%20%20%20%20%20pd%2C%0A%20%20%20%20%20%20%20%20readout_table%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Encouragement%20design%0A%0A%20%20%20%20Randomize%20a%20**prompt**%2C%20then%20estimate%20the%20effect%20of%20the%20behavior%20it%20changes.%0A%20%20%20%20Everyone%20has%20the%20help%20button%3B%20only%20the%20encouragement%20is%20assigned.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.vstack(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.Html(r%22%22%22%0A%20%20%20%20%3Cstyle%3E%0A%20%20%20%20.enc-diagram%20%7B%20max-width%3A%20920px%3B%20margin%3A%200%20auto%201.5rem%3B%20%7D%0A%20%20%20%20.enc-legend%20%7B%20display%3A%20flex%3B%20flex-wrap%3A%20wrap%3B%20gap%3A%201rem%3B%20justify-content%3A%20center%3B%20margin%3A%20.5rem%200%201.25rem%3B%20font-size%3A%20.85rem%3B%20%7D%0A%20%20%20%20.enc-key%20%7B%20display%3A%20flex%3B%20align-items%3A%20center%3B%20gap%3A%20.4rem%3B%20%7D%0A%20%20%20%20.enc-dot%20%7B%20width%3A%20.75rem%3B%20height%3A%20.75rem%3B%20border-radius%3A%20.2rem%3B%20display%3A%20inline-block%3B%20%7D%0A%20%20%20%20.enc-stage%20%7B%20display%3A%20grid%3B%20grid-template-columns%3A%209rem%20minmax(0%2C%201fr)%209rem%3B%20gap%3A%201rem%3B%20align-items%3A%20center%3B%20margin%3A%20.8rem%200%3B%20%7D%0A%20%20%20%20.enc-stage-label%20%7B%20text-align%3A%20right%3B%20font-weight%3A%20650%3B%20color%3A%20var(--slate-11)%3B%20%7D%0A%20%20%20%20.enc-stage-content%20%7B%20grid-column%3A%202%3B%20display%3A%20flex%3B%20gap%3A%201rem%3B%20justify-content%3A%20center%3B%20align-items%3A%20stretch%3B%20%7D%0A%20%20%20%20.enc-box%20%7B%20flex%3A%201%3B%20max-width%3A%2019rem%3B%20border%3A%201.5px%20solid%20var(--slate-7)%3B%20border-radius%3A%20.8rem%3B%20padding%3A%201rem%3B%20text-align%3A%20center%3B%20background%3A%20var(--slate-1)%3B%20%7D%0A%20%20%20%20.enc-box%20strong%20%7B%20display%3A%20block%3B%20margin-bottom%3A%20.25rem%3B%20%7D%0A%20%20%20%20.enc-instrument%20%7B%20border-color%3A%20%236c5ce7%3B%20background%3A%20%23f4f1ff%3B%20%7D%0A%20%20%20%20.enc-treatment%20%7B%20border-color%3A%20%2300a884%3B%20background%3A%20%23edfbf7%3B%20%7D%0A%20%20%20%20.enc-outcome%20%7B%20border-color%3A%20%23e67e22%3B%20background%3A%20%23fff5eb%3B%20%7D%0A%20%20%20%20.enc-arrow%20%7B%20text-align%3A%20center%3B%20color%3A%20var(--slate-9)%3B%20font-size%3A%201.3rem%3B%20line-height%3A%201%3B%20%7D%0A%20%20%20%20.enc-phone%20%7B%20width%3A%205.5rem%3B%20margin%3A%20.6rem%20auto%200%3B%20border%3A%202px%20solid%20%2334495e%3B%20border-radius%3A%20.7rem%3B%20padding%3A%20.55rem%20.45rem%20.45rem%3B%20background%3A%20white%3B%20%7D%0A%20%20%20%20.enc-line%20%7B%20height%3A%20.35rem%3B%20background%3A%20%23dfe6e9%3B%20border-radius%3A%20.25rem%3B%20margin%3A%20.3rem%200%3B%20%7D%0A%20%20%20%20.enc-button%20%7B%20background%3A%20%2300a884%3B%20color%3A%20white%3B%20border-radius%3A%20.35rem%3B%20padding%3A%20.35rem%20.2rem%3B%20margin-top%3A%20.55rem%3B%20font-size%3A%20.7rem%3B%20%7D%0A%20%20%20%20.enc-prompt%20%7B%20background%3A%20%236c5ce7%3B%20color%3A%20white%3B%20border-radius%3A%20.4rem%3B%20padding%3A%20.35rem%3B%20font-size%3A%20.65rem%3B%20margin-bottom%3A%20.4rem%3B%20transform%3A%20rotate(-2deg)%3B%20%7D%0A%20%20%20%20.enc-results%20%7B%20display%3A%20grid%3B%20grid-template-columns%3A%20repeat(3%2C%201fr)%3B%20gap%3A%20.65rem%3B%20margin%3A%201.25rem%20auto%20.8rem%3B%20max-width%3A%2047rem%3B%20%7D%0A%20%20%20%20.enc-result%20%7B%20border-top%3A%204px%20solid%20%236c5ce7%3B%20border-radius%3A%20.55rem%3B%20padding%3A%20.8rem%3B%20background%3A%20var(--slate-1)%3B%20%7D%0A%20%20%20%20.enc-assumption%20%7B%20max-width%3A%2047rem%3B%20margin%3A%201rem%20auto%200%3B%20padding%3A%20.75rem%201rem%3B%20border-left%3A%204px%20solid%20%23e67e22%3B%20background%3A%20%23fff5eb%3B%20border-radius%3A%20.4rem%3B%20%7D%0A%20%20%20%20%40media%20(max-width%3A%20700px)%20%7B%0A%20%20%20%20%20%20.enc-stage%20%7B%20grid-template-columns%3A%201fr%3B%20%7D%0A%20%20%20%20%20%20.enc-stage-label%20%7B%20text-align%3A%20center%3B%20%7D%0A%20%20%20%20%20%20.enc-stage-content%20%7B%20grid-column%3A%201%3B%20flex-direction%3A%20column%3B%20align-items%3A%20center%3B%20%7D%0A%20%20%20%20%20%20.enc-box%20%7B%20width%3A%20100%25%3B%20box-sizing%3A%20border-box%3B%20%7D%0A%20%20%20%20%20%20.enc-results%20%7B%20grid-template-columns%3A%201fr%3B%20%7D%0A%20%20%20%20%7D%0A%20%20%20%20%3C%2Fstyle%3E%0A%20%20%20%20%3Cdiv%20class%3D%22enc-diagram%22%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-legend%22%3E%0A%20%20%20%20%20%20%20%20%3Cspan%20class%3D%22enc-key%22%3E%3Ci%20class%3D%22enc-dot%22%20style%3D%22background%3A%236c5ce7%22%3E%3C%2Fi%3E%20Randomized%20encouragement%3C%2Fspan%3E%0A%20%20%20%20%20%20%20%20%3Cspan%20class%3D%22enc-key%22%3E%3Ci%20class%3D%22enc-dot%22%20style%3D%22background%3A%2300a884%22%3E%3C%2Fi%3E%20Chosen%20treatment%3C%2Fspan%3E%0A%20%20%20%20%20%20%20%20%3Cspan%20class%3D%22enc-key%22%3E%3Ci%20class%3D%22enc-dot%22%20style%3D%22background%3A%23e67e22%22%3E%3C%2Fi%3E%20Outcome%3C%2Fspan%3E%0A%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage%22%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage-label%22%3EAvailable%20to%20everyone%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage-content%22%3E%3Cdiv%20class%3D%22enc-box%22%3E%3Cstrong%3EHelp%20button%3C%2Fstrong%3EEvery%20user%20can%20click%20it.%3C%2Fdiv%3E%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-arrow%22%3E%E2%86%93%20randomize%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage%22%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage-label%22%3EEncouragement%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage-content%22%3E%0A%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-box%20enc-instrument%22%3E%3Cstrong%3EControl%3C%2Fstrong%3ENo%20prompt%3Cdiv%20class%3D%22enc-phone%22%3E%3Cdiv%20class%3D%22enc-line%22%3E%3C%2Fdiv%3E%3Cdiv%20class%3D%22enc-line%22%3E%3C%2Fdiv%3E%3Cdiv%20class%3D%22enc-button%22%3EHelp%3C%2Fdiv%3E%3C%2Fdiv%3E%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-box%20enc-instrument%22%3E%3Cstrong%3EEncouraged%3C%2Fstrong%3EStrong%20prompt%3Cdiv%20class%3D%22enc-phone%22%3E%3Cdiv%20class%3D%22enc-prompt%22%3ENeed%20help%3F%20Try%20this%3C%2Fdiv%3E%3Cdiv%20class%3D%22enc-line%22%3E%3C%2Fdiv%3E%3Cdiv%20class%3D%22enc-button%22%3EHelp%3C%2Fdiv%3E%3C%2Fdiv%3E%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-arrow%22%3E%E2%86%93%20users%20choose%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage%22%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage-label%22%3EUptake%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage-content%22%3E%0A%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-box%20enc-treatment%22%3E%3Cstrong%3E12%25%20click%3C%2Fstrong%3EBaseline%20uptake%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-box%20enc-treatment%22%3E%3Cstrong%3E55%25%20click%3C%2Fstrong%3EEncouraged%20uptake%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-arrow%22%3E%E2%86%93%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage%22%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage-label%22%3EOutcome%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-stage-content%22%3E%3Cdiv%20class%3D%22enc-box%20enc-outcome%22%3E%3Cstrong%3ERevenue%3C%2Fstrong%3EMeasured%20for%20every%20user%3C%2Fdiv%3E%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-results%22%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-result%22%3E%3Cstrong%3EITT%3C%2Fstrong%3E%3Cbr%3EEffect%20of%20the%20prompt%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-result%22%20style%3D%22border-color%3A%2300a884%22%3E%3Cstrong%3EUptake%3C%2Fstrong%3E%3Cbr%3E55%25%20%E2%88%92%2012%25%20%3D%2043%20pp%3C%2Fdiv%3E%0A%20%20%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-result%22%20style%3D%22border-color%3A%23e67e22%22%3E%3Cstrong%3ELATE%3C%2Fstrong%3E%3Cbr%3EEffect%20of%20clicking%20for%20compliers%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%20%20%3Cdiv%20class%3D%22enc-assumption%22%3E%3Cstrong%3ERequired%20assumptions%3A%3C%2Fstrong%3E%20the%20prompt%20affects%20revenue%20only%20through%20clicking%2C%20and%20no%20user%20would%20click%20without%20the%20prompt%20but%20refuse%20when%20prompted.%3C%2Fdiv%3E%0A%20%20%20%20%3C%2Fdiv%3E%0A%20%20%20%20%22%22%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Simulate%20user-level%20data%0A%0A%20%20%20%20One%20row%20per%20user%3A%20assigned%20prompt%2C%20click%2C%20and%20revenue.%20A%20shared%20latent%20uptake%20threshold%20makes%20the%20simulated%20click%20response%20monotone%3A%20the%20prompt%20can%20create%20clicks%2C%20not%20deter%20them.%0A%20%20%20%20%22%22%22)%2C%0A%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20pd)%3A%0A%20%20%20%20def%20simulate_encouragement(%0A%20%20%20%20%20%20%20%20rng%2C%0A%20%20%20%20%20%20%20%20n_per_arm%2C%0A%20%20%20%20%20%20%20%20control_uptake%2C%0A%20%20%20%20%20%20%20%20encouraged_uptake%2C%0A%20%20%20%20%20%20%20%20tau%2C%0A%20%20%20%20%20%20%20%20base%3D20.0%2C%0A%20%20%20%20%20%20%20%20noise_sd%3D6.0%2C%0A%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Two-sided%20encouragement%20with%20monotone%20latent%20uptake%20thresholds.%22%22%22%0A%20%20%20%20%20%20%20%20rows%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20group%2C%20uptake_rate%20in%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20(%22control%22%2C%20control_uptake)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20(%22encouraged%22%2C%20encouraged_uptake)%2C%0A%20%20%20%20%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20uptake_rank%20%3D%20rng.uniform(size%3Dn_per_arm)%0A%20%20%20%20%20%20%20%20%20%20%20%20clicked%20%3D%20(uptake_rank%20%3C%20uptake_rate).astype(int)%0A%20%20%20%20%20%20%20%20%20%20%20%20revenue%20%3D%20base%20%2B%20tau%20*%20clicked%20%2B%20rng.normal(0%2C%20noise_sd%2C%20size%3Dn_per_arm)%0A%20%20%20%20%20%20%20%20%20%20%20%20rows.extend(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(f%22%7Bgroup%5B0%5D%7D%7Bi%3A04d%7D%22%2C%20group%2C%20float(revenue%5Bi%5D)%2C%20int(clicked%5Bi%5D))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20i%20in%20range(n_per_arm)%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20return%20pd.DataFrame(rows%2C%20columns%3D%5B%22user_id%22%2C%20%22variant%22%2C%20%22revenue%22%2C%20%22clicked%22%5D)%0A%0A%20%20%20%20encouragement_df%20%3D%20simulate_encouragement(%0A%20%20%20%20%20%20%20%20np.random.default_rng(42)%2C%0A%20%20%20%20%20%20%20%20n_per_arm%3D1500%2C%0A%20%20%20%20%20%20%20%20control_uptake%3D0.12%2C%0A%20%20%20%20%20%20%20%20encouraged_uptake%3D0.55%2C%0A%20%20%20%20%20%20%20%20tau%3D18.0%2C%0A%20%20%20%20)%0A%20%20%20%20encouragement_df.head()%0A%20%20%20%20return%20encouragement_df%2C%20simulate_encouragement%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20Analysis%2C%0A%20%20%20%20Encouragement%2C%0A%20%20%20%20ExclusionRestriction%2C%0A%20%20%20%20UptakeSpec%2C%0A%20%20%20%20encouragement_df%2C%0A)%3A%0A%20%20%20%20encouragement_design%20%3D%20Encouragement(%0A%20%20%20%20%20%20%20%20control_group%3D%22control%22%2C%0A%20%20%20%20%20%20%20%20uptake%3DUptakeSpec(fact%3D%22clicked%22)%2C%0A%20%20%20%20%20%20%20%20exclusion_restriction%3DExclusionRestriction(%0A%20%20%20%20%20%20%20%20%20%20%20%20acknowledged%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20justification%3D%22the%20randomized%20prompt%20affects%20revenue%20only%20through%20help-button%20clicks%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20one_sided%3DFalse%2C%0A%20%20%20%20)%0A%20%20%20%20encouragement_results%20%3D%20Analysis.from_unit_summary(%0A%20%20%20%20%20%20%20%20encouragement_df%2C%0A%20%20%20%20%20%20%20%20unit%3D%22user_id%22%2C%0A%20%20%20%20%20%20%20%20group%3D%22variant%22%2C%0A%20%20%20%20%20%20%20%20metrics%3D%7B%22revenue%22%3A%20%22mean%22%7D%2C%0A%20%20%20%20%20%20%20%20design%3Dencouragement_design%2C%0A%20%20%20%20).run()%0A%20%20%20%20return%20encouragement_design%2C%20encouragement_results%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(encouragement_df%2C%20encouragement_results%2C%20mo)%3A%0A%20%20%20%20_itt%20%3D%20next(r%20for%20r%20in%20encouragement_results%20if%20r.estimand%20%3D%3D%20%22itt%22)%0A%20%20%20%20_uptake%20%3D%20encouragement_df.groupby(%22variant%22)%5B%22clicked%22%5D.mean()%0A%20%20%20%20_control_uptake%20%3D%20float(_uptake%5B%22control%22%5D)%0A%20%20%20%20_encouraged_uptake%20%3D%20float(_uptake%5B%22encouraged%22%5D)%0A%20%20%20%20_uptake_difference%20%3D%20_encouraged_uptake%20-%20_control_uptake%0A%20%20%20%20_late%20%3D%20next(%0A%20%20%20%20%20%20%20%20r%20for%20r%20in%20encouragement_results%20if%20r.estimand%20%3D%3D%20%22late%22%20and%20r.value_scale%20%3D%3D%20%22relative%22%0A%20%20%20%20)%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22%22%22%0A%20%20%20%20%23%23%20Results%0A%0A%20%20%20%20-%20**ITT%20%E2%80%94%20prompt%3A**%20%7B_itt.lift.value%3A%2B.1%25%7D%20revenue%20lift%0A%20%20%20%20-%20**Uptake%20%E2%80%94%20clicking%3A**%20%7B_uptake_difference%20*%20100%3A%2B.1f%7D%20percentage%20points%20(%7B_encouraged_uptake%3A.1%25%7D%20vs%20%7B_control_uptake%3A.1%25%7D)%0A%20%20%20%20-%20**LATE%20%E2%80%94%20clicking%20for%20compliers%3A**%20%7B_late.lift.value%3A%2B.1%25%7D%20revenue%20lift%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%22%22%22%0A%20%20%20%20%23%23%23%20Intervals%20and%20assumptions%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(encouragement_results%2C%20estimates_to_readout%2C%20readout_table)%3A%0A%20%20%20%20readout_table(%0A%20%20%20%20%20%20%20%20estimates_to_readout(%5Br%20for%20r%20in%20encouragement_results%20if%20r.estimand%20%3D%3D%20%22itt%22%5D)%2C%0A%20%20%20%20%20%20%20%20title%3D%22ITT%20%E2%80%94%20effect%20of%20the%20prompt%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(encouragement_results%2C%20estimates_to_readout%2C%20readout_table)%3A%0A%20%20%20%20readout_table(%0A%20%20%20%20%20%20%20%20estimates_to_readout(%5Br%20for%20r%20in%20encouragement_results%20if%20r.estimand%20%3D%3D%20%22compliance%22%5D)%2C%0A%20%20%20%20%20%20%20%20title%3D%22Uptake%20%E2%80%94%20relative%20lift%20in%20clicking%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(encouragement_results%2C%20estimates_to_readout%2C%20readout_table)%3A%0A%20%20%20%20readout_table(%0A%20%20%20%20%20%20%20%20estimates_to_readout(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20r%20in%20encouragement_results%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20r.estimand%20%3D%3D%20%22late%22%20and%20r.value_scale%20%3D%3D%20%22relative%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20title%3D%22LATE%20%E2%80%94%20effect%20of%20clicking%20for%20compliers%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Weak%20encouragement%0A%0A%20%20%20%20LATE%20divides%20ITT%20by%20the%20change%20in%20uptake.%20If%20that%20change%20is%20too%20uncertain%2C%0A%20%20%20%20increment%20omits%20LATE%20but%20still%20reports%20the%20randomized%20ITT.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Analysis%2C%20encouragement_design%2C%20np%2C%20simulate_encouragement)%3A%0A%20%20%20%20weak_df%20%3D%20simulate_encouragement(%0A%20%20%20%20%20%20%20%20np.random.default_rng(7)%2C%0A%20%20%20%20%20%20%20%20n_per_arm%3D40%2C%0A%20%20%20%20%20%20%20%20control_uptake%3D0.12%2C%0A%20%20%20%20%20%20%20%20encouraged_uptake%3D0.16%2C%0A%20%20%20%20%20%20%20%20tau%3D18.0%2C%0A%20%20%20%20)%0A%20%20%20%20weak_results%20%3D%20Analysis.from_unit_summary(%0A%20%20%20%20%20%20%20%20weak_df%2C%0A%20%20%20%20%20%20%20%20unit%3D%22user_id%22%2C%0A%20%20%20%20%20%20%20%20group%3D%22variant%22%2C%0A%20%20%20%20%20%20%20%20metrics%3D%7B%22revenue%22%3A%20%22mean%22%7D%2C%0A%20%20%20%20%20%20%20%20design%3Dencouragement_design%2C%0A%20%20%20%20).run()%0A%20%20%20%20return%20(weak_results%2C)%0A%0A%0A%40app.cell%0Adef%20_(mo%2C%20weak_results)%3A%0A%20%20%20%20_estimands%20%3D%20sorted(%7Br.estimand%20for%20r%20in%20weak_results%7D)%0A%20%20%20%20_compliance%20%3D%20next(r%20for%20r%20in%20weak_results%20if%20r.estimand%20%3D%3D%20%22compliance%22)%0A%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20Reported%3A%20**%7B%22%2C%20%22.join(_estimands)%7D**.%20LATE%20is%20omitted.%0A%0A%20%20%20%20%3E%20%7B_compliance.note%7D%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(estimates_to_readout%2C%20readout_table%2C%20weak_results)%3A%0A%20%20%20%20readout_table(%0A%20%20%20%20%20%20%20%20estimates_to_readout(%5Br%20for%20r%20in%20weak_results%20if%20r.estimand%20%3D%3D%20%22itt%22%5D)%2C%0A%20%20%20%20%20%20%20%20title%3D%22Weak%20encouragement%20%E2%80%94%20ITT%20remains%20valid%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(estimates_to_readout%2C%20readout_table%2C%20weak_results)%3A%0A%20%20%20%20readout_table(%0A%20%20%20%20%20%20%20%20estimates_to_readout(%5Br%20for%20r%20in%20weak_results%20if%20r.estimand%20%3D%3D%20%22compliance%22%5D)%2C%0A%20%20%20%20%20%20%20%20title%3D%22Weak%20encouragement%20%E2%80%94%20uncertain%20uptake%20change%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Monitor%20LATE%20over%20time%0A%0A%20%20%20%20Fixed-horizon%20LATE%20trends%20carry%20a%20repeated-look%20warning.%20Binary%20uptake%0A%20%20%20%20makes%20the%20joint%20LATE%20score%20non-Gaussian%2C%20so%20it%20cannot%20use%20the%20registered%0A%20%20%20%20Gaussian%20likelihood.%20The%20certified%20series%20below%20instead%20monitors%20relative%0A%20%20%20%20uptake%20with%20an%20Always%20valid%20Bernoulli%2FBeta%20model%2C%20declared%20as%0A%20%20%20%20%60InferenceSpec(kind%3D%22always_valid%22%2C%20registration%3D...)%60%20on%20the%20source's%0A%20%20%20%20%60AnalysisPlan%60%20before%20the%20simulation%20runs%20--%20%60always_valid%60%20inference%20is%0A%20%20%20%20read%20from%20that%20declaration%2C%20never%20passed%20at%20call%20time.%20Both%20series%20use%0A%20%20%20%20%60completed_windows_only%3DTrue%60%2C%20so%20every%20displayed%20date%20admits%20a%20unit%0A%20%20%20%20only%20once%20its%20finalized%20outcome%20and%20uptake%20windows%20have%20closed.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(%0A%20%20%20%20Analysis%2C%0A%20%20%20%20AnalysisPlan%2C%0A%20%20%20%20Encouragement%2C%0A%20%20%20%20ExclusionRestriction%2C%0A%20%20%20%20InferenceSpec%2C%0A%20%20%20%20MetricSpec%2C%0A%20%20%20%20UptakeSpec%2C%0A%20%20%20%20np%2C%0A%20%20%20%20pd%2C%0A%20%20%20%20simulate_encouragement%2C%0A)%3A%0A%20%20%20%20from%20increment%20import%20(%0A%20%20%20%20%20%20%20%20JointReveal%2C%0A%20%20%20%20%20%20%20%20PredictivePrior%2C%0A%20%20%20%20%20%20%20%20SequentialCell%2C%0A%20%20%20%20%20%20%20%20SequentialCompliancePolicy%2C%0A%20%20%20%20%20%20%20%20SequentialModel%2C%0A%20%20%20%20%20%20%20%20SequentialRegistration%2C%0A%20%20%20%20)%0A%20%20%20%20from%20increment.frame%20import%20synthesise_metric%0A%20%20%20%20from%20increment.sequential_source%20import%20frame_observation_mapping%2C%20sequential_definition_id%0A%0A%20%20%20%20_window_days%20%3D%207%0A%20%20%20%20_design%20%3D%20Encouragement(%0A%20%20%20%20%20%20%20%20control_group%3D%22control%22%2C%0A%20%20%20%20%20%20%20%20uptake%3DUptakeSpec(fact%3D%22clicked%22%2C%20window_days%3D_window_days)%2C%0A%20%20%20%20%20%20%20%20exclusion_restriction%3DExclusionRestriction(%0A%20%20%20%20%20%20%20%20%20%20%20%20acknowledged%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20justification%3D%22the%20randomized%20prompt%20affects%20revenue%20only%20through%20help-button%20clicks%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20one_sided%3DFalse%2C%0A%20%20%20%20)%0A%20%20%20%20_specs%20%3D%20%5BMetricSpec(name%3D%22revenue%22%2C%20type%3D%22mean%22%2C%20window_days%3D_window_days)%5D%0A%20%20%20%20_prior%20%3D%20PredictivePrior(kind%3D%22beta%22%2C%20a%3D1%2C%20b%3D1)%0A%20%20%20%20_registration%20%3D%20SequentialRegistration(%0A%20%20%20%20%20%20%20%20source_id%3D%22help_button_prompt%22%2C%0A%20%20%20%20%20%20%20%20control_group%3D%22control%22%2C%0A%20%20%20%20%20%20%20%20committed_before_data%3DTrue%2C%0A%20%20%20%20%20%20%20%20definitions_id%3Dsequential_definition_id(%0A%20%20%20%20%20%20%20%20%20%20%20%20%5Bsynthesise_metric(spec)%20for%20spec%20in%20_specs%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_design%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20transformations%3D_specs%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20source_mapping%3Dframe_observation_mapping(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20unit%3D%22user_id%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20group%3D%22variant%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20date%3D%22ds%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20exposure_date%3D%22exposed_on%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20uptake%3D%22clicked%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20reveal%3DJointReveal(%0A%20%20%20%20%20%20%20%20%20%20%20%20filtration_id%3D%22help-button-finalized-units%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20independent_unit_vectors%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20simultaneous_metrics%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20outcome_independent_order%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20immutable_finalized_outcomes%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20longest_window_days%3D_window_days%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20models%3D(%0A%20%20%20%20%20%20%20%20%20%20%20%20SequentialModel(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20metric%3D%22uptake%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20observable%3D%22uptake%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20law%3D%22bernoulli%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20control_prior%3D_prior%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20treatment_prior%3D_prior%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20positive_population_control%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20roster%3D(SequentialCell(metric%3D%22uptake%22%2C%20group_id%3D%22encouraged%22%2C%20estimand%3D%22compliance%22)%2C)%2C%0A%20%20%20%20)%0A%20%20%20%20_registered_plan%20%3D%20AnalysisPlan(%0A%20%20%20%20%20%20%20%20inference%3DInferenceSpec(kind%3D%22always_valid%22%2C%20registration%3D_registration)%2C%0A%20%20%20%20%20%20%20%20compliance%3DSequentialCompliancePolicy(alpha%3D_registration.roster%5B0%5D.alpha)%2C%0A%20%20%20%20)%0A%20%20%20%20_rng%20%3D%20np.random.default_rng(3)%0A%20%20%20%20%23%20Staggered%20enrollment%20over%2021%20days%2C%20so%20day_index%20varies%20across%20units%0A%20%20%20%20%23%20even%20though%20%60simulate_encouragement%60%20realizes%20each%20outcome%20once.%0A%20%20%20%20_sim%20%3D%20simulate_encouragement(%0A%20%20%20%20%20%20%20%20_rng%2C%0A%20%20%20%20%20%20%20%20n_per_arm%3D250%2C%0A%20%20%20%20%20%20%20%20control_uptake%3D0.12%2C%0A%20%20%20%20%20%20%20%20encouraged_uptake%3D0.55%2C%0A%20%20%20%20%20%20%20%20tau%3D18.0%2C%0A%20%20%20%20).reset_index(drop%3DTrue)%0A%20%20%20%20_enroll%20%3D%20list(pd.date_range(%222026-03-01%22%2C%20periods%3D21%2C%20freq%3D%22D%22).date)%0A%20%20%20%20_sim%5B%22user_id%22%5D%20%3D%20%22u%22%20%2B%20_sim.index.astype(str)%0A%20%20%20%20_sim%5B%22exposed_on%22%5D%20%3D%20np.array(_enroll)%5B_sim.index%20%25%20len(_enroll)%5D%0A%20%20%20%20%23%20Keep%20outcome%20and%20completion%20rows%3B%20%60%60from_unit_panel%60%60%20densifies%20the%0A%20%20%20%20%23%20intervening%20days%20and%20admits%20each%20cohort%20once%20both%20windows%20are%20complete.%0A%20%20%20%20_exposure_rows%20%3D%20_sim.assign(ds%3D_sim%5B%22exposed_on%22%5D)%0A%20%20%20%20_completion_rows%20%3D%20_sim.assign(%0A%20%20%20%20%20%20%20%20ds%3D_sim%5B%22exposed_on%22%5D%20%2B%20pd.Timedelta(days%3D_window_days)%2C%20revenue%3D0.0%2C%20clicked%3D0.0%0A%20%20%20%20)%0A%20%20%20%20_panel%20%3D%20pd.concat(%5B_exposure_rows%2C%20_completion_rows%5D%2C%20ignore_index%3DTrue)%5B%0A%20%20%20%20%20%20%20%20%5B%22user_id%22%2C%20%22variant%22%2C%20%22ds%22%2C%20%22exposed_on%22%2C%20%22revenue%22%2C%20%22clicked%22%5D%0A%20%20%20%20%5D%0A%20%20%20%20_analysis%20%3D%20Analysis.from_unit_panel(%0A%20%20%20%20%20%20%20%20_panel%2C%0A%20%20%20%20%20%20%20%20unit%3D%22user_id%22%2C%0A%20%20%20%20%20%20%20%20group%3D%22variant%22%2C%0A%20%20%20%20%20%20%20%20date%3D%22ds%22%2C%0A%20%20%20%20%20%20%20%20metrics%3D%5BMetricSpec(name%3D%22revenue%22%2C%20type%3D%22mean%22%2C%20window_days%3D_window_days)%5D%2C%0A%20%20%20%20%20%20%20%20design%3D_design%2C%0A%20%20%20%20%20%20%20%20exposure_date%3D%22exposed_on%22%2C%0A%20%20%20%20%20%20%20%20experiment_id%3D%22help_button_prompt%22%2C%0A%20%20%20%20)%0A%20%20%20%20_av_analysis%20%3D%20Analysis.from_unit_panel(%0A%20%20%20%20%20%20%20%20_panel%2C%0A%20%20%20%20%20%20%20%20unit%3D%22user_id%22%2C%0A%20%20%20%20%20%20%20%20group%3D%22variant%22%2C%0A%20%20%20%20%20%20%20%20date%3D%22ds%22%2C%0A%20%20%20%20%20%20%20%20metrics%3D%5BMetricSpec(name%3D%22revenue%22%2C%20type%3D%22mean%22%2C%20window_days%3D_window_days)%5D%2C%0A%20%20%20%20%20%20%20%20design%3D_design%2C%0A%20%20%20%20%20%20%20%20plan%3D_registered_plan%2C%0A%20%20%20%20%20%20%20%20exposure_date%3D%22exposed_on%22%2C%0A%20%20%20%20%20%20%20%20experiment_id%3D%22help_button_prompt%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20def%20_late_trend(results)%3A%0A%20%20%20%20%20%20%20%20return%20%5Brow%20for%20row%20in%20results%20if%20row.estimand%20%3D%3D%20%22late%22%20and%20row.value_scale%20%3D%3D%20%22relative%22%5D%0A%0A%20%20%20%20fixed_late_trend%20%3D%20_late_trend(_analysis.run_asof_lift(completed_windows_only%3DTrue))%0A%20%20%20%20uptake_trend%20%3D%20%5B%5D%0A%20%20%20%20for%20_day%20in%20sorted(set(_completion_rows%5B%22ds%22%5D))%3A%0A%20%20%20%20%20%20%20%20_av_analysis.capture_sequential(finalized%3DTrue%2C%20as_of%3D_day)%0A%20%20%20%20%20%20%20%20uptake_trend.extend(%0A%20%20%20%20%20%20%20%20%20%20%20%20_av_analysis.run_asof_lift(estimands%3D(%22compliance%22%2C)%2C%20completed_windows_only%3DTrue)%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20return%20fixed_late_trend%2C%20uptake_trend%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(pd%2C%20uptake_trend)%3A%0A%20%20%20%20pd.DataFrame(%0A%20%20%20%20%20%20%20%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22ds%22%3A%20r.ds%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22uptake_lift%22%3A%20None%20if%20r.lift%20is%20None%20else%20r.lift.value%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22lb%22%3A%20r.sequential_result.bounds.lower%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22ub%22%3A%20r.sequential_result.bounds.upper%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22inference%22%3A%20r.inference%2C%0A%20%20%20%20%20%20%20%20%7D%0A%20%20%20%20%20%20%20%20for%20r%20in%20uptake_trend%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(fixed_late_trend%2C%20mo%2C%20uptake_trend)%3A%0A%20%20%20%20_fixed_last%20%3D%20fixed_late_trend%5B-1%5D%0A%20%20%20%20_av_last%20%3D%20uptake_trend%5B-1%5D%0A%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20-%20**Fixed%20alpha%3A**%20%5B%7B_fixed_last.lift.lb%3A%2B.1%25%7D%2C%20%7B_fixed_last.lift.ub%3A%2B.1%25%7D%5D%20%E2%80%94%20repeated-look%20warning%0A%20%20%20%20-%20**Registered%20uptake%3A**%20%7B_av_last.sequential_result.bounds%7D%20%E2%80%94%20ratio-coordinate%20confidence%20sequence%0A%0A%20%20%20%20The%20rows%20answer%20different%20questions%3A%20the%20causal%20effect%20among%20compliers%20and%20the%20randomized%20uptake%20contrast.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
afab064453b52641ad84e0542ccd79ee