import { lazy, Suspense, useState, type ReactNode } from 'react'; import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { PageHeader } from '../components/ui/PageHeader'; import { Callout } from '../components/ui/Callout'; import { Disclosure } from '../components/ui/Disclosure'; import { Badge } from '../components/ui/Badge'; import { SkeletonCard, SkeletonTable } from '../components/ui/Skeleton'; import { useAuthStore } from '../stores/authStore'; import { getEventStudy, getRegimeConfig, getRegimeFundamentals, getRegimeMonitor, refreshRegimeFundamentals, updateRegimeConfig, updateRegimeFundamentals, } from '../api/regime'; import type { CapexState, EventStudyReport, GoodNewsReaction, RegimeBand, RegimeConfig, RegimeFundamentalOverlay, RegimeFundamentals, RegimeFundamentalsUpdate, RegimeReading, } from '../lib/types'; const ScoreHistoryChart = lazy(() => import('../components/regime/ScoreHistoryChart')); const RegimeQuadrant = lazy(() => import('../components/regime/RegimeQuadrant')); const BAND_STYLES: Record = { stable: { text: 'text-emerald-400', bar: 'bg-emerald-400', ring: 'border-emerald-400/30', label: 'Stable' }, watch: { text: 'text-amber-400', bar: 'bg-amber-400', ring: 'border-amber-400/30', label: 'Watch' }, elevated: { text: 'text-orange-400', bar: 'bg-orange-400', ring: 'border-orange-400/30', label: 'Elevated' }, breaking: { text: 'text-red-400', bar: 'bg-red-400', ring: 'border-red-400/30', label: 'High stress' }, }; function TrendChip({ label, delta }: { label: string; delta: number | null | undefined }) { if (delta == null) { return {label}: n/a; } const color = delta === 0 ? 'text-gray-400' : delta > 0 ? 'text-red-400' : 'text-emerald-400'; const arrow = delta === 0 ? '→' : delta > 0 ? '↑' : '↓'; return ( {label}: {arrow} {delta > 0 ? '+' : ''}{delta} ); } function ScoreGauge({ label, reading, divider, footnote, }: { label: string; reading: RegimeReading | undefined; divider?: number; footnote: ReactNode; }) { const score = reading?.score; const complete = reading?.band != null; const style = complete ? BAND_STYLES[reading.band as RegimeBand] : null; const position = Math.min(100, Math.max(0, score ?? 0)); const bands = reading?.bands; const ticks = bands ? [bands.watch, bands.elevated, bands.breaking] : [30, 60, 80]; return (
{label}
{score == null ? '—' : Math.round(score)} {score != null && / 100}
{style?.label ?? 'Incomplete'} coverage {Math.round(reading?.coverage ?? 0)}%
{score != null && ( <>
{divider != null && (
)}
{/* Thresholds come from the reading: the two axes no longer share them. */}
0 {ticks.map((tick) => ( {tick} ))} 100
)}

{footnote}

); } const CAPEX_TONE: Record = { raising: 'text-emerald-400', holding: 'text-amber-400', cutting: 'text-red-400', unknown: 'text-gray-500', }; function FundamentalOverlayCard({ overlay }: { overlay: RegimeFundamentalOverlay }) { const capex = overlay.capex ?? {}; const reaction = overlay.good_news_stock_down; return (
Fundamental overlay · context, not scored
{overlay.source && {overlay.source}} {overlay.effective_date && · effective {overlay.effective_date}} {overlay.pending && } {overlay.stale && }
{overlay.pending ? (

A newer observation was collected but is not effective until {overlay.effective_date ?? 'the next session'}. Observations are never backdated, so the reading below appears from that session onward.

) : ( <>
Hyperscaler capex guidance {overlay.capex_stress ?? 'n/a'}
{Object.entries(capex).map(([symbol, state]) => (
{symbol} {state}
))}
Good news, stock down {overlay.earnings_stress ?? 'n/a'}
{reaction === 'yes' ? 'Yes — beats sold into' : reaction === 'no' ? 'No — ordinary reactions' : 'Mixed'}
{overlay.reasoning && (

{overlay.reasoning}

)} )}

These observations are qualitative, refreshed roughly quarterly, and deliberately excluded from State and Warning. In v2 they carried 20 of 100 Warning points — not enough to cross the study's alarm threshold even when both were pegged — so they are reported here rather than diluted into a daily score.

); } function PillarBreakdown({ title, reading }: { title: string; reading: RegimeReading }) { return (
{reading.pillars.map((pillar) => ( ))}
Pillar / sensor Score Weight Contribution
{pillar.label}
{pillar.sensors.map((sensor) => (
{sensor.id} {sensor.label}:{' '} {sensor.score == null ? 'n/a' : sensor.score}
))}
{pillar.score ?? '—'} {pillar.weight} {pillar.available ? pillar.contribution.toFixed(1) : '—'}
); } function EventStudyBody({ report }: { report: EventStudyReport }) { const metrics = report.metrics; return (
{report.generated_at && generated {new Date(report.generated_at).toLocaleDateString()}} {report.sample && test {report.sample.test_start} → {report.sample.end}}

{report.summary}

{metrics && (
{[ ['Warned', `${metrics.events_warned}/${metrics.events}`], ['Missed', metrics.events_missed], ['False alarms/year', metrics.false_alarms_per_year.toFixed(1)], ['Median lead', metrics.median_lead_days == null ? '—' : `${metrics.median_lead_days}d`], ].map(([label, value]) => (
{label}
{value}
))}
)} {report.events && report.events.length > 0 && (
{report.events.map((event) => ( ))}
Correction Warned Lead
{event.date} {event.warned ? 'yes' : 'no'} {event.lead_days == null ? '—' : `${event.lead_days}d`}
)} {report.reliability && (report.reliability.underpowered || report.reliability.sensor_coverage_mismatch) && (
{report.reliability.underpowered && (

Underpowered. Only {report.reliability.events_in_holdout} of{' '} {report.reliability.events_detected} detected corrections fall in the test period ( {report.reliability.minimum_events}+ needed). Recall is one event away from a materially different headline, and which events flip is usually decided by where the frozen threshold lands rather than by what the score saw. Read the direction, not the ratio.

)} {report.reliability.sensor_coverage_mismatch && (

Sensor coverage differs across the split.{' '} {report.reliability.train_full_sensor_share}% of training sessions had all{' '} {report.reliability.sensors_expected} Warning sensors versus{' '} {report.reliability.holdout_full_sensor_share}% of test sessions {report.params?.credit_sensor_from && ` — credit history begins ${report.params.credit_sensor_from}`} . The score renormalises over what is available, so the threshold was frozen on a partly different construct than it is measured against.

)}
)}

The threshold is frozen on the training period and measured on the chronological test period. Reconstructed pre-freeze basket history remains exploratory.

); } function EventStudyPanel() { const study = useQuery({ queryKey: ['regime', 'event-study'], queryFn: getEventStudy }); return ( {study.isLoading && } {study.data === null && Not run yet — trigger “Event Study” in Admin → Jobs.} {study.data && !study.data.available && {study.data.reason ?? 'No data'}} {study.data?.available && } ); } const SELECT_CLASS = 'rounded-md border border-white/[0.08] bg-white/[0.03] px-2 py-1.5 text-xs text-gray-200'; const CAPEX_OPTIONS: { value: CapexState; label: string }[] = [ { value: 'raising', label: 'Raising' }, { value: 'holding', label: 'Holding' }, { value: 'cutting', label: 'Cutting' }, { value: 'unknown', label: 'Unknown' }, ]; function FundamentalsEditor({ data, onSave, onRefresh, saving, refreshing, }: { data: RegimeFundamentals; onSave: (body: RegimeFundamentalsUpdate) => void; onRefresh: () => void; saving: boolean; refreshing: boolean; }) { const [capex, setCapex] = useState>(() => ({ ...data.capex })); const [reaction, setReaction] = useState(data.good_news_stock_down); const knownCapex = Object.values(capex).filter((state) => state !== 'unknown'); // Mirrors _CAPEX_STATE_SCORES: raising 0, holding 50, cutting 100. Holding is // the deceleration case and used to score identically to raising. const capexPoints = knownCapex.reduce((sum, state) => sum + (state === 'cutting' ? 100 : state === 'holding' ? 50 : 0), 0); const derivedF1 = knownCapex.length >= 3 ? Math.round((capexPoints / knownCapex.length) * 10) / 10 : null; const derivedF3 = reaction === 'yes' ? 100 : reaction === 'no' ? 0 : null; return (
Source: {data.source} {data.fetched_at && · fetched {new Date(data.fetched_at).toLocaleDateString()}} {data.effective_date && · effective {data.effective_date}} {data.locked && }
{data.reasoning &&

{data.reasoning}

}
F1 · Capex guidance by hyperscaler score {derivedF1 ?? 'n/a'}
{Object.entries(capex).map(([symbol, state]) => ( ))}

Raising = 0, holding = 50, cutting = 100; at least three known names required. Display only — this does not enter Warning.

{data.locked && }
); } function ConfigEditor({ data, onSave, saving }: { data: RegimeConfig; onSave: (updates: Partial) => void; saving: boolean }) { const [basket, setBasket] = useState(data.breadth_basket.join(', ')); const [staleness, setStaleness] = useState(data.fundamental_staleness_days); const symbols = basket.split(/[\s,]+/).map((symbol) => symbol.trim().toUpperCase()).filter(Boolean); return (