mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-10-30 17:27:09 +00:00
feat(studio): enable SDK cutover by default for every op family
Master flag defaults true; unset family list now means all five families. VITE_STUDIO_SDK_CUTOVER_ENABLED=false / VITE_STUDIO_SDK_CUTOVER_FAMILIES=... remain as runtime kill switches via __HF_STUDIO_ENV__. Gate: 0 divergences on 0.8.41-0.8.46 shadow tile, 3455/0 success/failed on dev builds (30d). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
82f49262ec
commit
26ea8a0740
@@ -1,5 +1,6 @@
|
||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
import { resolveStudioBooleanEnvFlag } from "./manualEditingAvailability";
|
||||
import { STUDIO_SDK_OPERATION_FAMILIES } from "../../utils/sdkCutoverPolicy";
|
||||
|
||||
async function loadAvailabilityWithEnv(env: Record<string, string | undefined>) {
|
||||
vi.resetModules();
|
||||
@@ -88,4 +89,22 @@ describe("manual editing availability", () => {
|
||||
});
|
||||
expect(off.STUDIO_FLAT_INSPECTOR_ENABLED).toBe(false);
|
||||
});
|
||||
|
||||
it("defaults SDK cutover on for every family", async () => {
|
||||
const all = await loadAvailabilityWithEnv({});
|
||||
expect(all.STUDIO_SDK_CUTOVER_ENABLED).toBe(true);
|
||||
expect(all.STUDIO_SDK_CUTOVER_FAMILIES).toEqual(new Set(STUDIO_SDK_OPERATION_FAMILIES));
|
||||
});
|
||||
|
||||
it("honors the SDK cutover kill switches", async () => {
|
||||
const off = await loadAvailabilityWithEnv({ VITE_STUDIO_SDK_CUTOVER_ENABLED: "false" });
|
||||
expect(off.STUDIO_SDK_CUTOVER_ENABLED).toBe(false);
|
||||
expect(off.STUDIO_SDK_CUTOVER_FAMILIES.size).toBe(0);
|
||||
|
||||
const subset = await loadAvailabilityWithEnv({
|
||||
VITE_STUDIO_SDK_CUTOVER_FAMILIES: "dom,timing",
|
||||
});
|
||||
expect(subset.STUDIO_SDK_CUTOVER_ENABLED).toBe(true);
|
||||
expect(subset.STUDIO_SDK_CUTOVER_FAMILIES).toEqual(new Set(["dom", "timing"]));
|
||||
});
|
||||
});
|
||||
|
||||
@@ -38,16 +38,20 @@ const runtimeEnv =
|
||||
: {};
|
||||
const env = { ...(import.meta.env ?? {}), ...runtimeEnv } as StudioFeatureFlagEnv;
|
||||
|
||||
// Stage 7 Step 3c: SDK cutover — routes inline-style ops through SDK dispatch
|
||||
// instead of the server patch-element API. Default false; enable via
|
||||
// VITE_STUDIO_SDK_CUTOVER_ENABLED=true. Requires SDK session to be open.
|
||||
// Stage 7 SDK cutover — routes Studio edits through SDK dispatch instead of the
|
||||
// server patch/mutation routes. Default TRUE as of the flip release (spec:
|
||||
// 2026-09-17-studio-sdk-cutover-flip-design.md). Kill switch:
|
||||
// VITE_STUDIO_SDK_CUTOVER_ENABLED=false (works at runtime via __HF_STUDIO_ENV__).
|
||||
export const STUDIO_SDK_CUTOVER_ENABLED = resolveStudioBooleanEnvFlag(
|
||||
env,
|
||||
["VITE_STUDIO_SDK_CUTOVER_ENABLED"],
|
||||
false,
|
||||
true,
|
||||
);
|
||||
|
||||
/** Explicit per-operation-family canary selection; the master flag alone enables nothing. */
|
||||
/**
|
||||
* Per-family selection. Unset = every family (the master alone enables all).
|
||||
* Set `VITE_STUDIO_SDK_CUTOVER_FAMILIES=dom,timing` to RESTRICT to a subset.
|
||||
*/
|
||||
export const STUDIO_SDK_CUTOVER_FAMILIES = resolveEnabledSdkFamilies(
|
||||
env,
|
||||
STUDIO_SDK_CUTOVER_ENABLED,
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { describe, expect, it, vi } from "vitest";
|
||||
|
||||
// Dark-launch contract: with STUDIO_SDK_CUTOVER_ENABLED=false, EVERY cutover
|
||||
// Kill-switch contract: with VITE_STUDIO_SDK_CUTOVER_ENABLED=false, EVERY cutover
|
||||
// persist chokepoint must explicitly decline so the caller takes the legacy server
|
||||
// path — even when a valid SDK session exists (one always does, for
|
||||
// shadow/selection). This is the contract the prod flag-flip rests on; a future
|
||||
// refactor of the gate guards that silently re-enables cutover on flag-off
|
||||
// turns these red. (sdkCutover.test.ts mocks the flag TRUE; this is its sibling.)
|
||||
// shadow/selection). Default is ON (manualEditingAvailability.test.ts pins that);
|
||||
// this file pins that the env override still turns it fully off. A future
|
||||
// refactor of the gate guards that ignores the flag turns these red.
|
||||
// (sdkCutover.test.ts mocks the flag TRUE; this is its sibling.)
|
||||
vi.mock("../components/editor/manualEditingAvailability", () => ({
|
||||
STUDIO_SDK_CUTOVER_ENABLED: false,
|
||||
STUDIO_SDK_RESOLVER_SHADOW_ENABLED: false,
|
||||
|
||||
@@ -7,8 +7,17 @@ import {
|
||||
} from "./sdkCutoverPolicy";
|
||||
|
||||
describe("Studio SDK operation-family policy", () => {
|
||||
it("enables no family from the master switch alone", () => {
|
||||
expect(resolveEnabledSdkFamilies({}, true).size).toBe(0);
|
||||
it("enables every family when the master switch is on and no family list is set", () => {
|
||||
const all = new Set(STUDIO_SDK_OPERATION_FAMILIES);
|
||||
expect(resolveEnabledSdkFamilies({}, true)).toEqual(all);
|
||||
expect(resolveEnabledSdkFamilies({ VITE_STUDIO_SDK_CUTOVER_FAMILIES: "" }, true)).toEqual(all);
|
||||
expect(resolveEnabledSdkFamilies({ VITE_STUDIO_SDK_CUTOVER_FAMILIES: " " }, true)).toEqual(
|
||||
all,
|
||||
);
|
||||
});
|
||||
|
||||
it("enables no family when the master switch is off, regardless of the family list", () => {
|
||||
expect(resolveEnabledSdkFamilies({}, false).size).toBe(0);
|
||||
expect(resolveEnabledSdkFamilies({ VITE_STUDIO_SDK_CUTOVER_FAMILIES: "dom" }, false).size).toBe(
|
||||
0,
|
||||
);
|
||||
|
||||
@@ -54,7 +54,8 @@ export function resolveEnabledSdkFamilies(
|
||||
): ReadonlySet<StudioSdkOperationFamily> {
|
||||
if (!masterEnabled) return new Set();
|
||||
const raw = env["VITE_STUDIO_SDK_CUTOVER_FAMILIES"];
|
||||
if (typeof raw !== "string" || raw.trim() === "") return new Set();
|
||||
// Unset/blank = every family. The list exists to RESTRICT (kill switch per family).
|
||||
if (typeof raw !== "string" || raw.trim() === "") return new Set(STUDIO_SDK_OPERATION_FAMILIES);
|
||||
const requested = raw
|
||||
.split(",")
|
||||
.map((family) => family.trim())
|
||||
@@ -85,8 +86,9 @@ export function renderStudioSdkCutoverReport(): string {
|
||||
return [
|
||||
"# Studio SDK cutover report",
|
||||
"",
|
||||
"Master flag: `VITE_STUDIO_SDK_CUTOVER_ENABLED=true`",
|
||||
"Family flag: `VITE_STUDIO_SDK_CUTOVER_FAMILIES=dom,timing,...`",
|
||||
"Default: SDK persist ON for every family. Kill switches:",
|
||||
" `VITE_STUDIO_SDK_CUTOVER_ENABLED=false` (all families → server path)",
|
||||
" `VITE_STUDIO_SDK_CUTOVER_FAMILIES=dom,timing` (only listed families → SDK; rest → server)",
|
||||
"",
|
||||
"A family graduates only after zero unexplained resolver/serialization divergences over its agreed corpus and soak window.",
|
||||
"",
|
||||
|
||||
Reference in New Issue
Block a user