1import{r as N,au as M,j as e,B as V,K,ak as X,C as b,a8 as y,aa as w,a9 as _,b as v,L as Y,W as S,U as J,aD as Q,aI as Z,bp as ee,I as C}from"./index-CwRyDTkN.js";import{T as se,a as te,b as R}from"./tabs-Dl0aRh_n.js";import{T as D,a as W,b as L,c as x,d as z,e as d}from"./table-DPuTNloT.js";import{A as ae,b as re,a as ie}from"./alert-DNmVZxBd.js";import{I as ne}from"./info-BZiUgeXH.js";import{R as le,k as ce,X as oe,Y as de,T as me,B as he,o as xe}from"./generateCategoricalChart-BiZ2bqEV.js";import{B as ue}from"./BarChart-m9dXRF_b.js";import{M as U}from"./minus-CmqZi-Qk.js";import"./isEqual-CVrr51JR.js";import"./string-Dx7P_S-w.js";import"./index-D95X0B-W.js";import"./linear-DGECpK-G.js";import"./init-Dmth1JHB.js";import"./defaultLocale-C4B-KCzX.js";import"./time-ByyzYylg.js";import"./band-CquvqAHh.js";import"./ordinal-DILIJJjt.js";const fe={app_return:1,content_started:2,content_completed:3,active_day:1,dm_reply:2,retained_7d:3,retained_30d:4,subscription_started:8,email_opened:0,email_clicked:0},je=a=>{if(!a||typeof a!="object")return 0;const g=a;let o=0;for(const[f,n]of Object.entries(fe)){if(n===0)continue;const r=g[f];o+=(typeof r=="number"?r:r===!0?1:0)*n}return o},$=(a,g)=>{const o=new Map;for(const n of a){const r=g(n);if(!r)continue;let c=o.get(r.key);c||(c={label:r.label,t:[],h:[]},o.set(r.key,c));const u=je(n.metrics);n.cohort==="holdout"?c.h.push(u):c.t.push(u)}const f=n=>n.length?n.reduce((r,c)=>r+c,0)/n.length:0;return Array.from(o.entries()).map(([n,r])=>{const c=f(r.t),u=f(r.h),k=c-u;return{key:n,label:r.label,treatmentN:r.t.length,treatmentMean:c,holdoutN:r.h.length,holdoutMean:u,absoluteLift:k,relativeLift:u>0?k/u*100:null}}).sort((n,r)=>r.treatmentN+r.holdoutN-(n.treatmentN+n.holdoutN))},h=(a,g=2)=>Number.isFinite(a)?a.toFixed(g):"â",G=({group:a})=>{if(!(a.holdoutN>0))return e.jsxs(S,{variant:"outline",className:"border-border text-muted-foreground",children:[e.jsx(U,{className:"h-3 w-3 mr-1"})," No holdout yet"]});const o=a.absoluteLift>1e-4,f=a.absoluteLift<-1e-4;return e.jsxs(S,{variant:"outline",className:o?"border-primary/30 bg-primary/10 text-primary":f?"border-destructive/30 bg-destructive/10 text-destructive":"border-border text-muted-foreground",children:[o?e.jsx(Z,{className:"h-3 w-3 mr-1"}):f?e.jsx(ee,{className:"h-3 w-3 mr-1"}):e.jsx(U,{className:"h-3 w-3 mr-1"}),a.absoluteLift>=0?"+":"",h(a.absoluteLift),a.relativeLift!==null&&e.jsxs("span",{className:"ml-1 opacity-70",children:["(",a.relativeLift>=0?"+":"",h(a.relativeLift,1),"%)"]})]})},Ee=()=>{const[a,g]=N.useState("7d"),{data:o=[],isLoading:f,isFetching:n,refetch:r}=M({queryKey:["nicole-lift-windows",a],queryFn:async()=>{const{data:s,error:t}=await C.from("nicole_outcome_windows").select("id, cohort, window_label, status, metrics, measured_at, closes_at, experiment_arm_id, decision:nicole_decision_opportunities!nicole_outcome_windows_decision_id_fkey(strategy_id, trigger_type, user_state:nicole_user_states(state_key, lifecycle_stage, engagement_tier))").eq("window_label",a).order("closes_at",{ascending:!1}).limit(1e3);if(t)throw t;return s??[]}}),{data:c=[]}=M({queryKey:["nicole-strategies-lite"],queryFn:async()=>{const{data:s,error:t}=await C.from("nicole_strategies").select("id, code, version");if(t)throw t;return s??[]}}),{data:u=[]}=M({queryKey:["nicole-lift-experiments"],queryFn:async()=>{const{data:s,error:t}=await C.from("nicole_experiments").select("id, bucket_key, state_key, status, champion_weight, challenger_weight, explore_weight").order("updated_at",{ascending:!1});if(t)throw t;return s??[]}}),{data:k=[]}=M({queryKey:["nicole-lift-arms"],queryFn:async()=>{const{data:s,error:t}=await C.from("nicole_experiment_arms").select("id, experiment_id, role, exposures, status");if(t)throw t;return s??[]}}),q=N.useMemo(()=>{const s=new Map;return c.forEach(t=>s.set(t.id,`${t.code} v${t.version}`)),s},[c]),p=N.useMemo(()=>o.filter(s=>s.status==="measured"||s.measured_at!==null),[o]),i=N.useMemo(()=>$(p,()=>({key:"all",label:"All families"}))[0],[p]),T=N.useMemo(()=>$(p,s=>{var m;const t=(m=s.decision)==null?void 0:m.user_state,l=(t==null?void 0:t.lifecycle_stage)??(t==null?void 0:t.state_key);if(!l)return null;const j=t==null?void 0:t.engagement_tier;return{key:`${l}::${j??"unknown"}`,label:j?`${l} · ${j}`:l}}),[p]),F=N.useMemo(()=>$(p,s=>{var l;const t=(l=s.decision)==null?void 0:l.strategy_id;return t?{key:t,label:q.get(t)??t.slice(0,8)}:null}),[p,q]),H=N.useMemo(()=>T.slice(0,10).map(s=>({name:s.label,lift:Number(s.absoluteLift.toFixed(3)),n:s.treatmentN+s.holdoutN})),[T]),I=N.useMemo(()=>{const s=new Map;
1return k.forEach(t=>{const l=s.get(t.experiment_id)??[];l.push(t),s.set(t.experiment_id,l)}),u.map(t=>{const l=s.get(t.id)??[],j=l.reduce((A,B)=>A+Number(B.exposures??0),0),m=A=>{const B=l.filter(E=>E.role===A).reduce((E,P)=>E+Number(P.exposures??0),0);return j>0?B/j*100:0};return{experiment:t,total:j,actual:{champion:m("champion"),challenger:m("challenger"),explore:m("explore")},target:{champion:Number(t.champion_weight??0)*100,challenger:Number(t.challenger_weight??0)*100,explore:Number(t.explore_weight??0)*100}}})},[u,k]),O=o.length-p.length;return e.jsxs("div",{className:"space-y-8",children:[e.jsxs("div",{className:"flex flex-col gap-4 md:flex-row md:items-end md:justify-between",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx("h1",{className:"text-2xl font-semibold tracking-tight",children:"Experiment Lift"}),e.jsx("p",{className:"text-sm text-muted-foreground max-w-2xl",children:"Incremental lift is the difference between treated families and the 15% holdout that received nothing â measured on the same outcome window."})]}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(se,{value:a,onValueChange:s=>g(s),children:e.jsxs(te,{children:[e.jsx(R,{value:"7d",children:"7-day window"}),e.jsx(R,{value:"30d",children:"30-day window"})]})}),e.jsxs(V,{variant:"outline",size:"sm",className:"min-h-11",onClick:()=>r(),disabled:n,children:[n?e.jsx(K,{className:"h-4 w-4 animate-spin"}):e.jsx(X,{className:"h-4 w-4"}),e.jsx("span",{className:"ml-2",children:"Refresh"})]})]})]}),f?e.jsxs("div",{className:"flex items-center gap-2 text-muted-foreground",children:[e.jsx(K,{className:"h-4 w-4 animate-spin"})," Loading outcome windowsâ¦"]}):e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid gap-6 md:grid-cols-4",children:[e.jsxs(b,{children:[e.jsxs(y,{className:"pb-2",children:[e.jsxs(w,{children:["Incremental lift (",a,")"]}),e.jsx(_,{className:"text-2xl",children:i?`${i.absoluteLift>=0?"+":""}${h(i.absoluteLift)}`:"â"})]}),e.jsx(v,{className:"text-sm text-muted-foreground",children:(i==null?void 0:i.relativeLift)!==null&&i?`${i.relativeLift>=0?"+":""}${h(i.relativeLift,1)}% vs holdout`:"Holdout baseline still forming"})]}),e.jsxs(b,{children:[e.jsxs(y,{className:"pb-2",children:[e.jsx(w,{children:"Treated families"}),e.jsx(_,{className:"text-2xl",children:(i==null?void 0:i.treatmentN)??0})]}),e.jsxs(v,{className:"text-sm text-muted-foreground",children:["mean score ",i?h(i.treatmentMean):"â"]})]}),e.jsxs(b,{children:[e.jsxs(y,{className:"pb-2",children:[e.jsx(w,{children:"Holdout families"}),e.jsx(_,{className:"text-2xl",children:(i==null?void 0:i.holdoutN)??0})]}),e.jsxs(v,{className:"text-sm text-muted-foreground",children:["mean score ",i?h(i.holdoutMean):"â"]})]}),e.jsxs(b,{children:[e.jsxs(y,{className:"pb-2",children:[e.jsx(w,{children:"Windows still open"}),e.jsx(_,{className:"text-2xl",children:O})]}),e.jsx(v,{className:"text-sm text-muted-foreground",children:"excluded until measured"})]})]}),p.length===0&&e.jsxs(ae,{children:[e.jsx(ne,{className:"h-4 w-4"}),e.jsx(re,{children:"No measured windows yet"}),e.jsxs(ie,{children:["Lift appears once ",a," outcome windows close and the learning job records their metrics. Check"," ",e.jsx(Y,{to:"/admin/nicole-experiments",className:"underline",children:"Experiments"})," ","for live arms in the meantime."]})]}),e.jsxs(b,{children:[e.jsxs(y,{children:[e.jsx(_,{className:"text-lg",children:"Lift by user state"}),e.jsx(w,{children:"Lifecycle stage and engagement tier at the moment of the decision."})]}),e.jsxs(v,{className:"space-y-6",children:[H.length>0&&e.jsx("div",{className:"h-72 w-full",children:e.jsx(le,{width:"100%",height:"100%",children:e.jsxs(ue,{data:H,margin:{top:8,right:8,left:0,bottom:32},children:[e.jsx(ce,{strokeDasharray:"3 3",stroke:"hsl(var(--border))",vertical:!1}),e.jsx(oe,{dataKey:"name",tick:{fontSize:11,fill:"hsl(var(--muted-foreground))"},interval:0,angle:-18,textAnchor:"end",height:48}),e.jsx(de,{tick:{fontSize:11,fill:"hsl(var(--muted-foreground))"}}),e.jsx(me,{contentStyle:{background:"hsl(var(--popover))",border:"1px solid hsl(var(--border))",borderRadius:8,color:"hsl(var(--popover-foreground))",fontSize:12},formatter:(s,t)=>t==="lift"?[s,"Incremental lift"]:[s,"Windows"]}
1),e.jsx(he,{dataKey:"lift",radius:[4,4,0,0],children:H.map(s=>e.jsx(xe,{fill:s.lift>=0?"hsl(var(--primary))":"hsl(var(--destructive))"},s.name))})]})})}),e.jsxs(D,{children:[e.jsx(W,{children:e.jsxs(L,{children:[e.jsx(x,{children:"User state"}),e.jsx(x,{className:"text-right",children:"Treated"}),e.jsx(x,{className:"text-right",children:"Treated mean"}),e.jsx(x,{className:"text-right",children:"Holdout"}),e.jsx(x,{className:"text-right",children:"Holdout mean"}),e.jsx(x,{className:"text-right",children:"Lift"})]})}),e.jsx(z,{children:T.length===0?e.jsx(L,{children:e.jsx(d,{colSpan:6,className:"text-center text-muted-foreground py-8",children:"No state-tagged windows in this period."})}):T.map(s=>e.jsxs(L,{children:[e.jsx(d,{className:"font-medium",children:s.label}),e.jsx(d,{className:"text-right",children:s.treatmentN}),e.jsx(d,{className:"text-right",children:h(s.treatmentMean)}),e.jsx(d,{className:"text-right",children:s.holdoutN}),e.jsx(d,{className:"text-right",children:h(s.holdoutMean)}),e.jsx(d,{className:"text-right",children:e.jsx(G,{group:s})})]},s.key))})]})]})]}),e.jsxs(b,{children:[e.jsxs(y,{children:[e.jsx(_,{className:"text-lg",children:"Lift by strategy"}),e.jsx(w,{children:"Which playbook is actually moving families forward."})]}),e.jsx(v,{children:e.jsxs(D,{children:[e.jsx(W,{children:e.jsxs(L,{children:[e.jsx(x,{children:"Strategy"}),e.jsx(x,{className:"text-right",children:"Treated"}),e.jsx(x,{className:"text-right",children:"Treated mean"}),e.jsx(x,{className:"text-right",children:"Holdout mean"}),e.jsx(x,{className:"text-right",children:"Lift"})]})}),e.jsx(z,{children:F.length===0?e.jsx(L,{children:e.jsx(d,{colSpan:5,className:"text-center text-muted-foreground py-8",children:"No strategy-tagged windows in this period."})}):F.map(s=>e.jsxs(L,{children:[e.jsx(d,{className:"font-medium",children:s.label}),e.jsx(d,{className:"text-right",children:s.treatmentN}),e.jsx(d,{className:"text-right",children:h(s.treatmentMean)}),e.jsx(d,{className:"text-right",children:h(s.holdoutMean)}),e.jsx(d,{className:"text-right",children:e.jsx(G,{group:s})})]},s.key))})]})})]}),e.jsxs(b,{children:[e.jsxs(y,{children:[e.jsx(_,{className:"text-lg",children:"Strategy allocation (70 / 20 / 10)"}),e.jsx(w,{children:"Target exploration mix versus the exposures each arm role has actually received."})]}),e.jsx(v,{className:"space-y-8",children:I.length===0?e.jsx("p",{className:"text-muted-foreground text-sm",children:"No experiments configured yet."}):I.map(({experiment:s,total:t,actual:l,target:j})=>e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex flex-wrap items-center gap-3",children:[e.jsx("span",{className:"font-medium",children:s.bucket_key}),e.jsx(S,{variant:"outline",className:"text-muted-foreground border-border",children:s.state_key}),e.jsx(S,{variant:"outline",className:"text-muted-foreground border-border",children:s.status}),e.jsxs("span",{className:"text-sm text-muted-foreground inline-flex items-center gap-1",children:[e.jsx(J,{className:"h-3.5 w-3.5"})," ",t," exposures"]})]}),["champion","challenger","explore"].map(m=>e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between text-sm",children:[e.jsx("span",{className:"capitalize",children:m}),e.jsxs("span",{className:"text-muted-foreground",children:["actual ",h(l[m],1),"% · target ",h(j[m],1),"%"]})]}),e.jsx(Q,{value:Math.min(100,l[m]),className:"h-2"})]},m))]},s.id))})]})]})]})};export{Ee as default};
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.