apps/operator-dashboard/src/pages/BeautyGeneratorLabPage.tsx

TSX · 27,862 source bytes · SHA-256 1b9017f812706f5c449f1bb35b86aa9e636148c15fdfe61e204597091b1d63a8
import {
  BEAUTY_RECIPE_REGISTRY,
  compileBeautyGeneratorLabCandidate,
  createBeautyDesignCompilerFixtures,
  type BeautyDesignCompilerFixture,
  type BeautyGeneratorLabControls,
  type BeautyGeneratorLabResult,
} from "@site-rescue/commercial/beauty-design";
import {
  Braces,
  Check,
  Columns2,
  Copy,
  Dices,
  Download,
  Eye,
  FileImage,
  FlaskConical,
  Grid2X2,
  RefreshCw,
  Sparkles,
} from "lucide-react";
import { useCallback, useEffect, useMemo, useState } from "react";
import { PageHeader, Panel, StatusBadge } from "../components/ui";
import "./beauty-generator-lab.css";

type InspectorTab =
  "manifest" | "capsule" | "tournament" | "lineage" | "tokens" | "coverage" | "assets";

const DEFAULT_CONTROLS: BeautyGeneratorLabControls = {
  seed: "01".repeat(32),
  compilerMode: "v2",
  variant: "auto",
  recipe: "auto",
  artDirectionIntensity: "balanced",
  serviceCount: 6,
  teamCount: 3,
  reviewCount: 3,
  locationCount: 1,
  imageRichness: "rich",
  generatedAssetState: "available",
  candidateCount: 20,
  minimumQualityScore: 88,
};

function randomSeed(): string {
  const bytes = new Uint8Array(32);
  crypto.getRandomValues(bytes);
  return [...bytes].map((byte) => byte.toString(16).padStart(2, "0")).join("");
}

function shortHash(value: string): string {
  return `${value.slice(0, 8)}…${value.slice(-6)}`;
}

function Help({ children }: { children: string }) {
  return (
    <span aria-label={children} className="lab-help" role="img" tabIndex={0} title={children}>
      ?
    </span>
  );
}

function SelectField({
  children,
  help,
  label,
  onChange,
  value,
}: {
  children: React.ReactNode;
  help: string;
  label: string;
  onChange: (value: string) => void;
  value: string;
}) {
  return (
    <label className="lab-field">
      <span>
        {label} <Help>{help}</Help>
      </span>
      <select onChange={(event) => onChange(event.target.value)} value={value}>
        {children}
      </select>
    </label>
  );
}

function jsonDownload(filename: string, value: unknown) {
  const blob = new Blob([JSON.stringify(value, null, 2)], {
    type: "application/json;charset=utf-8",
  });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.download = filename;
  link.href = url;
  link.click();
  URL.revokeObjectURL(url);
}

function PreviewFrame({ label, result }: { label: string; result: BeautyGeneratorLabResult }) {
  return (
    <article className="lab-preview-card">
      <header>
        <div>
          <span>{label}</span>
          <strong>{result.manifest.masterRecipe}</strong>
        </div>
        <StatusBadge tone={result.rendered.informationCoverage.complete ? "green" : "red"}>
          {result.rendered.informationCoverage.complete ? "Coverage passed" : "Coverage failed"}
        </StatusBadge>
      </header>
      <div className="lab-browser">
        <div aria-hidden="true" className="lab-browser__chrome">
          <i />
          <i />
          <i />
          <span>{result.siteSpec.seo.canonicalUrl}</span>
        </div>
        <iframe
          sandbox="allow-same-origin"
          srcDoc={result.rendered.primaryHtml}
          title={`${label} generated website`}
        />
      </div>
    </article>
  );
}

export function BeautyGeneratorLabPage() {
  const [fixtures, setFixtures] = useState<readonly BeautyDesignCompilerFixture[]>([]);
  const [fixtureId, setFixtureId] = useState("morrow-and-muse");
  const [controls, setControls] = useState<BeautyGeneratorLabControls>(DEFAULT_CONTROLS);
  const [result, setResult] = useState<BeautyGeneratorLabResult | null>(null);
  const [compareResult, setCompareResult] = useState<BeautyGeneratorLabResult | null>(null);
  const [compareEnabled, setCompareEnabled] = useState(false);
  const [baselineEnabled, setBaselineEnabled] = useState(false);
  const [gridResults, setGridResults] = useState<readonly BeautyGeneratorLabResult[]>([]);
  const [inspector, setInspector] = useState<InspectorTab>("manifest");
  const [busy, setBusy] = useState(true);
  const [error, setError] = useState<string | null>(null);

  useEffect(() => {
    let active = true;
    void createBeautyDesignCompilerFixtures()
      .then((value) => {
        if (active) setFixtures(value);
      })
      .catch((reason: unknown) => {
        if (active) setError(reason instanceof Error ? reason.message : "Fixture load failed.");
      });
    return () => {
      active = false;
    };
  }, []);

  const fixture = useMemo(
    () => fixtures.find((candidate) => candidate.id === fixtureId) ?? fixtures[0] ?? null,
    [fixtureId, fixtures],
  );
  const eligibleRecipes = useMemo(() => {
    if (controls.variant === "auto") return BEAUTY_RECIPE_REGISTRY;
    return BEAUTY_RECIPE_REGISTRY.filter((recipe) => recipe.variant === controls.variant);
  }, [controls.variant]);

  const compile = useCallback(async () => {
    if (fixture === null) return;
    setBusy(true);
    setError(null);
    setGridResults([]);
    try {
      const primary = await compileBeautyGeneratorLabCandidate(fixture, controls);
      setResult(primary);
      if (baselineEnabled) {
        setCompareResult(
          await compileBeautyGeneratorLabCandidate(fixture, {
            ...controls,
            compilerMode: "v1",
          }),
        );
      } else if (compareEnabled) {
        setCompareResult(
          await compileBeautyGeneratorLabCandidate(fixture, {
            ...controls,
            seed: randomSeed(),
          }),
        );
      } else {
        setCompareResult(null);
      }
    } catch (reason) {
      setResult(null);
      setCompareResult(null);
      setError(reason instanceof Error ? reason.message : "Design compilation failed.");
    } finally {
      setBusy(false);
    }
  }, [baselineEnabled, compareEnabled, controls, fixture]);

  useEffect(() => {
    void compile();
  }, [compile]);

  const update = <Key extends keyof BeautyGeneratorLabControls>(
    key: Key,
    value: BeautyGeneratorLabControls[Key],
  ) => {
    setControls((current) => ({ ...current, [key]: value }));
  };

  const renderSeedGrid = async () => {
    if (fixture === null) return;
    setBusy(true);
    setError(null);
    try {
      const generated = await Promise.all(
        Array.from({ length: 12 }, () =>
          compileBeautyGeneratorLabCandidate(fixture, {
            ...controls,
            seed: randomSeed(),
            recipe: "auto",
          }),
        ),
      );
      setGridResults(generated);
    } catch (reason) {
      setError(reason instanceof Error ? reason.message : "Seed grid failed.");
    } finally {
      setBusy(false);
    }
  };

  const inspectorValue =
    result === null
      ? null
      : inspector === "manifest"
        ? result.manifest
        : inspector === "capsule"
          ? (result.v2?.capsule ?? {
              message: "Capsule inspection is available in V2 mode.",
            })
          : inspector === "tournament"
            ? (result.v2?.tournament ?? {
                message: "Candidate tournaments are available in V2 mode.",
              })
            : inspector === "lineage"
              ? (result.v2?.lineage ?? {
                  message: "Capsule lineage is available in V2 mode.",
                })
              : inspector === "tokens"
                ? {
                    typography: result.manifest.typography,
                    color: result.manifest.color,
                    spacing: result.manifest.spacing,
                    geometry: result.manifest.geometry,
                    motif: result.manifest.motif,
                    motion: result.manifest.motion,
                  }
                : inspector === "coverage"
                  ? result.rendered.informationCoverage
                  : {
                      briefs: result.manifest.generatedAssetBriefs,
                      exactPrompts: result.exactPrompts,
                    };
  const selectedV2Candidate = result?.v2?.tournament.candidates.find(
    (candidate) => candidate.selected,
  );
  const rejectedV2Count =
    result?.v2?.tournament.candidates.filter((candidate) => !candidate.eligible).length ?? 0;

  return (
    <div className="page beauty-lab">
      <PageHeader
        actions={
          <StatusBadge tone={error === null ? "green" : "red"}>
            {busy ? "Compiling" : error === null ? "Deterministic" : "Needs attention"}
          </StatusBadge>
        }
        description="Protected fixture-only workspace for compiling, comparing, and inspecting pinned beauty designs. It cannot publish, bill, crawl, or contact anyone."
        title="Beauty Generator Lab"
      />

      <div className="beauty-lab__layout">
        <aside className="beauty-lab__controls">
          <Panel title="Design inputs">
            <SelectField
              help="A fictional, isolated SiteSpec used to exercise specific content conditions."
              label="Fixture"
              onChange={setFixtureId}
              value={fixtureId}
            >
              {fixtures.map((candidate) => (
                <option key={candidate.id} value={candidate.id}>
                  {candidate.caseName} · {candidate.siteSpec.pages[0]?.title}
                </option>
              ))}
            </SelectField>

            <div className="lab-field-grid">
              <SelectField
                help="V2 evaluates a deterministic field of capsule-owned candidates. V1 remains available only as an archived visual baseline."
                label="Compiler"
                onChange={(value) =>
                  update("compilerMode", value as BeautyGeneratorLabControls["compilerMode"])
                }
                value={controls.compilerMode ?? "v2"}
              >
                <option value="v2">V2 capsule tournament</option>
                <option value="v1">V1 archived baseline</option>
              </SelectField>
              <SelectField
                help="The bounded tournament renders structurally meaningful alternatives, never cosmetic accent-only variants."
                label="Candidates"
                onChange={(value) =>
                  update(
                    "candidateCount",
                    Number(value) as BeautyGeneratorLabControls["candidateCount"],
                  )
                }
                value={String(controls.candidateCount ?? 20)}
              >
                <option value="16">16 candidates</option>
                <option value="20">20 candidates</option>
                <option value="24">24 candidates</option>
              </SelectField>
            </div>

            <SelectField
              help="Candidates below this static quality floor cannot be accepted automatically. The default corrective floor is 88."
              label="Static quality floor"
              onChange={(value) => update("minimumQualityScore", Number(value))}
              value={String(controls.minimumQualityScore ?? 88)}
            >
              <option value="84">84 · diagnostic</option>
              <option value="88">88 · release floor</option>
              <option value="90">90 · strict</option>
              <option value="92">92 · very strict</option>
            </SelectField>

            <label className="lab-field">
              <span>
                Persistent seed{" "}
                <Help>Normal content updates reuse this 256-bit identity and never reroll it.</Help>
              </span>
              <div className="lab-seed">
                <input
                  aria-invalid={!/^[a-f0-9]{64}$/u.test(controls.seed)}
                  onChange={(event) => update("seed", event.target.value.toLowerCase())}
                  spellCheck={false}
                  value={controls.seed}
                />
                <button
                  aria-label="Generate a new local design seed"
                  onClick={() => update("seed", randomSeed())}
                  title="Generate a new local design seed"
                  type="button"
                >
                  <Dices aria-hidden="true" size={18} />
                </button>
              </div>
            </label>

            <div className="lab-field-grid">
              <SelectField
                help="Automatic selection is category-weighted. An explicit choice remains authoritative."
                label="Variant"
                onChange={(value) => {
                  update("variant", value as BeautyGeneratorLabControls["variant"]);
                  update("recipe", "auto");
                }}
                value={controls.variant}
              >
                <option value="auto">Automatic</option>
                <option value="atelier">Atelier</option>
                <option value="ritual">Ritual</option>
                <option value="studio">Studio</option>
                <option value="precision">Precision</option>
              </SelectField>
              <SelectField
                help="A recipe is a curated composition family, not a copied page component."
                label="Master recipe"
                onChange={(value) => update("recipe", value)}
                value={controls.recipe}
              >
                <option value="auto">Automatic</option>
                {eligibleRecipes.map((recipe) => (
                  <option key={recipe.id} value={recipe.id}>
                    {recipe.id}
                  </option>
                ))}
              </SelectField>
            </div>

            <SelectField
              help="Controls motif and art-direction energy without changing facts or accessibility."
              label="Art direction"
              onChange={(value) =>
                update(
                  "artDirectionIntensity",
                  value as BeautyGeneratorLabControls["artDirectionIntensity"],
                )
              }
              value={controls.artDirectionIntensity}
            >
              <option value="restrained">Restrained</option>
              <option value="balanced">Balanced</option>
              <option value="expressive">Expressive</option>
            </SelectField>
          </Panel>

          <Panel title="Content pressure">
            <div className="lab-field-grid">
              <SelectField
                help="Exercises focused, normal, and indexed large-menu behavior."
                label="Services"
                onChange={(value) =>
                  update(
                    "serviceCount",
                    Number(value) as BeautyGeneratorLabControls["serviceCount"],
                  )
                }
                value={String(controls.serviceCount)}
              >
                <option value="1">1 service</option>
                <option value="6">6 services</option>
                <option value="24">24 services</option>
              </SelectField>
              <SelectField
                help="Zero omits the section; one becomes a founder feature; larger values recompose it."
                label="Team"
                onChange={(value) =>
                  update("teamCount", Number(value) as BeautyGeneratorLabControls["teamCount"])
                }
                value={String(controls.teamCount)}
              >
                <option value="0">No team</option>
                <option value="1">1 founder</option>
                <option value="3">3 people</option>
                <option value="6">6 people</option>
              </SelectField>
              <SelectField
                help="Only supplied verified fixture proof renders. Zero always omits proof."
                label="Reviews"
                onChange={(value) =>
                  update("reviewCount", Number(value) as BeautyGeneratorLabControls["reviewCount"])
                }
                value={String(controls.reviewCount)}
              >
                <option value="0">No proof</option>
                <option value="1">1 quote</option>
                <option value="3">3 reviews</option>
              </SelectField>
              <SelectField
                help="Two locations must preserve distinct NAP records and use a selector composition."
                label="Locations"
                onChange={(value) =>
                  update(
                    "locationCount",
                    Number(value) as BeautyGeneratorLabControls["locationCount"],
                  )
                }
                value={String(controls.locationCount)}
              >
                <option value="1">1 location</option>
                <option value="2">2 locations</option>
              </SelectField>
              <SelectField
                help="Approved fixture imagery is optional; missing imagery invokes a designed fallback."
                label="Image richness"
                onChange={(value) =>
                  update("imageRichness", value as BeautyGeneratorLabControls["imageRichness"])
                }
                value={controls.imageRichness}
              >
                <option value="none">No images</option>
                <option value="sparse">One image</option>
                <option value="rich">Rich</option>
              </SelectField>
              <SelectField
                help="Failure must still render a polished type/procedural fallback and preserve the prompt."
                label="Asset generation"
                onChange={(value) =>
                  update(
                    "generatedAssetState",
                    value as BeautyGeneratorLabControls["generatedAssetState"],
                  )
                }
                value={controls.generatedAssetState}
              >
                <option value="available">Available</option>
                <option value="failed">Force failure</option>
              </SelectField>
            </div>
          </Panel>

          <Panel title="Comparison">
            <label className="lab-check">
              <input
                checked={baselineEnabled}
                onChange={(event) => {
                  setBaselineEnabled(event.target.checked);
                  if (event.target.checked) setCompareEnabled(false);
                }}
                type="checkbox"
              />
              <span>
                Compare current V1
                <small>Same fictional facts and seed, archived compiler versus V2.</small>
              </span>
            </label>
            <label className="lab-check">
              <input
                checked={compareEnabled}
                onChange={(event) => {
                  setCompareEnabled(event.target.checked);
                  if (event.target.checked) setBaselineEnabled(false);
                }}
                type="checkbox"
              />
              <span>
                Compare a second seed
                <small>Same facts, independently compiled presentation.</small>
              </span>
            </label>
            <button
              className="button button--secondary lab-wide-button"
              disabled={busy}
              onClick={() => void renderSeedGrid()}
              type="button"
            >
              <Grid2X2 aria-hidden="true" size={17} />
              Render 12-seed grid
            </button>
          </Panel>
        </aside>

        <main className="beauty-lab__workspace">
          {error ? (
            <div className="lab-error" role="alert">
              <strong>Compiler refused this combination.</strong>
              <span>{error}</span>
              <button onClick={() => void compile()} type="button">
                <RefreshCw aria-hidden="true" size={16} /> Retry
              </button>
            </div>
          ) : null}

          {busy && result === null ? (
            <div className="lab-loading" role="status">
              <Sparkles aria-hidden="true" size={22} />
              Compiling and validating the selected design…
            </div>
          ) : null}

          {result ? (
            <>
              <div className={`lab-preview-grid ${compareResult ? "is-comparing" : ""}`}>
                <PreviewFrame
                  label={result.compilerMode === "v2" ? "V2 selected candidate" : "V1 baseline"}
                  result={result}
                />
                {compareResult ? (
                  <PreviewFrame
                    label={
                      baselineEnabled ? "Archived V1 baseline" : "V2 independent comparison seed"
                    }
                    result={compareResult}
                  />
                ) : null}
              </div>

              <section className="lab-fingerprint" aria-label="Design identity">
                <div>
                  <FlaskConical aria-hidden="true" size={18} />
                  <span>{result.v2 ? "Semantic fingerprint V2" : "Fingerprint V1"}</span>
                  <strong
                    title={
                      result.v2?.semanticFingerprint.fingerprint ??
                      result.manifest.uniqueness.fingerprint
                    }
                  >
                    {shortHash(
                      result.v2?.semanticFingerprint.fingerprint ??
                        result.manifest.uniqueness.fingerprint,
                    )}
                  </strong>
                </div>
                <div>
                  <Columns2 aria-hidden="true" size={18} />
                  <span>Recent-cohort similarity</span>
                  <strong>
                    {selectedV2Candidate
                      ? `${(100 - selectedV2Candidate.quality.diversity).toFixed(1)}%`
                      : result.manifest.uniqueness.nearestSimilarityScore === undefined
                        ? "No cohort match"
                        : `${(result.manifest.uniqueness.nearestSimilarityScore * 100).toFixed(1)}%`}
                  </strong>
                </div>
                <div>
                  <Check aria-hidden="true" size={18} />
                  <span>Capsule</span>
                  <strong>{result.v2?.capsule.id ?? result.manifest.masterRecipe}</strong>
                </div>
                <div>
                  <Sparkles aria-hidden="true" size={18} />
                  <span>Selected quality</span>
                  <strong>
                    {selectedV2Candidate
                      ? `${selectedV2Candidate.quality.total.toFixed(1)} / 100`
                      : "V1 · unscored"}
                  </strong>
                </div>
                <div>
                  <Braces aria-hidden="true" size={18} />
                  <span>Tournament</span>
                  <strong>
                    {result.v2
                      ? `${rejectedV2Count} rejected · ${result.v2.tournament.candidateCount} total`
                      : `Candidate ${result.manifest.candidateNonce}`}
                  </strong>
                </div>
                <div>
                  <Eye aria-hidden="true" size={18} />
                  <span>Coverage</span>
                  <strong>{result.rendered.informationCoverage.entries.length} mapped facts</strong>
                </div>
              </section>

              <Panel
                actions={
                  <button
                    className="button button--secondary"
                    onClick={() =>
                      jsonDownload(
                        `${fixtureId}-${result.manifest.uniqueness.fingerprint.slice(0, 8)}.json`,
                        {
                          fixtureId,
                          siteSpec: result.siteSpec,
                          manifest: result.manifest,
                          compilerMode: result.compilerMode,
                          capsule: result.v2?.capsule,
                          tournament: result.v2?.tournament,
                          capsuleLineage: result.v2?.lineage,
                          semanticFingerprint: result.v2?.semanticFingerprint,
                          eliteArchive: result.v2?.eliteArchive,
                          coverage: result.rendered.informationCoverage,
                          assetPrompts: result.exactPrompts,
                        },
                      )
                    }
                    type="button"
                  >
                    <Download aria-hidden="true" size={16} />
                    Export development manifest
                  </button>
                }
                className="lab-inspector"
                title="Compiler inspector"
              >
                <div aria-label="Inspector views" className="lab-tabs" role="tablist">
                  {(
                    [
                      ["manifest", Braces, "Manifest"],
                      ["capsule", FlaskConical, "Capsule"],
                      ["tournament", Grid2X2, "Tournament"],
                      ["lineage", Columns2, "Lineage"],
                      ["tokens", Sparkles, "Resolved tokens"],
                      ["coverage", Check, "Coverage"],
                      ["assets", FileImage, "Asset prompts"],
                    ] as const
                  ).map(([id, Icon, label]) => (
                    <button
                      aria-selected={inspector === id}
                      className={inspector === id ? "is-active" : ""}
                      key={id}
                      onClick={() => setInspector(id)}
                      role="tab"
                      type="button"
                    >
                      <Icon aria-hidden="true" size={16} />
                      {label}
                    </button>
                  ))}
                </div>
                <div className="lab-code-header">
                  <span>
                    {inspector === "assets" && result.exactPrompts.length === 0
                      ? "No generated asset is needed for this candidate."
                      : "Read-only deterministic output"}
                  </span>
                  <button
                    aria-label="Copy inspector JSON"
                    onClick={() =>
                      void navigator.clipboard.writeText(JSON.stringify(inspectorValue, null, 2))
                    }
                    title="Copy inspector JSON"
                    type="button"
                  >
                    <Copy aria-hidden="true" size={15} />
                  </button>
                </div>
                <pre role="tabpanel">{JSON.stringify(inspectorValue, null, 2)}</pre>
              </Panel>
            </>
          ) : null}

          {gridResults.length > 0 ? (
            <section className="lab-seed-grid">
              <header>
                <div>
                  <span>Structural variation</span>
                  <h2>12 independently seeded candidates</h2>
                </div>
                <button onClick={() => setGridResults([])} type="button">
                  Close grid
                </button>
              </header>
              <div>
                {gridResults.map((candidate) => (
                  <article key={candidate.manifest.uniqueness.fingerprint}>
                    <iframe
                      sandbox="allow-same-origin"
                      srcDoc={candidate.rendered.primaryHtml}
                      title={`Seed ${shortHash(candidate.manifest.uniqueness.fingerprint)}`}
                    />
                    <footer>
                      <strong>{candidate.manifest.masterRecipe}</strong>
                      <span>{candidate.manifest.typography.pairingId}</span>
                    </footer>
                  </article>
                ))}
              </div>
            </section>
          ) : null}
        </main>
      </div>
    </div>
  );
}