feat(desktop): add build-gated Bestie experiment

Co-authored-by: Codex <noreply@openai.com>
Signed-off-by: Arjun Mahanti <arjun@squareup.com>
This commit is contained in:
Arjun Mahanti
2026-08-26 17:20:51 -04:00
parent eb8e97cfe7
commit 48892e4465
12 changed files with 134 additions and 3 deletions

View File

@@ -206,6 +206,9 @@ RUST_LOG=buzz_relay=debug,buzz_datastore=info,buzz_db=debug,buzz_auth=debug,buzz
# app launch while keeping the current identity and relay data.
# VITE_BUZZ_FORCE_FRESH_ONBOARDING=true
# Makes the default-off Bestie experiment available in eligible builds.
# VITE_BUZZ_BESTIE=1
# ── Subscription & filtering ─────────────────────────────────────────────────
# Subscribe mode: "mentions" (default), "all", or "config" (rule-based).
# BUZZ_ACP_SUBSCRIBE=mentions

View File

@@ -1,5 +1,5 @@
import { setAgentManagedProfiles } from "@/shared/api/tauri";
import { desktopFeatures, useFeatureToggle } from "@/shared/features";
import { availableDesktopFeatures, useFeatureToggle } from "@/shared/features";
import type { FeatureDefinition } from "@/shared/features";
import { Switch } from "@/shared/ui/switch";
import { SettingsOptionGroup, SettingsOptionRow } from "./SettingsOptionGroup";
@@ -42,7 +42,7 @@ function FeatureRow({ feature }: { feature: FeatureDefinition }) {
export function ExperimentalFeaturesCard() {
// Manifest is preview-only by definition; every desktop entry is a preview
// feature.
const previewFeatures = desktopFeatures;
const previewFeatures = availableDesktopFeatures;
return (
<section className="min-w-0" data-testid="settings-experimental">

View File

@@ -0,0 +1,43 @@
import assert from "node:assert/strict";
import { describe, it } from "node:test";
import {
filterBuildAvailableFeatures,
isFeatureBuildAvailable,
} from "./buildAvailability.ts";
const publicFeature = {
id: "projects",
name: "Projects",
description: "",
};
const bestie = {
id: "bestie",
name: "Bestie",
description: "",
requiredBuildFlag: "bestie",
};
describe("feature build availability", () => {
it("keeps features without a required build flag available", () => {
assert.equal(
isFeatureBuildAvailable(publicFeature, { bestie: false }),
true,
);
});
it("does not allow a required feature into an ineligible build", () => {
assert.equal(isFeatureBuildAvailable(bestie, { bestie: false }), false);
});
it("shows a required feature when its build opts in", () => {
assert.equal(isFeatureBuildAvailable(bestie, { bestie: true }), true);
});
it("filters unavailable features out of the experiment picker", () => {
assert.deepEqual(
filterBuildAvailableFeatures([publicFeature, bestie], { bestie: false }),
[publicFeature],
);
});
});

View File

@@ -0,0 +1,24 @@
import type { FeatureBuildFlag, FeatureDefinition } from "./types";
export type FeatureBuildFlags = Record<FeatureBuildFlag, boolean>;
/**
* Build capabilities are deliberately separate from user preference. A local
* storage override cannot make an unavailable feature visible.
*/
export function isFeatureBuildAvailable(
feature: FeatureDefinition,
buildFlags: FeatureBuildFlags,
): boolean {
const requiredFlag = feature.requiredBuildFlag;
return requiredFlag ? buildFlags[requiredFlag] : true;
}
export function filterBuildAvailableFeatures(
features: FeatureDefinition[],
buildFlags: FeatureBuildFlags,
): FeatureDefinition[] {
return features.filter((feature) =>
isFeatureBuildAvailable(feature, buildFlags),
);
}

View File

@@ -1,8 +1,10 @@
export { FeatureGate } from "./FeatureGate";
export { allFeatures, desktopFeatures, getFeature, manifest } from "./manifest";
export { availableDesktopFeatures } from "./runtimeBuildAvailability";
export { getOverrides, setOverride, clearOverride } from "./store";
export type {
FeatureDefinition,
FeatureBuildFlag,
FeaturesManifest,
FeaturePlatform,
} from "./types";

View File

@@ -8,6 +8,7 @@ import type { FeatureDefinition, FeaturesManifest } from "./types";
// The app keeps working; gated UI stays hidden; nothing accidentally leaks.
const FeaturePlatformSchema = z.enum(["desktop", "mobile"]);
const FeatureBuildFlagSchema = z.enum(["bestie"]);
const FeatureDefinitionSchema = z.object({
id: z.string().min(1),
@@ -15,6 +16,7 @@ const FeatureDefinitionSchema = z.object({
description: z.string(),
defaultEnabled: z.boolean().optional(),
platforms: z.array(FeaturePlatformSchema).optional(),
requiredBuildFlag: FeatureBuildFlagSchema.optional(),
});
const FeaturesManifestSchema = z.object({

View File

@@ -30,4 +30,20 @@ describe("resolveEnabled (preview-only)", () => {
it("ignores overrides for unrelated ids", () => {
assert.equal(resolveEnabled("workflows", { pulse: true }), false);
});
it("requires both build availability and a user opt-in", () => {
const cases = [
{ buildAvailable: false, optedIn: false, expected: false },
{ buildAvailable: false, optedIn: true, expected: false },
{ buildAvailable: true, optedIn: false, expected: false },
{ buildAvailable: true, optedIn: true, expected: true },
];
for (const { buildAvailable, optedIn, expected } of cases) {
assert.equal(
resolveEnabled("bestie", { bestie: optedIn }, false, buildAvailable),
expected,
);
}
});
});

View File

@@ -14,6 +14,8 @@ export function resolveEnabled(
featureId: string,
overrides: Record<string, boolean>,
defaultEnabled = false,
buildAvailable = true,
): boolean {
if (!buildAvailable) return false;
return overrides[featureId] ?? defaultEnabled;
}

View File

@@ -0,0 +1,21 @@
import {
filterBuildAvailableFeatures,
isFeatureBuildAvailable,
type FeatureBuildFlags,
} from "./buildAvailability";
import { desktopFeatures } from "./manifest";
const runtimeBuildFlags: FeatureBuildFlags = {
bestie: import.meta.env.VITE_BUZZ_BESTIE === "1",
};
export function isFeatureAvailableInThisBuild(
feature: Parameters<typeof isFeatureBuildAvailable>[0],
): boolean {
return isFeatureBuildAvailable(feature, runtimeBuildFlags);
}
export const availableDesktopFeatures = filterBuildAvailableFeatures(
desktopFeatures,
runtimeBuildFlags,
);

View File

@@ -1,6 +1,9 @@
/** Platforms a feature is available on */
export type FeaturePlatform = "desktop" | "mobile";
/** Build-time capabilities that can make a preview available to users. */
export type FeatureBuildFlag = "bestie";
/**
* A single feature definition from the manifest.
*
@@ -16,6 +19,8 @@ export interface FeatureDefinition {
defaultEnabled?: boolean;
/** If omitted, feature is available on all platforms */
platforms?: FeaturePlatform[];
/** If present, the build must opt in before the user can see or enable it */
requiredBuildFlag?: FeatureBuildFlag;
}
/** The root manifest schema */

View File

@@ -1,6 +1,7 @@
import { useSyncExternalStore, useCallback, useEffect } from "react";
import { getFeature } from "./manifest";
import { resolveEnabled } from "./resolveEnabled";
import { isFeatureAvailableInThisBuild } from "./runtimeBuildAvailability";
import { getOverrides, setOverride, OVERRIDES_KEY } from "./store";
type Listener = () => void;
@@ -102,7 +103,12 @@ export function useFeatureEnabled(featureId: string): boolean {
return true;
}
return resolveEnabled(featureId, overrides, feature.defaultEnabled);
return resolveEnabled(
featureId,
overrides,
feature.defaultEnabled,
isFeatureAvailableInThisBuild(feature),
);
}
/**

View File

@@ -30,6 +30,13 @@
"name": "Agent-managed profiles",
"description": "Let agents manage their own relay name and avatar instead of restoring the desktop copy",
"platforms": ["desktop"]
},
{
"id": "bestie",
"name": "Bestie",
"description": "Try a personal agent that is always close at hand",
"platforms": ["desktop"],
"requiredBuildFlag": "bestie"
}
]
}