>;
+};
+
+export function withExperiment(
+Control: React.ComponentType
,
+opts: WithExperimentOpts
+): React.ComponentType
void; probat?: { trackClick: () => void } }> {
+const { proposalId, registry } = opts;
+
+function Wrapped(props: P) {
+ const [choice, setChoice] = React.useState<{ experiment_id: string; label: string } | null>(null);
+
+ React.useEffect(() => {
+ let alive = true;
+
+ const cached = readChoice(proposalId);
+ if (cached) {
+ setChoice({ experiment_id: cached.experiment_id, label: cached.label });
+ }
+
+ if (!cached) {
+ (async () => {
+ try {
+ const { experiment_id, label } = await fetchDecision(ENV_BASE, proposalId);
+ if (!alive) return;
+ setChoice({ experiment_id, label });
+ } catch (e) {
+ if (!alive) return;
+ setChoice({ experiment_id: `exp_${proposalId}`, label: "control" });
+ }
+ })();
+ }
+
+ return () => { alive = false; };
+ }, [proposalId]);
+
+ const trackClick = React.useCallback(() => {
+ const exp = choice?.experiment_id;
+ const lbl = choice?.label ?? "control";
+ void sendClickMetric(ENV_BASE, proposalId, exp, lbl);
+ }, [proposalId, choice?.experiment_id, choice?.label]);
+
+ const label = choice?.label ?? "control";
+ const Variant = registry[label] || Control;
+
+ const key = `${proposalId}:${label}`;
+ return (
+
+ {React.createElement(Variant, {
+ key,
+ ...(props as any),
+ onProbatClick: trackClick,
+ probat: { trackClick },
+ })}
+
+ );
+}
+
+(Wrapped as any).displayName = `withExperiment(${(Control as any).displayName || Control.name || "Component"})`;
+return Wrapped as any;
+}
From fca403ed4d9c46c3a4f1fed1c5062f50a84f9a23 Mon Sep 17 00:00:00 2001
From: "probatai[bot]" <236084945+probatai[bot]@users.noreply.github.com>
Date: Thu, 6 Nov 2025 14:37:26 +0000
Subject: [PATCH 12/15] Add probat/index.tsx
---
probat/index.tsx | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 probat/index.tsx
diff --git a/probat/index.tsx b/probat/index.tsx
new file mode 100644
index 00000000..c5493906
--- /dev/null
+++ b/probat/index.tsx
@@ -0,0 +1,4 @@
+// probat/index.tsx
+export { withExperiment } from "./runtime";
+export { PROBAT_REGISTRIES } from "./registry";
+export { PROBAT_COMPONENTS } from "./config";
From 80798b6c54b0ae69f8cb92bac272a5811349c8f1 Mon Sep 17 00:00:00 2001
From: "probatai[bot]" <236084945+probatai[bot]@users.noreply.github.com>
Date: Thu, 6 Nov 2025 14:37:47 +0000
Subject: [PATCH 13/15] Ensure probat/config.tsx entry
---
probat/config.tsx | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 probat/config.tsx
diff --git a/probat/config.tsx b/probat/config.tsx
new file mode 100644
index 00000000..0a4dfabd
--- /dev/null
+++ b/probat/config.tsx
@@ -0,0 +1,4 @@
+// probat/config.tsx
+export const PROBAT_COMPONENTS: Record = {
+ "src/components/Hero.tsx": { proposalId: "6e929522-333a-4a43-b822-4927dd894f8c" }
+};
From 8bba720d89a030b1c964f166710351634d62c369 Mon Sep 17 00:00:00 2001
From: "probatai[bot]" <236084945+probatai[bot]@users.noreply.github.com>
Date: Thu, 6 Nov 2025 14:38:04 +0000
Subject: [PATCH 14/15] Ensure probat/registry.tsx entry
---
probat/registry.tsx | 26 ++++++++++++++++++++++++++
1 file changed, 26 insertions(+)
create mode 100644 probat/registry.tsx
diff --git a/probat/registry.tsx b/probat/registry.tsx
new file mode 100644
index 00000000..bc22c14a
--- /dev/null
+++ b/probat/registry.tsx
@@ -0,0 +1,26 @@
+// probat/registry.tsx
+ import type React from "react";
+ import Exp_0_a from "./6e929522-333a-4a43-b822-4927dd894f8c/a02f30b6-48d2-47ca-9006-c65203989a59";
+import Exp_1_b from "./6e929522-333a-4a43-b822-4927dd894f8c/acad765c-6b86-47c7-96f2-bc9a7fad4578";
+import Exp_2_c from "./6e929522-333a-4a43-b822-4927dd894f8c/c998493b-6d28-428f-9266-53959fe68550";
+import Exp_3_d from "./6e929522-333a-4a43-b822-4927dd894f8c/e69357f0-d93b-464b-8f11-7a8e111a3267";
+import Exp_4_e from "./6e929522-333a-4a43-b822-4927dd894f8c/f8f68bc8-a7f1-40f2-bd74-d23ca064d1e1";
+import Exp_5_f from "./6e929522-333a-4a43-b822-4927dd894f8c/f88fecb7-9105-4ab6-ac4c-408308c4d32b";
+import Exp_6_g from "./6e929522-333a-4a43-b822-4927dd894f8c/e23b3962-c657-4819-8921-565756603a25";
+import Exp_7_h from "./6e929522-333a-4a43-b822-4927dd894f8c/f9b4e04c-badc-4168-9a88-8b3e9255e1b9";
+import Exp_8_i from "./6e929522-333a-4a43-b822-4927dd894f8c/0aec55fd-21c6-46d4-918d-21089e7c9b86";
+import Exp_9_j from "./6e929522-333a-4a43-b822-4927dd894f8c/a3cd35cd-f444-4a70-9072-9d81e482de2f";
+ export const PROBAT_REGISTRIES: Record>> = {
+ "src/components/Hero.tsx": {
+ "a": Exp_0_a,
+ "b": Exp_1_b,
+ "c": Exp_2_c,
+ "d": Exp_3_d,
+ "e": Exp_4_e,
+ "f": Exp_5_f,
+ "g": Exp_6_g,
+ "h": Exp_7_h,
+ "i": Exp_8_i,
+ "j": Exp_9_j,
+ },
+ };
From cab1a9f57ca7b2a70c6228684180bcc3b02efac0 Mon Sep 17 00:00:00 2001
From: "probatai[bot]" <236084945+probatai[bot]@users.noreply.github.com>
Date: Thu, 6 Nov 2025 14:38:24 +0000
Subject: [PATCH 15/15] probat: auto-edit component to integrate Probat at
src/components/Hero.tsx
---
src/components/Hero.tsx | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/src/components/Hero.tsx b/src/components/Hero.tsx
index 66d7f27c..30312928 100644
--- a/src/components/Hero.tsx
+++ b/src/components/Hero.tsx
@@ -1,6 +1,10 @@
import React from 'react'
+import { withExperiment } from "../../probat/runtime";
+import { PROBAT_COMPONENTS, PROBAT_REGISTRIES } from "../../probat/index";
import './Hero.css'
+const __PROBAT_KEY__ = "src/components/Hero.tsx";
+
const Hero: React.FC = () => {
return (
@@ -61,4 +65,10 @@ const Hero: React.FC = () => {
)
}
-export default Hero
+export default (() => {
+ const meta = PROBAT_COMPONENTS[__PROBAT_KEY__];
+ const reg = PROBAT_REGISTRIES[__PROBAT_KEY__] as Record> | undefined;
+ return (meta?.proposalId && reg)
+ ? withExperiment(Hero as any, { proposalId: meta.proposalId, registry: reg })
+ : Hero;
+})();