expand ci quality gates
All checks were successful
CI / Validate (push) Successful in 1m13s

This commit is contained in:
dirtydishes 2026-05-30 02:34:28 -04:00
parent 65139bf8d0
commit 44431c4e66
71 changed files with 2262 additions and 1173 deletions

View file

@ -9,11 +9,8 @@ export async function GET(): Promise<Response> {
}
export async function PUT(req: Request): Promise<Response> {
return proxySyntheticAdminRequest(
"/admin/synthetic/control",
{
method: "PUT",
body: await req.text()
}
);
return proxySyntheticAdminRequest("/admin/synthetic/control", {
method: "PUT",
body: await req.text()
});
}

View file

@ -1,8 +1,5 @@
import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
import {
getSyntheticAdminProxyConfig,
isSyntheticAdminFeatureEnabled
} from "./shared";
import { getSyntheticAdminProxyConfig, isSyntheticAdminFeatureEnabled } from "./shared";
const originalFetch = globalThis.fetch;

View file

@ -18,25 +18,29 @@ const variants: Record<
> = {
mock1: {
title: "Command Deck",
premise: "Closest to the reference: left navigation, ticker ribbon, dense evidence panes, replay rail.",
premise:
"Closest to the reference: left navigation, ticker ribbon, dense evidence panes, replay rail.",
mode: "Dense ops",
layout: "classic"
},
mock2: {
title: "Investigation Stack",
premise: "A calmer analyst layout with the selected symbol story in the center and context wrapped around it.",
premise:
"A calmer analyst layout with the selected symbol story in the center and context wrapped around it.",
mode: "Forensic",
layout: "focus"
},
mock3: {
title: "Signal Wall",
premise: "Prioritizes alert triage and cross-symbol scanning before a user drills into price action.",
premise:
"Prioritizes alert triage and cross-symbol scanning before a user drills into price action.",
mode: "Triage",
layout: "signals"
},
mock4: {
title: "Replay Lab",
premise: "A replay-first structure with timeline, event tape, and causality context always visible.",
premise:
"A replay-first structure with timeline, event tape, and causality context always visible.",
mode: "Replay",
layout: "replay"
}
@ -93,7 +97,10 @@ export function DashboardMock({ variant }: DashboardMockProps) {
const config = variants[variant];
return (
<section className={`mock-terminal mock-terminal-${config.layout}`} aria-labelledby="mock-title">
<section
className={`mock-terminal mock-terminal-${config.layout}`}
aria-labelledby="mock-title"
>
<MockHeader config={config} active={variant} />
<TickerRail />
{variant === "mock1" ? <ClassicLayout /> : null}
@ -277,7 +284,11 @@ function OptionTape({ condensed = false }: { condensed?: boolean }) {
function ChartPanel({ compact = false }: { compact?: boolean }) {
return (
<Panel title="AAPL | Price & Flow" meta="1m / 5m / 15m" className={compact ? "mock-chart is-compact" : "mock-chart"}>
<Panel
title="AAPL | Price & Flow"
meta="1m / 5m / 15m"
className={compact ? "mock-chart is-compact" : "mock-chart"}
>
<div className="mock-chart-meta">
<strong>194.88</strong>
<span className="mock-move is-up">+2.34 (+1.22%)</span>
@ -306,16 +317,24 @@ function ChartPanel({ compact = false }: { compact?: boolean }) {
function SignalPanel({ hero = false }: { hero?: boolean }) {
return (
<Panel title="Signals & Alerts" meta="All / Signals / System" className={hero ? "mock-signals is-hero" : "mock-signals"}>
<Panel
title="Signals & Alerts"
meta="All / Signals / System"
className={hero ? "mock-signals is-hero" : "mock-signals"}
>
<div className="mock-signal-list">
{signals.map(([time, title, symbol, value, tag]) => (
<article className="mock-signal-item" key={`${time}-${title}`}>
<time>{time}</time>
<div>
<strong>{title}</strong>
<span>{symbol} / {value}</span>
<span>
{symbol} / {value}
</span>
</div>
<span className={`mock-pill ${tag === "Bearish" ? "is-bearish" : tag === "News" ? "is-news" : "is-bullish"}`}>
<span
className={`mock-pill ${tag === "Bearish" ? "is-bearish" : tag === "News" ? "is-news" : "is-bullish"}`}
>
{tag}
</span>
</article>
@ -332,7 +351,9 @@ function FeedHealth() {
{feedHealth.map(([feed, status, lag, rate]) => (
<div className="mock-table-row" key={feed}>
<span>{feed}</span>
<span className={`mock-pill ${status === "Degraded" ? "is-warning" : "is-bullish"}`}>{status}</span>
<span className={`mock-pill ${status === "Degraded" ? "is-warning" : "is-bullish"}`}>
{status}
</span>
<span>{lag}</span>
<span>{rate}/s</span>
</div>
@ -350,7 +371,9 @@ function DarkFlow() {
<div className="mock-table-row" key={`${time}-${side}-${size}`}>
<span>{time}</span>
<strong>{symbol}</strong>
<span className={`mock-pill ${side === "Sell" ? "is-bearish" : "is-bullish"}`}>{side}</span>
<span className={`mock-pill ${side === "Sell" ? "is-bearish" : "is-bullish"}`}>
{side}
</span>
<span>{size}</span>
<span>{notional}</span>
<span>{type}</span>
@ -402,7 +425,11 @@ function EventContext() {
function ReplayRail({ compact = false }: { compact?: boolean }) {
return (
<Panel title="Replay" meta="May 16, 2024" className={compact ? "mock-replay is-compact" : "mock-replay"}>
<Panel
title="Replay"
meta="May 16, 2024"
className={compact ? "mock-replay is-compact" : "mock-replay"}
>
<div className="mock-replay-controls">
<button type="button">Prev</button>
<button type="button">Pause</button>
@ -430,8 +457,9 @@ function SymbolBrief() {
<span className="mock-move is-up">+1.22%</span>
</div>
<p>
Dark sweep pressure aligns with short-window momentum and a fresh news catalyst. Context confidence is high, but
the largest block remains off-exchange and should be checked against next print behavior.
Dark sweep pressure aligns with short-window momentum and a fresh news catalyst. Context
confidence is high, but the largest block remains off-exchange and should be checked against
next print behavior.
</p>
<div className="mock-brief-tags">
<span className="mock-pill is-bullish">Bullish</span>
@ -444,7 +472,12 @@ function SymbolBrief() {
function Sparkline({ direction }: { direction: string }) {
return (
<svg className="mock-sparkline" viewBox="0 0 96 28" role="img" aria-label={`${direction} sparkline`}>
<svg
className="mock-sparkline"
viewBox="0 0 96 28"
role="img"
aria-label={`${direction} sparkline`}
>
<polyline
fill="none"
points={

View file

@ -161,7 +161,10 @@ input {
text-transform: uppercase;
letter-spacing: 0.14em;
font-size: 0.76rem;
transition: border-color 0.15s ease, background-color 0.15s ease, color 0.15s ease;
transition:
border-color 0.15s ease,
background-color 0.15s ease,
color 0.15s ease;
}
.terminal-nav-link:hover {
@ -800,8 +803,7 @@ h3 {
border: 1px solid var(--border-strong);
border-radius: 8px;
background:
linear-gradient(135deg, oklch(0.78 0.12 74 / 0.7), oklch(0.28 0.035 250)),
var(--accent-soft);
linear-gradient(135deg, oklch(0.78 0.12 74 / 0.7), oklch(0.28 0.035 250)), var(--accent-soft);
}
.command-deck-kicker,
@ -1608,19 +1610,31 @@ h3 {
.data-table-row-classified {
background:
linear-gradient(90deg, rgba(var(--classifier-rgb, 192, 200, 210), calc(0.012 + var(--classifier-intensity, 0) * 0.06)), transparent 62%),
linear-gradient(
90deg,
rgba(
var(--classifier-rgb, 192, 200, 210),
calc(0.012 + var(--classifier-intensity, 0) * 0.06)
),
transparent 62%
),
oklch(0.98 0.008 250 / 0.008);
}
.data-table-row-classified:hover,
.data-table-row-classified:focus-visible {
background:
linear-gradient(90deg, rgba(var(--classifier-rgb, 192, 200, 210), calc(0.02 + var(--classifier-intensity, 0) * 0.1)), transparent 68%),
linear-gradient(
90deg,
rgba(var(--classifier-rgb, 192, 200, 210), calc(0.02 + var(--classifier-intensity, 0) * 0.1)),
transparent 68%
),
oklch(0.78 0.12 74 / 0.035);
}
.data-table-row-classified.is-classified {
box-shadow: inset 0 0 0 1px rgba(var(--classifier-rgb), calc(0.16 + var(--classifier-intensity) * 0.12));
box-shadow: inset 0 0 0 1px
rgba(var(--classifier-rgb), calc(0.16 + var(--classifier-intensity) * 0.12));
}
.data-table-row-warn,
@ -1641,32 +1655,56 @@ h3 {
.data-table-options .data-table-head,
.data-table-options .data-table-row {
grid-template-columns: minmax(72px, 0.8fr) minmax(50px, 0.55fr) minmax(64px, 0.7fr) minmax(58px, 0.6fr) minmax(34px, 0.35fr) minmax(62px, 0.65fr) minmax(104px, 1fr) minmax(54px, 0.55fr) minmax(66px, 0.7fr) minmax(48px, 0.5fr) minmax(42px, 0.45fr) minmax(92px, 0.9fr);
grid-template-columns: minmax(72px, 0.8fr) minmax(50px, 0.55fr) minmax(64px, 0.7fr) minmax(
58px,
0.6fr
) minmax(34px, 0.35fr) minmax(62px, 0.65fr) minmax(104px, 1fr) minmax(54px, 0.55fr) minmax(
66px,
0.7fr
) minmax(48px, 0.5fr) minmax(42px, 0.45fr) minmax(92px, 0.9fr);
}
.data-table-equities .data-table-head,
.data-table-equities .data-table-row {
grid-template-columns: minmax(76px, 0.9fr) minmax(70px, 0.8fr) minmax(76px, 0.8fr) minmax(70px, 0.75fr) minmax(80px, 0.8fr) minmax(76px, 0.75fr);
grid-template-columns: minmax(76px, 0.9fr) minmax(70px, 0.8fr) minmax(76px, 0.8fr) minmax(
70px,
0.75fr
) minmax(80px, 0.8fr) minmax(76px, 0.75fr);
}
.data-table-flow .data-table-head,
.data-table-flow .data-table-row {
grid-template-columns: minmax(148px, 1.1fr) minmax(180px, 1.4fr) minmax(62px, 0.45fr) minmax(70px, 0.5fr) minmax(88px, 0.7fr) minmax(74px, 0.55fr) minmax(132px, 1fr) minmax(110px, 0.8fr) minmax(210px, 1.6fr);
grid-template-columns: minmax(148px, 1.1fr) minmax(180px, 1.4fr) minmax(62px, 0.45fr) minmax(
70px,
0.5fr
) minmax(88px, 0.7fr) minmax(74px, 0.55fr) minmax(132px, 1fr) minmax(110px, 0.8fr) minmax(
210px,
1.6fr
);
}
.data-table-alerts .data-table-head,
.data-table-alerts .data-table-row {
grid-template-columns: minmax(76px, 0.75fr) minmax(170px, 1.4fr) minmax(52px, 0.45fr) minmax(58px, 0.45fr) minmax(52px, 0.4fr) minmax(66px, 0.55fr) minmax(260px, 2fr);
grid-template-columns: minmax(76px, 0.75fr) minmax(170px, 1.4fr) minmax(52px, 0.45fr) minmax(
58px,
0.45fr
) minmax(52px, 0.4fr) minmax(66px, 0.55fr) minmax(260px, 2fr);
}
.data-table-classifier .data-table-head,
.data-table-classifier .data-table-row {
grid-template-columns: minmax(76px, 0.75fr) minmax(180px, 1.45fr) minmax(70px, 0.6fr) minmax(74px, 0.65fr) minmax(300px, 2.2fr);
grid-template-columns: minmax(76px, 0.75fr) minmax(180px, 1.45fr) minmax(70px, 0.6fr) minmax(
74px,
0.65fr
) minmax(300px, 2.2fr);
}
.data-table-dark .data-table-head,
.data-table-dark .data-table-row {
grid-template-columns: minmax(76px, 0.75fr) minmax(170px, 1.35fr) minmax(76px, 0.65fr) minmax(74px, 0.65fr) minmax(74px, 0.65fr) minmax(260px, 2fr);
grid-template-columns: minmax(76px, 0.75fr) minmax(170px, 1.35fr) minmax(76px, 0.65fr) minmax(
74px,
0.65fr
) minmax(74px, 0.65fr) minmax(260px, 2fr);
}
.data-table-cell {
@ -1698,7 +1736,13 @@ h3 {
.options-table-head,
.options-table-row {
display: grid;
grid-template-columns: minmax(72px, 0.8fr) minmax(50px, 0.55fr) minmax(64px, 0.7fr) minmax(58px, 0.6fr) minmax(34px, 0.35fr) minmax(62px, 0.65fr) minmax(104px, 1fr) minmax(54px, 0.55fr) minmax(66px, 0.7fr) minmax(48px, 0.5fr) minmax(42px, 0.45fr) minmax(92px, 0.9fr);
grid-template-columns: minmax(72px, 0.8fr) minmax(50px, 0.55fr) minmax(64px, 0.7fr) minmax(
58px,
0.6fr
) minmax(34px, 0.35fr) minmax(62px, 0.65fr) minmax(104px, 1fr) minmax(54px, 0.55fr) minmax(
66px,
0.7fr
) minmax(48px, 0.5fr) minmax(42px, 0.45fr) minmax(92px, 0.9fr);
align-items: center;
column-gap: 8px;
}
@ -1729,7 +1773,14 @@ h3 {
border: 0;
border-bottom: 1px solid oklch(0.72 0.012 250 / 0.08);
background:
linear-gradient(90deg, rgba(var(--classifier-rgb, 192, 200, 210), calc(0.012 + var(--classifier-intensity, 0) * 0.06)), transparent 62%),
linear-gradient(
90deg,
rgba(
var(--classifier-rgb, 192, 200, 210),
calc(0.012 + var(--classifier-intensity, 0) * 0.06)
),
transparent 62%
),
oklch(0.98 0.008 250 / 0.012);
color: inherit;
font: inherit;
@ -1740,13 +1791,18 @@ h3 {
.options-table-row:focus-visible {
outline: none;
background:
linear-gradient(90deg, rgba(var(--classifier-rgb, 192, 200, 210), calc(0.02 + var(--classifier-intensity, 0) * 0.1)), transparent 68%),
linear-gradient(
90deg,
rgba(var(--classifier-rgb, 192, 200, 210), calc(0.02 + var(--classifier-intensity, 0) * 0.1)),
transparent 68%
),
oklch(0.78 0.12 74 / 0.03);
}
.options-table-row.is-classified {
cursor: pointer;
box-shadow: inset 0 0 0 1px rgba(var(--classifier-rgb), calc(0.16 + var(--classifier-intensity) * 0.12));
box-shadow: inset 0 0 0 1px
rgba(var(--classifier-rgb), calc(0.16 + var(--classifier-intensity) * 0.12));
}
.options-table-row > span {
@ -1761,17 +1817,39 @@ h3 {
font-variant-numeric: tabular-nums;
}
.classifier-green { --classifier-rgb: 37, 193, 122; }
.classifier-red { --classifier-rgb: 255, 107, 95; }
.classifier-amber { --classifier-rgb: 245, 166, 35; }
.classifier-copper { --classifier-rgb: 198, 122, 75; }
.classifier-blue { --classifier-rgb: 77, 163, 255; }
.classifier-teal { --classifier-rgb: 64, 210, 190; }
.classifier-yellowgreen { --classifier-rgb: 174, 210, 78; }
.classifier-violet { --classifier-rgb: 170, 130, 255; }
.classifier-cyan { --classifier-rgb: 94, 214, 255; }
.classifier-magenta { --classifier-rgb: 255, 92, 205; }
.classifier-neutral { --classifier-rgb: 192, 200, 210; }
.classifier-green {
--classifier-rgb: 37, 193, 122;
}
.classifier-red {
--classifier-rgb: 255, 107, 95;
}
.classifier-amber {
--classifier-rgb: 245, 166, 35;
}
.classifier-copper {
--classifier-rgb: 198, 122, 75;
}
.classifier-blue {
--classifier-rgb: 77, 163, 255;
}
.classifier-teal {
--classifier-rgb: 64, 210, 190;
}
.classifier-yellowgreen {
--classifier-rgb: 174, 210, 78;
}
.classifier-violet {
--classifier-rgb: 170, 130, 255;
}
.classifier-cyan {
--classifier-rgb: 94, 214, 255;
}
.classifier-magenta {
--classifier-rgb: 255, 92, 205;
}
.classifier-neutral {
--classifier-rgb: 192, 200, 210;
}
.contract,
.drawer-row-title {
@ -1921,7 +1999,9 @@ h3 {
opacity: 0;
pointer-events: none;
transform: translateY(8px);
transition: opacity 0.15s ease, transform 0.15s ease;
transition:
opacity 0.15s ease,
transform 0.15s ease;
z-index: 5;
}
@ -2047,7 +2127,10 @@ h3 {
color: var(--text-dim);
box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28);
z-index: 45;
transition: border-color 0.16s ease, background-color 0.16s ease, color 0.16s ease;
transition:
border-color 0.16s ease,
background-color 0.16s ease,
color 0.16s ease;
}
.synthetic-control-gear:hover,
@ -2213,7 +2296,9 @@ h3 {
background: oklch(0.18 0.012 250 / 0.6);
color: var(--text);
text-align: left;
transition: border-color 150ms ease, background 150ms ease;
transition:
border-color 150ms ease,
background 150ms ease;
}
.news-row:hover {
@ -2520,7 +2605,11 @@ h3 {
@media (max-width: 720px) {
.terminal-shell {
background-size: 24px 24px, 24px 24px, 100% 100%, auto;
background-size:
24px 24px,
24px 24px,
100% 100%,
auto;
}
.terminal-nav-drawer {
@ -2877,9 +2966,7 @@ h3 {
width: 34px;
height: 34px;
border-radius: 9px;
background:
linear-gradient(135deg, oklch(0.68 0.14 246), oklch(0.68 0.12 164)),
var(--blue-soft);
background: linear-gradient(135deg, oklch(0.68 0.14 246), oklch(0.68 0.12 164)), var(--blue-soft);
box-shadow: inset 0 0 0 1px oklch(0.94 0.02 240 / 0.24);
}

View file

@ -311,12 +311,16 @@ describe("live manifest", () => {
});
it("includes news subscriptions on home and /news", () => {
expect(getLiveManifest("/", "SPY", 60000, buildDefaultFlowFilters()).map((subscription) => subscription.channel)).toContain(
"news"
);
expect(getLiveManifest("/news", "SPY", 60000, buildDefaultFlowFilters()).map((subscription) => subscription.channel)).toEqual([
"news"
]);
expect(
getLiveManifest("/", "SPY", 60000, buildDefaultFlowFilters()).map(
(subscription) => subscription.channel
)
).toContain("news");
expect(
getLiveManifest("/news", "SPY", 60000, buildDefaultFlowFilters()).map(
(subscription) => subscription.channel
)
).toEqual(["news"]);
});
it("scopes /charts subscriptions to chart channels only", () => {
@ -520,12 +524,36 @@ describe("route feature map", () => {
describe("fixed tape virtualization config", () => {
it("uses expected fixed row heights and overscan by table", () => {
expect(getTapeVirtualConfig("options")).toEqual({ rowHeight: 36, overscan: 44, debugLabel: "options" });
expect(getTapeVirtualConfig("equities")).toEqual({ rowHeight: 36, overscan: 36, debugLabel: "equities" });
expect(getTapeVirtualConfig("flow")).toEqual({ rowHeight: 44, overscan: 24, debugLabel: "flow" });
expect(getTapeVirtualConfig("alerts")).toEqual({ rowHeight: 44, overscan: 24, debugLabel: "alerts" });
expect(getTapeVirtualConfig("classifier")).toEqual({ rowHeight: 44, overscan: 24, debugLabel: "classifier" });
expect(getTapeVirtualConfig("dark")).toEqual({ rowHeight: 44, overscan: 24, debugLabel: "dark" });
expect(getTapeVirtualConfig("options")).toEqual({
rowHeight: 36,
overscan: 44,
debugLabel: "options"
});
expect(getTapeVirtualConfig("equities")).toEqual({
rowHeight: 36,
overscan: 36,
debugLabel: "equities"
});
expect(getTapeVirtualConfig("flow")).toEqual({
rowHeight: 44,
overscan: 24,
debugLabel: "flow"
});
expect(getTapeVirtualConfig("alerts")).toEqual({
rowHeight: 44,
overscan: 24,
debugLabel: "alerts"
});
expect(getTapeVirtualConfig("classifier")).toEqual({
rowHeight: 44,
overscan: 24,
debugLabel: "classifier"
});
expect(getTapeVirtualConfig("dark")).toEqual({
rowHeight: 44,
overscan: 24,
debugLabel: "dark"
});
});
});
@ -712,7 +740,11 @@ describe("live tape history helpers", () => {
});
it("promotes hot-window overflow into the history tail", () => {
const currentHot = [makeItem("hot-3", 3, 300), makeItem("hot-2", 2, 200), makeItem("hot-1", 1, 100)];
const currentHot = [
makeItem("hot-3", 3, 300),
makeItem("hot-2", 2, 200),
makeItem("hot-1", 1, 100)
];
const incoming = [makeItem("hot-4", 4, 400)];
const { kept, evicted } = mergeNewestWithOverflow(incoming, currentHot, 3);
@ -727,7 +759,11 @@ describe("live tape history helpers", () => {
let history: Array<ReturnType<typeof makeItem>> = [];
for (let seq = 1; seq <= 5; seq += 1) {
const { kept, evicted } = mergeNewestWithOverflow([makeItem(`row-${seq}`, seq, seq * 100)], hot, 2);
const { kept, evicted } = mergeNewestWithOverflow(
[makeItem(`row-${seq}`, seq, seq * 100)],
hot,
2
);
hot = kept;
history = appendHistoryTail(history, evicted, hot, 5000);
}
@ -762,13 +798,24 @@ describe("live tape history helpers", () => {
});
it("dedupes the seam between promoted overflow and fetched history", () => {
const currentHot = [makeItem("hot-3", 3, 300), makeItem("hot-2", 2, 200), makeItem("hot-1", 1, 100)];
const currentHot = [
makeItem("hot-3", 3, 300),
makeItem("hot-2", 2, 200),
makeItem("hot-1", 1, 100)
];
const { kept, evicted } = mergeNewestWithOverflow([makeItem("hot-4", 4, 400)], currentHot, 3);
const promoted = appendHistoryTail([], evicted, kept, 5000);
const merged = appendHistoryTail(promoted, [makeItem("hot-1", 1, 100), makeItem("older", 0, 50)], kept, 5000);
const merged = appendHistoryTail(
promoted,
[makeItem("hot-1", 1, 100), makeItem("older", 0, 50)],
kept,
5000
);
expect(merged.map((item) => item.trace_id)).toEqual(["hot-1", "older"]);
expect(new Set([...kept, ...merged].map((item) => item.trace_id)).size).toBe(kept.length + merged.length);
expect(new Set([...kept, ...merged].map((item) => item.trace_id)).size).toBe(
kept.length + merged.length
);
});
it("trims the history tail to the soft cap", () => {
@ -821,10 +868,9 @@ describe("live tape history helpers", () => {
makeItem("hist-2", 2, 200)
];
expect(mergeHeldTapeHistory(displayed, incoming, frozenLive).map((item) => item.trace_id)).toEqual([
"hist-3",
"hist-2"
]);
expect(
mergeHeldTapeHistory(displayed, incoming, frozenLive).map((item) => item.trace_id)
).toEqual(["hist-3", "hist-2"]);
});
it("appends truly older lazy-loaded rows to the held history tail", () => {
@ -837,12 +883,9 @@ describe("live tape history helpers", () => {
makeItem("older-0", 0, 50)
];
expect(mergeHeldTapeHistory(displayed, incoming, frozenLive).map((item) => item.trace_id)).toEqual([
"hist-3",
"hist-2",
"older-1",
"older-0"
]);
expect(
mergeHeldTapeHistory(displayed, incoming, frozenLive).map((item) => item.trace_id)
).toEqual(["hist-3", "hist-2", "older-1", "older-0"]);
});
it("resyncs buffered live history by replacing the held segment after resume", () => {
@ -855,7 +898,12 @@ describe("live tape history helpers", () => {
const resynced = appendHistoryTail([], [makeItem("overflow-newer", 6, 600), ...held], [], 0);
expect(held.map((item) => item.trace_id)).toEqual(["hist-3", "hist-2", "older-1"]);
expect(resynced.map((item) => item.trace_id)).toEqual(["overflow-newer", "hist-3", "hist-2", "older-1"]);
expect(resynced.map((item) => item.trace_id)).toEqual([
"overflow-newer",
"hist-3",
"hist-2",
"older-1"
]);
});
});
@ -935,9 +983,21 @@ describe("classifier row decoration helpers", () => {
it("selects primary hits by confidence, source timestamp, then seq", () => {
const hit = selectPrimaryClassifierHit([
{ ...makeAlert({ classifier_id: "old", confidence: 0.9, source_ts: 1_000, seq: 1 }), direction: "bullish", explanations: [] },
{ ...makeAlert({ classifier_id: "new", confidence: 0.9, source_ts: 2_000, seq: 1 }), direction: "bullish", explanations: [] },
{ ...makeAlert({ classifier_id: "low", confidence: 0.5, source_ts: 3_000, seq: 9 }), direction: "bullish", explanations: [] }
{
...makeAlert({ classifier_id: "old", confidence: 0.9, source_ts: 1_000, seq: 1 }),
direction: "bullish",
explanations: []
},
{
...makeAlert({ classifier_id: "new", confidence: 0.9, source_ts: 2_000, seq: 1 }),
direction: "bullish",
explanations: []
},
{
...makeAlert({ classifier_id: "low", confidence: 0.5, source_ts: 3_000, seq: 9 }),
direction: "bullish",
explanations: []
}
]);
expect(hit?.classifier_id).toBe("new");
@ -1010,9 +1070,9 @@ describe("signals helpers", () => {
)
).toBe("bearish");
expect(deriveAlertDirection(makeAlert({ hits: [{ direction: "weird", confidence: 0.4 }] }))).toBe(
"neutral"
);
expect(
deriveAlertDirection(makeAlert({ hits: [{ direction: "weird", confidence: 0.4 }] }))
).toBe("neutral");
expect(deriveAlertDirection(makeAlert({ hits: [] }))).toBe("neutral");
});

File diff suppressed because it is too large Load diff

View file

@ -2,11 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "preserve",
"lib": [
"DOM",
"DOM.Iterable",
"ES2022"
],
"lib": ["DOM", "DOM.Iterable", "ES2022"],
"incremental": true,
"noEmit": true,
"allowJs": true,
@ -24,8 +20,5 @@
".next/types/**/*.ts",
".next-dev/types/**/*.ts"
],
"exclude": [
"node_modules",
"scripts"
]
"exclude": ["node_modules", "scripts"]
}