From 9fb5b6d48d2c5aef7d956355e5149059c49b3830 Mon Sep 17 00:00:00 2001 From: GautamTalksDev Date: Sun, 30 Aug 2026 02:05:39 -0400 Subject: [PATCH 1/3] feat: add guided demo recording flow Automate the paced scan, human CI approval gate, execution results, and verified audit-ledger finish while keeping the controls isolated to demo and replay modes. Co-authored-by: Cursor --- apps/web/src/App.tsx | 33 ++ apps/web/src/api/client.ts | 88 ++++- apps/web/src/api/types.ts | 20 + apps/web/src/components/ApprovalCardView.tsx | 29 +- apps/web/src/components/ApprovalQueue.tsx | 36 +- apps/web/src/components/GuidedDemoPanel.tsx | 220 +++++++++++ apps/web/src/hooks/useGuidedDemo.ts | 349 ++++++++++++++++++ apps/web/src/hooks/useScanSession.ts | 18 +- docs/CONNECTORS.md | 13 +- docs/EXECUTE.md | 62 +++- docs/UI.md | 11 + fixtures/test-org/manifest.json | 2 +- .../connectors/src/github.contract.test.ts | 57 ++- packages/connectors/src/github/connector.ts | 193 ++++++++-- packages/connectors/src/github/tools.ts | 3 + .../connectors/src/revoke.contract.test.ts | 55 +++ packages/core/src/grant.ts | 35 +- packages/core/src/identity/run.ts | 15 +- scripts/demo.ts | 1 + scripts/test-org/live.ts | 103 ++++-- 20 files changed, 1195 insertions(+), 148 deletions(-) create mode 100644 apps/web/src/components/GuidedDemoPanel.tsx create mode 100644 apps/web/src/hooks/useGuidedDemo.ts diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 1ac3f23..7a2ce6c 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -1,11 +1,24 @@ import { AgentActivity } from "./components/AgentActivity.js"; import { ApprovalQueue } from "./components/ApprovalQueue.js"; import { ErrorBanner } from "./components/ErrorBanner.js"; +import { GuidedDemoPanel } from "./components/GuidedDemoPanel.js"; import { useScanSession } from "./hooks/useScanSession.js"; +import { useGuidedDemo } from "./hooks/useGuidedDemo.js"; import { classifyClientError, recoveryFor, type ProductErrorKind } from "./lib/errors.js"; export function App() { const session = useScanSession(); + const demoMode = + import.meta.env.VITE_DEMO_MODE === "1" || + import.meta.env.VITE_SCAN_DRIVER === "replay" || + session.activity.driver === "replay"; + const guided = useGuidedDemo({ + activity: session.activity, + cards: session.cards, + beginScan: session.beginScan, + updateCard: session.updateCard, + cancelScan: session.cancelScan, + }); const costs = session.activity.costs; const capped = session.activity.status === "cost_capped"; const partial = session.activity.status === "partial"; @@ -44,6 +57,15 @@ export function App() { : "no active scan"} {session.activity.driver ? ` · ${session.activity.driver}` : ""} + {demoMode && !guided.active ? ( + + ) : null} {showBanner && message ? ( @@ -72,9 +94,20 @@ export function App() { scanId={session.activity.scanId} scanStatus={session.activity.status} onCardUpdated={session.updateCard} + guidedMode={demoMode && guided.state.phase !== "idle"} + guidedCardId={guided.state.targetCardId} /> + {demoMode && guided.state.phase !== "idle" ? ( + + ) : null} +