executable-stories-react 0.15.0 → 0.17.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/interactive/ReportInteractive.tsx","../src/components/ui/empty.tsx","../src/lib/utils.ts","../src/components/ReportEmpty.tsx","../src/hooks/useReport.ts","../src/context/ReportContext.ts","../src/components/ReportScenario.tsx","../src/lib/step-params.tsx","../src/components/ReportSteps.tsx","../src/components/doc/DocNote.tsx","../src/components/ui/badge.tsx","../src/components/doc/DocTag.tsx","../src/components/doc/DocKv.tsx","../src/hooks/useRenderers.ts","../src/components/doc/DocCode.tsx","../src/components/doc/DocTable.tsx","../src/components/doc/DocLink.tsx","../src/lib/markdown.ts","../src/lib/url.ts","../src/components/doc/DocSection.tsx","../src/components/doc/DocMermaid.tsx","../src/components/doc/DocScreenshot.tsx","../src/components/doc/DocVideo.tsx","../src/components/doc/DocHtml.tsx","../src/components/doc/DocState.tsx","../src/components/doc/DocCustom.tsx","../src/components/doc/DocEntry.tsx","../src/components/ReportDocEntries.tsx","../src/components/ReportStoryboard.tsx","../src/components/ReportAttachments.tsx","../src/components/ReportTrace.tsx","../src/lib/trace.ts","../src/interactive/scenario-history-context.ts","../src/lib/run-history.ts","../src/components/ScenarioRunHistory.tsx","../src/components/ScenarioStaleness.tsx","../src/lib/provenance.ts","../src/interactive/scenario-freshness-context.tsx","../src/interactive/collapse-context.ts","../src/interactive/scenario-actions.tsx","../src/components/ui/card.tsx","../src/components/ui/dropdown-menu.tsx","../src/components/ReportScenarioList.tsx","../src/components/ReportFeatureIntro.tsx","../src/components/ReportFeature.tsx","../src/components/ReportFeatureList.tsx","../src/components/ReportMeta.tsx","../src/components/ReportSummary.tsx","../src/components/ReportSchemaError.tsx","../src/components/ReportShell.tsx","../src/components/ui/switch.tsx","../src/components/ui/toggle-group.tsx","../src/context/ReportRoot.tsx","../src/components/doc/NarrativeBlocks.tsx","../src/lib/hash-state.ts","../src/lib/scroll.ts","../src/result.ts","../src/interactive/filter.ts","../src/interactive/ReportAgentFilterNotice.tsx","../src/interactive/ReportFailureBanner.tsx","../src/interactive/ReportFilters.tsx","../src/interactive/ReportFreshness.tsx","../src/interactive/ReportLastRunDelta.tsx","../src/interactive/ReportSearch.tsx","../src/components/ui/input.tsx","../src/interactive/ReportShare.tsx","../src/components/ui/button.tsx","../src/interactive/ReportSinceLastVisit.tsx","../src/interactive/last-visit.ts","../src/interactive/ReportShortcutsHelp.tsx","../src/interactive/ReportToc.tsx","../src/interactive/ReportTocDrawer.tsx","../src/interactive/triage-default.ts","../src/interactive/use-deep-link-scroll.ts","../src/interactive/use-keyboard-shortcuts.ts","../src/interactive/use-theme.ts","../src/interactive/use-url-state.ts","../src/interactive/webmcp-tools.ts","../src/interactive/ReportInteractiveIsland.tsx","../src/interactive/island-renderers.tsx","../src/components/doc/MermaidView.tsx"],"sourcesContent":["'use client';\n\nimport type { StoryReport } from 'executable-stories-core';\nimport { Monitor, Moon, Sun } from 'lucide-react';\nimport { useTools } from 'webmcpable/react';\nimport {\n useCallback,\n useDeferredValue,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { ReportEmpty } from '../components/ReportEmpty';\nimport { ReportFeatureList } from '../components/ReportFeatureList';\nimport { ReportMeta } from '../components/ReportMeta';\nimport { ReportErrorShell } from '../components/ReportShell';\nimport { ReportSummary } from '../components/ReportSummary';\nimport { Switch } from '../components/ui/switch';\nimport { ToggleGroup, ToggleGroupItem } from '../components/ui/toggle-group';\nimport { ReportRoot } from '../context/ReportRoot';\nimport { reportLastRunMs } from '../lib/provenance';\nimport type { ScenarioHistoryMap } from '../lib/run-history';\nimport { scrollToScenarioId } from '../lib/scroll';\nimport { cn } from '../lib/utils';\nimport type { BuiltinRenderers, CustomRenderers } from '../renderers';\nimport type { Result } from '../result';\nimport { unwrapReport } from '../result';\nimport {\n CollapseProvider,\n useCollapseState,\n type CollapseApi,\n} from './collapse-context';\nimport {\n allTags,\n failedScenarios,\n filterReport,\n listFailures,\n type StatusFilter,\n} from './filter';\nimport { ReportAgentFilterNotice } from './ReportAgentFilterNotice';\nimport { ReportFailureBanner } from './ReportFailureBanner';\nimport { ReportFilters } from './ReportFilters';\nimport { ReportFreshness } from './ReportFreshness';\nimport { ReportLastRunDelta } from './ReportLastRunDelta';\nimport { ReportSearch } from './ReportSearch';\nimport { ReportShare } from './ReportShare';\nimport { ReportSinceLastVisit } from './ReportSinceLastVisit';\nimport { ReportShortcutsHelp } from './ReportShortcutsHelp';\nimport { ReportToc } from './ReportToc';\nimport { ReportTocDrawer } from './ReportTocDrawer';\nimport {\n failuresToPrompt,\n ScenarioActionsProvider,\n scenarioPermalink,\n scenarioToMarkdown,\n scenarioToPrompt,\n type ScenarioActions,\n} from './scenario-actions';\nimport { ScenarioFreshnessProvider } from './scenario-freshness-context';\nimport { ScenarioHistoryProvider } from './scenario-history-context';\nimport { defaultCollapsedIds, failuresFirst } from './triage-default';\nimport { useDeepLinkScroll } from './use-deep-link-scroll';\nimport { useKeyboardShortcuts } from './use-keyboard-shortcuts';\nimport { useTheme, type ThemePref } from './use-theme';\nimport { useUrlState } from './use-url-state';\nimport { reportTools, type AppliedFilter } from './webmcp-tools';\n\nexport interface ReportInteractiveProps {\n /** A StoryReport, or a Result-wrapped one (e.g., from parseStoryReport). */\n report: StoryReport | Result<StoryReport>;\n /** Renderers keyed by `story.custom({ type })` strings. */\n customRenderers?: CustomRenderers;\n /** Optional overrides for the heavy built-ins (mermaid, code, section). */\n renderers?: BuiltinRenderers;\n className?: string;\n title?: string;\n dataTheme?: 'light' | 'dark';\n /**\n * Drop the report's own title block (`<h1>` + summary + meta) while keeping\n * the search and filter controls. Use when the surrounding page already shows\n * the report title as its heading — e.g. the Astro stories index embedded in\n * Starlight, where Starlight renders the page `<h1>`.\n */\n hideHeader?: boolean;\n /**\n * Drop the report's in-content scenario table-of-contents sidebar and render\n * the scenarios full-width. Use when the surrounding page already provides\n * scenario navigation — e.g. the Astro stories index, where the feature/\n * scenario tree lives in Starlight's own sidebar. Avoids a second nav rail.\n */\n hideToc?: boolean;\n /**\n * Days before the report is flagged as stale (warning banner instead of the\n * \"Verified N ago\" line). 0 disables the stale warning. Default 7.\n */\n staleAfterDays?: number;\n /**\n * Recent run events per scenario id (from the CLI's --history-file store).\n * When present, scenario cards show a run-over-run timeline strip.\n */\n scenarioHistory?: ScenarioHistoryMap;\n /** Show the Share button in the header (default false). `--html-share` turns it on. */\n share?: boolean;\n /** Command the share dialog hands over. Default: `npx executable-stories share reports/`. */\n shareCommand?: string;\n}\n\nexport function ReportInteractive(props: ReportInteractiveProps) {\n const { report, className, title, dataTheme } = props;\n const result = unwrapReport(report);\n if (!result.ok) {\n return (\n <ReportErrorShell\n error={result.error}\n className={className}\n title={title}\n dataTheme={dataTheme}\n />\n );\n }\n return <ReportInteractiveView {...props} report={result.data} />;\n}\n\ninterface ReportInteractiveViewProps extends Omit<\n ReportInteractiveProps,\n 'report'\n> {\n report: StoryReport;\n}\n\nconst THEME_OPTIONS: { value: ThemePref; label: string; Icon: typeof Sun }[] = [\n { value: 'light', label: 'Light', Icon: Sun },\n { value: 'system', label: 'System', Icon: Monitor },\n { value: 'dark', label: 'Dark', Icon: Moon },\n];\n\n// Light / System / Dark as an icon segmented control, matching the view-mode one.\nfunction ThemeSegment({\n pref,\n onPref,\n}: {\n pref: ThemePref;\n onPref: (p: ThemePref) => void;\n}) {\n return (\n <ToggleGroup\n size=\"sm\"\n value={[pref]}\n onValueChange={(v) => {\n const next = v[0] as ThemePref | undefined;\n if (next) onPref(next);\n }}\n aria-label=\"Color theme\"\n >\n {THEME_OPTIONS.map(({ value, label, Icon }) => (\n <ToggleGroupItem\n key={value}\n value={value}\n aria-label={label}\n title={label}\n className=\"px-2\"\n >\n <Icon />\n </ToggleGroupItem>\n ))}\n </ToggleGroup>\n );\n}\n\nfunction ReportInteractiveView({\n report,\n customRenderers,\n renderers,\n className,\n title,\n dataTheme,\n hideHeader = false,\n hideToc = false,\n staleAfterDays = 7,\n scenarioHistory,\n share = false,\n shareCommand,\n}: ReportInteractiveViewProps) {\n // Search, status, tags and detail live in the URL fragment, so a filtered\n // view survives a refresh and can be pasted to someone else.\n const [urlState, setUrlState] = useUrlState();\n const { query, status: statusFilter, tags: activeTags, detail } = urlState;\n const setQuery = useCallback(\n (next: string) => setUrlState({ query: next }),\n [setUrlState],\n );\n const setStatusFilter = useCallback(\n (next: StatusFilter) => setUrlState({ status: next }),\n [setUrlState],\n );\n const setDetail = useCallback(\n (next: 'full' | 'minimal') => setUrlState({ detail: next }),\n [setUrlState],\n );\n const [helpOpen, setHelpOpen] = useState(false);\n const { pref: themePref, setPref: setThemePref } = useTheme();\n const searchRef = useRef<HTMLInputElement>(null);\n const expandId = useId();\n const docsId = useId();\n // Defer filtering off the live input value so typing stays responsive even\n // when the report is large — the input updates immediately, the filtered\n // tree catches up. (Vercel rerender-use-deferred-value.)\n const deferredQuery = useDeferredValue(query);\n const failures = useMemo(() => listFailures(report), [report]);\n const filtered = useMemo(\n // Features carrying failures float to the top so the first thing on screen\n // is the thing that needs attention; an all-green run keeps source order.\n () =>\n failuresFirst(\n filterReport(report, {\n query: deferredQuery,\n status: statusFilter,\n tags: activeTags,\n }),\n ),\n [report, deferredQuery, statusFilter, activeTags],\n );\n const isFiltering = query !== deferredQuery;\n\n const statusOptions = useMemo(() => {\n const s = report.summary;\n const opts: Array<{ key: StatusFilter; label: string; count: number }> = [\n { key: 'all', label: 'All', count: s.total },\n ];\n if (s.passed)\n opts.push({ key: 'passed', label: 'Passed', count: s.passed });\n if (s.failed)\n opts.push({ key: 'failed', label: 'Failed', count: s.failed });\n if (s.skipped)\n opts.push({ key: 'skipped', label: 'Skipped', count: s.skipped });\n if (s.pending)\n opts.push({ key: 'pending', label: 'Pending', count: s.pending });\n return opts;\n }, [report]);\n const tagOptions = useMemo(() => allTags(report), [report]);\n const toggleTag = useCallback(\n (tag: string) =>\n setUrlState({\n tags: activeTags.includes(tag)\n ? activeTags.filter((t) => t !== tag)\n : [...activeTags, tag],\n }),\n [activeTags, setUrlState],\n );\n\n const [toast, setToast] = useState<string | null>(null);\n const toastTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const showToast = useCallback((msg: string) => {\n setToast(msg);\n if (toastTimer.current) clearTimeout(toastTimer.current);\n toastTimer.current = setTimeout(() => setToast(null), 1800);\n }, []);\n const copy = useCallback(\n (text: string, msg: string) => {\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n navigator.clipboard.writeText(text).then(\n () => showToast(msg),\n () => showToast('Copy failed'),\n );\n }\n },\n [showToast],\n );\n const scenarioActions = useMemo<ScenarioActions>(\n () => ({\n copyLink: (s) => copy(scenarioPermalink(s), 'Link copied'),\n copyMarkdown: (s) => copy(scenarioToMarkdown(s), 'Markdown copied'),\n copyPrompt: (s) => copy(scenarioToPrompt(s), 'Prompt copied'),\n }),\n [copy],\n );\n const copyAllFailures = useCallback(\n () => copy(failuresToPrompt(failedScenarios(filtered)), 'Failures copied'),\n [copy, filtered],\n );\n const failureIndexRef = useRef(0);\n\n const allCollapsibleIds = useMemo(\n () =>\n report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),\n [report],\n );\n // On a run WITH failures the report opens as a triage surface: passing work\n // collapsed to titles, failures expanded (see defaultCollapsedIds). An\n // all-green run collapses nothing. Either way a persisted collapse set from a\n // previous visit wins, so this only ever seeds a first visit.\n const collapse = useCollapseState(\n useCallback(() => defaultCollapsedIds(report), [report]),\n );\n // Filtering is a temporary lens over the report, not a change to the user's\n // persisted collapse preferences. Always reveal matching features/scenarios\n // while a filter is active, then restore the previous collapse state when it\n // is cleared. Otherwise search can report a match that remains hidden inside\n // a triage-collapsed feature.\n const revealFilteredResults =\n deferredQuery.trim() !== '' ||\n statusFilter !== 'all' ||\n activeTags.length > 0;\n const visibleCollapse = useMemo<CollapseApi>(\n () =>\n revealFilteredResults\n ? { ...collapse.api, isCollapsed: () => false }\n : collapse.api,\n [collapse.api, revealFilteredResults],\n );\n const collapseAll = useCallback(\n () => collapse.collapseAll(allCollapsibleIds),\n [collapse, allCollapsibleIds],\n );\n // \"Expand all\" is a single binary: checked → every scenario open, unchecked →\n // all collapsed to titles. Starts unchecked on a failing run so the control\n // matches the triage default above rather than contradicting it.\n // (Per-scenario toggles may drift from this; harmless.)\n const [expandedAll, setExpandedAll] = useState<boolean>(\n () => report.summary.failed === 0,\n );\n const setExpanded = useCallback(\n (expanded: boolean) => {\n if (expanded) collapse.expandAll();\n else collapseAll();\n setExpandedAll(expanded);\n },\n [collapse, collapseAll],\n );\n\n // WebMCP: hand a browser agent the same four reads the MCP server exposes,\n // plus one tool that drives this view. A no-op in every browser without\n // `document.modelContext`, which is all of them outside flagged Chrome/Edge.\n const [agentFilter, setAgentFilter] = useState<AppliedFilter | null>(null);\n useTools(\n reportTools({\n report,\n view: urlState,\n setView: setUrlState,\n onAgentFilter: setAgentFilter,\n }),\n );\n // The notice belongs to the filter it announced. The moment the view no\n // longer matches — the reader typed, cleared a tag, hit reset — it is stale,\n // so it stops rendering without anything having to clear it.\n const showAgentFilter =\n agentFilter !== null &&\n agentFilter.search === query &&\n agentFilter.status === statusFilter &&\n agentFilter.tags.length === activeTags.length &&\n agentFilter.tags.every((tag) => activeTags.includes(tag));\n const clearFilters = useCallback(\n () => setUrlState({ query: '', status: 'all', tags: [] }),\n [setUrlState],\n );\n\n const focusSearch = useCallback(() => {\n searchRef.current?.focus();\n }, []);\n\n const stepFailure = useCallback(\n (direction: 1 | -1) => {\n if (failures.length === 0) return;\n failureIndexRef.current =\n (failureIndexRef.current + direction + failures.length) %\n failures.length;\n const target = failures[failureIndexRef.current];\n if (target) scrollToScenarioId(target.scenarioId);\n },\n [failures],\n );\n\n const toggleHelp = useCallback(() => {\n setHelpOpen((v) => !v);\n }, []);\n\n const escape = useCallback(() => {\n if (helpOpen) setHelpOpen(false);\n else if (query !== '') setQuery('');\n }, [helpOpen, query, setQuery]);\n\n useKeyboardShortcuts({\n onFocusSearch: focusSearch,\n onNextFailure: () => stepFailure(1),\n onPrevFailure: () => stepFailure(-1),\n onToggleHelp: toggleHelp,\n onEscape: escape,\n onExpandAll: () => setExpanded(true),\n onCollapseAll: () => setExpanded(false),\n });\n\n useDeepLinkScroll();\n\n const hasContent = filtered.features.length > 0;\n const totalScenarios = report.summary.total;\n const matchedScenarios = filtered.summary.total;\n // The scenario TOC earns its rail only when there's enough to jump between.\n // For a sparse report (a few scenarios, e.g. a single Playwright story) the\n // rail is dead space that squashes the content — render full-width instead.\n // `hideToc` (host-provided nav, e.g. Astro/Starlight) always wins.\n const showToc = !hideToc && totalScenarios > 3;\n\n return (\n <CollapseProvider value={visibleCollapse}>\n <ScenarioActionsProvider value={scenarioActions}>\n <ScenarioHistoryProvider value={scenarioHistory ?? null}>\n <ScenarioFreshnessProvider value={{ staleAfterDays, report }}>\n <ReportRoot\n report={filtered}\n customRenderers={customRenderers}\n renderers={renderers}\n >\n <main\n className={cn('es-report', 'es-report-interactive', className)}\n aria-label={title ?? 'Test report'}\n aria-busy={isFiltering}\n data-theme={dataTheme}\n data-detail-level={detail}\n >\n <header className=\"es-report-header\">\n {/* Nav bar: title left, search right (search stays even when the\n host page owns the title — hideHeader). */}\n <div\n data-es-navbar\n className={cn(\n 'flex flex-wrap items-center gap-4',\n hideHeader ? 'justify-end' : 'justify-between',\n )}\n >\n {hideHeader ? null : (\n <h1 className=\"min-w-0\">{title ?? 'Story Report'}</h1>\n )}\n {/* Search + theme sit together in the top-right corner — theme is\n set-once global chrome, so it lives in the header, not down in\n the per-list view controls. */}\n <div className=\"flex items-center gap-2\">\n <ReportSearch\n ref={searchRef}\n value={query}\n onChange={setQuery}\n matchedCount={matchedScenarios}\n totalCount={totalScenarios}\n />\n {share ? (\n <ReportShare command={shareCommand} onCopy={copy} />\n ) : null}\n <ThemeSegment pref={themePref} onPref={setThemePref} />\n </div>\n </div>\n {hideHeader ? null : (\n <>\n <ReportSummary />\n <ReportMeta />\n </>\n )}\n <ReportFreshness\n lastRunMs={reportLastRunMs(report)}\n ciUrl={report.ci?.url}\n staleAfterDays={staleAfterDays}\n />\n <ReportLastRunDelta\n history={scenarioHistory}\n report={report}\n />\n <ReportSinceLastVisit report={report} />\n\n {/* Filters first (what's shown: status, then tags)… */}\n <ReportFilters\n statuses={statusOptions}\n status={statusFilter}\n onStatus={setStatusFilter}\n tags={tagOptions}\n activeTags={activeTags}\n onToggleTag={toggleTag}\n />\n {/* …then the view controls (how it's shown), separated by a hairline\n so \"filter the data\" and \"change the view\" read as distinct.\n Switches, not checkboxes: these are immediate on/off view modes,\n which is what a switch signals. \"Show only failures\" is the\n Failed status filter's job, not a view mode. */}\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3\">\n {/* Narrow-screen scenario nav (the sidebar is lg-only). */}\n {showToc ? <ReportTocDrawer /> : null}\n <div className=\"flex items-center gap-2\">\n <Switch\n id={expandId}\n checked={expandedAll}\n onCheckedChange={setExpanded}\n />\n <label\n htmlFor={expandId}\n className=\"cursor-pointer text-sm text-muted-foreground select-none\"\n >\n Expand all\n </label>\n </div>\n <div className=\"flex items-center gap-2\">\n <Switch\n id={docsId}\n checked={detail === 'full'}\n onCheckedChange={(checked) =>\n setDetail(checked ? 'full' : 'minimal')\n }\n />\n <label\n htmlFor={docsId}\n className=\"cursor-pointer text-sm text-muted-foreground select-none\"\n >\n Show documentation\n </label>\n </div>\n </div>\n </header>\n {showAgentFilter ? (\n <ReportAgentFilterNotice\n applied={agentFilter}\n onReset={clearFilters}\n onDismiss={() => setAgentFilter(null)}\n />\n ) : null}\n <ReportFailureBanner failures={failures} onCopyAll={copyAllFailures} />\n {hasContent ? (\n showToc ? (\n <div className=\"flex gap-6\">\n <ReportToc />\n <div className=\"flex min-w-0 flex-1 flex-col gap-4\">\n <ReportFeatureList />\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col gap-4\">\n <ReportFeatureList />\n </div>\n )\n ) : (\n <ReportEmpty\n message={\n query ? 'No scenarios match the search.' : undefined\n }\n />\n )}\n {/* `?` is the shortcut (it is already Shift+/, so aria-keyshortcuts is\n just \"?\", not the malformed \"Shift+?\"). Character-based, so it\n works regardless of where ? sits on the user's keyboard layout. */}\n <button\n type=\"button\"\n className=\"es-shortcuts-trigger fixed right-4 bottom-4 z-40 flex size-9 items-center justify-center rounded-full border border-border bg-card text-muted-foreground shadow-sm transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50\"\n aria-label=\"Keyboard shortcuts\"\n aria-keyshortcuts=\"?\"\n onClick={toggleHelp}\n >\n ?\n </button>\n <ReportShortcutsHelp\n open={helpOpen}\n onClose={() => setHelpOpen(false)}\n />\n {toast ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"fixed bottom-4 left-1/2 -translate-x-1/2 rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background shadow-lg\"\n >\n {toast}\n </div>\n ) : null}\n </main>\n </ReportRoot>\n </ScenarioFreshnessProvider>\n </ScenarioHistoryProvider>\n </ScenarioActionsProvider>\n </CollapseProvider>\n );\n}\n","import { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Empty({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty\"\n className={cn(\n \"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-header\"\n className={cn(\n \"flex max-w-sm flex-col items-center gap-2 text-center\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst emptyMediaVariants = cva(\n \"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-6\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction EmptyMedia({\n className,\n variant = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof emptyMediaVariants>) {\n return (\n <div\n data-slot=\"empty-icon\"\n data-variant={variant}\n className={cn(emptyMediaVariants({ variant, className }))}\n {...props}\n />\n )\n}\n\nfunction EmptyTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-title\"\n className={cn(\"text-lg font-medium tracking-tight\", className)}\n {...props}\n />\n )\n}\n\nfunction EmptyDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <div\n data-slot=\"empty-description\"\n className={cn(\n \"text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-content\"\n className={cn(\n \"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Empty,\n EmptyHeader,\n EmptyTitle,\n EmptyDescription,\n EmptyContent,\n EmptyMedia,\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/** Merge class names with Tailwind-aware conflict resolution (shadcn `cn`). */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { Empty, EmptyHeader, EmptyTitle } from \"@/components/ui/empty\";\n\nexport interface ReportEmptyProps {\n message?: string;\n}\n\nexport function ReportEmpty({ message }: ReportEmptyProps) {\n return (\n <Empty aria-live=\"polite\" className=\"border\">\n <EmptyHeader>\n <EmptyTitle>{message ?? \"No scenarios in this report.\"}</EmptyTitle>\n </EmptyHeader>\n </Empty>\n );\n}\n","import { useContext } from \"react\";\nimport { ReportContext } from \"../context/ReportContext\";\n\nexport function useReport() {\n const ctx = useContext(ReportContext);\n if (!ctx) {\n throw new Error(\n \"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those.\",\n );\n }\n return ctx.report;\n}\n","import { createContext } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\nimport type { BuiltinRenderers, CustomRenderers } from \"../renderers\";\n\nexport interface ReportContextValue {\n report: StoryReport;\n customRenderers: CustomRenderers;\n renderers: BuiltinRenderers;\n}\n\nexport const ReportContext = createContext<ReportContextValue | null>(null);\n","import type { ReportScenario as ReportScenarioT } from \"executable-stories-core\";\nimport { formatDuration } from \"executable-stories-core/utils/duration\";\nimport { ReportSteps } from \"./ReportSteps\";\nimport { ReportStoryboard } from \"./ReportStoryboard\";\nimport { ReportDocEntries } from \"./ReportDocEntries\";\nimport { ReportAttachments } from \"./ReportAttachments\";\nimport { ReportTrace } from \"./ReportTrace\";\nimport { ScenarioRunHistory } from \"./ScenarioRunHistory\";\nimport { ScenarioStaleness } from \"./ScenarioStaleness\";\nimport { useCollapse } from \"../interactive/collapse-context\";\nimport { useScenarioActions } from \"../interactive/scenario-actions\";\nimport { Card, CardContent, CardHeader } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportScenarioProps {\n scenario: ReportScenarioT;\n /**\n * Omit the card's own title row (status badge + tags still render). Use when\n * the surrounding page already shows the scenario title as its heading — e.g.\n * the Astro detail page, where Starlight renders the title as the page `h1`.\n */\n hideTitle?: boolean;\n}\n\ntype Status = ReportScenarioT[\"status\"];\n\ninterface StatusMeta {\n label: string;\n glyph: string;\n glyphColor: string;\n badgeVariant: \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n /**\n * Whether to render the status as a visible pill. Passing scenarios drop it:\n * the green ✓ glyph + title already carry the status, so the pill would be\n * pure redundancy on every (usually passing) row, and dropping it keeps a\n * green run calm while the failure pill stays the one loud badge. A\n * non-showPill status still exposes an sr-only label for screen readers.\n */\n showPill: boolean;\n}\n\nconst STATUS_META: Record<Status, StatusMeta> = {\n passed: { label: \"Passed\", glyph: \"✓\", glyphColor: \"text-pass\", badgeVariant: \"passed\", showPill: false },\n failed: { label: \"Failed\", glyph: \"✗\", glyphColor: \"text-fail\", badgeVariant: \"failed\", showPill: true },\n skipped: { label: \"Skipped\", glyph: \"○\", glyphColor: \"text-skip\", badgeVariant: \"skipped\", showPill: true },\n pending: { label: \"Pending\", glyph: \"○\", glyphColor: \"text-pend\", badgeVariant: \"pending\", showPill: true },\n};\n\nexport function ReportScenario({ scenario, hideTitle = false }: ReportScenarioProps) {\n const titleId = `${scenario.id}-title`;\n const bodyId = `${scenario.id}-body`;\n const meta = STATUS_META[scenario.status];\n // A planned scenario (it.todo) is canonically \"pending\", but the reader\n // should see intent, not limbo.\n const label = scenario.planned ? \"Planned\" : meta.label;\n const collapse = useCollapse();\n const collapsible = collapse !== null && !hideTitle;\n const collapsed = collapsible ? collapse!.isCollapsed(scenario.id) : false;\n const actions = useScenarioActions();\n return (\n <Card\n id={scenario.id}\n data-status={scenario.status}\n {...(hideTitle\n ? { \"aria-label\": `${scenario.title}, ${label}` }\n : { \"aria-labelledby\": titleId })}\n className=\"gap-0 py-0\"\n >\n <CardHeader className=\"px-4 py-3\">\n <div\n className={cn(\n // Wraps rather than squeezing: on a phone the status/duration group\n // is ~160px, which leaves a title column a few characters wide.\n \"flex flex-wrap items-start gap-x-4 gap-y-1\",\n hideTitle ? \"justify-end\" : \"justify-between\",\n )}\n >\n {hideTitle ? null : (\n <h3 id={titleId} className=\"flex min-w-0 flex-1 basis-48 items-center gap-2 text-sm font-medium text-foreground\">\n {collapsible ? (\n <button\n type=\"button\"\n onClick={() => collapse!.toggle(scenario.id)}\n aria-expanded={!collapsed}\n aria-controls={bodyId}\n aria-label={`Toggle ${scenario.title}`}\n className=\"shrink-0 cursor-pointer text-muted-foreground hover:text-foreground\"\n >\n <span aria-hidden className={cn(\"inline-block text-xs transition-transform\", !collapsed && \"rotate-90\")}>▸</span>\n </button>\n ) : null}\n <span aria-hidden className={cn(\"text-sm leading-none\", meta.glyphColor)}>\n {meta.glyph}\n </span>\n <span>{scenario.title}</span>\n </h3>\n )}\n <div className=\"flex shrink-0 items-center gap-2\">\n <ScenarioRunHistory scenarioId={scenario.id} />\n <ScenarioStaleness scenario={scenario} />\n {scenario.durationMs > 0 ? (\n <span className=\"whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground\">\n {formatDuration(scenario.durationMs)}\n </span>\n ) : null}\n {meta.showPill ? (\n <Badge variant={meta.badgeVariant} aria-label={`Status: ${label}`}>\n {label}\n </Badge>\n ) : (\n <span className=\"sr-only\">{`Status: ${label}`}</span>\n )}\n {actions ? (\n <DropdownMenu>\n <DropdownMenuTrigger\n aria-label={`Actions for ${scenario.title}`}\n className=\"cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4\"\n >\n <MoreHorizontalIcon aria-hidden />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => actions.copyLink(scenario)}>\n <LinkIcon /> Copy link\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => actions.copyMarkdown(scenario)}>\n <FileTextIcon /> Copy as Markdown\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => actions.copyPrompt(scenario)}>\n <SparklesIcon /> Explain with AI\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n </div>\n {scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? (\n <ul aria-label=\"Tags and tickets\" className=\"flex flex-wrap gap-1.5\">\n {scenario.tags.map((t) => (\n <li key={`tag-${t}`}>\n <Badge variant=\"tag\">{t}</Badge>\n </li>\n ))}\n {(scenario.tickets ?? []).map((ticket) => (\n <li key={`ticket-${ticket.id}`}>\n {ticket.url ? (\n <a href={ticket.url} target=\"_blank\" rel=\"noreferrer noopener\" className=\"inline-flex min-h-6 items-center\">\n <Badge variant=\"outline\">{ticket.id}</Badge>\n </a>\n ) : (\n <Badge variant=\"outline\">{ticket.id}</Badge>\n )}\n </li>\n ))}\n </ul>\n ) : null}\n </CardHeader>\n <CardContent id={bodyId} hidden={collapsed} className=\"px-4 pt-0 pb-4\">\n {scenario.errorMessage ? (\n <pre\n role=\"alert\"\n className=\"mb-1 overflow-x-auto rounded-md border border-fail-border bg-fail-bg px-4 py-3.5 font-mono text-xs leading-relaxed whitespace-pre-wrap text-fail\"\n >\n {scenario.errorMessage}\n </pre>\n ) : null}\n <ReportStoryboard scenario={scenario} />\n <ReportSteps scenario={scenario} />\n {scenario.docEntries.length > 0 ? (\n <div data-es-docs className=\"mt-3\">\n <ReportDocEntries entries={scenario.docEntries} />\n </div>\n ) : null}\n <ReportAttachments attachments={scenario.attachments} />\n <ReportTrace spans={scenario.otelSpans} />\n </CardContent>\n </Card>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * Highlight step parameters (double-quoted strings, standalone numbers) in step\n * text — the React equivalent of the report's highlightStepParams. Returns a\n * node array so the matched params can be wrapped in a styled <span> without\n * dangerouslySetInnerHTML.\n *\n * Regex mirrors the string renderer exactly:\n * - `\"[^\"]*\"` double-quoted strings (numbers inside quotes stay part of the string)\n * - `(?<![\\w.-])\\d+(?:\\.\\d+)?(?![\\w.-])` standalone numbers, dot/word-boundary aware\n */\nconst STEP_PARAM_PATTERN = /\"[^\"]*\"|(?<![\\w.-])\\d+(?:\\.\\d+)?(?![\\w.-])/g;\n\nexport function highlightStepParams(text: string): ReactNode {\n const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));\n if (matches.length === 0) return text;\n\n const nodes: ReactNode[] = [];\n let lastIndex = 0;\n matches.forEach((match, i) => {\n const start = match.index;\n const end = start + match[0].length;\n if (start > lastIndex) nodes.push(text.slice(lastIndex, start));\n nodes.push(\n <span key={i} className=\"font-medium text-step-param italic\">\n {match[0]}\n </span>,\n );\n lastIndex = end;\n });\n if (lastIndex < text.length) nodes.push(text.slice(lastIndex));\n return nodes;\n}\n","import { highlightStepParams } from '@/lib/step-params';\nimport { cn } from '@/lib/utils';\nimport type { ReportScenario, ReportStep } from 'executable-stories-core';\nimport {\n assertionState,\n assertiveSteps,\n} from 'executable-stories-core/utils/assertive-steps';\nimport { formatDuration } from 'executable-stories-core/utils/duration';\nimport { ReportDocEntries } from './ReportDocEntries';\n\nexport interface ReportStepsProps {\n scenario: ReportScenario;\n}\n\nconst STEP_GLYPH: Record<string, string> = {\n passed: '✓',\n failed: '✗',\n skipped: '○',\n pending: '○',\n};\n\nconst STEP_GLYPH_COLOR: Record<string, string> = {\n passed: 'text-pass',\n failed: 'text-fail',\n skipped: 'text-skip',\n pending: 'text-pend',\n};\n\nexport function ReportSteps({ scenario }: ReportStepsProps) {\n if (scenario.steps.length === 0) return null;\n const unasserted = new Set(\n assertionState(scenario.steps) === 'unasserted'\n ? assertiveSteps(scenario.steps).map((step) => step.id)\n : [],\n );\n return (\n <ol data-slot=\"steps\" className=\"flex flex-col\">\n {scenario.steps.map((step) => (\n <ReportStepItem\n key={step.id}\n step={step}\n unasserted={unasserted.has(step.id)}\n />\n ))}\n </ol>\n );\n}\n\nexport function ReportStepItem({\n step,\n unasserted = false,\n}: {\n step: ReportStep;\n unasserted?: boolean;\n}) {\n // And/But (incl. auto-And repeats) read as continuations of the prior step —\n // indented with a muted keyword, matching the report's `.step.continuation`.\n const kw = step.keyword.toLowerCase();\n const continuation = kw === 'and' || kw === 'but';\n return (\n <li\n id={step.id}\n data-status={step.status}\n className={cn(\n 'py-1.5 text-[0.8125rem] leading-normal',\n continuation && 'pl-5',\n )}\n >\n <div className=\"flex items-baseline gap-2\">\n <span\n aria-hidden\n className={cn(\n 'w-4 shrink-0 text-center text-xs',\n STEP_GLYPH_COLOR[step.status],\n )}\n >\n {STEP_GLYPH[step.status] ?? '○'}\n </span>\n <span\n className={cn(\n 'min-w-[52px] shrink-0 font-mono text-xs font-semibold capitalize',\n continuation ? 'font-medium text-muted-foreground' : 'text-keyword',\n )}\n >\n {step.keyword}\n </span>\n <span className=\"flex-1 text-foreground\">\n {highlightStepParams(step.text)}\n </span>\n {unasserted ? (\n <span className=\"shrink-0 rounded-full border border-pend-border bg-pend-bg px-2 py-0.5 text-[0.6875rem] font-medium text-pend\">\n No assertion\n </span>\n ) : null}\n {step.durationMs > 0 ? (\n <span className=\"shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground\">\n {formatDuration(step.durationMs)}\n </span>\n ) : null}\n </div>\n {step.errorMessage ? (\n <pre\n role=\"alert\"\n className=\"mt-2.5 ml-6 overflow-x-auto rounded-md border border-fail-border bg-fail-bg px-4 py-3.5 font-mono text-xs leading-relaxed whitespace-pre-wrap text-fail\"\n >\n {step.errorMessage}\n </pre>\n ) : null}\n {step.docEntries.length > 0 ? (\n <div data-es-docs className=\"mt-2 ml-6\">\n <ReportDocEntries entries={step.docEntries} />\n </div>\n ) : null}\n </li>\n );\n}\n","import type { ReportDocNote } from \"executable-stories-core\";\n\nexport function DocNote({ entry }: { entry: ReportDocNote }) {\n return <p className=\"my-2 text-sm text-muted-foreground\">{entry.text}</p>;\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { useRender } from \"@base-ui/react/use-render\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90\",\n outline:\n \"border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n ghost: \"[a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 [a&]:hover:underline\",\n // Pass/skip/pending are the quiet states: outline + coloured text, no\n // fill, so a green report reads calm. Only `failed` keeps a tinted\n // fill, making it the single loud badge on the page, so red pops the\n // instant something breaks. Colour-as-accent, matching the KPI cards.\n passed: \"border-pass-border text-pass font-mono uppercase\",\n failed: \"border-fail-border bg-fail-bg text-fail font-mono uppercase\",\n skipped: \"border-skip-border text-skip font-mono uppercase\",\n pending: \"border-pend-border text-pend font-mono uppercase\",\n tag: \"border-border text-muted-foreground font-mono font-medium [a&]:hover:bg-muted\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant = \"default\",\n render,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & {\n // Base UI composition: pass `render={<a … />}` to swap the underlying tag —\n // replaces Radix's `asChild`. See rules/base-vs-radix.md.\n render?: useRender.RenderProp\n }) {\n return useRender({\n defaultTagName: \"span\",\n render,\n props: {\n \"data-slot\": \"badge\",\n \"data-variant\": variant,\n className: cn(badgeVariants({ variant }), className),\n ...props,\n },\n })\n}\n\nexport { Badge, badgeVariants }\n","import type { ReportDocTag } from \"executable-stories-core\";\nimport { Badge } from \"@/components/ui/badge\";\n\nexport function DocTag({ entry }: { entry: ReportDocTag }) {\n return (\n <ul className=\"my-2 flex flex-wrap gap-1.5\" aria-label=\"Tags\">\n {entry.names.map((n) => (\n <li key={n}>\n <Badge variant=\"tag\">{n}</Badge>\n </li>\n ))}\n </ul>\n );\n}\n","import type { ReportDocKv } from \"executable-stories-core\";\n\nfunction formatValue(value: unknown): string {\n if (value === null) return \"null\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport function DocKv({ entry }: { entry: ReportDocKv }) {\n return (\n <dl className=\"my-2 flex flex-wrap items-baseline gap-x-2 text-sm\">\n <dt className=\"font-semibold text-muted-foreground\">{entry.label}</dt>\n <dd className=\"min-w-0 break-words font-mono text-foreground\">{formatValue(entry.value)}</dd>\n </dl>\n );\n}\n","import { useContext } from \"react\";\nimport { ReportContext } from \"../context/ReportContext\";\nimport type { BuiltinRenderers, CustomRenderers } from \"../renderers\";\n\nconst EMPTY_CUSTOM: CustomRenderers = {};\nconst EMPTY_RENDERERS: BuiltinRenderers = {};\n\nexport function useCustomRenderers(): CustomRenderers {\n const ctx = useContext(ReportContext);\n return ctx?.customRenderers ?? EMPTY_CUSTOM;\n}\n\nexport function useBuiltinRenderers(): BuiltinRenderers {\n const ctx = useContext(ReportContext);\n return ctx?.renderers ?? EMPTY_RENDERERS;\n}\n","import type { ReactNode } from \"react\";\nimport type { ReportDocCode } from \"executable-stories-core\";\nimport { useBuiltinRenderers } from \"../../hooks/useRenderers\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Shared shell for code blocks: optional label + the scrollable `<pre>`. Both\n * the static `DocCode` and the island's CDN-highlighted variant render their\n * `<code>` into this so the two can never drift in spacing or chrome.\n */\nexport function CodeFigure({ label, children }: { label?: string; children: ReactNode }) {\n return (\n <figure className=\"my-3\">\n {label ? (\n <figcaption className=\"mb-1.5 text-xs font-medium text-muted-foreground\">{label}</figcaption>\n ) : null}\n <pre tabIndex={0} className=\"overflow-x-auto rounded-md bg-muted p-3\">\n {children}\n </pre>\n </figure>\n );\n}\n\nexport function DocCode({ entry }: { entry: ReportDocCode }) {\n const renderers = useBuiltinRenderers();\n if (renderers.code) {\n return <>{renderers.code(entry)}</>;\n }\n return (\n <CodeFigure label={entry.label}>\n <code className={cn(\"font-mono text-xs\", entry.lang && `language-${entry.lang}`)}>\n {entry.content}\n </code>\n </CodeFigure>\n );\n}\n","import type { ReportDocTable } from \"executable-stories-core\";\n\nexport function DocTable({ entry }: { entry: ReportDocTable }) {\n return (\n <figure className=\"my-3\">\n {entry.label ? (\n <figcaption className=\"mb-1.5 text-xs font-medium text-muted-foreground\">\n {entry.label}\n </figcaption>\n ) : null}\n <div tabIndex={0} className=\"overflow-x-auto rounded-md border border-border\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"bg-muted/50\">\n {entry.columns.map((c) => (\n <th key={c} scope=\"col\" className=\"border-b border-border px-3 py-2 text-left font-semibold\">\n {c}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {entry.rows.map((row, i) => (\n <tr key={i}>\n {row.map((cell, j) => (\n <td key={j} className=\"border-b border-border px-3 py-2 text-foreground\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </figure>\n );\n}\n","import type { ReportDocLink } from \"executable-stories-core\";\n\nexport function DocLink({ entry }: { entry: ReportDocLink }) {\n return (\n <a\n className=\"text-sm font-medium text-primary underline underline-offset-2 hover:no-underline\"\n href={entry.url}\n rel=\"noreferrer noopener\"\n target=\"_blank\"\n >\n {entry.label}\n </a>\n );\n}\n","import { marked } from \"marked\";\nimport { safeUrl } from \"./url\";\n\n/**\n * Best-effort sanitizer for marked-generated HTML. The markdown we render is\n * authored in test source (developer-trusted), so this is defense-in-depth,\n * not a hard boundary against hostile input. It:\n * - drops <script>/<style> and other active elements (iframe/object/embed/form)\n * - strips on* event-handler attributes\n * - neutralizes any non-http(s) scheme on href/src via the shared `safeUrl`\n * allow-list (covers javascript:/data:/vbscript:/file:, not just javascript:)\n *\n * It is NOT a substitute for a full HTML sanitizer (it won't catch entity-\n * obfuscated schemes). For untrusted markdown, supply your own renderer.\n */\nexport function safeMarkdownHtml(markdown: string): string {\n const raw = marked.parse(markdown, { async: false }) as string;\n return raw\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gi, \"\")\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, \"\")\n .replace(/<\\/?(?:iframe|object|embed|form|base)\\b[^>]*>/gi, \"\")\n .replace(/\\son[a-z]+\\s*=\\s*\"[^\"]*\"/gi, \"\")\n .replace(/\\son[a-z]+\\s*=\\s*'[^']*'/gi, \"\")\n .replace(/\\son[a-z]+\\s*=\\s*[^\\s>]+/gi, \"\")\n .replace(/(href|src)\\s*=\\s*\"([^\"]*)\"/gi, (_m, attr, val) => `${attr}=\"${neutralizeUrl(val)}\"`)\n .replace(/(href|src)\\s*=\\s*'([^']*)'/gi, (_m, attr, val) => `${attr}='${neutralizeUrl(val)}'`);\n}\n\n/**\n * Strip the leading indentation a template literal picks up from its source.\n *\n * Narratives are written inline in test files, so they arrive indented to match\n * the surrounding code. Left alone, four spaces make Markdown render the whole\n * paragraph as a code block.\n */\nexport function dedent(text: string): string {\n const lines = text.replace(/\\t/g, \" \").split(\"\\n\");\n const indents = lines\n .filter((line) => line.trim().length > 0)\n .map((line) => line.length - line.trimStart().length);\n const shortest = indents.length > 0 ? Math.min(...indents) : 0;\n return lines\n .map((line) => line.slice(shortest))\n .join(\"\\n\")\n .trim();\n}\n\nfunction neutralizeUrl(value: string): string {\n return safeUrl(value) ?? \"#\";\n}\n","/**\n * URL trust boundary for report-sourced strings reaching the DOM. The\n * implementation lives in executable-stories-core/utils/url (shared with the\n * Astro state-catalog thumbnails); this module stays as the package-local\n * import point. Subpath import: the core package root pulls in Node-only\n * converters, which breaks browser bundles.\n */\nexport { safeUrl, safeImageUrl, isLocalFsPath } from \"executable-stories-core/utils/url\";\n","import type { ReportDocSection } from \"executable-stories-core\";\nimport { useBuiltinRenderers } from \"../../hooks/useRenderers\";\nimport { safeMarkdownHtml } from \"../../lib/markdown\";\n\nexport function DocSection({ entry }: { entry: ReportDocSection }) {\n const renderers = useBuiltinRenderers();\n if (renderers.section) {\n return <>{renderers.section(entry)}</>;\n }\n const html = safeMarkdownHtml(entry.markdown);\n return (\n <section className=\"my-3 text-sm\" aria-label={entry.title}>\n {entry.title ? <h4 className=\"mb-1 font-semibold text-foreground\">{entry.title}</h4> : null}\n <div\n className=\"es-doc-prose prose prose-sm max-w-none\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </section>\n );\n}\n","import type { Ref } from \"react\";\nimport type { ReportDocMermaid } from \"executable-stories-core\";\nimport { useBuiltinRenderers } from \"../../hooks/useRenderers\";\n\n/**\n * The raw mermaid source as a semantic `<pre data-mermaid>`. This is the\n * default render and the universal fallback: AI agents, screen readers, and\n * no-JS views all get the readable source. `<MermaidDiagram>` upgrades this to\n * a drawn diagram on the client.\n */\nexport function MermaidSource({ entry, ref }: { entry: ReportDocMermaid; ref?: Ref<HTMLElement> }) {\n return (\n <figure ref={ref} className=\"my-3\" aria-label={entry.title ?? \"Diagram\"}>\n {entry.title ? (\n <figcaption className=\"mb-1.5 text-xs font-medium text-muted-foreground\">{entry.title}</figcaption>\n ) : null}\n <pre\n data-mermaid\n tabIndex={0}\n className=\"overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground\"\n >\n {entry.code}\n </pre>\n </figure>\n );\n}\n\n/**\n * Renders mermaid source as a semantic `<pre data-mermaid>` by default.\n *\n * To draw the diagram, supply a `renderers.mermaid` prop — e.g. the shipped\n * `MermaidDiagram` (`renderers={{ mermaid: (e) => <MermaidDiagram entry={e} /> }}`).\n */\nexport function DocMermaid({ entry }: { entry: ReportDocMermaid }) {\n const renderers = useBuiltinRenderers();\n if (renderers.mermaid) {\n return <>{renderers.mermaid(entry)}</>;\n }\n return <MermaidSource entry={entry} />;\n}\n","import type { ReportDocScreenshot } from \"executable-stories-core\";\nimport { isLocalFsPath, safeImageUrl } from \"../../lib/url\";\n\n/**\n * A screenshot that's still an absolute local filesystem path by the time it\n * reaches this component means the report's asset bundler couldn't find the\n * file to inline/copy it (deleted, moved, or never captured — see\n * inlineScreenshotIfPossible in executable-stories-playwright). `<img src>`\n * would 404 against a path from the machine that generated the report, so\n * show a placeholder instead of a broken image.\n */\nexport function DocScreenshot({ entry }: { entry: ReportDocScreenshot }) {\n const src = isLocalFsPath(entry.path) ? undefined : safeImageUrl(entry.path);\n\n if (!src) {\n return (\n <figure className=\"my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground\">\n <div className=\"font-medium\">Screenshot unavailable</div>\n <div className=\"mt-1 break-all font-mono text-xs\">{entry.path}</div>\n {entry.alt ? <figcaption className=\"mt-1.5 text-xs\">{entry.alt}</figcaption> : null}\n </figure>\n );\n }\n\n return (\n <figure className=\"my-3\">\n <img\n src={src}\n alt={entry.alt ?? \"\"}\n loading=\"lazy\"\n className=\"max-w-full rounded-md border border-border\"\n />\n {entry.alt ? <figcaption className=\"mt-1.5 text-xs text-muted-foreground\">{entry.alt}</figcaption> : null}\n </figure>\n );\n}\n","import type { ReportDocVideo } from \"executable-stories-core\";\nimport { isLocalFsPath, safeUrl } from \"../../lib/url\";\n\n/**\n * Renders a video doc entry. Video bytes are large and never inlined; `path` is\n * a URL or a path that resolves alongside the report. Both `path` and `poster`\n * are adapter-supplied, so they go through the same scheme allow-list as the\n * DocHtml iframe src (no `javascript:`/`data:` URLs reach the DOM).\n *\n * An absolute local filesystem path means the report's asset bundler\n * couldn't find/copy the file — a `<video src>` pointed at a runner-local\n * path would just fail to load, so show a placeholder instead.\n */\nexport function DocVideo({ entry }: { entry: ReportDocVideo }) {\n if (isLocalFsPath(entry.path)) {\n return (\n <figure className=\"my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground\">\n <div className=\"font-medium\">Video unavailable</div>\n <div className=\"mt-1 break-all font-mono text-xs\">{entry.path}</div>\n {entry.caption ? <figcaption className=\"mt-1.5 text-xs\">{entry.caption}</figcaption> : null}\n </figure>\n );\n }\n\n const src = safeUrl(entry.path);\n const poster = safeUrl(entry.poster);\n return (\n <figure className=\"my-3\">\n <video\n controls\n preload=\"metadata\"\n {...(src ? { src } : {})}\n {...(poster ? { poster } : {})}\n className=\"max-w-full rounded-md border border-border\"\n />\n {entry.caption ? (\n <figcaption className=\"mt-1 text-xs text-muted-foreground\">{entry.caption}</figcaption>\n ) : null}\n </figure>\n );\n}\n","import type { ReportDocHtml } from \"executable-stories-core\";\nimport { safeUrl } from \"../../lib/url\";\n\n/**\n * Renders an embedded-HTML doc entry inside a SANDBOXED iframe. All embedded\n * HTML is untrusted, so the frame is `sandbox=\"allow-scripts\"` only (no\n * allow-same-origin) — embedded scripts run (charts work) but can't touch the\n * report DOM, cookies, or storage. Inline `content` → srcdoc (keeps the report\n * self-contained); `url`/`path` → src (scheme-validated).\n */\nexport function DocHtml({ entry }: { entry: ReportDocHtml }) {\n const height = typeof entry.height === \"number\" ? `${entry.height}px` : (entry.height ?? \"400px\");\n const title = entry.title ?? \"Embedded HTML\";\n const safeHref = safeUrl(entry.url ?? entry.path);\n\n // Exactly one of content / url / path is set. A url/path with an unsafe\n // scheme yields no src (the figure still renders, just empty).\n const frameProps = entry.content !== undefined ? { srcDoc: entry.content } : { src: safeHref ?? \"\" };\n\n return (\n <figure className=\"my-3 overflow-hidden rounded-md border border-border\">\n <figcaption className=\"flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground\">\n <span>{entry.title ?? \"HTML\"}</span>\n {safeHref ? (\n <a\n href={safeHref}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n aria-label=\"Open in new tab\"\n title=\"Open in new tab\"\n className=\"text-primary\"\n >\n ↗\n </a>\n ) : null}\n </figcaption>\n <iframe\n {...frameProps}\n sandbox=\"allow-scripts\"\n loading=\"lazy\"\n title={title}\n className=\"block w-full border-0\"\n // Embedded HTML is authored standalone, so it assumes a light page. An\n // iframe with no background inherits the host's dark canvas (via the\n // report's `color-scheme`), leaving that authored dark text unreadable.\n style={{ height, colorScheme: \"light\", background: \"#fff\" }}\n />\n </figure>\n );\n}\n","import type { ReportDocState } from \"executable-stories-core\";\nimport { CodeFigure } from \"./DocCode\";\n\n/**\n * A `story.state()` snapshot in the step detail: label + pretty JSON, same\n * chrome as `code(json)`. Frame-to-frame diffs are the storyboard's job —\n * here the entry just shows what was captured at this step.\n */\nexport function DocState({ entry }: { entry: ReportDocState }) {\n let json: string;\n try {\n json = JSON.stringify(entry.value, null, 2) ?? String(entry.value);\n } catch {\n json = String(entry.value);\n }\n return (\n <CodeFigure label={entry.label ?? \"State\"}>\n <code className=\"font-mono text-xs language-json\">{json}</code>\n </CodeFigure>\n );\n}\n","import type { ReportDocCustom } from \"executable-stories-core\";\nimport { useCustomRenderers } from \"../../hooks/useRenderers\";\n\nexport function DocCustom({ entry }: { entry: ReportDocCustom }) {\n const renderers = useCustomRenderers();\n const renderer = renderers[entry.type];\n if (renderer) {\n return <>{renderer(entry)}</>;\n }\n return (\n <div className=\"my-2\" data-type={entry.type}>\n <p className=\"mb-1 text-xs font-medium text-muted-foreground\">{entry.type}</p>\n <pre tabIndex={0} className=\"overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground\">\n {safeStringify(entry.data)}\n </pre>\n </div>\n );\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n","import type { ReportDocEntry } from \"executable-stories-core\";\nimport { DocNote } from \"./DocNote\";\nimport { DocTag } from \"./DocTag\";\nimport { DocKv } from \"./DocKv\";\nimport { DocCode } from \"./DocCode\";\nimport { DocTable } from \"./DocTable\";\nimport { DocLink } from \"./DocLink\";\nimport { DocSection } from \"./DocSection\";\nimport { DocMermaid } from \"./DocMermaid\";\nimport { DocScreenshot } from \"./DocScreenshot\";\nimport { DocVideo } from \"./DocVideo\";\nimport { DocHtml } from \"./DocHtml\";\nimport { DocState } from \"./DocState\";\nimport { DocCustom } from \"./DocCustom\";\n\nexport function DocEntry({ entry }: { entry: ReportDocEntry }) {\n switch (entry.kind) {\n case \"note\":\n return <DocNote entry={entry} />;\n case \"tag\":\n return <DocTag entry={entry} />;\n case \"kv\":\n return <DocKv entry={entry} />;\n case \"code\":\n return <DocCode entry={entry} />;\n case \"table\":\n return <DocTable entry={entry} />;\n case \"link\":\n return <DocLink entry={entry} />;\n case \"section\":\n return <DocSection entry={entry} />;\n case \"mermaid\":\n return <DocMermaid entry={entry} />;\n case \"screenshot\":\n return <DocScreenshot entry={entry} />;\n case \"video\":\n return <DocVideo entry={entry} />;\n case \"html\":\n return <DocHtml entry={entry} />;\n case \"state\":\n return <DocState entry={entry} />;\n case \"custom\":\n return <DocCustom entry={entry} />;\n }\n}\n","import type { ReportDocEntry } from \"executable-stories-core\";\nimport { DocEntry } from \"./doc/DocEntry\";\n\nexport interface ReportDocEntriesProps {\n entries: readonly ReportDocEntry[];\n}\n\nexport function ReportDocEntries({ entries }: ReportDocEntriesProps) {\n if (entries.length === 0) return null;\n return (\n <>\n {entries.map((entry, i) => (\n <DocEntry key={i} entry={entry} />\n ))}\n </>\n );\n}\n","import type { ReportScenario } from \"executable-stories-core\";\n// Subpath import: the core package root pulls in Node-only converters\n// (node:crypto), which breaks browser bundles — see formatDuration's import.\nimport { extractStoryboardFrames } from \"executable-stories-core/storyboard\";\nimport type { StoryboardFrame, StoryboardStateCard } from \"executable-stories-core/storyboard\";\nimport { summarizeStateChanges } from \"executable-stories-core/state-diff\";\nimport type { StateChangeKind } from \"executable-stories-core/state-diff\";\nimport { isLocalFsPath, safeImageUrl } from \"executable-stories-core/utils/url\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportStoryboardProps {\n scenario: ReportScenario;\n}\n\nconst FRAME_GLYPH: Record<string, string> = {\n passed: \"✓\",\n failed: \"✗\",\n skipped: \"○\",\n pending: \"○\",\n};\n\nconst FRAME_GLYPH_COLOR: Record<string, string> = {\n passed: \"text-pass\",\n failed: \"text-fail\",\n skipped: \"text-skip\",\n pending: \"text-pend\",\n};\n\n/**\n * Storyboard — a horizontal filmstrip of the scenario's step evidence\n * (Given → When → Then), derived from the same step docs the vertical step\n * list renders. A frame is a container: the step's screenshot (when present)\n * plus its `story.state()` snapshot cards, so data-only scenarios get\n * filmstrips too. Each frame links to its step's anchor.\n *\n * Renders nothing below 2 frames: a single capture is evidence, not a\n * walkthrough, and it already shows under its step.\n *\n * Must stay hydration-free: the Astro story pages render this inside a static\n * (no client JS) island, so navigation is plain anchors and snapshot expansion\n * is a native <details> — no lightbox or toggle state.\n */\nexport function ReportStoryboard({ scenario }: ReportStoryboardProps) {\n const frames = extractStoryboardFrames(scenario);\n if (frames.length < 2) return null;\n return (\n <section data-slot=\"storyboard\" aria-label=\"Storyboard\" className=\"mb-3\">\n <h4 className=\"mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n Storyboard\n </h4>\n <ol className=\"flex items-start gap-3 overflow-x-auto pb-2\">\n {frames.map((frame) => (\n <StoryboardFrameItem key={frame.stepId} frame={frame} />\n ))}\n </ol>\n </section>\n );\n}\n\nfunction StoryboardFrameItem({ frame }: { frame: StoryboardFrame }) {\n const label = `${frame.keyword} ${frame.text}`;\n const hasStates = frame.states.length > 0;\n const caption = (\n <p className=\"mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug\">\n <span aria-hidden className={cn(\"shrink-0\", FRAME_GLYPH_COLOR[frame.status])}>\n {FRAME_GLYPH[frame.status] ?? \"○\"}\n </span>\n <span className=\"min-w-0\">\n <span className=\"font-mono font-semibold text-keyword\">{frame.keyword}</span>{\" \"}\n <span className=\"text-muted-foreground\">{frame.screenshot?.alt ?? frame.text}</span>\n </span>\n </p>\n );\n return (\n // State cards need room for diff rows; screenshot-only frames keep the\n // original narrow film-cell width (and DOM) unchanged.\n <li className={cn(\"shrink-0\", hasStates ? \"w-64\" : \"w-40\")}>\n {frame.screenshot ? (\n <FrameScreenshot frame={frame} label={label} />\n ) : null}\n {hasStates ? (\n <div className={cn(\"flex flex-col gap-1.5\", frame.screenshot && \"mt-1.5\")}>\n {frame.states.map((card, i) => (\n <StateCardView key={card.label ?? i} card={card} />\n ))}\n </div>\n ) : null}\n {frame.screenshot ? (\n caption\n ) : (\n // No screenshot means no image anchor, so the caption carries the\n // jump-to-step link instead.\n <a href={`#${frame.stepId}`} aria-label={`Jump to step: ${label}`} className=\"block hover:underline\">\n {caption}\n </a>\n )}\n </li>\n );\n}\n\nfunction FrameScreenshot({ frame, label }: { frame: StoryboardFrame; label: string }) {\n const path = frame.screenshot?.path ?? \"\";\n const src = isLocalFsPath(path) ? undefined : safeImageUrl(path);\n return (\n <a\n href={`#${frame.stepId}`}\n aria-label={`Jump to step: ${label}`}\n className=\"block overflow-hidden rounded-md border border-border transition-colors hover:border-ring\"\n >\n {src ? (\n <img\n src={src}\n alt={frame.screenshot?.alt ?? label}\n loading=\"lazy\"\n className=\"h-24 w-full bg-muted object-cover object-top\"\n />\n ) : (\n <span className=\"flex h-24 w-full items-center justify-center border-b border-dashed border-border bg-muted px-2 text-center text-[0.6875rem] text-muted-foreground\">\n Screenshot unavailable\n </span>\n )}\n </a>\n );\n}\n\n// Same accent scheme as the status badges/KPI cards: green = new, red = gone,\n// amber (skip tokens) = changed. Text + bg pairs are the AA-audited --es-*\n// combinations from tailwind.css.\nconst CHANGE_TONE: Record<StateChangeKind, string> = {\n added: \"bg-pass-bg text-pass\",\n removed: \"bg-fail-bg text-fail\",\n changed: \"bg-skip-bg text-skip\",\n};\n\nfunction prettyJson(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/**\n * One `story.state()` snapshot card: label chip, then what changed since the\n * previous frame's snapshot of the same label (changed fields first, full\n * snapshot behind a disclosure). First appearance shows the snapshot itself\n * with a \"first capture\" hint — there is nothing to diff against yet.\n */\nfunction StateCardView({ card }: { card: StoryboardStateCard }) {\n const json = prettyJson(card.value);\n const firstCapture = card.changes === undefined;\n return (\n <div data-slot=\"state-card\" className=\"rounded-md border border-border bg-card p-2\">\n <p className=\"flex flex-wrap items-baseline gap-1.5\">\n <span className=\"inline-flex rounded-full border border-border px-1.5 font-mono text-[0.625rem] font-medium text-muted-foreground\">\n {card.label ?? \"State\"}\n </span>\n {firstCapture ? (\n <span className=\"text-[0.625rem] text-muted-foreground italic\">first capture</span>\n ) : null}\n </p>\n {!firstCapture &&\n (card.changes && card.changes.length > 0 ? (\n <ul className=\"mt-1.5 flex flex-col gap-0.5\">\n {card.changes.map((change, i) => (\n <li\n key={i}\n className={cn(\n \"rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all\",\n CHANGE_TONE[change.kind]\n )}\n >\n {summarizeStateChanges([change])[0]}\n </li>\n ))}\n </ul>\n ) : (\n <p className=\"mt-1.5 text-[0.625rem] text-muted-foreground\">No changes</p>\n ))}\n <details\n // First capture opens short snapshots by default: it IS the card's\n // content. Diff cards keep the snapshot collapsed — the rows above\n // already tell the story.\n open={firstCapture && json.length <= 240}\n className={cn(firstCapture ? \"mt-1.5\" : \"mt-1\")}\n >\n <summary className=\"cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground\">\n Snapshot\n </summary>\n <pre tabIndex={0} className=\"mt-1 max-h-48 overflow-auto rounded-sm bg-muted p-1.5 font-mono text-[0.625rem] leading-snug\">\n {json}\n </pre>\n </details>\n </div>\n );\n}\n","import type { ReportAttachment } from \"executable-stories-core\";\n\n/**\n * Renders scenario attachments. Base64 images embed inline; everything else\n * becomes a labelled data-URI download link. Mirrors the report's attachments\n * block (which also inlines images and links other media).\n */\nexport function ReportAttachments({ attachments }: { attachments: ReportAttachment[] }) {\n if (attachments.length === 0) return null;\n return (\n // role=\"group\" (not a labelled <section>) so multiple scenarios' attachment\n // blocks don't create duplicate \"Attachments\" region landmarks.\n <div role=\"group\" aria-label=\"Attachments\" className=\"mt-3 flex flex-col gap-2\">\n {attachments.map((att, i) => {\n const dataUri =\n att.contentEncoding === \"BASE64\"\n ? `data:${att.mediaType};base64,${att.body}`\n : `data:${att.mediaType},${encodeURIComponent(att.body)}`;\n const isImage = att.mediaType.startsWith(\"image/\");\n return (\n <figure key={`${att.name}-${i}`} className=\"m-0\">\n {isImage ? (\n <>\n <img\n src={dataUri}\n alt={att.name}\n loading=\"lazy\"\n className=\"max-w-full rounded-md border border-border\"\n />\n <figcaption className=\"mt-1 text-xs text-muted-foreground\">{att.name}</figcaption>\n </>\n ) : (\n <a\n href={dataUri}\n download={att.name}\n className=\"text-xs text-link underline underline-offset-2\"\n >\n {att.name} <span className=\"text-muted-foreground\">({att.mediaType})</span>\n </a>\n )}\n </figure>\n );\n })}\n </div>\n );\n}\n","import type { OtelSpan } from \"executable-stories-core/types/otel\";\nimport { formatDuration } from \"executable-stories-core/utils/duration\";\nimport { toTraceRows, traceWindow } from \"@/lib/trace\";\nimport { cn } from \"@/lib/utils\";\n\nconst BAR_COLOR: Record<string, string> = {\n ok: \"bg-pass\",\n error: \"bg-fail\",\n unset: \"bg-skip\",\n};\n\n/**\n * OTel trace waterfall. Collapsed by default (native <details>, no JS) so it\n * renders in both the static and interactive reports. Each span is a row with a\n * depth-indented name and a bar positioned/sized by its time window.\n */\nexport function ReportTrace({ spans }: { spans: readonly OtelSpan[] | undefined }) {\n if (!spans || spans.length === 0) return null;\n const rows = toTraceRows(spans);\n if (rows.length === 0) return null;\n const { minStartMs, totalMs } = traceWindow(rows);\n\n return (\n <details className=\"mt-3 rounded-md border border-border bg-muted/30\">\n <summary className=\"cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground\">\n Trace ({rows.length} span{rows.length === 1 ? \"\" : \"s\"}, {formatDuration(totalMs)})\n </summary>\n <ul className=\"flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]\">\n {rows.map((row, i) => {\n const leftPct = ((row.startTimeMs - minStartMs) / totalMs) * 100;\n const widthPct = Math.max((row.durationMs / totalMs) * 100, 0.5);\n return (\n <li key={`${row.spanId}-${i}`} className=\"flex items-center gap-2\">\n <span\n className=\"min-w-0 flex-1 truncate text-foreground\"\n style={{ paddingLeft: `${row.depth * 12}px` }}\n title={row.statusMessage ? `${row.name}: ${row.statusMessage}` : row.name}\n >\n {row.name}\n </span>\n <span className=\"relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40\">\n <span\n className={cn(\"absolute top-0 h-full rounded-sm\", BAR_COLOR[row.status])}\n style={{ left: `${leftPct}%`, width: `${widthPct}%` }}\n />\n </span>\n <span className=\"w-16 shrink-0 text-right text-muted-foreground\">\n {formatDuration(row.durationMs)}\n </span>\n </li>\n );\n })}\n </ul>\n </details>\n );\n}\n","/**\n * Pure span normalization + tree building for the OTel trace waterfall.\n * Ported from the formatters trace-view renderer so the React waterfall shows\n * the same structure. Side-effect-free for unit testing.\n */\n\nimport type { OtelSpan } from \"executable-stories-core/types/otel\";\n\nexport interface NormalizedSpan {\n spanId: string;\n parentSpanId?: string;\n name: string;\n startTimeMs: number;\n durationMs: number;\n status: \"ok\" | \"error\" | \"unset\";\n statusMessage?: string;\n}\n\nexport interface TraceRow extends NormalizedSpan {\n depth: number;\n}\n\nconst VALID = new Set([\"ok\", \"error\", \"unset\"]);\nconst safeStatus = (s: string): NormalizedSpan[\"status\"] => (VALID.has(s) ? (s as NormalizedSpan[\"status\"]) : \"unset\");\n\nexport function normalizeSpans(spans: readonly OtelSpan[]): NormalizedSpan[] {\n const out: NormalizedSpan[] = [];\n for (const span of spans) {\n if (!span || typeof span.spanId !== \"string\" || typeof span.name !== \"string\") continue;\n let startTimeMs: number;\n let durationMs: number;\n if (span.startTimeMs != null && span.durationMs != null) {\n startTimeMs = span.startTimeMs;\n durationMs = span.durationMs;\n } else if (span.startTimeUnixNano != null && span.endTimeUnixNano != null) {\n startTimeMs = span.startTimeUnixNano / 1e6;\n durationMs = (span.endTimeUnixNano - span.startTimeUnixNano) / 1e6;\n } else {\n continue;\n }\n durationMs = Math.max(0, durationMs);\n if (!isFinite(startTimeMs) || !isFinite(durationMs)) continue;\n out.push({\n spanId: span.spanId,\n parentSpanId: span.parentSpanId,\n name: span.name,\n startTimeMs,\n durationMs,\n status: safeStatus(span.status),\n statusMessage: span.statusMessage,\n });\n }\n return out;\n}\n\n/** Flatten spans into rows in tree order with a depth, parent before children. */\nexport function toTraceRows(spans: readonly OtelSpan[]): TraceRow[] {\n const normalized = normalizeSpans(spans);\n if (normalized.length === 0) return [];\n\n interface Node {\n span: NormalizedSpan;\n children: Node[];\n depth: number;\n }\n const byId = new Map<string, Node>();\n for (const span of normalized) {\n let key = span.spanId;\n let suffix = 2;\n while (byId.has(key)) key = `${span.spanId}__dup${suffix++}`;\n byId.set(key, { span: { ...span, spanId: key }, children: [], depth: 0 });\n }\n\n const roots: Node[] = [];\n for (const node of byId.values()) {\n const parent = node.span.parentSpanId ? byId.get(node.span.parentSpanId) : undefined;\n if (parent && parent !== node) parent.children.push(node);\n else roots.push(node);\n }\n for (const node of byId.values()) node.children.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);\n roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);\n\n const rows: TraceRow[] = [];\n const seen = new Set<string>();\n const walk = (node: Node, depth: number): void => {\n if (seen.has(node.span.spanId)) return;\n seen.add(node.span.spanId);\n rows.push({ ...node.span, depth });\n for (const child of node.children) walk(child, depth + 1);\n };\n for (const root of roots) walk(root, 0);\n // Orphans from cycles: promote to depth 0.\n for (const node of byId.values()) {\n if (!seen.has(node.span.spanId)) walk(node, 0);\n }\n return rows;\n}\n\nexport interface TraceWindow {\n minStartMs: number;\n totalMs: number;\n}\n\nexport function traceWindow(rows: readonly TraceRow[]): TraceWindow {\n let min = Infinity;\n let max = -Infinity;\n for (const r of rows) {\n min = Math.min(min, r.startTimeMs);\n max = Math.max(max, r.startTimeMs + r.durationMs);\n }\n const total = max - min;\n return { minStartMs: isFinite(min) ? min : 0, totalMs: total > 0 ? total : 1 };\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { ScenarioHistoryMap } from \"../lib/run-history\";\n\n/**\n * Provided only inside <ReportInteractive> when the CLI embedded a run\n * history (--history-file). When null (the static <Report/> render,\n * Storybook, Astro), scenario cards simply omit the history strip.\n */\nconst ScenarioHistoryContext = createContext<ScenarioHistoryMap | null>(null);\n\nexport const ScenarioHistoryProvider = ScenarioHistoryContext.Provider;\n\nexport function useScenarioHistory(): ScenarioHistoryMap | null {\n return useContext(ScenarioHistoryContext);\n}\n","export type ScenarioRunStatus = \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n\n/** One historical run of a scenario, oldest → newest in a history array. */\nexport interface ScenarioRunEvent {\n /** Epoch ms the run started. */\n timestamp: number;\n status: ScenarioRunStatus;\n runId?: string;\n durationMs?: number;\n commitSha?: string;\n branch?: string;\n}\n\n/** Recent run events keyed by ReportScenario.id. */\nexport type ScenarioHistoryMap = Record<string, ScenarioRunEvent[]>;\n\nexport interface RunStreak {\n status: ScenarioRunStatus;\n /** How many consecutive trailing runs share that status (≥1). */\n count: number;\n}\n\n/** The trailing same-status streak — \"passing for 5 runs\", \"failing for 2\". */\nexport function currentStreak(entries: readonly ScenarioRunEvent[]): RunStreak | undefined {\n const last = entries[entries.length - 1];\n if (!last) return undefined;\n let count = 0;\n for (let i = entries.length - 1; i >= 0 && entries[i]!.status === last.status; i--) count++;\n return { status: last.status, count };\n}\n\nconst STREAK_VERB: Record<ScenarioRunStatus, string> = {\n passed: \"Passing\",\n failed: \"Failing\",\n skipped: \"Skipped\",\n pending: \"Pending\",\n};\n\n/** Short human summary of a history window, used for the strip's tooltip. */\nexport function describeRunHistory(entries: readonly ScenarioRunEvent[]): string {\n const passed = entries.filter((e) => e.status === \"passed\").length;\n const base = `${passed}/${entries.length} runs passed`;\n const streak = currentStreak(entries);\n if (!streak || entries.length < 2) return base;\n return `${base} · ${STREAK_VERB[streak.status]} for the last ${streak.count === 1 ? \"run\" : `${streak.count} runs`}`;\n}\n\nexport type FlakinessLevel = \"stable\" | \"unstable\" | \"flaky\";\n\n/**\n * Below this many pass/fail samples a scenario is always \"stable\" — mirrors\n * MIN_FLAKINESS_SAMPLES in the formatters history module, which owns the\n * canonical thresholds. Keep the two in sync.\n */\nconst MIN_FLAKINESS_SAMPLES = 3;\n\n/**\n * Status-transition flakiness over a scenario's recent runs. Same\n * classification as the CLI history module (`calculateFlakiness`), ported so\n * the island stays self-sufficient on the embedded history JSON.\n */\nexport function flakinessOf(entries: readonly ScenarioRunEvent[]): FlakinessLevel {\n const countable = entries.filter((e) => e.status === \"passed\" || e.status === \"failed\");\n if (countable.length < MIN_FLAKINESS_SAMPLES) return \"stable\";\n\n let transitions = 0;\n for (let i = 1; i < countable.length; i++) {\n if (countable[i]!.status !== countable[i - 1]!.status) transitions++;\n }\n const transitionScore = transitions / (countable.length - 1);\n const failureRate = countable.filter((e) => e.status === \"failed\").length / countable.length;\n\n if (transitionScore > 0.5 || (transitionScore > 0.3 && failureRate > 0.2)) return \"flaky\";\n if (transitionScore > 0.2 || failureRate > 0.3) return \"unstable\";\n return \"stable\";\n}\n\nexport interface ScenarioRef {\n id: string;\n title: string;\n}\n\nexport interface LastRunDelta {\n /** Failed in this run, not failed in the previous one. */\n newlyFailing: ScenarioRef[];\n /** Passed in this run, failed in the previous one. */\n newlyPassing: ScenarioRef[];\n /** First appearance in the history window — no previous run to compare. */\n added: ScenarioRef[];\n}\n\n/**\n * What changed between the previous run and this one, for the report-header\n * strip. The history store appends the current run before the report is\n * generated, so each scenario's last entry IS this run and the entry before\n * it is the previous run. Returns undefined when no scenario has a previous\n * run to compare against (first run with history enabled).\n */\nexport function diffSinceLastRun(\n history: ScenarioHistoryMap,\n scenarios: readonly ScenarioRef[],\n): LastRunDelta | undefined {\n let hasPreviousRun = false;\n const delta: LastRunDelta = { newlyFailing: [], newlyPassing: [], added: [] };\n\n for (const scenario of scenarios) {\n const entries = history[scenario.id];\n if (!entries || entries.length === 0) continue;\n const last = entries[entries.length - 1]!;\n const prev = entries[entries.length - 2];\n if (!prev) {\n delta.added.push(scenario);\n continue;\n }\n hasPreviousRun = true;\n if (last.status === \"failed\" && prev.status !== \"failed\") delta.newlyFailing.push(scenario);\n else if (last.status === \"passed\" && prev.status === \"failed\") delta.newlyPassing.push(scenario);\n }\n\n return hasPreviousRun ? delta : undefined;\n}\n","import { useScenarioHistory } from \"../interactive/scenario-history-context\";\nimport { describeRunHistory, flakinessOf, type ScenarioRunEvent, type ScenarioRunStatus } from \"../lib/run-history\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { cn } from \"@/lib/utils\";\n\n/** How many trailing runs the strip shows; older entries stay in the tooltip count. */\nconst MAX_DOTS = 10;\n\nconst DOT_COLOR: Record<ScenarioRunStatus, string> = {\n passed: \"bg-pass\",\n failed: \"bg-fail\",\n skipped: \"bg-skip\",\n pending: \"bg-pend\",\n};\n\nfunction dotTitle(e: ScenarioRunEvent): string {\n const parts = [new Date(e.timestamp).toLocaleString(), e.status];\n if (e.commitSha) parts.push(e.commitSha.slice(0, 8));\n return parts.join(\" · \");\n}\n\n/**\n * Compact run-over-run timeline for one scenario: a dot per recent run,\n * oldest → newest. Renders nothing outside <ReportInteractive> or when the\n * report was generated without --history-file — history is presentation-layer\n * data and never part of the StoryReport contract.\n */\nexport function ScenarioRunHistory({ scenarioId }: { scenarioId: string }) {\n const history = useScenarioHistory();\n const entries = history?.[scenarioId];\n if (!entries || entries.length < 2) return null; // one run = no timeline yet\n\n const recent = entries.slice(-MAX_DOTS);\n // Judge flakiness on the same window the dots show, so the badge never\n // contradicts the strip next to it.\n const flaky = flakinessOf(recent) === \"flaky\";\n const summary = flaky ? `${describeRunHistory(recent)} · Flaky` : describeRunHistory(recent);\n\n return (\n <>\n {flaky ? (\n <Badge variant=\"pending\" aria-label=\"Flaky: status flips between recent runs\" title={summary}>\n Flaky\n </Badge>\n ) : null}\n <span\n role=\"img\"\n aria-label={`Run history: ${summary}`}\n title={summary}\n className=\"flex shrink-0 items-center gap-[3px]\"\n >\n {recent.map((e, i) => (\n <span\n key={`${e.timestamp}-${i}`}\n aria-hidden\n title={dotTitle(e)}\n className={cn(\n \"inline-block size-1.5 rounded-full\",\n DOT_COLOR[e.status],\n // The newest run (rightmost dot) is the one the card's status\n // badge already describes; ring it so the timeline reads as\n // \"…leading up to now\".\n i === recent.length - 1 && \"ring-1 ring-border ring-offset-1 ring-offset-card\",\n )}\n />\n ))}\n </span>\n </>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { formatRelativeAge, isReportStale } from \"../lib/provenance\";\nimport { useScenarioFreshness } from \"../interactive/scenario-freshness-context\";\nimport { Badge } from \"@/components/ui/badge\";\n\n/**\n * Per-scenario age signal.\n *\n * A report assembled from accumulated runs can be freshly rendered while some\n * of its scenarios last ran weeks ago. The report-level banner speaks for the\n * run, not for those scenarios, so without this the carried-over ones borrow a\n * freshness they have not earned.\n *\n * Only scenarios that are actually old say anything: a scenario that ran in\n * this run is the normal case and adds no badge. Age is computed on mount for\n * the same reason the report banner does it — static HTML is generated once and\n * read later, so an age baked in at build time would lie.\n */\nexport function ScenarioStaleness({ scenario }: { scenario: { lastRunAtMs?: number } }) {\n const freshness = useScenarioFreshness();\n const fixedNow = freshness?.nowMs;\n const [now, setNow] = useState<number | undefined>(fixedNow);\n\n useEffect(() => {\n if (fixedNow === undefined) setNow(Date.now());\n }, [fixedNow]);\n\n if (!freshness || now === undefined) return null;\n\n // No stamp means the report predates stamping, or came straight from one run.\n // Either way the report-level signal already speaks for it.\n const lastRunAtMs = scenario.lastRunAtMs;\n if (!lastRunAtMs || lastRunAtMs <= 0) return null;\n if (!isReportStale(lastRunAtMs, freshness.staleAfterDays, now)) return null;\n\n return (\n <Badge variant=\"outline\" aria-label=\"Scenario freshness\">\n Last ran {formatRelativeAge(lastRunAtMs, now)}\n </Badge>\n );\n}\n","import type { StoryReport } from \"executable-stories-core\";\n\ntype ReportCI = NonNullable<StoryReport[\"ci\"]>;\n\n/**\n * Epoch ms of the run the report documents — the staleness reference.\n * Prefers finishedAtMs; falls back to startedAtMs for reports from adapters\n * that only stamp a start time.\n */\nexport function reportLastRunMs(\n report: Pick<StoryReport, \"startedAtMs\" | \"finishedAtMs\">,\n): number | undefined {\n if (report.finishedAtMs && report.finishedAtMs > 0) return report.finishedAtMs;\n if (report.startedAtMs && report.startedAtMs > 0) return report.startedAtMs;\n return undefined;\n}\n\n/**\n * Epoch ms of the run that produced one scenario.\n *\n * A report assembled from accumulated runs holds scenarios that last ran at\n * different times, so the run-level timestamp overstates how fresh most of them\n * are. Falls back to the report for scenarios recorded before stamping, and for\n * reports rendered straight from a single run.\n */\nexport function scenarioLastRunMs(\n scenario: { lastRunAtMs?: number },\n report: Pick<StoryReport, \"startedAtMs\" | \"finishedAtMs\">,\n): number | undefined {\n if (scenario.lastRunAtMs && scenario.lastRunAtMs > 0) return scenario.lastRunAtMs;\n return reportLastRunMs(report);\n}\n\n/**\n * Human-readable age like \"just now\", \"5 minutes ago\", \"3 hours ago\",\n * \"12 days ago\". Clock skew (thenMs in the future) reads as \"just now\".\n */\nexport function formatRelativeAge(thenMs: number, nowMs: number): string {\n const deltaMs = Math.max(0, nowMs - thenMs);\n const minutes = Math.floor(deltaMs / 60_000);\n if (minutes < 1) return \"just now\";\n if (minutes < 60) return `${minutes} minute${minutes === 1 ? \"\" : \"s\"} ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours} hour${hours === 1 ? \"\" : \"s\"} ago`;\n const days = Math.floor(hours / 24);\n return `${days} day${days === 1 ? \"\" : \"s\"} ago`;\n}\n\n/**\n * A report is stale once its run is `staleAfterDays` or more days old.\n * A threshold of 0 (or negative) disables staleness entirely.\n */\nexport function isReportStale(\n lastRunMs: number | undefined,\n staleAfterDays: number,\n nowMs: number,\n): boolean {\n if (lastRunMs === undefined || staleAfterDays <= 0) return false;\n return nowMs - lastRunMs >= staleAfterDays * 86_400_000;\n}\n\n/**\n * StoryReport.ci.name carries the raw transport name — lowercase provider\n * keys (\"github\") from env detection, or a free-form string from older\n * adapters (\"GitHub Actions\"). Map the known keys to display names and pass\n * everything else through.\n */\nconst CI_DISPLAY_NAMES: Record<string, string> = {\n github: \"GitHub Actions\",\n gitlab: \"GitLab CI\",\n circleci: \"CircleCI\",\n jenkins: \"Jenkins\",\n azure: \"Azure DevOps\",\n buildkite: \"Buildkite\",\n travis: \"Travis CI\",\n ci: \"CI\",\n};\n\nexport function ciDisplayName(name: string): string {\n return CI_DISPLAY_NAMES[name] ?? name;\n}\n\n/**\n * Derive a browsable commit URL from the CI run URL, for the providers whose\n * URL structure makes that safe:\n * GitHub Actions …/owner/repo/actions/runs/123 -> …/owner/repo/commit/<sha>\n * GitLab CI …/group/project/-/pipelines/123 -> …/group/project/-/commit/<sha>\n * Other providers return undefined (a wrong link is worse than none).\n */\nexport function commitUrl(ci: ReportCI | undefined, sha: string | undefined): string | undefined {\n const commitSha = ci?.commitSha ?? sha;\n if (!ci?.url || !commitSha) return undefined;\n\n const github = ci.url.match(/^(https?:\\/\\/[^/]+\\/[^/]+\\/[^/]+)\\/actions\\/runs\\//);\n if (github) return `${github[1]}/commit/${commitSha}`;\n\n const gitlab = ci.url.match(/^(https?:\\/\\/.+)\\/-\\/pipelines\\//);\n if (gitlab) return `${gitlab[1]}/-/commit/${commitSha}`;\n\n return undefined;\n}\n\n/**\n * Derive a pull-request URL for GitHub-shaped CI run URLs. GitLab and the\n * rest return undefined for the same wrong-link-is-worse-than-none reason.\n */\nexport function prUrl(ci: ReportCI | undefined): string | undefined {\n if (!ci?.url || !ci.prNumber) return undefined;\n const github = ci.url.match(/^(https?:\\/\\/[^/]+\\/[^/]+\\/[^/]+)\\/actions\\/runs\\//);\n if (github) return `${github[1]}/pull/${ci.prNumber}`;\n return undefined;\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\n\nexport interface ScenarioFreshness {\n /** Days before a scenario counts as stale; 0 disables the signal. */\n staleAfterDays: number;\n /** The run being rendered, used for scenarios carrying no stamp of their own. */\n report: Pick<StoryReport, \"startedAtMs\" | \"finishedAtMs\">;\n /** Test seam: fixed \"now\". Left undefined, the badge reads the clock on mount. */\n nowMs?: number;\n}\n\n/**\n * Provided only where a report knows its staleness threshold. When null (a bare\n * <Report/> render, Storybook), scenario cards simply omit the age signal —\n * same shape as the run-history context.\n */\nconst ScenarioFreshnessContext = createContext<ScenarioFreshness | null>(null);\n\nexport const ScenarioFreshnessProvider = ScenarioFreshnessContext.Provider;\n\nexport function useScenarioFreshness(): ScenarioFreshness | null {\n return useContext(ScenarioFreshnessContext);\n}\n","\"use client\";\n\nimport { createContext, useCallback, useContext, useState } from \"react\";\n\nexport interface CollapseApi {\n isCollapsed: (id: string) => boolean;\n toggle: (id: string) => void;\n}\n\n/**\n * Provided only inside <ReportInteractive>. When null (the static <Report/>\n * render, Storybook, Astro), components render fully expanded with no toggle\n * affordance — so the static path and component-tier tests are unaffected.\n */\nconst CollapseContext = createContext<CollapseApi | null>(null);\n\nexport const CollapseProvider = CollapseContext.Provider;\n\nexport function useCollapse(): CollapseApi | null {\n return useContext(CollapseContext);\n}\n\nconst STORAGE_KEY = \"es-collapsed-ids\";\n\n/** Returns the persisted collapsed set, or null when the user has never set one\n * (so the caller can fall back to a data-driven default like failures-first). */\nfunction readPersisted(): Set<string> | null {\n if (typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n return raw ? new Set(JSON.parse(raw) as string[]) : null;\n } catch {\n return null;\n }\n}\n\nfunction persist(ids: Set<string>): void {\n if (typeof localStorage === \"undefined\") return;\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify([...ids]));\n } catch {\n /* quota / disabled — collapse still works for the session */\n }\n}\n\n/**\n * Collapse state for the interactive report: a persisted set of collapsed\n * feature/scenario ids, plus expand-all / collapse-all. `computeDefault` seeds\n * the initial set the FIRST time (nothing persisted yet) — the report uses it\n * to open failures and collapse the rest, so a broken run reveals what failed\n * without a click. Once the user toggles anything, their choice persists and\n * wins over the default.\n */\nexport function useCollapseState(computeDefault?: () => Set<string>) {\n const [collapsed, setCollapsed] = useState<Set<string>>(\n () => readPersisted() ?? computeDefault?.() ?? new Set<string>(),\n );\n\n const isCollapsed = useCallback((id: string) => collapsed.has(id), [collapsed]);\n\n const toggle = useCallback((id: string) => {\n setCollapsed((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n persist(next);\n return next;\n });\n }, []);\n\n const collapseAll = useCallback((ids: string[]) => {\n setCollapsed(() => {\n const next = new Set(ids);\n persist(next);\n return next;\n });\n }, []);\n\n const expandAll = useCallback(() => {\n setCollapsed(() => {\n const next = new Set<string>();\n persist(next);\n return next;\n });\n }, []);\n\n return { api: { isCollapsed, toggle } as CollapseApi, collapseAll, expandAll };\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { ReportScenario } from \"executable-stories-core\";\n// Deep import, NOT the package barrel: core's index pulls in Node-only modules\n// (attachment resolution reads the filesystem), which a browser bundler cannot\n// resolve. Types erase at compile time, so the type-only import above is safe;\n// this one is a value and must stay on the fs-free subpath.\nimport { scenarioToMarkdown as coreScenarioToMarkdown } from \"executable-stories-core/utils/scenario-markdown\";\n\nexport interface ScenarioActions {\n copyLink: (scenario: ReportScenario) => void;\n copyMarkdown: (scenario: ReportScenario) => void;\n copyPrompt: (scenario: ReportScenario) => void;\n}\n\n/**\n * Provided only inside <ReportInteractive>. When null (static render), scenarios\n * show no per-scenario action buttons.\n */\nconst ScenarioActionsContext = createContext<ScenarioActions | null>(null);\nexport const ScenarioActionsProvider = ScenarioActionsContext.Provider;\nexport function useScenarioActions(): ScenarioActions | null {\n return useContext(ScenarioActionsContext);\n}\n\n/**\n * A scenario rendered as Markdown — for pasting into PRs / issues / docs.\n *\n * Delegates to the shared serializer in core (`variant: \"compact\"`), the same\n * one behind the Astro site's `<slug>.md` twin endpoints, so what you copy here\n * and what an agent fetches there can never drift.\n */\nexport function scenarioToMarkdown(scenario: ReportScenario): string {\n return coreScenarioToMarkdown(scenario, { variant: \"compact\" });\n}\n\n/**\n * A failed scenario rendered as an investigation prompt for an AI agent — the\n * \"cheap to verify\" loop: hand the agent the failing behaviour + error verbatim.\n */\nexport function scenarioToPrompt(scenario: ReportScenario): string {\n const lines: string[] = [\n `A test scenario is ${scenario.status}. Investigate the likely cause and propose a fix.`,\n \"\",\n `Scenario: ${scenario.title}`,\n \"Steps:\",\n ];\n for (const step of scenario.steps) {\n const mark = step.status === \"failed\" ? \" ⟵ failed here\" : \"\";\n lines.push(` ${step.keyword} ${step.text}${mark}`);\n }\n if (scenario.errorMessage) {\n lines.push(\"\", \"Error:\", scenario.errorMessage.trim());\n }\n if (scenario.errorStack) {\n lines.push(\"\", \"Stack:\", scenario.errorStack.trim());\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Every failure in the run as ONE prompt. A red run is rarely one broken thing,\n * and copying scenarios one at a time loses the shape of the breakage — the\n * agent that sees all three at once can spot the shared cause.\n */\nexport function failuresToPrompt(scenarios: readonly ReportScenario[]): string {\n if (scenarios.length === 0) return \"\";\n const noun = scenarios.length === 1 ? \"test scenario is\" : \"test scenarios are\";\n const lines: string[] = [\n `${scenarios.length} ${noun} failing. Investigate the likely cause (they may share one) and propose a fix.`,\n ];\n scenarios.forEach((scenario, i) => {\n lines.push(\"\", `${i + 1}. ${scenario.title}`, \"Steps:\");\n for (const step of scenario.steps) {\n const mark = step.status === \"failed\" ? \" ⟵ failed here\" : \"\";\n lines.push(` ${step.keyword} ${step.text}${mark}`);\n }\n if (scenario.errorMessage) {\n lines.push(\"Error:\", scenario.errorMessage.trim());\n }\n });\n return lines.join(\"\\n\");\n}\n\n/** Absolute permalink to a scenario in the current document. */\nexport function scenarioPermalink(scenario: ReportScenario): string {\n if (typeof location === \"undefined\") return `#${scenario.id}`;\n return `${location.href.split(\"#\")[0]}#${scenario.id}`;\n}\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6 [.border-t]:pt-6\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\nimport { CheckIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst itemClasses =\n \"relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg:not([class*='text-'])]:text-muted-foreground\"\n\nfunction DropdownMenu(props: React.ComponentProps<typeof MenuPrimitive.Root>) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuTrigger(\n props: React.ComponentProps<typeof MenuPrimitive.Trigger>,\n) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n className,\n align = \"end\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.Popup> & {\n align?: MenuPrimitive.Positioner.Props[\"align\"]\n sideOffset?: MenuPrimitive.Positioner.Props[\"sideOffset\"]\n}) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner\n data-slot=\"dropdown-menu-positioner\"\n className=\"z-50\"\n align={align}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\n \"z-50 min-w-[11rem] origin-[var(--transform-origin)] overflow-hidden rounded-md border border-border bg-popover p-1 font-sans text-sm text-popover-foreground shadow-md transition-[opacity,transform] data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\n className,\n )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuItem({\n className,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.Item>) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n className={cn(itemClasses, className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuLabel({\n className,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.GroupLabel>) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n className={cn(\"px-2 py-1.5 text-xs font-medium text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\n// Base UI's Menu has no Separator part; a plain divider row is equivalent.\nfunction DropdownMenuSeparator({ className }: { className?: string }) {\n return <div role=\"separator\" className={cn(\"-mx-1 my-1 h-px bg-border\", className)} />\n}\n\nfunction DropdownMenuRadioGroup(\n props: React.ComponentProps<typeof MenuPrimitive.RadioGroup>,\n) {\n return <MenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.RadioItem>) {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(itemClasses, \"pl-8\", className)}\n {...props}\n >\n <span className=\"absolute left-2 flex size-3.5 items-center justify-center\">\n <MenuPrimitive.RadioItemIndicator>\n <CheckIcon className=\"size-4 text-foreground\" />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.CheckboxItem>) {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(itemClasses, \"pl-8\", className)}\n {...props}\n >\n <span className=\"absolute left-2 flex size-3.5 items-center justify-center\">\n <MenuPrimitive.CheckboxItemIndicator>\n <CheckIcon className=\"size-4\" />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuCheckboxItem,\n}\n","import type { ReportFeature } from \"executable-stories-core\";\nimport { ReportScenario } from \"./ReportScenario\";\n\nexport interface ReportScenarioListProps {\n feature: ReportFeature;\n}\n\nexport function ReportScenarioList({ feature }: ReportScenarioListProps) {\n return (\n <>\n {feature.scenarios.map((scenario) => (\n <ReportScenario key={scenario.id} scenario={scenario} />\n ))}\n </>\n );\n}\n","import type { ReportFeature } from \"executable-stories-core\";\nimport { dedent, safeMarkdownHtml } from \"../lib/markdown\";\n\nexport interface ReportFeatureIntroProps {\n feature: ReportFeature;\n}\n\n/**\n * What the feature is for, ahead of the scenarios that prove it.\n *\n * Scenarios answer \"what does it do\". A reader arriving cold needs \"why does\n * this exist and who is it for\" first, which is what `story.feature(...)`\n * records. Renders nothing when a file never declared one, so existing reports\n * look exactly as they did.\n */\nexport function ReportFeatureIntro({ feature }: ReportFeatureIntroProps) {\n const hasNarrative = Boolean(feature.narrative?.trim());\n const hasGlossary = Boolean(feature.glossary?.length);\n if (!hasNarrative && !hasGlossary) return null;\n\n return (\n <div className=\"flex flex-col gap-3 border-l-2 border-border pl-4 text-sm\">\n {hasNarrative ? (\n <div\n className=\"es-doc-prose prose prose-sm max-w-none text-muted-foreground\"\n dangerouslySetInnerHTML={{ __html: safeMarkdownHtml(dedent(feature.narrative!)) }}\n />\n ) : null}\n\n {hasGlossary ? (\n <dl className=\"grid gap-1.5\" aria-label=\"Glossary\">\n {feature.glossary!.map((entry) => (\n <div key={entry.term} className=\"flex flex-wrap gap-x-2 text-xs\">\n <dt className=\"font-medium text-foreground\">{entry.term}</dt>\n <dd className=\"flex-1 text-muted-foreground\">{entry.definition}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n </div>\n );\n}\n\n/**\n * Label the feature the way it was declared.\n *\n * An ability reads as something a person can now do; a business need covers the\n * cross-cutting concerns nobody asks for by name, like security or performance.\n * Naming the kind keeps that distinction visible to a reader who never sees the\n * test code. A derived title gets no badge, since nobody claimed anything.\n */\nexport function featureKindLabel(kind: ReportFeature[\"kind\"]): string | null {\n if (kind === \"ability\") return \"Ability\";\n if (kind === \"business-need\") return \"Business need\";\n if (kind === \"feature\") return \"Feature\";\n return null;\n}\n","import type { ReportFeature as ReportFeatureT } from \"executable-stories-core\";\nimport { ReportScenarioList } from \"./ReportScenarioList\";\nimport { ReportFeatureIntro, featureKindLabel } from \"./ReportFeatureIntro\";\nimport { useCollapse } from \"../interactive/collapse-context\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportFeatureProps {\n feature: ReportFeatureT;\n}\n\n/**\n * Feature group — the report's `.feature` card: a header bar with the feature\n * title + mono source path and ✓/✗/○ status counts on the right, over a stack\n * of scenario cards. Kept a semantic <section> (a region), not a shadcn Card\n * div, so it stays a landmark and doesn't collide with the scenario cards'\n * `[data-slot=\"card\"]`.\n */\nexport function ReportFeature({ feature }: ReportFeatureProps) {\n const titleId = `${feature.id}-title`;\n const bodyId = `${feature.id}-body`;\n const s = feature.summary;\n const skipped = s.skipped + s.pending;\n const collapse = useCollapse();\n const collapsed = collapse?.isCollapsed(feature.id) ?? false;\n const kindLabel = featureKindLabel(feature.kind);\n return (\n // Suite = a section heading + a divider, NOT another bordered card. Drops a\n // layer of nesting so the scenario cards below read as the primary unit.\n <section\n id={feature.id}\n data-slot=\"feature\"\n aria-labelledby={titleId}\n className=\"flex flex-col gap-3\"\n >\n <div className=\"flex items-end justify-between gap-4 border-b border-border pb-2\">\n <div className=\"min-w-0\">\n {/* The heading itself is the toggle — a wide, obvious hit area rather\n than a lone caret. Kept inside <h2> so it stays a landmark. */}\n <h2 id={titleId} className=\"text-base font-semibold tracking-tight text-foreground\">\n {collapse ? (\n <button\n type=\"button\"\n onClick={() => collapse.toggle(feature.id)}\n aria-expanded={!collapsed}\n aria-controls={bodyId}\n className=\"flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80\"\n >\n <span aria-hidden className={cn(\"shrink-0 text-xs text-muted-foreground transition-transform\", !collapsed && \"rotate-90\")}>▸</span>\n <span className=\"truncate\">{feature.title}</span>\n </button>\n ) : (\n feature.title\n )}\n </h2>\n <p className={cn(\"mt-0.5 flex items-center gap-2 text-xs text-muted-foreground\", collapse && \"pl-5\")}>\n {kindLabel ? (\n <span className=\"shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-medium text-foreground\">\n {kindLabel}\n </span>\n ) : null}\n <span className=\"truncate font-mono\">{feature.sourceFile}</span>\n </p>\n </div>\n {/* Readable, failure-weighted counts — only the failure count carries\n colour, so a broken suite reads at a glance without a colour salad. */}\n <p\n className=\"flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground\"\n aria-label={`${s.passed} passed, ${s.failed} failed, ${skipped} skipped`}\n >\n <span>{s.passed} passed</span>\n <span aria-hidden>·</span>\n <span className={cn(s.failed > 0 && \"font-medium text-fail\")}>{s.failed} failed</span>\n {skipped > 0 ? (\n <>\n <span aria-hidden>·</span>\n <span>{skipped} skipped</span>\n </>\n ) : null}\n </p>\n </div>\n <div id={bodyId} hidden={collapsed} className=\"flex flex-col gap-3\">\n <ReportFeatureIntro feature={feature} />\n <ReportScenarioList feature={feature} />\n </div>\n </section>\n );\n}\n","import { useReport } from \"../hooks/useReport\";\nimport { ReportFeature } from \"./ReportFeature\";\n\nexport function ReportFeatureList() {\n const report = useReport();\n // Roomy gap between features — they're now divider-led sections rather than\n // self-contained cards, so they need clear air to read as separate suites.\n return (\n <div className=\"flex flex-col gap-8\">\n {report.features.map((feature) => (\n <ReportFeature key={feature.id} feature={feature} />\n ))}\n </div>\n );\n}\n","import { formatDuration } from \"executable-stories-core/utils/duration\";\nimport { slowestScenarios } from \"executable-stories-core/report-queries\";\nimport { useReport } from \"../hooks/useReport\";\nimport { ciDisplayName, commitUrl, prUrl } from \"../lib/provenance\";\n\n/**\n * Run metadata line (started, duration, version, branch, git SHA, CI, PR) —\n * the React equivalent of the report's `.meta-info` block. Reads the top-level\n * StoryReport fields from context. Commit and PR become links when the CI run\n * URL lets us derive them safely (GitHub/GitLab shapes only).\n */\nexport function ReportMeta() {\n const report = useReport();\n\n const items: Array<{ label: string; value: React.ReactNode }> = [];\n const linkClass = \"text-primary underline underline-offset-2\";\n\n if (report.startedAtMs) {\n items.push({ label: \"Started\", value: new Date(report.startedAtMs).toLocaleString() });\n }\n if (report.durationMs) {\n items.push({ label: \"Duration\", value: formatDuration(report.durationMs) });\n }\n if (report.packageVersion) {\n items.push({ label: \"Version\", value: report.packageVersion });\n }\n if (report.ci?.branch) {\n items.push({ label: \"Branch\", value: report.ci.branch });\n }\n const sha = report.ci?.commitSha ?? report.gitSha;\n if (sha) {\n const url = commitUrl(report.ci, report.gitSha);\n const short = sha.slice(0, 8);\n items.push({\n label: \"Commit\",\n value: url ? (\n <a href={url} target=\"_blank\" rel=\"noreferrer noopener\" className={linkClass}>\n {short}\n </a>\n ) : (\n short\n ),\n });\n }\n if (report.ci) {\n items.push({\n label: \"CI\",\n value: report.ci.url ? (\n <a href={report.ci.url} target=\"_blank\" rel=\"noreferrer noopener\" className={linkClass}>\n {ciDisplayName(report.ci.name)}\n {report.ci.buildNumber ? ` #${report.ci.buildNumber}` : \"\"}\n </a>\n ) : (\n `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : \"\"}`\n ),\n });\n }\n if (report.ci?.prNumber) {\n const url = prUrl(report.ci);\n const label = `#${report.ci.prNumber}`;\n items.push({\n label: \"PR\",\n value: url ? (\n <a href={url} target=\"_blank\" rel=\"noreferrer noopener\" className={linkClass}>\n {label}\n </a>\n ) : (\n label\n ),\n });\n }\n\n // A \"slowest\" list needs a field to rank: below a handful of timed scenarios\n // it just repeats the run in a different order.\n const slowest = slowestScenarios(report, 5);\n const showSlowest = slowest.length >= 3;\n\n if (items.length === 0 && !showSlowest) return null;\n\n return (\n // Run metadata is useful but secondary to \"what failed\" — tuck it into a\n // collapsed disclosure so it doesn't push the result down. Native <details>\n // so it works with no JS (the SSR/no-hydration report still toggles).\n <details data-es-meta-card className=\"es-run-details group rounded-lg border border-border bg-card text-xs\">\n <summary className=\"flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <span aria-hidden className=\"text-xs transition-transform group-open:rotate-90\">▸</span>\n Run details\n </summary>\n <dl className=\"flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground\" aria-label=\"Run metadata\">\n {items.map((item) => (\n <div key={item.label} className=\"flex items-baseline gap-1.5\">\n <dt className=\"font-medium\">{item.label}</dt>\n <dd className=\"font-mono text-foreground\">{item.value}</dd>\n </div>\n ))}\n </dl>\n {showSlowest ? (\n <div className=\"border-t border-border px-4 py-3\">\n <div className=\"mb-1.5 font-medium text-muted-foreground\">Slowest scenarios</div>\n <ol className=\"flex flex-col gap-1\" aria-label=\"Slowest scenarios\">\n {slowest.map((s) => (\n <li key={s.id} className=\"flex items-baseline justify-between gap-4\">\n <a href={`#${s.id}`} className=\"min-w-0 text-primary underline underline-offset-2\">\n {s.title}\n </a>\n <span className=\"shrink-0 font-mono tabular-nums text-muted-foreground\">\n {formatDuration(s.durationMs)}\n </span>\n </li>\n ))}\n </ol>\n </div>\n ) : null}\n </details>\n );\n}\n","import type { ReportSummary as ReportSummaryT } from \"executable-stories-core\";\nimport { useReport } from \"../hooks/useReport\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportSummaryProps {\n className?: string;\n}\n\nexport function ReportSummary({ className }: ReportSummaryProps) {\n const report = useReport();\n return (\n <ReportSummaryView\n summary={report.summary}\n {...(className !== undefined && { className })}\n ariaLabel=\"Run summary\"\n />\n );\n}\n\nexport interface ReportSummaryViewProps {\n summary: ReportSummaryT;\n className?: string;\n ariaLabel?: string;\n}\n\n/**\n * A single stat card. All cards share the neutral card surface; the status\n * *number* carries the colour (`--es-pass/fail/skip/pend`, mapped to Tailwind\n * in tailwind.css) and a matching leading dot. This drops the earlier pastel\n * fills for the flatter, dashboard-style KPI treatment — a mono micro-label\n * above an oversized tabular number.\n */\nconst TONE = {\n total: { num: \"text-foreground\", dot: \"bg-muted-foreground/50\" },\n passed: { num: \"text-pass\", dot: \"bg-pass\" },\n failed: { num: \"text-fail\", dot: \"bg-fail\" },\n skipped: { num: \"text-skip\", dot: \"bg-skip\" },\n pending: { num: \"text-pend\", dot: \"bg-pend\" },\n} as const;\n\nexport function ReportSummaryView({ summary, className, ariaLabel }: ReportSummaryViewProps) {\n const cards: Array<{ status: keyof typeof TONE; label: string; value: number }> = [\n { status: \"total\", label: \"Total\", value: summary.total },\n { status: \"passed\", label: \"Passed\", value: summary.passed },\n { status: \"failed\", label: \"Failed\", value: summary.failed },\n { status: \"skipped\", label: \"Skipped\", value: summary.skipped },\n ];\n if (summary.pending > 0) {\n cards.push({ status: \"pending\", label: \"Pending\", value: summary.pending });\n }\n return (\n <dl\n className={cn(\n \"grid grid-cols-2 gap-3\",\n // Columns follow the card count so the row is always full — 5 statuses\n // (pending present) never leave a lone orphan card below a row of four.\n cards.length === 5 ? \"sm:grid-cols-5\" : \"sm:grid-cols-4\",\n className,\n )}\n aria-label={ariaLabel}\n >\n {cards.map((c) => {\n const tone = TONE[c.status];\n return (\n <div\n key={c.status}\n data-status={c.status}\n className=\"rounded-lg border bg-card px-4 py-3\"\n >\n <dt className=\"flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground\">\n <span className={cn(\"size-1.5 shrink-0 rounded-full\", tone.dot)} aria-hidden=\"true\" />\n {c.label}\n </dt>\n <dd className={cn(\"mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums\", tone.num)}>\n {c.value}\n </dd>\n </div>\n );\n })}\n </dl>\n );\n}\n","import type { ReportParseError } from \"../result\";\n\nexport interface ReportSchemaErrorProps {\n error: ReportParseError;\n}\n\nexport function ReportSchemaError({ error }: ReportSchemaErrorProps) {\n return (\n <section className=\"es-schema-error\" role=\"alert\" aria-live=\"assertive\">\n <p>\n <strong>Report could not be displayed.</strong>\n </p>\n <p>{error.message}</p>\n {error.code === \"SCHEMA_VERSION_MISMATCH\" ? (\n <p>\n The report bundle is newer than this version of <code>executable-stories-react</code>.\n Upgrade the package, or regenerate the report with an older formatters CLI.\n </p>\n ) : null}\n {error.issues && error.issues.length > 0 ? (\n <details>\n <summary>{error.issues.length} validation issue{error.issues.length === 1 ? \"\" : \"s\"}</summary>\n <pre>\n {error.issues\n .slice(0, 20)\n .map((i) => `${i.path}: ${i.message}`)\n .join(\"\\n\")}\n </pre>\n </details>\n ) : null}\n </section>\n );\n}\n","import type { ReactNode } from \"react\";\nimport type { ReportParseError } from \"../result\";\nimport { cn } from \"../lib/utils\";\nimport { ReportSummary } from \"./ReportSummary\";\nimport { ReportMeta } from \"./ReportMeta\";\nimport { ReportSchemaError } from \"./ReportSchemaError\";\n\n/**\n * The report's title block — `<h1>` + summary + meta. Shared by the static\n * `Report` header and the interactive `ReportInteractive` header so the two\n * views can't drift on the no-JS fallback.\n */\nexport function ReportTitleBlock({ title }: { title?: string }) {\n return (\n <>\n <h1>{title ?? \"Story Report\"}</h1>\n <ReportSummary />\n <ReportMeta />\n </>\n );\n}\n\n/**\n * The `<main>` landmark shown when the report failed to parse. Both entrypoints\n * render the identical shell on a `Result` error, so it lives here once.\n */\nexport function ReportErrorShell({\n error,\n className,\n title,\n dataTheme,\n}: {\n error: ReportParseError;\n className?: string;\n title?: string;\n dataTheme?: \"light\" | \"dark\";\n}): ReactNode {\n return (\n <main className={cn(\"es-report\", className)} aria-label={title ?? \"Test report\"} data-theme={dataTheme}>\n <ReportSchemaError error={error} />\n </main>\n );\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Switch as SwitchPrimitive } from \"@base-ui/react/switch\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Official shadcn Switch, ported to Base UI's Switch primitive (Radix's\n// `data-[state=checked]` becomes Base UI's `data-[checked]`/`data-[unchecked]`).\n// Same porting pattern as checkbox.tsx / toggle-group.tsx across ui/.\nfunction Switch({\n className,\n ...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n className={cn(\n \"peer inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[checked]:bg-primary data-[unchecked]:bg-input\",\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className=\"pointer-events-none block size-4 rounded-full bg-background ring-0 transition-transform data-[checked]:translate-x-[calc(100%-2px)] data-[unchecked]:translate-x-0\"\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { ToggleGroup as ToggleGroupPrimitive } from \"@base-ui/react/toggle-group\"\nimport { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Segmented control on Base UI's ToggleGroup: a muted rounded track holding\n// toggle \"pills\". The active item lifts to a `bg-background` surface with a\n// subtle shadow (the shadcn Tabs look). Base UI's group holds an array value and\n// its items are `Toggle` primitives (there is no `ToggleGroup.Item`), so\n// ToggleGroupItem wraps Toggle. Radix's `data-[state=on]` is Base UI's\n// `data-[pressed]`.\nconst toggleItemVariants = cva(\n \"inline-flex items-center justify-center gap-1.5 rounded-md font-medium whitespace-nowrap text-muted-foreground transition-[color,background-color,box-shadow] outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-background data-[pressed]:text-foreground data-[pressed]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n size: {\n default: \"h-9 px-3 text-sm\",\n sm: \"h-8 px-2.5 text-[0.82rem]\",\n },\n },\n defaultVariants: { size: \"default\" },\n },\n)\n\nconst ToggleGroupContext = React.createContext<VariantProps<typeof toggleItemVariants>>({\n size: \"default\",\n})\n\nfunction ToggleGroup({\n className,\n size,\n children,\n ...props\n}: ToggleGroupPrimitive.Props & VariantProps<typeof toggleItemVariants>) {\n return (\n <ToggleGroupPrimitive\n data-slot=\"toggle-group\"\n className={cn(\"flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5\", className)}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ size }}>{children}</ToggleGroupContext.Provider>\n </ToggleGroupPrimitive>\n )\n}\n\nfunction ToggleGroupItem({\n className,\n children,\n size,\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleItemVariants>) {\n const context = React.useContext(ToggleGroupContext)\n return (\n <TogglePrimitive\n data-slot=\"toggle-group-item\"\n className={cn(toggleItemVariants({ size: context.size ?? size }), \"flex-1 shrink-0\", className)}\n {...props}\n >\n {children}\n </TogglePrimitive>\n )\n}\n\nexport { ToggleGroup, ToggleGroupItem }\n","import { useMemo, type ReactNode } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\nimport type { BuiltinRenderers, CustomRenderers } from \"../renderers\";\nimport { ReportContext, type ReportContextValue } from \"./ReportContext\";\nimport { narrativeBlockRenderers } from \"../components/doc/NarrativeBlocks\";\n\nexport interface ReportRootProps {\n report: StoryReport;\n customRenderers?: CustomRenderers;\n renderers?: BuiltinRenderers;\n children: ReactNode;\n}\n\nconst EMPTY_RENDERERS: BuiltinRenderers = {};\n\nexport function ReportRoot({\n report,\n customRenderers,\n renderers,\n children,\n}: ReportRootProps) {\n const value = useMemo<ReportContextValue>(\n () => ({\n report,\n // Narrative blocks render everywhere the report does (static SSR, the\n // island, Astro) without every host wiring them up. A host renderer for\n // the same type still wins.\n customRenderers: { ...narrativeBlockRenderers, ...customRenderers },\n renderers: renderers ?? EMPTY_RENDERERS,\n }),\n [report, customRenderers, renderers],\n );\n return <ReportContext.Provider value={value}>{children}</ReportContext.Provider>;\n}\n","/**\n * Renderers for the two narrative block types an agent reaches for when it\n * explains a change: a file map and a data shape.\n *\n * They ride on `story.custom({ type, data })`, so every adapter can already\n * emit them with no API change; only the renderer is new. Register them with\n * `customRenderers` (the standalone report island does this by default).\n *\n * These blocks describe, they do not prove. Nothing here executed, so a block\n * whose `data.authored` says an agent wrote it renders a visible marker. A\n * picture that looks as trustworthy as a passing test, without being one, is\n * the failure mode this whole report exists to avoid.\n */\n\nimport type { ReportDocCustom } from \"executable-stories-core\";\nimport { Badge } from \"../ui/badge\";\nimport { cn } from \"../../lib/utils\";\n\nexport const FILE_TREE_TYPE = \"file-tree\";\nexport const DATA_MODEL_TYPE = \"data-model\";\n\n/** Change annotation shared by both blocks. */\ntype ChangeKind = \"added\" | \"modified\" | \"removed\" | \"renamed\";\n\nfunction isChangeKind(value: unknown): value is ChangeKind {\n return value === \"added\" || value === \"modified\" || value === \"removed\" || value === \"renamed\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\n/**\n * \"Written by an agent, not verified by a run.\" Only rendered when the author\n * says so; there is no way to detect it after the fact, which is exactly why\n * the authoring skills are told to set it.\n */\nfunction AuthoredMarker({ authored }: { authored?: string }) {\n if (authored !== \"agent\") return null;\n return (\n <Badge variant=\"outline\" className=\"border-border text-[10px] text-muted-foreground\">\n AI-authored, not verified by a run\n </Badge>\n );\n}\n\nfunction BlockFrame({\n title,\n authored,\n children,\n}: {\n title?: string;\n authored?: string;\n children: React.ReactNode;\n}) {\n return (\n <figure className=\"my-3\">\n {title || authored === \"agent\" ? (\n <figcaption className=\"mb-1.5 flex flex-wrap items-center gap-2\">\n {title ? <span className=\"text-xs font-medium text-muted-foreground\">{title}</span> : null}\n <AuthoredMarker authored={authored} />\n </figcaption>\n ) : null}\n {children}\n </figure>\n );\n}\n\n/**\n * Deliberately uncoloured. In this report colour carries test status, so a\n * green \"added\" badge beside a failing scenario would read as a pass. The word\n * does the work.\n */\nfunction ChangeBadge({ change }: { change: ChangeKind }) {\n return (\n <Badge variant=\"tag\" className=\"text-[10px]\">\n {change}\n </Badge>\n );\n}\n\n// ---------------------------------------------------------------------------\n// file-tree\n// ---------------------------------------------------------------------------\n\ninterface FileEntry {\n path: string;\n change?: ChangeKind;\n note?: string;\n}\n\nexport interface FileTreeData {\n title?: string;\n authored?: string;\n files: FileEntry[];\n}\n\nexport function parseFileTree(data: unknown): FileTreeData | undefined {\n if (!isRecord(data) || !Array.isArray(data.files)) return undefined;\n const files: FileEntry[] = [];\n for (const raw of data.files) {\n // A bare string is a path; anything without one is not a file.\n if (typeof raw === \"string\") {\n if (raw) files.push({ path: raw });\n continue;\n }\n if (!isRecord(raw)) continue;\n const path = str(raw.path);\n if (!path) continue;\n files.push({\n path,\n change: isChangeKind(raw.change) ? raw.change : undefined,\n note: str(raw.note),\n });\n }\n if (files.length === 0) return undefined;\n return { title: str(data.title), authored: str(data.authored), files };\n}\n\ninterface TreeNode {\n name: string;\n children: Map<string, TreeNode>;\n file?: FileEntry;\n}\n\n/** Flat paths in, nested directories out. Sorting puts folders before files. */\nfunction buildTree(files: FileEntry[]): TreeNode {\n const root: TreeNode = { name: \"\", children: new Map() };\n for (const file of files) {\n const segments = file.path.split(\"/\").filter(Boolean);\n let node = root;\n segments.forEach((segment, index) => {\n let child = node.children.get(segment);\n if (!child) {\n child = { name: segment, children: new Map() };\n node.children.set(segment, child);\n }\n if (index === segments.length - 1) child.file = file;\n node = child;\n });\n }\n return root;\n}\n\nfunction sortedChildren(node: TreeNode): TreeNode[] {\n return [...node.children.values()].sort((a, b) => {\n const aDir = a.children.size > 0;\n const bDir = b.children.size > 0;\n if (aDir !== bDir) return aDir ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n}\n\nfunction TreeBranch({ node, depth }: { node: TreeNode; depth: number }) {\n const children = sortedChildren(node);\n return (\n <ul className={cn(\"space-y-0.5\", depth > 0 && \"ml-3 border-l border-border/60 pl-3\")}>\n {children.map((child) => {\n const isDir = child.children.size > 0;\n return (\n <li key={child.name}>\n <div className=\"flex flex-wrap items-baseline gap-2\">\n <span\n className={cn(\n \"font-mono text-xs\",\n isDir ? \"text-muted-foreground\" : \"text-foreground\",\n )}\n >\n {isDir ? `${child.name}/` : child.name}\n </span>\n {child.file?.change ? <ChangeBadge change={child.file.change} /> : null}\n {child.file?.note ? (\n <span className=\"text-xs text-muted-foreground\">{child.file.note}</span>\n ) : null}\n </div>\n {isDir ? <TreeBranch node={child} depth={depth + 1} /> : null}\n </li>\n );\n })}\n </ul>\n );\n}\n\nexport function FileTreeBlock({ entry }: { entry: ReportDocCustom }) {\n const data = parseFileTree(entry.data);\n if (!data) return <UnreadableBlock entry={entry} />;\n return (\n <BlockFrame title={data.title ?? \"Files changed\"} authored={data.authored}>\n <div tabIndex={0} className=\"overflow-x-auto rounded-md border border-border bg-card p-3\">\n <TreeBranch node={buildTree(data.files)} depth={0} />\n </div>\n </BlockFrame>\n );\n}\n\n// ---------------------------------------------------------------------------\n// data-model\n// ---------------------------------------------------------------------------\n\ninterface ModelField {\n name: string;\n type?: string;\n note?: string;\n change?: ChangeKind;\n}\n\nexport interface DataModelData {\n title?: string;\n authored?: string;\n name?: string;\n fields: ModelField[];\n}\n\nexport function parseDataModel(data: unknown): DataModelData | undefined {\n if (!isRecord(data) || !Array.isArray(data.fields)) return undefined;\n const fields: ModelField[] = [];\n for (const raw of data.fields) {\n if (!isRecord(raw)) continue;\n const name = str(raw.name);\n if (!name) continue;\n fields.push({\n name,\n type: str(raw.type),\n note: str(raw.note),\n change: isChangeKind(raw.change) ? raw.change : undefined,\n });\n }\n if (fields.length === 0) return undefined;\n return {\n title: str(data.title),\n authored: str(data.authored),\n name: str(data.name),\n fields,\n };\n}\n\nexport function DataModelBlock({ entry }: { entry: ReportDocCustom }) {\n const data = parseDataModel(entry.data);\n if (!data) return <UnreadableBlock entry={entry} />;\n const hasNotes = data.fields.some((f) => f.note);\n return (\n <BlockFrame title={data.title ?? data.name ?? \"Data model\"} authored={data.authored}>\n <div tabIndex={0} className=\"overflow-x-auto rounded-md border border-border\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"bg-muted/50\">\n <th scope=\"col\" className=\"border-b border-border px-3 py-2 text-left font-semibold\">\n Field\n </th>\n <th scope=\"col\" className=\"border-b border-border px-3 py-2 text-left font-semibold\">\n Type\n </th>\n {hasNotes ? (\n <th scope=\"col\" className=\"border-b border-border px-3 py-2 text-left font-semibold\">\n Note\n </th>\n ) : null}\n </tr>\n </thead>\n <tbody>\n {data.fields.map((field) => (\n <tr key={field.name}>\n <td className=\"border-b border-border px-3 py-2\">\n <span className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-mono text-xs text-foreground\">{field.name}</span>\n {field.change ? <ChangeBadge change={field.change} /> : null}\n </span>\n </td>\n <td className=\"border-b border-border px-3 py-2 font-mono text-xs text-muted-foreground\">\n {field.type ?? \"\"}\n </td>\n {hasNotes ? (\n <td className=\"border-b border-border px-3 py-2 text-foreground\">\n {field.note ?? \"\"}\n </td>\n ) : null}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </BlockFrame>\n );\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Shape we could not read. Show the raw data rather than nothing: a malformed\n * block is a bug in whatever wrote it, and hiding it hides the bug.\n */\nfunction UnreadableBlock({ entry }: { entry: ReportDocCustom }) {\n return (\n <div className=\"my-2\" data-type={entry.type}>\n <p className=\"mb-1 text-xs font-medium text-muted-foreground\">\n {entry.type} (unrecognised shape)\n </p>\n <pre\n tabIndex={0}\n className=\"overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground\"\n >\n {safeStringify(entry.data)}\n </pre>\n </div>\n );\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\n/**\n * The narrative block renderers, ready to spread into `customRenderers`.\n * Consumer-supplied renderers for the same type win, so a project can swap\n * either one out.\n */\nexport const narrativeBlockRenderers = {\n [FILE_TREE_TYPE]: (entry: ReportDocCustom) => <FileTreeBlock entry={entry} />,\n [DATA_MODEL_TYPE]: (entry: ReportDocCustom) => <DataModelBlock entry={entry} />,\n};\n","/**\n * View state in the URL, so a filtered report survives a refresh and can be\n * shared as a link.\n *\n * It lives in the HASH, not the query string, because the flagship surface is a\n * single HTML file opened from disk. A `file://` document has an opaque origin,\n * and Chrome refuses `history.pushState`/`replaceState` when the URL argument\n * changes anything but the fragment there. The fragment is the one part every\n * browser lets us rewrite in place.\n *\n * Format: `#<anchor>?<params>` — the anchor half stays exactly what it has\n * always been, a scenario id deep link, so existing permalinks keep working and\n * a link with no filters is unchanged.\n */\n\nexport type UrlStatusFilter = \"all\" | \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n\nexport interface ReportUrlState {\n query: string;\n status: UrlStatusFilter;\n /** Scenario tag filter; a scenario matches if it carries ANY of these. */\n tags: string[];\n detail: \"full\" | \"minimal\";\n}\n\nexport const DEFAULT_URL_STATE: ReportUrlState = {\n query: \"\",\n status: \"all\",\n tags: [],\n detail: \"full\",\n};\n\nconst STATUSES: readonly UrlStatusFilter[] = [\"all\", \"passed\", \"failed\", \"skipped\", \"pending\"];\n\nexport interface SplitHash {\n /** Scenario id deep link (may be empty). */\n anchor: string;\n params: URLSearchParams;\n}\n\nexport function splitHash(hash: string): SplitHash {\n const raw = hash.replace(/^#/, \"\");\n const split = raw.indexOf(\"?\");\n if (split === -1) return { anchor: raw, params: new URLSearchParams() };\n return { anchor: raw.slice(0, split), params: new URLSearchParams(raw.slice(split + 1)) };\n}\n\nexport function decodeUrlState(params: URLSearchParams): ReportUrlState {\n const status = params.get(\"status\");\n const tags = params.get(\"tags\");\n return {\n query: params.get(\"q\") ?? DEFAULT_URL_STATE.query,\n status: STATUSES.includes(status as UrlStatusFilter)\n ? (status as UrlStatusFilter)\n : DEFAULT_URL_STATE.status,\n tags: tags ? tags.split(\",\").filter(Boolean) : [],\n detail: params.get(\"docs\") === \"0\" ? \"minimal\" : \"full\",\n };\n}\n\n/** Only non-default values reach the URL, so an untouched report has a clean one. */\nexport function encodeUrlState(state: ReportUrlState): string {\n const params = new URLSearchParams();\n if (state.query) params.set(\"q\", state.query);\n if (state.status !== \"all\") params.set(\"status\", state.status);\n if (state.tags.length > 0) params.set(\"tags\", state.tags.join(\",\"));\n if (state.detail === \"minimal\") params.set(\"docs\", \"0\");\n return params.toString();\n}\n\nexport function formatHash(anchor: string, params: string): string {\n if (params) return `#${anchor}?${params}`;\n return anchor ? `#${anchor}` : \"\";\n}\n\n/**\n * Rewrite the fragment without adding a history entry or reloading. Falls back\n * to assigning `location.hash` where the History API refuses the change (a\n * `file://` document in Chrome); that costs a history entry, which is why every\n * caller debounces keystroke-rate updates.\n */\nexport function writeHash(anchor: string, params: string): void {\n if (typeof window === \"undefined\") return;\n const next = formatHash(anchor, params);\n if (next === window.location.hash) return;\n // No fragment at all: strip it rather than leaving a bare \"#\".\n const url = next || window.location.href.split(\"#\")[0];\n try {\n window.history.replaceState(window.history.state, \"\", url);\n } catch {\n window.location.hash = next.slice(1);\n }\n}\n","/**\n * Scroll helpers that honour `prefers-reduced-motion`.\n *\n * JS `scrollIntoView({ behavior: \"smooth\" })` bypasses the CSS\n * `scroll-behavior` cascade, so reduced-motion users must be handled\n * explicitly here rather than in the stylesheet.\n */\n\nimport { splitHash, writeHash } from \"./hash-state\";\n\n/** True when the user has asked the OS to minimise non-essential motion. */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return false;\n }\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\nexport interface ScrollToScenarioOptions {\n /** Replace the URL hash with `#<scenarioId>` after scrolling. Defaults to true. */\n updateHash?: boolean;\n}\n\n/**\n * Scrolls a scenario into view by id. No-op in SSR or when the element is\n * absent. Uses an instant jump for reduced-motion users, smooth otherwise.\n */\nexport function scrollToScenarioId(\n scenarioId: string,\n options: ScrollToScenarioOptions = {},\n): void {\n if (typeof document === \"undefined\") return;\n const el = document.getElementById(scenarioId);\n if (!el) return;\n el.scrollIntoView({\n behavior: prefersReducedMotion() ? \"auto\" : \"smooth\",\n block: \"start\",\n });\n if (options.updateHash !== false) {\n // Keep any filter params already in the fragment: jumping to a scenario\n // must not silently drop the filters that surfaced it.\n writeHash(scenarioId, splitHash(window.location.hash).params.toString());\n }\n}\n","/**\n * Result<T> — explicit success/error type matching the cookbook convention.\n *\n * Used at the boundary where a StoryReport is parsed: the consumer hands us\n * an unknown value (file contents, fetch body, prop) and we return a Result.\n */\nimport type { StoryReport } from \"executable-stories-core\";\n\nexport type Result<T, E = ReportParseError> =\n | { ok: true; data: T }\n | { ok: false; error: E };\n\nexport interface ReportParseError {\n message: string;\n code: ReportParseErrorCode;\n issues?: readonly { path: string; message: string }[];\n}\n\nexport type ReportParseErrorCode =\n | \"INVALID_INPUT\"\n | \"SCHEMA_VERSION_MISMATCH\"\n | \"VALIDATION_FAILED\";\n\nexport const ok = <T>(data: T): Result<T> => ({ ok: true, data });\nexport const err = (error: ReportParseError): Result<never> => ({ ok: false, error });\n\n/**\n * Normalize the `StoryReport | Result<StoryReport>` prop accepted across the\n * render entrypoints (`Report`, `ReportInteractive`, `renderReportToHtml`) into\n * a single `Result`. A bare report becomes `ok(report)`; an already-wrapped\n * value passes through. One place owns the \"is this a Result?\" discrimination.\n */\nexport function unwrapReport(value: StoryReport | Result<StoryReport>): Result<StoryReport> {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"ok\" in value &&\n typeof (value as { ok: unknown }).ok === \"boolean\"\n ) {\n return value as Result<StoryReport>;\n }\n return ok(value as StoryReport);\n}\n","/**\n * Pure functions for filtering a StoryReport by a search query.\n * Used by <ReportInteractive>. Kept side-effect-free so it can be unit-tested.\n */\n\nimport type {\n ReportScenario,\n ReportFeature,\n StoryReport,\n} from \"executable-stories-core\";\nimport type { UrlStatusFilter } from \"../lib/hash-state\";\n\n/** Defined with the URL codec that has to validate it, so the two can't drift. */\nexport type StatusFilter = UrlStatusFilter;\n\nexport interface FilterCriteria {\n query?: string;\n status?: StatusFilter;\n /** Scenario matches if it carries ANY of these tags (empty = no tag filter). */\n tags?: string[];\n}\n\nexport function normalizeQuery(query: string): string {\n return query.trim().toLowerCase();\n}\n\n/** Unique scenario tags across the whole report, in first-seen order. */\nexport function allTags(report: StoryReport): string[] {\n const seen = new Set<string>();\n for (const feature of report.features) {\n for (const scenario of feature.scenarios) {\n for (const tag of scenario.tags) seen.add(tag);\n }\n }\n return [...seen];\n}\n\n/**\n * What people paste into the search box rarely comes from the report itself: a\n * ticket id from the tracker, a string out of a stack trace, a path from a PR\n * diff. So the query matches those too, not just the title/tags/steps.\n */\nfunction queryMatches(scenario: ReportScenario, q: string, sourceFile?: string): boolean {\n if (q === \"\") return true;\n if (scenario.title.toLowerCase().includes(q)) return true;\n if (sourceFile?.toLowerCase().includes(q)) return true;\n if (scenario.errorMessage?.toLowerCase().includes(q)) return true;\n for (const tag of scenario.tags) {\n if (tag.toLowerCase().includes(q)) return true;\n }\n for (const ticket of scenario.tickets ?? []) {\n if (ticket.id.toLowerCase().includes(q)) return true;\n }\n for (const step of scenario.steps) {\n if (step.text.toLowerCase().includes(q)) return true;\n }\n return false;\n}\n\nfunction scenarioMatches(\n scenario: ReportScenario,\n q: string,\n status: StatusFilter,\n tags: string[],\n sourceFile?: string,\n): boolean {\n if (status !== \"all\" && scenario.status !== status) return false;\n if (tags.length > 0 && !tags.some((t) => scenario.tags.includes(t))) return false;\n return queryMatches(scenario, q, sourceFile);\n}\n\nfunction summarizeScenarios(scenarios: ReportScenario[]) {\n let total = 0,\n passed = 0,\n failed = 0,\n skipped = 0,\n pending = 0,\n durationMs = 0;\n for (const s of scenarios) {\n total += 1;\n durationMs += s.durationMs;\n if (s.status === \"passed\") passed += 1;\n else if (s.status === \"failed\") failed += 1;\n else if (s.status === \"skipped\") skipped += 1;\n else pending += 1;\n }\n return { total, passed, failed, skipped, pending, durationMs };\n}\n\nexport function filterReport(report: StoryReport, criteria: string | FilterCriteria): StoryReport {\n const c: FilterCriteria = typeof criteria === \"string\" ? { query: criteria } : criteria;\n const q = normalizeQuery(c.query ?? \"\");\n const status = c.status ?? \"all\";\n const tags = c.tags ?? [];\n if (q === \"\" && status === \"all\" && tags.length === 0) return report;\n\n const features: ReportFeature[] = [];\n let topTotal = 0,\n topPassed = 0,\n topFailed = 0,\n topSkipped = 0,\n topPending = 0,\n topDuration = 0;\n\n for (const feature of report.features) {\n const matched = feature.scenarios.filter((s) =>\n scenarioMatches(s, q, status, tags, feature.sourceFile),\n );\n if (matched.length === 0) continue;\n const summary = summarizeScenarios(matched);\n features.push({ ...feature, summary, scenarios: matched });\n topTotal += summary.total;\n topPassed += summary.passed;\n topFailed += summary.failed;\n topSkipped += summary.skipped;\n topPending += summary.pending;\n topDuration += summary.durationMs;\n }\n\n return {\n ...report,\n summary: {\n total: topTotal,\n passed: topPassed,\n failed: topFailed,\n skipped: topSkipped,\n pending: topPending,\n durationMs: topDuration,\n },\n features,\n };\n}\n\nexport interface FailureRef {\n featureId: string;\n scenarioId: string;\n scenarioTitle: string;\n errorMessage?: string;\n}\n\n/** The failing scenarios themselves — for handing the whole red set to an agent. */\nexport function failedScenarios(report: StoryReport): ReportScenario[] {\n return report.features.flatMap((f) => f.scenarios.filter((s) => s.status === \"failed\"));\n}\n\nexport function listFailures(report: StoryReport): FailureRef[] {\n const out: FailureRef[] = [];\n for (const feature of report.features) {\n for (const scenario of feature.scenarios) {\n if (scenario.status === \"failed\") {\n const ref: FailureRef = {\n featureId: feature.id,\n scenarioId: scenario.id,\n scenarioTitle: scenario.title,\n };\n if (scenario.errorMessage !== undefined) {\n ref.errorMessage = scenario.errorMessage;\n }\n out.push(ref);\n }\n }\n }\n return out;\n}\n","\"use client\";\n\nimport { Bot, X } from \"lucide-react\";\nimport type { AppliedFilter } from \"./webmcp-tools\";\n\nexport interface ReportAgentFilterNoticeProps {\n applied: AppliedFilter;\n onReset: () => void;\n onDismiss: () => void;\n}\n\n/**\n * Says who moved the page.\n *\n * When an agent calls `filter_scenarios` the list changes under the reader with\n * nothing on screen to explain it. There is no confirmation step in front of\n * that — filtering a read-only report is not a risk worth a dialogue — so this\n * is the alternative: say what was applied, and offer the way back.\n *\n * The caller renders this only while the applied filter still matches the live\n * view state, so the notice disappears on its own the moment the reader touches\n * a filter themselves.\n */\nexport function ReportAgentFilterNotice({\n applied,\n onReset,\n onDismiss,\n}: ReportAgentFilterNoticeProps) {\n const terms: string[] = [];\n if (applied.search) terms.push(`matching “${applied.search}”`);\n if (applied.status !== \"all\") terms.push(applied.status);\n if (applied.tags.length > 0) terms.push(applied.tags.join(\", \"));\n\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"flex flex-wrap items-center gap-x-3 gap-y-1 rounded-md border border-primary/40 bg-primary/5 px-3 py-2 text-sm\"\n >\n <Bot aria-hidden className=\"size-4 shrink-0 text-primary\" />\n <span className=\"min-w-0 flex-1\">\n An agent filtered this report\n {terms.length > 0 ? <> to {terms.join(\" · \")}</> : null} —{\" \"}\n <span className=\"tabular-nums\">\n {applied.matched} of {applied.total} scenarios\n </span>\n .\n </span>\n <button\n type=\"button\"\n onClick={onReset}\n className=\"cursor-pointer rounded-md border border-border px-2 py-1 text-xs hover:bg-muted\"\n >\n Show all\n </button>\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className=\"cursor-pointer rounded-md p-1 text-muted-foreground hover:text-foreground\"\n >\n <X aria-hidden className=\"size-4\" />\n </button>\n </div>\n );\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\nimport type { FailureRef } from \"./filter\";\nimport { scrollToScenarioId } from \"../lib/scroll\";\n\nexport interface ReportFailureBannerProps {\n failures: readonly FailureRef[];\n /** Copies every failure as one agent prompt. Omitted on a static render. */\n onCopyAll?: () => void;\n}\n\nexport function ReportFailureBanner({ failures, onCopyAll }: ReportFailureBannerProps) {\n const first = failures[0];\n\n const jumpToFirst = useCallback(() => {\n if (!first) return;\n scrollToScenarioId(first.scenarioId);\n }, [first]);\n\n if (failures.length === 0) return null;\n\n // A live status region: `role=\"status\"` is not a valid role on <aside>\n // (whose implicit role is `complementary`), so use a <div> to carry it.\n return (\n <div\n className=\"es-failure-banner\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label=\"Failure summary\"\n >\n <span className=\"es-failure-banner-text\">\n <strong>{failures.length}</strong>{\" \"}\n failure{failures.length === 1 ? \"\" : \"s\"}\n </span>\n <button\n type=\"button\"\n className=\"es-failure-banner-jump\"\n onClick={jumpToFirst}\n aria-label=\"View first failure\"\n >\n View first failure ↓\n </button>\n {onCopyAll ? (\n <button\n type=\"button\"\n className=\"es-failure-banner-jump\"\n onClick={onCopyAll}\n aria-label=\"Copy failures for an agent\"\n >\n Copy {failures.length} failure{failures.length === 1 ? \"\" : \"s\"} for an agent\n </button>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { StatusFilter } from \"./filter\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { cn } from \"@/lib/utils\";\n\n// Above this many tags the filter list collapses to one row behind a \"+N more\"\n// toggle, so a tag-heavy report doesn't open with a tall grey brick before the\n// content. Small reports (≤ limit) show every tag, no toggle.\nconst TAG_LIMIT = 12;\n\nexport interface ReportFiltersProps {\n /** Status options to show (only those present in the run), with counts. */\n statuses: Array<{ key: StatusFilter; label: string; count: number }>;\n status: StatusFilter;\n onStatus: (status: StatusFilter) => void;\n tags: string[];\n activeTags: string[];\n onToggleTag: (tag: string) => void;\n}\n\nexport function ReportFilters({\n statuses,\n status,\n onStatus,\n tags,\n activeTags,\n onToggleTag,\n}: ReportFiltersProps) {\n // Local view-only state (tag list expanded or collapsed). The parent still\n // owns the domain filters — selected status and active tags — so this doesn't\n // break the component's presentational contract.\n const [showAllTags, setShowAllTags] = useState(false);\n if (statuses.length === 0 && tags.length === 0) return null;\n const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;\n const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;\n return (\n <div className=\"flex flex-col gap-2\">\n {statuses.length > 0 ? (\n <div role=\"group\" aria-label=\"Filter by status\" className=\"flex flex-wrap gap-1\">\n {statuses.map((opt) => {\n const active = status === opt.key;\n return (\n <button\n key={opt.key}\n type=\"button\"\n aria-pressed={active}\n onClick={() => onStatus(active && opt.key !== \"all\" ? \"all\" : opt.key)}\n className={cn(\n \"cursor-pointer rounded-md border px-2 py-1 text-xs transition-colors\",\n active\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border text-muted-foreground hover:bg-muted hover:text-foreground\",\n )}\n >\n {opt.label}\n <span className=\"ml-1 font-mono opacity-70\">{opt.count}</span>\n </button>\n );\n })}\n </div>\n ) : null}\n {tags.length > 0 ? (\n <ul aria-label=\"Filter by tag\" className=\"flex flex-wrap items-center gap-1.5\">\n {visibleTags.map((tag) => {\n const active = activeTags.includes(tag);\n return (\n <li key={tag}>\n <button\n type=\"button\"\n aria-pressed={active}\n onClick={() => onToggleTag(tag)}\n className=\"cursor-pointer\"\n >\n {/* Always the `tag` variant (font-mono) so the active state\n only swaps colours, never the font family. Switching to a\n sans variant on select would change the pill's width and\n reflow every sibling. */}\n <Badge\n variant=\"tag\"\n className={cn(\n active && \"border-primary bg-primary text-primary-foreground\",\n )}\n >\n {tag}\n </Badge>\n </button>\n </li>\n );\n })}\n {tags.length > TAG_LIMIT ? (\n <li>\n <button\n type=\"button\"\n aria-expanded={showAllTags}\n onClick={() => setShowAllTags((v) => !v)}\n className=\"cursor-pointer rounded-full px-2 py-0.5 text-xs font-medium text-muted-foreground hover:text-foreground\"\n >\n {tagsCollapsed ? `+${tags.length - TAG_LIMIT} more` : \"Show fewer\"}\n </button>\n </li>\n ) : null}\n </ul>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { formatRelativeAge, isReportStale } from \"../lib/provenance\";\n\nexport interface ReportFreshnessProps {\n /** Epoch ms of the run this report documents (see reportLastRunMs). */\n lastRunMs?: number;\n /** CI run URL, linked from the banner so readers can check for newer runs. */\n ciUrl?: string;\n /** Days before the report counts as stale; 0 disables the warning. */\n staleAfterDays: number;\n /** Test seam: fixed \"now\"; defaults to Date.now() on mount. */\n nowMs?: number;\n}\n\n/**\n * The report's freshness signal. Fresh reports get a one-line \"Last verified\n * N ago\" status; reports older than `staleAfterDays` get a warning banner —\n * living documentation is only trustworthy while it is recent.\n *\n * Age is computed on mount (never during server render): the static HTML is\n * generated once but read later, so any age baked in at build time would lie.\n */\nexport function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }: ReportFreshnessProps) {\n const [now, setNow] = useState<number | undefined>(nowMs);\n useEffect(() => {\n if (nowMs === undefined) setNow(Date.now());\n }, [nowMs]);\n\n if (lastRunMs === undefined || now === undefined) return null;\n\n const age = formatRelativeAge(lastRunMs, now);\n const runLink = ciUrl ? (\n <a\n href={ciUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"underline underline-offset-2\"\n >\n View CI run\n </a>\n ) : null;\n\n if (isReportStale(lastRunMs, staleAfterDays, now)) {\n return (\n <div className=\"es-stale-banner\" role=\"status\" aria-label=\"Report freshness\">\n <span>\n <strong>Last verified {age}.</strong> This report may no longer match the current\n behavior. Look for a newer run.\n </span>\n {runLink}\n </div>\n );\n }\n\n return (\n <p className=\"es-freshness\" aria-label=\"Report freshness\">\n Verified {age}\n {runLink ? <> · {runLink}</> : null}\n </p>\n );\n}\n","import type { StoryReport } from \"executable-stories-core\";\n\nimport { diffSinceLastRun, type ScenarioHistoryMap, type ScenarioRef } from \"../lib/run-history\";\nimport { cn } from \"@/lib/utils\";\n\nconst MAX_LINKS = 5;\n\nfunction ScenarioLinks({ scenarios, tone }: { scenarios: ScenarioRef[]; tone: string }) {\n return (\n <>\n {scenarios.slice(0, MAX_LINKS).map((s, i) => (\n <span key={s.id}>\n {i > 0 ? \", \" : \"\"}\n <a href={`#${s.id}`} className={cn(\"underline underline-offset-2 hover:no-underline\", tone)}>\n {s.title}\n </a>\n </span>\n ))}\n {scenarios.length > MAX_LINKS ? <span> and {scenarios.length - MAX_LINKS} more</span> : null}\n </>\n );\n}\n\n/**\n * One-line \"what changed since the previous run\" strip for the report header:\n * newly failing, newly passing, and first-seen scenarios, computed from the\n * embedded history store. Renders nothing without a previous run to compare\n * (no --history-file, or the first run with history enabled). Takes the\n * unfiltered report so search and filter chips never change the delta.\n */\nexport function ReportLastRunDelta({\n history,\n report,\n}: {\n history: ScenarioHistoryMap | undefined;\n report: StoryReport;\n}) {\n if (!history) return null;\n const scenarios = report.features.flatMap((f) => f.scenarios.map((s) => ({ id: s.id, title: s.title })));\n const delta = diffSinceLastRun(history, scenarios);\n if (!delta) return null;\n\n const { newlyFailing, newlyPassing, added } = delta;\n if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {\n return (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"es-last-run-delta\">\n Since last run: no behavior changes.\n </p>\n );\n }\n\n return (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"es-last-run-delta\">\n <span className=\"font-medium text-foreground\">Since last run:</span>\n {newlyFailing.length > 0 ? (\n <span className=\"ml-2 text-fail\">\n {newlyFailing.length} newly failing (<ScenarioLinks scenarios={newlyFailing} tone=\"text-fail\" />)\n </span>\n ) : null}\n {newlyPassing.length > 0 ? (\n <span className=\"ml-2 text-pass\">\n {newlyPassing.length} fixed (<ScenarioLinks scenarios={newlyPassing} tone=\"text-pass\" />)\n </span>\n ) : null}\n {added.length > 0 ? <span className=\"ml-2\">{added.length} new</span> : null}\n </p>\n );\n}\n","\"use client\";\n\nimport {\n forwardRef,\n useId,\n type ChangeEvent,\n type KeyboardEvent,\n} from \"react\";\nimport { Search } from \"lucide-react\";\nimport { Input } from \"@/components/ui/input\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportSearchProps {\n value: string;\n onChange: (next: string) => void;\n matchedCount?: number;\n totalCount?: number;\n placeholder?: string;\n className?: string;\n}\n\nexport const ReportSearch = forwardRef<HTMLInputElement, ReportSearchProps>(\n function ReportSearch(props, ref) {\n const {\n value,\n onChange,\n matchedCount,\n totalCount,\n placeholder = \"Search scenarios, tags, tickets, errors…\",\n className,\n } = props;\n const inputId = useId();\n // Only surface a count once the user is actually filtering — the \"All N\"\n // status tab already shows the total, so a resting \"N total\" is duplication.\n const showCounts =\n value.trim().length > 0 &&\n typeof matchedCount === \"number\" &&\n typeof totalCount === \"number\";\n\n function handleChange(e: ChangeEvent<HTMLInputElement>) {\n onChange(e.target.value);\n }\n\n function handleKeyDown(e: KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Escape\" && value !== \"\") {\n onChange(\"\");\n e.preventDefault();\n }\n }\n\n // `es-search` is kept only as the print-hide hook (styles.css @media print);\n // all styling is the shadcn Input + utilities now.\n return (\n <div className={cn(\"es-search flex flex-col gap-1\", className)}>\n <label htmlFor={inputId} className=\"sr-only\">\n Search\n </label>\n <div className=\"relative w-full sm:w-72\">\n <Search\n aria-hidden\n className=\"pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n ref={ref}\n id={inputId}\n type=\"search\"\n value={value}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n autoComplete=\"off\"\n spellCheck={false}\n aria-keyshortcuts=\"/\"\n className=\"pl-8\"\n />\n </div>\n {showCounts ? (\n <span\n className=\"text-xs tabular-nums text-muted-foreground\"\n aria-live=\"polite\"\n >\n {matchedCount} of {totalCount} scenarios\n </span>\n ) : null}\n </div>\n );\n },\n);\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30\",\n \"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n \"aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","'use client';\n\n/** CLI handoff for sharing a standalone HTML report and its local assets. */\n\nimport { Share2 } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport { Button } from '../components/ui/button';\n\nexport const DEFAULT_SHARE_COMMAND = 'npx executable-stories share reports/';\n\nexport interface ReportShareProps {\n /** Command the dialog tells the user to run. */\n command?: string;\n /** Copy to clipboard + toast; supplied by the report so one toast serves all. */\n onCopy: (text: string, message: string) => void;\n}\n\nexport function ReportShare({\n command = DEFAULT_SHARE_COMMAND,\n onCopy,\n}: ReportShareProps) {\n const [open, setOpen] = useState(false);\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open && !dialog.open) dialog.showModal();\n else if (!open && dialog.open) dialog.close();\n }, [open]);\n\n return (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Share this report\"\n title=\"Share this report\"\n onClick={() => setOpen(true)}\n >\n <Share2 aria-hidden=\"true\" className=\"size-4\" />\n <span className=\"sr-only sm:not-sr-only\">Share</span>\n </Button>\n <dialog\n ref={dialogRef}\n className=\"es-report-share m-auto w-[min(90vw,32rem)] rounded-lg border border-border bg-card p-6 text-card-foreground shadow-lg [overscroll-behavior:contain] backdrop:bg-black/40\"\n aria-label=\"Share this report\"\n onClose={() => setOpen(false)}\n >\n <h2 className=\"text-base font-semibold\">Share this report</h2>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n Publish it to Executable Stories Cloud and send a link. Screenshots\n and videos go with it. Run this from your project:\n </p>\n <div className=\"mt-4 flex items-center gap-2\">\n <code className=\"min-w-0 flex-1 truncate rounded border border-border bg-muted px-3 py-2 font-mono text-xs\">\n {command}\n </code>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => onCopy(command, 'Command copied')}\n >\n Copy\n </Button>\n </div>\n <p className=\"mt-3 text-xs text-muted-foreground\">\n The file you are reading cannot upload itself, so the command does it:\n only the CLI can read the assets this report links to.\n </p>\n <div className=\"mt-6 flex items-center justify-between gap-4\">\n <a\n className=\"text-xs underline underline-offset-2\"\n href=\"https://executablestories.com/guides/sharing-reports/\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n How sharing works\n </a>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setOpen(false)}>\n Close\n </Button>\n </div>\n </dialog>\n </>\n );\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { useRender } from \"@base-ui/react/use-render\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n xs: \"h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 rounded-md [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n render,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n // Base UI composition: pass `render={<a … />}` (or any element) to swap the\n // underlying tag — replaces Radix's `asChild`. See rules/base-vs-radix.md.\n render?: useRender.RenderProp\n }) {\n return useRender({\n defaultTagName: \"button\",\n render,\n props: {\n \"data-slot\": \"button\",\n \"data-variant\": variant,\n \"data-size\": size,\n className: cn(buttonVariants({ variant, size, className })),\n ...props,\n },\n })\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\n\nimport { formatRelativeAge } from \"../lib/provenance\";\nimport type { ScenarioRef } from \"../lib/run-history\";\nimport { cn } from \"../lib/utils\";\nimport { diffSinceVisit, snapshotOf, type VisitDelta, type VisitSnapshot } from \"./last-visit\";\n\nconst KEY = \"es-last-visit\";\nconst MAX_LINKS = 5;\n\nfunction readVisit(): VisitSnapshot | null {\n try {\n const raw = localStorage.getItem(KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const v = parsed as Partial<VisitSnapshot>;\n if (typeof v.runId !== \"string\" || typeof v.atMs !== \"number\" || typeof v.statuses !== \"object\") {\n return null;\n }\n return { runId: v.runId, atMs: v.atMs, statuses: v.statuses as VisitSnapshot[\"statuses\"] };\n } catch {\n // Disabled storage, or a snapshot written by an older shape. Either way the\n // reader just gets no strip — never a crashed report.\n return null;\n }\n}\n\nfunction writeVisit(snapshot: VisitSnapshot): void {\n try {\n localStorage.setItem(KEY, JSON.stringify(snapshot));\n } catch {\n /* disabled / quota */\n }\n}\n\nfunction ScenarioLinks({ scenarios, tone }: { scenarios: ScenarioRef[]; tone: string }) {\n return (\n <>\n {scenarios.slice(0, MAX_LINKS).map((s, i) => (\n <span key={s.id}>\n {i > 0 ? \", \" : \"\"}\n <a href={`#${s.id}`} className={cn(\"underline underline-offset-2 hover:no-underline\", tone)}>\n {s.title}\n </a>\n </span>\n ))}\n {scenarios.length > MAX_LINKS ? <span> and {scenarios.length - MAX_LINKS} more</span> : null}\n </>\n );\n}\n\n/**\n * \"Since your last visit\" — the delta against what THIS reader last saw, which\n * on a tab opened a week later is a different question from what the last run\n * changed. Reads and writes one localStorage key: the snapshot never leaves the\n * browser, and a reader with storage disabled simply sees no strip.\n *\n * Runs in an effect (not during render) because it touches storage and the\n * clock — the server render and the first client paint have to agree.\n */\nexport function ReportSinceLastVisit({ report }: { report: StoryReport }) {\n const [delta, setDelta] = useState<VisitDelta | null>(null);\n const [nowMs, setNowMs] = useState(0);\n\n useEffect(() => {\n const now = Date.now();\n setDelta(diffSinceVisit(readVisit(), report));\n setNowMs(now);\n writeVisit(snapshotOf(report, now));\n }, [report]);\n\n if (!delta) return null;\n const { newlyFailing, newlyPassing, added } = delta;\n\n return (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"es-since-last-visit\">\n <span className=\"font-medium text-foreground\">\n Since your last visit ({formatRelativeAge(delta.sinceMs, nowMs)}):\n </span>\n {newlyFailing.length > 0 ? (\n <span className=\"ml-2 text-fail\">\n {newlyFailing.length} started failing (<ScenarioLinks scenarios={newlyFailing} tone=\"text-fail\" />)\n </span>\n ) : null}\n {newlyPassing.length > 0 ? (\n <span className=\"ml-2 text-pass\">\n {newlyPassing.length} fixed (<ScenarioLinks scenarios={newlyPassing} tone=\"text-pass\" />)\n </span>\n ) : null}\n {added.length > 0 ? <span className=\"ml-2\">{added.length} new</span> : null}\n </p>\n );\n}\n","/**\n * \"Since YOU were last here\" — a per-reader delta, kept in this browser only.\n *\n * The run-to-run delta (<ReportLastRunDelta>) answers \"what changed in the last\n * run\", which is rarely the question someone opening a week-old tab arrives\n * with. This compares the report against the statuses that reader last saw,\n * however many runs ago that was. Pure functions; the storage and the clock\n * live in <ReportSinceLastVisit>.\n */\n\nimport type { StoryReport } from \"executable-stories-core\";\nimport type { ScenarioRef, ScenarioRunStatus } from \"../lib/run-history\";\n\nexport interface VisitSnapshot {\n runId: string;\n atMs: number;\n statuses: Record<string, ScenarioRunStatus>;\n}\n\nexport interface VisitDelta {\n /** When the reader was last here. */\n sinceMs: number;\n newlyFailing: ScenarioRef[];\n newlyPassing: ScenarioRef[];\n /** Scenarios that did not exist (for this reader) at the last visit. */\n added: ScenarioRef[];\n}\n\nexport function snapshotOf(report: StoryReport, atMs: number): VisitSnapshot {\n const statuses: Record<string, ScenarioRunStatus> = {};\n for (const feature of report.features) {\n for (const scenario of feature.scenarios) {\n statuses[scenario.id] = scenario.status;\n }\n }\n return { runId: report.runId, atMs, statuses };\n}\n\n/**\n * Null when there is nothing worth saying: no previous visit, the same run the\n * reader already saw, or a new run that changed nothing they had seen.\n */\nexport function diffSinceVisit(previous: VisitSnapshot | null, report: StoryReport): VisitDelta | null {\n if (!previous) return null;\n if (previous.runId === report.runId) return null;\n\n const newlyFailing: ScenarioRef[] = [];\n const newlyPassing: ScenarioRef[] = [];\n const added: ScenarioRef[] = [];\n\n for (const feature of report.features) {\n for (const scenario of feature.scenarios) {\n const ref: ScenarioRef = { id: scenario.id, title: scenario.title };\n const before = previous.statuses[scenario.id];\n if (before === undefined) {\n added.push(ref);\n } else if (before !== \"failed\" && scenario.status === \"failed\") {\n newlyFailing.push(ref);\n } else if (before === \"failed\" && scenario.status === \"passed\") {\n newlyPassing.push(ref);\n }\n }\n }\n\n if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) return null;\n return { sinceMs: previous.atMs, newlyFailing, newlyPassing, added };\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { Button } from \"../components/ui/button\";\n\nexport interface ReportShortcutsHelpProps {\n open: boolean;\n onClose: () => void;\n}\n\n// Kept in lockstep with the bindings in use-keyboard-shortcuts.ts — every key it\n// handles is listed here so the help never lies about what's available.\nconst SHORTCUTS: ReadonlyArray<{ keys: string; description: string }> = [\n { keys: \"/\", description: \"Focus search\" },\n { keys: \"f\", description: \"Jump to next failure\" },\n { keys: \"Shift F\", description: \"Jump to previous failure\" },\n { keys: \"e\", description: \"Expand all\" },\n { keys: \"c\", description: \"Collapse all\" },\n { keys: \"?\", description: \"Toggle this help\" },\n { keys: \"Esc\", description: \"Clear search / close\" },\n];\n\nfunction Keys({ keys }: { keys: string }) {\n // Split combos (\"Shift F\") into one chip per key with a \"+\" between.\n const parts = keys.split(\" \");\n return (\n <span className=\"inline-flex items-center gap-1\">\n {parts.map((k, i) => (\n <span key={k} className=\"inline-flex items-center gap-1\">\n {i > 0 ? <span className=\"text-xs text-muted-foreground\">+</span> : null}\n <kbd className=\"inline-flex h-6 min-w-6 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs font-medium text-muted-foreground\">\n {k}\n </kbd>\n </span>\n ))}\n </span>\n );\n}\n\nexport function ReportShortcutsHelp({ open, onClose }: ReportShortcutsHelpProps) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open && !dialog.open) dialog.showModal();\n else if (!open && dialog.open) dialog.close();\n }, [open]);\n\n return (\n <dialog\n ref={dialogRef}\n className=\"es-shortcuts-help m-auto w-[min(90vw,28rem)] rounded-lg border border-border bg-card p-6 text-card-foreground shadow-lg [overscroll-behavior:contain] backdrop:bg-black/40\"\n aria-label=\"Keyboard shortcuts\"\n onClose={onClose}\n >\n <h2 className=\"text-base font-semibold\">Keyboard shortcuts</h2>\n <dl className=\"mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5\">\n {SHORTCUTS.map((s) => (\n <div key={s.keys} className=\"col-span-2 grid grid-cols-subgrid items-center\">\n <dt className=\"justify-self-start\">\n <Keys keys={s.keys} />\n </dt>\n <dd className=\"text-sm text-muted-foreground\">{s.description}</dd>\n </div>\n ))}\n </dl>\n <form method=\"dialog\" className=\"mt-6\">\n <Button type=\"submit\" variant=\"outline\" size=\"sm\">\n Close\n </Button>\n </form>\n </dialog>\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useReport } from \"../hooks/useReport\";\nimport { scrollToScenarioId } from \"../lib/scroll\";\nimport { cn } from \"@/lib/utils\";\n\nconst DOT: Record<string, string> = {\n passed: \"bg-pass\",\n failed: \"bg-fail\",\n skipped: \"bg-skip\",\n pending: \"bg-pend\",\n};\n\n/**\n * The table-of-contents list + scroll-spy, shared by the sticky `ReportToc`\n * sidebar (lg+) and the narrow-screen `ReportTocDrawer`. Tracks the scenario\n * nearest the top of the viewport via IntersectionObserver. `onNavigate` fires\n * after a link is followed, so the drawer can close itself.\n */\nexport function TocContent({ onNavigate }: { onNavigate?: () => void }) {\n const report = useReport();\n const [activeId, setActiveId] = useState<string | null>(null);\n\n const scenarioIds = useMemo(\n () => report.features.flatMap((f) => f.scenarios.map((s) => s.id)),\n [report],\n );\n\n useEffect(() => {\n if (typeof IntersectionObserver === \"undefined\") return;\n const els = scenarioIds\n .map((id) => document.getElementById(id))\n .filter((el): el is HTMLElement => el !== null);\n if (els.length === 0) return;\n\n const observer = new IntersectionObserver(\n (entries) => {\n const visible = entries\n .filter((e) => e.isIntersecting)\n .sort((a, b) => a.boundingClientRect.top - b.boundingClientRect.top);\n if (visible[0]) setActiveId(visible[0].target.id);\n },\n { rootMargin: \"-8% 0px -80% 0px\" },\n );\n els.forEach((el) => observer.observe(el));\n return () => observer.disconnect();\n }, [scenarioIds]);\n\n if (report.features.length === 0) return null;\n\n // `list-none pl-0` explicitly: the drawer portals OUTSIDE `.es-report-island`,\n // so it can't rely on the island's list reset — bullets would leak otherwise.\n return (\n <ul className=\"flex list-none flex-col gap-4 pl-0\">\n {report.features.map((feature) => (\n <li key={feature.id}>\n <p className=\"mb-1.5 font-semibold leading-snug text-foreground\">{feature.title}</p>\n <ul className=\"flex list-none flex-col gap-0.5 pl-0\">\n {feature.scenarios.map((scenario) => {\n const active = activeId === scenario.id;\n return (\n <li key={scenario.id}>\n <a\n href={`#${scenario.id}`}\n onClick={(e) => {\n e.preventDefault();\n scrollToScenarioId(scenario.id, { updateHash: true });\n onNavigate?.();\n }}\n aria-current={active ? \"true\" : undefined}\n className={cn(\n \"flex items-start gap-2 border-l-2 py-1 pl-2.5 leading-snug hover:text-foreground\",\n active\n ? \"border-primary font-medium text-foreground\"\n : \"border-border text-muted-foreground\",\n )}\n >\n <span\n aria-hidden\n className={cn(\"mt-1 size-1.5 shrink-0 rounded-full\", DOT[scenario.status])}\n />\n <span className=\"break-words\">{scenario.title}</span>\n </a>\n </li>\n );\n })}\n </ul>\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * Sticky table-of-contents nav for the interactive report (lg+ only). On\n * narrow screens it's hidden and `ReportTocDrawer` provides the same nav.\n */\nexport function ReportToc() {\n const report = useReport();\n if (report.features.length === 0) return null;\n return (\n <nav\n aria-label=\"Table of contents\"\n className=\"sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block\"\n >\n <p className=\"mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n Contents\n </p>\n <TocContent />\n </nav>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\";\nimport { ListIcon, XIcon } from \"lucide-react\";\nimport { useReport } from \"../hooks/useReport\";\nimport { TocContent } from \"./ReportToc\";\n\n/**\n * Narrow-screen table of contents: a left-sliding drawer holding the same\n * `TocContent` (and scroll-spy) as the sticky sidebar. The trigger is\n * `lg:hidden`, so on wide screens the sidebar shows instead and this stays out\n * of the way. Following a link closes the drawer so the scenario is revealed.\n */\nexport function ReportTocDrawer() {\n const report = useReport();\n const [open, setOpen] = useState(false);\n if (report.features.length === 0) return null;\n return (\n <DialogPrimitive.Root open={open} onOpenChange={setOpen}>\n <DialogPrimitive.Trigger className=\"flex cursor-pointer items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground lg:hidden [&_svg]:size-3.5\">\n <ListIcon aria-hidden /> Contents\n </DialogPrimitive.Trigger>\n <DialogPrimitive.Portal>\n <DialogPrimitive.Backdrop className=\"fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0\" />\n <DialogPrimitive.Popup className=\"fixed inset-y-0 left-0 z-50 flex w-72 max-w-[80vw] flex-col gap-3 overflow-y-auto border-r border-border bg-background p-4 font-sans text-xs shadow-lg outline-none transition-transform duration-200 data-[ending-style]:-translate-x-full data-[starting-style]:-translate-x-full\">\n <div className=\"flex items-center justify-between\">\n <DialogPrimitive.Title className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n Contents\n </DialogPrimitive.Title>\n <DialogPrimitive.Close\n aria-label=\"Close contents\"\n className=\"cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4\"\n >\n <XIcon aria-hidden />\n </DialogPrimitive.Close>\n </div>\n <TocContent onNavigate={() => setOpen(false)} />\n </DialogPrimitive.Popup>\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n );\n}\n","/**\n * Failure-first defaults for the interactive report.\n *\n * A report of a broken run is a triage surface before it is an archive: the\n * question is \"what failed\", not \"show me all 400 scenarios\". So on a run with\n * failures the report opens with passing work collapsed to its titles and\n * failing work expanded — the same \"compress passing, expand failing\" posture\n * the `check` CLI takes.\n *\n * Two deliberate limits:\n * - an all-green run collapses NOTHING; there is nothing to triage, and a wall\n * of collapsed titles would be worse than the current view.\n * - this only ever seeds the FIRST visit. `useCollapseState` prefers a\n * persisted set, so a user who has expressed a preference keeps it.\n */\nimport type { StoryReport } from \"executable-stories-core\";\n\n/** True when a scenario is one the reader needs to see immediately. */\nfunction needsAttention(status: string): boolean {\n return status === \"failed\";\n}\n\n/**\n * The ids to collapse on first view: every passing/skipped feature and\n * scenario, when the run has at least one failure. Empty set otherwise.\n */\nexport function defaultCollapsedIds(report: StoryReport): Set<string> {\n const collapsed = new Set<string>();\n if (report.summary.failed === 0) return collapsed;\n\n for (const feature of report.features) {\n const featureHasFailure = feature.scenarios.some((s) => needsAttention(s.status));\n // A feature with no failures collapses whole — its scenarios stay in the\n // set too, so expanding the feature doesn't dump every step at once.\n if (!featureHasFailure) collapsed.add(feature.id);\n for (const scenario of feature.scenarios) {\n if (!needsAttention(scenario.status)) collapsed.add(scenario.id);\n }\n }\n return collapsed;\n}\n\n/**\n * Order features so the ones with failures come first, preserving the original\n * relative order within each group (a stable partition, not a re-sort — source\n * order still carries meaning for everything else).\n */\nexport function failuresFirst(report: StoryReport): StoryReport {\n if (report.summary.failed === 0) return report;\n const withFailures: StoryReport[\"features\"] = [];\n const rest: StoryReport[\"features\"] = [];\n for (const feature of report.features) {\n (feature.scenarios.some((s) => needsAttention(s.status)) ? withFailures : rest).push(feature);\n }\n if (withFailures.length === 0) return report;\n return { ...report, features: [...withFailures, ...rest] };\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { scrollToScenarioId } from \"../lib/scroll\";\nimport { splitHash } from \"../lib/hash-state\";\n\n/**\n * Scrolls to a scenario by URL hash on mount and whenever the deep link\n * changes. No-op in SSR (only runs in useEffect). Honours\n * `prefers-reduced-motion`.\n *\n * The fragment also carries filter state (`#<anchor>?q=...`), so only the\n * anchor half is read — and a hashchange that merely rewrote the filters must\n * not yank the page back to the last anchor, hence the last-anchor guard.\n */\nexport function useDeepLinkScroll(): void {\n const lastAnchor = useRef<string | null>(null);\n\n useEffect(() => {\n function scrollToHash() {\n const { anchor } = splitHash(window.location.hash);\n if (!anchor || anchor === lastAnchor.current) return;\n lastAnchor.current = anchor;\n // The hash is already in the URL; don't rewrite history on arrival.\n requestAnimationFrame(() => {\n scrollToScenarioId(anchor, { updateHash: false });\n });\n }\n scrollToHash();\n window.addEventListener(\"hashchange\", scrollToHash);\n return () => window.removeEventListener(\"hashchange\", scrollToHash);\n }, []);\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\nexport interface KeyboardShortcutHandlers {\n onFocusSearch?: () => void;\n onNextFailure?: () => void;\n onPrevFailure?: () => void;\n onToggleHelp?: () => void;\n onEscape?: () => void;\n onExpandAll?: () => void;\n onCollapseAll?: () => void;\n}\n\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false;\n const tag = target.tagName;\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") return true;\n if (target.isContentEditable) return true;\n return false;\n}\n\n/**\n * Attaches one keydown listener for the lifetime of the component, regardless\n * of how often the consumer passes a fresh handlers object. Handlers are read\n * from a ref so each keypress hits the latest version — see Vercel's\n * advanced-use-latest pattern.\n */\nexport function useKeyboardShortcuts(handlers: KeyboardShortcutHandlers): void {\n const ref = useRef(handlers);\n ref.current = handlers;\n\n useEffect(() => {\n function onKeyDown(e: KeyboardEvent) {\n const h = ref.current;\n if (e.key === \"Escape\") {\n h.onEscape?.();\n return;\n }\n\n if (isEditableTarget(e.target)) return;\n if (e.metaKey || e.ctrlKey || e.altKey) return;\n\n switch (e.key) {\n case \"/\":\n h.onFocusSearch?.();\n e.preventDefault();\n return;\n case \"?\":\n h.onToggleHelp?.();\n e.preventDefault();\n return;\n case \"f\":\n h.onNextFailure?.();\n e.preventDefault();\n return;\n case \"F\":\n h.onPrevFailure?.();\n e.preventDefault();\n return;\n case \"e\":\n h.onExpandAll?.();\n e.preventDefault();\n return;\n case \"c\":\n h.onCollapseAll?.();\n e.preventDefault();\n return;\n default:\n return;\n }\n }\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, []);\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\n\nexport type ThemePref = \"light\" | \"system\" | \"dark\";\nconst KEY = \"es-theme\";\n\nfunction systemDark(): boolean {\n return typeof matchMedia !== \"undefined\" && matchMedia(\"(prefers-color-scheme: dark)\").matches;\n}\n\nfunction resolve(pref: ThemePref): \"light\" | \"dark\" {\n return pref === \"system\" ? (systemDark() ? \"dark\" : \"light\") : pref;\n}\n\nfunction applyTheme(pref: ThemePref): void {\n if (typeof document !== \"undefined\") {\n document.documentElement.setAttribute(\"data-theme\", resolve(pref));\n }\n}\n\nfunction initialPref(): ThemePref {\n if (typeof localStorage !== \"undefined\") {\n const stored = localStorage.getItem(KEY);\n if (stored === \"light\" || stored === \"dark\" || stored === \"system\") return stored;\n }\n // Nothing stored → follow the OS. (The old 2-way toggle also honoured the\n // prefers-color-scheme media query on first load, so this keeps that default.)\n return \"system\";\n}\n\n/**\n * Light / System / Dark theme preference for the standalone report. Sets\n * `data-theme` on <html> (the Tailwind `dark` variant keys off it), resolving\n * \"system\" through prefers-color-scheme and re-resolving when the OS flips while\n * on \"system\". Persists the choice. No-ops gracefully outside the browser.\n */\nexport function useTheme(): { pref: ThemePref; setPref: (p: ThemePref) => void } {\n const [pref, setPrefState] = useState<ThemePref>(\"system\");\n\n useEffect(() => {\n const p = initialPref();\n setPrefState(p);\n applyTheme(p);\n }, []);\n\n useEffect(() => {\n if (typeof matchMedia === \"undefined\") return;\n const mq = matchMedia(\"(prefers-color-scheme: dark)\");\n const onChange = () => {\n if (pref === \"system\") applyTheme(\"system\");\n };\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, [pref]);\n\n const setPref = useCallback((p: ThemePref) => {\n setPrefState(p);\n applyTheme(p);\n try {\n localStorage.setItem(KEY, p);\n } catch {\n /* disabled / quota */\n }\n }, []);\n\n return { pref, setPref };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n DEFAULT_URL_STATE,\n decodeUrlState,\n encodeUrlState,\n splitHash,\n writeHash,\n type ReportUrlState,\n} from \"../lib/hash-state\";\n\n/** Keystroke-rate updates coalesce into one URL write. */\nconst WRITE_DELAY_MS = 250;\n\n/**\n * Search / status / tag / detail state, mirrored into the URL fragment so a\n * refresh or a shared link restores the same view. See lib/hash-state for why\n * the fragment and not the query string.\n *\n * The URL is read in an effect rather than during render: this component also\n * hydrates a server-rendered tree (Astro `client:load`), where a first client\n * render that disagreed with the server markup would be a hydration mismatch.\n */\nexport function useUrlState(): [ReportUrlState, (patch: Partial<ReportUrlState>) => void] {\n const [state, setState] = useState<ReportUrlState>(DEFAULT_URL_STATE);\n const ready = useRef(false);\n\n useEffect(() => {\n const read = () => setState(decodeUrlState(splitHash(window.location.hash).params));\n read();\n ready.current = true;\n // Back/forward and in-page anchor jumps both surface as hashchange.\n window.addEventListener(\"hashchange\", read);\n return () => window.removeEventListener(\"hashchange\", read);\n }, []);\n\n useEffect(() => {\n // Never write before the first read, or mount would erase incoming filters.\n if (!ready.current) return;\n const timer = setTimeout(\n () => writeHash(splitHash(window.location.hash).anchor, encodeUrlState(state)),\n WRITE_DELAY_MS,\n );\n return () => clearTimeout(timer);\n }, [state]);\n\n const update = useCallback(\n (patch: Partial<ReportUrlState>) => setState((prev) => ({ ...prev, ...patch })),\n [],\n );\n\n return [state, update];\n}\n","'use client';\n\n/**\n * WebMCP tools the HTML report registers in the reader's own browser.\n *\n * The report already has an agent channel for coding agents: the MCP server and\n * the StoryReport JSON, both of which need a filesystem. This is the channel for\n * the reader who has neither — someone with a browser agent open, pointed at a\n * shared report URL or a self-contained `report.html`, asking it questions.\n *\n * Four reads and one view-driving tool. The reads answer from the report the\n * page already holds. `filter_scenarios` drives the same URL-fragment state the\n * search box and filter pills write, so an agent asked to \"show the failing\n * checkout scenarios\" changes what the reader is looking at.\n *\n * Deliberately NOT here, and staying MCP-only:\n * - `get_scenario_index` / `get_behavior_manifest` — both route through\n * `scenarioContentHash`, which is node-only (`node:crypto`) and must never\n * enter a browser bundle.\n * - `run_scenario` — a static page has no backend to run tests on.\n *\n * The four reads mirror the MCP server's names and payload shapes; the shared\n * projections live in `executable-stories-core/report-queries` so the two\n * transports cannot answer the same question differently.\n */\n\nimport {\n getFeatureSummary,\n getScenario,\n listScenarioSummaries,\n runProvenance,\n toScenarioSummary,\n type ScenarioFilters,\n} from 'executable-stories-core/report-queries';\nimport type {\n StoryReport,\n TestStatus,\n} from 'executable-stories-core/types/story-report';\nimport type { ToolDef } from 'webmcpable';\nimport type { ReportUrlState, UrlStatusFilter } from '../lib/hash-state';\nimport { filterReport, type StatusFilter } from './filter';\n\nconst STATUSES: readonly TestStatus[] = [\n 'passed',\n 'failed',\n 'skipped',\n 'pending',\n];\nconst VIEW_STATUSES: readonly UrlStatusFilter[] = ['all', ...STATUSES];\n\n/**\n * Every payload carries this.\n *\n * A report is a snapshot, and a reader asking questions of a three-week-old\n * `report.html` has no way to tell it from this morning's. Without the run's\n * age in the answer, an agent relays a long-dead failure as current fact.\n */\nexport interface WithRun {\n run: ReturnType<typeof runProvenance>;\n}\n\nexport interface ReportToolsDeps {\n /** The whole report, unfiltered — reads always answer from all of it. */\n report: StoryReport;\n /** Current view state, so `filter_scenarios` can patch rather than replace. */\n view: ReportUrlState;\n setView: (patch: Partial<ReportUrlState>) => void;\n /**\n * Called when an agent changes the view, so the UI can say so. The reader\n * sees the list change; this is what tells them why.\n */\n onAgentFilter?: (applied: AppliedFilter) => void;\n /** Injected for tests. Defaults to `Date.now`. */\n now?: () => number;\n}\n\nexport interface AppliedFilter {\n search: string;\n status: UrlStatusFilter;\n tags: string[];\n matched: number;\n total: number;\n}\n\n/**\n * A raw JSON Schema is a description, not a validator: webmcpable enforces the\n * top-level `required` list and nothing else. Anything an agent can get wrong\n * inside an optional field has to be checked here, and reported by RETURNING a\n * message — Chrome replaces a thrown error with a generic `UnknownError`, so a\n * throw teaches the agent nothing.\n */\nclass ToolArgumentError extends Error {}\n\n/**\n * The handler signature erases the input type (the registry holds a union of\n * tool definitions), and a raw JSON Schema is not a parser, so the argument\n * really is unknown here. Narrow once, at the boundary.\n */\nfunction asRecord(input: unknown): Record<string, unknown> {\n return typeof input === 'object' && input !== null\n ? (input as Record<string, unknown>)\n : {};\n}\n\nfunction readString(input: Record<string, unknown>, key: string): string | undefined {\n const value = input[key];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string') {\n throw new ToolArgumentError(`\"${key}\" must be a string, received ${typeof value}.`);\n }\n return value;\n}\n\nfunction readStringArray(\n input: Record<string, unknown>,\n key: string,\n): string[] | undefined {\n const value = input[key];\n if (value === undefined || value === null) return undefined;\n // A single tag as a bare string is the mistake an agent actually makes, and\n // the intent is unambiguous. Accept it rather than refusing the call.\n if (typeof value === 'string') return [value];\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {\n throw new ToolArgumentError(`\"${key}\" must be an array of strings.`);\n }\n return value as string[];\n}\n\nfunction readEnum<T extends string>(\n input: Record<string, unknown>,\n key: string,\n allowed: readonly T[],\n): T | undefined {\n const value = readString(input, key);\n if (value === undefined) return undefined;\n if (!allowed.includes(value as T)) {\n throw new ToolArgumentError(\n `\"${key}\" must be one of: ${allowed.join(', ')}. Received \"${value}\".`,\n );\n }\n return value as T;\n}\n\nfunction readStatuses(input: Record<string, unknown>): TestStatus[] | undefined {\n const values = readStringArray(input, 'statuses');\n if (values === undefined) return undefined;\n const invalid = values.filter((v) => !STATUSES.includes(v as TestStatus));\n if (invalid.length > 0) {\n throw new ToolArgumentError(\n `\"statuses\" must contain only: ${STATUSES.join(', ')}. Received \"${invalid.join('\", \"')}\".`,\n );\n }\n return values as TestStatus[];\n}\n\n/** Turns an argument mistake into text the agent can act on, not a dead call. */\nfunction guarded<T>(run: () => T): T | string {\n try {\n return run();\n } catch (error) {\n if (error instanceof ToolArgumentError) return `Invalid input — ${error.message}`;\n throw error;\n }\n}\n\nconst scenarioListSchema = {\n type: 'object',\n properties: {\n statuses: {\n type: 'array',\n items: { type: 'string', enum: [...STATUSES] },\n description: 'Keep only scenarios with any of these statuses.',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Keep only scenarios carrying any of these tags.',\n },\n sourceFiles: {\n type: 'array',\n items: { type: 'string' },\n description: 'Keep only scenarios whose source file path contains any of these.',\n },\n },\n} as const;\n\n/**\n * `readOnlyHint` keeps the reads out of any confirmation flow.\n * `untrustedContentHint` is the one that matters: scenario titles, step text and\n * assertion messages are written in someone's test suite, and a report can carry\n * whatever a fixture put there. It is data for the model to read about, never\n * instructions for it to follow.\n */\nconst READ_ONLY = { readOnlyHint: true, untrustedContentHint: true } as const;\n\nexport function reportTools(deps: ReportToolsDeps): Record<string, ToolDef> {\n const { report, setView, onAgentFilter } = deps;\n const now = deps.now ?? Date.now;\n const provenance = (): WithRun => ({ run: runProvenance(report, now()) });\n\n const list = (filters: ScenarioFilters) => {\n const scenarios = listScenarioSummaries(report, filters);\n return { ...provenance(), total: scenarios.length, scenarios };\n };\n\n return {\n list_scenarios: {\n title: 'List scenarios',\n description:\n 'List the behaviour scenarios in this report, optionally filtered by status, tag, or source file. Returns each scenario with its steps, tags, timing and failure message.',\n annotations: READ_ONLY,\n input: scenarioListSchema,\n execute: (input) =>\n guarded(() => {\n const args = asRecord(input);\n const filters: ScenarioFilters = {};\n const statuses = readStatuses(args);\n const tags = readStringArray(args, 'tags');\n const sourceFiles = readStringArray(args, 'sourceFiles');\n if (statuses) filters.statuses = statuses;\n if (tags) filters.tags = tags;\n if (sourceFiles) filters.sourceFiles = sourceFiles;\n return list(filters);\n }),\n },\n\n get_failing_scenarios: {\n title: 'Get failing scenarios',\n description:\n 'List only the scenarios that failed in this run, each with the step that failed and its error message. Use this first when asked what is broken.',\n annotations: READ_ONLY,\n execute: () => list({ statuses: ['failed'] }),\n },\n\n get_feature_summary: {\n title: 'Get feature summary',\n description:\n 'Summarise each feature in the report with its scenario counts by status. Use this for \"how are we doing\" questions rather than listing every scenario.',\n annotations: READ_ONLY,\n execute: () => ({\n ...provenance(),\n summary: report.summary,\n features: getFeatureSummary(report),\n }),\n },\n\n get_scenario: {\n title: 'Get scenario',\n description:\n 'Get one scenario by its id or its exact title, with every step and any failure detail. Attachment and document bodies are omitted — `docKinds` names what the page shows.',\n annotations: READ_ONLY,\n input: {\n type: 'object',\n properties: {\n idOrTitle: {\n type: 'string',\n description: 'The scenario id, or its exact title as shown in the report.',\n },\n },\n required: ['idOrTitle'],\n },\n execute: (input) =>\n guarded(() => {\n const idOrTitle = readString(asRecord(input), 'idOrTitle') ?? '';\n const found = getScenario(report, idOrTitle);\n if (!found) {\n return {\n ...provenance(),\n error: `No scenario found with id or title \"${idOrTitle}\". Call list_scenarios to see what this report contains.`,\n };\n }\n return {\n ...provenance(),\n feature: {\n id: found.feature.id,\n title: found.feature.title,\n sourceFile: found.feature.sourceFile,\n },\n // The summary projection, not the raw scenario: doc entry bodies and\n // base64 attachments are unbounded, and this payload goes straight\n // into a model's context window.\n scenario: toScenarioSummary(found.feature, found.scenario),\n };\n }),\n },\n\n filter_scenarios: {\n title: 'Filter the report',\n description:\n 'Change what the reader is looking at: set the report\\'s search text, status filter and tag filter. Omitted fields are left as they are; pass an empty string, \"all\", or an empty array to clear one.',\n input: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description:\n 'Free text matched against scenario titles, tags and step text. Empty string clears it.',\n },\n status: {\n type: 'string',\n enum: [...VIEW_STATUSES],\n description: 'Show only scenarios with this status. \"all\" clears the filter.',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Show only scenarios carrying any of these tags. Empty array clears the filter.',\n },\n },\n },\n execute: (input) =>\n guarded(() => {\n const args = asRecord(input);\n const search = readString(args, 'search');\n const status = readEnum(args, 'status', VIEW_STATUSES);\n const tags = readStringArray(args, 'tags');\n\n const applied = {\n search: search ?? deps.view.query,\n status: status ?? deps.view.status,\n tags: tags ?? deps.view.tags,\n };\n\n const patch: Partial<ReportUrlState> = {};\n if (search !== undefined) patch.query = search;\n if (status !== undefined) patch.status = status;\n if (tags !== undefined) patch.tags = tags;\n setView(patch);\n\n // Counted with the same function the list itself renders through, so\n // the number the agent reports back cannot disagree with the screen.\n const matched = filterReport(report, {\n query: applied.search,\n status: applied.status as StatusFilter,\n tags: applied.tags,\n }).summary.total;\n\n const result: AppliedFilter = {\n ...applied,\n matched,\n total: report.summary.total,\n };\n onAgentFilter?.(result);\n return { ...provenance(), applied: result };\n }),\n },\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\nimport type { Result } from \"../result\";\nimport { ReportInteractive } from \"./ReportInteractive\";\nimport { buildIslandRenderers } from \"./island-renderers\";\n\nexport interface ReportInteractiveIslandProps {\n report: StoryReport | Result<StoryReport>;\n title?: string;\n className?: string;\n hideHeader?: boolean;\n /** Drop the in-content scenario TOC sidebar (host provides scenario nav). */\n hideToc?: boolean;\n /** Render code blocks with CDN highlight.js (default true). */\n syntaxHighlighting?: boolean;\n /** Render `story.mermaid(...)` blocks as CDN-loaded SVG diagrams (default true). */\n mermaid?: boolean;\n}\n\n/**\n * Self-contained interactive island for host frameworks that hydrate this as a\n * client island (e.g. Astro `<ReportInteractiveIsland client:load/>`).\n *\n * Frameworks like Astro serialize island props as JSON, so they CANNOT pass the\n * `renderers` functions to <ReportInteractive> directly — which is why a host\n * would otherwise fall back to a separate post-hydration script that mutates the\n * island's DOM (and gets clobbered when the island re-renders). This wrapper\n * builds the React-OWNED highlighting + mermaid renderers internally, so the\n * enhancements live inside the React tree and survive every re-render. The\n * heavy libraries load from a CDN at runtime, so the host bundle stays lean.\n */\nexport function ReportInteractiveIsland({\n report,\n title,\n className,\n hideHeader,\n hideToc,\n syntaxHighlighting = true,\n mermaid = true,\n}: ReportInteractiveIslandProps) {\n const renderers = useMemo(\n () => buildIslandRenderers({ syntaxHighlighting, mermaid }),\n [syntaxHighlighting, mermaid],\n );\n return (\n <ReportInteractive\n report={report}\n title={title}\n className={className}\n hideHeader={hideHeader}\n hideToc={hideToc}\n renderers={renderers}\n />\n );\n}\n","\"use client\";\n\n/**\n * Built-in renderer overrides for the standalone report island.\n *\n * The static HTML emits readable `<pre data-mermaid>` / `<pre><code>` fallbacks.\n * When the interactive island takes over (createRoot), it OWNS that DOM and will\n * clobber any externally-applied highlight spans / detach mermaid's injected SVG\n * on its next render. So highlighting + mermaid must live INSIDE the React tree\n * (rendered into state, owned by React) rather than as post-processing scripts\n * mutating island-managed nodes. These renderers do exactly that, loading the\n * heavy libraries from a CDN at runtime so they never bloat the inlined island.\n */\n\nimport { createElement, useEffect, useState } from \"react\";\nimport type { ReportDocCode } from \"executable-stories-core\";\nimport { MermaidView, type MermaidApi } from \"../components/doc/MermaidView\";\nimport { CodeFigure } from \"../components/doc/DocCode\";\nimport type { BuiltinRenderers } from \"../renderers\";\nimport { cn } from \"../lib/utils\";\n\n// CDN URLs mirror ssr-entry's cdnAssets so the standalone report stays\n// version-pinned and works offline-degraded (falls back to the readable source).\nconst HLJS_ESM = \"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js\";\nconst MERMAID_ESM = \"https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs\";\n\n/**\n * Import a module from a CDN URL once, caching the promise. The URL is passed as\n * a variable so it stays opaque to the bundler — the heavy library is loaded at\n * runtime, never inlined into the island. `default ?? namespace` tolerates both\n * default and namespace CDN builds.\n */\nfunction cachedCdnModule<T>(url: string): () => Promise<T> {\n let loader: Promise<T> | undefined;\n return () => {\n // Intentional runtime dynamic import of a CDN URL (not bundled into the island).\n // eslint-disable-next-line no-restricted-syntax\n loader ??= import(/* @vite-ignore */ /* webpackIgnore: true */ url).then((m) => (m.default ?? m) as T);\n return loader;\n };\n}\n\nconst loadMermaidFromCdn = cachedCdnModule<MermaidApi>(MERMAID_ESM);\n\ninterface Hljs {\n highlight(code: string, opts: { language: string; ignoreIllegals?: boolean }): { value: string };\n highlightAuto(code: string): { value: string };\n getLanguage(name: string): unknown;\n}\nconst loadHljs = cachedCdnModule<Hljs>(HLJS_ESM);\n\n/**\n * Code block whose syntax highlighting is produced by highlight.js loaded from\n * the CDN, rendered into React-owned markup via state. Falls back to the plain\n * (escaped) source before load and on any failure.\n */\nfunction CdnHighlightedCode({ entry }: { entry: ReportDocCode }) {\n const [html, setHtml] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n try {\n const hljs = await loadHljs();\n const lang = entry.lang && hljs.getLanguage(entry.lang) ? entry.lang : undefined;\n const result = lang\n ? hljs.highlight(entry.content, { language: lang, ignoreIllegals: true })\n : hljs.highlightAuto(entry.content);\n if (!cancelled) setHtml(result.value);\n } catch {\n if (!cancelled) setHtml(null);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [entry.content, entry.lang]);\n\n return (\n <CodeFigure label={entry.label}>\n {html !== null ? (\n <code\n className={cn(\"hljs font-mono text-xs\", entry.lang && `language-${entry.lang}`)}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n ) : (\n <code className={cn(\"font-mono text-xs\", entry.lang && `language-${entry.lang}`)}>{entry.content}</code>\n )}\n </CodeFigure>\n );\n}\n\nexport interface IslandRendererOptions {\n syntaxHighlighting: boolean;\n mermaid: boolean;\n}\n\n/**\n * Build the BuiltinRenderers map the island passes to <ReportInteractive>.\n * Created once at mount so the renderer functions stay referentially stable.\n */\nexport function buildIslandRenderers(opts: IslandRendererOptions): BuiltinRenderers {\n const renderers: BuiltinRenderers = {};\n if (opts.mermaid) {\n renderers.mermaid = (entry) => createElement(MermaidView, { entry, load: loadMermaidFromCdn });\n }\n if (opts.syntaxHighlighting) {\n renderers.code = (entry) => createElement(CdnHighlightedCode, { entry });\n }\n return renderers;\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { ReportDocMermaid } from \"executable-stories-core\";\nimport { MermaidSource } from \"./DocMermaid\";\n\nexport type MermaidApi = typeof import(\"mermaid\").default;\nexport type MermaidLoader = () => Promise<MermaidApi>;\n\nfunction prefersDark(el: HTMLElement | null): boolean {\n const themed = el?.closest<HTMLElement>(\"[data-theme]\");\n if (themed?.dataset.theme === \"dark\") return true;\n if (themed?.dataset.theme === \"light\") return false;\n return typeof window !== \"undefined\" && !!window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches;\n}\n\n/**\n * Presentational mermaid renderer with the loader INJECTED — it contains no\n * literal `import(\"mermaid\")`, so a bundler following this module never pulls\n * mermaid in. `MermaidDiagram` wraps this with the installed-package loader;\n * the standalone report island wraps it with a CDN loader so the heavy library\n * never bloats the inlined island bundle.\n *\n * Draws the diagram to inline SVG (React-owned via state, so an island\n * re-render can't clobber it), redraws when the report's `data-theme` flips,\n * and falls back to `<MermaidSource>` (the readable, agent-friendly code) on\n * the server, before load, and on any error.\n */\nexport function MermaidView({ entry, load }: { entry: ReportDocMermaid; load: MermaidLoader }) {\n const ref = useRef<HTMLElement>(null);\n const [svg, setSvg] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n const draw = async () => {\n let mermaid: MermaidApi;\n try {\n mermaid = await load();\n } catch {\n // No library (offline, blocked CDN). Not the diagram's fault, so keep\n // the quiet source fallback rather than accusing the author.\n if (!cancelled) {\n setSvg(null);\n setError(null);\n }\n return;\n }\n try {\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: \"strict\",\n theme: prefersDark(ref.current) ? \"dark\" : \"default\",\n });\n // mermaid.parse is the library's own syntax check. Running it first\n // turns a broken diagram into a message naming the problem, and keeps\n // mermaid from injecting its own error graphic into the document.\n await mermaid.parse(entry.code);\n const id = `es-mermaid-${Math.random().toString(36).slice(2)}`;\n const { svg: rendered } = await mermaid.render(id, entry.code);\n if (!cancelled) {\n setSvg(rendered);\n setError(null);\n }\n } catch (err) {\n if (!cancelled) {\n setSvg(null);\n setError(err instanceof Error ? err.message : String(err));\n }\n }\n };\n void draw();\n\n // Redraw when the report toggles theme on an ancestor.\n const themed = ref.current?.closest<HTMLElement>(\"[data-theme]\");\n const observer = themed ? new MutationObserver(() => void draw()) : undefined;\n observer?.observe(themed!, { attributes: true, attributeFilter: [\"data-theme\"] });\n\n return () => {\n cancelled = true;\n observer?.disconnect();\n };\n }, [entry.code, load]);\n\n if (svg) {\n return (\n <figure ref={ref} className=\"my-3\">\n {entry.title ? (\n <figcaption className=\"mb-1.5 text-xs font-medium text-muted-foreground\">{entry.title}</figcaption>\n ) : null}\n {/* role=\"img\" presents the diagram as a single labelled graphic. */}\n <div\n role=\"img\"\n aria-label={entry.title ?? \"Mermaid diagram\"}\n className=\"overflow-x-auto rounded-md border border-border bg-card p-3 [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full\"\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n </figure>\n );\n }\n\n // Pre-render / fallback: the readable source. The ref lets the effect locate\n // the themed ancestor from the same DOM position before the SVG swaps in.\n // A syntax error shows above it, because a diagram that silently degrades to\n // a code block is a diagram nobody ever fixes.\n return (\n <>\n {error ? (\n <p\n role=\"alert\"\n data-es-mermaid-error\n className=\"mt-3 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive\"\n >\n Diagram failed to render: {error}\n </p>\n ) : null}\n <MermaidSource entry={entry} ref={ref} />\n </>\n );\n}\n"],"mappings":"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","names":["useCallback","useId","useMemo","useRef","useState","jsx","formatDuration","jsx","jsx","cva","cva","jsx","jsx","useContext","useContext","jsx","jsxs","jsx","jsxs","jsx","Fragment","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","Fragment","jsx","jsxs","jsx","Fragment","jsx","jsx","jsxs","isLocalFsPath","safeImageUrl","jsx","jsxs","isLocalFsPath","safeImageUrl","Fragment","jsx","jsxs","formatDuration","jsx","jsxs","formatDuration","createContext","useContext","Fragment","jsx","jsxs","createContext","useContext","jsxs","createContext","useContext","useState","createContext","useContext","jsx","jsx","jsx","jsxs","jsx","jsxs","formatDuration","Fragment","jsx","jsx","jsxs","Fragment","jsx","jsxs","jsx","formatDuration","jsx","jsxs","formatDuration","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsx","React","cva","jsx","cva","jsx","jsxs","safeStringify","jsx","EMPTY_RENDERERS","Fragment","jsx","jsxs","useCallback","jsx","jsxs","useCallback","useState","jsx","jsxs","useState","useEffect","useState","Fragment","jsx","jsxs","useState","useEffect","Fragment","jsx","jsxs","jsx","jsx","jsxs","ReportSearch","useEffect","useState","cva","useRender","cva","useRender","Fragment","jsx","jsxs","useState","useEffect","useEffect","useState","Fragment","jsx","jsxs","MAX_LINKS","ScenarioLinks","useState","useEffect","useEffect","useRef","jsx","jsxs","useRef","useEffect","useEffect","useMemo","useState","jsx","jsxs","useState","useMemo","useEffect","useState","jsx","jsxs","useState","useEffect","useRef","useRef","useEffect","useEffect","useRef","useCallback","useEffect","useState","KEY","useCallback","useEffect","useRef","useState","useState","useRef","useEffect","useCallback","STATUSES","Fragment","jsx","jsxs","useCallback","useState","useRef","useId","useMemo","useMemo","useEffect","useState","useEffect","useRef","useState","Fragment","jsx","jsxs","useRef","useState","useEffect","jsx","useState","useEffect","jsx","useMemo"]}
1
+ {"version":3,"sources":["../src/interactive/ReportInteractive.tsx","../src/components/ui/empty.tsx","../src/lib/utils.ts","../src/components/ReportEmpty.tsx","../src/hooks/useReport.ts","../src/context/ReportContext.ts","../src/components/ReportScenario.tsx","../src/lib/step-params.tsx","../src/components/ReportSteps.tsx","../src/components/doc/DocNote.tsx","../src/components/ui/badge.tsx","../src/components/doc/DocTag.tsx","../src/components/doc/DocKv.tsx","../src/hooks/useRenderers.ts","../src/components/doc/DocCode.tsx","../src/components/doc/DocTable.tsx","../src/components/doc/DocLink.tsx","../src/lib/markdown.ts","../src/lib/url.ts","../src/components/doc/DocSection.tsx","../src/components/doc/DocMermaid.tsx","../src/components/doc/DocScreenshot.tsx","../src/components/doc/DocVideo.tsx","../src/components/doc/DocHtml.tsx","../src/components/doc/DocState.tsx","../src/components/doc/DocCustom.tsx","../src/components/doc/DocEntry.tsx","../src/components/ReportDocEntries.tsx","../src/components/ReportStoryboard.tsx","../src/components/ReportAttachments.tsx","../src/components/ReportTrace.tsx","../src/lib/trace.ts","../src/interactive/scenario-history-context.ts","../src/lib/run-history.ts","../src/components/ScenarioRunHistory.tsx","../src/components/ScenarioStaleness.tsx","../src/lib/provenance.ts","../src/interactive/scenario-freshness-context.tsx","../src/interactive/collapse-context.ts","../src/interactive/scenario-actions.tsx","../src/components/ui/card.tsx","../src/components/ui/dropdown-menu.tsx","../src/components/ReportScenarioList.tsx","../src/components/ReportFeatureIntro.tsx","../src/components/ReportFeature.tsx","../src/components/ReportFeatureList.tsx","../src/components/ReportMeta.tsx","../src/components/ReportSummary.tsx","../src/components/ReportSchemaError.tsx","../src/components/ReportShell.tsx","../src/components/ReportSpanGraph.tsx","../src/components/ui/switch.tsx","../src/components/ui/toggle-group.tsx","../src/context/ReportRoot.tsx","../src/components/doc/NarrativeBlocks.tsx","../src/lib/hash-state.ts","../src/lib/scroll.ts","../src/result.ts","../src/interactive/filter.ts","../src/interactive/ReportAgentFilterNotice.tsx","../src/interactive/ReportFailureBanner.tsx","../src/interactive/ReportFilters.tsx","../src/interactive/ReportFreshness.tsx","../src/interactive/ReportLastRunDelta.tsx","../src/interactive/ReportSearch.tsx","../src/components/ui/input.tsx","../src/interactive/ReportShare.tsx","../src/components/ui/button.tsx","../src/interactive/ReportSinceLastVisit.tsx","../src/interactive/last-visit.ts","../src/interactive/ReportShortcutsHelp.tsx","../src/interactive/ReportToc.tsx","../src/interactive/ReportTocDrawer.tsx","../src/interactive/triage-default.ts","../src/interactive/use-deep-link-scroll.ts","../src/interactive/use-keyboard-shortcuts.ts","../src/interactive/use-theme.ts","../src/interactive/use-url-state.ts","../src/interactive/webmcp-tools.ts","../src/interactive/ReportInteractiveIsland.tsx","../src/interactive/island-renderers.tsx","../src/components/doc/MermaidView.tsx"],"sourcesContent":["'use client';\n\nimport type { StoryReport } from 'executable-stories-core';\nimport { Monitor, Moon, Sun } from 'lucide-react';\nimport { useTools } from 'webmcpable/react';\nimport {\n useCallback,\n useDeferredValue,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { ReportEmpty } from '../components/ReportEmpty';\nimport { ReportFeatureList } from '../components/ReportFeatureList';\nimport { ReportMeta } from '../components/ReportMeta';\nimport { ReportErrorShell } from '../components/ReportShell';\nimport { ReportSpanGraph } from '../components/ReportSpanGraph';\nimport { ReportSummary } from '../components/ReportSummary';\nimport { Switch } from '../components/ui/switch';\nimport { ToggleGroup, ToggleGroupItem } from '../components/ui/toggle-group';\nimport { ReportRoot } from '../context/ReportRoot';\nimport { reportLastRunMs } from '../lib/provenance';\nimport type { ScenarioHistoryMap } from '../lib/run-history';\nimport { scrollToScenarioId } from '../lib/scroll';\nimport { cn } from '../lib/utils';\nimport type { BuiltinRenderers, CustomRenderers } from '../renderers';\nimport type { Result } from '../result';\nimport { unwrapReport } from '../result';\nimport {\n CollapseProvider,\n useCollapseState,\n type CollapseApi,\n} from './collapse-context';\nimport {\n allTags,\n failedScenarios,\n filterReport,\n listFailures,\n type StatusFilter,\n} from './filter';\nimport { ReportAgentFilterNotice } from './ReportAgentFilterNotice';\nimport { ReportFailureBanner } from './ReportFailureBanner';\nimport { ReportFilters } from './ReportFilters';\nimport { ReportFreshness } from './ReportFreshness';\nimport { ReportLastRunDelta } from './ReportLastRunDelta';\nimport { ReportSearch } from './ReportSearch';\nimport { ReportShare } from './ReportShare';\nimport { ReportSinceLastVisit } from './ReportSinceLastVisit';\nimport { ReportShortcutsHelp } from './ReportShortcutsHelp';\nimport { ReportToc } from './ReportToc';\nimport { ReportTocDrawer } from './ReportTocDrawer';\nimport {\n failuresToPrompt,\n ScenarioActionsProvider,\n scenarioPermalink,\n scenarioToMarkdown,\n scenarioToPrompt,\n type ScenarioActions,\n} from './scenario-actions';\nimport { ScenarioFreshnessProvider } from './scenario-freshness-context';\nimport { ScenarioHistoryProvider } from './scenario-history-context';\nimport { defaultCollapsedIds, failuresFirst } from './triage-default';\nimport { useDeepLinkScroll } from './use-deep-link-scroll';\nimport { useKeyboardShortcuts } from './use-keyboard-shortcuts';\nimport { useTheme, type ThemePref } from './use-theme';\nimport { useUrlState } from './use-url-state';\nimport { reportTools, type AppliedFilter } from './webmcp-tools';\n\nexport interface ReportInteractiveProps {\n /** A StoryReport, or a Result-wrapped one (e.g., from parseStoryReport). */\n report: StoryReport | Result<StoryReport>;\n /** Renderers keyed by `story.custom({ type })` strings. */\n customRenderers?: CustomRenderers;\n /** Optional overrides for the heavy built-ins (mermaid, code, section). */\n renderers?: BuiltinRenderers;\n className?: string;\n title?: string;\n dataTheme?: 'light' | 'dark';\n /**\n * Drop the report's own title block (`<h1>` + summary + meta) while keeping\n * the search and filter controls. Use when the surrounding page already shows\n * the report title as its heading — e.g. the Astro stories index embedded in\n * Starlight, where Starlight renders the page `<h1>`.\n */\n hideHeader?: boolean;\n /**\n * Drop the report's in-content scenario table-of-contents sidebar and render\n * the scenarios full-width. Use when the surrounding page already provides\n * scenario navigation — e.g. the Astro stories index, where the feature/\n * scenario tree lives in Starlight's own sidebar. Avoids a second nav rail.\n */\n hideToc?: boolean;\n /**\n * Days before the report is flagged as stale (warning banner instead of the\n * \"Verified N ago\" line). 0 disables the stale warning. Default 7.\n */\n staleAfterDays?: number;\n /**\n * Recent run events per scenario id (from the CLI's --history-file store).\n * When present, scenario cards show a run-over-run timeline strip.\n */\n scenarioHistory?: ScenarioHistoryMap;\n /** Show the Share button in the header (default false). `--html-share` turns it on. */\n share?: boolean;\n /**\n * Draw the \"Architecture, as it ran\" section (default false). Only an\n * instrumented suite has anything to draw, and the span picture is a\n * specialist view. `--html-architecture` turns it on.\n */\n architecture?: boolean;\n /** Command the share dialog hands over. Default: `npx executable-stories share reports/`. */\n shareCommand?: string;\n}\n\nexport function ReportInteractive(props: ReportInteractiveProps) {\n const { report, className, title, dataTheme } = props;\n const result = unwrapReport(report);\n if (!result.ok) {\n return (\n <ReportErrorShell\n error={result.error}\n className={className}\n title={title}\n dataTheme={dataTheme}\n />\n );\n }\n return <ReportInteractiveView {...props} report={result.data} />;\n}\n\ninterface ReportInteractiveViewProps extends Omit<\n ReportInteractiveProps,\n 'report'\n> {\n report: StoryReport;\n}\n\nconst THEME_OPTIONS: { value: ThemePref; label: string; Icon: typeof Sun }[] = [\n { value: 'light', label: 'Light', Icon: Sun },\n { value: 'system', label: 'System', Icon: Monitor },\n { value: 'dark', label: 'Dark', Icon: Moon },\n];\n\n// Light / System / Dark as an icon segmented control, matching the view-mode one.\nfunction ThemeSegment({\n pref,\n onPref,\n}: {\n pref: ThemePref;\n onPref: (p: ThemePref) => void;\n}) {\n return (\n <ToggleGroup\n size=\"sm\"\n value={[pref]}\n onValueChange={(v) => {\n const next = v[0] as ThemePref | undefined;\n if (next) onPref(next);\n }}\n aria-label=\"Color theme\"\n >\n {THEME_OPTIONS.map(({ value, label, Icon }) => (\n <ToggleGroupItem\n key={value}\n value={value}\n aria-label={label}\n title={label}\n className=\"px-2\"\n >\n <Icon />\n </ToggleGroupItem>\n ))}\n </ToggleGroup>\n );\n}\n\nfunction ReportInteractiveView({\n report,\n customRenderers,\n renderers,\n className,\n title,\n dataTheme,\n hideHeader = false,\n hideToc = false,\n staleAfterDays = 7,\n scenarioHistory,\n share = false,\n architecture = false,\n shareCommand,\n}: ReportInteractiveViewProps) {\n // Search, status, tags and detail live in the URL fragment, so a filtered\n // view survives a refresh and can be pasted to someone else.\n const [urlState, setUrlState] = useUrlState();\n const { query, status: statusFilter, tags: activeTags, detail } = urlState;\n const setQuery = useCallback(\n (next: string) => setUrlState({ query: next }),\n [setUrlState],\n );\n const setStatusFilter = useCallback(\n (next: StatusFilter) => setUrlState({ status: next }),\n [setUrlState],\n );\n const setDetail = useCallback(\n (next: 'full' | 'minimal') => setUrlState({ detail: next }),\n [setUrlState],\n );\n const [helpOpen, setHelpOpen] = useState(false);\n const { pref: themePref, setPref: setThemePref } = useTheme();\n const searchRef = useRef<HTMLInputElement>(null);\n const expandId = useId();\n const docsId = useId();\n // Defer filtering off the live input value so typing stays responsive even\n // when the report is large — the input updates immediately, the filtered\n // tree catches up. (Vercel rerender-use-deferred-value.)\n const deferredQuery = useDeferredValue(query);\n const failures = useMemo(() => listFailures(report), [report]);\n const filtered = useMemo(\n // Features carrying failures float to the top so the first thing on screen\n // is the thing that needs attention; an all-green run keeps source order.\n () =>\n failuresFirst(\n filterReport(report, {\n query: deferredQuery,\n status: statusFilter,\n tags: activeTags,\n }),\n ),\n [report, deferredQuery, statusFilter, activeTags],\n );\n const isFiltering = query !== deferredQuery;\n\n const statusOptions = useMemo(() => {\n const s = report.summary;\n const opts: Array<{ key: StatusFilter; label: string; count: number }> = [\n { key: 'all', label: 'All', count: s.total },\n ];\n if (s.passed)\n opts.push({ key: 'passed', label: 'Passed', count: s.passed });\n if (s.failed)\n opts.push({ key: 'failed', label: 'Failed', count: s.failed });\n if (s.skipped)\n opts.push({ key: 'skipped', label: 'Skipped', count: s.skipped });\n if (s.pending)\n opts.push({ key: 'pending', label: 'Pending', count: s.pending });\n return opts;\n }, [report]);\n const tagOptions = useMemo(() => allTags(report), [report]);\n const toggleTag = useCallback(\n (tag: string) =>\n setUrlState({\n tags: activeTags.includes(tag)\n ? activeTags.filter((t) => t !== tag)\n : [...activeTags, tag],\n }),\n [activeTags, setUrlState],\n );\n\n const [toast, setToast] = useState<string | null>(null);\n const toastTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const showToast = useCallback((msg: string) => {\n setToast(msg);\n if (toastTimer.current) clearTimeout(toastTimer.current);\n toastTimer.current = setTimeout(() => setToast(null), 1800);\n }, []);\n const copy = useCallback(\n (text: string, msg: string) => {\n if (typeof navigator !== 'undefined' && navigator.clipboard) {\n navigator.clipboard.writeText(text).then(\n () => showToast(msg),\n () => showToast('Copy failed'),\n );\n }\n },\n [showToast],\n );\n const scenarioActions = useMemo<ScenarioActions>(\n () => ({\n copyLink: (s) => copy(scenarioPermalink(s), 'Link copied'),\n copyMarkdown: (s) => copy(scenarioToMarkdown(s), 'Markdown copied'),\n copyPrompt: (s) => copy(scenarioToPrompt(s), 'Prompt copied'),\n }),\n [copy],\n );\n const copyAllFailures = useCallback(\n () => copy(failuresToPrompt(failedScenarios(filtered)), 'Failures copied'),\n [copy, filtered],\n );\n const failureIndexRef = useRef(0);\n\n const allCollapsibleIds = useMemo(\n () =>\n report.features.flatMap((f) => [f.id, ...f.scenarios.map((s) => s.id)]),\n [report],\n );\n // On a run WITH failures the report opens as a triage surface: passing work\n // collapsed to titles, failures expanded (see defaultCollapsedIds). An\n // all-green run collapses nothing. Either way a persisted collapse set from a\n // previous visit wins, so this only ever seeds a first visit.\n const collapse = useCollapseState(\n useCallback(() => defaultCollapsedIds(report), [report]),\n );\n // Filtering is a temporary lens over the report, not a change to the user's\n // persisted collapse preferences. Always reveal matching features/scenarios\n // while a filter is active, then restore the previous collapse state when it\n // is cleared. Otherwise search can report a match that remains hidden inside\n // a triage-collapsed feature.\n const revealFilteredResults =\n deferredQuery.trim() !== '' ||\n statusFilter !== 'all' ||\n activeTags.length > 0;\n const visibleCollapse = useMemo<CollapseApi>(\n () =>\n revealFilteredResults\n ? { ...collapse.api, isCollapsed: () => false }\n : collapse.api,\n [collapse.api, revealFilteredResults],\n );\n const collapseAll = useCallback(\n () => collapse.collapseAll(allCollapsibleIds),\n [collapse, allCollapsibleIds],\n );\n // \"Expand all\" is a single binary: checked → every scenario open, unchecked →\n // all collapsed to titles. Starts unchecked on a failing run so the control\n // matches the triage default above rather than contradicting it.\n // (Per-scenario toggles may drift from this; harmless.)\n const [expandedAll, setExpandedAll] = useState<boolean>(\n () => report.summary.failed === 0,\n );\n const setExpanded = useCallback(\n (expanded: boolean) => {\n if (expanded) collapse.expandAll();\n else collapseAll();\n setExpandedAll(expanded);\n },\n [collapse, collapseAll],\n );\n\n // WebMCP: hand a browser agent the same four reads the MCP server exposes,\n // plus one tool that drives this view. A no-op in every browser without\n // `document.modelContext`, which is all of them outside flagged Chrome/Edge.\n const [agentFilter, setAgentFilter] = useState<AppliedFilter | null>(null);\n useTools(\n reportTools({\n report,\n view: urlState,\n setView: setUrlState,\n onAgentFilter: setAgentFilter,\n }),\n );\n // The notice belongs to the filter it announced. The moment the view no\n // longer matches — the reader typed, cleared a tag, hit reset — it is stale,\n // so it stops rendering without anything having to clear it.\n const showAgentFilter =\n agentFilter !== null &&\n agentFilter.search === query &&\n agentFilter.status === statusFilter &&\n agentFilter.tags.length === activeTags.length &&\n agentFilter.tags.every((tag) => activeTags.includes(tag));\n const clearFilters = useCallback(\n () => setUrlState({ query: '', status: 'all', tags: [] }),\n [setUrlState],\n );\n\n const focusSearch = useCallback(() => {\n searchRef.current?.focus();\n }, []);\n\n const stepFailure = useCallback(\n (direction: 1 | -1) => {\n if (failures.length === 0) return;\n failureIndexRef.current =\n (failureIndexRef.current + direction + failures.length) %\n failures.length;\n const target = failures[failureIndexRef.current];\n if (target) scrollToScenarioId(target.scenarioId);\n },\n [failures],\n );\n\n const toggleHelp = useCallback(() => {\n setHelpOpen((v) => !v);\n }, []);\n\n const escape = useCallback(() => {\n if (helpOpen) setHelpOpen(false);\n else if (query !== '') setQuery('');\n }, [helpOpen, query, setQuery]);\n\n useKeyboardShortcuts({\n onFocusSearch: focusSearch,\n onNextFailure: () => stepFailure(1),\n onPrevFailure: () => stepFailure(-1),\n onToggleHelp: toggleHelp,\n onEscape: escape,\n onExpandAll: () => setExpanded(true),\n onCollapseAll: () => setExpanded(false),\n });\n\n useDeepLinkScroll();\n\n const hasContent = filtered.features.length > 0;\n const totalScenarios = report.summary.total;\n const matchedScenarios = filtered.summary.total;\n // The scenario TOC earns its rail only when there's enough to jump between.\n // For a sparse report (a few scenarios, e.g. a single Playwright story) the\n // rail is dead space that squashes the content — render full-width instead.\n // `hideToc` (host-provided nav, e.g. Astro/Starlight) always wins.\n const showToc = !hideToc && totalScenarios > 3;\n\n return (\n <CollapseProvider value={visibleCollapse}>\n <ScenarioActionsProvider value={scenarioActions}>\n <ScenarioHistoryProvider value={scenarioHistory ?? null}>\n <ScenarioFreshnessProvider value={{ staleAfterDays, report }}>\n <ReportRoot\n report={filtered}\n customRenderers={customRenderers}\n renderers={renderers}\n >\n <main\n className={cn('es-report', 'es-report-interactive', className)}\n aria-label={title ?? 'Test report'}\n aria-busy={isFiltering}\n data-theme={dataTheme}\n data-detail-level={detail}\n >\n <header className=\"es-report-header\">\n {/* Nav bar: title left, search right (search stays even when the\n host page owns the title — hideHeader). */}\n <div\n data-es-navbar\n className={cn(\n 'flex flex-wrap items-center gap-4',\n hideHeader ? 'justify-end' : 'justify-between',\n )}\n >\n {hideHeader ? null : (\n <h1 className=\"min-w-0\">{title ?? 'Story Report'}</h1>\n )}\n {/* Search + theme sit together in the top-right corner — theme is\n set-once global chrome, so it lives in the header, not down in\n the per-list view controls. */}\n <div className=\"flex items-center gap-2\">\n <ReportSearch\n ref={searchRef}\n value={query}\n onChange={setQuery}\n matchedCount={matchedScenarios}\n totalCount={totalScenarios}\n />\n {share ? (\n <ReportShare command={shareCommand} onCopy={copy} />\n ) : null}\n <ThemeSegment pref={themePref} onPref={setThemePref} />\n </div>\n </div>\n {hideHeader ? null : (\n <>\n <ReportSummary />\n <ReportMeta />\n </>\n )}\n {/* Opt-in (`architecture`), and outside `hideHeader`\n deliberately: that flag drops the duplicate title block\n for a page that renders its own <h1> (the Astro/Starlight\n docs site), and the architecture is content rather than\n title. Shows the whole run rather than the filtered view:\n a search narrows which scenarios you read, not which\n components the run exercised. */}\n {architecture ? <ReportSpanGraph /> : null}\n <ReportFreshness\n lastRunMs={reportLastRunMs(report)}\n ciUrl={report.ci?.url}\n staleAfterDays={staleAfterDays}\n />\n <ReportLastRunDelta\n history={scenarioHistory}\n report={report}\n />\n <ReportSinceLastVisit report={report} />\n\n {/* Filters first (what's shown: status, then tags)… */}\n <ReportFilters\n statuses={statusOptions}\n status={statusFilter}\n onStatus={setStatusFilter}\n tags={tagOptions}\n activeTags={activeTags}\n onToggleTag={toggleTag}\n />\n {/* …then the view controls (how it's shown), separated by a hairline\n so \"filter the data\" and \"change the view\" read as distinct.\n Switches, not checkboxes: these are immediate on/off view modes,\n which is what a switch signals. \"Show only failures\" is the\n Failed status filter's job, not a view mode. */}\n <div className=\"flex flex-wrap items-center gap-x-6 gap-y-2 border-t border-border/60 pt-3\">\n {/* Narrow-screen scenario nav (the sidebar is lg-only). */}\n {showToc ? <ReportTocDrawer /> : null}\n <div className=\"flex items-center gap-2\">\n <Switch\n id={expandId}\n checked={expandedAll}\n onCheckedChange={setExpanded}\n />\n <label\n htmlFor={expandId}\n className=\"cursor-pointer text-sm text-muted-foreground select-none\"\n >\n Expand all\n </label>\n </div>\n <div className=\"flex items-center gap-2\">\n <Switch\n id={docsId}\n checked={detail === 'full'}\n onCheckedChange={(checked) =>\n setDetail(checked ? 'full' : 'minimal')\n }\n />\n <label\n htmlFor={docsId}\n className=\"cursor-pointer text-sm text-muted-foreground select-none\"\n >\n Show documentation\n </label>\n </div>\n </div>\n </header>\n {showAgentFilter ? (\n <ReportAgentFilterNotice\n applied={agentFilter}\n onReset={clearFilters}\n onDismiss={() => setAgentFilter(null)}\n />\n ) : null}\n <ReportFailureBanner failures={failures} onCopyAll={copyAllFailures} />\n {hasContent ? (\n showToc ? (\n <div className=\"flex gap-6\">\n <ReportToc />\n <div className=\"flex min-w-0 flex-1 flex-col gap-4\">\n <ReportFeatureList />\n </div>\n </div>\n ) : (\n <div className=\"flex flex-col gap-4\">\n <ReportFeatureList />\n </div>\n )\n ) : (\n <ReportEmpty\n message={\n query ? 'No scenarios match the search.' : undefined\n }\n />\n )}\n {/* `?` is the shortcut (it is already Shift+/, so aria-keyshortcuts is\n just \"?\", not the malformed \"Shift+?\"). Character-based, so it\n works regardless of where ? sits on the user's keyboard layout. */}\n <button\n type=\"button\"\n className=\"es-shortcuts-trigger fixed right-4 bottom-4 z-40 flex size-9 items-center justify-center rounded-full border border-border bg-card text-muted-foreground shadow-sm transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50\"\n aria-label=\"Keyboard shortcuts\"\n aria-keyshortcuts=\"?\"\n onClick={toggleHelp}\n >\n ?\n </button>\n <ReportShortcutsHelp\n open={helpOpen}\n onClose={() => setHelpOpen(false)}\n />\n {toast ? (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"fixed bottom-4 left-1/2 -translate-x-1/2 rounded-md bg-foreground px-3 py-1.5 text-xs font-medium text-background shadow-lg\"\n >\n {toast}\n </div>\n ) : null}\n </main>\n </ReportRoot>\n </ScenarioFreshnessProvider>\n </ScenarioHistoryProvider>\n </ScenarioActionsProvider>\n </CollapseProvider>\n );\n}\n","import { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Empty({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty\"\n className={cn(\n \"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-header\"\n className={cn(\n \"flex max-w-sm flex-col items-center gap-2 text-center\",\n className\n )}\n {...props}\n />\n )\n}\n\nconst emptyMediaVariants = cva(\n \"mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0\",\n {\n variants: {\n variant: {\n default: \"bg-transparent\",\n icon: \"flex size-10 shrink-0 items-center justify-center rounded-lg bg-muted text-foreground [&_svg:not([class*='size-'])]:size-6\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction EmptyMedia({\n className,\n variant = \"default\",\n ...props\n}: React.ComponentProps<\"div\"> & VariantProps<typeof emptyMediaVariants>) {\n return (\n <div\n data-slot=\"empty-icon\"\n data-variant={variant}\n className={cn(emptyMediaVariants({ variant, className }))}\n {...props}\n />\n )\n}\n\nfunction EmptyTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-title\"\n className={cn(\"text-lg font-medium tracking-tight\", className)}\n {...props}\n />\n )\n}\n\nfunction EmptyDescription({ className, ...props }: React.ComponentProps<\"p\">) {\n return (\n <div\n data-slot=\"empty-description\"\n className={cn(\n \"text-sm/relaxed text-muted-foreground [&>a]:underline [&>a]:underline-offset-4 [&>a:hover]:text-primary\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction EmptyContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"empty-content\"\n className={cn(\n \"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport {\n Empty,\n EmptyHeader,\n EmptyTitle,\n EmptyDescription,\n EmptyContent,\n EmptyMedia,\n}\n","import { clsx, type ClassValue } from \"clsx\";\nimport { twMerge } from \"tailwind-merge\";\n\n/** Merge class names with Tailwind-aware conflict resolution (shadcn `cn`). */\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","import { Empty, EmptyHeader, EmptyTitle } from \"@/components/ui/empty\";\n\nexport interface ReportEmptyProps {\n message?: string;\n}\n\nexport function ReportEmpty({ message }: ReportEmptyProps) {\n return (\n <Empty aria-live=\"polite\" className=\"border\">\n <EmptyHeader>\n <EmptyTitle>{message ?? \"No scenarios in this report.\"}</EmptyTitle>\n </EmptyHeader>\n </Empty>\n );\n}\n","import { useContext } from \"react\";\nimport { ReportContext } from \"../context/ReportContext\";\n\nexport function useReport() {\n const ctx = useContext(ReportContext);\n if (!ctx) {\n throw new Error(\n \"useReport must be used inside <ReportRoot> or <Report>. Wrap your tree with one of those.\",\n );\n }\n return ctx.report;\n}\n","import { createContext } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\nimport type { BuiltinRenderers, CustomRenderers } from \"../renderers\";\n\nexport interface ReportContextValue {\n report: StoryReport;\n customRenderers: CustomRenderers;\n renderers: BuiltinRenderers;\n}\n\nexport const ReportContext = createContext<ReportContextValue | null>(null);\n","import type { ReportScenario as ReportScenarioT } from \"executable-stories-core\";\nimport { formatDuration } from \"executable-stories-core/utils/duration\";\nimport { ReportSteps } from \"./ReportSteps\";\nimport { ReportStoryboard } from \"./ReportStoryboard\";\nimport { ReportDocEntries } from \"./ReportDocEntries\";\nimport { ReportAttachments } from \"./ReportAttachments\";\nimport { ReportTrace } from \"./ReportTrace\";\nimport { ScenarioRunHistory } from \"./ScenarioRunHistory\";\nimport { ScenarioStaleness } from \"./ScenarioStaleness\";\nimport { useCollapse } from \"../interactive/collapse-context\";\nimport { useScenarioActions } from \"../interactive/scenario-actions\";\nimport { Card, CardContent, CardHeader } from \"@/components/ui/card\";\nimport { Badge } from \"@/components/ui/badge\";\nimport {\n DropdownMenu,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuTrigger,\n} from \"@/components/ui/dropdown-menu\";\nimport { LinkIcon, FileTextIcon, SparklesIcon, MoreHorizontalIcon } from \"lucide-react\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportScenarioProps {\n scenario: ReportScenarioT;\n /**\n * Omit the card's own title row (status badge + tags still render). Use when\n * the surrounding page already shows the scenario title as its heading — e.g.\n * the Astro detail page, where Starlight renders the title as the page `h1`.\n */\n hideTitle?: boolean;\n}\n\ntype Status = ReportScenarioT[\"status\"];\n\ninterface StatusMeta {\n label: string;\n glyph: string;\n glyphColor: string;\n badgeVariant: \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n /**\n * Whether to render the status as a visible pill. Passing scenarios drop it:\n * the green ✓ glyph + title already carry the status, so the pill would be\n * pure redundancy on every (usually passing) row, and dropping it keeps a\n * green run calm while the failure pill stays the one loud badge. A\n * non-showPill status still exposes an sr-only label for screen readers.\n */\n showPill: boolean;\n}\n\nconst STATUS_META: Record<Status, StatusMeta> = {\n passed: { label: \"Passed\", glyph: \"✓\", glyphColor: \"text-pass\", badgeVariant: \"passed\", showPill: false },\n failed: { label: \"Failed\", glyph: \"✗\", glyphColor: \"text-fail\", badgeVariant: \"failed\", showPill: true },\n skipped: { label: \"Skipped\", glyph: \"○\", glyphColor: \"text-skip\", badgeVariant: \"skipped\", showPill: true },\n pending: { label: \"Pending\", glyph: \"○\", glyphColor: \"text-pend\", badgeVariant: \"pending\", showPill: true },\n};\n\nexport function ReportScenario({ scenario, hideTitle = false }: ReportScenarioProps) {\n const titleId = `${scenario.id}-title`;\n const bodyId = `${scenario.id}-body`;\n const meta = STATUS_META[scenario.status];\n // A planned scenario (it.todo) is canonically \"pending\", but the reader\n // should see intent, not limbo.\n const label = scenario.planned ? \"Planned\" : meta.label;\n const collapse = useCollapse();\n const collapsible = collapse !== null && !hideTitle;\n const collapsed = collapsible ? collapse!.isCollapsed(scenario.id) : false;\n const actions = useScenarioActions();\n return (\n <Card\n id={scenario.id}\n data-status={scenario.status}\n {...(hideTitle\n ? { \"aria-label\": `${scenario.title}, ${label}` }\n : { \"aria-labelledby\": titleId })}\n className=\"gap-0 py-0\"\n >\n <CardHeader className=\"px-4 py-3\">\n <div\n className={cn(\n // Wraps rather than squeezing: on a phone the status/duration group\n // is ~160px, which leaves a title column a few characters wide.\n \"flex flex-wrap items-start gap-x-4 gap-y-1\",\n hideTitle ? \"justify-end\" : \"justify-between\",\n )}\n >\n {hideTitle ? null : (\n <h3 id={titleId} className=\"flex min-w-0 flex-1 basis-48 items-center gap-2 text-sm font-medium text-foreground\">\n {collapsible ? (\n <button\n type=\"button\"\n onClick={() => collapse!.toggle(scenario.id)}\n aria-expanded={!collapsed}\n aria-controls={bodyId}\n aria-label={`Toggle ${scenario.title}`}\n className=\"shrink-0 cursor-pointer text-muted-foreground hover:text-foreground\"\n >\n <span aria-hidden className={cn(\"inline-block text-xs transition-transform\", !collapsed && \"rotate-90\")}>▸</span>\n </button>\n ) : null}\n <span aria-hidden className={cn(\"text-sm leading-none\", meta.glyphColor)}>\n {meta.glyph}\n </span>\n <span>{scenario.title}</span>\n </h3>\n )}\n <div className=\"flex shrink-0 items-center gap-2\">\n <ScenarioRunHistory scenarioId={scenario.id} />\n <ScenarioStaleness scenario={scenario} />\n {scenario.durationMs > 0 ? (\n <span className=\"whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground\">\n {formatDuration(scenario.durationMs)}\n </span>\n ) : null}\n {meta.showPill ? (\n <Badge variant={meta.badgeVariant} aria-label={`Status: ${label}`}>\n {label}\n </Badge>\n ) : (\n <span className=\"sr-only\">{`Status: ${label}`}</span>\n )}\n {actions ? (\n <DropdownMenu>\n <DropdownMenuTrigger\n aria-label={`Actions for ${scenario.title}`}\n className=\"cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4\"\n >\n <MoreHorizontalIcon aria-hidden />\n </DropdownMenuTrigger>\n <DropdownMenuContent align=\"end\">\n <DropdownMenuItem onClick={() => actions.copyLink(scenario)}>\n <LinkIcon /> Copy link\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => actions.copyMarkdown(scenario)}>\n <FileTextIcon /> Copy as Markdown\n </DropdownMenuItem>\n <DropdownMenuItem onClick={() => actions.copyPrompt(scenario)}>\n <SparklesIcon /> Explain with AI\n </DropdownMenuItem>\n </DropdownMenuContent>\n </DropdownMenu>\n ) : null}\n </div>\n </div>\n {scenario.tags.length > 0 || (scenario.tickets?.length ?? 0) > 0 ? (\n <ul aria-label=\"Tags and tickets\" className=\"flex flex-wrap gap-1.5\">\n {scenario.tags.map((t) => (\n <li key={`tag-${t}`}>\n <Badge variant=\"tag\">{t}</Badge>\n </li>\n ))}\n {(scenario.tickets ?? []).map((ticket) => (\n <li key={`ticket-${ticket.id}`}>\n {ticket.url ? (\n <a href={ticket.url} target=\"_blank\" rel=\"noreferrer noopener\" className=\"inline-flex min-h-6 items-center\">\n <Badge variant=\"outline\">{ticket.id}</Badge>\n </a>\n ) : (\n <Badge variant=\"outline\">{ticket.id}</Badge>\n )}\n </li>\n ))}\n </ul>\n ) : null}\n </CardHeader>\n <CardContent id={bodyId} hidden={collapsed} className=\"px-4 pt-0 pb-4\">\n {scenario.errorMessage ? (\n <pre\n role=\"alert\"\n className=\"mb-1 overflow-x-auto rounded-md border border-fail-border bg-fail-bg px-4 py-3.5 font-mono text-xs leading-relaxed whitespace-pre-wrap text-fail\"\n >\n {scenario.errorMessage}\n </pre>\n ) : null}\n <ReportStoryboard scenario={scenario} />\n <ReportSteps scenario={scenario} />\n {scenario.docEntries.length > 0 ? (\n <div data-es-docs className=\"mt-3\">\n <ReportDocEntries entries={scenario.docEntries} />\n </div>\n ) : null}\n <ReportAttachments attachments={scenario.attachments} />\n <ReportTrace spans={scenario.otelSpans} />\n </CardContent>\n </Card>\n );\n}\n","import type { ReactNode } from \"react\";\n\n/**\n * Highlight step parameters (double-quoted strings, standalone numbers) in step\n * text — the React equivalent of the report's highlightStepParams. Returns a\n * node array so the matched params can be wrapped in a styled <span> without\n * dangerouslySetInnerHTML.\n *\n * Regex mirrors the string renderer exactly:\n * - `\"[^\"]*\"` double-quoted strings (numbers inside quotes stay part of the string)\n * - `(?<![\\w.-])\\d+(?:\\.\\d+)?(?![\\w.-])` standalone numbers, dot/word-boundary aware\n */\nconst STEP_PARAM_PATTERN = /\"[^\"]*\"|(?<![\\w.-])\\d+(?:\\.\\d+)?(?![\\w.-])/g;\n\nexport function highlightStepParams(text: string): ReactNode {\n const matches = Array.from(text.matchAll(STEP_PARAM_PATTERN));\n if (matches.length === 0) return text;\n\n const nodes: ReactNode[] = [];\n let lastIndex = 0;\n matches.forEach((match, i) => {\n const start = match.index;\n const end = start + match[0].length;\n if (start > lastIndex) nodes.push(text.slice(lastIndex, start));\n nodes.push(\n <span key={i} className=\"font-medium text-step-param italic\">\n {match[0]}\n </span>,\n );\n lastIndex = end;\n });\n if (lastIndex < text.length) nodes.push(text.slice(lastIndex));\n return nodes;\n}\n","import { highlightStepParams } from '@/lib/step-params';\nimport { cn } from '@/lib/utils';\nimport type { ReportScenario, ReportStep } from 'executable-stories-core';\nimport {\n assertionState,\n assertiveSteps,\n} from 'executable-stories-core/utils/assertive-steps';\nimport { formatDuration } from 'executable-stories-core/utils/duration';\nimport { ReportDocEntries } from './ReportDocEntries';\n\nexport interface ReportStepsProps {\n scenario: ReportScenario;\n}\n\nconst STEP_GLYPH: Record<string, string> = {\n passed: '✓',\n failed: '✗',\n skipped: '○',\n pending: '○',\n};\n\nconst STEP_GLYPH_COLOR: Record<string, string> = {\n passed: 'text-pass',\n failed: 'text-fail',\n skipped: 'text-skip',\n pending: 'text-pend',\n};\n\nexport function ReportSteps({ scenario }: ReportStepsProps) {\n if (scenario.steps.length === 0) return null;\n const unasserted = new Set(\n assertionState(scenario.steps) === 'unasserted'\n ? assertiveSteps(scenario.steps).map((step) => step.id)\n : [],\n );\n return (\n <ol data-slot=\"steps\" className=\"flex flex-col\">\n {scenario.steps.map((step) => (\n <ReportStepItem\n key={step.id}\n step={step}\n unasserted={unasserted.has(step.id)}\n />\n ))}\n </ol>\n );\n}\n\nexport function ReportStepItem({\n step,\n unasserted = false,\n}: {\n step: ReportStep;\n unasserted?: boolean;\n}) {\n // And/But (incl. auto-And repeats) read as continuations of the prior step —\n // indented with a muted keyword, matching the report's `.step.continuation`.\n const kw = step.keyword.toLowerCase();\n const continuation = kw === 'and' || kw === 'but';\n return (\n <li\n id={step.id}\n data-status={step.status}\n className={cn(\n 'py-1.5 text-[0.8125rem] leading-normal',\n continuation && 'pl-5',\n )}\n >\n <div className=\"flex items-baseline gap-2\">\n <span\n aria-hidden\n className={cn(\n 'w-4 shrink-0 text-center text-xs',\n STEP_GLYPH_COLOR[step.status],\n )}\n >\n {STEP_GLYPH[step.status] ?? '○'}\n </span>\n <span\n className={cn(\n 'min-w-[52px] shrink-0 font-mono text-xs font-semibold capitalize',\n continuation ? 'font-medium text-muted-foreground' : 'text-keyword',\n )}\n >\n {step.keyword}\n </span>\n <span className=\"flex-1 text-foreground\">\n {highlightStepParams(step.text)}\n </span>\n {unasserted ? (\n <span className=\"shrink-0 rounded-full border border-pend-border bg-pend-bg px-2 py-0.5 text-[0.6875rem] font-medium text-pend\">\n No assertion\n </span>\n ) : null}\n {step.durationMs > 0 ? (\n <span className=\"shrink-0 whitespace-nowrap font-mono text-[0.6875rem] text-muted-foreground\">\n {formatDuration(step.durationMs)}\n </span>\n ) : null}\n </div>\n {step.errorMessage ? (\n <pre\n role=\"alert\"\n className=\"mt-2.5 ml-6 overflow-x-auto rounded-md border border-fail-border bg-fail-bg px-4 py-3.5 font-mono text-xs leading-relaxed whitespace-pre-wrap text-fail\"\n >\n {step.errorMessage}\n </pre>\n ) : null}\n {step.docEntries.length > 0 ? (\n <div data-es-docs className=\"mt-2 ml-6\">\n <ReportDocEntries entries={step.docEntries} />\n </div>\n ) : null}\n </li>\n );\n}\n","import type { ReportDocNote } from \"executable-stories-core\";\n\nexport function DocNote({ entry }: { entry: ReportDocNote }) {\n return <p className=\"my-2 text-sm text-muted-foreground\">{entry.text}</p>;\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { useRender } from \"@base-ui/react/use-render\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst badgeVariants = cva(\n \"inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground [a&]:hover:bg-primary/90\",\n secondary:\n \"bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90\",\n destructive:\n \"bg-destructive text-white focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40 [a&]:hover:bg-destructive/90\",\n outline:\n \"border-border text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n ghost: \"[a&]:hover:bg-accent [a&]:hover:text-accent-foreground\",\n link: \"text-primary underline-offset-4 [a&]:hover:underline\",\n // Pass/skip/pending are the quiet states: outline + coloured text, no\n // fill, so a green report reads calm. Only `failed` keeps a tinted\n // fill, making it the single loud badge on the page, so red pops the\n // instant something breaks. Colour-as-accent, matching the KPI cards.\n passed: \"border-pass-border text-pass font-mono uppercase\",\n failed: \"border-fail-border bg-fail-bg text-fail font-mono uppercase\",\n skipped: \"border-skip-border text-skip font-mono uppercase\",\n pending: \"border-pend-border text-pend font-mono uppercase\",\n tag: \"border-border text-muted-foreground font-mono font-medium [a&]:hover:bg-muted\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n },\n }\n)\n\nfunction Badge({\n className,\n variant = \"default\",\n render,\n ...props\n}: React.ComponentProps<\"span\"> &\n VariantProps<typeof badgeVariants> & {\n // Base UI composition: pass `render={<a … />}` to swap the underlying tag —\n // replaces Radix's `asChild`. See rules/base-vs-radix.md.\n render?: useRender.RenderProp\n }) {\n return useRender({\n defaultTagName: \"span\",\n render,\n props: {\n \"data-slot\": \"badge\",\n \"data-variant\": variant,\n className: cn(badgeVariants({ variant }), className),\n ...props,\n },\n })\n}\n\nexport { Badge, badgeVariants }\n","import type { ReportDocTag } from \"executable-stories-core\";\nimport { Badge } from \"@/components/ui/badge\";\n\nexport function DocTag({ entry }: { entry: ReportDocTag }) {\n return (\n <ul className=\"my-2 flex flex-wrap gap-1.5\" aria-label=\"Tags\">\n {entry.names.map((n) => (\n <li key={n}>\n <Badge variant=\"tag\">{n}</Badge>\n </li>\n ))}\n </ul>\n );\n}\n","import type { ReportDocKv } from \"executable-stories-core\";\n\nfunction formatValue(value: unknown): string {\n if (value === null) return \"null\";\n if (typeof value === \"string\") return value;\n if (typeof value === \"number\" || typeof value === \"boolean\") return String(value);\n try {\n return JSON.stringify(value);\n } catch {\n return String(value);\n }\n}\n\nexport function DocKv({ entry }: { entry: ReportDocKv }) {\n return (\n <dl className=\"my-2 flex flex-wrap items-baseline gap-x-2 text-sm\">\n <dt className=\"font-semibold text-muted-foreground\">{entry.label}</dt>\n <dd className=\"min-w-0 break-words font-mono text-foreground\">{formatValue(entry.value)}</dd>\n </dl>\n );\n}\n","import { useContext } from \"react\";\nimport { ReportContext } from \"../context/ReportContext\";\nimport type { BuiltinRenderers, CustomRenderers } from \"../renderers\";\n\nconst EMPTY_CUSTOM: CustomRenderers = {};\nconst EMPTY_RENDERERS: BuiltinRenderers = {};\n\nexport function useCustomRenderers(): CustomRenderers {\n const ctx = useContext(ReportContext);\n return ctx?.customRenderers ?? EMPTY_CUSTOM;\n}\n\nexport function useBuiltinRenderers(): BuiltinRenderers {\n const ctx = useContext(ReportContext);\n return ctx?.renderers ?? EMPTY_RENDERERS;\n}\n","import type { ReactNode } from \"react\";\nimport type { ReportDocCode } from \"executable-stories-core\";\nimport { useBuiltinRenderers } from \"../../hooks/useRenderers\";\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Shared shell for code blocks: optional label + the scrollable `<pre>`. Both\n * the static `DocCode` and the island's CDN-highlighted variant render their\n * `<code>` into this so the two can never drift in spacing or chrome.\n */\nexport function CodeFigure({ label, children }: { label?: string; children: ReactNode }) {\n return (\n <figure className=\"my-3\">\n {label ? (\n <figcaption className=\"mb-1.5 text-xs font-medium text-muted-foreground\">{label}</figcaption>\n ) : null}\n <pre tabIndex={0} className=\"overflow-x-auto rounded-md bg-muted p-3\">\n {children}\n </pre>\n </figure>\n );\n}\n\nexport function DocCode({ entry }: { entry: ReportDocCode }) {\n const renderers = useBuiltinRenderers();\n if (renderers.code) {\n return <>{renderers.code(entry)}</>;\n }\n return (\n <CodeFigure label={entry.label}>\n <code className={cn(\"font-mono text-xs\", entry.lang && `language-${entry.lang}`)}>\n {entry.content}\n </code>\n </CodeFigure>\n );\n}\n","import type { ReportDocTable } from \"executable-stories-core\";\n\nexport function DocTable({ entry }: { entry: ReportDocTable }) {\n return (\n <figure className=\"my-3\">\n {entry.label ? (\n <figcaption className=\"mb-1.5 text-xs font-medium text-muted-foreground\">\n {entry.label}\n </figcaption>\n ) : null}\n <div tabIndex={0} className=\"overflow-x-auto rounded-md border border-border\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"bg-muted/50\">\n {entry.columns.map((c) => (\n <th key={c} scope=\"col\" className=\"border-b border-border px-3 py-2 text-left font-semibold\">\n {c}\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {entry.rows.map((row, i) => (\n <tr key={i}>\n {row.map((cell, j) => (\n <td key={j} className=\"border-b border-border px-3 py-2 text-foreground\">\n {cell}\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </figure>\n );\n}\n","import type { ReportDocLink } from \"executable-stories-core\";\n\nexport function DocLink({ entry }: { entry: ReportDocLink }) {\n return (\n <a\n className=\"text-sm font-medium text-primary underline underline-offset-2 hover:no-underline\"\n href={entry.url}\n rel=\"noreferrer noopener\"\n target=\"_blank\"\n >\n {entry.label}\n </a>\n );\n}\n","import { marked } from \"marked\";\nimport { safeUrl } from \"./url\";\n\n/**\n * Best-effort sanitizer for marked-generated HTML. The markdown we render is\n * authored in test source (developer-trusted), so this is defense-in-depth,\n * not a hard boundary against hostile input. It:\n * - drops <script>/<style> and other active elements (iframe/object/embed/form)\n * - strips on* event-handler attributes\n * - neutralizes any non-http(s) scheme on href/src via the shared `safeUrl`\n * allow-list (covers javascript:/data:/vbscript:/file:, not just javascript:)\n *\n * It is NOT a substitute for a full HTML sanitizer (it won't catch entity-\n * obfuscated schemes). For untrusted markdown, supply your own renderer.\n */\nexport function safeMarkdownHtml(markdown: string): string {\n const raw = marked.parse(markdown, { async: false }) as string;\n return raw\n .replace(/<script\\b[^>]*>[\\s\\S]*?<\\/script>/gi, \"\")\n .replace(/<style\\b[^>]*>[\\s\\S]*?<\\/style>/gi, \"\")\n .replace(/<\\/?(?:iframe|object|embed|form|base)\\b[^>]*>/gi, \"\")\n .replace(/\\son[a-z]+\\s*=\\s*\"[^\"]*\"/gi, \"\")\n .replace(/\\son[a-z]+\\s*=\\s*'[^']*'/gi, \"\")\n .replace(/\\son[a-z]+\\s*=\\s*[^\\s>]+/gi, \"\")\n .replace(/(href|src)\\s*=\\s*\"([^\"]*)\"/gi, (_m, attr, val) => `${attr}=\"${neutralizeUrl(val)}\"`)\n .replace(/(href|src)\\s*=\\s*'([^']*)'/gi, (_m, attr, val) => `${attr}='${neutralizeUrl(val)}'`);\n}\n\n/**\n * Strip the leading indentation a template literal picks up from its source.\n *\n * Narratives are written inline in test files, so they arrive indented to match\n * the surrounding code. Left alone, four spaces make Markdown render the whole\n * paragraph as a code block.\n */\nexport function dedent(text: string): string {\n const lines = text.replace(/\\t/g, \" \").split(\"\\n\");\n const indents = lines\n .filter((line) => line.trim().length > 0)\n .map((line) => line.length - line.trimStart().length);\n const shortest = indents.length > 0 ? Math.min(...indents) : 0;\n return lines\n .map((line) => line.slice(shortest))\n .join(\"\\n\")\n .trim();\n}\n\nfunction neutralizeUrl(value: string): string {\n return safeUrl(value) ?? \"#\";\n}\n","/**\n * URL trust boundary for report-sourced strings reaching the DOM. The\n * implementation lives in executable-stories-core/utils/url (shared with the\n * Astro state-catalog thumbnails); this module stays as the package-local\n * import point. Subpath import: the core package root pulls in Node-only\n * converters, which breaks browser bundles.\n */\nexport { safeUrl, safeImageUrl, isLocalFsPath } from \"executable-stories-core/utils/url\";\n","import type { ReportDocSection } from \"executable-stories-core\";\nimport { useBuiltinRenderers } from \"../../hooks/useRenderers\";\nimport { safeMarkdownHtml } from \"../../lib/markdown\";\n\nexport function DocSection({ entry }: { entry: ReportDocSection }) {\n const renderers = useBuiltinRenderers();\n if (renderers.section) {\n return <>{renderers.section(entry)}</>;\n }\n const html = safeMarkdownHtml(entry.markdown);\n return (\n <section className=\"my-3 text-sm\" aria-label={entry.title}>\n {entry.title ? <h4 className=\"mb-1 font-semibold text-foreground\">{entry.title}</h4> : null}\n <div\n className=\"es-doc-prose prose prose-sm max-w-none\"\n dangerouslySetInnerHTML={{ __html: html }}\n />\n </section>\n );\n}\n","import type { Ref } from \"react\";\nimport type { ReportDocMermaid } from \"executable-stories-core\";\nimport { useBuiltinRenderers } from \"../../hooks/useRenderers\";\n\n/**\n * The raw mermaid source as a semantic `<pre data-mermaid>`. This is the\n * default render and the universal fallback: AI agents, screen readers, and\n * no-JS views all get the readable source. `<MermaidDiagram>` upgrades this to\n * a drawn diagram on the client.\n */\nexport function MermaidSource({ entry, ref }: { entry: ReportDocMermaid; ref?: Ref<HTMLElement> }) {\n return (\n <figure ref={ref} className=\"my-3\" aria-label={entry.title ?? \"Diagram\"}>\n {entry.title ? (\n <figcaption className=\"mb-1.5 text-xs font-medium text-muted-foreground\">{entry.title}</figcaption>\n ) : null}\n <pre\n data-mermaid\n tabIndex={0}\n className=\"overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground\"\n >\n {entry.code}\n </pre>\n </figure>\n );\n}\n\n/**\n * Renders mermaid source as a semantic `<pre data-mermaid>` by default.\n *\n * To draw the diagram, supply a `renderers.mermaid` prop — e.g. the shipped\n * `MermaidDiagram` (`renderers={{ mermaid: (e) => <MermaidDiagram entry={e} /> }}`).\n */\nexport function DocMermaid({ entry }: { entry: ReportDocMermaid }) {\n const renderers = useBuiltinRenderers();\n if (renderers.mermaid) {\n return <>{renderers.mermaid(entry)}</>;\n }\n return <MermaidSource entry={entry} />;\n}\n","import type { ReportDocScreenshot } from \"executable-stories-core\";\nimport { isLocalFsPath, safeImageUrl } from \"../../lib/url\";\n\n/**\n * A screenshot that's still an absolute local filesystem path by the time it\n * reaches this component means the report's asset bundler couldn't find the\n * file to inline/copy it (deleted, moved, or never captured — see\n * inlineScreenshotIfPossible in executable-stories-playwright). `<img src>`\n * would 404 against a path from the machine that generated the report, so\n * show a placeholder instead of a broken image.\n */\nexport function DocScreenshot({ entry }: { entry: ReportDocScreenshot }) {\n const src = isLocalFsPath(entry.path) ? undefined : safeImageUrl(entry.path);\n\n if (!src) {\n return (\n <figure className=\"my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground\">\n <div className=\"font-medium\">Screenshot unavailable</div>\n <div className=\"mt-1 break-all font-mono text-xs\">{entry.path}</div>\n {entry.alt ? <figcaption className=\"mt-1.5 text-xs\">{entry.alt}</figcaption> : null}\n </figure>\n );\n }\n\n return (\n <figure className=\"my-3\">\n <img\n src={src}\n alt={entry.alt ?? \"\"}\n loading=\"lazy\"\n className=\"max-w-full rounded-md border border-border\"\n />\n {entry.alt ? <figcaption className=\"mt-1.5 text-xs text-muted-foreground\">{entry.alt}</figcaption> : null}\n </figure>\n );\n}\n","import type { ReportDocVideo } from \"executable-stories-core\";\nimport { isLocalFsPath, safeUrl } from \"../../lib/url\";\n\n/**\n * Renders a video doc entry. Video bytes are large and never inlined; `path` is\n * a URL or a path that resolves alongside the report. Both `path` and `poster`\n * are adapter-supplied, so they go through the same scheme allow-list as the\n * DocHtml iframe src (no `javascript:`/`data:` URLs reach the DOM).\n *\n * An absolute local filesystem path means the report's asset bundler\n * couldn't find/copy the file — a `<video src>` pointed at a runner-local\n * path would just fail to load, so show a placeholder instead.\n */\nexport function DocVideo({ entry }: { entry: ReportDocVideo }) {\n if (isLocalFsPath(entry.path)) {\n return (\n <figure className=\"my-3 rounded-md border border-dashed border-border p-3 text-sm text-muted-foreground\">\n <div className=\"font-medium\">Video unavailable</div>\n <div className=\"mt-1 break-all font-mono text-xs\">{entry.path}</div>\n {entry.caption ? <figcaption className=\"mt-1.5 text-xs\">{entry.caption}</figcaption> : null}\n </figure>\n );\n }\n\n const src = safeUrl(entry.path);\n const poster = safeUrl(entry.poster);\n return (\n <figure className=\"my-3\">\n <video\n controls\n preload=\"metadata\"\n {...(src ? { src } : {})}\n {...(poster ? { poster } : {})}\n className=\"max-w-full rounded-md border border-border\"\n />\n {entry.caption ? (\n <figcaption className=\"mt-1 text-xs text-muted-foreground\">{entry.caption}</figcaption>\n ) : null}\n </figure>\n );\n}\n","import { useEffect, useRef, useState } from \"react\";\nimport type { ReportDocHtml } from \"executable-stories-core\";\nimport { safeUrl } from \"../../lib/url\";\n\n/**\n * Measures the framed page and posts its height out.\n *\n * The frame is `sandbox=\"allow-scripts\"` with no `allow-same-origin`, so it is\n * an opaque origin and the report cannot read into it. Measurement has to run\n * inside the frame and come back by postMessage, which is only possible for\n * HTML the report owns — inline `content`. A remote `url`/`path` page can only\n * do this if its own author opts in, so those keep their declared height.\n *\n * Inlined rather than fetched: the HTML report is a single self-contained file\n * with no CDN and no external requests.\n *\n * The closing tag is written plainly. This module is bundled into the report\n * island, which is inlined into a `<script>` in the report HTML, where a raw\n * `</script>` inside a string would close that tag early. esbuild escapes it on\n * the way out, so hand-escaping here only trips the linter. Checked against the\n * generated bundle rather than assumed.\n */\nconst MEASURE_SCRIPT =\n \"<script>(function(){\" +\n \"if(parent===window)return;\" +\n \"var last=0,queued=false;\" +\n // Measure the bottom edge of body's children, never the document's own\n // scrollHeight. A standalone artifact routinely sets `html,body{height:100%}`,\n // which makes scrollHeight equal to the frame, so measuring it is a ratchet:\n // the frame grows and can never shrink, because the thing measured is the\n // frame.\n //\n // Zero means there was nothing to measure that way: `content` is any string,\n // so it can be bare text with no element children, or text beside only\n // non-rendered ones (a <style> block, a <script>). Body's own box is what\n // gives that text a box to be measured in. It is the fallback and not the\n // primary because a stretched body is exactly the ratchet above.\n \"var measure=function(){\" +\n \"var kids=document.body.children,h=0;\" +\n \"for(var i=0;i<kids.length;i++)h=Math.max(h,kids[i].getBoundingClientRect().bottom);\" +\n \"return Math.ceil(h||document.body.getBoundingClientRect().bottom)};\" +\n // Unchanged height posts nothing. That both spares the report a re-render per\n // frame and breaks the feedback loop: resizing the frame resizes a stretched\n // body, which fires the observer again.\n \"var post=function(){queued=false;var h=measure();if(h===last)return;last=h;\" +\n \"parent.postMessage({__esHtmlHeight:h},'*')};\" +\n // One measurement per frame: mutations arrive in bursts and each measure\n // forces a layout.\n \"var schedule=function(){if(queued)return;queued=true;requestAnimationFrame(post)};\" +\n \"var start=function(){\" +\n // ResizeObserver catches reflow (images, fonts, viewport). MutationObserver\n // catches DOM and style changes, which the observer never sees when body is\n // stretched to the frame and so never changes size itself.\n \"new ResizeObserver(schedule).observe(document.body);\" +\n \"new MutationObserver(schedule).observe(document.body,\" +\n \"{subtree:true,childList:true,attributes:true,characterData:true});\" +\n \"addEventListener('load',schedule);post()};\" +\n \"if(document.body)start();else addEventListener('DOMContentLoaded',start)\" +\n \"})();</script>\";\n\n/**\n * The tallest frame the report will grow to. The embedded page is untrusted by\n * construction, so a height it reports is input at a trust boundary: a broken\n * or hostile document claiming 10 million pixels would otherwise take the page\n * with it. Past this the frame scrolls.\n */\nconst MAX_MEASURED_HEIGHT = 5000;\n\n/**\n * Renders an embedded-HTML doc entry inside a SANDBOXED iframe. All embedded\n * HTML is untrusted, so the frame is `sandbox=\"allow-scripts\"` only (no\n * allow-same-origin) — embedded scripts run (charts work) but can't touch the\n * report DOM, cookies, or storage. Inline `content` → srcdoc (keeps the report\n * self-contained); `url`/`path` → src (scheme-validated).\n */\nexport function DocHtml({ entry }: { entry: ReportDocHtml }) {\n const declaredHeight =\n typeof entry.height === \"number\" ? `${entry.height}px` : (entry.height ?? \"400px\");\n const title = entry.title ?? \"Embedded HTML\";\n const safeHref = safeUrl(entry.url ?? entry.path);\n\n const frameRef = useRef<HTMLIFrameElement>(null);\n const [measuredHeight, setMeasuredHeight] = useState<number>();\n\n // Runs only on the client, so the server and the first client render agree on\n // the declared height and hydration is stable.\n useEffect(() => {\n if (entry.content === undefined) return;\n\n const onMessage = (event: MessageEvent) => {\n // The frame has an opaque origin (sandboxed without allow-same-origin),\n // so `event.origin` is \"null\" and proves nothing. Identity comes from the\n // source window instead: this is the only check separating our own frame\n // from every other script on the page posting at us.\n if (event.source !== frameRef.current?.contentWindow) return;\n\n const reported = (event.data as { __esHtmlHeight?: unknown } | null)?.__esHtmlHeight;\n if (typeof reported !== \"number\" || !Number.isFinite(reported) || reported <= 0) return;\n setMeasuredHeight(Math.min(reported, MAX_MEASURED_HEIGHT));\n };\n\n window.addEventListener(\"message\", onMessage);\n return () => window.removeEventListener(\"message\", onMessage);\n }, [entry.content]);\n\n const height = measuredHeight === undefined ? declaredHeight : `${measuredHeight}px`;\n\n // Exactly one of content / url / path is set. A url/path with an unsafe\n // scheme yields no src (the figure still renders, just empty).\n const frameProps =\n entry.content !== undefined\n ? { srcDoc: entry.content + MEASURE_SCRIPT }\n : { src: safeHref ?? \"\" };\n\n return (\n <figure className=\"my-3 overflow-hidden rounded-md border border-border\">\n <figcaption className=\"flex items-center justify-between border-b border-border bg-muted/40 px-3 py-1.5 text-xs font-medium text-muted-foreground\">\n <span>{entry.title ?? \"HTML\"}</span>\n {safeHref ? (\n <a\n href={safeHref}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n aria-label=\"Open in new tab\"\n title=\"Open in new tab\"\n className=\"text-primary\"\n >\n ↗\n </a>\n ) : null}\n </figcaption>\n <iframe\n ref={frameRef}\n {...frameProps}\n sandbox=\"allow-scripts\"\n loading=\"lazy\"\n title={title}\n className=\"block w-full border-0\"\n // Embedded HTML is authored standalone, so it assumes a light page. An\n // iframe with no background inherits the host's dark canvas (via the\n // report's `color-scheme`), leaving that authored dark text unreadable.\n style={{ height, colorScheme: \"light\", background: \"#fff\" }}\n />\n </figure>\n );\n}\n","import type { ReportDocState } from \"executable-stories-core\";\nimport { CodeFigure } from \"./DocCode\";\n\n/**\n * A `story.state()` snapshot in the step detail: label + pretty JSON, same\n * chrome as `code(json)`. Frame-to-frame diffs are the storyboard's job —\n * here the entry just shows what was captured at this step.\n */\nexport function DocState({ entry }: { entry: ReportDocState }) {\n let json: string;\n try {\n json = JSON.stringify(entry.value, null, 2) ?? String(entry.value);\n } catch {\n json = String(entry.value);\n }\n return (\n <CodeFigure label={entry.label ?? \"State\"}>\n <code className=\"font-mono text-xs language-json\">{json}</code>\n </CodeFigure>\n );\n}\n","import type { ReportDocCustom } from \"executable-stories-core\";\nimport { useCustomRenderers } from \"../../hooks/useRenderers\";\n\nexport function DocCustom({ entry }: { entry: ReportDocCustom }) {\n const renderers = useCustomRenderers();\n const renderer = renderers[entry.type];\n if (renderer) {\n return <>{renderer(entry)}</>;\n }\n return (\n <div className=\"my-2\" data-type={entry.type}>\n <p className=\"mb-1 text-xs font-medium text-muted-foreground\">{entry.type}</p>\n <pre tabIndex={0} className=\"overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground\">\n {safeStringify(entry.data)}\n </pre>\n </div>\n );\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n","import type { ReportDocEntry } from \"executable-stories-core\";\nimport { DocNote } from \"./DocNote\";\nimport { DocTag } from \"./DocTag\";\nimport { DocKv } from \"./DocKv\";\nimport { DocCode } from \"./DocCode\";\nimport { DocTable } from \"./DocTable\";\nimport { DocLink } from \"./DocLink\";\nimport { DocSection } from \"./DocSection\";\nimport { DocMermaid } from \"./DocMermaid\";\nimport { DocScreenshot } from \"./DocScreenshot\";\nimport { DocVideo } from \"./DocVideo\";\nimport { DocHtml } from \"./DocHtml\";\nimport { DocState } from \"./DocState\";\nimport { DocCustom } from \"./DocCustom\";\n\nexport function DocEntry({ entry }: { entry: ReportDocEntry }) {\n switch (entry.kind) {\n case \"note\":\n return <DocNote entry={entry} />;\n case \"tag\":\n return <DocTag entry={entry} />;\n case \"kv\":\n return <DocKv entry={entry} />;\n case \"code\":\n return <DocCode entry={entry} />;\n case \"table\":\n return <DocTable entry={entry} />;\n case \"link\":\n return <DocLink entry={entry} />;\n case \"section\":\n return <DocSection entry={entry} />;\n case \"mermaid\":\n return <DocMermaid entry={entry} />;\n case \"screenshot\":\n return <DocScreenshot entry={entry} />;\n case \"video\":\n return <DocVideo entry={entry} />;\n case \"html\":\n return <DocHtml entry={entry} />;\n case \"state\":\n return <DocState entry={entry} />;\n case \"custom\":\n return <DocCustom entry={entry} />;\n }\n}\n","import type { ReportDocEntry } from \"executable-stories-core\";\nimport { DocEntry } from \"./doc/DocEntry\";\n\nexport interface ReportDocEntriesProps {\n entries: readonly ReportDocEntry[];\n}\n\nexport function ReportDocEntries({ entries }: ReportDocEntriesProps) {\n if (entries.length === 0) return null;\n return (\n <>\n {entries.map((entry, i) => (\n <DocEntry key={i} entry={entry} />\n ))}\n </>\n );\n}\n","import type { ReportScenario } from \"executable-stories-core\";\n// Subpath import: the core package root pulls in Node-only converters\n// (node:crypto), which breaks browser bundles — see formatDuration's import.\nimport { extractStoryboardFrames } from \"executable-stories-core/storyboard\";\nimport type { StoryboardFrame, StoryboardStateCard } from \"executable-stories-core/storyboard\";\nimport { summarizeStateChanges } from \"executable-stories-core/state-diff\";\nimport type { StateChangeKind } from \"executable-stories-core/state-diff\";\nimport { isLocalFsPath, safeImageUrl } from \"executable-stories-core/utils/url\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportStoryboardProps {\n scenario: ReportScenario;\n}\n\nconst FRAME_GLYPH: Record<string, string> = {\n passed: \"✓\",\n failed: \"✗\",\n skipped: \"○\",\n pending: \"○\",\n};\n\nconst FRAME_GLYPH_COLOR: Record<string, string> = {\n passed: \"text-pass\",\n failed: \"text-fail\",\n skipped: \"text-skip\",\n pending: \"text-pend\",\n};\n\n/**\n * Storyboard — a horizontal filmstrip of the scenario's step evidence\n * (Given → When → Then), derived from the same step docs the vertical step\n * list renders. A frame is a container: the step's screenshot (when present)\n * plus its `story.state()` snapshot cards, so data-only scenarios get\n * filmstrips too. Each frame links to its step's anchor.\n *\n * Renders nothing below 2 frames: a single capture is evidence, not a\n * walkthrough, and it already shows under its step.\n *\n * Must stay hydration-free: the Astro story pages render this inside a static\n * (no client JS) island, so navigation is plain anchors and snapshot expansion\n * is a native <details> — no lightbox or toggle state.\n */\nexport function ReportStoryboard({ scenario }: ReportStoryboardProps) {\n const frames = extractStoryboardFrames(scenario);\n if (frames.length < 2) return null;\n return (\n <section data-slot=\"storyboard\" aria-label=\"Storyboard\" className=\"mb-3\">\n <h4 className=\"mb-1.5 text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n Storyboard\n </h4>\n <ol className=\"flex items-start gap-3 overflow-x-auto pb-2\">\n {frames.map((frame) => (\n <StoryboardFrameItem key={frame.stepId} frame={frame} />\n ))}\n </ol>\n </section>\n );\n}\n\nfunction StoryboardFrameItem({ frame }: { frame: StoryboardFrame }) {\n const label = `${frame.keyword} ${frame.text}`;\n const hasStates = frame.states.length > 0;\n const caption = (\n <p className=\"mt-1 flex items-baseline gap-1.5 text-[0.6875rem] leading-snug\">\n <span aria-hidden className={cn(\"shrink-0\", FRAME_GLYPH_COLOR[frame.status])}>\n {FRAME_GLYPH[frame.status] ?? \"○\"}\n </span>\n <span className=\"min-w-0\">\n <span className=\"font-mono font-semibold text-keyword\">{frame.keyword}</span>{\" \"}\n <span className=\"text-muted-foreground\">{frame.screenshot?.alt ?? frame.text}</span>\n </span>\n </p>\n );\n return (\n // State cards need room for diff rows; screenshot-only frames keep the\n // original narrow film-cell width (and DOM) unchanged.\n <li className={cn(\"shrink-0\", hasStates ? \"w-64\" : \"w-40\")}>\n {frame.screenshot ? (\n <FrameScreenshot frame={frame} label={label} />\n ) : null}\n {hasStates ? (\n <div className={cn(\"flex flex-col gap-1.5\", frame.screenshot && \"mt-1.5\")}>\n {frame.states.map((card, i) => (\n <StateCardView key={card.label ?? i} card={card} />\n ))}\n </div>\n ) : null}\n {frame.screenshot ? (\n caption\n ) : (\n // No screenshot means no image anchor, so the caption carries the\n // jump-to-step link instead.\n <a href={`#${frame.stepId}`} aria-label={`Jump to step: ${label}`} className=\"block hover:underline\">\n {caption}\n </a>\n )}\n </li>\n );\n}\n\nfunction FrameScreenshot({ frame, label }: { frame: StoryboardFrame; label: string }) {\n const path = frame.screenshot?.path ?? \"\";\n const src = isLocalFsPath(path) ? undefined : safeImageUrl(path);\n return (\n <a\n href={`#${frame.stepId}`}\n aria-label={`Jump to step: ${label}`}\n className=\"block overflow-hidden rounded-md border border-border transition-colors hover:border-ring\"\n >\n {src ? (\n <img\n src={src}\n alt={frame.screenshot?.alt ?? label}\n loading=\"lazy\"\n className=\"h-24 w-full bg-muted object-cover object-top\"\n />\n ) : (\n <span className=\"flex h-24 w-full items-center justify-center border-b border-dashed border-border bg-muted px-2 text-center text-[0.6875rem] text-muted-foreground\">\n Screenshot unavailable\n </span>\n )}\n </a>\n );\n}\n\n// Same accent scheme as the status badges/KPI cards: green = new, red = gone,\n// amber (skip tokens) = changed. Text + bg pairs are the AA-audited --es-*\n// combinations from tailwind.css.\nconst CHANGE_TONE: Record<StateChangeKind, string> = {\n added: \"bg-pass-bg text-pass\",\n removed: \"bg-fail-bg text-fail\",\n changed: \"bg-skip-bg text-skip\",\n};\n\nfunction prettyJson(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2) ?? String(value);\n } catch {\n return String(value);\n }\n}\n\n/**\n * One `story.state()` snapshot card: label chip, then what changed since the\n * previous frame's snapshot of the same label (changed fields first, full\n * snapshot behind a disclosure). First appearance shows the snapshot itself\n * with a \"first capture\" hint — there is nothing to diff against yet.\n */\nfunction StateCardView({ card }: { card: StoryboardStateCard }) {\n const json = prettyJson(card.value);\n const firstCapture = card.changes === undefined;\n return (\n <div data-slot=\"state-card\" className=\"rounded-md border border-border bg-card p-2\">\n <p className=\"flex flex-wrap items-baseline gap-1.5\">\n <span className=\"inline-flex rounded-full border border-border px-1.5 font-mono text-[0.625rem] font-medium text-muted-foreground\">\n {card.label ?? \"State\"}\n </span>\n {firstCapture ? (\n <span className=\"text-[0.625rem] text-muted-foreground italic\">first capture</span>\n ) : null}\n </p>\n {!firstCapture &&\n (card.changes && card.changes.length > 0 ? (\n <ul className=\"mt-1.5 flex flex-col gap-0.5\">\n {card.changes.map((change, i) => (\n <li\n key={i}\n className={cn(\n \"rounded-sm px-1.5 py-0.5 font-mono text-[0.625rem] leading-snug break-all\",\n CHANGE_TONE[change.kind]\n )}\n >\n {summarizeStateChanges([change])[0]}\n </li>\n ))}\n </ul>\n ) : (\n <p className=\"mt-1.5 text-[0.625rem] text-muted-foreground\">No changes</p>\n ))}\n <details\n // First capture opens short snapshots by default: it IS the card's\n // content. Diff cards keep the snapshot collapsed — the rows above\n // already tell the story.\n open={firstCapture && json.length <= 240}\n className={cn(firstCapture ? \"mt-1.5\" : \"mt-1\")}\n >\n <summary className=\"cursor-pointer text-[0.625rem] text-muted-foreground hover:text-foreground\">\n Snapshot\n </summary>\n <pre tabIndex={0} className=\"mt-1 max-h-48 overflow-auto rounded-sm bg-muted p-1.5 font-mono text-[0.625rem] leading-snug\">\n {json}\n </pre>\n </details>\n </div>\n );\n}\n","import type { ReportAttachment } from \"executable-stories-core\";\n\n/**\n * Renders scenario attachments. Base64 images embed inline; everything else\n * becomes a labelled data-URI download link. Mirrors the report's attachments\n * block (which also inlines images and links other media).\n */\nexport function ReportAttachments({ attachments }: { attachments: ReportAttachment[] }) {\n if (attachments.length === 0) return null;\n return (\n // role=\"group\" (not a labelled <section>) so multiple scenarios' attachment\n // blocks don't create duplicate \"Attachments\" region landmarks.\n <div role=\"group\" aria-label=\"Attachments\" className=\"mt-3 flex flex-col gap-2\">\n {attachments.map((att, i) => {\n const dataUri =\n att.contentEncoding === \"BASE64\"\n ? `data:${att.mediaType};base64,${att.body}`\n : `data:${att.mediaType},${encodeURIComponent(att.body)}`;\n const isImage = att.mediaType.startsWith(\"image/\");\n return (\n <figure key={`${att.name}-${i}`} className=\"m-0\">\n {isImage ? (\n <>\n <img\n src={dataUri}\n alt={att.name}\n loading=\"lazy\"\n className=\"max-w-full rounded-md border border-border\"\n />\n <figcaption className=\"mt-1 text-xs text-muted-foreground\">{att.name}</figcaption>\n </>\n ) : (\n <a\n href={dataUri}\n download={att.name}\n className=\"text-xs text-link underline underline-offset-2\"\n >\n {att.name} <span className=\"text-muted-foreground\">({att.mediaType})</span>\n </a>\n )}\n </figure>\n );\n })}\n </div>\n );\n}\n","import type { OtelSpan } from \"executable-stories-core/types/otel\";\nimport { formatDuration } from \"executable-stories-core/utils/duration\";\nimport { toTraceRows, traceWindow } from \"@/lib/trace\";\nimport { cn } from \"@/lib/utils\";\n\nconst BAR_COLOR: Record<string, string> = {\n ok: \"bg-pass\",\n error: \"bg-fail\",\n unset: \"bg-skip\",\n};\n\n/**\n * OTel trace waterfall. Collapsed by default (native <details>, no JS) so it\n * renders in both the static and interactive reports. Each span is a row with a\n * depth-indented name and a bar positioned/sized by its time window.\n */\nexport function ReportTrace({ spans }: { spans: readonly OtelSpan[] | undefined }) {\n if (!spans || spans.length === 0) return null;\n const rows = toTraceRows(spans);\n if (rows.length === 0) return null;\n const { minStartMs, totalMs } = traceWindow(rows);\n\n return (\n <details className=\"mt-3 rounded-md border border-border bg-muted/30\">\n <summary className=\"cursor-pointer px-3 py-2 text-xs font-medium text-muted-foreground\">\n Trace ({rows.length} span{rows.length === 1 ? \"\" : \"s\"}, {formatDuration(totalMs)})\n </summary>\n <ul className=\"flex flex-col gap-0.5 px-3 pb-3 font-mono text-[0.6875rem]\">\n {rows.map((row, i) => {\n const leftPct = ((row.startTimeMs - minStartMs) / totalMs) * 100;\n const widthPct = Math.max((row.durationMs / totalMs) * 100, 0.5);\n return (\n <li key={`${row.spanId}-${i}`} className=\"flex items-center gap-2\">\n <span\n className=\"min-w-0 flex-1 truncate text-foreground\"\n style={{ paddingLeft: `${row.depth * 12}px` }}\n title={row.statusMessage ? `${row.name}: ${row.statusMessage}` : row.name}\n >\n {row.name}\n </span>\n <span className=\"relative h-3 w-1/2 shrink-0 overflow-hidden rounded-sm bg-border/40\">\n <span\n className={cn(\"absolute top-0 h-full rounded-sm\", BAR_COLOR[row.status])}\n style={{ left: `${leftPct}%`, width: `${widthPct}%` }}\n />\n </span>\n <span className=\"w-16 shrink-0 text-right text-muted-foreground\">\n {formatDuration(row.durationMs)}\n </span>\n </li>\n );\n })}\n </ul>\n </details>\n );\n}\n","/**\n * Pure span normalization + tree building for the OTel trace waterfall.\n * Ported from the formatters trace-view renderer so the React waterfall shows\n * the same structure. Side-effect-free for unit testing.\n */\n\nimport type { OtelSpan } from \"executable-stories-core/types/otel\";\n\nexport interface NormalizedSpan {\n spanId: string;\n parentSpanId?: string;\n name: string;\n startTimeMs: number;\n durationMs: number;\n status: \"ok\" | \"error\" | \"unset\";\n statusMessage?: string;\n}\n\nexport interface TraceRow extends NormalizedSpan {\n depth: number;\n}\n\nconst VALID = new Set([\"ok\", \"error\", \"unset\"]);\nconst safeStatus = (s: string): NormalizedSpan[\"status\"] => (VALID.has(s) ? (s as NormalizedSpan[\"status\"]) : \"unset\");\n\nexport function normalizeSpans(spans: readonly OtelSpan[]): NormalizedSpan[] {\n const out: NormalizedSpan[] = [];\n for (const span of spans) {\n if (!span || typeof span.spanId !== \"string\" || typeof span.name !== \"string\") continue;\n let startTimeMs: number;\n let durationMs: number;\n if (span.startTimeMs != null && span.durationMs != null) {\n startTimeMs = span.startTimeMs;\n durationMs = span.durationMs;\n } else if (span.startTimeUnixNano != null && span.endTimeUnixNano != null) {\n startTimeMs = span.startTimeUnixNano / 1e6;\n durationMs = (span.endTimeUnixNano - span.startTimeUnixNano) / 1e6;\n } else {\n continue;\n }\n durationMs = Math.max(0, durationMs);\n if (!isFinite(startTimeMs) || !isFinite(durationMs)) continue;\n out.push({\n spanId: span.spanId,\n parentSpanId: span.parentSpanId,\n name: span.name,\n startTimeMs,\n durationMs,\n status: safeStatus(span.status),\n statusMessage: span.statusMessage,\n });\n }\n return out;\n}\n\n/** Flatten spans into rows in tree order with a depth, parent before children. */\nexport function toTraceRows(spans: readonly OtelSpan[]): TraceRow[] {\n const normalized = normalizeSpans(spans);\n if (normalized.length === 0) return [];\n\n interface Node {\n span: NormalizedSpan;\n children: Node[];\n depth: number;\n }\n const byId = new Map<string, Node>();\n for (const span of normalized) {\n let key = span.spanId;\n let suffix = 2;\n while (byId.has(key)) key = `${span.spanId}__dup${suffix++}`;\n byId.set(key, { span: { ...span, spanId: key }, children: [], depth: 0 });\n }\n\n const roots: Node[] = [];\n for (const node of byId.values()) {\n const parent = node.span.parentSpanId ? byId.get(node.span.parentSpanId) : undefined;\n if (parent && parent !== node) parent.children.push(node);\n else roots.push(node);\n }\n for (const node of byId.values()) node.children.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);\n roots.sort((a, b) => a.span.startTimeMs - b.span.startTimeMs);\n\n const rows: TraceRow[] = [];\n const seen = new Set<string>();\n const walk = (node: Node, depth: number): void => {\n if (seen.has(node.span.spanId)) return;\n seen.add(node.span.spanId);\n rows.push({ ...node.span, depth });\n for (const child of node.children) walk(child, depth + 1);\n };\n for (const root of roots) walk(root, 0);\n // Orphans from cycles: promote to depth 0.\n for (const node of byId.values()) {\n if (!seen.has(node.span.spanId)) walk(node, 0);\n }\n return rows;\n}\n\nexport interface TraceWindow {\n minStartMs: number;\n totalMs: number;\n}\n\nexport function traceWindow(rows: readonly TraceRow[]): TraceWindow {\n let min = Infinity;\n let max = -Infinity;\n for (const r of rows) {\n min = Math.min(min, r.startTimeMs);\n max = Math.max(max, r.startTimeMs + r.durationMs);\n }\n const total = max - min;\n return { minStartMs: isFinite(min) ? min : 0, totalMs: total > 0 ? total : 1 };\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { ScenarioHistoryMap } from \"../lib/run-history\";\n\n/**\n * Provided only inside <ReportInteractive> when the CLI embedded a run\n * history (--history-file). When null (the static <Report/> render,\n * Storybook, Astro), scenario cards simply omit the history strip.\n */\nconst ScenarioHistoryContext = createContext<ScenarioHistoryMap | null>(null);\n\nexport const ScenarioHistoryProvider = ScenarioHistoryContext.Provider;\n\nexport function useScenarioHistory(): ScenarioHistoryMap | null {\n return useContext(ScenarioHistoryContext);\n}\n","export type ScenarioRunStatus = \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n\n/** One historical run of a scenario, oldest → newest in a history array. */\nexport interface ScenarioRunEvent {\n /** Epoch ms the run started. */\n timestamp: number;\n status: ScenarioRunStatus;\n runId?: string;\n durationMs?: number;\n commitSha?: string;\n branch?: string;\n}\n\n/** Recent run events keyed by ReportScenario.id. */\nexport type ScenarioHistoryMap = Record<string, ScenarioRunEvent[]>;\n\nexport interface RunStreak {\n status: ScenarioRunStatus;\n /** How many consecutive trailing runs share that status (≥1). */\n count: number;\n}\n\n/** The trailing same-status streak — \"passing for 5 runs\", \"failing for 2\". */\nexport function currentStreak(entries: readonly ScenarioRunEvent[]): RunStreak | undefined {\n const last = entries[entries.length - 1];\n if (!last) return undefined;\n let count = 0;\n for (let i = entries.length - 1; i >= 0 && entries[i]!.status === last.status; i--) count++;\n return { status: last.status, count };\n}\n\nconst STREAK_VERB: Record<ScenarioRunStatus, string> = {\n passed: \"Passing\",\n failed: \"Failing\",\n skipped: \"Skipped\",\n pending: \"Pending\",\n};\n\n/** Short human summary of a history window, used for the strip's tooltip. */\nexport function describeRunHistory(entries: readonly ScenarioRunEvent[]): string {\n const passed = entries.filter((e) => e.status === \"passed\").length;\n const base = `${passed}/${entries.length} runs passed`;\n const streak = currentStreak(entries);\n if (!streak || entries.length < 2) return base;\n return `${base} · ${STREAK_VERB[streak.status]} for the last ${streak.count === 1 ? \"run\" : `${streak.count} runs`}`;\n}\n\nexport type FlakinessLevel = \"stable\" | \"unstable\" | \"flaky\";\n\n/**\n * Below this many pass/fail samples a scenario is always \"stable\" — mirrors\n * MIN_FLAKINESS_SAMPLES in the formatters history module, which owns the\n * canonical thresholds. Keep the two in sync.\n */\nconst MIN_FLAKINESS_SAMPLES = 3;\n\n/**\n * Status-transition flakiness over a scenario's recent runs. Same\n * classification as the CLI history module (`calculateFlakiness`), ported so\n * the island stays self-sufficient on the embedded history JSON.\n */\nexport function flakinessOf(entries: readonly ScenarioRunEvent[]): FlakinessLevel {\n const countable = entries.filter((e) => e.status === \"passed\" || e.status === \"failed\");\n if (countable.length < MIN_FLAKINESS_SAMPLES) return \"stable\";\n\n let transitions = 0;\n for (let i = 1; i < countable.length; i++) {\n if (countable[i]!.status !== countable[i - 1]!.status) transitions++;\n }\n const transitionScore = transitions / (countable.length - 1);\n const failureRate = countable.filter((e) => e.status === \"failed\").length / countable.length;\n\n if (transitionScore > 0.5 || (transitionScore > 0.3 && failureRate > 0.2)) return \"flaky\";\n if (transitionScore > 0.2 || failureRate > 0.3) return \"unstable\";\n return \"stable\";\n}\n\nexport interface ScenarioRef {\n id: string;\n title: string;\n}\n\nexport interface LastRunDelta {\n /** Failed in this run, not failed in the previous one. */\n newlyFailing: ScenarioRef[];\n /** Passed in this run, failed in the previous one. */\n newlyPassing: ScenarioRef[];\n /** First appearance in the history window — no previous run to compare. */\n added: ScenarioRef[];\n}\n\n/**\n * What changed between the previous run and this one, for the report-header\n * strip. The history store appends the current run before the report is\n * generated, so each scenario's last entry IS this run and the entry before\n * it is the previous run. Returns undefined when no scenario has a previous\n * run to compare against (first run with history enabled).\n */\nexport function diffSinceLastRun(\n history: ScenarioHistoryMap,\n scenarios: readonly ScenarioRef[],\n): LastRunDelta | undefined {\n let hasPreviousRun = false;\n const delta: LastRunDelta = { newlyFailing: [], newlyPassing: [], added: [] };\n\n for (const scenario of scenarios) {\n const entries = history[scenario.id];\n if (!entries || entries.length === 0) continue;\n const last = entries[entries.length - 1]!;\n const prev = entries[entries.length - 2];\n if (!prev) {\n delta.added.push(scenario);\n continue;\n }\n hasPreviousRun = true;\n if (last.status === \"failed\" && prev.status !== \"failed\") delta.newlyFailing.push(scenario);\n else if (last.status === \"passed\" && prev.status === \"failed\") delta.newlyPassing.push(scenario);\n }\n\n return hasPreviousRun ? delta : undefined;\n}\n","import { useScenarioHistory } from \"../interactive/scenario-history-context\";\nimport { describeRunHistory, flakinessOf, type ScenarioRunEvent, type ScenarioRunStatus } from \"../lib/run-history\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { cn } from \"@/lib/utils\";\n\n/** How many trailing runs the strip shows; older entries stay in the tooltip count. */\nconst MAX_DOTS = 10;\n\nconst DOT_COLOR: Record<ScenarioRunStatus, string> = {\n passed: \"bg-pass\",\n failed: \"bg-fail\",\n skipped: \"bg-skip\",\n pending: \"bg-pend\",\n};\n\nfunction dotTitle(e: ScenarioRunEvent): string {\n const parts = [new Date(e.timestamp).toLocaleString(), e.status];\n if (e.commitSha) parts.push(e.commitSha.slice(0, 8));\n return parts.join(\" · \");\n}\n\n/**\n * Compact run-over-run timeline for one scenario: a dot per recent run,\n * oldest → newest. Renders nothing outside <ReportInteractive> or when the\n * report was generated without --history-file — history is presentation-layer\n * data and never part of the StoryReport contract.\n */\nexport function ScenarioRunHistory({ scenarioId }: { scenarioId: string }) {\n const history = useScenarioHistory();\n const entries = history?.[scenarioId];\n if (!entries || entries.length < 2) return null; // one run = no timeline yet\n\n const recent = entries.slice(-MAX_DOTS);\n // Judge flakiness on the same window the dots show, so the badge never\n // contradicts the strip next to it.\n const flaky = flakinessOf(recent) === \"flaky\";\n const summary = flaky ? `${describeRunHistory(recent)} · Flaky` : describeRunHistory(recent);\n\n return (\n <>\n {flaky ? (\n <Badge variant=\"pending\" aria-label=\"Flaky: status flips between recent runs\" title={summary}>\n Flaky\n </Badge>\n ) : null}\n <span\n role=\"img\"\n aria-label={`Run history: ${summary}`}\n title={summary}\n className=\"flex shrink-0 items-center gap-[3px]\"\n >\n {recent.map((e, i) => (\n <span\n key={`${e.timestamp}-${i}`}\n aria-hidden\n title={dotTitle(e)}\n className={cn(\n \"inline-block size-1.5 rounded-full\",\n DOT_COLOR[e.status],\n // The newest run (rightmost dot) is the one the card's status\n // badge already describes; ring it so the timeline reads as\n // \"…leading up to now\".\n i === recent.length - 1 && \"ring-1 ring-border ring-offset-1 ring-offset-card\",\n )}\n />\n ))}\n </span>\n </>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { formatRelativeAge, isReportStale } from \"../lib/provenance\";\nimport { useScenarioFreshness } from \"../interactive/scenario-freshness-context\";\nimport { Badge } from \"@/components/ui/badge\";\n\n/**\n * Per-scenario age signal.\n *\n * A report assembled from accumulated runs can be freshly rendered while some\n * of its scenarios last ran weeks ago. The report-level banner speaks for the\n * run, not for those scenarios, so without this the carried-over ones borrow a\n * freshness they have not earned.\n *\n * Only scenarios that are actually old say anything: a scenario that ran in\n * this run is the normal case and adds no badge. Age is computed on mount for\n * the same reason the report banner does it — static HTML is generated once and\n * read later, so an age baked in at build time would lie.\n */\nexport function ScenarioStaleness({ scenario }: { scenario: { lastRunAtMs?: number } }) {\n const freshness = useScenarioFreshness();\n const fixedNow = freshness?.nowMs;\n const [now, setNow] = useState<number | undefined>(fixedNow);\n\n useEffect(() => {\n if (fixedNow === undefined) setNow(Date.now());\n }, [fixedNow]);\n\n if (!freshness || now === undefined) return null;\n\n // No stamp means the report predates stamping, or came straight from one run.\n // Either way the report-level signal already speaks for it.\n const lastRunAtMs = scenario.lastRunAtMs;\n if (!lastRunAtMs || lastRunAtMs <= 0) return null;\n if (!isReportStale(lastRunAtMs, freshness.staleAfterDays, now)) return null;\n\n return (\n <Badge variant=\"outline\" aria-label=\"Scenario freshness\">\n Last ran {formatRelativeAge(lastRunAtMs, now)}\n </Badge>\n );\n}\n","import type { StoryReport } from \"executable-stories-core\";\n\ntype ReportCI = NonNullable<StoryReport[\"ci\"]>;\n\n/**\n * Epoch ms of the run the report documents — the staleness reference.\n * Prefers finishedAtMs; falls back to startedAtMs for reports from adapters\n * that only stamp a start time.\n */\nexport function reportLastRunMs(\n report: Pick<StoryReport, \"startedAtMs\" | \"finishedAtMs\">,\n): number | undefined {\n if (report.finishedAtMs && report.finishedAtMs > 0) return report.finishedAtMs;\n if (report.startedAtMs && report.startedAtMs > 0) return report.startedAtMs;\n return undefined;\n}\n\n/**\n * Epoch ms of the run that produced one scenario.\n *\n * A report assembled from accumulated runs holds scenarios that last ran at\n * different times, so the run-level timestamp overstates how fresh most of them\n * are. Falls back to the report for scenarios recorded before stamping, and for\n * reports rendered straight from a single run.\n */\nexport function scenarioLastRunMs(\n scenario: { lastRunAtMs?: number },\n report: Pick<StoryReport, \"startedAtMs\" | \"finishedAtMs\">,\n): number | undefined {\n if (scenario.lastRunAtMs && scenario.lastRunAtMs > 0) return scenario.lastRunAtMs;\n return reportLastRunMs(report);\n}\n\n/**\n * Human-readable age like \"just now\", \"5 minutes ago\", \"3 hours ago\",\n * \"12 days ago\". Clock skew (thenMs in the future) reads as \"just now\".\n */\nexport function formatRelativeAge(thenMs: number, nowMs: number): string {\n const deltaMs = Math.max(0, nowMs - thenMs);\n const minutes = Math.floor(deltaMs / 60_000);\n if (minutes < 1) return \"just now\";\n if (minutes < 60) return `${minutes} minute${minutes === 1 ? \"\" : \"s\"} ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours} hour${hours === 1 ? \"\" : \"s\"} ago`;\n const days = Math.floor(hours / 24);\n return `${days} day${days === 1 ? \"\" : \"s\"} ago`;\n}\n\n/**\n * A report is stale once its run is `staleAfterDays` or more days old.\n * A threshold of 0 (or negative) disables staleness entirely.\n */\nexport function isReportStale(\n lastRunMs: number | undefined,\n staleAfterDays: number,\n nowMs: number,\n): boolean {\n if (lastRunMs === undefined || staleAfterDays <= 0) return false;\n return nowMs - lastRunMs >= staleAfterDays * 86_400_000;\n}\n\n/**\n * StoryReport.ci.name carries the raw transport name — lowercase provider\n * keys (\"github\") from env detection, or a free-form string from older\n * adapters (\"GitHub Actions\"). Map the known keys to display names and pass\n * everything else through.\n */\nconst CI_DISPLAY_NAMES: Record<string, string> = {\n github: \"GitHub Actions\",\n gitlab: \"GitLab CI\",\n circleci: \"CircleCI\",\n jenkins: \"Jenkins\",\n azure: \"Azure DevOps\",\n buildkite: \"Buildkite\",\n travis: \"Travis CI\",\n ci: \"CI\",\n};\n\nexport function ciDisplayName(name: string): string {\n return CI_DISPLAY_NAMES[name] ?? name;\n}\n\n/**\n * Derive a browsable commit URL from the CI run URL, for the providers whose\n * URL structure makes that safe:\n * GitHub Actions …/owner/repo/actions/runs/123 -> …/owner/repo/commit/<sha>\n * GitLab CI …/group/project/-/pipelines/123 -> …/group/project/-/commit/<sha>\n * Other providers return undefined (a wrong link is worse than none).\n */\nexport function commitUrl(ci: ReportCI | undefined, sha: string | undefined): string | undefined {\n const commitSha = ci?.commitSha ?? sha;\n if (!ci?.url || !commitSha) return undefined;\n\n const github = ci.url.match(/^(https?:\\/\\/[^/]+\\/[^/]+\\/[^/]+)\\/actions\\/runs\\//);\n if (github) return `${github[1]}/commit/${commitSha}`;\n\n const gitlab = ci.url.match(/^(https?:\\/\\/.+)\\/-\\/pipelines\\//);\n if (gitlab) return `${gitlab[1]}/-/commit/${commitSha}`;\n\n return undefined;\n}\n\n/**\n * Derive a pull-request URL for GitHub-shaped CI run URLs. GitLab and the\n * rest return undefined for the same wrong-link-is-worse-than-none reason.\n */\nexport function prUrl(ci: ReportCI | undefined): string | undefined {\n if (!ci?.url || !ci.prNumber) return undefined;\n const github = ci.url.match(/^(https?:\\/\\/[^/]+\\/[^/]+\\/[^/]+)\\/actions\\/runs\\//);\n if (github) return `${github[1]}/pull/${ci.prNumber}`;\n return undefined;\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\n\nexport interface ScenarioFreshness {\n /** Days before a scenario counts as stale; 0 disables the signal. */\n staleAfterDays: number;\n /** The run being rendered, used for scenarios carrying no stamp of their own. */\n report: Pick<StoryReport, \"startedAtMs\" | \"finishedAtMs\">;\n /** Test seam: fixed \"now\". Left undefined, the badge reads the clock on mount. */\n nowMs?: number;\n}\n\n/**\n * Provided only where a report knows its staleness threshold. When null (a bare\n * <Report/> render, Storybook), scenario cards simply omit the age signal —\n * same shape as the run-history context.\n */\nconst ScenarioFreshnessContext = createContext<ScenarioFreshness | null>(null);\n\nexport const ScenarioFreshnessProvider = ScenarioFreshnessContext.Provider;\n\nexport function useScenarioFreshness(): ScenarioFreshness | null {\n return useContext(ScenarioFreshnessContext);\n}\n","\"use client\";\n\nimport { createContext, useCallback, useContext, useState } from \"react\";\n\nexport interface CollapseApi {\n isCollapsed: (id: string) => boolean;\n toggle: (id: string) => void;\n}\n\n/**\n * Provided only inside <ReportInteractive>. When null (the static <Report/>\n * render, Storybook, Astro), components render fully expanded with no toggle\n * affordance — so the static path and component-tier tests are unaffected.\n */\nconst CollapseContext = createContext<CollapseApi | null>(null);\n\nexport const CollapseProvider = CollapseContext.Provider;\n\nexport function useCollapse(): CollapseApi | null {\n return useContext(CollapseContext);\n}\n\nconst STORAGE_KEY = \"es-collapsed-ids\";\n\n/** Returns the persisted collapsed set, or null when the user has never set one\n * (so the caller can fall back to a data-driven default like failures-first). */\nfunction readPersisted(): Set<string> | null {\n if (typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n return raw ? new Set(JSON.parse(raw) as string[]) : null;\n } catch {\n return null;\n }\n}\n\nfunction persist(ids: Set<string>): void {\n if (typeof localStorage === \"undefined\") return;\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify([...ids]));\n } catch {\n /* quota / disabled — collapse still works for the session */\n }\n}\n\n/**\n * Collapse state for the interactive report: a persisted set of collapsed\n * feature/scenario ids, plus expand-all / collapse-all. `computeDefault` seeds\n * the initial set the FIRST time (nothing persisted yet) — the report uses it\n * to open failures and collapse the rest, so a broken run reveals what failed\n * without a click. Once the user toggles anything, their choice persists and\n * wins over the default.\n */\nexport function useCollapseState(computeDefault?: () => Set<string>) {\n const [collapsed, setCollapsed] = useState<Set<string>>(\n () => readPersisted() ?? computeDefault?.() ?? new Set<string>(),\n );\n\n const isCollapsed = useCallback((id: string) => collapsed.has(id), [collapsed]);\n\n const toggle = useCallback((id: string) => {\n setCollapsed((prev) => {\n const next = new Set(prev);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n persist(next);\n return next;\n });\n }, []);\n\n const collapseAll = useCallback((ids: string[]) => {\n setCollapsed(() => {\n const next = new Set(ids);\n persist(next);\n return next;\n });\n }, []);\n\n const expandAll = useCallback(() => {\n setCollapsed(() => {\n const next = new Set<string>();\n persist(next);\n return next;\n });\n }, []);\n\n return { api: { isCollapsed, toggle } as CollapseApi, collapseAll, expandAll };\n}\n","\"use client\";\n\nimport { createContext, useContext } from \"react\";\nimport type { ReportScenario } from \"executable-stories-core\";\n// Deep import, NOT the package barrel: core's index pulls in Node-only modules\n// (attachment resolution reads the filesystem), which a browser bundler cannot\n// resolve. Types erase at compile time, so the type-only import above is safe;\n// this one is a value and must stay on the fs-free subpath.\nimport { scenarioToMarkdown as coreScenarioToMarkdown } from \"executable-stories-core/utils/scenario-markdown\";\n\nexport interface ScenarioActions {\n copyLink: (scenario: ReportScenario) => void;\n copyMarkdown: (scenario: ReportScenario) => void;\n copyPrompt: (scenario: ReportScenario) => void;\n}\n\n/**\n * Provided only inside <ReportInteractive>. When null (static render), scenarios\n * show no per-scenario action buttons.\n */\nconst ScenarioActionsContext = createContext<ScenarioActions | null>(null);\nexport const ScenarioActionsProvider = ScenarioActionsContext.Provider;\nexport function useScenarioActions(): ScenarioActions | null {\n return useContext(ScenarioActionsContext);\n}\n\n/**\n * A scenario rendered as Markdown — for pasting into PRs / issues / docs.\n *\n * Delegates to the shared serializer in core (`variant: \"compact\"`), the same\n * one behind the Astro site's `<slug>.md` twin endpoints, so what you copy here\n * and what an agent fetches there can never drift.\n */\nexport function scenarioToMarkdown(scenario: ReportScenario): string {\n return coreScenarioToMarkdown(scenario, { variant: \"compact\" });\n}\n\n/**\n * A failed scenario rendered as an investigation prompt for an AI agent — the\n * \"cheap to verify\" loop: hand the agent the failing behaviour + error verbatim.\n */\nexport function scenarioToPrompt(scenario: ReportScenario): string {\n const lines: string[] = [\n `A test scenario is ${scenario.status}. Investigate the likely cause and propose a fix.`,\n \"\",\n `Scenario: ${scenario.title}`,\n \"Steps:\",\n ];\n for (const step of scenario.steps) {\n const mark = step.status === \"failed\" ? \" ⟵ failed here\" : \"\";\n lines.push(` ${step.keyword} ${step.text}${mark}`);\n }\n if (scenario.errorMessage) {\n lines.push(\"\", \"Error:\", scenario.errorMessage.trim());\n }\n if (scenario.errorStack) {\n lines.push(\"\", \"Stack:\", scenario.errorStack.trim());\n }\n return lines.join(\"\\n\");\n}\n\n/**\n * Every failure in the run as ONE prompt. A red run is rarely one broken thing,\n * and copying scenarios one at a time loses the shape of the breakage — the\n * agent that sees all three at once can spot the shared cause.\n */\nexport function failuresToPrompt(scenarios: readonly ReportScenario[]): string {\n if (scenarios.length === 0) return \"\";\n const noun = scenarios.length === 1 ? \"test scenario is\" : \"test scenarios are\";\n const lines: string[] = [\n `${scenarios.length} ${noun} failing. Investigate the likely cause (they may share one) and propose a fix.`,\n ];\n scenarios.forEach((scenario, i) => {\n lines.push(\"\", `${i + 1}. ${scenario.title}`, \"Steps:\");\n for (const step of scenario.steps) {\n const mark = step.status === \"failed\" ? \" ⟵ failed here\" : \"\";\n lines.push(` ${step.keyword} ${step.text}${mark}`);\n }\n if (scenario.errorMessage) {\n lines.push(\"Error:\", scenario.errorMessage.trim());\n }\n });\n return lines.join(\"\\n\");\n}\n\n/** Absolute permalink to a scenario in the current document. */\nexport function scenarioPermalink(scenario: ReportScenario): string {\n if (typeof location === \"undefined\") return `#${scenario.id}`;\n return `${location.href.split(\"#\")[0]}#${scenario.id}`;\n}\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Card({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card\"\n className={cn(\n \"flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground shadow-xs\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardHeader({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-header\"\n className={cn(\n \"@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardTitle({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-title\"\n className={cn(\"leading-none font-semibold\", className)}\n {...props}\n />\n )\n}\n\nfunction CardDescription({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-description\"\n className={cn(\"text-sm text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\nfunction CardAction({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-action\"\n className={cn(\n \"col-start-2 row-span-2 row-start-1 self-start justify-self-end\",\n className\n )}\n {...props}\n />\n )\n}\n\nfunction CardContent({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-content\"\n className={cn(\"px-6\", className)}\n {...props}\n />\n )\n}\n\nfunction CardFooter({ className, ...props }: React.ComponentProps<\"div\">) {\n return (\n <div\n data-slot=\"card-footer\"\n className={cn(\"flex items-center px-6 [.border-t]:pt-6\", className)}\n {...props}\n />\n )\n}\n\nexport {\n Card,\n CardHeader,\n CardFooter,\n CardTitle,\n CardAction,\n CardDescription,\n CardContent,\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Menu as MenuPrimitive } from \"@base-ui/react/menu\"\nimport { CheckIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst itemClasses =\n \"relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 [&_svg:not([class*='text-'])]:text-muted-foreground\"\n\nfunction DropdownMenu(props: React.ComponentProps<typeof MenuPrimitive.Root>) {\n return <MenuPrimitive.Root data-slot=\"dropdown-menu\" {...props} />\n}\n\nfunction DropdownMenuTrigger(\n props: React.ComponentProps<typeof MenuPrimitive.Trigger>,\n) {\n return <MenuPrimitive.Trigger data-slot=\"dropdown-menu-trigger\" {...props} />\n}\n\nfunction DropdownMenuContent({\n className,\n align = \"end\",\n sideOffset = 4,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.Popup> & {\n align?: MenuPrimitive.Positioner.Props[\"align\"]\n sideOffset?: MenuPrimitive.Positioner.Props[\"sideOffset\"]\n}) {\n return (\n <MenuPrimitive.Portal>\n <MenuPrimitive.Positioner\n data-slot=\"dropdown-menu-positioner\"\n className=\"z-50\"\n align={align}\n sideOffset={sideOffset}\n >\n <MenuPrimitive.Popup\n data-slot=\"dropdown-menu-content\"\n className={cn(\n \"z-50 min-w-[11rem] origin-[var(--transform-origin)] overflow-hidden rounded-md border border-border bg-popover p-1 font-sans text-sm text-popover-foreground shadow-md transition-[opacity,transform] data-[ending-style]:scale-95 data-[ending-style]:opacity-0 data-[starting-style]:scale-95 data-[starting-style]:opacity-0\",\n className,\n )}\n {...props}\n />\n </MenuPrimitive.Positioner>\n </MenuPrimitive.Portal>\n )\n}\n\nfunction DropdownMenuItem({\n className,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.Item>) {\n return (\n <MenuPrimitive.Item\n data-slot=\"dropdown-menu-item\"\n className={cn(itemClasses, className)}\n {...props}\n />\n )\n}\n\nfunction DropdownMenuLabel({\n className,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.GroupLabel>) {\n return (\n <MenuPrimitive.GroupLabel\n data-slot=\"dropdown-menu-label\"\n className={cn(\"px-2 py-1.5 text-xs font-medium text-muted-foreground\", className)}\n {...props}\n />\n )\n}\n\n// Base UI's Menu has no Separator part; a plain divider row is equivalent.\nfunction DropdownMenuSeparator({ className }: { className?: string }) {\n return <div role=\"separator\" className={cn(\"-mx-1 my-1 h-px bg-border\", className)} />\n}\n\nfunction DropdownMenuRadioGroup(\n props: React.ComponentProps<typeof MenuPrimitive.RadioGroup>,\n) {\n return <MenuPrimitive.RadioGroup data-slot=\"dropdown-menu-radio-group\" {...props} />\n}\n\nfunction DropdownMenuRadioItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.RadioItem>) {\n return (\n <MenuPrimitive.RadioItem\n data-slot=\"dropdown-menu-radio-item\"\n className={cn(itemClasses, \"pl-8\", className)}\n {...props}\n >\n <span className=\"absolute left-2 flex size-3.5 items-center justify-center\">\n <MenuPrimitive.RadioItemIndicator>\n <CheckIcon className=\"size-4 text-foreground\" />\n </MenuPrimitive.RadioItemIndicator>\n </span>\n {children}\n </MenuPrimitive.RadioItem>\n )\n}\n\nfunction DropdownMenuCheckboxItem({\n className,\n children,\n ...props\n}: React.ComponentProps<typeof MenuPrimitive.CheckboxItem>) {\n return (\n <MenuPrimitive.CheckboxItem\n data-slot=\"dropdown-menu-checkbox-item\"\n className={cn(itemClasses, \"pl-8\", className)}\n {...props}\n >\n <span className=\"absolute left-2 flex size-3.5 items-center justify-center\">\n <MenuPrimitive.CheckboxItemIndicator>\n <CheckIcon className=\"size-4\" />\n </MenuPrimitive.CheckboxItemIndicator>\n </span>\n {children}\n </MenuPrimitive.CheckboxItem>\n )\n}\n\nexport {\n DropdownMenu,\n DropdownMenuTrigger,\n DropdownMenuContent,\n DropdownMenuItem,\n DropdownMenuLabel,\n DropdownMenuSeparator,\n DropdownMenuRadioGroup,\n DropdownMenuRadioItem,\n DropdownMenuCheckboxItem,\n}\n","import type { ReportFeature } from \"executable-stories-core\";\nimport { ReportScenario } from \"./ReportScenario\";\n\nexport interface ReportScenarioListProps {\n feature: ReportFeature;\n}\n\nexport function ReportScenarioList({ feature }: ReportScenarioListProps) {\n return (\n <>\n {feature.scenarios.map((scenario) => (\n <ReportScenario key={scenario.id} scenario={scenario} />\n ))}\n </>\n );\n}\n","import type { ReportFeature } from \"executable-stories-core\";\nimport { dedent, safeMarkdownHtml } from \"../lib/markdown\";\n\nexport interface ReportFeatureIntroProps {\n feature: ReportFeature;\n}\n\n/**\n * What the feature is for, ahead of the scenarios that prove it.\n *\n * Scenarios answer \"what does it do\". A reader arriving cold needs \"why does\n * this exist and who is it for\" first, which is what `story.feature(...)`\n * records. Renders nothing when a file never declared one, so existing reports\n * look exactly as they did.\n */\nexport function ReportFeatureIntro({ feature }: ReportFeatureIntroProps) {\n const hasNarrative = Boolean(feature.narrative?.trim());\n const hasGlossary = Boolean(feature.glossary?.length);\n if (!hasNarrative && !hasGlossary) return null;\n\n return (\n <div className=\"flex flex-col gap-3 border-l-2 border-border pl-4 text-sm\">\n {hasNarrative ? (\n <div\n className=\"es-doc-prose prose prose-sm max-w-none text-muted-foreground\"\n dangerouslySetInnerHTML={{ __html: safeMarkdownHtml(dedent(feature.narrative!)) }}\n />\n ) : null}\n\n {hasGlossary ? (\n <dl className=\"grid gap-1.5\" aria-label=\"Glossary\">\n {feature.glossary!.map((entry) => (\n <div key={entry.term} className=\"flex flex-wrap gap-x-2 text-xs\">\n <dt className=\"font-medium text-foreground\">{entry.term}</dt>\n <dd className=\"flex-1 text-muted-foreground\">{entry.definition}</dd>\n </div>\n ))}\n </dl>\n ) : null}\n </div>\n );\n}\n\n/**\n * Label the feature the way it was declared.\n *\n * An ability reads as something a person can now do; a business need covers the\n * cross-cutting concerns nobody asks for by name, like security or performance.\n * Naming the kind keeps that distinction visible to a reader who never sees the\n * test code. A derived title gets no badge, since nobody claimed anything.\n */\nexport function featureKindLabel(kind: ReportFeature[\"kind\"]): string | null {\n if (kind === \"ability\") return \"Ability\";\n if (kind === \"business-need\") return \"Business need\";\n if (kind === \"feature\") return \"Feature\";\n return null;\n}\n","import type { ReportFeature as ReportFeatureT } from \"executable-stories-core\";\nimport { ReportScenarioList } from \"./ReportScenarioList\";\nimport { ReportFeatureIntro, featureKindLabel } from \"./ReportFeatureIntro\";\nimport { useCollapse } from \"../interactive/collapse-context\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportFeatureProps {\n feature: ReportFeatureT;\n}\n\n/**\n * Feature group — the report's `.feature` card: a header bar with the feature\n * title + mono source path and ✓/✗/○ status counts on the right, over a stack\n * of scenario cards. Kept a semantic <section> (a region), not a shadcn Card\n * div, so it stays a landmark and doesn't collide with the scenario cards'\n * `[data-slot=\"card\"]`.\n */\nexport function ReportFeature({ feature }: ReportFeatureProps) {\n const titleId = `${feature.id}-title`;\n const bodyId = `${feature.id}-body`;\n const s = feature.summary;\n const skipped = s.skipped + s.pending;\n const collapse = useCollapse();\n const collapsed = collapse?.isCollapsed(feature.id) ?? false;\n const kindLabel = featureKindLabel(feature.kind);\n return (\n // Suite = a section heading + a divider, NOT another bordered card. Drops a\n // layer of nesting so the scenario cards below read as the primary unit.\n <section\n id={feature.id}\n data-slot=\"feature\"\n aria-labelledby={titleId}\n className=\"flex flex-col gap-3\"\n >\n <div className=\"flex items-end justify-between gap-4 border-b border-border pb-2\">\n <div className=\"min-w-0\">\n {/* The heading itself is the toggle — a wide, obvious hit area rather\n than a lone caret. Kept inside <h2> so it stays a landmark. */}\n <h2 id={titleId} className=\"text-base font-semibold tracking-tight text-foreground\">\n {collapse ? (\n <button\n type=\"button\"\n onClick={() => collapse.toggle(feature.id)}\n aria-expanded={!collapsed}\n aria-controls={bodyId}\n className=\"flex w-full cursor-pointer items-center gap-2 text-left hover:text-foreground/80\"\n >\n <span aria-hidden className={cn(\"shrink-0 text-xs text-muted-foreground transition-transform\", !collapsed && \"rotate-90\")}>▸</span>\n <span className=\"truncate\">{feature.title}</span>\n </button>\n ) : (\n feature.title\n )}\n </h2>\n <p className={cn(\"mt-0.5 flex items-center gap-2 text-xs text-muted-foreground\", collapse && \"pl-5\")}>\n {kindLabel ? (\n <span className=\"shrink-0 rounded-sm bg-muted px-1.5 py-0.5 font-medium text-foreground\">\n {kindLabel}\n </span>\n ) : null}\n <span className=\"truncate font-mono\">{feature.sourceFile}</span>\n </p>\n </div>\n {/* Readable, failure-weighted counts — only the failure count carries\n colour, so a broken suite reads at a glance without a colour salad. */}\n <p\n className=\"flex shrink-0 items-center gap-1.5 text-xs text-muted-foreground\"\n aria-label={`${s.passed} passed, ${s.failed} failed, ${skipped} skipped`}\n >\n <span>{s.passed} passed</span>\n <span aria-hidden>·</span>\n <span className={cn(s.failed > 0 && \"font-medium text-fail\")}>{s.failed} failed</span>\n {skipped > 0 ? (\n <>\n <span aria-hidden>·</span>\n <span>{skipped} skipped</span>\n </>\n ) : null}\n </p>\n </div>\n <div id={bodyId} hidden={collapsed} className=\"flex flex-col gap-3\">\n <ReportFeatureIntro feature={feature} />\n <ReportScenarioList feature={feature} />\n </div>\n </section>\n );\n}\n","import { useReport } from \"../hooks/useReport\";\nimport { ReportFeature } from \"./ReportFeature\";\n\nexport function ReportFeatureList() {\n const report = useReport();\n // Roomy gap between features — they're now divider-led sections rather than\n // self-contained cards, so they need clear air to read as separate suites.\n return (\n <div className=\"flex flex-col gap-8\">\n {report.features.map((feature) => (\n <ReportFeature key={feature.id} feature={feature} />\n ))}\n </div>\n );\n}\n","import { formatDuration } from \"executable-stories-core/utils/duration\";\nimport { slowestScenarios } from \"executable-stories-core/report-queries\";\nimport { useReport } from \"../hooks/useReport\";\nimport { ciDisplayName, commitUrl, prUrl } from \"../lib/provenance\";\n\n/**\n * Run metadata line (started, duration, version, branch, git SHA, CI, PR) —\n * the React equivalent of the report's `.meta-info` block. Reads the top-level\n * StoryReport fields from context. Commit and PR become links when the CI run\n * URL lets us derive them safely (GitHub/GitLab shapes only).\n */\nexport function ReportMeta() {\n const report = useReport();\n\n const items: Array<{ label: string; value: React.ReactNode }> = [];\n const linkClass = \"text-primary underline underline-offset-2\";\n\n if (report.startedAtMs) {\n items.push({ label: \"Started\", value: new Date(report.startedAtMs).toLocaleString() });\n }\n if (report.durationMs) {\n items.push({ label: \"Duration\", value: formatDuration(report.durationMs) });\n }\n if (report.packageVersion) {\n items.push({ label: \"Version\", value: report.packageVersion });\n }\n if (report.ci?.branch) {\n items.push({ label: \"Branch\", value: report.ci.branch });\n }\n const sha = report.ci?.commitSha ?? report.gitSha;\n if (sha) {\n const url = commitUrl(report.ci, report.gitSha);\n const short = sha.slice(0, 8);\n items.push({\n label: \"Commit\",\n value: url ? (\n <a href={url} target=\"_blank\" rel=\"noreferrer noopener\" className={linkClass}>\n {short}\n </a>\n ) : (\n short\n ),\n });\n }\n if (report.ci) {\n items.push({\n label: \"CI\",\n value: report.ci.url ? (\n <a href={report.ci.url} target=\"_blank\" rel=\"noreferrer noopener\" className={linkClass}>\n {ciDisplayName(report.ci.name)}\n {report.ci.buildNumber ? ` #${report.ci.buildNumber}` : \"\"}\n </a>\n ) : (\n `${ciDisplayName(report.ci.name)}${report.ci.buildNumber ? ` #${report.ci.buildNumber}` : \"\"}`\n ),\n });\n }\n if (report.ci?.prNumber) {\n const url = prUrl(report.ci);\n const label = `#${report.ci.prNumber}`;\n items.push({\n label: \"PR\",\n value: url ? (\n <a href={url} target=\"_blank\" rel=\"noreferrer noopener\" className={linkClass}>\n {label}\n </a>\n ) : (\n label\n ),\n });\n }\n\n // A \"slowest\" list needs a field to rank: below a handful of timed scenarios\n // it just repeats the run in a different order.\n const slowest = slowestScenarios(report, 5);\n const showSlowest = slowest.length >= 3;\n\n if (items.length === 0 && !showSlowest) return null;\n\n return (\n // Run metadata is useful but secondary to \"what failed\" — tuck it into a\n // collapsed disclosure so it doesn't push the result down. Native <details>\n // so it works with no JS (the SSR/no-hydration report still toggles).\n <details data-es-meta-card className=\"es-run-details group rounded-lg border border-border bg-card text-xs\">\n <summary className=\"flex cursor-pointer list-none select-none items-center gap-1.5 px-4 py-2 font-medium text-muted-foreground [&::-webkit-details-marker]:hidden\">\n <span aria-hidden className=\"text-xs transition-transform group-open:rotate-90\">▸</span>\n Run details\n </summary>\n <dl className=\"flex flex-wrap gap-x-5 gap-y-2 border-t border-border px-4 py-3 text-muted-foreground\" aria-label=\"Run metadata\">\n {items.map((item) => (\n <div key={item.label} className=\"flex items-baseline gap-1.5\">\n <dt className=\"font-medium\">{item.label}</dt>\n <dd className=\"font-mono text-foreground\">{item.value}</dd>\n </div>\n ))}\n </dl>\n {showSlowest ? (\n <div className=\"border-t border-border px-4 py-3\">\n <div className=\"mb-1.5 font-medium text-muted-foreground\">Slowest scenarios</div>\n <ol className=\"flex flex-col gap-1\" aria-label=\"Slowest scenarios\">\n {slowest.map((s) => (\n <li key={s.id} className=\"flex items-baseline justify-between gap-4\">\n <a href={`#${s.id}`} className=\"min-w-0 text-primary underline underline-offset-2\">\n {s.title}\n </a>\n <span className=\"shrink-0 font-mono tabular-nums text-muted-foreground\">\n {formatDuration(s.durationMs)}\n </span>\n </li>\n ))}\n </ol>\n </div>\n ) : null}\n </details>\n );\n}\n","import type { ReportSummary as ReportSummaryT } from \"executable-stories-core\";\nimport { useReport } from \"../hooks/useReport\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportSummaryProps {\n className?: string;\n}\n\nexport function ReportSummary({ className }: ReportSummaryProps) {\n const report = useReport();\n return (\n <ReportSummaryView\n summary={report.summary}\n {...(className !== undefined && { className })}\n ariaLabel=\"Run summary\"\n />\n );\n}\n\nexport interface ReportSummaryViewProps {\n summary: ReportSummaryT;\n className?: string;\n ariaLabel?: string;\n}\n\n/**\n * A single stat card. All cards share the neutral card surface; the status\n * *number* carries the colour (`--es-pass/fail/skip/pend`, mapped to Tailwind\n * in tailwind.css) and a matching leading dot. This drops the earlier pastel\n * fills for the flatter, dashboard-style KPI treatment — a mono micro-label\n * above an oversized tabular number.\n */\nconst TONE = {\n total: { num: \"text-foreground\", dot: \"bg-muted-foreground/50\" },\n passed: { num: \"text-pass\", dot: \"bg-pass\" },\n failed: { num: \"text-fail\", dot: \"bg-fail\" },\n skipped: { num: \"text-skip\", dot: \"bg-skip\" },\n pending: { num: \"text-pend\", dot: \"bg-pend\" },\n} as const;\n\nexport function ReportSummaryView({ summary, className, ariaLabel }: ReportSummaryViewProps) {\n const cards: Array<{ status: keyof typeof TONE; label: string; value: number }> = [\n { status: \"total\", label: \"Total\", value: summary.total },\n { status: \"passed\", label: \"Passed\", value: summary.passed },\n { status: \"failed\", label: \"Failed\", value: summary.failed },\n { status: \"skipped\", label: \"Skipped\", value: summary.skipped },\n ];\n if (summary.pending > 0) {\n cards.push({ status: \"pending\", label: \"Pending\", value: summary.pending });\n }\n return (\n <dl\n className={cn(\n \"grid grid-cols-2 gap-3\",\n // Columns follow the card count so the row is always full — 5 statuses\n // (pending present) never leave a lone orphan card below a row of four.\n cards.length === 5 ? \"sm:grid-cols-5\" : \"sm:grid-cols-4\",\n className,\n )}\n aria-label={ariaLabel}\n >\n {cards.map((c) => {\n const tone = TONE[c.status];\n return (\n <div\n key={c.status}\n data-status={c.status}\n className=\"rounded-lg border bg-card px-4 py-3\"\n >\n <dt className=\"flex items-center gap-1.5 font-mono text-[11px] font-medium uppercase tracking-wider text-muted-foreground\">\n <span className={cn(\"size-1.5 shrink-0 rounded-full\", tone.dot)} aria-hidden=\"true\" />\n {c.label}\n </dt>\n <dd className={cn(\"mt-2 text-3xl font-semibold leading-none tracking-tight tabular-nums\", tone.num)}>\n {c.value}\n </dd>\n </div>\n );\n })}\n </dl>\n );\n}\n","import type { ReportParseError } from \"../result\";\n\nexport interface ReportSchemaErrorProps {\n error: ReportParseError;\n}\n\nexport function ReportSchemaError({ error }: ReportSchemaErrorProps) {\n return (\n <section className=\"es-schema-error\" role=\"alert\" aria-live=\"assertive\">\n <p>\n <strong>Report could not be displayed.</strong>\n </p>\n <p>{error.message}</p>\n {error.code === \"SCHEMA_VERSION_MISMATCH\" ? (\n <p>\n The report bundle is newer than this version of <code>executable-stories-react</code>.\n Upgrade the package, or regenerate the report with an older formatters CLI.\n </p>\n ) : null}\n {error.issues && error.issues.length > 0 ? (\n <details>\n <summary>{error.issues.length} validation issue{error.issues.length === 1 ? \"\" : \"s\"}</summary>\n <pre>\n {error.issues\n .slice(0, 20)\n .map((i) => `${i.path}: ${i.message}`)\n .join(\"\\n\")}\n </pre>\n </details>\n ) : null}\n </section>\n );\n}\n","import type { ReactNode } from \"react\";\nimport type { ReportParseError } from \"../result\";\nimport { cn } from \"../lib/utils\";\nimport { ReportSummary } from \"./ReportSummary\";\nimport { ReportMeta } from \"./ReportMeta\";\nimport { ReportSchemaError } from \"./ReportSchemaError\";\n\n/**\n * The report's title block — `<h1>` + summary + meta. Shared by the static\n * `Report` header and the interactive `ReportInteractive` header so the two\n * views can't drift on the no-JS fallback.\n */\nexport function ReportTitleBlock({ title }: { title?: string }) {\n return (\n <>\n <h1>{title ?? \"Story Report\"}</h1>\n <ReportSummary />\n <ReportMeta />\n </>\n );\n}\n\n/**\n * The `<main>` landmark shown when the report failed to parse. Both entrypoints\n * render the identical shell on a `Result` error, so it lives here once.\n */\nexport function ReportErrorShell({\n error,\n className,\n title,\n dataTheme,\n}: {\n error: ReportParseError;\n className?: string;\n title?: string;\n dataTheme?: \"light\" | \"dark\";\n}): ReactNode {\n return (\n <main className={cn(\"es-report\", className)} aria-label={title ?? \"Test report\"} data-theme={dataTheme}>\n <ReportSchemaError error={error} />\n </main>\n );\n}\n","// Subpath imports: the core package root pulls in Node-only converters\n// (node:crypto), which breaks browser bundles — same rule as ReportStoryboard.\nimport { deriveSpanGraph, spanGraphNodeMark, spanGraphToMermaid } from \"executable-stories-core/span-graph\";\nimport type { SpanGraphKind, SpanGraphNode } from \"executable-stories-core/span-graph\";\nimport { useMemo } from \"react\";\nimport { useReport } from \"../hooks/useReport\";\nimport { DocMermaid } from \"./doc/DocMermaid\";\nimport { cn } from \"../lib/utils\";\n\nconst LANE_LABEL: Record<SpanGraphKind, string> = {\n edge: \"Edge\",\n service: \"Service\",\n queue: \"Queue\",\n datastore: \"Data\",\n};\n\nconst MARK_LABEL = {\n failing: \"Failing\",\n added: \"New\",\n changed: \"Changed\",\n} as const;\n\nconst MARK_CLASS = {\n failing: \"text-fail\",\n added: \"text-pass\",\n changed: \"text-pend\",\n} as const;\n\nfunction MarkBadge({ node }: { node: SpanGraphNode }) {\n const mark = spanGraphNodeMark(node);\n if (!mark) return null;\n return (\n <span className={cn(\"ml-2 text-xs font-medium\", MARK_CLASS[mark])}>{MARK_LABEL[mark]}</span>\n );\n}\n\n/**\n * The architecture the run exercised, drawn from its OTel spans.\n *\n * Every other picture of a system's shape is inferred — from the folder tree,\n * the import graph, or a model reading a diff — and so has to be labelled as\n * unverified when it sits beside a scenario that executed. This one is not: a\n * component is here because a span named it during a run, and the scenarios\n * that put it there are listed beside it and link to their own cards.\n *\n * Renders nothing when the run carries no spans, which is most runs. A section\n * saying \"no diagram\" in every report of every uninstrumented suite is worse\n * than no section.\n *\n * Hydration-free: the derivation is pure and the links are plain anchors, so\n * this renders identically in the static report, the interactive island, and\n * the Astro story pages.\n */\nexport function ReportSpanGraph() {\n const report = useReport();\n // Memoised on the report, not recomputed per render: the interactive island\n // re-renders on every keystroke in the search box, and this walks every span\n // of every scenario. The report object is stable for the life of the view, so\n // the graph is derived once.\n const { code, graph, titleById } = useMemo(() => {\n const scenarios = report.features.flatMap((feature) => feature.scenarios);\n const derived = deriveSpanGraph(scenarios);\n return {\n graph: derived,\n code: spanGraphToMermaid(derived),\n titleById: new Map(scenarios.map((scenario) => [scenario.id, scenario.title])),\n };\n }, [report]);\n\n if (code === \"\") return null;\n\n return (\n <section className=\"es-span-graph mt-6\" aria-labelledby=\"es-span-graph-heading\">\n <h2 id=\"es-span-graph-heading\" className=\"text-base font-semibold text-foreground\">\n Architecture, as it ran\n </h2>\n <p className=\"mt-1 text-sm text-muted-foreground\">\n Derived from this run&rsquo;s traces. Every component was named by a span while a\n scenario ran, so nothing here is inferred from the code. Instrumented, exercised\n paths only: a component no scenario reaches does not appear.\n </p>\n\n <DocMermaid entry={{ kind: \"mermaid\", phase: \"static\", code }} />\n\n <table className=\"mt-2 w-full border-collapse text-left text-sm\">\n <caption className=\"sr-only\">\n Each component and the scenarios that exercised it\n </caption>\n <thead>\n <tr className=\"text-xs text-muted-foreground\">\n <th scope=\"col\" className=\"py-1 pr-4 font-medium\">\n Component\n </th>\n <th scope=\"col\" className=\"py-1 pr-4 font-medium\">\n Lane\n </th>\n <th scope=\"col\" className=\"py-1 font-medium\">\n Covered by\n </th>\n </tr>\n </thead>\n <tbody>\n {graph.nodes.map((node) => (\n <tr key={node.id} className=\"border-t border-border align-top\">\n <th scope=\"row\" className=\"py-1.5 pr-4 font-mono text-xs font-normal\">\n {node.id}\n <MarkBadge node={node} />\n </th>\n <td className=\"py-1.5 pr-4 text-xs text-muted-foreground\">\n {LANE_LABEL[node.kind]}\n </td>\n <td className=\"py-1.5\">\n <ul className=\"flex flex-col gap-0.5\">\n {node.scenarioIds.map((id) => (\n <li key={id}>\n {/* The card sets id={scenario.id}, so this jumps to it. */}\n <a href={`#${id}`} className=\"text-xs text-link underline underline-offset-2 hover:text-foreground\">\n {titleById.get(id) ?? id}\n </a>\n </li>\n ))}\n </ul>\n </td>\n </tr>\n ))}\n </tbody>\n </table>\n </section>\n );\n}\n","\"use client\"\n\nimport * as React from \"react\"\nimport { Switch as SwitchPrimitive } from \"@base-ui/react/switch\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Official shadcn Switch, ported to Base UI's Switch primitive (Radix's\n// `data-[state=checked]` becomes Base UI's `data-[checked]`/`data-[unchecked]`).\n// Same porting pattern as checkbox.tsx / toggle-group.tsx across ui/.\nfunction Switch({\n className,\n ...props\n}: React.ComponentProps<typeof SwitchPrimitive.Root>) {\n return (\n <SwitchPrimitive.Root\n data-slot=\"switch\"\n className={cn(\n \"peer inline-flex h-[1.15rem] w-8 shrink-0 items-center rounded-full border border-transparent shadow-xs outline-none transition-all focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 data-[checked]:bg-primary data-[unchecked]:bg-input\",\n className,\n )}\n {...props}\n >\n <SwitchPrimitive.Thumb\n data-slot=\"switch-thumb\"\n className=\"pointer-events-none block size-4 rounded-full bg-background ring-0 transition-transform data-[checked]:translate-x-[calc(100%-2px)] data-[unchecked]:translate-x-0\"\n />\n </SwitchPrimitive.Root>\n )\n}\n\nexport { Switch }\n","\"use client\"\n\nimport * as React from \"react\"\nimport { ToggleGroup as ToggleGroupPrimitive } from \"@base-ui/react/toggle-group\"\nimport { Toggle as TogglePrimitive } from \"@base-ui/react/toggle\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\n// Segmented control on Base UI's ToggleGroup: a muted rounded track holding\n// toggle \"pills\". The active item lifts to a `bg-background` surface with a\n// subtle shadow (the shadcn Tabs look). Base UI's group holds an array value and\n// its items are `Toggle` primitives (there is no `ToggleGroup.Item`), so\n// ToggleGroupItem wraps Toggle. Radix's `data-[state=on]` is Base UI's\n// `data-[pressed]`.\nconst toggleItemVariants = cva(\n \"inline-flex items-center justify-center gap-1.5 rounded-md font-medium whitespace-nowrap text-muted-foreground transition-[color,background-color,box-shadow] outline-none hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[pressed]:bg-background data-[pressed]:text-foreground data-[pressed]:shadow-sm [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n size: {\n default: \"h-9 px-3 text-sm\",\n sm: \"h-8 px-2.5 text-[0.82rem]\",\n },\n },\n defaultVariants: { size: \"default\" },\n },\n)\n\nconst ToggleGroupContext = React.createContext<VariantProps<typeof toggleItemVariants>>({\n size: \"default\",\n})\n\nfunction ToggleGroup({\n className,\n size,\n children,\n ...props\n}: ToggleGroupPrimitive.Props & VariantProps<typeof toggleItemVariants>) {\n return (\n <ToggleGroupPrimitive\n data-slot=\"toggle-group\"\n className={cn(\"flex w-fit items-center gap-0.5 rounded-lg bg-muted p-0.5\", className)}\n {...props}\n >\n <ToggleGroupContext.Provider value={{ size }}>{children}</ToggleGroupContext.Provider>\n </ToggleGroupPrimitive>\n )\n}\n\nfunction ToggleGroupItem({\n className,\n children,\n size,\n ...props\n}: TogglePrimitive.Props & VariantProps<typeof toggleItemVariants>) {\n const context = React.useContext(ToggleGroupContext)\n return (\n <TogglePrimitive\n data-slot=\"toggle-group-item\"\n className={cn(toggleItemVariants({ size: context.size ?? size }), \"flex-1 shrink-0\", className)}\n {...props}\n >\n {children}\n </TogglePrimitive>\n )\n}\n\nexport { ToggleGroup, ToggleGroupItem }\n","import { useMemo, type ReactNode } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\nimport type { BuiltinRenderers, CustomRenderers } from \"../renderers\";\nimport { ReportContext, type ReportContextValue } from \"./ReportContext\";\nimport { narrativeBlockRenderers } from \"../components/doc/NarrativeBlocks\";\n\nexport interface ReportRootProps {\n report: StoryReport;\n customRenderers?: CustomRenderers;\n renderers?: BuiltinRenderers;\n children: ReactNode;\n}\n\nconst EMPTY_RENDERERS: BuiltinRenderers = {};\n\nexport function ReportRoot({\n report,\n customRenderers,\n renderers,\n children,\n}: ReportRootProps) {\n const value = useMemo<ReportContextValue>(\n () => ({\n report,\n // Narrative blocks render everywhere the report does (static SSR, the\n // island, Astro) without every host wiring them up. A host renderer for\n // the same type still wins.\n customRenderers: { ...narrativeBlockRenderers, ...customRenderers },\n renderers: renderers ?? EMPTY_RENDERERS,\n }),\n [report, customRenderers, renderers],\n );\n return <ReportContext.Provider value={value}>{children}</ReportContext.Provider>;\n}\n","/**\n * Renderers for the two narrative block types an agent reaches for when it\n * explains a change: a file map and a data shape.\n *\n * They ride on `story.custom({ type, data })`, so every adapter can already\n * emit them with no API change; only the renderer is new. Register them with\n * `customRenderers` (the standalone report island does this by default).\n *\n * These blocks describe, they do not prove. Nothing here executed, so a block\n * whose `data.authored` says an agent wrote it renders a visible marker. A\n * picture that looks as trustworthy as a passing test, without being one, is\n * the failure mode this whole report exists to avoid.\n */\n\nimport type { ReportDocCustom } from \"executable-stories-core\";\nimport { Badge } from \"../ui/badge\";\nimport { cn } from \"../../lib/utils\";\n\nexport const FILE_TREE_TYPE = \"file-tree\";\nexport const DATA_MODEL_TYPE = \"data-model\";\n\n/** Change annotation shared by both blocks. */\ntype ChangeKind = \"added\" | \"modified\" | \"removed\" | \"renamed\";\n\nfunction isChangeKind(value: unknown): value is ChangeKind {\n return value === \"added\" || value === \"modified\" || value === \"removed\" || value === \"renamed\";\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction str(value: unknown): string | undefined {\n return typeof value === \"string\" && value !== \"\" ? value : undefined;\n}\n\n/**\n * \"Written by an agent, not verified by a run.\" Only rendered when the author\n * says so; there is no way to detect it after the fact, which is exactly why\n * the authoring skills are told to set it.\n */\nfunction AuthoredMarker({ authored }: { authored?: string }) {\n if (authored !== \"agent\") return null;\n return (\n <Badge variant=\"outline\" className=\"border-border text-[10px] text-muted-foreground\">\n AI-authored, not verified by a run\n </Badge>\n );\n}\n\nfunction BlockFrame({\n title,\n authored,\n children,\n}: {\n title?: string;\n authored?: string;\n children: React.ReactNode;\n}) {\n return (\n <figure className=\"my-3\">\n {title || authored === \"agent\" ? (\n <figcaption className=\"mb-1.5 flex flex-wrap items-center gap-2\">\n {title ? <span className=\"text-xs font-medium text-muted-foreground\">{title}</span> : null}\n <AuthoredMarker authored={authored} />\n </figcaption>\n ) : null}\n {children}\n </figure>\n );\n}\n\n/**\n * Deliberately uncoloured. In this report colour carries test status, so a\n * green \"added\" badge beside a failing scenario would read as a pass. The word\n * does the work.\n */\nfunction ChangeBadge({ change }: { change: ChangeKind }) {\n return (\n <Badge variant=\"tag\" className=\"text-[10px]\">\n {change}\n </Badge>\n );\n}\n\n// ---------------------------------------------------------------------------\n// file-tree\n// ---------------------------------------------------------------------------\n\ninterface FileEntry {\n path: string;\n change?: ChangeKind;\n note?: string;\n}\n\nexport interface FileTreeData {\n title?: string;\n authored?: string;\n files: FileEntry[];\n}\n\nexport function parseFileTree(data: unknown): FileTreeData | undefined {\n if (!isRecord(data) || !Array.isArray(data.files)) return undefined;\n const files: FileEntry[] = [];\n for (const raw of data.files) {\n // A bare string is a path; anything without one is not a file.\n if (typeof raw === \"string\") {\n if (raw) files.push({ path: raw });\n continue;\n }\n if (!isRecord(raw)) continue;\n const path = str(raw.path);\n if (!path) continue;\n files.push({\n path,\n change: isChangeKind(raw.change) ? raw.change : undefined,\n note: str(raw.note),\n });\n }\n if (files.length === 0) return undefined;\n return { title: str(data.title), authored: str(data.authored), files };\n}\n\ninterface TreeNode {\n name: string;\n children: Map<string, TreeNode>;\n file?: FileEntry;\n}\n\n/** Flat paths in, nested directories out. Sorting puts folders before files. */\nfunction buildTree(files: FileEntry[]): TreeNode {\n const root: TreeNode = { name: \"\", children: new Map() };\n for (const file of files) {\n const segments = file.path.split(\"/\").filter(Boolean);\n let node = root;\n segments.forEach((segment, index) => {\n let child = node.children.get(segment);\n if (!child) {\n child = { name: segment, children: new Map() };\n node.children.set(segment, child);\n }\n if (index === segments.length - 1) child.file = file;\n node = child;\n });\n }\n return root;\n}\n\nfunction sortedChildren(node: TreeNode): TreeNode[] {\n return [...node.children.values()].sort((a, b) => {\n const aDir = a.children.size > 0;\n const bDir = b.children.size > 0;\n if (aDir !== bDir) return aDir ? -1 : 1;\n return a.name.localeCompare(b.name);\n });\n}\n\nfunction TreeBranch({ node, depth }: { node: TreeNode; depth: number }) {\n const children = sortedChildren(node);\n return (\n <ul className={cn(\"space-y-0.5\", depth > 0 && \"ml-3 border-l border-border/60 pl-3\")}>\n {children.map((child) => {\n const isDir = child.children.size > 0;\n return (\n <li key={child.name}>\n <div className=\"flex flex-wrap items-baseline gap-2\">\n <span\n className={cn(\n \"font-mono text-xs\",\n isDir ? \"text-muted-foreground\" : \"text-foreground\",\n )}\n >\n {isDir ? `${child.name}/` : child.name}\n </span>\n {child.file?.change ? <ChangeBadge change={child.file.change} /> : null}\n {child.file?.note ? (\n <span className=\"text-xs text-muted-foreground\">{child.file.note}</span>\n ) : null}\n </div>\n {isDir ? <TreeBranch node={child} depth={depth + 1} /> : null}\n </li>\n );\n })}\n </ul>\n );\n}\n\nexport function FileTreeBlock({ entry }: { entry: ReportDocCustom }) {\n const data = parseFileTree(entry.data);\n if (!data) return <UnreadableBlock entry={entry} />;\n return (\n <BlockFrame title={data.title ?? \"Files changed\"} authored={data.authored}>\n <div tabIndex={0} className=\"overflow-x-auto rounded-md border border-border bg-card p-3\">\n <TreeBranch node={buildTree(data.files)} depth={0} />\n </div>\n </BlockFrame>\n );\n}\n\n// ---------------------------------------------------------------------------\n// data-model\n// ---------------------------------------------------------------------------\n\ninterface ModelField {\n name: string;\n type?: string;\n note?: string;\n change?: ChangeKind;\n}\n\nexport interface DataModelData {\n title?: string;\n authored?: string;\n name?: string;\n fields: ModelField[];\n}\n\nexport function parseDataModel(data: unknown): DataModelData | undefined {\n if (!isRecord(data) || !Array.isArray(data.fields)) return undefined;\n const fields: ModelField[] = [];\n for (const raw of data.fields) {\n if (!isRecord(raw)) continue;\n const name = str(raw.name);\n if (!name) continue;\n fields.push({\n name,\n type: str(raw.type),\n note: str(raw.note),\n change: isChangeKind(raw.change) ? raw.change : undefined,\n });\n }\n if (fields.length === 0) return undefined;\n return {\n title: str(data.title),\n authored: str(data.authored),\n name: str(data.name),\n fields,\n };\n}\n\nexport function DataModelBlock({ entry }: { entry: ReportDocCustom }) {\n const data = parseDataModel(entry.data);\n if (!data) return <UnreadableBlock entry={entry} />;\n const hasNotes = data.fields.some((f) => f.note);\n return (\n <BlockFrame title={data.title ?? data.name ?? \"Data model\"} authored={data.authored}>\n <div tabIndex={0} className=\"overflow-x-auto rounded-md border border-border\">\n <table className=\"w-full border-collapse text-sm\">\n <thead>\n <tr className=\"bg-muted/50\">\n <th scope=\"col\" className=\"border-b border-border px-3 py-2 text-left font-semibold\">\n Field\n </th>\n <th scope=\"col\" className=\"border-b border-border px-3 py-2 text-left font-semibold\">\n Type\n </th>\n {hasNotes ? (\n <th scope=\"col\" className=\"border-b border-border px-3 py-2 text-left font-semibold\">\n Note\n </th>\n ) : null}\n </tr>\n </thead>\n <tbody>\n {data.fields.map((field) => (\n <tr key={field.name}>\n <td className=\"border-b border-border px-3 py-2\">\n <span className=\"flex flex-wrap items-center gap-2\">\n <span className=\"font-mono text-xs text-foreground\">{field.name}</span>\n {field.change ? <ChangeBadge change={field.change} /> : null}\n </span>\n </td>\n <td className=\"border-b border-border px-3 py-2 font-mono text-xs text-muted-foreground\">\n {field.type ?? \"\"}\n </td>\n {hasNotes ? (\n <td className=\"border-b border-border px-3 py-2 text-foreground\">\n {field.note ?? \"\"}\n </td>\n ) : null}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </BlockFrame>\n );\n}\n\n// ---------------------------------------------------------------------------\n\n/**\n * Shape we could not read. Show the raw data rather than nothing: a malformed\n * block is a bug in whatever wrote it, and hiding it hides the bug.\n */\nfunction UnreadableBlock({ entry }: { entry: ReportDocCustom }) {\n return (\n <div className=\"my-2\" data-type={entry.type}>\n <p className=\"mb-1 text-xs font-medium text-muted-foreground\">\n {entry.type} (unrecognised shape)\n </p>\n <pre\n tabIndex={0}\n className=\"overflow-x-auto rounded-md bg-muted p-3 font-mono text-xs text-foreground\"\n >\n {safeStringify(entry.data)}\n </pre>\n </div>\n );\n}\n\nfunction safeStringify(value: unknown): string {\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n}\n\n/**\n * The narrative block renderers, ready to spread into `customRenderers`.\n * Consumer-supplied renderers for the same type win, so a project can swap\n * either one out.\n */\nexport const narrativeBlockRenderers = {\n [FILE_TREE_TYPE]: (entry: ReportDocCustom) => <FileTreeBlock entry={entry} />,\n [DATA_MODEL_TYPE]: (entry: ReportDocCustom) => <DataModelBlock entry={entry} />,\n};\n","/**\n * View state in the URL, so a filtered report survives a refresh and can be\n * shared as a link.\n *\n * It lives in the HASH, not the query string, because the flagship surface is a\n * single HTML file opened from disk. A `file://` document has an opaque origin,\n * and Chrome refuses `history.pushState`/`replaceState` when the URL argument\n * changes anything but the fragment there. The fragment is the one part every\n * browser lets us rewrite in place.\n *\n * Format: `#<anchor>?<params>` — the anchor half stays exactly what it has\n * always been, a scenario id deep link, so existing permalinks keep working and\n * a link with no filters is unchanged.\n */\n\nexport type UrlStatusFilter = \"all\" | \"passed\" | \"failed\" | \"skipped\" | \"pending\";\n\nexport interface ReportUrlState {\n query: string;\n status: UrlStatusFilter;\n /** Scenario tag filter; a scenario matches if it carries ANY of these. */\n tags: string[];\n detail: \"full\" | \"minimal\";\n}\n\nexport const DEFAULT_URL_STATE: ReportUrlState = {\n query: \"\",\n status: \"all\",\n tags: [],\n detail: \"full\",\n};\n\nconst STATUSES: readonly UrlStatusFilter[] = [\"all\", \"passed\", \"failed\", \"skipped\", \"pending\"];\n\nexport interface SplitHash {\n /** Scenario id deep link (may be empty). */\n anchor: string;\n params: URLSearchParams;\n}\n\nexport function splitHash(hash: string): SplitHash {\n const raw = hash.replace(/^#/, \"\");\n const split = raw.indexOf(\"?\");\n if (split === -1) return { anchor: raw, params: new URLSearchParams() };\n return { anchor: raw.slice(0, split), params: new URLSearchParams(raw.slice(split + 1)) };\n}\n\nexport function decodeUrlState(params: URLSearchParams): ReportUrlState {\n const status = params.get(\"status\");\n const tags = params.get(\"tags\");\n return {\n query: params.get(\"q\") ?? DEFAULT_URL_STATE.query,\n status: STATUSES.includes(status as UrlStatusFilter)\n ? (status as UrlStatusFilter)\n : DEFAULT_URL_STATE.status,\n tags: tags ? tags.split(\",\").filter(Boolean) : [],\n detail: params.get(\"docs\") === \"0\" ? \"minimal\" : \"full\",\n };\n}\n\n/** Only non-default values reach the URL, so an untouched report has a clean one. */\nexport function encodeUrlState(state: ReportUrlState): string {\n const params = new URLSearchParams();\n if (state.query) params.set(\"q\", state.query);\n if (state.status !== \"all\") params.set(\"status\", state.status);\n if (state.tags.length > 0) params.set(\"tags\", state.tags.join(\",\"));\n if (state.detail === \"minimal\") params.set(\"docs\", \"0\");\n return params.toString();\n}\n\nexport function formatHash(anchor: string, params: string): string {\n if (params) return `#${anchor}?${params}`;\n return anchor ? `#${anchor}` : \"\";\n}\n\n/**\n * Rewrite the fragment without adding a history entry or reloading. Falls back\n * to assigning `location.hash` where the History API refuses the change (a\n * `file://` document in Chrome); that costs a history entry, which is why every\n * caller debounces keystroke-rate updates.\n */\nexport function writeHash(anchor: string, params: string): void {\n if (typeof window === \"undefined\") return;\n const next = formatHash(anchor, params);\n if (next === window.location.hash) return;\n // No fragment at all: strip it rather than leaving a bare \"#\".\n const url = next || window.location.href.split(\"#\")[0];\n try {\n window.history.replaceState(window.history.state, \"\", url);\n } catch {\n window.location.hash = next.slice(1);\n }\n}\n","/**\n * Scroll helpers that honour `prefers-reduced-motion`.\n *\n * JS `scrollIntoView({ behavior: \"smooth\" })` bypasses the CSS\n * `scroll-behavior` cascade, so reduced-motion users must be handled\n * explicitly here rather than in the stylesheet.\n */\n\nimport { splitHash, writeHash } from \"./hash-state\";\n\n/** True when the user has asked the OS to minimise non-essential motion. */\nexport function prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\" || typeof window.matchMedia !== \"function\") {\n return false;\n }\n return window.matchMedia(\"(prefers-reduced-motion: reduce)\").matches;\n}\n\nexport interface ScrollToScenarioOptions {\n /** Replace the URL hash with `#<scenarioId>` after scrolling. Defaults to true. */\n updateHash?: boolean;\n}\n\n/**\n * Scrolls a scenario into view by id. No-op in SSR or when the element is\n * absent. Uses an instant jump for reduced-motion users, smooth otherwise.\n */\nexport function scrollToScenarioId(\n scenarioId: string,\n options: ScrollToScenarioOptions = {},\n): void {\n if (typeof document === \"undefined\") return;\n const el = document.getElementById(scenarioId);\n if (!el) return;\n el.scrollIntoView({\n behavior: prefersReducedMotion() ? \"auto\" : \"smooth\",\n block: \"start\",\n });\n if (options.updateHash !== false) {\n // Keep any filter params already in the fragment: jumping to a scenario\n // must not silently drop the filters that surfaced it.\n writeHash(scenarioId, splitHash(window.location.hash).params.toString());\n }\n}\n","/**\n * Result<T> — explicit success/error type matching the cookbook convention.\n *\n * Used at the boundary where a StoryReport is parsed: the consumer hands us\n * an unknown value (file contents, fetch body, prop) and we return a Result.\n */\nimport type { StoryReport } from \"executable-stories-core\";\n\nexport type Result<T, E = ReportParseError> =\n | { ok: true; data: T }\n | { ok: false; error: E };\n\nexport interface ReportParseError {\n message: string;\n code: ReportParseErrorCode;\n issues?: readonly { path: string; message: string }[];\n}\n\nexport type ReportParseErrorCode =\n | \"INVALID_INPUT\"\n | \"SCHEMA_VERSION_MISMATCH\"\n | \"VALIDATION_FAILED\";\n\nexport const ok = <T>(data: T): Result<T> => ({ ok: true, data });\nexport const err = (error: ReportParseError): Result<never> => ({ ok: false, error });\n\n/**\n * Normalize the `StoryReport | Result<StoryReport>` prop accepted across the\n * render entrypoints (`Report`, `ReportInteractive`, `renderReportToHtml`) into\n * a single `Result`. A bare report becomes `ok(report)`; an already-wrapped\n * value passes through. One place owns the \"is this a Result?\" discrimination.\n */\nexport function unwrapReport(value: StoryReport | Result<StoryReport>): Result<StoryReport> {\n if (\n typeof value === \"object\" &&\n value !== null &&\n \"ok\" in value &&\n typeof (value as { ok: unknown }).ok === \"boolean\"\n ) {\n return value as Result<StoryReport>;\n }\n return ok(value as StoryReport);\n}\n","/**\n * Pure functions for filtering a StoryReport by a search query.\n * Used by <ReportInteractive>. Kept side-effect-free so it can be unit-tested.\n */\n\nimport type {\n ReportScenario,\n ReportFeature,\n StoryReport,\n} from \"executable-stories-core\";\nimport type { UrlStatusFilter } from \"../lib/hash-state\";\n\n/** Defined with the URL codec that has to validate it, so the two can't drift. */\nexport type StatusFilter = UrlStatusFilter;\n\nexport interface FilterCriteria {\n query?: string;\n status?: StatusFilter;\n /** Scenario matches if it carries ANY of these tags (empty = no tag filter). */\n tags?: string[];\n}\n\nexport function normalizeQuery(query: string): string {\n return query.trim().toLowerCase();\n}\n\n/** Unique scenario tags across the whole report, in first-seen order. */\nexport function allTags(report: StoryReport): string[] {\n const seen = new Set<string>();\n for (const feature of report.features) {\n for (const scenario of feature.scenarios) {\n for (const tag of scenario.tags) seen.add(tag);\n }\n }\n return [...seen];\n}\n\n/**\n * What people paste into the search box rarely comes from the report itself: a\n * ticket id from the tracker, a string out of a stack trace, a path from a PR\n * diff. So the query matches those too, not just the title/tags/steps.\n */\nfunction queryMatches(scenario: ReportScenario, q: string, sourceFile?: string): boolean {\n if (q === \"\") return true;\n if (scenario.title.toLowerCase().includes(q)) return true;\n if (sourceFile?.toLowerCase().includes(q)) return true;\n if (scenario.errorMessage?.toLowerCase().includes(q)) return true;\n for (const tag of scenario.tags) {\n if (tag.toLowerCase().includes(q)) return true;\n }\n for (const ticket of scenario.tickets ?? []) {\n if (ticket.id.toLowerCase().includes(q)) return true;\n }\n for (const step of scenario.steps) {\n if (step.text.toLowerCase().includes(q)) return true;\n }\n return false;\n}\n\nfunction scenarioMatches(\n scenario: ReportScenario,\n q: string,\n status: StatusFilter,\n tags: string[],\n sourceFile?: string,\n): boolean {\n if (status !== \"all\" && scenario.status !== status) return false;\n if (tags.length > 0 && !tags.some((t) => scenario.tags.includes(t))) return false;\n return queryMatches(scenario, q, sourceFile);\n}\n\nfunction summarizeScenarios(scenarios: ReportScenario[]) {\n let total = 0,\n passed = 0,\n failed = 0,\n skipped = 0,\n pending = 0,\n durationMs = 0;\n for (const s of scenarios) {\n total += 1;\n durationMs += s.durationMs;\n if (s.status === \"passed\") passed += 1;\n else if (s.status === \"failed\") failed += 1;\n else if (s.status === \"skipped\") skipped += 1;\n else pending += 1;\n }\n return { total, passed, failed, skipped, pending, durationMs };\n}\n\nexport function filterReport(report: StoryReport, criteria: string | FilterCriteria): StoryReport {\n const c: FilterCriteria = typeof criteria === \"string\" ? { query: criteria } : criteria;\n const q = normalizeQuery(c.query ?? \"\");\n const status = c.status ?? \"all\";\n const tags = c.tags ?? [];\n if (q === \"\" && status === \"all\" && tags.length === 0) return report;\n\n const features: ReportFeature[] = [];\n let topTotal = 0,\n topPassed = 0,\n topFailed = 0,\n topSkipped = 0,\n topPending = 0,\n topDuration = 0;\n\n for (const feature of report.features) {\n const matched = feature.scenarios.filter((s) =>\n scenarioMatches(s, q, status, tags, feature.sourceFile),\n );\n if (matched.length === 0) continue;\n const summary = summarizeScenarios(matched);\n features.push({ ...feature, summary, scenarios: matched });\n topTotal += summary.total;\n topPassed += summary.passed;\n topFailed += summary.failed;\n topSkipped += summary.skipped;\n topPending += summary.pending;\n topDuration += summary.durationMs;\n }\n\n return {\n ...report,\n summary: {\n total: topTotal,\n passed: topPassed,\n failed: topFailed,\n skipped: topSkipped,\n pending: topPending,\n durationMs: topDuration,\n },\n features,\n };\n}\n\nexport interface FailureRef {\n featureId: string;\n scenarioId: string;\n scenarioTitle: string;\n errorMessage?: string;\n}\n\n/** The failing scenarios themselves — for handing the whole red set to an agent. */\nexport function failedScenarios(report: StoryReport): ReportScenario[] {\n return report.features.flatMap((f) => f.scenarios.filter((s) => s.status === \"failed\"));\n}\n\nexport function listFailures(report: StoryReport): FailureRef[] {\n const out: FailureRef[] = [];\n for (const feature of report.features) {\n for (const scenario of feature.scenarios) {\n if (scenario.status === \"failed\") {\n const ref: FailureRef = {\n featureId: feature.id,\n scenarioId: scenario.id,\n scenarioTitle: scenario.title,\n };\n if (scenario.errorMessage !== undefined) {\n ref.errorMessage = scenario.errorMessage;\n }\n out.push(ref);\n }\n }\n }\n return out;\n}\n","\"use client\";\n\nimport { Bot, X } from \"lucide-react\";\nimport type { AppliedFilter } from \"./webmcp-tools\";\n\nexport interface ReportAgentFilterNoticeProps {\n applied: AppliedFilter;\n onReset: () => void;\n onDismiss: () => void;\n}\n\n/**\n * Says who moved the page.\n *\n * When an agent calls `filter_scenarios` the list changes under the reader with\n * nothing on screen to explain it. There is no confirmation step in front of\n * that — filtering a read-only report is not a risk worth a dialogue — so this\n * is the alternative: say what was applied, and offer the way back.\n *\n * The caller renders this only while the applied filter still matches the live\n * view state, so the notice disappears on its own the moment the reader touches\n * a filter themselves.\n */\nexport function ReportAgentFilterNotice({\n applied,\n onReset,\n onDismiss,\n}: ReportAgentFilterNoticeProps) {\n const terms: string[] = [];\n if (applied.search) terms.push(`matching “${applied.search}”`);\n if (applied.status !== \"all\") terms.push(applied.status);\n if (applied.tags.length > 0) terms.push(applied.tags.join(\", \"));\n\n return (\n <div\n role=\"status\"\n aria-live=\"polite\"\n className=\"flex flex-wrap items-center gap-x-3 gap-y-1 rounded-md border border-primary/40 bg-primary/5 px-3 py-2 text-sm\"\n >\n <Bot aria-hidden className=\"size-4 shrink-0 text-primary\" />\n <span className=\"min-w-0 flex-1\">\n An agent filtered this report\n {terms.length > 0 ? <> to {terms.join(\" · \")}</> : null} —{\" \"}\n <span className=\"tabular-nums\">\n {applied.matched} of {applied.total} scenarios\n </span>\n .\n </span>\n <button\n type=\"button\"\n onClick={onReset}\n className=\"cursor-pointer rounded-md border border-border px-2 py-1 text-xs hover:bg-muted\"\n >\n Show all\n </button>\n <button\n type=\"button\"\n onClick={onDismiss}\n aria-label=\"Dismiss\"\n className=\"cursor-pointer rounded-md p-1 text-muted-foreground hover:text-foreground\"\n >\n <X aria-hidden className=\"size-4\" />\n </button>\n </div>\n );\n}\n","\"use client\";\n\nimport { useCallback } from \"react\";\nimport type { FailureRef } from \"./filter\";\nimport { scrollToScenarioId } from \"../lib/scroll\";\n\nexport interface ReportFailureBannerProps {\n failures: readonly FailureRef[];\n /** Copies every failure as one agent prompt. Omitted on a static render. */\n onCopyAll?: () => void;\n}\n\nexport function ReportFailureBanner({ failures, onCopyAll }: ReportFailureBannerProps) {\n const first = failures[0];\n\n const jumpToFirst = useCallback(() => {\n if (!first) return;\n scrollToScenarioId(first.scenarioId);\n }, [first]);\n\n if (failures.length === 0) return null;\n\n // A live status region: `role=\"status\"` is not a valid role on <aside>\n // (whose implicit role is `complementary`), so use a <div> to carry it.\n return (\n <div\n className=\"es-failure-banner\"\n role=\"status\"\n aria-live=\"polite\"\n aria-label=\"Failure summary\"\n >\n <span className=\"es-failure-banner-text\">\n <strong>{failures.length}</strong>{\" \"}\n failure{failures.length === 1 ? \"\" : \"s\"}\n </span>\n <button\n type=\"button\"\n className=\"es-failure-banner-jump\"\n onClick={jumpToFirst}\n aria-label=\"View first failure\"\n >\n View first failure ↓\n </button>\n {onCopyAll ? (\n <button\n type=\"button\"\n className=\"es-failure-banner-jump\"\n onClick={onCopyAll}\n aria-label=\"Copy failures for an agent\"\n >\n Copy {failures.length} failure{failures.length === 1 ? \"\" : \"s\"} for an agent\n </button>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport type { StatusFilter } from \"./filter\";\nimport { Badge } from \"@/components/ui/badge\";\nimport { cn } from \"@/lib/utils\";\n\n// Above this many tags the filter list collapses to one row behind a \"+N more\"\n// toggle, so a tag-heavy report doesn't open with a tall grey brick before the\n// content. Small reports (≤ limit) show every tag, no toggle.\nconst TAG_LIMIT = 12;\n\nexport interface ReportFiltersProps {\n /** Status options to show (only those present in the run), with counts. */\n statuses: Array<{ key: StatusFilter; label: string; count: number }>;\n status: StatusFilter;\n onStatus: (status: StatusFilter) => void;\n tags: string[];\n activeTags: string[];\n onToggleTag: (tag: string) => void;\n}\n\nexport function ReportFilters({\n statuses,\n status,\n onStatus,\n tags,\n activeTags,\n onToggleTag,\n}: ReportFiltersProps) {\n // Local view-only state (tag list expanded or collapsed). The parent still\n // owns the domain filters — selected status and active tags — so this doesn't\n // break the component's presentational contract.\n const [showAllTags, setShowAllTags] = useState(false);\n if (statuses.length === 0 && tags.length === 0) return null;\n const tagsCollapsed = tags.length > TAG_LIMIT && !showAllTags;\n const visibleTags = tagsCollapsed ? tags.slice(0, TAG_LIMIT) : tags;\n return (\n <div className=\"flex flex-col gap-2\">\n {statuses.length > 0 ? (\n <div role=\"group\" aria-label=\"Filter by status\" className=\"flex flex-wrap gap-1\">\n {statuses.map((opt) => {\n const active = status === opt.key;\n return (\n <button\n key={opt.key}\n type=\"button\"\n aria-pressed={active}\n onClick={() => onStatus(active && opt.key !== \"all\" ? \"all\" : opt.key)}\n className={cn(\n \"cursor-pointer rounded-md border px-2 py-1 text-xs transition-colors\",\n active\n ? \"border-primary bg-primary text-primary-foreground\"\n : \"border-border text-muted-foreground hover:bg-muted hover:text-foreground\",\n )}\n >\n {opt.label}\n <span className=\"ml-1 font-mono opacity-70\">{opt.count}</span>\n </button>\n );\n })}\n </div>\n ) : null}\n {tags.length > 0 ? (\n <ul aria-label=\"Filter by tag\" className=\"flex flex-wrap items-center gap-1.5\">\n {visibleTags.map((tag) => {\n const active = activeTags.includes(tag);\n return (\n <li key={tag}>\n <button\n type=\"button\"\n aria-pressed={active}\n onClick={() => onToggleTag(tag)}\n className=\"cursor-pointer\"\n >\n {/* Always the `tag` variant (font-mono) so the active state\n only swaps colours, never the font family. Switching to a\n sans variant on select would change the pill's width and\n reflow every sibling. */}\n <Badge\n variant=\"tag\"\n className={cn(\n active && \"border-primary bg-primary text-primary-foreground\",\n )}\n >\n {tag}\n </Badge>\n </button>\n </li>\n );\n })}\n {tags.length > TAG_LIMIT ? (\n <li>\n <button\n type=\"button\"\n aria-expanded={showAllTags}\n onClick={() => setShowAllTags((v) => !v)}\n className=\"cursor-pointer rounded-full px-2 py-0.5 text-xs font-medium text-muted-foreground hover:text-foreground\"\n >\n {tagsCollapsed ? `+${tags.length - TAG_LIMIT} more` : \"Show fewer\"}\n </button>\n </li>\n ) : null}\n </ul>\n ) : null}\n </div>\n );\n}\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport { formatRelativeAge, isReportStale } from \"../lib/provenance\";\n\nexport interface ReportFreshnessProps {\n /** Epoch ms of the run this report documents (see reportLastRunMs). */\n lastRunMs?: number;\n /** CI run URL, linked from the banner so readers can check for newer runs. */\n ciUrl?: string;\n /** Days before the report counts as stale; 0 disables the warning. */\n staleAfterDays: number;\n /** Test seam: fixed \"now\"; defaults to Date.now() on mount. */\n nowMs?: number;\n}\n\n/**\n * The report's freshness signal. Fresh reports get a one-line \"Last verified\n * N ago\" status; reports older than `staleAfterDays` get a warning banner —\n * living documentation is only trustworthy while it is recent.\n *\n * Age is computed on mount (never during server render): the static HTML is\n * generated once but read later, so any age baked in at build time would lie.\n */\nexport function ReportFreshness({ lastRunMs, ciUrl, staleAfterDays, nowMs }: ReportFreshnessProps) {\n const [now, setNow] = useState<number | undefined>(nowMs);\n useEffect(() => {\n if (nowMs === undefined) setNow(Date.now());\n }, [nowMs]);\n\n if (lastRunMs === undefined || now === undefined) return null;\n\n const age = formatRelativeAge(lastRunMs, now);\n const runLink = ciUrl ? (\n <a\n href={ciUrl}\n target=\"_blank\"\n rel=\"noreferrer noopener\"\n className=\"underline underline-offset-2\"\n >\n View CI run\n </a>\n ) : null;\n\n if (isReportStale(lastRunMs, staleAfterDays, now)) {\n return (\n <div className=\"es-stale-banner\" role=\"status\" aria-label=\"Report freshness\">\n <span>\n <strong>Last verified {age}.</strong> This report may no longer match the current\n behavior. Look for a newer run.\n </span>\n {runLink}\n </div>\n );\n }\n\n return (\n <p className=\"es-freshness\" aria-label=\"Report freshness\">\n Verified {age}\n {runLink ? <> · {runLink}</> : null}\n </p>\n );\n}\n","import type { StoryReport } from \"executable-stories-core\";\n\nimport { diffSinceLastRun, type ScenarioHistoryMap, type ScenarioRef } from \"../lib/run-history\";\nimport { cn } from \"@/lib/utils\";\n\nconst MAX_LINKS = 5;\n\nfunction ScenarioLinks({ scenarios, tone }: { scenarios: ScenarioRef[]; tone: string }) {\n return (\n <>\n {scenarios.slice(0, MAX_LINKS).map((s, i) => (\n <span key={s.id}>\n {i > 0 ? \", \" : \"\"}\n <a href={`#${s.id}`} className={cn(\"underline underline-offset-2 hover:no-underline\", tone)}>\n {s.title}\n </a>\n </span>\n ))}\n {scenarios.length > MAX_LINKS ? <span> and {scenarios.length - MAX_LINKS} more</span> : null}\n </>\n );\n}\n\n/**\n * One-line \"what changed since the previous run\" strip for the report header:\n * newly failing, newly passing, and first-seen scenarios, computed from the\n * embedded history store. Renders nothing without a previous run to compare\n * (no --history-file, or the first run with history enabled). Takes the\n * unfiltered report so search and filter chips never change the delta.\n */\nexport function ReportLastRunDelta({\n history,\n report,\n}: {\n history: ScenarioHistoryMap | undefined;\n report: StoryReport;\n}) {\n if (!history) return null;\n const scenarios = report.features.flatMap((f) => f.scenarios.map((s) => ({ id: s.id, title: s.title })));\n const delta = diffSinceLastRun(history, scenarios);\n if (!delta) return null;\n\n const { newlyFailing, newlyPassing, added } = delta;\n if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) {\n return (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"es-last-run-delta\">\n Since last run: no behavior changes.\n </p>\n );\n }\n\n return (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"es-last-run-delta\">\n <span className=\"font-medium text-foreground\">Since last run:</span>\n {newlyFailing.length > 0 ? (\n <span className=\"ml-2 text-fail\">\n {newlyFailing.length} newly failing (<ScenarioLinks scenarios={newlyFailing} tone=\"text-fail\" />)\n </span>\n ) : null}\n {newlyPassing.length > 0 ? (\n <span className=\"ml-2 text-pass\">\n {newlyPassing.length} fixed (<ScenarioLinks scenarios={newlyPassing} tone=\"text-pass\" />)\n </span>\n ) : null}\n {added.length > 0 ? <span className=\"ml-2\">{added.length} new</span> : null}\n </p>\n );\n}\n","\"use client\";\n\nimport {\n forwardRef,\n useId,\n type ChangeEvent,\n type KeyboardEvent,\n} from \"react\";\nimport { Search } from \"lucide-react\";\nimport { Input } from \"@/components/ui/input\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface ReportSearchProps {\n value: string;\n onChange: (next: string) => void;\n matchedCount?: number;\n totalCount?: number;\n placeholder?: string;\n className?: string;\n}\n\nexport const ReportSearch = forwardRef<HTMLInputElement, ReportSearchProps>(\n function ReportSearch(props, ref) {\n const {\n value,\n onChange,\n matchedCount,\n totalCount,\n placeholder = \"Search scenarios, tags, tickets, errors…\",\n className,\n } = props;\n const inputId = useId();\n // Only surface a count once the user is actually filtering — the \"All N\"\n // status tab already shows the total, so a resting \"N total\" is duplication.\n const showCounts =\n value.trim().length > 0 &&\n typeof matchedCount === \"number\" &&\n typeof totalCount === \"number\";\n\n function handleChange(e: ChangeEvent<HTMLInputElement>) {\n onChange(e.target.value);\n }\n\n function handleKeyDown(e: KeyboardEvent<HTMLInputElement>) {\n if (e.key === \"Escape\" && value !== \"\") {\n onChange(\"\");\n e.preventDefault();\n }\n }\n\n // `es-search` is kept only as the print-hide hook (styles.css @media print);\n // all styling is the shadcn Input + utilities now.\n return (\n <div className={cn(\"es-search flex flex-col gap-1\", className)}>\n <label htmlFor={inputId} className=\"sr-only\">\n Search\n </label>\n <div className=\"relative w-full sm:w-72\">\n <Search\n aria-hidden\n className=\"pointer-events-none absolute top-1/2 left-2.5 size-4 -translate-y-1/2 text-muted-foreground\"\n />\n <Input\n ref={ref}\n id={inputId}\n type=\"search\"\n value={value}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n placeholder={placeholder}\n autoComplete=\"off\"\n spellCheck={false}\n aria-keyshortcuts=\"/\"\n className=\"pl-8\"\n />\n </div>\n {showCounts ? (\n <span\n className=\"text-xs tabular-nums text-muted-foreground\"\n aria-live=\"polite\"\n >\n {matchedCount} of {totalCount} scenarios\n </span>\n ) : null}\n </div>\n );\n },\n);\n","import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nfunction Input({ className, type, ...props }: React.ComponentProps<\"input\">) {\n return (\n <input\n type={type}\n data-slot=\"input\"\n className={cn(\n \"h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30\",\n \"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50\",\n \"aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40\",\n className\n )}\n {...props}\n />\n )\n}\n\nexport { Input }\n","'use client';\n\n/** CLI handoff for sharing a standalone HTML report and its local assets. */\n\nimport { Share2 } from 'lucide-react';\nimport { useEffect, useRef, useState } from 'react';\nimport { Button } from '../components/ui/button';\n\nexport const DEFAULT_SHARE_COMMAND = 'npx executable-stories share reports/';\n\nexport interface ReportShareProps {\n /** Command the dialog tells the user to run. */\n command?: string;\n /** Copy to clipboard + toast; supplied by the report so one toast serves all. */\n onCopy: (text: string, message: string) => void;\n}\n\nexport function ReportShare({\n command = DEFAULT_SHARE_COMMAND,\n onCopy,\n}: ReportShareProps) {\n const [open, setOpen] = useState(false);\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open && !dialog.open) dialog.showModal();\n else if (!open && dialog.open) dialog.close();\n }, [open]);\n\n return (\n <>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"sm\"\n aria-label=\"Share this report\"\n title=\"Share this report\"\n onClick={() => setOpen(true)}\n >\n <Share2 aria-hidden=\"true\" className=\"size-4\" />\n <span className=\"sr-only sm:not-sr-only\">Share</span>\n </Button>\n <dialog\n ref={dialogRef}\n className=\"es-report-share m-auto w-[min(90vw,32rem)] rounded-lg border border-border bg-card p-6 text-card-foreground shadow-lg [overscroll-behavior:contain] backdrop:bg-black/40\"\n aria-label=\"Share this report\"\n onClose={() => setOpen(false)}\n >\n <h2 className=\"text-base font-semibold\">Share this report</h2>\n <p className=\"mt-2 text-sm text-muted-foreground\">\n Publish it to Executable Stories Cloud and send a link. Screenshots\n and videos go with it. Run this from your project:\n </p>\n <div className=\"mt-4 flex items-center gap-2\">\n <code className=\"min-w-0 flex-1 truncate rounded border border-border bg-muted px-3 py-2 font-mono text-xs\">\n {command}\n </code>\n <Button\n type=\"button\"\n size=\"sm\"\n onClick={() => onCopy(command, 'Command copied')}\n >\n Copy\n </Button>\n </div>\n <p className=\"mt-3 text-xs text-muted-foreground\">\n The file you are reading cannot upload itself, so the command does it:\n only the CLI can read the assets this report links to.\n </p>\n <div className=\"mt-6 flex items-center justify-between gap-4\">\n <a\n className=\"text-xs underline underline-offset-2\"\n href=\"https://executablestories.com/guides/sharing-reports/\"\n target=\"_blank\"\n rel=\"noreferrer\"\n >\n How sharing works\n </a>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" onClick={() => setOpen(false)}>\n Close\n </Button>\n </div>\n </dialog>\n </>\n );\n}\n","import * as React from \"react\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { useRender } from \"@base-ui/react/use-render\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst buttonVariants = cva(\n \"inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,background-color,border-color,box-shadow] outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4\",\n {\n variants: {\n variant: {\n default: \"bg-primary text-primary-foreground hover:bg-primary/90\",\n destructive:\n \"bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:bg-destructive/60 dark:focus-visible:ring-destructive/40\",\n outline:\n \"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50\",\n secondary:\n \"bg-secondary text-secondary-foreground hover:bg-secondary/80\",\n ghost:\n \"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50\",\n link: \"text-primary underline-offset-4 hover:underline\",\n },\n size: {\n default: \"h-9 px-4 py-2 has-[>svg]:px-3\",\n xs: \"h-6 gap-1 rounded-md px-2 text-xs has-[>svg]:px-1.5 [&_svg:not([class*='size-'])]:size-3\",\n sm: \"h-8 gap-1.5 rounded-md px-3 has-[>svg]:px-2.5\",\n lg: \"h-10 rounded-md px-6 has-[>svg]:px-4\",\n icon: \"size-9\",\n \"icon-xs\": \"size-6 rounded-md [&_svg:not([class*='size-'])]:size-3\",\n \"icon-sm\": \"size-8\",\n \"icon-lg\": \"size-10\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n)\n\nfunction Button({\n className,\n variant = \"default\",\n size = \"default\",\n render,\n ...props\n}: React.ComponentProps<\"button\"> &\n VariantProps<typeof buttonVariants> & {\n // Base UI composition: pass `render={<a … />}` (or any element) to swap the\n // underlying tag — replaces Radix's `asChild`. See rules/base-vs-radix.md.\n render?: useRender.RenderProp\n }) {\n return useRender({\n defaultTagName: \"button\",\n render,\n props: {\n \"data-slot\": \"button\",\n \"data-variant\": variant,\n \"data-size\": size,\n className: cn(buttonVariants({ variant, size, className })),\n ...props,\n },\n })\n}\n\nexport { Button, buttonVariants }\n","\"use client\";\n\nimport { useEffect, useState } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\n\nimport { formatRelativeAge } from \"../lib/provenance\";\nimport type { ScenarioRef } from \"../lib/run-history\";\nimport { cn } from \"../lib/utils\";\nimport { diffSinceVisit, snapshotOf, type VisitDelta, type VisitSnapshot } from \"./last-visit\";\n\nconst KEY = \"es-last-visit\";\nconst MAX_LINKS = 5;\n\nfunction readVisit(): VisitSnapshot | null {\n try {\n const raw = localStorage.getItem(KEY);\n if (!raw) return null;\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const v = parsed as Partial<VisitSnapshot>;\n if (typeof v.runId !== \"string\" || typeof v.atMs !== \"number\" || typeof v.statuses !== \"object\") {\n return null;\n }\n return { runId: v.runId, atMs: v.atMs, statuses: v.statuses as VisitSnapshot[\"statuses\"] };\n } catch {\n // Disabled storage, or a snapshot written by an older shape. Either way the\n // reader just gets no strip — never a crashed report.\n return null;\n }\n}\n\nfunction writeVisit(snapshot: VisitSnapshot): void {\n try {\n localStorage.setItem(KEY, JSON.stringify(snapshot));\n } catch {\n /* disabled / quota */\n }\n}\n\nfunction ScenarioLinks({ scenarios, tone }: { scenarios: ScenarioRef[]; tone: string }) {\n return (\n <>\n {scenarios.slice(0, MAX_LINKS).map((s, i) => (\n <span key={s.id}>\n {i > 0 ? \", \" : \"\"}\n <a href={`#${s.id}`} className={cn(\"underline underline-offset-2 hover:no-underline\", tone)}>\n {s.title}\n </a>\n </span>\n ))}\n {scenarios.length > MAX_LINKS ? <span> and {scenarios.length - MAX_LINKS} more</span> : null}\n </>\n );\n}\n\n/**\n * \"Since your last visit\" — the delta against what THIS reader last saw, which\n * on a tab opened a week later is a different question from what the last run\n * changed. Reads and writes one localStorage key: the snapshot never leaves the\n * browser, and a reader with storage disabled simply sees no strip.\n *\n * Runs in an effect (not during render) because it touches storage and the\n * clock — the server render and the first client paint have to agree.\n */\nexport function ReportSinceLastVisit({ report }: { report: StoryReport }) {\n const [delta, setDelta] = useState<VisitDelta | null>(null);\n const [nowMs, setNowMs] = useState(0);\n\n useEffect(() => {\n const now = Date.now();\n setDelta(diffSinceVisit(readVisit(), report));\n setNowMs(now);\n writeVisit(snapshotOf(report, now));\n }, [report]);\n\n if (!delta) return null;\n const { newlyFailing, newlyPassing, added } = delta;\n\n return (\n <p className=\"text-xs text-muted-foreground\" data-testid=\"es-since-last-visit\">\n <span className=\"font-medium text-foreground\">\n Since your last visit ({formatRelativeAge(delta.sinceMs, nowMs)}):\n </span>\n {newlyFailing.length > 0 ? (\n <span className=\"ml-2 text-fail\">\n {newlyFailing.length} started failing (<ScenarioLinks scenarios={newlyFailing} tone=\"text-fail\" />)\n </span>\n ) : null}\n {newlyPassing.length > 0 ? (\n <span className=\"ml-2 text-pass\">\n {newlyPassing.length} fixed (<ScenarioLinks scenarios={newlyPassing} tone=\"text-pass\" />)\n </span>\n ) : null}\n {added.length > 0 ? <span className=\"ml-2\">{added.length} new</span> : null}\n </p>\n );\n}\n","/**\n * \"Since YOU were last here\" — a per-reader delta, kept in this browser only.\n *\n * The run-to-run delta (<ReportLastRunDelta>) answers \"what changed in the last\n * run\", which is rarely the question someone opening a week-old tab arrives\n * with. This compares the report against the statuses that reader last saw,\n * however many runs ago that was. Pure functions; the storage and the clock\n * live in <ReportSinceLastVisit>.\n */\n\nimport type { StoryReport } from \"executable-stories-core\";\nimport type { ScenarioRef, ScenarioRunStatus } from \"../lib/run-history\";\n\nexport interface VisitSnapshot {\n runId: string;\n atMs: number;\n statuses: Record<string, ScenarioRunStatus>;\n}\n\nexport interface VisitDelta {\n /** When the reader was last here. */\n sinceMs: number;\n newlyFailing: ScenarioRef[];\n newlyPassing: ScenarioRef[];\n /** Scenarios that did not exist (for this reader) at the last visit. */\n added: ScenarioRef[];\n}\n\nexport function snapshotOf(report: StoryReport, atMs: number): VisitSnapshot {\n const statuses: Record<string, ScenarioRunStatus> = {};\n for (const feature of report.features) {\n for (const scenario of feature.scenarios) {\n statuses[scenario.id] = scenario.status;\n }\n }\n return { runId: report.runId, atMs, statuses };\n}\n\n/**\n * Null when there is nothing worth saying: no previous visit, the same run the\n * reader already saw, or a new run that changed nothing they had seen.\n */\nexport function diffSinceVisit(previous: VisitSnapshot | null, report: StoryReport): VisitDelta | null {\n if (!previous) return null;\n if (previous.runId === report.runId) return null;\n\n const newlyFailing: ScenarioRef[] = [];\n const newlyPassing: ScenarioRef[] = [];\n const added: ScenarioRef[] = [];\n\n for (const feature of report.features) {\n for (const scenario of feature.scenarios) {\n const ref: ScenarioRef = { id: scenario.id, title: scenario.title };\n const before = previous.statuses[scenario.id];\n if (before === undefined) {\n added.push(ref);\n } else if (before !== \"failed\" && scenario.status === \"failed\") {\n newlyFailing.push(ref);\n } else if (before === \"failed\" && scenario.status === \"passed\") {\n newlyPassing.push(ref);\n }\n }\n }\n\n if (newlyFailing.length === 0 && newlyPassing.length === 0 && added.length === 0) return null;\n return { sinceMs: previous.atMs, newlyFailing, newlyPassing, added };\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { Button } from \"../components/ui/button\";\n\nexport interface ReportShortcutsHelpProps {\n open: boolean;\n onClose: () => void;\n}\n\n// Kept in lockstep with the bindings in use-keyboard-shortcuts.ts — every key it\n// handles is listed here so the help never lies about what's available.\nconst SHORTCUTS: ReadonlyArray<{ keys: string; description: string }> = [\n { keys: \"/\", description: \"Focus search\" },\n { keys: \"f\", description: \"Jump to next failure\" },\n { keys: \"Shift F\", description: \"Jump to previous failure\" },\n { keys: \"e\", description: \"Expand all\" },\n { keys: \"c\", description: \"Collapse all\" },\n { keys: \"?\", description: \"Toggle this help\" },\n { keys: \"Esc\", description: \"Clear search / close\" },\n];\n\nfunction Keys({ keys }: { keys: string }) {\n // Split combos (\"Shift F\") into one chip per key with a \"+\" between.\n const parts = keys.split(\" \");\n return (\n <span className=\"inline-flex items-center gap-1\">\n {parts.map((k, i) => (\n <span key={k} className=\"inline-flex items-center gap-1\">\n {i > 0 ? <span className=\"text-xs text-muted-foreground\">+</span> : null}\n <kbd className=\"inline-flex h-6 min-w-6 items-center justify-center rounded border border-border bg-muted px-1.5 font-mono text-xs font-medium text-muted-foreground\">\n {k}\n </kbd>\n </span>\n ))}\n </span>\n );\n}\n\nexport function ReportShortcutsHelp({ open, onClose }: ReportShortcutsHelpProps) {\n const dialogRef = useRef<HTMLDialogElement>(null);\n\n useEffect(() => {\n const dialog = dialogRef.current;\n if (!dialog) return;\n if (open && !dialog.open) dialog.showModal();\n else if (!open && dialog.open) dialog.close();\n }, [open]);\n\n return (\n <dialog\n ref={dialogRef}\n className=\"es-shortcuts-help m-auto w-[min(90vw,28rem)] rounded-lg border border-border bg-card p-6 text-card-foreground shadow-lg [overscroll-behavior:contain] backdrop:bg-black/40\"\n aria-label=\"Keyboard shortcuts\"\n onClose={onClose}\n >\n <h2 className=\"text-base font-semibold\">Keyboard shortcuts</h2>\n <dl className=\"mt-4 grid grid-cols-[auto_1fr] items-center gap-x-4 gap-y-2.5\">\n {SHORTCUTS.map((s) => (\n <div key={s.keys} className=\"col-span-2 grid grid-cols-subgrid items-center\">\n <dt className=\"justify-self-start\">\n <Keys keys={s.keys} />\n </dt>\n <dd className=\"text-sm text-muted-foreground\">{s.description}</dd>\n </div>\n ))}\n </dl>\n <form method=\"dialog\" className=\"mt-6\">\n <Button type=\"submit\" variant=\"outline\" size=\"sm\">\n Close\n </Button>\n </form>\n </dialog>\n );\n}\n","\"use client\";\n\nimport { useEffect, useMemo, useState } from \"react\";\nimport { useReport } from \"../hooks/useReport\";\nimport { scrollToScenarioId } from \"../lib/scroll\";\nimport { cn } from \"@/lib/utils\";\n\nconst DOT: Record<string, string> = {\n passed: \"bg-pass\",\n failed: \"bg-fail\",\n skipped: \"bg-skip\",\n pending: \"bg-pend\",\n};\n\n/**\n * The table-of-contents list + scroll-spy, shared by the sticky `ReportToc`\n * sidebar (lg+) and the narrow-screen `ReportTocDrawer`. Tracks the scenario\n * nearest the top of the viewport via IntersectionObserver. `onNavigate` fires\n * after a link is followed, so the drawer can close itself.\n */\nexport function TocContent({ onNavigate }: { onNavigate?: () => void }) {\n const report = useReport();\n const [activeId, setActiveId] = useState<string | null>(null);\n\n const scenarioIds = useMemo(\n () => report.features.flatMap((f) => f.scenarios.map((s) => s.id)),\n [report],\n );\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const els = scenarioIds\n .map((id) => document.getElementById(id))\n .filter((el): el is HTMLElement => el !== null);\n if (els.length === 0) return;\n\n // Measured from every card on each scroll, not from IntersectionObserver\n // entries. An observer callback only carries the elements whose visibility\n // just CHANGED, so once the page is scrolled past the last card nothing\n // changes again and the highlight stays stuck on whichever scenario\n // crossed the band last — the reported bug: at the bottom of the report the\n // sidebar named a card several screens up.\n let frame = 0;\n const update = () => {\n frame = 0;\n // The reading line: a fifth down the viewport. Active = the last card\n // that has crossed it, or the first card when none has yet.\n //\n // At the very bottom of the document the line stops moving, so the last\n // few cards can never cross it and the highlight sticks several screens\n // above what fills the screen. There the whole viewport is the line: the\n // last card that has started wins.\n const atBottom =\n window.scrollY + window.innerHeight >=\n document.documentElement.scrollHeight - 2;\n const line = atBottom ? window.innerHeight : window.innerHeight * 0.2;\n let active = els[0]!;\n let best = -Infinity;\n let firstId: string | null = null;\n let firstTop = Infinity;\n for (const el of els) {\n const top = el.getBoundingClientRect().top;\n if (top <= line && top > best) {\n best = top;\n active = el;\n }\n if (top < firstTop) {\n firstTop = top;\n firstId = el.id;\n }\n }\n setActiveId(best === -Infinity ? firstId : active.id);\n };\n\n const onScroll = () => {\n if (frame === 0) frame = requestAnimationFrame(update);\n };\n update();\n window.addEventListener(\"scroll\", onScroll, { passive: true });\n window.addEventListener(\"resize\", onScroll);\n return () => {\n window.removeEventListener(\"scroll\", onScroll);\n window.removeEventListener(\"resize\", onScroll);\n if (frame !== 0) cancelAnimationFrame(frame);\n };\n }, [scenarioIds]);\n\n if (report.features.length === 0) return null;\n\n // `list-none pl-0` explicitly: the drawer portals OUTSIDE `.es-report-island`,\n // so it can't rely on the island's list reset — bullets would leak otherwise.\n return (\n <ul className=\"flex list-none flex-col gap-4 pl-0\">\n {report.features.map((feature) => (\n <li key={feature.id}>\n <p className=\"mb-1.5 font-semibold leading-snug text-foreground\">{feature.title}</p>\n <ul className=\"flex list-none flex-col gap-0.5 pl-0\">\n {feature.scenarios.map((scenario) => {\n const active = activeId === scenario.id;\n return (\n <li key={scenario.id}>\n <a\n href={`#${scenario.id}`}\n onClick={(e) => {\n e.preventDefault();\n scrollToScenarioId(scenario.id, { updateHash: true });\n onNavigate?.();\n }}\n aria-current={active ? \"true\" : undefined}\n className={cn(\n \"flex items-start gap-2 border-l-2 py-1 pl-2.5 leading-snug hover:text-foreground\",\n active\n ? \"border-primary font-medium text-foreground\"\n : \"border-border text-muted-foreground\",\n )}\n >\n <span\n aria-hidden\n className={cn(\"mt-1 size-1.5 shrink-0 rounded-full\", DOT[scenario.status])}\n />\n <span className=\"break-words\">{scenario.title}</span>\n </a>\n </li>\n );\n })}\n </ul>\n </li>\n ))}\n </ul>\n );\n}\n\n/**\n * Sticky table-of-contents nav for the interactive report (lg+ only). On\n * narrow screens it's hidden and `ReportTocDrawer` provides the same nav.\n */\nexport function ReportToc() {\n const report = useReport();\n if (report.features.length === 0) return null;\n return (\n <nav\n aria-label=\"Table of contents\"\n className=\"sticky top-4 hidden h-fit w-64 shrink-0 self-start text-xs lg:block\"\n >\n <p className=\"mb-3 text-xs font-semibold uppercase tracking-wide text-muted-foreground\">\n Contents\n </p>\n <TocContent />\n </nav>\n );\n}\n","\"use client\";\n\nimport { useState } from \"react\";\nimport { Dialog as DialogPrimitive } from \"@base-ui/react/dialog\";\nimport { ListIcon, XIcon } from \"lucide-react\";\nimport { useReport } from \"../hooks/useReport\";\nimport { TocContent } from \"./ReportToc\";\n\n/**\n * Narrow-screen table of contents: a left-sliding drawer holding the same\n * `TocContent` (and scroll-spy) as the sticky sidebar. The trigger is\n * `lg:hidden`, so on wide screens the sidebar shows instead and this stays out\n * of the way. Following a link closes the drawer so the scenario is revealed.\n */\nexport function ReportTocDrawer() {\n const report = useReport();\n const [open, setOpen] = useState(false);\n if (report.features.length === 0) return null;\n return (\n <DialogPrimitive.Root open={open} onOpenChange={setOpen}>\n <DialogPrimitive.Trigger className=\"flex cursor-pointer items-center gap-1 rounded-md border border-border px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground lg:hidden [&_svg]:size-3.5\">\n <ListIcon aria-hidden /> Contents\n </DialogPrimitive.Trigger>\n <DialogPrimitive.Portal>\n <DialogPrimitive.Backdrop className=\"fixed inset-0 z-50 bg-black/50 transition-opacity duration-200 data-[ending-style]:opacity-0 data-[starting-style]:opacity-0\" />\n <DialogPrimitive.Popup className=\"fixed inset-y-0 left-0 z-50 flex w-72 max-w-[80vw] flex-col gap-3 overflow-y-auto border-r border-border bg-background p-4 font-sans text-xs shadow-lg outline-none transition-transform duration-200 data-[ending-style]:-translate-x-full data-[starting-style]:-translate-x-full\">\n <div className=\"flex items-center justify-between\">\n <DialogPrimitive.Title className=\"text-xs font-semibold tracking-wide text-muted-foreground uppercase\">\n Contents\n </DialogPrimitive.Title>\n <DialogPrimitive.Close\n aria-label=\"Close contents\"\n className=\"cursor-pointer rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground [&_svg]:size-4\"\n >\n <XIcon aria-hidden />\n </DialogPrimitive.Close>\n </div>\n <TocContent onNavigate={() => setOpen(false)} />\n </DialogPrimitive.Popup>\n </DialogPrimitive.Portal>\n </DialogPrimitive.Root>\n );\n}\n","/**\n * Failure-first defaults for the interactive report.\n *\n * A report of a broken run is a triage surface before it is an archive: the\n * question is \"what failed\", not \"show me all 400 scenarios\". So on a run with\n * failures the report opens with passing work collapsed to its titles and\n * failing work expanded — the same \"compress passing, expand failing\" posture\n * the `check` CLI takes.\n *\n * Two deliberate limits:\n * - an all-green run collapses NOTHING; there is nothing to triage, and a wall\n * of collapsed titles would be worse than the current view.\n * - this only ever seeds the FIRST visit. `useCollapseState` prefers a\n * persisted set, so a user who has expressed a preference keeps it.\n */\nimport type { StoryReport } from \"executable-stories-core\";\n\n/** True when a scenario is one the reader needs to see immediately. */\nfunction needsAttention(status: string): boolean {\n return status === \"failed\";\n}\n\n/**\n * The ids to collapse on first view: every passing/skipped feature and\n * scenario, when the run has at least one failure. Empty set otherwise.\n */\nexport function defaultCollapsedIds(report: StoryReport): Set<string> {\n const collapsed = new Set<string>();\n if (report.summary.failed === 0) return collapsed;\n\n for (const feature of report.features) {\n const featureHasFailure = feature.scenarios.some((s) => needsAttention(s.status));\n // A feature with no failures collapses whole — its scenarios stay in the\n // set too, so expanding the feature doesn't dump every step at once.\n if (!featureHasFailure) collapsed.add(feature.id);\n for (const scenario of feature.scenarios) {\n if (!needsAttention(scenario.status)) collapsed.add(scenario.id);\n }\n }\n return collapsed;\n}\n\n/**\n * Order features so the ones with failures come first, preserving the original\n * relative order within each group (a stable partition, not a re-sort — source\n * order still carries meaning for everything else).\n */\nexport function failuresFirst(report: StoryReport): StoryReport {\n if (report.summary.failed === 0) return report;\n const withFailures: StoryReport[\"features\"] = [];\n const rest: StoryReport[\"features\"] = [];\n for (const feature of report.features) {\n (feature.scenarios.some((s) => needsAttention(s.status)) ? withFailures : rest).push(feature);\n }\n if (withFailures.length === 0) return report;\n return { ...report, features: [...withFailures, ...rest] };\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\nimport { scrollToScenarioId } from \"../lib/scroll\";\nimport { splitHash } from \"../lib/hash-state\";\n\n/**\n * Scrolls to a scenario by URL hash on mount and whenever the deep link\n * changes. No-op in SSR (only runs in useEffect). Honours\n * `prefers-reduced-motion`.\n *\n * The fragment also carries filter state (`#<anchor>?q=...`), so only the\n * anchor half is read — and a hashchange that merely rewrote the filters must\n * not yank the page back to the last anchor, hence the last-anchor guard.\n */\nexport function useDeepLinkScroll(): void {\n const lastAnchor = useRef<string | null>(null);\n\n useEffect(() => {\n function scrollToHash() {\n const { anchor } = splitHash(window.location.hash);\n if (!anchor || anchor === lastAnchor.current) return;\n lastAnchor.current = anchor;\n // The hash is already in the URL; don't rewrite history on arrival.\n requestAnimationFrame(() => {\n scrollToScenarioId(anchor, { updateHash: false });\n });\n }\n scrollToHash();\n window.addEventListener(\"hashchange\", scrollToHash);\n return () => window.removeEventListener(\"hashchange\", scrollToHash);\n }, []);\n}\n","\"use client\";\n\nimport { useEffect, useRef } from \"react\";\n\nexport interface KeyboardShortcutHandlers {\n onFocusSearch?: () => void;\n onNextFailure?: () => void;\n onPrevFailure?: () => void;\n onToggleHelp?: () => void;\n onEscape?: () => void;\n onExpandAll?: () => void;\n onCollapseAll?: () => void;\n}\n\nfunction isEditableTarget(target: EventTarget | null): boolean {\n if (!(target instanceof HTMLElement)) return false;\n const tag = target.tagName;\n if (tag === \"INPUT\" || tag === \"TEXTAREA\" || tag === \"SELECT\") return true;\n if (target.isContentEditable) return true;\n return false;\n}\n\n/**\n * Attaches one keydown listener for the lifetime of the component, regardless\n * of how often the consumer passes a fresh handlers object. Handlers are read\n * from a ref so each keypress hits the latest version — see Vercel's\n * advanced-use-latest pattern.\n */\nexport function useKeyboardShortcuts(handlers: KeyboardShortcutHandlers): void {\n const ref = useRef(handlers);\n ref.current = handlers;\n\n useEffect(() => {\n function onKeyDown(e: KeyboardEvent) {\n const h = ref.current;\n if (e.key === \"Escape\") {\n h.onEscape?.();\n return;\n }\n\n if (isEditableTarget(e.target)) return;\n if (e.metaKey || e.ctrlKey || e.altKey) return;\n\n switch (e.key) {\n case \"/\":\n h.onFocusSearch?.();\n e.preventDefault();\n return;\n case \"?\":\n h.onToggleHelp?.();\n e.preventDefault();\n return;\n case \"f\":\n h.onNextFailure?.();\n e.preventDefault();\n return;\n case \"F\":\n h.onPrevFailure?.();\n e.preventDefault();\n return;\n case \"e\":\n h.onExpandAll?.();\n e.preventDefault();\n return;\n case \"c\":\n h.onCollapseAll?.();\n e.preventDefault();\n return;\n default:\n return;\n }\n }\n\n window.addEventListener(\"keydown\", onKeyDown);\n return () => window.removeEventListener(\"keydown\", onKeyDown);\n }, []);\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useState } from \"react\";\n\nexport type ThemePref = \"light\" | \"system\" | \"dark\";\nconst KEY = \"es-theme\";\n\nfunction systemDark(): boolean {\n return typeof matchMedia !== \"undefined\" && matchMedia(\"(prefers-color-scheme: dark)\").matches;\n}\n\nfunction resolve(pref: ThemePref): \"light\" | \"dark\" {\n return pref === \"system\" ? (systemDark() ? \"dark\" : \"light\") : pref;\n}\n\nfunction applyTheme(pref: ThemePref): void {\n if (typeof document !== \"undefined\") {\n document.documentElement.setAttribute(\"data-theme\", resolve(pref));\n }\n}\n\nfunction initialPref(): ThemePref {\n if (typeof localStorage !== \"undefined\") {\n const stored = localStorage.getItem(KEY);\n if (stored === \"light\" || stored === \"dark\" || stored === \"system\") return stored;\n }\n // Nothing stored → follow the OS. (The old 2-way toggle also honoured the\n // prefers-color-scheme media query on first load, so this keeps that default.)\n return \"system\";\n}\n\n/**\n * Light / System / Dark theme preference for the standalone report. Sets\n * `data-theme` on <html> (the Tailwind `dark` variant keys off it), resolving\n * \"system\" through prefers-color-scheme and re-resolving when the OS flips while\n * on \"system\". Persists the choice. No-ops gracefully outside the browser.\n */\nexport function useTheme(): { pref: ThemePref; setPref: (p: ThemePref) => void } {\n const [pref, setPrefState] = useState<ThemePref>(\"system\");\n\n useEffect(() => {\n const p = initialPref();\n setPrefState(p);\n applyTheme(p);\n }, []);\n\n useEffect(() => {\n if (typeof matchMedia === \"undefined\") return;\n const mq = matchMedia(\"(prefers-color-scheme: dark)\");\n const onChange = () => {\n if (pref === \"system\") applyTheme(\"system\");\n };\n mq.addEventListener(\"change\", onChange);\n return () => mq.removeEventListener(\"change\", onChange);\n }, [pref]);\n\n const setPref = useCallback((p: ThemePref) => {\n setPrefState(p);\n applyTheme(p);\n try {\n localStorage.setItem(KEY, p);\n } catch {\n /* disabled / quota */\n }\n }, []);\n\n return { pref, setPref };\n}\n","\"use client\";\n\nimport { useCallback, useEffect, useRef, useState } from \"react\";\nimport {\n DEFAULT_URL_STATE,\n decodeUrlState,\n encodeUrlState,\n splitHash,\n writeHash,\n type ReportUrlState,\n} from \"../lib/hash-state\";\n\n/** Keystroke-rate updates coalesce into one URL write. */\nconst WRITE_DELAY_MS = 250;\n\n/**\n * Search / status / tag / detail state, mirrored into the URL fragment so a\n * refresh or a shared link restores the same view. See lib/hash-state for why\n * the fragment and not the query string.\n *\n * The URL is read in an effect rather than during render: this component also\n * hydrates a server-rendered tree (Astro `client:load`), where a first client\n * render that disagreed with the server markup would be a hydration mismatch.\n */\nexport function useUrlState(): [ReportUrlState, (patch: Partial<ReportUrlState>) => void] {\n const [state, setState] = useState<ReportUrlState>(DEFAULT_URL_STATE);\n const ready = useRef(false);\n\n useEffect(() => {\n const read = () => setState(decodeUrlState(splitHash(window.location.hash).params));\n read();\n ready.current = true;\n // Back/forward and in-page anchor jumps both surface as hashchange.\n window.addEventListener(\"hashchange\", read);\n return () => window.removeEventListener(\"hashchange\", read);\n }, []);\n\n useEffect(() => {\n // Never write before the first read, or mount would erase incoming filters.\n if (!ready.current) return;\n const timer = setTimeout(\n () => writeHash(splitHash(window.location.hash).anchor, encodeUrlState(state)),\n WRITE_DELAY_MS,\n );\n return () => clearTimeout(timer);\n }, [state]);\n\n const update = useCallback(\n (patch: Partial<ReportUrlState>) => setState((prev) => ({ ...prev, ...patch })),\n [],\n );\n\n return [state, update];\n}\n","'use client';\n\n/**\n * WebMCP tools the HTML report registers in the reader's own browser.\n *\n * The report already has an agent channel for coding agents: the MCP server and\n * the StoryReport JSON, both of which need a filesystem. This is the channel for\n * the reader who has neither — someone with a browser agent open, pointed at a\n * shared report URL or a self-contained `report.html`, asking it questions.\n *\n * Four reads and one view-driving tool. The reads answer from the report the\n * page already holds. `filter_scenarios` drives the same URL-fragment state the\n * search box and filter pills write, so an agent asked to \"show the failing\n * checkout scenarios\" changes what the reader is looking at.\n *\n * Deliberately NOT here, and staying MCP-only:\n * - `get_scenario_index` / `get_behavior_manifest` — both route through\n * `scenarioContentHash`, which is node-only (`node:crypto`) and must never\n * enter a browser bundle.\n * - `run_scenario` — a static page has no backend to run tests on.\n *\n * The four reads mirror the MCP server's names and payload shapes; the shared\n * projections live in `executable-stories-core/report-queries` so the two\n * transports cannot answer the same question differently.\n */\n\nimport {\n getFeatureSummary,\n getScenario,\n listScenarioSummaries,\n runProvenance,\n toScenarioSummary,\n type ScenarioFilters,\n} from 'executable-stories-core/report-queries';\nimport type {\n StoryReport,\n TestStatus,\n} from 'executable-stories-core/types/story-report';\nimport type { ToolDef } from 'webmcpable';\nimport type { ReportUrlState, UrlStatusFilter } from '../lib/hash-state';\nimport { filterReport, type StatusFilter } from './filter';\n\nconst STATUSES: readonly TestStatus[] = [\n 'passed',\n 'failed',\n 'skipped',\n 'pending',\n];\nconst VIEW_STATUSES: readonly UrlStatusFilter[] = ['all', ...STATUSES];\n\n/**\n * Every payload carries this.\n *\n * A report is a snapshot, and a reader asking questions of a three-week-old\n * `report.html` has no way to tell it from this morning's. Without the run's\n * age in the answer, an agent relays a long-dead failure as current fact.\n */\nexport interface WithRun {\n run: ReturnType<typeof runProvenance>;\n}\n\nexport interface ReportToolsDeps {\n /** The whole report, unfiltered — reads always answer from all of it. */\n report: StoryReport;\n /** Current view state, so `filter_scenarios` can patch rather than replace. */\n view: ReportUrlState;\n setView: (patch: Partial<ReportUrlState>) => void;\n /**\n * Called when an agent changes the view, so the UI can say so. The reader\n * sees the list change; this is what tells them why.\n */\n onAgentFilter?: (applied: AppliedFilter) => void;\n /** Injected for tests. Defaults to `Date.now`. */\n now?: () => number;\n}\n\nexport interface AppliedFilter {\n search: string;\n status: UrlStatusFilter;\n tags: string[];\n matched: number;\n total: number;\n}\n\n/**\n * A raw JSON Schema is a description, not a validator: webmcpable enforces the\n * top-level `required` list and nothing else. Anything an agent can get wrong\n * inside an optional field has to be checked here, and reported by RETURNING a\n * message — Chrome replaces a thrown error with a generic `UnknownError`, so a\n * throw teaches the agent nothing.\n */\nclass ToolArgumentError extends Error {}\n\n/**\n * The handler signature erases the input type (the registry holds a union of\n * tool definitions), and a raw JSON Schema is not a parser, so the argument\n * really is unknown here. Narrow once, at the boundary.\n */\nfunction asRecord(input: unknown): Record<string, unknown> {\n return typeof input === 'object' && input !== null\n ? (input as Record<string, unknown>)\n : {};\n}\n\nfunction readString(input: Record<string, unknown>, key: string): string | undefined {\n const value = input[key];\n if (value === undefined || value === null) return undefined;\n if (typeof value !== 'string') {\n throw new ToolArgumentError(`\"${key}\" must be a string, received ${typeof value}.`);\n }\n return value;\n}\n\nfunction readStringArray(\n input: Record<string, unknown>,\n key: string,\n): string[] | undefined {\n const value = input[key];\n if (value === undefined || value === null) return undefined;\n // A single tag as a bare string is the mistake an agent actually makes, and\n // the intent is unambiguous. Accept it rather than refusing the call.\n if (typeof value === 'string') return [value];\n if (!Array.isArray(value) || value.some((item) => typeof item !== 'string')) {\n throw new ToolArgumentError(`\"${key}\" must be an array of strings.`);\n }\n return value as string[];\n}\n\nfunction readEnum<T extends string>(\n input: Record<string, unknown>,\n key: string,\n allowed: readonly T[],\n): T | undefined {\n const value = readString(input, key);\n if (value === undefined) return undefined;\n if (!allowed.includes(value as T)) {\n throw new ToolArgumentError(\n `\"${key}\" must be one of: ${allowed.join(', ')}. Received \"${value}\".`,\n );\n }\n return value as T;\n}\n\nfunction readStatuses(input: Record<string, unknown>): TestStatus[] | undefined {\n const values = readStringArray(input, 'statuses');\n if (values === undefined) return undefined;\n const invalid = values.filter((v) => !STATUSES.includes(v as TestStatus));\n if (invalid.length > 0) {\n throw new ToolArgumentError(\n `\"statuses\" must contain only: ${STATUSES.join(', ')}. Received \"${invalid.join('\", \"')}\".`,\n );\n }\n return values as TestStatus[];\n}\n\n/** Turns an argument mistake into text the agent can act on, not a dead call. */\nfunction guarded<T>(run: () => T): T | string {\n try {\n return run();\n } catch (error) {\n if (error instanceof ToolArgumentError) return `Invalid input — ${error.message}`;\n throw error;\n }\n}\n\nconst scenarioListSchema = {\n type: 'object',\n properties: {\n statuses: {\n type: 'array',\n items: { type: 'string', enum: [...STATUSES] },\n description: 'Keep only scenarios with any of these statuses.',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Keep only scenarios carrying any of these tags.',\n },\n sourceFiles: {\n type: 'array',\n items: { type: 'string' },\n description: 'Keep only scenarios whose source file path contains any of these.',\n },\n },\n} as const;\n\n/**\n * `readOnlyHint` keeps the reads out of any confirmation flow.\n * `untrustedContentHint` is the one that matters: scenario titles, step text and\n * assertion messages are written in someone's test suite, and a report can carry\n * whatever a fixture put there. It is data for the model to read about, never\n * instructions for it to follow.\n */\nconst READ_ONLY = { readOnlyHint: true, untrustedContentHint: true } as const;\n\nexport function reportTools(deps: ReportToolsDeps): Record<string, ToolDef> {\n const { report, setView, onAgentFilter } = deps;\n const now = deps.now ?? Date.now;\n const provenance = (): WithRun => ({ run: runProvenance(report, now()) });\n\n const list = (filters: ScenarioFilters) => {\n const scenarios = listScenarioSummaries(report, filters);\n return { ...provenance(), total: scenarios.length, scenarios };\n };\n\n return {\n list_scenarios: {\n title: 'List scenarios',\n description:\n 'List the behaviour scenarios in this report, optionally filtered by status, tag, or source file. Returns each scenario with its steps, tags, timing and failure message.',\n annotations: READ_ONLY,\n input: scenarioListSchema,\n execute: (input) =>\n guarded(() => {\n const args = asRecord(input);\n const filters: ScenarioFilters = {};\n const statuses = readStatuses(args);\n const tags = readStringArray(args, 'tags');\n const sourceFiles = readStringArray(args, 'sourceFiles');\n if (statuses) filters.statuses = statuses;\n if (tags) filters.tags = tags;\n if (sourceFiles) filters.sourceFiles = sourceFiles;\n return list(filters);\n }),\n },\n\n get_failing_scenarios: {\n title: 'Get failing scenarios',\n description:\n 'List only the scenarios that failed in this run, each with the step that failed and its error message. Use this first when asked what is broken.',\n annotations: READ_ONLY,\n execute: () => list({ statuses: ['failed'] }),\n },\n\n get_feature_summary: {\n title: 'Get feature summary',\n description:\n 'Summarise each feature in the report with its scenario counts by status. Use this for \"how are we doing\" questions rather than listing every scenario.',\n annotations: READ_ONLY,\n execute: () => ({\n ...provenance(),\n summary: report.summary,\n features: getFeatureSummary(report),\n }),\n },\n\n get_scenario: {\n title: 'Get scenario',\n description:\n 'Get one scenario by its id or its exact title, with every step and any failure detail. Attachment and document bodies are omitted — `docKinds` names what the page shows.',\n annotations: READ_ONLY,\n input: {\n type: 'object',\n properties: {\n idOrTitle: {\n type: 'string',\n description: 'The scenario id, or its exact title as shown in the report.',\n },\n },\n required: ['idOrTitle'],\n },\n execute: (input) =>\n guarded(() => {\n const idOrTitle = readString(asRecord(input), 'idOrTitle') ?? '';\n const found = getScenario(report, idOrTitle);\n if (!found) {\n return {\n ...provenance(),\n error: `No scenario found with id or title \"${idOrTitle}\". Call list_scenarios to see what this report contains.`,\n };\n }\n return {\n ...provenance(),\n feature: {\n id: found.feature.id,\n title: found.feature.title,\n sourceFile: found.feature.sourceFile,\n },\n // The summary projection, not the raw scenario: doc entry bodies and\n // base64 attachments are unbounded, and this payload goes straight\n // into a model's context window.\n scenario: toScenarioSummary(found.feature, found.scenario),\n };\n }),\n },\n\n filter_scenarios: {\n title: 'Filter the report',\n description:\n 'Change what the reader is looking at: set the report\\'s search text, status filter and tag filter. Omitted fields are left as they are; pass an empty string, \"all\", or an empty array to clear one.',\n input: {\n type: 'object',\n properties: {\n search: {\n type: 'string',\n description:\n 'Free text matched against scenario titles, tags and step text. Empty string clears it.',\n },\n status: {\n type: 'string',\n enum: [...VIEW_STATUSES],\n description: 'Show only scenarios with this status. \"all\" clears the filter.',\n },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description:\n 'Show only scenarios carrying any of these tags. Empty array clears the filter.',\n },\n },\n },\n execute: (input) =>\n guarded(() => {\n const args = asRecord(input);\n const search = readString(args, 'search');\n const status = readEnum(args, 'status', VIEW_STATUSES);\n const tags = readStringArray(args, 'tags');\n\n const applied = {\n search: search ?? deps.view.query,\n status: status ?? deps.view.status,\n tags: tags ?? deps.view.tags,\n };\n\n const patch: Partial<ReportUrlState> = {};\n if (search !== undefined) patch.query = search;\n if (status !== undefined) patch.status = status;\n if (tags !== undefined) patch.tags = tags;\n setView(patch);\n\n // Counted with the same function the list itself renders through, so\n // the number the agent reports back cannot disagree with the screen.\n const matched = filterReport(report, {\n query: applied.search,\n status: applied.status as StatusFilter,\n tags: applied.tags,\n }).summary.total;\n\n const result: AppliedFilter = {\n ...applied,\n matched,\n total: report.summary.total,\n };\n onAgentFilter?.(result);\n return { ...provenance(), applied: result };\n }),\n },\n };\n}\n","\"use client\";\n\nimport { useMemo } from \"react\";\nimport type { StoryReport } from \"executable-stories-core\";\nimport type { Result } from \"../result\";\nimport { ReportInteractive } from \"./ReportInteractive\";\nimport { buildIslandRenderers } from \"./island-renderers\";\n\nexport interface ReportInteractiveIslandProps {\n report: StoryReport | Result<StoryReport>;\n title?: string;\n className?: string;\n hideHeader?: boolean;\n /** Drop the in-content scenario TOC sidebar (host provides scenario nav). */\n hideToc?: boolean;\n /** Render code blocks with CDN highlight.js (default true). */\n syntaxHighlighting?: boolean;\n /** Render `story.mermaid(...)` blocks as CDN-loaded SVG diagrams (default true). */\n mermaid?: boolean;\n}\n\n/**\n * Self-contained interactive island for host frameworks that hydrate this as a\n * client island (e.g. Astro `<ReportInteractiveIsland client:load/>`).\n *\n * Frameworks like Astro serialize island props as JSON, so they CANNOT pass the\n * `renderers` functions to <ReportInteractive> directly — which is why a host\n * would otherwise fall back to a separate post-hydration script that mutates the\n * island's DOM (and gets clobbered when the island re-renders). This wrapper\n * builds the React-OWNED highlighting + mermaid renderers internally, so the\n * enhancements live inside the React tree and survive every re-render. The\n * heavy libraries load from a CDN at runtime, so the host bundle stays lean.\n */\nexport function ReportInteractiveIsland({\n report,\n title,\n className,\n hideHeader,\n hideToc,\n syntaxHighlighting = true,\n mermaid = true,\n}: ReportInteractiveIslandProps) {\n const renderers = useMemo(\n () => buildIslandRenderers({ syntaxHighlighting, mermaid }),\n [syntaxHighlighting, mermaid],\n );\n return (\n <ReportInteractive\n report={report}\n title={title}\n className={className}\n hideHeader={hideHeader}\n hideToc={hideToc}\n renderers={renderers}\n />\n );\n}\n","\"use client\";\n\n/**\n * Built-in renderer overrides for the standalone report island.\n *\n * The static HTML emits readable `<pre data-mermaid>` / `<pre><code>` fallbacks.\n * When the interactive island takes over (createRoot), it OWNS that DOM and will\n * clobber any externally-applied highlight spans / detach mermaid's injected SVG\n * on its next render. So highlighting + mermaid must live INSIDE the React tree\n * (rendered into state, owned by React) rather than as post-processing scripts\n * mutating island-managed nodes. These renderers do exactly that, loading the\n * heavy libraries from a CDN at runtime so they never bloat the inlined island.\n */\n\nimport { createElement, useEffect, useState } from \"react\";\nimport type { ReportDocCode } from \"executable-stories-core\";\nimport { MermaidView, type MermaidApi } from \"../components/doc/MermaidView\";\nimport { CodeFigure } from \"../components/doc/DocCode\";\nimport type { BuiltinRenderers } from \"../renderers\";\nimport { cn } from \"../lib/utils\";\n\n// CDN URLs mirror ssr-entry's cdnAssets so the standalone report stays\n// version-pinned and works offline-degraded (falls back to the readable source).\nconst HLJS_ESM = \"https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/es/highlight.min.js\";\nconst MERMAID_ESM = \"https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs\";\n\n/**\n * Import a module from a CDN URL once, caching the promise. The URL is passed as\n * a variable so it stays opaque to the bundler — the heavy library is loaded at\n * runtime, never inlined into the island. `default ?? namespace` tolerates both\n * default and namespace CDN builds.\n */\nfunction cachedCdnModule<T>(url: string): () => Promise<T> {\n let loader: Promise<T> | undefined;\n return () => {\n // Intentional runtime dynamic import of a CDN URL (not bundled into the island).\n // eslint-disable-next-line no-restricted-syntax\n loader ??= import(/* @vite-ignore */ /* webpackIgnore: true */ url).then((m) => (m.default ?? m) as T);\n return loader;\n };\n}\n\nconst loadMermaidFromCdn = cachedCdnModule<MermaidApi>(MERMAID_ESM);\n\ninterface Hljs {\n highlight(code: string, opts: { language: string; ignoreIllegals?: boolean }): { value: string };\n highlightAuto(code: string): { value: string };\n getLanguage(name: string): unknown;\n}\nconst loadHljs = cachedCdnModule<Hljs>(HLJS_ESM);\n\n/**\n * Code block whose syntax highlighting is produced by highlight.js loaded from\n * the CDN, rendered into React-owned markup via state. Falls back to the plain\n * (escaped) source before load and on any failure.\n */\nfunction CdnHighlightedCode({ entry }: { entry: ReportDocCode }) {\n const [html, setHtml] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n void (async () => {\n try {\n const hljs = await loadHljs();\n const lang = entry.lang && hljs.getLanguage(entry.lang) ? entry.lang : undefined;\n const result = lang\n ? hljs.highlight(entry.content, { language: lang, ignoreIllegals: true })\n : hljs.highlightAuto(entry.content);\n if (!cancelled) setHtml(result.value);\n } catch {\n if (!cancelled) setHtml(null);\n }\n })();\n return () => {\n cancelled = true;\n };\n }, [entry.content, entry.lang]);\n\n return (\n <CodeFigure label={entry.label}>\n {html !== null ? (\n <code\n className={cn(\"hljs font-mono text-xs\", entry.lang && `language-${entry.lang}`)}\n dangerouslySetInnerHTML={{ __html: html }}\n />\n ) : (\n <code className={cn(\"font-mono text-xs\", entry.lang && `language-${entry.lang}`)}>{entry.content}</code>\n )}\n </CodeFigure>\n );\n}\n\nexport interface IslandRendererOptions {\n syntaxHighlighting: boolean;\n mermaid: boolean;\n}\n\n/**\n * Build the BuiltinRenderers map the island passes to <ReportInteractive>.\n * Created once at mount so the renderer functions stay referentially stable.\n */\nexport function buildIslandRenderers(opts: IslandRendererOptions): BuiltinRenderers {\n const renderers: BuiltinRenderers = {};\n if (opts.mermaid) {\n renderers.mermaid = (entry) => createElement(MermaidView, { entry, load: loadMermaidFromCdn });\n }\n if (opts.syntaxHighlighting) {\n renderers.code = (entry) => createElement(CdnHighlightedCode, { entry });\n }\n return renderers;\n}\n","\"use client\";\n\nimport { useEffect, useRef, useState } from \"react\";\nimport type { ReportDocMermaid } from \"executable-stories-core\";\nimport { MermaidSource } from \"./DocMermaid\";\n\nexport type MermaidApi = typeof import(\"mermaid\").default;\nexport type MermaidLoader = () => Promise<MermaidApi>;\n\nfunction prefersDark(el: HTMLElement | null): boolean {\n const themed = el?.closest<HTMLElement>(\"[data-theme]\");\n if (themed?.dataset.theme === \"dark\") return true;\n if (themed?.dataset.theme === \"light\") return false;\n return typeof window !== \"undefined\" && !!window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches;\n}\n\n/**\n * Presentational mermaid renderer with the loader INJECTED — it contains no\n * literal `import(\"mermaid\")`, so a bundler following this module never pulls\n * mermaid in. `MermaidDiagram` wraps this with the installed-package loader;\n * the standalone report island wraps it with a CDN loader so the heavy library\n * never bloats the inlined island bundle.\n *\n * Draws the diagram to inline SVG (React-owned via state, so an island\n * re-render can't clobber it), redraws when the report's `data-theme` flips,\n * and falls back to `<MermaidSource>` (the readable, agent-friendly code) on\n * the server, before load, and on any error.\n */\nexport function MermaidView({ entry, load }: { entry: ReportDocMermaid; load: MermaidLoader }) {\n const ref = useRef<HTMLElement>(null);\n const [svg, setSvg] = useState<string | null>(null);\n const [error, setError] = useState<string | null>(null);\n\n useEffect(() => {\n let cancelled = false;\n const draw = async () => {\n let mermaid: MermaidApi;\n try {\n mermaid = await load();\n } catch {\n // No library (offline, blocked CDN). Not the diagram's fault, so keep\n // the quiet source fallback rather than accusing the author.\n if (!cancelled) {\n setSvg(null);\n setError(null);\n }\n return;\n }\n try {\n mermaid.initialize({\n startOnLoad: false,\n securityLevel: \"strict\",\n // \"neutral\" in light: the same theme the static, no-JS render uses\n // in ssr-entry, so a diagram keeps its colours when the island takes\n // over.\n theme: prefersDark(ref.current) ? \"dark\" : \"neutral\",\n });\n // mermaid.parse is the library's own syntax check. Running it first\n // turns a broken diagram into a message naming the problem, and keeps\n // mermaid from injecting its own error graphic into the document.\n await mermaid.parse(entry.code);\n const id = `es-mermaid-${Math.random().toString(36).slice(2)}`;\n const { svg: rendered } = await mermaid.render(id, entry.code);\n if (!cancelled) {\n setSvg(rendered);\n setError(null);\n }\n } catch (err) {\n if (!cancelled) {\n setSvg(null);\n setError(err instanceof Error ? err.message : String(err));\n }\n }\n };\n void draw();\n\n // Redraw when the report toggles theme on an ancestor.\n const themed = ref.current?.closest<HTMLElement>(\"[data-theme]\");\n const observer = themed ? new MutationObserver(() => void draw()) : undefined;\n observer?.observe(themed!, { attributes: true, attributeFilter: [\"data-theme\"] });\n\n return () => {\n cancelled = true;\n observer?.disconnect();\n };\n }, [entry.code, load]);\n\n if (svg) {\n return (\n <figure ref={ref} className=\"my-3\">\n {entry.title ? (\n <figcaption className=\"mb-1.5 text-xs font-medium text-muted-foreground\">{entry.title}</figcaption>\n ) : null}\n {/* role=\"img\" presents the diagram as a single labelled graphic. */}\n <div\n role=\"img\"\n aria-label={entry.title ?? \"Mermaid diagram\"}\n className=\"overflow-x-auto rounded-md border border-border bg-card p-3 [&_svg]:mx-auto [&_svg]:h-auto [&_svg]:max-w-full\"\n dangerouslySetInnerHTML={{ __html: svg }}\n />\n </figure>\n );\n }\n\n // Pre-render / fallback: the readable source. The ref lets the effect locate\n // the themed ancestor from the same DOM position before the SVG swaps in.\n // A syntax error shows above it, because a diagram that silently degrades to\n // a code block is a diagram nobody ever fixes.\n return (\n <>\n {error ? (\n <p\n role=\"alert\"\n data-es-mermaid-error\n className=\"mt-3 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive\"\n >\n Diagram failed to render: {error}\n </p>\n ) : null}\n <MermaidSource entry={entry} ref={ref} />\n </>\n );\n}\n"],"mappings":"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","names":["useCallback","useId","useMemo","useRef","useState","jsx","formatDuration","jsx","jsx","cva","cva","jsx","jsx","useContext","useContext","jsx","jsxs","jsx","jsxs","jsx","Fragment","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","jsxs","jsx","Fragment","jsx","jsxs","jsx","Fragment","jsx","jsx","jsxs","isLocalFsPath","safeImageUrl","jsx","jsxs","isLocalFsPath","safeImageUrl","Fragment","jsx","jsxs","formatDuration","jsx","jsxs","formatDuration","createContext","useContext","Fragment","jsx","jsxs","useEffect","useState","createContext","useContext","jsxs","useState","useEffect","createContext","useContext","useState","createContext","useContext","jsx","jsx","jsx","jsxs","jsx","jsxs","formatDuration","Fragment","jsx","jsx","jsxs","Fragment","jsx","jsxs","jsx","formatDuration","jsx","jsxs","formatDuration","jsx","jsxs","jsx","jsxs","Fragment","jsx","jsxs","jsx","jsx","jsxs","jsx","React","cva","jsx","cva","useMemo","jsx","jsxs","safeStringify","jsx","EMPTY_RENDERERS","useMemo","Fragment","jsx","jsxs","useCallback","jsx","jsxs","useCallback","useState","jsx","jsxs","useState","useEffect","useState","Fragment","jsx","jsxs","useState","useEffect","Fragment","jsx","jsxs","jsx","jsx","jsxs","ReportSearch","useEffect","useRef","useState","cva","useRender","cva","useRender","Fragment","jsx","jsxs","useState","useRef","useEffect","useEffect","useState","Fragment","jsx","jsxs","MAX_LINKS","ScenarioLinks","useState","useEffect","useEffect","useRef","jsx","jsxs","useRef","useEffect","useEffect","useMemo","useState","jsx","jsxs","useState","useMemo","useEffect","useState","jsx","jsxs","useState","useEffect","useRef","useRef","useEffect","useEffect","useRef","useCallback","useEffect","useState","KEY","useCallback","useEffect","useRef","useState","useState","useRef","useEffect","useCallback","STATUSES","Fragment","jsx","jsxs","useCallback","useState","useRef","useId","useMemo","useMemo","useEffect","useState","useEffect","useRef","useState","Fragment","jsx","jsxs","useRef","useState","useEffect","jsx","useState","useEffect","jsx","useMemo"]}