From 5eaad184b05a131146734c7dea3a89cf51bd92b8 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 24 Jul 2026 15:47:32 -0300 Subject: [PATCH 1/4] feat(frontend): terminal-style overview dashboard Rework the overview page from generic metric cards into a dense, terminal-styled risk console: - Context strip (snapshot, as-of, regime, stress, counts) with a live/loading status indicator. - Compact metric row replacing the executive Metric cards. - Risk path chart upgraded from LineChart to ComposedChart with a gradient area, grid, and policy reference lines at the 15% review and 30% elevated impairment thresholds (mirroring src/atlas/domain/reports/builder.py). - New "Exposure by portfolio" pane ranking portfolios by mean P(impairment). - Tone helpers (risk/stress/regime/severity) centralised in the page. The tooltip formatter takes recharts 3's ValueType (possibly undefined) rather than a bare number. Co-Authored-By: Claude Opus 5 --- .../src/features/overview/OverviewPage.tsx | 365 +++++++++++------- frontend/src/styles/global.css | 139 +++++++ 2 files changed, 356 insertions(+), 148 deletions(-) diff --git a/frontend/src/features/overview/OverviewPage.tsx b/frontend/src/features/overview/OverviewPage.tsx index a2b4dd5..52d9409 100644 --- a/frontend/src/features/overview/OverviewPage.tsx +++ b/frontend/src/features/overview/OverviewPage.tsx @@ -1,47 +1,66 @@ import { useQuery } from "@tanstack/react-query"; -import { Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; +import { + Area, + CartesianGrid, + ComposedChart, + ReferenceArea, + ReferenceLine, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis +} from "recharts"; import type { RouteId } from "../../components/layout/AppShell"; -import { Metric } from "../../components/ui/Metric"; -import { Panel } from "../../components/ui/Panel"; -import { SeverityBadge } from "../../components/ui/SeverityBadge"; import { StateBlock } from "../../components/ui/StateBlock"; import { fetchAnalyses, fetchPortfolios, fetchReports } from "../../lib/api"; -import { latestImpairment, latestMacro, riskSeries, totalActions, worstReport } from "../../lib/analytics"; -import { compactDate, number, percent, relativeTime, titleCase } from "../../lib/format"; -import type { Analysis } from "../../lib/schemas"; - -function outcomeTone(analysis: Analysis): string { - if (analysis.engine === "macro_monitor") { - const stress = analysis.stress_index ?? 0; - if (stress >= 0.66) return "is-neg"; - if (stress >= 0.5) return "is-warn"; - return "is-pos"; - } - const risk = analysis.portfolio_mean_p_impairment ?? 0; - if (risk >= 0.25) return "is-neg"; - if (risk >= 0.15) return "is-warn"; - return "is-pos"; +import { + latestImpairment, + latestMacro, + riskSeries, + totalActions, + worstReport +} from "../../lib/analytics"; +import { compactDate, number, percent, titleCase } from "../../lib/format"; +import type { Analysis, ReportSummary, Severity } from "../../lib/schemas"; + +// Policy thresholds (mirror src/atlas/domain/reports/builder.py). These are the +// reference lines a risk chart in this domain must show. +const IMPAIRMENT_REVIEW = 15; +const IMPAIRMENT_ELEVATED = 30; + +function riskTone(risk: number | null | undefined): string { + const value = (risk ?? 0) * 100; + if (value >= IMPAIRMENT_ELEVATED) return "neg"; + if (value >= IMPAIRMENT_REVIEW) return "warn"; + return "pos"; +} + +function stressTone(stress: number | null | undefined): string { + const value = stress ?? 0; + if (value >= 0.66) return "neg"; + if (value >= 0.5) return "warn"; + return "pos"; +} + +function regimeTone(regime: string | null | undefined): string { + if (regime === "crisis") return "neg"; + if (regime === "tightening") return "warn"; + return "pos"; +} + +function severityTone(severity: Severity): string { + return { info: "muted", watch: "warn", elevated: "warn", critical: "neg" }[severity] ?? "muted"; } export function OverviewPage({ - onNavigate, - focus + onNavigate }: { onNavigate: (route: RouteId) => void; focus?: "portfolios"; }) { - const analysesQuery = useQuery({ - queryKey: ["analyses"], - queryFn: () => fetchAnalyses(100) - }); - const reportsQuery = useQuery({ - queryKey: ["reports"], - queryFn: () => fetchReports(100) - }); - const portfoliosQuery = useQuery({ - queryKey: ["portfolios"], - queryFn: () => fetchPortfolios(100) - }); + const analysesQuery = useQuery({ queryKey: ["analyses"], queryFn: () => fetchAnalyses(100) }); + const reportsQuery = useQuery({ queryKey: ["reports"], queryFn: () => fetchReports(100) }); + const portfoliosQuery = useQuery({ queryKey: ["portfolios"], queryFn: () => fetchPortfolios(100) }); const analyses = analysesQuery.data ?? []; const reports = reportsQuery.data ?? []; @@ -57,137 +76,187 @@ export function OverviewPage({ return ( onNavigate("system")}>Open system} /> ); } + const snapshot = impairment?.snapshot_id ?? macro?.snapshot_id ?? "-"; + const asOf = impairment?.created_at ?? macro?.created_at; + + // Per-portfolio exposure, ranked by risk — the "who is most exposed" table. + const exposures = analyses + .filter((a) => a.engine === "impairment" && a.portfolio_mean_p_impairment != null) + .map((a) => ({ + name: a.portfolio_name ?? a.portfolio_id ?? a.job_id, + risk: a.portfolio_mean_p_impairment ?? 0, + when: a.created_at + })) + .sort((x, y) => y.risk - x.risk); + const maxRisk = Math.max(0.3, ...exposures.map((e) => e.risk)); + + const ctx: Array<[string, string, string?]> = [ + ["SNAP", snapshot], + ["AS OF", compactDate(asOf)], + ["REGIME", macro?.macro_regime ? titleCase(macro.macro_regime) : "-", regimeTone(macro?.macro_regime)], + ["STRESS", number(macro?.stress_index), stressTone(macro?.stress_index)], + ["PF", String(portfolios.length)], + ["RUNS", String(analyses.length)], + ["RPT", String(reports.length)] + ]; + + const metrics: Array<[string, string, string?]> = [ + ["MEAN P(IMP)", percent(impairment?.portfolio_mean_p_impairment), riskTone(impairment?.portfolio_mean_p_impairment)], + ["MACRO REGIME", macro?.macro_regime ? titleCase(macro.macro_regime) : "-", regimeTone(macro?.macro_regime)], + ["STRESS IDX", number(macro?.stress_index), stressTone(macro?.stress_index)], + ["OPEN ACTIONS", String(totalActions(reports)), totalActions(reports) > 0 ? "warn" : "pos"], + ["PORTFOLIOS", String(portfolios.length)], + ["REPORTS", String(reports.length)] + ]; + return ( -
-
- 0.25 ? "critical" : "neutral"} - /> - - 0 ? "watch" : "good"} - /> - -
- - - {loading ? ( -
- ) : chartData.length ? ( - - - - - - - - - ) : ( - - )} - - - onNavigate("reports")}>Reports} - className="memo-panel" - > - {topReport ? ( -
- -

{topReport.headline}

-
-
-
Scope
-
{topReport.portfolio_name ?? titleCase(topReport.engine)}
-
-
-
Actions
-
{topReport.action_count}
-
-
-
Created
-
{compactDate(topReport.created_at)}
-
-
-
- ) : ( - - )} -
- - onNavigate("analyses")}>Full ledger} - className="wide-panel" - > -
- +
+
+ {ctx.map(([k, v, tone]) => ( + + {k} + {v} + + ))} + + + {loading ? "LOADING" : "LIVE"} + +
+ +
+ {metrics.map(([k, v, tone]) => ( +
+ {k} + {v} +
+ ))} +
+ +
+
+
+ Portfolio risk path + P(impairment) % · review {IMPAIRMENT_REVIEW} · elevated {IMPAIRMENT_ELEVATED} +
+ {loading ? ( +
+ ) : chartData.length ? ( + + + + + + + + + + + + + + + [`${Number(v ?? 0)}%`, "risk"]} + /> + + + + ) : ( + + )} +
+ +
+
+ Exposure by portfolio + ranked · P(imp) +
+
+ + {exposures.length ? exposures.map((e) => ( + + + + + + )) : ( + + )} + +
{e.name} + + + + {percent(e.risk)}
No exposures.
+ +
+ +
+
+
+ Analyses + +
+ - - - - - + - {analyses.slice(0, 7).map((analysis) => ( - - - - - + + + + - + ))} - {!analyses.length && ( - - - - )} + {!analyses.length && }
RunEngineStatusOutcomeCreatedRUNENGINESTATUSOUTCOMECREATED
{analysis.job_id}{titleCase(analysis.engine)} - - {titleCase(analysis.status)} - - - - {analysis.engine === "macro_monitor" - ? `Stress ${number(analysis.stress_index)}` - : percent(analysis.portfolio_mean_p_impairment)} - + {analyses.map((a: Analysis) => ( +
{a.job_id}{titleCase(a.engine)}{a.status.toUpperCase()} + {a.engine === "macro_monitor" ? number(a.stress_index) : percent(a.portfolio_mean_p_impairment)} {compactDate(analysis.created_at)}{compactDate(a.created_at)}
No analyses available.
No analyses.
-
-
+ + +
+
+ Decision reports + +
+
+ {reports.length ? reports.map((r: ReportSummary) => ( + + )) : ( + + )} + {topReport && ( +
TOP: {titleCase(topReport.max_severity)} · {topReport.portfolio_name ?? titleCase(topReport.engine)}
+ )} +
+
+
); } diff --git a/frontend/src/styles/global.css b/frontend/src/styles/global.css index ddf194a..a5a2f7b 100644 --- a/frontend/src/styles/global.css +++ b/frontend/src/styles/global.css @@ -822,3 +822,142 @@ tbody tr:hover td { flex-direction: column; } } + +/* ============================================================================ + Terminal composition (Overview) — dense, edge-to-edge, no hero numbers. + ========================================================================== */ +.term { + display: flex; + flex-direction: column; + gap: 8px; + max-width: 1680px; + margin: 0 auto; +} + +/* context strip: snapshot / as-of / regime / stress / counts / status */ +.term-context { + display: flex; + align-items: center; + flex-wrap: wrap; + gap: 0; + height: 30px; + padding: 0 4px; + border: 1px solid var(--line); + background: var(--surface); +} +.ctx-item { + display: inline-flex; + align-items: baseline; + gap: 6px; + padding: 0 12px; + height: 100%; + align-items: center; + border-right: 1px solid var(--line); +} +.ctx-item.ctx-right { margin-left: auto; border-right: 0; } +.ctx-k { color: var(--muted); font-size: 10px; letter-spacing: 0.08em; } +.ctx-v { color: var(--ink); font-size: 12px; } +.ctx-v.is-pos, .tm-v.is-pos, .num.is-pos, .ctx-v.is-good { color: var(--green); } +.ctx-v.is-warn, .tm-v.is-warn, .num.is-warn { color: var(--amber); } +.ctx-v.is-neg, .tm-v.is-neg, .num.is-neg { color: var(--red); } +.ctx-v.is-muted, .tm-v.is-muted { color: var(--ink-soft); } +.status-dot.is-live { background: var(--green); } + +/* compact metric row — small uniform figures, hairline separators, NO hero */ +.term-metrics { + display: grid; + grid-template-columns: repeat(6, minmax(0, 1fr)); + border: 1px solid var(--line); + background: var(--surface); +} +.term-metric { + display: flex; + flex-direction: column; + gap: 3px; + padding: 9px 13px; + border-right: 1px solid var(--line); +} +.term-metric:last-child { border-right: 0; } +.tm-k { color: var(--muted); font-size: 10px; letter-spacing: 0.07em; } +.tm-v { color: var(--ink); font-size: 17px; font-weight: 500; line-height: 1; } + +/* pane grid */ +.term-grid { + display: grid; + grid-template-columns: 1fr minmax(300px, 380px); + gap: 8px; +} +.term-grid-2 { grid-template-columns: 1fr minmax(340px, 440px); } + +.pane { + border: 1px solid var(--line); + background: var(--surface); + min-width: 0; +} +.pane-head { + display: flex; + align-items: center; + justify-content: space-between; + height: 28px; + padding: 0 10px; + border-bottom: 1px solid var(--line); +} +.pane-title { color: var(--ink); font-size: 11px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; } +.pane-meta { color: var(--muted); font-size: 10px; } +.pane-link { border: 0; background: transparent; color: var(--ink-soft); font-size: 10px; letter-spacing: 0.06em; padding: 0; } +.pane-link:hover { color: var(--accent); } +.pane-chart { padding: 8px 8px 4px; } +.pane-chart .pane-head { padding: 0 2px 0 2px; margin-bottom: 6px; border-bottom: 0; height: auto; } + +/* dense tables */ +.term-table { width: 100%; border-collapse: collapse; font-size: 12px; } +.term-table td, .term-table th { padding: 5px 10px; border-bottom: 1px solid var(--line); white-space: nowrap; } +.term-table tr:last-child td { border-bottom: 0; } +.term-table th { color: var(--muted); font-size: 10px; font-weight: 600; letter-spacing: 0.06em; text-align: left; background: var(--surface-strong); } +.term-table .num { text-align: right; font-variant-numeric: tabular-nums; } +.term-table .tt-id { color: var(--ink-soft); } +.term-table .tt-time { color: var(--muted); } +.term-table .tt-name { color: var(--ink); max-width: 180px; overflow: hidden; text-overflow: ellipsis; } +.term-table .tt-empty { color: var(--muted); text-align: center; padding: 18px; } +.term-table tbody tr:hover { background: var(--surface-strong); } + +/* sparkbar in the exposure table */ +.tt-bar { width: 50%; } +.sparkbar { display: block; height: 8px; background: var(--bg); border: 1px solid var(--line); } +.sparkbar-fill { display: block; height: 100%; } +.sparkbar-fill.is-pos { background: var(--green); } +.sparkbar-fill.is-warn { background: var(--amber); } +.sparkbar-fill.is-neg { background: var(--red); } + +/* status tag */ +.tag { font-size: 10px; letter-spacing: 0.05em; padding: 1px 6px; border: 1px solid var(--line-strong); color: var(--ink-soft); font-family: var(--mono); } +.tag.is-succeeded { color: var(--green); border-color: rgba(31,199,125,0.4); } +.tag.is-failed { color: var(--red); border-color: rgba(255,77,68,0.4); } +.tag.is-running, .tag.is-queued { color: var(--amber); border-color: rgba(240,168,48,0.4); } + +/* reports list */ +.report-list { display: flex; flex-direction: column; } +.report-row { display: flex; gap: 0; text-align: left; border: 0; border-bottom: 1px solid var(--line); background: transparent; padding: 0; } +.report-row:hover { background: var(--surface-strong); } +.sev-tick { width: 3px; flex: 0 0 3px; } +.sev-tick.is-warn { background: var(--amber); } +.sev-tick.is-neg { background: var(--red); } +.sev-tick.is-muted { background: var(--line-strong); } +.rr-body { display: flex; flex-direction: column; gap: 3px; padding: 8px 10px; min-width: 0; } +.rr-head { display: flex; gap: 8px; align-items: center; font-size: 10px; } +.rr-sev.is-warn { color: var(--amber); } +.rr-sev.is-neg { color: var(--red); } +.rr-sev.is-muted { color: var(--ink-soft); } +.rr-meta { color: var(--muted); } +.rr-line { color: var(--ink-soft); font-size: 12px; line-height: 1.4; white-space: normal; } +.report-foot { padding: 7px 10px; color: var(--muted); font-size: 10px; border-top: 1px solid var(--line); letter-spacing: 0.05em; } + +@media (max-width: 1080px) { + .term-grid, .term-grid-2 { grid-template-columns: 1fr; } +} + +/* Terminal frame: tighten the page header — small title, no prose subtitle. */ +.main { padding-top: 12px; } +.topbar { margin-bottom: 8px; align-items: center; } +.topbar h1 { font-size: 14px; letter-spacing: 0.04em; text-transform: uppercase; } +.topbar p { display: none; } From e7fb9527cf76845de54347ddc61581efdbe65543 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 24 Jul 2026 15:47:32 -0300 Subject: [PATCH 2/4] fix(build): repair manualChunks typing under vite 8 PR #9 bumped vite 6 -> 8 (rollup 4). The object form of build.rollupOptions.output.manualChunks now resolves against ManualChunksFunction and fails to typecheck: vite.config.ts(25,11): error TS2769: No overload matches this call. 'charts' does not exist in type 'ManualChunksFunction' Since the build script is `tsc -b && vite build`, this broke every deployment on master independently of any feature work. Switched to the function form; the emitted chunks (charts, tables, react-vendor) are unchanged. Co-Authored-By: Claude Opus 5 --- frontend/vite.config.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index b5cbfd7..79c2aa3 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -21,10 +21,19 @@ export default defineConfig({ emptyOutDir: true, rollupOptions: { output: { - manualChunks: { - charts: ["recharts"], - tables: ["@tanstack/react-table"], - "react-vendor": ["react", "react-dom", "@tanstack/react-query"] + // Function form, not the object form: under Rollup 4 (vite 8) the + // object literal resolves against ManualChunksFunction and fails to + // typecheck. Same three chunks as before. + manualChunks(id: string) { + if (id.includes("/node_modules/recharts/")) return "charts"; + if (id.includes("/node_modules/@tanstack/react-table/")) return "tables"; + if ( + id.includes("/node_modules/react/") || + id.includes("/node_modules/react-dom/") || + id.includes("/node_modules/@tanstack/react-query/") + ) { + return "react-vendor"; + } } } } From d200b1dbde3155b17001497fa079e1d06b69b10b Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 24 Jul 2026 15:47:32 -0300 Subject: [PATCH 3/4] fix(vercel): install with pnpm instead of npm The project's install command was overridden to `npm install`, which ignores frontend/pnpm-lock.yaml and re-resolves the tree from the registry. A dependency in that fresh tree now ships a `workspace:*` spec, which npm cannot parse: npm error code EUNSUPPORTEDPROTOCOL npm error Unsupported URL Type "workspace:": workspace:* Every deployment since ebea833 failed this way, including the #14 production build, so the live site was pinned to a stale commit. vercel.json build settings take precedence over dashboard project settings, so pinning the install command here fixes it in-repo and keeps it under review. --frozen-lockfile also makes the deployed tree match the committed lockfile, which the npm path never did. Co-Authored-By: Claude Opus 5 --- frontend/vercel.json | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 frontend/vercel.json diff --git a/frontend/vercel.json b/frontend/vercel.json new file mode 100644 index 0000000..d7c3813 --- /dev/null +++ b/frontend/vercel.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://openapi.vercel.sh/vercel.json", + "installCommand": "pnpm install --frozen-lockfile" +} From 20c1d01af7bb1e98941100294ebe9eefa5fd0745 Mon Sep 17 00:00:00 2001 From: Lucas Date: Fri, 24 Jul 2026 15:49:36 -0300 Subject: [PATCH 4/4] fix(deps): pin typescript to 5.9, TS 7 breaks Vercel's function builder MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #9 bumped typescript 5.9.3 -> 7.0.2. TypeScript 7 is the native port and changes the compiler API surface. Vercel's @vercel/node builder compiles frontend/api/atlas/[...path].ts with the locally installed TypeScript, and crashes on it: Using TypeScript 7.0.2 (local user-provided) Error: Cannot read properties of undefined (reading 'readFile') The vite build itself succeeds and emits identical chunks — the failure is only in the serverless function stage, after the client bundle is already built, which is why it reads as a green build followed by a failed deployment. Pinned with ~ rather than ^ so dependabot cannot walk it back to 7 until Vercel's builder supports it. Co-Authored-By: Claude Opus 5 --- frontend/package.json | 2 +- frontend/pnpm-lock.yaml | 213 ++-------------------------------------- 2 files changed, 7 insertions(+), 208 deletions(-) diff --git a/frontend/package.json b/frontend/package.json index 2af1af7..ea68fa2 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -31,7 +31,7 @@ "@types/react-dom": "^19.1.6", "@vitejs/plugin-react": "^6.0.3", "jsdom": "^29.1.1", - "typescript": "^7.0.2", + "typescript": "~5.9.3", "vite": "^8.1.5", "vitest": "^4.1.10" } diff --git a/frontend/pnpm-lock.yaml b/frontend/pnpm-lock.yaml index 8fb8602..7d281b5 100644 --- a/frontend/pnpm-lock.yaml +++ b/frontend/pnpm-lock.yaml @@ -58,8 +58,8 @@ importers: specifier: ^29.1.1 version: 29.1.1 typescript: - specifier: ^7.0.2 - version: 7.0.2 + specifier: ~5.9.3 + version: 5.9.3 vite: specifier: ^8.1.5 version: 8.1.5(@types/node@26.1.1) @@ -381,126 +381,6 @@ packages: '@types/use-sync-external-store@0.0.6': resolution: {integrity: sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==} - '@typescript/typescript-aix-ppc64@7.0.2': - resolution: {integrity: sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==} - engines: {node: '>=16.20.0'} - cpu: [ppc64] - os: [aix] - - '@typescript/typescript-darwin-arm64@7.0.2': - resolution: {integrity: sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [darwin] - - '@typescript/typescript-darwin-x64@7.0.2': - resolution: {integrity: sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [darwin] - - '@typescript/typescript-freebsd-arm64@7.0.2': - resolution: {integrity: sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [freebsd] - - '@typescript/typescript-freebsd-x64@7.0.2': - resolution: {integrity: sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [freebsd] - - '@typescript/typescript-linux-arm64@7.0.2': - resolution: {integrity: sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [linux] - - '@typescript/typescript-linux-arm@7.0.2': - resolution: {integrity: sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==} - engines: {node: '>=16.20.0'} - cpu: [arm] - os: [linux] - - '@typescript/typescript-linux-loong64@7.0.2': - resolution: {integrity: sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==} - engines: {node: '>=16.20.0'} - cpu: [loong64] - os: [linux] - - '@typescript/typescript-linux-mips64el@7.0.2': - resolution: {integrity: sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==} - engines: {node: '>=16.20.0'} - cpu: [mips64el] - os: [linux] - - '@typescript/typescript-linux-ppc64@7.0.2': - resolution: {integrity: sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==} - engines: {node: '>=16.20.0'} - cpu: [ppc64] - os: [linux] - - '@typescript/typescript-linux-riscv64@7.0.2': - resolution: {integrity: sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==} - engines: {node: '>=16.20.0'} - cpu: [riscv64] - os: [linux] - - '@typescript/typescript-linux-s390x@7.0.2': - resolution: {integrity: sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==} - engines: {node: '>=16.20.0'} - cpu: [s390x] - os: [linux] - - '@typescript/typescript-linux-x64@7.0.2': - resolution: {integrity: sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [linux] - - '@typescript/typescript-netbsd-arm64@7.0.2': - resolution: {integrity: sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [netbsd] - - '@typescript/typescript-netbsd-x64@7.0.2': - resolution: {integrity: sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [netbsd] - - '@typescript/typescript-openbsd-arm64@7.0.2': - resolution: {integrity: sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [openbsd] - - '@typescript/typescript-openbsd-x64@7.0.2': - resolution: {integrity: sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [openbsd] - - '@typescript/typescript-sunos-x64@7.0.2': - resolution: {integrity: sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [sunos] - - '@typescript/typescript-win32-arm64@7.0.2': - resolution: {integrity: sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==} - engines: {node: '>=16.20.0'} - cpu: [arm64] - os: [win32] - - '@typescript/typescript-win32-x64@7.0.2': - resolution: {integrity: sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==} - engines: {node: '>=16.20.0'} - cpu: [x64] - os: [win32] - '@vitejs/plugin-react@6.0.3': resolution: {integrity: sha512-vmFvco5/QuC2f9Oj+wTk0+9XeDFkHxSamwZKYc7MxYwKICfvUvlMhqKI0VuICPltGqh1neqBKDvO4kes1ya8vg==} engines: {node: ^20.19.0 || >=22.12.0} @@ -980,9 +860,9 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} - typescript@7.0.2: - resolution: {integrity: sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==} - engines: {node: '>=16.20.0'} + typescript@5.9.3: + resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==} + engines: {node: '>=14.17'} hasBin: true undici-types@8.3.0: @@ -1376,66 +1256,6 @@ snapshots: '@types/use-sync-external-store@0.0.6': {} - '@typescript/typescript-aix-ppc64@7.0.2': - optional: true - - '@typescript/typescript-darwin-arm64@7.0.2': - optional: true - - '@typescript/typescript-darwin-x64@7.0.2': - optional: true - - '@typescript/typescript-freebsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-freebsd-x64@7.0.2': - optional: true - - '@typescript/typescript-linux-arm64@7.0.2': - optional: true - - '@typescript/typescript-linux-arm@7.0.2': - optional: true - - '@typescript/typescript-linux-loong64@7.0.2': - optional: true - - '@typescript/typescript-linux-mips64el@7.0.2': - optional: true - - '@typescript/typescript-linux-ppc64@7.0.2': - optional: true - - '@typescript/typescript-linux-riscv64@7.0.2': - optional: true - - '@typescript/typescript-linux-s390x@7.0.2': - optional: true - - '@typescript/typescript-linux-x64@7.0.2': - optional: true - - '@typescript/typescript-netbsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-netbsd-x64@7.0.2': - optional: true - - '@typescript/typescript-openbsd-arm64@7.0.2': - optional: true - - '@typescript/typescript-openbsd-x64@7.0.2': - optional: true - - '@typescript/typescript-sunos-x64@7.0.2': - optional: true - - '@typescript/typescript-win32-arm64@7.0.2': - optional: true - - '@typescript/typescript-win32-x64@7.0.2': - optional: true - '@vitejs/plugin-react@6.0.3(vite@8.1.5(@types/node@26.1.1))': dependencies: '@rolldown/pluginutils': 1.0.1 @@ -1861,28 +1681,7 @@ snapshots: tslib@2.8.1: optional: true - typescript@7.0.2: - optionalDependencies: - '@typescript/typescript-aix-ppc64': 7.0.2 - '@typescript/typescript-darwin-arm64': 7.0.2 - '@typescript/typescript-darwin-x64': 7.0.2 - '@typescript/typescript-freebsd-arm64': 7.0.2 - '@typescript/typescript-freebsd-x64': 7.0.2 - '@typescript/typescript-linux-arm': 7.0.2 - '@typescript/typescript-linux-arm64': 7.0.2 - '@typescript/typescript-linux-loong64': 7.0.2 - '@typescript/typescript-linux-mips64el': 7.0.2 - '@typescript/typescript-linux-ppc64': 7.0.2 - '@typescript/typescript-linux-riscv64': 7.0.2 - '@typescript/typescript-linux-s390x': 7.0.2 - '@typescript/typescript-linux-x64': 7.0.2 - '@typescript/typescript-netbsd-arm64': 7.0.2 - '@typescript/typescript-netbsd-x64': 7.0.2 - '@typescript/typescript-openbsd-arm64': 7.0.2 - '@typescript/typescript-openbsd-x64': 7.0.2 - '@typescript/typescript-sunos-x64': 7.0.2 - '@typescript/typescript-win32-arm64': 7.0.2 - '@typescript/typescript-win32-x64': 7.0.2 + typescript@5.9.3: {} undici-types@8.3.0: {}