Files
buzz/desktop/tests/e2e/experimental-features.spec.ts
Salman Mohammed 59328d5ae3 feat(desktop): add thread-scoped ACP session experiment (#6909)
## Why

Thread-scoped ACP sessions from #6732 need an opt-in desktop rollout
that preserves today’s channel policy by default.

## What

- Add the default-off “Thread Scoped ACP Sessions” toggle under Settings
→ Experiments using the existing feature-override persistence.
- Map the persisted setting to `BUZZ_ACP_SESSION_POLICY=channel|thread`
for every local and provider-backed managed ACP launch. Changes apply
when managed agents next start; DMs remain conversation-scoped by the
backend.
- Keep the desktop setting authoritative over descriptor environment and
cover the UI, persistence, local spawn, provider payload, and existing
Projects/Workflows experiments.

## Risk Assessment

Low. The experiment defaults off and explicitly preserves `channel`;
changes are limited to managed-agent launch configuration. Existing
running agents are unchanged until their next start.

## Testing

- `. ./bin/activate-hermit && just ci` — passed on the final restacked
tree, including 5,674 desktop tests, 2,796 Tauri tests, and 1,860 mobile
tests.
- `cd desktop && pnpm build:e2e && pnpm exec playwright test
tests/e2e/experimental-features.spec.ts --project=smoke` — 1 passed.
- `. ./bin/activate-hermit && cargo test --manifest-path
desktop/src-tauri/Cargo.toml session_policy --lib` — 4 passed.
- `. ./bin/activate-hermit && cargo test --manifest-path
desktop/src-tauri/Cargo.toml commands::agents::deploy::tests --lib` — 15
passed.
- `. ./bin/activate-hermit && cargo test -p buzz-backend-kubernetes
--test wire_fixtures` — 4 passed.

## Stack Info

Stacked on #6732. This PR depends on #6732 and should merge after it.

Generated with Codex

---------

Signed-off-by: Salman Mohammed <smohammed@squareup.com>
Signed-off-by: Leo <5faf251baee50ee6bcde338aef6acdd70bb3e60115664c2cd490d94a55dfc488@buzz.block.builderlab.xyz>
Co-authored-by: Leo <5faf251baee50ee6bcde338aef6acdd70bb3e60115664c2cd490d94a55dfc488@buzz.block.builderlab.xyz>
2026-09-01 08:37:27 -05:00

80 lines
2.6 KiB
TypeScript

import { expect, test } from "@playwright/test";
import { installMockBridge } from "../helpers/bridge";
import { FEATURE_OVERRIDES_STORAGE_KEY } from "../helpers/features";
import { openSettings } from "../helpers/settings";
const DESCRIPTION =
"Give each channel thread isolated agent context. Applies when managed agents next start; DMs stay conversation-scoped.";
test("thread-scoped ACP sessions is default-off, persists, and applies on reload", async ({
page,
}) => {
await installMockBridge(page, undefined, { seedPreviewFeatures: false });
await page.goto("/");
await expect
.poll(() =>
page.evaluate(() => {
const call = window.__BUZZ_E2E_COMMAND_LOG__?.find(
({ command }) => command === "apply_workspace",
);
return (call?.payload as { threadScopedAcpSessions?: boolean } | null)
?.threadScopedAcpSessions;
}),
)
.toBe(false);
await openSettings(page, "experimental");
const toggle = page.getByTestId("feature-toggle-threadScopedAcpSessions");
await expect(
page.getByText("Thread Scoped ACP Sessions", { exact: true }),
).toBeVisible();
await expect(page.getByText(DESCRIPTION, { exact: true })).toBeVisible();
await expect(toggle).not.toBeChecked();
await expect(page.getByTestId("feature-toggle-projects")).not.toBeChecked();
await expect(page.getByTestId("feature-toggle-workflows")).not.toBeChecked();
await toggle.click();
await expect(toggle).toBeChecked();
await expect
.poll(() =>
page.evaluate(() => {
const calls = window.__BUZZ_E2E_COMMAND_LOG__ ?? [];
const call = calls.findLast(
({ command }) => command === "set_thread_scoped_acp_sessions",
);
return (call?.payload as { enabled?: boolean } | null)?.enabled;
}),
)
.toBe(true);
await expect
.poll(() =>
page.evaluate(
(key) => window.localStorage.getItem(key),
FEATURE_OVERRIDES_STORAGE_KEY,
),
)
.toContain('"threadScopedAcpSessions":true');
await page.reload();
// Settings route/section state survives reload, so wait for that restored
// view rather than trying to reopen settings from the app chrome.
await expect(page.getByTestId("settings-view")).toBeVisible();
await expect(
page.getByTestId("feature-toggle-threadScopedAcpSessions"),
).toBeChecked();
await expect
.poll(() =>
page.evaluate(() => {
const call = window.__BUZZ_E2E_COMMAND_LOG__?.find(
({ command }) => command === "apply_workspace",
);
return (call?.payload as { threadScopedAcpSessions?: boolean } | null)
?.threadScopedAcpSessions;
}),
)
.toBe(true);
});