feat: rebuild Process Studio into multi-phase Process Creation Wizard\n\n- Replace toy Studio.tsx with proper Wizard.tsx canvas\n- Build 6-step flow: Intake -> Analyze -> Generate -> Validate -> Draft saved -> Publish\n- Implement incremental EA2 writes via wizardApi.ts (flow, batch apply)\n- Use localStorage for draft recovery across reloads\n- Apply industrial-blueprint UI styling matching core doctrine\n- Add Vitest tests for Wizard components and API wrappers

This commit is contained in:
2026-06-14 03:47:26 +04:00
parent b2c1e57c86
commit 4bc7ae228a
27 changed files with 2274 additions and 275 deletions
+21 -4
View File
@@ -4,12 +4,14 @@ import { useApp, scenarioById } from "./state/store";
import Landing from "./scenes/Landing";
import MissionControl from "./scenes/MissionControl";
import RunHistory from "./scenes/RunHistory";
import Studio from "./scenes/Studio";
import Wizard from "./scenes/Wizard";
import Settings from "./scenes/Settings";
import Login from "./scenes/Login";
import SsoCallback from "./scenes/SsoCallback";
import CommandBar from "./components/CommandBar";
import Toaster from "./components/Toaster";
import Console from "./components/Console";
import { Cmd, Home, Layers, History as HistoryIcon, Pulse, Refresh, Branch, Cog, User } from "./components/icons";
import { Cmd, Home, Layers, HistoryIcon, Pulse, Refresh, Branch, Cog, User, Sun, Moon } from "./components/icons";
import { liveMeta } from "./data/scenarios";
export default function App() {
@@ -30,6 +32,16 @@ export default function App() {
const userEmail = useApp((s) => s.userEmail);
const startPolling = useApp((s) => s.startPolling);
const stopPolling = useApp((s) => s.stopPolling);
const isAuthed = useApp((s) => s.isAuthed);
// Auth guard and SSO callback detector
useEffect(() => {
if (typeof window !== "undefined" && window.location.hash.includes("access_token")) {
setScene("sso-callback");
} else if (!isAuthed && scene !== "login" && scene !== "sso-callback") {
setScene("login");
}
}, [isAuthed, scene, setScene]);
useEffect(() => {
if (mode === "live") startPolling();
@@ -40,7 +52,7 @@ export default function App() {
return (
<div className={`shell shell-${scene}`}>
{scene !== "landing" && (
{scene !== "landing" && scene !== "login" && scene !== "sso-callback" && (
<header className="topbar" data-anchor="topbar">
<button className="brand-lock brand-btn" onClick={() => setScene("landing")} aria-label="Home">
<span className="brand-mark sm" />
@@ -121,6 +133,9 @@ export default function App() {
<Layers size={12} /> Console
{apiLogCount > 0 && <span className="badge mono">{apiLogCount}</span>}
</button>
<button className="link-btn" onClick={() => useApp.getState().setTheme(useApp.getState().theme === "dark" ? "light" : "dark")} title="Toggle theme">
{useApp.getState().theme === "dark" ? <Sun size={13} /> : <Moon size={13} />}
</button>
<button className="link-btn" onClick={() => setCmdOpen(true)}>
<Cmd size={13} /> <kbd>K</kbd>
</button>
@@ -129,10 +144,12 @@ export default function App() {
)}
<div className="scene">
{scene === "login" && <Login />}
{scene === "sso-callback" && <SsoCallback />}
{scene === "landing" && <Landing />}
{scene === "mission" && <MissionControl />}
{scene === "history" && <RunHistory />}
{scene === "studio" && <Studio />}
{scene === "studio" && <Wizard />}
{scene === "settings" && <Settings />}
</div>