diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 2edc86e..6b02a97 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -2,6 +2,7 @@ import { useEffect, useMemo, useRef, useState } from "react"; import { useQuery } from "@tanstack/react-query"; import { ApiError, + DEMO_REPLAY_QUERY_KEY, assetQueryKeys, DEFAULT_ASSET, fetchDemoReplay, @@ -21,9 +22,10 @@ import { RegistryPanel } from "./components/RegistryPanel"; import { Panel } from "./components/ui"; import { Icon } from "./components/Icon"; import { EVIDENCE } from "./lib/evidence"; -import { ageLabel, compactUsd, lastUpdatedLabel, money, pct, sigma, sourceLabel } from "./lib/format"; +import { ageLabel, compactUsd, money, pct, reasonLabel, sourceLabel } from "./lib/format"; import { deriveOnchainSync } from "./lib/onchain"; import { clampPosition, mergeObservations, rebasePosition } from "./lib/playback"; +import { evidenceCopy, isEvidenceStateV2, modelDistanceLabel } from "./lib/semantics"; import { HistoricalReplay } from "./views/HistoricalReplay"; import { ObservationRecord } from "./views/ObservationRecord"; import { ReferenceComparison } from "./views/ReferenceComparison"; @@ -49,6 +51,10 @@ export function consoleContextFromSearch(search: string): Context { return "Operational"; } +export function effectiveContextAsset(context: Context, selectedAsset: string): string { + return context === "Demo" ? DEFAULT_ASSET : selectedAsset; +} + export default function App() { const view = typeof window === "undefined" ? "console" : new URLSearchParams(window.location.search).get("view"); const showConsole = view === "console"; @@ -79,18 +85,19 @@ function ValidationConsole() { const [historicalRange, setHistoricalRange] = useState("ALL"); const [demoRange, setDemoRange] = useState("FULL"); const isOperational = context === "Operational"; + const contextAsset = effectiveContextAsset(context, selectedAsset); const health = useQuery({ queryKey: ["health"], queryFn: fetchHealth, refetchInterval: 30_000 }); const backendUp = health.data === true; const assets = useQuery({ queryKey: assetQueryKeys.assets, queryFn: fetchAssets, refetchInterval: 60_000, retry: 0 }); - const selectedAssetInfo = assets.data?.find((item) => item.asset === selectedAsset); + const selectedAssetInfo = assets.data?.find((item) => item.asset === contextAsset); const profile = selectedAssetInfo?.reference_profile ?? "profile-unresolved"; - const operational = useQuery({ queryKey: assetQueryKeys.operational(selectedAsset, profile), queryFn: () => fetchOperationalValuation(selectedAsset), refetchInterval: 20_000, retry: 0, enabled: backendUp }); - const history = useQuery({ queryKey: assetQueryKeys.history(selectedAsset, OPERATIONAL_HISTORY_MAX, profile), queryFn: () => fetchOperationalHistory(selectedAsset, OPERATIONAL_HISTORY_MAX), refetchInterval: 5 * 60_000, retry: 0, enabled: isOperational && !!operational.data }); - const historical = useQuery({ queryKey: assetQueryKeys.historical(selectedAsset, profile), queryFn: () => fetchHistoricalReplay(selectedAsset), staleTime: Infinity, retry: 0, enabled: context === "Historical" && backendUp }); - const demo = useQuery({ queryKey: ["demo-replay", selectedAsset, "canonical"], queryFn: () => fetchDemoReplay(selectedAsset), staleTime: Infinity, enabled: context === "Demo" && selectedAsset === DEFAULT_ASSET }); - const runtime = useQuery({ queryKey: assetQueryKeys.runtime(selectedAsset), queryFn: () => fetchRuntime(selectedAsset), refetchInterval: 30_000, retry: 0, enabled: backendUp }); - const onchain = useQuery({ queryKey: assetQueryKeys.onchain(selectedAsset), queryFn: () => fetchOnchain(selectedAsset), refetchInterval: 45_000, retry: 0, enabled: backendUp && !!selectedAssetInfo?.onchain_binding_configured }); - const enforcement = useQuery({ queryKey: assetQueryKeys.enforcement(selectedAsset), queryFn: () => fetchOnchainEnforcement(selectedAsset), refetchInterval: 45_000, retry: 0, enabled: backendUp && !!selectedAssetInfo?.onchain_binding_configured }); + const operational = useQuery({ queryKey: assetQueryKeys.operational(contextAsset, profile), queryFn: () => fetchOperationalValuation(contextAsset), refetchInterval: 20_000, retry: 0, enabled: isOperational && backendUp }); + const history = useQuery({ queryKey: assetQueryKeys.history(contextAsset, OPERATIONAL_HISTORY_MAX, profile), queryFn: () => fetchOperationalHistory(contextAsset, OPERATIONAL_HISTORY_MAX), refetchInterval: 5 * 60_000, retry: 0, enabled: isOperational && !!operational.data }); + const historical = useQuery({ queryKey: assetQueryKeys.historical(contextAsset, profile), queryFn: () => fetchHistoricalReplay(contextAsset), staleTime: Infinity, retry: 0, enabled: context === "Historical" && backendUp }); + const demo = useQuery({ queryKey: DEMO_REPLAY_QUERY_KEY, queryFn: () => fetchDemoReplay(DEFAULT_ASSET), staleTime: Infinity, retry: 0, enabled: context === "Demo" }); + const runtime = useQuery({ queryKey: assetQueryKeys.runtime(contextAsset), queryFn: () => fetchRuntime(contextAsset), refetchInterval: 30_000, retry: 0, enabled: backendUp }); + const onchain = useQuery({ queryKey: assetQueryKeys.onchain(contextAsset), queryFn: () => fetchOnchain(contextAsset), refetchInterval: 45_000, retry: 0, enabled: backendUp && !!selectedAssetInfo?.onchain_binding_configured }); + const enforcement = useQuery({ queryKey: assetQueryKeys.enforcement(contextAsset), queryFn: () => fetchOnchainEnforcement(contextAsset), refetchInterval: 45_000, retry: 0, enabled: backendUp && !!selectedAssetInfo?.onchain_binding_configured }); const [position, setPosition] = useState(0); const [playing, setPlaying] = useState(false); const [followLatest, setFollowLatest] = useState(true); @@ -127,11 +134,11 @@ function ValidationConsole() { const source = isOperational ? `Operational · ${results.length} observations` : context === "Historical" ? `Historical · ${results.length} observations` - : selectedAsset !== DEFAULT_ASSET ? "Demo · NVDAx synthetic fixture only" : !demo.data ? "Demo · Loading" : demo.data.source === "backend-scenario" - ? `Demo scenario · ${demo.data.results.length} synthetic steps` - : `Demo fixture · ${demo.data.results.length} synthetic steps`; + : !demo.data ? "Demo · Loading" : demo.data.source === "backend-scenario" + ? `Demo Scenario · ${demo.data.results.length} Synthetic Steps` + : `Demo Backup · ${demo.data.results.length} Synthetic Steps`; const controlPlane = onchain.isError ? undefined : onchain.data; - const policy = controlPlane?.policy ?? (context === "Demo" ? EXAMPLE_DEMO_POLICY : undefined); + const policy = context === "Demo" ? EXAMPLE_DEMO_POLICY : controlPlane?.policy ?? null; const policyAction = policy && current ? actionFor(policy, current.evidence_state) : null; const sync = isOperational ? deriveOnchainSync(operational.data, controlPlane) : undefined; const activeQuery = isOperational ? operational : context === "Historical" ? historical : demo; @@ -139,7 +146,7 @@ function ValidationConsole() { const statusMessage = activeQuery.error instanceof Error ? activeQuery.error.message : "Data unavailable"; const runtimeNotWarmed = isOperational && (runtime.data?.has_live_result === false || (operational.error instanceof ApiError && operational.error.status === 503)); const chainError = !selectedAssetInfo?.onchain_binding_configured - ? `No X Layer deployment is configured for ${selectedAsset}.` + ? `X Layer is not configured for ${contextAsset}. Offchain validation remains available.` : backendUp ? onchain.error instanceof Error ? onchain.error.message : "The deployed contracts could not be read." : "Backend unavailable. Showing the last available data."; @@ -149,11 +156,12 @@ function ValidationConsole() { { setSelectedAsset(asset); setPosition(0); @@ -161,20 +169,19 @@ function ValidationConsole() { setFollowLatest(true); }} /> -
Research prototype · X Layer testnet · Not for production use
{selectedAssetInfo && selectedAssetInfo.readiness_error_codes.length > 0 &&
- {selectedAsset} readiness is partial: {selectedAssetInfo.readiness_error_codes.join(" · ")}. No other asset's prices, model, history, or X Layer binding are substituted. + Operational Readiness Issue: {selectedAssetInfo.readiness_error_codes.map(reasonLabel).join(" · ")}
}
{isDegraded && current &&
{context} degraded · showing last available observations. {history.isError && isOperational ? "History unavailable. " : ""}{activeQuery.isError ? statusMessage : runtime.data?.last_error}
} - {!current ?

{activeQuery.isLoading ? `Loading ${selectedAsset} ${context.toLowerCase()} observations…` : context === "Demo" && selectedAsset !== DEFAULT_ASSET ? "The deterministic Demo fixture is synthetic NVDAx-only. It is not relabeled as another asset." : runtimeNotWarmed ? "Runtime not warmed yet." : statusMessage}

: <> + {!current ?

{activeQuery.isLoading ? `Loading ${contextAsset} ${context.toLowerCase()} observations…` : runtimeNotWarmed ? "Runtime not warmed yet." : statusMessage}

: <>
setFollowLatest(false)} followingLatest={isOperational && followLatest} onLatest={isOperational ? () => { setPlaying(false); setFollowLatest(true); setPosition(results.length - 1); } : undefined} - viewportKey={`${selectedAsset}:${profile}:${context}:${activeRange}`} + viewportKey={`${contextAsset}:${profile}:${context}:${activeRange}`} periodMs={context === "Demo" ? 600 : 120} coverageNotice={isOperational ? operationalCoverageNotice(allOperationalResults, range) : undefined} onReset={() => { @@ -208,17 +215,18 @@ function ValidationConsole() { - {context === "Demo" &&
- Advanced: policy proposal -
-
}
+ {context === "Demo" &&
+ Advanced: Policy Proposal +
+
} +
@@ -229,34 +237,33 @@ function ValidationConsole() { {context === "Demo" &&
- Demo: token-rights metadata + Demo: Token Rights Metadata
} - {context === "Historical" && } + {context === "Historical" && } - + />} -
- {current ? `Model ${current.model_id} · v${current.model_version}` : ""} -
); } -function AppHeader({ backendUp, chainUp, source, context, onContextChange, assets, selectedAsset, onAssetChange }: { +function AppHeader({ backendUp, chainUp, chainConfigured, source, context, onContextChange, assets, selectedAsset, onAssetChange }: { backendUp: boolean; chainUp: boolean; + chainConfigured: boolean; source: string; context: Context; onContextChange: (context: Context) => void; @@ -272,10 +279,10 @@ function AppHeader({ backendUp, chainUp, source, context, onContextChange, asset
- + {context !== "Demo" && assetOptions.length > 0 && } {source} - - + + {chainConfigured && }
); @@ -291,33 +298,24 @@ function ConnectionLabel({ active, activeText, inactiveText }: { active: boolean } function DecisionSummary({ current, action }: { current: ValuationResult; action: PolicyAction | null }) { - const unified = current.validation_target === "xstock_observed_price" || current.reference_profile === "unified_xstock_p1ac_xperp_evidence_v1"; - const findings: Record = unified ? { - SUPPORTED: { title: "Tri-source evidence supports the observed xStock price", detail: "The P1a/xStock support band applies, exact-time X-Perp is available, and quality gates passed. P1a has assimilated this xStock observation, so this is source-aware model evidence—not proof from two independent votes." }, - INCONCLUSIVE: { title: "Tri-source evidence is inconclusive", detail: "The result remains in a watch band or an availability, freshness, ambiguity, or quality condition prevents a supported or challenged state." }, - CHALLENGED: { title: "Tri-source evidence challenges the observed xStock price", detail: "The P1a/xStock review band applies and exact-time X-Perp is closer to P1a-C. This selective risk signal warrants review; it does not prove the observed xStock price is objectively wrong." }, - } : { - SUPPORTED: { title: "Evidence supports the reference", detail: "Available independent evidence does not provide a material reason to challenge the price being tested." }, - INCONCLUSIVE: { title: "Evidence needs review", detail: "The available evidence is not strong enough for a confident conclusion." }, - CHALLENGED: { title: "Evidence challenges the reference", detail: "Available evidence materially challenges the tested price." }, - }; - const finding = findings[current.evidence_state]; + const finding = evidenceCopy(current); return
-
Current finding

{finding.title}

{finding.detail}

-
Policy action
{plainAction(action)}
+
Current Finding

{finding.title}

{finding.detail}

+
Policy Action
{plainAction(action)}
; } function MetricGrid({ current, isDemo, observationCount }: { current: ValuationResult; isDemo: boolean; observationCount: number }) { - const unified = current.validation_target === "xstock_observed_price" || current.reference_profile === "unified_xstock_p1ac_xperp_evidence_v1"; + const xperpPrice = isEvidenceStateV2(current) ? current.xperp_index_price : current.xperp_index_price ?? current.reference_under_test; + const xperpSource = isEvidenceStateV2(current) ? current.xperp_index_source : current.xperp_index_source ?? current.reference_under_test_source; return (
- - - - - - + + + + + +
); } @@ -328,74 +326,52 @@ function Metric({ label, value, sub, accent }: { label: string; value: string; s function EvidenceCard({ result }: { result: ValuationResult }) { const state = EVIDENCE[result.evidence_state]; - const unified = result.validation_target === "xstock_observed_price" || result.reference_profile === "unified_xstock_p1ac_xperp_evidence_v1"; - const detail = unified - ? result.evidence_state === "SUPPORTED" - ? "The support-band rule passed with exact-time X-Perp available and no quality abstention. P1a has assimilated this same xStock observation, so this is not a two-independent-source test." - : result.evidence_state === "CHALLENGED" - ? "The review-band rule passed and exact-time X-Perp directionally corroborates P1a-C. This selective signal does not prove which price is objectively correct." - : "The tri-source evidence is watch-band, unavailable, stale, ambiguous, or quality-gated, so the backend deliberately abstains." - : result.evidence_state === "SUPPORTED" - ? "The reference is not materially challenged by the available independent evidence." - : result.evidence_state === "CHALLENGED" - ? "The reference is materially inconsistent with the available independent evidence." - : "The available evidence is not strong enough for a confident conclusion."; return ( - +
{state.label}
-

{detail}

); } function PolicyCard({ state, action, source, label, enforced }: { state?: EvidenceState; action: PolicyAction | null; source: string; label: string; enforced?: OnchainControlPlane }) { - const riskGuardState = enforced ? enforced.fresh ? "FRESH" : "STALE" : "UNAVAILABLE"; - const riskGuardUpdated = lastUpdatedLabel(enforced?.attestation?.publishedAt); return ( - {label}}> + {label}}>
{plainAction(action)}
Reason
{plainEvidenceReason(state)}
- {enforced &&
RiskGuard data · {plainFreshness(enforced.fresh)}{riskGuardUpdated ? ` · ${riskGuardUpdated}` : ""}
} -
- Technical details+ -
- - - - {enforced && } -
-
+ {!action &&

No curator policy is connected for this asset.

} +
+ + + {enforced && } + {enforced && } +
); } -function TechnicalPolicyValue({ label, value }: { label: string; value: string }) { +function PolicyDetail({ label, value }: { label: string; value: string }) { return
{label}
{value}
; } function plainEvidenceReason(state?: EvidenceState): string { - if (state === "SUPPORTED") return "Evidence supports the validation target"; - if (state === "INCONCLUSIVE") return "Evidence is inconclusive"; - if (state === "CHALLENGED") return "Evidence challenges the validation target"; - return "Evidence is unavailable"; -} - -function plainFreshness(fresh: boolean): string { - return fresh ? "Fresh" : "Stale"; + if (state === "SUPPORTED") return "Observed xStock Is Supported"; + if (state === "INCONCLUSIVE") return "Evidence Is Inconclusive"; + if (state === "CHALLENGED") return "Observed xStock Is Challenged"; + return "Evidence Is Unavailable"; } function BasisCard({ result }: { result: ValuationResult }) { return (
- + - - + +
); @@ -412,9 +388,9 @@ function actionFor(policy: OnchainPolicy, state: EvidenceState): PolicyAction { } function plainAction(action: PolicyAction | null): string { - if (action === "ALLOW") return "Allow new borrowing"; - if (action === "MONITOR") return "Continue monitoring"; - if (action === "REQUIRE_REVIEW") return "Pause and review"; - if (action === "RESTRICT_NEW_RISK") return "Restrict new borrowing"; - return "Policy unavailable"; + if (action === "ALLOW") return "Allow New Borrowing"; + if (action === "MONITOR") return "Continue Monitoring"; + if (action === "REQUIRE_REVIEW") return "Pause And Review"; + if (action === "RESTRICT_NEW_RISK") return "Restrict New Borrowing"; + return "No Policy Connected"; } diff --git a/apps/web/src/api/client.ts b/apps/web/src/api/client.ts index 948c8f4..19bebdb 100644 --- a/apps/web/src/api/client.ts +++ b/apps/web/src/api/client.ts @@ -22,15 +22,15 @@ import type { RuntimeStatus, ValuationResult, } from "./types"; -import weekendDivergence from "../fixtures/weekend_divergence.json"; +import consoleWeekendDivergenceV2 from "../fixtures/console_weekend_divergence_v2.json"; export const BASE = import.meta.env.DEV ? "" : (import.meta.env.VITE_API_BASE_URL ?? "http://localhost:8000"); export const DEFAULT_ASSET = "NVDAx"; -export const PRIMARY_ASSET_OPTIONS = ["NVDAx", "SPYx", "QQQx", "AAPLx"] as const; -export type PrimaryAsset = (typeof PRIMARY_ASSET_OPTIONS)[number]; const LEGACY_REFERENCE_PROFILE = "legacy_xperp_vs_p1ac"; +const EVIDENCE_SEMANTICS_V2 = "p1a_xstock_band_with_xperp_review_corroboration_v2"; -const FIXTURE = weekendDivergence as unknown as ValuationResult[]; +const CONSOLE_BACKUP = consoleWeekendDivergenceV2 as unknown as ValuationResult[]; +export const DEMO_REPLAY_QUERY_KEY = ["demo-replay", DEFAULT_ASSET, "weekend_divergence", EVIDENCE_SEMANTICS_V2] as const; export class ApiError extends Error { constructor(public status: number, public detail: string) { @@ -101,7 +101,7 @@ function normalizeAssetInfo(value: unknown): AssetInfo { historical_data_available: item.historical_data_available ?? false, historical_panel_file_available: item.historical_panel_file_available ?? false, canonical_panel_verified: item.canonical_panel_verified ?? false, - historical_replay_ready: item.historical_replay_ready ?? item.historical_data_available ?? false, + historical_replay_ready: item.historical_replay_ready ?? false, historical_replay_mode: item.historical_replay_mode ?? null, historical_panel_error_code: item.historical_panel_error_code ?? null, challenger_detector_status: item.challenger_detector_status ?? "DETECTOR_STATUS_UNAVAILABLE", @@ -114,8 +114,8 @@ function normalizeAssetInfo(value: unknown): AssetInfo { latest_observation_timestamp: item.latest_observation_timestamp ?? null, latest_observation_age_seconds: item.latest_observation_age_seconds ?? null, latest_observation_freshness: item.latest_observation_freshness ?? "unavailable", - // Only the legacy NVDAx deployment is known to expose these routes without - // readiness metadata. Missing metadata never enables another asset. + // Preserve the pre-registry NVDAx migration seam only. Explicit metadata + // enables any bound asset; missing metadata fails closed for SPYx/AAPLx. onchain_binding_configured: item.onchain_binding_configured ?? legacyNvda, readiness_error_codes: Array.isArray(item.readiness_error_codes) ? item.readiness_error_codes @@ -247,15 +247,15 @@ export async function fetchOnchainEnforcement(asset = DEFAULT_ASSET): Promise( `/api/replay/${asset}?source=scenario&scenario=${encodeURIComponent(scenario)}`, ); - if (!Array.isArray(results) || results.length === 0) throw new Error("empty replay"); + if (!isV2Demo(results)) throw new Error("backend scenario does not satisfy the v2 Demo contract"); return { results: assertAssetRows(results, asset), source: "backend-scenario" }; } catch { - return { results: assertAssetRows(FIXTURE, asset), source: "offline-fixture" }; + return { results: assertAssetRows(CONSOLE_BACKUP, asset), source: "console-backup" }; } } + +function isV2Demo(results: unknown): results is ValuationResult[] { + return Array.isArray(results) + && results.length === 6 + && results.every((row) => row && typeof row === "object" + && (row as ValuationResult).asset === DEFAULT_ASSET + && (row as ValuationResult).evidence_semantics === EVIDENCE_SEMANTICS_V2 + && (row as ValuationResult).validation_target === "xstock_observed_price" + && (row as ValuationResult).xperp_role === "second_market_challenger" + && (row as ValuationResult).xperp_index_price != null); +} diff --git a/apps/web/src/api/types.ts b/apps/web/src/api/types.ts index 4a51bc3..fe2a993 100644 --- a/apps/web/src/api/types.ts +++ b/apps/web/src/api/types.ts @@ -9,7 +9,7 @@ export interface ChallengerDetectorEvidence { score: number | null; review_threshold: number; challenge_threshold: number; - research_band: "support" | "watch" | "review" | "unavailable"; + research_band: string; promotion_status: string; } @@ -183,6 +183,8 @@ export interface OnchainControlPlane extends OnchainEvaluation { policy: OnchainPolicy; attestation: OnchainAttestation | null; registry_fresh: boolean; + publication_compatible?: boolean; + publication_compatibility_status?: string | null; } export interface OnchainEnforcement extends OnchainEvaluation { diff --git a/apps/web/src/components/AssetPicker.tsx b/apps/web/src/components/AssetPicker.tsx index 4378aed..bb1932b 100644 --- a/apps/web/src/components/AssetPicker.tsx +++ b/apps/web/src/components/AssetPicker.tsx @@ -8,17 +8,16 @@ type AssetPickerOption = { const ASSET_DISPLAY_NAMES: Record = { NVDAx: "NVIDIA Tokenized Equity", SPYx: "S&P 500 Tokenized ETF", - QQQx: "Nasdaq-100 Tokenized ETF", AAPLx: "Apple Tokenized Equity", }; export function assetDisplayName(asset: string): string { - return ASSET_DISPLAY_NAMES[asset] ?? "Tokenized equity"; + return ASSET_DISPLAY_NAMES[asset] ?? "Tokenized Equity"; } export function assetAvailabilityLabel(operationalReady: boolean | undefined): string { if (operationalReady === undefined) return "Checking"; - return operationalReady ? "Available" : "Coming soon"; + return operationalReady ? "Available" : "Coming Soon"; } export function AssetPicker({ assets, selectedAsset, onChange }: { @@ -110,16 +109,16 @@ export function AssetPicker({ assets, selectedAsset, onChange }: { type="search" role="combobox" value={query} - aria-label="Search assets" + aria-label="Search Assets" aria-autocomplete="list" aria-controls="asset-picker-listbox" aria-expanded="true" aria-activedescendant={filtered[highlighted] ? `asset-option-${filtered[highlighted].asset}` : undefined} - placeholder="Search assets…" + placeholder="Search Assets…" onChange={(event) => setQuery(event.target.value)} onKeyDown={handleSearchKeyDown} /> -
+
{filtered.map((option, index) =>

Shared vocabulary

Use the product’s terms precisely.

These definitions stay constant across every profile. Short examples show how each term appears in the current product.

{glossary.map(({ term, definition, example }) =>
{term}
{definition}EXAMPLE{example}
)}

Also useful for

{guide.label}

These supporting concepts change with your selected profile, so the glossary stays focused on the decisions and questions you are most likely to encounter.

{supplementaryTerms.map(({ term, definition, example }) =>
{term}
{definition}{example}
)}
-

Current product scope

A focused vertical slice.

Operational validation
NVDAx / NVDA · SPYx / SPY · AAPLx / AAPL
Production asset selector
NVDAx, SPYx, AAPLx; each has a live scheduler, asset-specific runtime, and canonical historical panel.
Research-only asset
QQQx retains offline quant and historical research but is not exposed through production HTTP.
Validation semantics
Observed xStock target · P1a-C model-based challenger · exact-time X-Perp second-market evidence.
Onchain binding
NVDAx only · X Layer testnet

Trust and limitations

Research evidence, not a production guarantee.

  • No exact “true” fair value is observable while the strongest market is closed.
  • Historical diagnostics and retrospective tri-source results are not production guarantees.
  • The testnet contracts are not audited production lending infrastructure.
  • Valtide does not choose a universal LTV, trade, liquidate, or custody assets; consuming applications enforce their own policies.
+

Current product scope

A focused vertical slice.

Operational validation
NVDAx / NVDA · SPYx / SPY · AAPLx / AAPL
Production asset selector
NVDAx, SPYx, AAPLx; each has a live scheduler, asset-specific runtime, and canonical historical panel.
Research-only asset
QQQx retains offline quant and historical research but is not exposed through production HTTP.
Validation semantics
Observed xStock target · P1a-C model-based challenger · exact-time X-Perp second-market evidence.
Onchain binding
NVDAx · SPYx · AAPLx · X Layer testnet

Trust and limitations

Research evidence, not a production guarantee.

  • No exact “true” fair value is observable while the strongest market is closed.
  • Historical diagnostics and retrospective tri-source results are not production guarantees.
  • The testnet contracts are not audited production lending infrastructure.
  • Valtide does not choose a universal LTV, trade, liquidate, or custody assets; consuming applications enforce their own policies.
; diff --git a/apps/web/src/components/EscalationChart.tsx b/apps/web/src/components/EscalationChart.tsx index e03d91a..507332f 100644 --- a/apps/web/src/components/EscalationChart.tsx +++ b/apps/web/src/components/EscalationChart.tsx @@ -3,13 +3,14 @@ import { Area, ComposedChart, Line, ReferenceLine, ResponsiveContainer, Tooltip, import type { EvidenceState, ValuationResult } from "../api/types"; import { EVIDENCE } from "../lib/evidence"; import { coverageLabel, dateTimeUTC, timeAxisUTC } from "../lib/format"; +import { isEvidenceStateV2 } from "../lib/semantics"; interface ChartPoint { sourceIndex: number | null; ts: number; band: [number, number] | null; fair: number | null; - rut: number | null; + xperp: number | null; token: number | null; state: EvidenceState | null; } @@ -30,6 +31,12 @@ const DOMINANT_AXIS_THRESHOLD = 1.2; const CHART_MARGIN = { top: 10, right: 18, bottom: 4, left: 2 } as const; const Y_AXIS_WIDTH = 50; +export const VALUATION_CHART_LABELS = { + fair: "Valtide Fair Value", + token: "Observed xStock", + xperp: "X-Perp", +} as const; + export type ChartDomain = [number, number]; export function lowerBoundTimestamp(points: ChartPoint[], timestamp: number): number { @@ -77,6 +84,11 @@ export function chartDomain(timestamps: number[]): ChartDomain { return [valid[0], valid[valid.length - 1]]; } +export function chartIntervalLabel(results: ValuationResult[]): string { + const targets = [...new Set(results.map((result) => result.interval_coverage_target))]; + return targets.length === 1 ? coverageLabel(targets[0]) : "Valuation Range"; +} + export function minimumViewportWidth(timestamps: number[]): number { const valid = [...new Set(timestamps.filter((timestamp) => Number.isFinite(timestamp)))].sort((a, b) => a - b); const gaps = valid.slice(1).map((timestamp, index) => timestamp - valid[index]).filter((gap) => gap > 0); @@ -147,7 +159,6 @@ export function wheelGestureIntent(deltaX: number, deltaY: number): "pan" | "zoo export function EscalationChart({ results, index, playhead = index, onSelect, resetKey }: { results: ValuationResult[]; index: number; playhead?: number; onSelect: (i: number) => void; resetKey?: string | number }) { const data = useMemo(() => buildChartData(results), [results]); - const unified = results[index]?.validation_target === "xstock_observed_price" || results[index]?.reference_profile === "unified_xstock_p1ac_xperp_evidence_v1"; const realPoints = useMemo(() => data.filter((point) => point.sourceIndex != null), [data]); const timestamps = useMemo(() => realPoints.map((point) => point.ts), [realPoints]); const fullDomain = useMemo(() => chartDomain(timestamps), [timestamps]); @@ -195,14 +206,13 @@ export function EscalationChart({ results, index, playhead = index, onSelect, re [renderData, viewportDomain[0], viewportDomain[1]], ); const visibleRealPoints = useMemo(() => visibleData.filter((point) => point.sourceIndex != null), [visibleData]); - const allPrices = useMemo(() => data.flatMap((point) => [point.band?.[0], point.band?.[1], point.rut, point.token].filter((value): value is number => value != null)), [data]); - const visiblePrices = useMemo(() => visibleData.flatMap((point) => [point.band?.[0], point.band?.[1], point.rut, point.token].filter((value): value is number => value != null)), [visibleData]); + const allPrices = useMemo(() => data.flatMap((point) => [point.band?.[0], point.band?.[1], point.xperp, point.token].filter((value): value is number => value != null)), [data]); + const visiblePrices = useMemo(() => visibleData.flatMap((point) => [point.band?.[0], point.band?.[1], point.xperp, point.token].filter((value): value is number => value != null)), [visibleData]); const prices = visiblePrices.length ? visiblePrices : allPrices; const minTimestamp = viewportDomain[0]; const maxTimestamp = viewportDomain[1]; const multiDay = new Date(minTimestamp).toISOString().slice(0, 10) !== new Date(maxTimestamp).toISOString().slice(0, 10); - const coverageTargets = useMemo(() => [...new Set(results.map((result) => result.interval_coverage_target))], [results]); - const intervalName = coverageTargets.length === 1 ? coverageLabel(coverageTargets[0]) : "Calibrated interval"; + const intervalName = useMemo(() => chartIntervalLabel(results), [results]); const min = prices.length ? Math.min(...prices) : 0; const max = prices.length ? Math.max(...prices) : 1; const span = max - min; @@ -334,7 +344,7 @@ export function EscalationChart({ results, index, playhead = index, onSelect, re return (
- + point.sourceIndex != null && isEvidenceStateV2(results[point.sourceIndex])) ? VALUATION_CHART_LABELS.xperp : "Reference under test"} /> - + @@ -408,7 +418,7 @@ function StateDot({ cx, cy, payload, selectedIndex }: DotProps & { selectedIndex ); } -function buildChartData(results: ValuationResult[]): ChartPoint[] { +export function buildChartData(results: ValuationResult[]): ChartPoint[] { const points: ChartPoint[] = []; let previousTimestamp: number | null = null; @@ -416,9 +426,9 @@ function buildChartData(results: ValuationResult[]): ChartPoint[] { const timestamp = Date.parse(result.timestamp); if (!Number.isFinite(timestamp)) return; if (previousTimestamp != null && timestamp - previousTimestamp > CANONICAL_STEP_MS) { - points.push({ sourceIndex: null, ts: previousTimestamp + Math.floor((timestamp - previousTimestamp) / 2), band: null, fair: null, rut: null, token: null, state: null }); + points.push({ sourceIndex: null, ts: previousTimestamp + Math.floor((timestamp - previousTimestamp) / 2), band: null, fair: null, xperp: null, token: null, state: null }); } - points.push({ sourceIndex, ts: timestamp, band: [result.fair_value_lower, result.fair_value_upper], fair: result.valtide_fair_value, rut: result.reference_under_test, token: result.token_price, state: result.evidence_state }); + points.push({ sourceIndex, ts: timestamp, band: [result.fair_value_lower, result.fair_value_upper], fair: result.valtide_fair_value, xperp: isEvidenceStateV2(result) ? result.xperp_index_price ?? null : result.reference_under_test, token: result.token_price, state: result.evidence_state }); previousTimestamp = timestamp; }); return points; diff --git a/apps/web/src/components/InstrumentPassport.tsx b/apps/web/src/components/InstrumentPassport.tsx index 9a64b96..03cb380 100644 --- a/apps/web/src/components/InstrumentPassport.tsx +++ b/apps/web/src/components/InstrumentPassport.tsx @@ -34,9 +34,9 @@ export function InstrumentPassport({ initialAddress = "" }: { initialAddress?: s return (
Precomputed · not live} + title="Token Rights Metadata" + subtitle="Review demo economic-rights metadata before interpreting price evidence." + right={Demo Data} >
@@ -50,14 +50,14 @@ export function InstrumentPassport({ initialAddress = "" }: { initialAddress?: s className="technical-mono min-h-11 min-w-0 flex-1 rounded px-3 py-2 text-sm text-ink outline-none" style={{ background: "var(--color-panel-2)", border: `1px solid ${status === "invalid" ? "var(--color-line-strong)" : "var(--color-line)"}` }} /> - - + +
-

This preloaded fixture illustrates rights metadata. It does not query the address or verify a live token.

+

Demo data illustrates token rights. Address checks do not query the network or verify a live token.

{status === "invalid" &&

Enter 0x followed by exactly 40 hexadecimal characters.

} - {status === "unknown" &&

No verified passport fixture for this address. No collateral attributes have been inferred.

} + {status === "unknown" &&

No demo metadata is available for this address. No collateral attributes have been inferred.

} {status === "resolved" && }
@@ -67,23 +67,23 @@ export function InstrumentPassport({ initialAddress = "" }: { initialAddress?: s function PassportCard() { const rows = [ - ["Price exposure", DEMO_PASSPORT.priceExposure, "verified"], - ["Shareholder rights", DEMO_PASSPORT.shareholderRights, "mismatch"], - ["Dividend treatment", DEMO_PASSPORT.dividendTreatment, "warning"], + ["Price Exposure", DEMO_PASSPORT.priceExposure, "verified"], + ["Shareholder Rights", DEMO_PASSPORT.shareholderRights, "mismatch"], + ["Dividend Treatment", DEMO_PASSPORT.dividendTreatment, "warning"], ["Redemption", DEMO_PASSPORT.redemption, "warning"], ] as const; return ( -
+
-
Collateral identity
{DEMO_PASSPORT.asset} · {DEMO_PASSPORT.network}
- Rights profile · differs from a share +
Collateral Identity
{DEMO_PASSPORT.asset} · {DEMO_PASSPORT.network}
+ Rights Profile · Differs From A Share
- {rows.map(([label, value]) =>
{label}
{label === "Price exposure" ? `${value} · FIXTURE ASSERTION` : value}
)} + {rows.map(([label, value]) =>
{label}
{label === "Price Exposure" ? `${value} · Demo Assertion` : value}
)}
{DEMO_PASSPORT.address}
-

Precomputed fixture · not live address resolution

+

Demo Data · No Live Address Lookup

); } diff --git a/apps/web/src/components/LandingPage.tsx b/apps/web/src/components/LandingPage.tsx index e51ee48..8411b21 100644 --- a/apps/web/src/components/LandingPage.tsx +++ b/apps/web/src/components/LandingPage.tsx @@ -166,14 +166,14 @@ export function LandingPage() {
CURATOR / PROTOCOL

Policy mapping

ALLOWMONITORREQUIRE_REVIEWRESTRICT_NEW_RISK
CONSUMER

Enforcement

The consuming application defines what the returned action does.

-

The browser is read-only: it observes and explains. It does not calculate Evidence State, edit policy, hold the publisher signer, or publish attestations.

+

The browser is read-only: it observes and explains. It does not calculate Evidence State, edit policy, hold the publisher signer, sign, or submit transactions.

05AUDITABLE DELIVERY

Every conclusion leaves a trail.

-

The human interface explains the evidence. For NVDAx, the machine interface can publish an authorized attestation to the deployed X Layer testnet control plane; consuming applications remain responsible for enforcement.

+

The human interface explains the evidence. For NVDAx, SPYx, and AAPLx, the machine interface can publish authorized attestations to the deployed X Layer testnet control plane; consuming applications remain responsible for enforcement.

{deliverySteps.map((step) =>
{step.number}{step.title}{step.body}
)} @@ -183,7 +183,7 @@ export function LandingPage() {

Current prototype scope

-
Operational validation
NVDAx · SPYx · AAPLx
Validation target
Observed xStock price, with P1a-C and exact-time X-Perp evidence
Onchain binding
NVDAx only · X Layer testnet · Chain ID 1952
Research-only asset
QQQx · not exposed through production HTTP
Status
Research / hackathon prototype
+
Operational validation
NVDAx · SPYx · AAPLx
Validation target
Observed xStock price, with P1a-C and exact-time X-Perp evidence
Onchain binding
NVDAx · SPYx · AAPLx · X Layer testnet · Chain ID 1952
Research-only asset
QQQx · not exposed through production HTTP
Status
Research / hackathon prototype

Deliberate boundaries

diff --git a/apps/web/src/components/MethodologyPage.tsx b/apps/web/src/components/MethodologyPage.tsx index ebcb34d..ee2bfc6 100644 --- a/apps/web/src/components/MethodologyPage.tsx +++ b/apps/web/src/components/MethodologyPage.tsx @@ -44,7 +44,7 @@ export function MethodologyPage() { METHOD STATUS
Operational validation
NVDAx · SPYx · AAPLx
-
Onchain binding
NVDAx only
+
Onchain binding
NVDAx · SPYx · AAPLx
Challenger
{MODEL_EVIDENCE_SUMMARY.model}
Interval target
{(MODEL_EVIDENCE_SUMMARY.coverageTarget * 100).toFixed(0)}%
Network
X Layer testnet
diff --git a/apps/web/src/components/ObservationAudit.tsx b/apps/web/src/components/ObservationAudit.tsx index 5d7463d..ed2aca0 100644 --- a/apps/web/src/components/ObservationAudit.tsx +++ b/apps/web/src/components/ObservationAudit.tsx @@ -1,5 +1,8 @@ import type { OnchainControlPlane, RuntimeStatus, ValuationResult } from "../api/types"; -import { ageLabel, sourceLabel } from "../lib/format"; +import { ageLabel, dateTimeUTC, modelDisplayName, money, sourceLabel, timeUTC } from "../lib/format"; +import { isEvidenceStateV2 } from "../lib/semantics"; + +const EVIDENCE_STATE_V2 = "p1a_xstock_band_with_xperp_review_corroboration_v2"; // Ages are backend measurements at the selected observation, not risk buckets. export function ObservationAudit({ result, context, runtime, controlPlane }: { @@ -10,42 +13,62 @@ export function ObservationAudit({ result, context, runtime, controlPlane }: { }) { const observed = result?.timestamp; const recency = observed ? Math.max(0, Math.floor((Date.now() - Date.parse(observed)) / 1000)) : null; + const operational = context === "Operational"; + const runtimeHasError = operational && !!runtime && (runtime.last_tick_status === "failure" || !!runtime.last_error); + const feedStatus = !runtime?.scheduler_enabled ? "Unavailable" + : runtimeHasError ? "Check Required" + : runtime.last_tick_status === "success" ? "Ready" : "Starting"; + const titleTime = context === "Demo" ? timeUTC(observed) : dateTimeUTC(observed); + const olderRule = !!result?.evidence_semantics && result.evidence_semantics !== EVIDENCE_STATE_V2; + const xperpSource = result && (isEvidenceStateV2(result) ? result.xperp_index_source : result.xperp_index_source ?? result.reference_under_test_source); + const xperpObservedAt = result && (isEvidenceStateV2(result) ? result.xperp_index_ts : result.xperp_index_ts ?? result.reference_under_test_ts); + return (
- Observation details · {context === "Demo" ? "Scenario observation" : context === "Historical" ? "Historical observation" : "5-minute operational observation"} · {observed ?? "UNAVAILABLE"} + Observation Details · {context} · {titleTime}
- - - - - -
-
- - - {context === "Operational" && } - - - + + + + +
- - - - - + + + + + {operational && } + + {olderRule && } + {operational && controlPlane && }
+ {operational &&
+ + + {runtimeHasError && } + {runtimeHasError && } +
}
-
Source provenance
-
{Object.entries(result?.source_provenance ?? {}).map(([key, value]) => )}
- {!Object.keys(result?.source_provenance ?? {}).length && Not supplied} +
Source Provenance
+
{Object.entries(result?.source_provenance ?? {}).map(([key, value]) => )}
+ {!Object.keys(result?.source_provenance ?? {}).length && Not Supplied}
); } +function provenanceLabel(key: string): string { + const known: Record = { + token_source: "Token Source", + underlying_source: "Underlying Source", + scenario: "Scenario", + }; + return known[key] ?? key.replace(/[_-]+/g, " ").replace(/(^|\s)\w/g, (letter) => letter.toUpperCase()); +} + function Field({ label, value }: { label: string; value?: string | null }) { return
{label}
{value ?? "—"}
; } diff --git a/apps/web/src/components/PolicyFoundry.tsx b/apps/web/src/components/PolicyFoundry.tsx index f887bff..e5ce5f5 100644 --- a/apps/web/src/components/PolicyFoundry.tsx +++ b/apps/web/src/components/PolicyFoundry.tsx @@ -4,14 +4,14 @@ import { Panel } from "./ui"; export function PolicyFoundry() { return ( Not deployed} + title="Policy Proposal" + subtitle="A deterministic demo policy for review. It is not a live proposal." + right={Not Deployed} >
- $ valtide policy-proposal --fixture nvda-weekend - Read-only + $ valtide policy-proposal --demo weekend + Read Only
RuleCurrentProposed @@ -21,13 +21,13 @@ export function PolicyFoundry() {
-
Unsigned calldataChecked-in ABI fixture
+
Unsigned CalldataReference ABI
{POLICY_PROPOSAL.calldata}
-

The calldata format matches the checked-in ABI fixture. It has not been simulated, signed, or submitted. The browser has no publisher key, vault-owner key, signing capability, or transaction-submission tool.

+

This demo does not sign or submit transactions. It does not change the selected Evidence State or any deployed policy.

-
No transaction capability in this prototype
+
Review Only · No Transaction Submission
); } diff --git a/apps/web/src/components/ReasonCodes.tsx b/apps/web/src/components/ReasonCodes.tsx index f39644b..fc1dfb6 100644 --- a/apps/web/src/components/ReasonCodes.tsx +++ b/apps/web/src/components/ReasonCodes.tsx @@ -1,8 +1,8 @@ import type { EvidenceState } from "../api/types"; import { reasonLabel } from "../lib/format"; -const POSITIVE = new Set(["TOKEN_AND_CHALLENGER_AGREE", "P1A_XSTOCK_SUPPORT_BAND"]); -const CHALLENGE = new Set(["REFERENCE_UNDER_TEST_OUTSIDE_INTERVAL", "P1A_XSTOCK_REVIEW_BAND", "XPERP_CORROBORATES_P1A"]); +const POSITIVE = new Set(["P1A_XSTOCK_SUPPORT_BAND"]); +const CHALLENGE = new Set(["XPERP_CORROBORATES_P1A"]); const WARNING = new Set([ "TOKEN_DATA_UNAVAILABLE", "COMPARATOR_UNAVAILABLE", @@ -20,6 +20,8 @@ const WARNING = new Set([ "XPERP_EVIDENCE_STALE", "XPERP_EVIDENCE_AMBIGUOUS", "XPERP_CORROBORATES_XSTOCK", + "P1A_XSTOCK_REVIEW_BAND", + "XPERP_EVIDENCE_WRONG_SOURCE", ]); export function ReasonCodes({ codes, evidenceState }: { codes: string[]; evidenceState: EvidenceState }) { @@ -32,7 +34,8 @@ export function ReasonCodes({ codes, evidenceState }: { codes: string[]; evidenc return (
    {codes.map((c) => { - const tone = POSITIVE.has(c) ? "positive" : CHALLENGE.has(c) && evidenceState === "CHALLENGED" ? "challenge" : WARNING.has(c) || CHALLENGE.has(c) ? "warning" : "neutral"; + const challengeSignal = evidenceState === "CHALLENGED" && (CHALLENGE.has(c) || c === "P1A_XSTOCK_REVIEW_BAND"); + const tone = POSITIVE.has(c) ? "positive" : challengeSignal ? "challenge" : WARNING.has(c) || CHALLENGE.has(c) ? "warning" : "neutral"; const colors = tone === "positive" ? { background: "var(--color-supported-soft)", color: "var(--color-supported)", border: "var(--color-supported-line)" } : tone === "challenge" diff --git a/apps/web/src/components/ReferenceNumberLine.tsx b/apps/web/src/components/ReferenceNumberLine.tsx index f307f29..01d3f95 100644 --- a/apps/web/src/components/ReferenceNumberLine.tsx +++ b/apps/web/src/components/ReferenceNumberLine.tsx @@ -1,46 +1,63 @@ import type { ValuationResult } from "../api/types"; -import { money } from "../lib/format"; +import { coverageLabel, money } from "../lib/format"; import { priceToFraction, unitsToFraction } from "../lib/scale"; +import { isEvidenceStateV2, isXStockValidation } from "../lib/semantics"; export function ReferenceNumberLine({ r }: { r: ValuationResult }) { - const unified = r.validation_target === "xstock_observed_price" || r.reference_profile === "unified_xstock_p1ac_xperp_evidence_v1"; + const evidenceStateV2 = isEvidenceStateV2(r); + const xstockProduct = isXStockValidation(r); + const xperpPrice = evidenceStateV2 ? r.xperp_index_price : r.xperp_index_price ?? r.reference_under_test; + const fairValueFraction = priceToFraction(r.valtide_fair_value, r); + const xstockPrices = [ + { label: "Observed xStock", price: r.token_price, color: "var(--color-series-token)", shape: "circle" }, + { label: "Valtide Fair Value", price: r.valtide_fair_value, color: "var(--color-series-valtide)", shape: "square" }, + { label: "X-Perp", price: xperpPrice, color: "var(--color-series-reference)", shape: "diamond" }, + ]; const candidates = [ - { label: unified ? "X-Perp evidence" : "Reference", price: unified ? r.xperp_index_price : r.reference_under_test, color: "var(--color-series-reference)", shape: "diamond" }, - { label: unified ? "xStock target" : "Token market", price: r.token_price, color: "var(--color-series-token)", shape: "circle" }, - { label: "Last trusted price", price: r.last_trusted_reference, color: "var(--color-series-trusted)", shape: "square" }, - { label: "Constructed", price: r.external_constructed_reference, color: "var(--color-series-valtide)", shape: "circle" }, + ...(xstockProduct ? xstockPrices : [ + { label: "Reference under test", price: r.reference_under_test, color: "var(--color-series-reference)", shape: "diamond" }, + ]), ]; const markers = candidates.filter((marker): marker is typeof marker & { price: number } => marker.price != null); - const bandStart = unitsToFraction(-1) * 100; - const bandWidth = (unitsToFraction(1) - unitsToFraction(-1)) * 100; + const summary = xstockProduct ? xstockPrices : markers; + const validInterval = Number.isFinite(r.fair_value_lower) + && Number.isFinite(r.fair_value_upper) + && r.fair_value_upper > r.fair_value_lower; + const bandStart = validInterval ? unitsToFraction(-1) * 100 : fairValueFraction * 100; + const bandWidth = validInterval ? (unitsToFraction(1) - unitsToFraction(-1)) * 100 : 0; + const rangeLabel = coverageLabel(r.interval_coverage_target); + const accessibleLabel = xstockProduct + ? `Observed xStock ${money(r.token_price)}; Valtide Fair Value ${money(r.valtide_fair_value)}; X-Perp ${money(xperpPrice)}; ${rangeLabel} from ${money(r.fair_value_lower)} to ${money(r.fair_value_upper)}` + : `Reference under test ${money(r.reference_under_test)}; Valtide Fair Value ${money(r.valtide_fair_value)}; ${rangeLabel} from ${money(r.fair_value_lower)} to ${money(r.fair_value_upper)}`; return (
    {money(r.fair_value_lower)} – {money(r.fair_value_upper)} - {Math.round(r.interval_coverage_target * 100)}% interval + {rangeLabel}
    -
    +
    -
    -
    Fair value {money(r.valtide_fair_value)}
    - {markers.map((marker) => ( -
    +
    +
    Valtide Fair Value {money(r.valtide_fair_value)}
    + {markers.map((marker) => { + const markerFraction = marker.label === "Valtide Fair Value" ? fairValueFraction : priceToFraction(marker.price, r); + return
    -
    - ))} -
    Below rangeAbove range
    +
    ; + })} +
    Below RangeAbove Range
    - {markers.map((marker) =>
    {marker.label}
    {money(marker.price)}
    )} + {summary.map((item) =>
    {item.label}
    {money(item.price)}
    )}
    ); diff --git a/apps/web/src/components/RegistryPanel.tsx b/apps/web/src/components/RegistryPanel.tsx index d51088f..b4a2926 100644 --- a/apps/web/src/components/RegistryPanel.tsx +++ b/apps/web/src/components/RegistryPanel.tsx @@ -1,7 +1,7 @@ import type { ReactNode } from "react"; import type { OnchainControlPlane, OnchainEnforcement, RuntimeStatus } from "../api/types"; import type { OnchainSyncStatus } from "../lib/onchain"; -import { deliveryStatusLabel, pipelineStatusLabel, unixDateTimeUTC } from "../lib/format"; +import { dateTimeUTC, deliveryStatusLabel, pipelineStatusLabel, unixDateTimeUTC } from "../lib/format"; import { Panel } from "./ui"; interface RegistryPanelProps { @@ -10,41 +10,45 @@ interface RegistryPanelProps { runtime?: RuntimeStatus; sync?: OnchainSyncStatus; mode?: "operational" | "historical" | "demo"; + bindingConfigured?: boolean; isLoading?: boolean; isError?: boolean; errorDetail?: string; } -export function RegistryPanel({ controlPlane, enforcement, runtime, sync, mode = "operational", isLoading, isError, errorDetail }: RegistryPanelProps) { - if (isLoading) return ; +export function RegistryPanel({ controlPlane, enforcement, runtime, sync, mode = "operational", bindingConfigured = true, isLoading, isError, errorDetail }: RegistryPanelProps) { + if (!bindingConfigured) { + return null; + } + if (isLoading) return ; if (!controlPlane) { const modeDetail = mode === "demo" ? "Demo playback is read-only and does not publish." : mode === "historical" ? "Historical evidence is not substituted for current chain state." : "No deployed state was returned."; - return ; + return ; } const attestation = controlPlane.attestation; const modeNote = mode === "demo" ? "Live deployed state — not driven by this scenario." : mode === "historical" ? "Current deployed state — not historical chain state for the selected observation." : null; return ( - +
    {controlPlane.network}Chain {controlPlane.chain_id} · DEPLOYED
    {modeNote && {modeNote}}
    - - - - - + + + + +
    {sync &&
    Operational → Registry · {sync.state} — {sync.detail}{unixDateTimeUTC(sync.operationalObservedAt)} / {unixDateTimeUTC(sync.registryObservedAt)}
    }
    - Technical details+ + Technical Details+
    @@ -52,37 +56,36 @@ export function RegistryPanel({ controlPlane, enforcement, runtime, sync, mode = - - + + - + - - + +
    - {runtime?.last_publish_error &&

    Publication error: {runtime.last_publish_error}

    } + {runtime?.last_publish_error &&

    Publication Error: {runtime.last_publish_error}

    }
    - -

    Publishing is handled by the backend. This browser can only read onchain data.

    +
    ); } function UnavailableRegistryPanel({ status, detail, runtime }: { status: string; detail: string; runtime?: RuntimeStatus }) { return ( - {status}}> + {status}}>
    - - - - - + + + + +

    X Layer is the deployed control plane where Valtide attestations become protocol policy. {detail}

    @@ -90,18 +93,19 @@ function UnavailableRegistryPanel({ status, detail, runtime }: { status: string; ); } -function PublicationDetails({ runtime }: { runtime?: RuntimeStatus }) { +function PublicationDetails({ runtime, controlPlane }: { runtime?: RuntimeStatus; controlPlane?: OnchainControlPlane }) { return
    - Publication status + Publication Status
    - - - - - - -
    Transaction hash
    {runtime?.last_publish_tx_hash ?? "—"}
    -
    Delivery error
    {runtime?.last_publish_error ?? (runtime ? "None" : "UNAVAILABLE")}
    + + + + + + + +
    Transaction Hash
    {runtime?.last_publish_tx_hash ?? "—"}
    +
    Delivery Error
    {runtime?.last_publish_error ?? (runtime ? "None" : "Unavailable")}
    ; } diff --git a/apps/web/src/fixtures/console_weekend_divergence_v2.json b/apps/web/src/fixtures/console_weekend_divergence_v2.json new file mode 100644 index 0000000..3a42433 --- /dev/null +++ b/apps/web/src/fixtures/console_weekend_divergence_v2.json @@ -0,0 +1,8 @@ +[ + {"asset":"NVDAx","timestamp":"2026-09-19T14:00:00Z","market_state":"closed","last_trusted_reference":180,"token_price":180,"token_source":null,"token_observed_at":null,"token_volume":42000,"token_volume_usd":null,"token_liquidity_usd":null,"external_constructed_reference":null,"valtide_fair_value":180,"fair_value_lower":179.55951354541344,"fair_value_upper":180.4415670340159,"interval_coverage_target":0.9,"observed_token_move_pct":0,"model_implied_move_pct":0,"residual_premium_discount_pct":0,"reference_under_test":180,"reference_under_test_source":"okx_xperp_index","reference_profile":"unified_xstock_p1ac_xperp_evidence_v1","reference_under_test_ts":"2026-09-19T14:00:00Z","reference_under_test_age_seconds":0,"reference_deviation_pct":0,"standardized_deviation":null,"xperp_index_price":180,"xperp_index_source":"okx_xperp_index","xperp_index_ts":"2026-09-19T14:00:00Z","xstock_vs_p1ac_deviation_pct":0,"xperp_vs_p1ac_deviation_pct":0,"xstock_vs_xperp_deviation_pct":0,"xperp_deviation_scaled_by_model_predictive_sd":null,"evidence_state_basis":"frozen_p1a_xstock_support_band_with_exact_xperp_available","validation_target":"xstock_observed_price","evidence_semantics":"p1a_xstock_band_with_xperp_review_corroboration_v2","xperp_role":"second_market_challenger","challenger_detector":{"artifact_version":"james-challenger-tail-v1","score_name":"disagreement_z","score":0,"review_threshold":0.8224619622115359,"challenge_threshold":1.5816442827412427,"research_band":"support","promotion_status":"CHALLENGER_DETECTOR_NOT_PROMOTABLE"},"evidence_state":"SUPPORTED","reason_codes":["CALIBRATION_GLOBAL_FALLBACK","TOKEN_AND_CHALLENGER_AGREE","P1A_XSTOCK_SUPPORT_BAND"],"confidence":null,"model_id":"P1a-C","model_version":"0.2.0","interval_semantics":"reference_equivalent_predictive","interval_calibration_type":"session_sym","interval_calibration_source":"global_fallback","reference_age_seconds":64800,"source_provenance":{"scenario":"weekend_divergence"}}, + {"asset":"NVDAx","timestamp":"2026-09-19T14:05:00Z","market_state":"closed","last_trusted_reference":180,"token_price":179.9,"token_source":null,"token_observed_at":null,"token_volume":39000,"token_volume_usd":null,"token_liquidity_usd":null,"external_constructed_reference":null,"valtide_fair_value":179.94885319883048,"fair_value_lower":179.5921777922779,"fair_value_upper":180.30623697334875,"interval_coverage_target":0.9,"observed_token_move_pct":-0.05555555555555314,"model_implied_move_pct":-0.02841488953861937,"residual_premium_discount_pct":-0.027148380199171207,"reference_under_test":179.9,"reference_under_test_source":"okx_xperp_index","reference_profile":"unified_xstock_p1ac_xperp_evidence_v1","reference_under_test_ts":"2026-09-19T14:05:00Z","reference_under_test_age_seconds":0,"reference_deviation_pct":-0.027148380199171207,"standardized_deviation":null,"xperp_index_price":179.9,"xperp_index_source":"okx_xperp_index","xperp_index_ts":"2026-09-19T14:05:00Z","xstock_vs_p1ac_deviation_pct":-0.027148380199171207,"xperp_vs_p1ac_deviation_pct":-0.027148380199171207,"xstock_vs_xperp_deviation_pct":0,"xperp_deviation_scaled_by_model_predictive_sd":null,"evidence_state_basis":"frozen_p1a_xstock_support_band_with_exact_xperp_available","validation_target":"xstock_observed_price","evidence_semantics":"p1a_xstock_band_with_xperp_review_corroboration_v2","xperp_role":"second_market_challenger","challenger_detector":{"artifact_version":"james-challenger-tail-v1","score_name":"disagreement_z","score":0.18406462144079763,"review_threshold":0.8224619622115359,"challenge_threshold":1.5816442827412427,"research_band":"support","promotion_status":"CHALLENGER_DETECTOR_NOT_PROMOTABLE"},"evidence_state":"SUPPORTED","reason_codes":["CALIBRATION_GLOBAL_FALLBACK","TOKEN_AND_CHALLENGER_AGREE","P1A_XSTOCK_SUPPORT_BAND"],"confidence":null,"model_id":"P1a-C","model_version":"0.2.0","interval_semantics":"reference_equivalent_predictive","interval_calibration_type":"session_sym","interval_calibration_source":"global_fallback","reference_age_seconds":65100,"source_provenance":{"scenario":"weekend_divergence"}}, + {"asset":"NVDAx","timestamp":"2026-09-19T14:10:00Z","market_state":"closed","last_trusted_reference":180,"token_price":179.7,"token_source":null,"token_observed_at":null,"token_volume":51000,"token_volume_usd":null,"token_liquidity_usd":null,"external_constructed_reference":null,"valtide_fair_value":179.85670428606014,"fair_value_lower":179.5302525445358,"fair_value_upper":180.18374963639428,"interval_coverage_target":0.9,"observed_token_move_pct":-0.16666666666667052,"model_implied_move_pct":-0.07960872996659596,"residual_premium_discount_pct":-0.08712729763518112,"reference_under_test":179.7,"reference_under_test_source":"okx_xperp_index","reference_profile":"unified_xstock_p1ac_xperp_evidence_v1","reference_under_test_ts":"2026-09-19T14:10:00Z","reference_under_test_age_seconds":0,"reference_deviation_pct":-0.08712729763518112,"standardized_deviation":null,"xperp_index_price":179.7,"xperp_index_source":"okx_xperp_index","xperp_index_ts":"2026-09-19T14:10:00Z","xstock_vs_p1ac_deviation_pct":-0.08712729763518112,"xperp_vs_p1ac_deviation_pct":-0.08712729763518112,"xstock_vs_xperp_deviation_pct":0,"xperp_deviation_scaled_by_model_predictive_sd":null,"evidence_state_basis":"frozen_p1a_xstock_support_band_with_exact_xperp_available","validation_target":"xstock_observed_price","evidence_semantics":"p1a_xstock_band_with_xperp_review_corroboration_v2","xperp_role":"second_market_challenger","challenger_detector":{"artifact_version":"james-challenger-tail-v1","score_name":"disagreement_z","score":0.645325754757238,"review_threshold":0.8224619622115359,"challenge_threshold":1.5816442827412427,"research_band":"support","promotion_status":"CHALLENGER_DETECTOR_NOT_PROMOTABLE"},"evidence_state":"SUPPORTED","reason_codes":["CALIBRATION_GLOBAL_FALLBACK","TOKEN_AND_CHALLENGER_AGREE","P1A_XSTOCK_SUPPORT_BAND"],"confidence":null,"model_id":"P1a-C","model_version":"0.2.0","interval_semantics":"reference_equivalent_predictive","interval_calibration_type":"session_sym","interval_calibration_source":"global_fallback","reference_age_seconds":65400,"source_provenance":{"scenario":"weekend_divergence"}}, + {"asset":"NVDAx","timestamp":"2026-09-19T14:15:00Z","market_state":"closed","last_trusted_reference":180,"token_price":179.4,"token_source":null,"token_observed_at":null,"token_volume":60000,"token_volume_usd":null,"token_liquidity_usd":null,"external_constructed_reference":null,"valtide_fair_value":179.71563484699195,"fair_value_lower":179.40341456220114,"fair_value_upper":180.02839849661487,"interval_coverage_target":0.9,"observed_token_move_pct":-0.33333333333332993,"model_implied_move_pct":-0.15798064056002925,"residual_premium_discount_pct":-0.17563015441626195,"reference_under_test":180,"reference_under_test_source":"okx_xperp_index","reference_profile":"unified_xstock_p1ac_xperp_evidence_v1","reference_under_test_ts":"2026-09-19T14:15:00Z","reference_under_test_age_seconds":0,"reference_deviation_pct":0.1582306142980494,"standardized_deviation":null,"xperp_index_price":180,"xperp_index_source":"okx_xperp_index","xperp_index_ts":"2026-09-19T14:15:00Z","xstock_vs_p1ac_deviation_pct":-0.17563015441626195,"xperp_vs_p1ac_deviation_pct":0.1582306142980494,"xstock_vs_xperp_deviation_pct":-0.33333333333332993,"xperp_deviation_scaled_by_model_predictive_sd":null,"evidence_state_basis":"p1a_xstock_band_with_xperp_review_corroboration_v2","validation_target":"xstock_observed_price","evidence_semantics":"p1a_xstock_band_with_xperp_review_corroboration_v2","xperp_role":"second_market_challenger","challenger_detector":{"artifact_version":"james-challenger-tail-v1","score_name":"disagreement_z","score":1.359722377970915,"review_threshold":0.8224619622115359,"challenge_threshold":1.5816442827412427,"research_band":"watch","promotion_status":"CHALLENGER_DETECTOR_NOT_PROMOTABLE"},"evidence_state":"INCONCLUSIVE","reason_codes":["CALIBRATION_GLOBAL_FALLBACK","TOKEN_AND_CHALLENGER_AGREE","P1A_XSTOCK_WATCH_BAND"],"confidence":null,"model_id":"P1a-C","model_version":"0.2.0","interval_semantics":"reference_equivalent_predictive","interval_calibration_type":"session_sym","interval_calibration_source":"global_fallback","reference_age_seconds":65700,"source_provenance":{"scenario":"weekend_divergence"}}, + {"asset":"NVDAx","timestamp":"2026-09-19T14:20:00Z","market_state":"closed","last_trusted_reference":180,"token_price":178.8,"token_source":null,"token_observed_at":null,"token_volume":72000,"token_volume_usd":null,"token_liquidity_usd":null,"external_constructed_reference":null,"valtide_fair_value":179.4607091717363,"fair_value_lower":179.15613894197222,"fair_value_upper":179.7657971790402,"interval_coverage_target":0.9,"observed_token_move_pct":-0.6666666666666599,"model_implied_move_pct":-0.2996060157020475,"residual_premium_discount_pct":-0.3681636915320752,"reference_under_test":180,"reference_under_test_source":"okx_xperp_index","reference_profile":"unified_xstock_p1ac_xperp_evidence_v1","reference_under_test_ts":"2026-09-19T14:20:00Z","reference_under_test_age_seconds":0,"reference_deviation_pct":0.3005063508066286,"standardized_deviation":null,"xperp_index_price":180,"xperp_index_source":"okx_xperp_index","xperp_index_ts":"2026-09-19T14:20:00Z","xstock_vs_p1ac_deviation_pct":-0.3681636915320752,"xperp_vs_p1ac_deviation_pct":0.3005063508066286,"xstock_vs_xperp_deviation_pct":-0.6666666666666599,"xperp_deviation_scaled_by_model_predictive_sd":null,"evidence_state_basis":"frozen_p1a_xstock_review_band_with_xperp_directional_corroboration","validation_target":"xstock_observed_price","evidence_semantics":"p1a_xstock_band_with_xperp_review_corroboration_v2","xperp_role":"second_market_challenger","challenger_detector":{"artifact_version":"james-challenger-tail-v1","score_name":"disagreement_z","score":2.9206335174017806,"review_threshold":0.8224619622115359,"challenge_threshold":1.5816442827412427,"research_band":"review","promotion_status":"CHALLENGER_DETECTOR_NOT_PROMOTABLE"},"evidence_state":"CHALLENGED","reason_codes":["CALIBRATION_GLOBAL_FALLBACK","TOKEN_AND_CHALLENGER_AGREE","P1A_XSTOCK_REVIEW_BAND","XPERP_CORROBORATES_P1A"],"confidence":null,"model_id":"P1a-C","model_version":"0.2.0","interval_semantics":"reference_equivalent_predictive","interval_calibration_type":"session_sym","interval_calibration_source":"global_fallback","reference_age_seconds":66000,"source_provenance":{"scenario":"weekend_divergence"}}, + {"asset":"NVDAx","timestamp":"2026-09-19T14:25:00Z","market_state":"closed","last_trusted_reference":180,"token_price":178.2,"token_source":null,"token_observed_at":null,"token_volume":68000,"token_volume_usd":null,"token_liquidity_usd":null,"external_constructed_reference":null,"valtide_fair_value":179.13014522772664,"fair_value_lower":178.8300428498307,"fair_value_upper":179.43075122031613,"interval_coverage_target":0.9,"observed_token_move_pct":-1.0000000000000009,"model_implied_move_pct":-0.48325265126297756,"residual_premium_discount_pct":-0.5192566703634216,"reference_under_test":180,"reference_under_test_source":"okx_xperp_index","reference_profile":"unified_xstock_p1ac_xperp_evidence_v1","reference_under_test_ts":"2026-09-19T14:25:00Z","reference_under_test_age_seconds":0,"reference_deviation_pct":0.48559932286522667,"standardized_deviation":null,"xperp_index_price":180,"xperp_index_source":"okx_xperp_index","xperp_index_ts":"2026-09-19T14:25:00Z","xstock_vs_p1ac_deviation_pct":-0.5192566703634216,"xperp_vs_p1ac_deviation_pct":0.48559932286522667,"xstock_vs_xperp_deviation_pct":-1.0000000000000009,"xperp_deviation_scaled_by_model_predictive_sd":null,"evidence_state_basis":"frozen_p1a_xstock_review_band_with_xperp_directional_corroboration","validation_target":"xstock_observed_price","evidence_semantics":"p1a_xstock_band_with_xperp_review_corroboration_v2","xperp_role":"second_market_challenger","challenger_detector":{"artifact_version":"james-challenger-tail-v1","score_name":"disagreement_z","score":4.176087221906172,"review_threshold":0.8224619622115359,"challenge_threshold":1.5816442827412427,"research_band":"review","promotion_status":"CHALLENGER_DETECTOR_NOT_PROMOTABLE"},"evidence_state":"CHALLENGED","reason_codes":["CALIBRATION_GLOBAL_FALLBACK","TOKEN_AND_CHALLENGER_AGREE","P1A_XSTOCK_REVIEW_BAND","XPERP_CORROBORATES_P1A"],"confidence":null,"model_id":"P1a-C","model_version":"0.2.0","interval_semantics":"reference_equivalent_predictive","interval_calibration_type":"session_sym","interval_calibration_source":"global_fallback","reference_age_seconds":66300,"source_provenance":{"scenario":"weekend_divergence"}} +] diff --git a/apps/web/src/lib/format.ts b/apps/web/src/lib/format.ts index 56f3b5d..53cabaf 100644 --- a/apps/web/src/lib/format.ts +++ b/apps/web/src/lib/format.ts @@ -33,6 +33,11 @@ export function dateTimeUTC(iso: string | null | undefined): string { return `${d.toISOString().slice(0, 16).replace("T", " ")} UTC`; } +export function modelDisplayName(version: string | null | undefined): string { + if (!version) return "Valtide Model"; + return `Valtide Model · ${version.startsWith("v") ? version : `v${version}`}`; +} + export function unixTimeUTC(seconds: number | null | undefined): string { if (seconds == null || Number.isNaN(seconds) || seconds <= 0) return DASH; return timeUTC(new Date(seconds * 1000).toISOString()); @@ -71,8 +76,8 @@ export function compactUsd(x: number | null | undefined): string { } export function coverageLabel(target: number | null | undefined): string { - if (target == null || !Number.isFinite(target)) return "Calibrated interval"; - return `${Math.round(target * 100)}% calibrated interval`; + if (target == null || !Number.isFinite(target)) return "Valuation Range"; + return `${Math.round(target * 100)}% Valuation Range`; } export function timeAxisUTC(timestampMs: number, multiDay: boolean): string { @@ -85,14 +90,14 @@ export function timeAxisUTC(timestampMs: number, multiDay: boolean): string { export function sessionLabel(state: string): string { switch (state) { case "regular": - return "Regular session"; + return "Regular Session"; case "premarket": case "afterhours": - return "Extended hours"; + return "Extended Hours"; case "overnight": return "Overnight"; case "closed": - return "Market closed"; + return "Market Closed"; default: return state; } @@ -102,18 +107,16 @@ export function sourceLabel(source: string | null | undefined): string { if (!source) return DASH; const labels: Record = { okx_onchainos: "OKX OnchainOS", - okx_xperp_index: "OKX X-Perp index", - alpaca: "Alpaca NVDA", - dexscreener: "DexScreener diagnostic", + okx_xperp_index: "OKX X-Perp Index", + alpaca: "Alpaca", + dexscreener: "DexScreener Diagnostic", }; return labels[source] ?? source; } export function pipelineStatusLabel(status: string | null | undefined): string { - if (!status) return "UNAVAILABLE"; - if (status === "READ ONLY") return status; - if (status === "published") return "PUBLISHED"; - return status.replace(/[-\s]+/g, "_").toUpperCase(); + if (!status) return "Unavailable"; + return status.replace(/[_-]+/g, " ").toLowerCase().replace(/(^|\s)\w/g, (letter) => letter.toUpperCase()); } export function deliveryStatusLabel(status: string | null | undefined): string { @@ -126,25 +129,26 @@ const REASON_LABELS: Record = { TOKEN_DATA_UNAVAILABLE: "Tokenized-market observation unavailable", COMPARATOR_UNAVAILABLE: "Independent comparator unavailable", MODEL_UNCERTAINTY_INVALID: "Model uncertainty unavailable", - REFERENCE_UNDER_TEST_OUTSIDE_INTERVAL: "Reference under test is outside the calibrated interval", + REFERENCE_UNDER_TEST_OUTSIDE_INTERVAL: "Recorded reference is outside the calibrated interval", UNDERLYING_REFERENCE_STALE: "Trusted underlying observation is stale", REFERENCE_UNDER_TEST_STALE: "Reference under test is stale", TOKEN_MARKET_QUALITY_LOW: "Tokenized-market quality is low", TOKEN_AND_CHALLENGER_AGREE: "Tokenized market and model agree", TOKEN_UNIT_SUSPECT: "Possible token/underlying unit mismatch", MODEL_UNCERTAINTY_HIGH: "Model uncertainty is high", - CALIBRATION_GLOBAL_FALLBACK: "Global fallback calibration", - P1A_XSTOCK_DETECTOR_UNAVAILABLE: "P1a/xStock detector unavailable", - P1A_XSTOCK_SUPPORT_BAND: "P1a/xStock disagreement is in the support band", - P1A_XSTOCK_WATCH_BAND: "P1a/xStock disagreement is in the watch band", - P1A_XSTOCK_REVIEW_BAND: "P1a/xStock disagreement is in the review band", - P1A_XSTOCK_SUPPORT_NOT_PROMOTED: "Support state is not enabled for this asset", - P1A_XSTOCK_CHALLENGE_NOT_PROMOTED: "Challenge state is not enabled for this asset", - XPERP_EVIDENCE_UNAVAILABLE: "Exact-time X-Perp evidence unavailable", - XPERP_EVIDENCE_STALE: "X-Perp evidence is stale or not exact-time", - XPERP_EVIDENCE_AMBIGUOUS: "X-Perp does not clearly favor xStock or P1a", - XPERP_CORROBORATES_XSTOCK: "X-Perp is closer to the observed xStock price", - XPERP_CORROBORATES_P1A: "X-Perp directionally corroborates P1a", + CALIBRATION_GLOBAL_FALLBACK: "Global Calibration Applied", + P1A_XSTOCK_SUPPORT_BAND: "Low Model Disagreement", + P1A_XSTOCK_WATCH_BAND: "Moderate Model Disagreement", + P1A_XSTOCK_REVIEW_BAND: "High Model Disagreement", + XPERP_CORROBORATES_XSTOCK: "X-Perp Supports xStock", + XPERP_CORROBORATES_P1A: "X-Perp Supports Model Challenge", + XPERP_EVIDENCE_AMBIGUOUS: "X-Perp Evidence Is Ambiguous", + XPERP_EVIDENCE_UNAVAILABLE: "X-Perp Evidence Is Unavailable", + XPERP_EVIDENCE_STALE: "X-Perp Evidence Is Stale", + XPERP_EVIDENCE_WRONG_SOURCE: "X-Perp Source Is Not Verified", + P1A_XSTOCK_DETECTOR_UNAVAILABLE: "Model Disagreement Signal Unavailable", + P1A_XSTOCK_SUPPORT_NOT_PROMOTED: "Support Signal Not Enabled", + P1A_XSTOCK_CHALLENGE_NOT_PROMOTED: "Challenge Signal Not Enabled", }; export function reasonLabel(code: string): string { diff --git a/apps/web/src/lib/scale.ts b/apps/web/src/lib/scale.ts index ba60ff0..59f2706 100644 --- a/apps/web/src/lib/scale.ts +++ b/apps/web/src/lib/scale.ts @@ -1,30 +1,25 @@ -// Band-relative scaling — the chart display rule from PRODUCT_SEMANTICS.md. -// -// The whole demo happens inside a ~$0.90 window, so a raw-price axis makes -// SUPPORTED and CHALLENGED look identical. We instead plot everything in -// band-relative units: the challenger fair value is 0, the lower interval edge -// is -1, the upper edge is +1 (handling asymmetric bands). A reference at +1 -// sits exactly on the interval boundary; beyond ±1 it is outside the interval. +// Range View uses an interval-relative scale for the selected observation. import type { ValuationResult } from "../api/types"; +import { validationTargetPrice } from "./semantics"; -/** Fixed viewport so the reference visibly travels outward across steps. */ +/** Fixed normalized viewport; prices outside the interval can extend to its edges. */ export const AXIS_MIN = -3.5; export const AXIS_MAX = 3.5; -/** Convert a price into band-relative units for a given result. */ +/** Map a price linearly across the selected result's valuation interval. */ export function toBandUnits(price: number, r: ValuationResult): number { - const fair = r.valtide_fair_value; - if (price <= fair) { - const half = fair - r.fair_value_lower; - return half > 0 ? (price - fair) / half : 0; - } - const half = r.fair_value_upper - fair; - return half > 0 ? (price - fair) / half : 0; + const lower = r.fair_value_lower; + const upper = r.fair_value_upper; + const interval = upper - lower; + if (!Number.isFinite(price) || !Number.isFinite(lower) || !Number.isFinite(upper) || !Number.isFinite(interval) || !(interval > 0)) return 0; + const units = -1 + (2 * (price - lower)) / interval; + return Number.isFinite(units) ? units : 0; } /** Map band-units to a 0..1 fraction across the fixed axis (for CSS %). */ export function unitsToFraction(units: number): number { + if (!Number.isFinite(units)) return 0.5; const clamped = Math.max(AXIS_MIN, Math.min(AXIS_MAX, units)); return (clamped - AXIS_MIN) / (AXIS_MAX - AXIS_MIN); } @@ -36,8 +31,7 @@ export function priceToFraction(price: number, r: ValuationResult): number { /** Is the active validation target outside the actual calibrated interval bounds? */ export function referenceOutsideBand(r: ValuationResult): boolean { - const unified = r.validation_target === "xstock_observed_price" || r.reference_profile === "unified_xstock_p1ac_xperp_evidence_v1"; - const target = unified ? r.token_price : r.reference_under_test; + const target = validationTargetPrice(r); if (target == null) return false; return target < r.fair_value_lower || target > r.fair_value_upper; } diff --git a/apps/web/src/lib/semantics.ts b/apps/web/src/lib/semantics.ts new file mode 100644 index 0000000..3856111 --- /dev/null +++ b/apps/web/src/lib/semantics.ts @@ -0,0 +1,106 @@ +import type { EvidenceState, ValuationResult } from "../api/types"; +import { DASH } from "./format"; + +export const EVIDENCE_SEMANTICS_V2 = "p1a_xstock_band_with_xperp_review_corroboration_v2"; +export const UNIFIED_REFERENCE_PROFILE = "unified_xstock_p1ac_xperp_evidence_v1"; + +export function isEvidenceStateV2(result: Pick): boolean { + return result.evidence_semantics === EVIDENCE_SEMANTICS_V2; +} + +export function isXStockValidation(result: Pick): boolean { + return result.validation_target === "xstock_observed_price" + || result.reference_profile === "xstock_vs_p1ac_challenger" + || isEvidenceStateV2(result); +} + +export function validationTargetPrice(result: ValuationResult): number | null { + return isXStockValidation(result) ? result.token_price : result.reference_under_test; +} + +export interface EvidenceCopy { + title: string; + detail: string; +} + +const V2_COPY: Record = { + SUPPORTED: { + title: "Observed xStock Is Supported", + detail: "Model disagreement is low and required market data passes quality checks.", + }, + INCONCLUSIVE: { + title: "Evidence Is Inconclusive", + detail: "Model disagreement is elevated, evidence conflicts, or a required market check is unavailable.", + }, + CHALLENGED: { + title: "Observed xStock Is Challenged", + detail: "Model disagreement is high and X-Perp independently supports the model-side challenge. This does not prove the xStock price is wrong.", + }, +}; + +const LEGACY_XSTOCK_COPY: Record = { + SUPPORTED: { + title: "Model-Based Challenger Evidence Supports the Observed xStock", + detail: "This earlier model-based result is shown as recorded and has not been reclassified.", + }, + INCONCLUSIVE: { + title: "Model-Based Challenger Evidence Needs Review", + detail: "This earlier model-based result is shown as recorded and has not been reclassified.", + }, + CHALLENGED: { + title: "Model-Based Challenger Evidence Challenges the Observed xStock", + detail: "This earlier model-based result is shown as recorded and has not been reclassified.", + }, +}; + +export function evidenceCopy(result: ValuationResult): EvidenceCopy { + if (isEvidenceStateV2(result)) return V2_COPY[result.evidence_state]; + if (result.evidence_semantics) { + return { + title: `Recorded ${result.evidence_state.toLowerCase()} evidence`, + detail: "This earlier observation is shown with the Evidence State and rule metadata recorded at the time. It has not been reclassified by the current Console.", + }; + } + if (result.reference_profile === "xstock_vs_p1ac_challenger") return LEGACY_XSTOCK_COPY[result.evidence_state]; + return { + title: result.evidence_state === "SUPPORTED" ? "Evidence Supports the Reference" + : result.evidence_state === "CHALLENGED" ? "Evidence Challenges the Reference" : "Evidence Needs Review", + detail: "This earlier observation is shown with its recorded reference and Evidence State. It has not been reclassified by the current Console.", + }; +} + +export function modelDistanceLabel(scoreName: string | null | undefined, score: number | null | undefined): string { + if (score == null || !Number.isFinite(score)) return DASH; + if (scoreName === "disagreement_z") return `${score.toFixed(1)}σ`; + if (scoreName === "disagreement_bps") return `${score.toFixed(1)} bps`; + return DASH; +} + +export function peakModelDistance(results: ValuationResult[]): string { + const scored = results.flatMap((result) => { + const detector = result.challenger_detector; + return detector?.score != null && Number.isFinite(detector.score) + ? [{ scoreName: detector.score_name, score: Math.abs(detector.score) }] + : []; + }); + const scoreNames = new Set(scored.map(({ scoreName }) => scoreName)); + if (!scored.length || scoreNames.size !== 1) return DASH; + const scoreName = scored[0].scoreName; + return modelDistanceLabel(scoreName, Math.max(...scored.map(({ score }) => score))); +} + +export function modelDependenceNote(result: ValuationResult): string { + if (isEvidenceStateV2(result)) { + return "P1a-C assimilates the current xStock observation before emitting its estimate. xStock-versus-P1a-C is model-based challenger evidence, not two fully independent observations. X-Perp/index is separately sourced market evidence; disagreement alone does not establish which price is correct."; + } + if (result.reference_profile === UNIFIED_REFERENCE_PROFILE) { + return "This stored unified-profile observation retains the rule metadata available at the time. Its Evidence State is shown as recorded and is not recomputed by the Console."; + } + if (result.reference_profile === "legacy_xperp_vs_p1ac") { + return "This stored legacy observation evaluates the separate OKX X-Perp index against its recorded P1a-C challenger. Its Evidence State is retained as recorded."; + } + if (result.reference_profile === "xstock_vs_p1ac_challenger") { + return "P1a-C assimilates the current xStock observation before emitting its estimate. This is model-based challenger evidence, not two fully independent observations; disagreement alone does not establish which price is correct."; + } + return "This stored observation retains its original reference and Evidence State metadata."; +} diff --git a/apps/web/src/views/HistoricalReplay.tsx b/apps/web/src/views/HistoricalReplay.tsx index ee6682e..f6c2236 100644 --- a/apps/web/src/views/HistoricalReplay.tsx +++ b/apps/web/src/views/HistoricalReplay.tsx @@ -4,8 +4,9 @@ import { EscalationChart } from "../components/EscalationChart"; import { EvidenceChip } from "../components/EvidenceChip"; import { Panel } from "../components/ui"; import { Icon } from "../components/Icon"; -import { coverageLabel, money, dateTimeUTC } from "../lib/format"; +import { money, dateTimeUTC } from "../lib/format"; import { advancePosition, clampPosition } from "../lib/playback"; +import { isEvidenceStateV2 } from "../lib/semantics"; export function HistoricalReplay({ asset, @@ -66,38 +67,41 @@ export function HistoricalReplay({ const index = Math.floor(clampPosition(position, results.length)); const current = results[index]; + const v2 = results.some(isEvidenceStateV2); const atEnd = position >= results.length - 1; const targets = [...new Set(results.map((result) => result.interval_coverage_target))]; - const intervalLabel = targets.length === 1 ? coverageLabel(targets[0]) : "Calibrated interval"; + const intervalLabel = targets.length === 1 ? `${Math.round(targets[0] * 100)}% Valuation Range` : "Valuation Range"; const gaps = results.slice(1).filter((result, i) => Date.parse(result.timestamp) - Date.parse(results[i].timestamp) > 5 * 60_000).length; return ( {sourceLabel}} >
    -
    {followingLatest ? "Latest observation" : "Selected period"}
    +
    {followingLatest ? "Latest Observation" : "Selected Period"}
    {money(current.valtide_fair_value)}
    {rangeControl &&
    {rangeControl}
    - Scroll to zoom · Drag to pan + Scroll To Zoom · Drag To Pan
    }
    {coverageNotice &&

    {coverageNotice}

    }
    - - - + + + {intervalLabel} {gaps > 0 && {gaps} data gaps}
    - { onReview?.(); setPlaying(false); setPosition(clampPosition(next, results.length)); }} /> +
    + { onReview?.(); setPlaying(false); setPosition(clampPosition(next, results.length)); }} /> +
    {showPlayback && ( diff --git a/apps/web/src/views/ModelEvidence.tsx b/apps/web/src/views/ModelEvidence.tsx index 8872631..d756190 100644 --- a/apps/web/src/views/ModelEvidence.tsx +++ b/apps/web/src/views/ModelEvidence.tsx @@ -3,7 +3,7 @@ import type { EvidenceState } from "../api/types"; import { assetQueryKeys, fetchHistoricalBacktest } from "../api/client"; import { Panel } from "../components/ui"; import { EVIDENCE } from "../lib/evidence"; -import { dateTimeUTC } from "../lib/format"; +import { dateTimeUTC, modelDisplayName } from "../lib/format"; const STATES: EvidenceState[] = ["SUPPORTED", "INCONCLUSIVE", "CHALLENGED"]; @@ -23,20 +23,20 @@ export function ModelEvidence({ asset, profile }: { asset: string; profile: stri const hasMetrics = data && data.mae != null && data.rmse != null && data.interval_coverage != null; return ( - + {isError || !data ? (
    {isLoading ? "Loading historical model evidence…" : "Historical model evidence unavailable. Scenario verdicts are not empirical performance evidence."}
    ) : ( <> -

    These counts describe classifications, not price accuracy. This period is separate from the homepage evaluation.

    +

    These counts describe how the shared backend validation pipeline classified historical observations; they are not an accuracy score or a performance guarantee.

    - Evidence states across historical observations ({total}) + Evidence States Across Historical Observations ({total})
    - Window: {dateTimeUTC(data.window_start)} → {dateTimeUTC(data.window_end)} - Model: {data.model_id ?? "—"} {data.model_version ?? ""} + Historical window: {dateTimeUTC(data.window_start)} → {dateTimeUTC(data.window_end)} + Model: {modelDisplayName(data.model_version)}
    {STATES.map((s) => { @@ -55,13 +55,13 @@ export function ModelEvidence({ asset, profile }: { asset: string; profile: stri
    - - + +
    - Advanced point-error diagnostics -
    + Advanced Point-Error Diagnostics +

    {data.note}

    diff --git a/apps/web/src/views/ObservationRecord.tsx b/apps/web/src/views/ObservationRecord.tsx index ac7fbc5..af166ae 100644 --- a/apps/web/src/views/ObservationRecord.tsx +++ b/apps/web/src/views/ObservationRecord.tsx @@ -1,7 +1,8 @@ import type { EvidenceState, ValuationResult } from "../api/types"; import { Panel } from "../components/ui"; import { EVIDENCE } from "../lib/evidence"; -import { pct, sigma, sourceLabel, timeUTC } from "../lib/format"; +import { dateTimeUTC, modelDisplayName, pct, sessionLabel, sourceLabel, timeUTC } from "../lib/format"; +import { isXStockValidation, modelDistanceLabel, peakModelDistance } from "../lib/semantics"; const STATES: EvidenceState[] = ["SUPPORTED", "INCONCLUSIVE", "CHALLENGED"]; @@ -11,30 +12,33 @@ export function ObservationRecord({ results, currentIndex, sourceLabelText }: { return acc; }, { SUPPORTED: 0, INCONCLUSIVE: 0, CHALLENGED: 0 }); const transitions = results.filter((result, index) => index > 0 && result.evidence_state !== results[index - 1].evidence_state); - const breaches = results.filter((result) => result.reference_under_test != null && (result.reference_under_test < result.fair_value_lower || result.reference_under_test > result.fair_value_upper)).length; - const maxSigma = results.reduce((max, result) => Math.max(max, Math.abs(result.standardized_deviation ?? 0)), 0); + const scoredTargetRows = results.filter((result) => isXStockValidation(result) ? result.token_price != null : result.reference_under_test != null); + const breaches = scoredTargetRows.filter((result) => { + const target = isXStockValidation(result) ? result.token_price : result.reference_under_test; + return target != null && (target < result.fair_value_lower || target > result.fair_value_upper); + }).length; const current = results[Math.min(currentIndex, results.length - 1)]; const total = Math.max(results.length, 1); const events = results.filter((result, index) => index === 0 || result.evidence_state !== results[index - 1].evidence_state); return ( {sourceLabelText}} >

    Counts show how observations were classified in the selected period. They do not measure price accuracy or production performance.

    - - - + + +
    - State distribution + State Distribution Selected · {current?.evidence_state ?? "—"}
    @@ -48,18 +52,18 @@ export function ObservationRecord({ results, currentIndex, sourceLabelText }: { {results.map((result, index) => { const active = index === currentIndex; const style = EVIDENCE[result.evidence_state]; - return
    ; + return
    ; })}
    - - - - - - + + + + + +
    diff --git a/apps/web/src/views/ReferenceComparison.tsx b/apps/web/src/views/ReferenceComparison.tsx index 173bf2c..a7ca208 100644 --- a/apps/web/src/views/ReferenceComparison.tsx +++ b/apps/web/src/views/ReferenceComparison.tsx @@ -1,22 +1,17 @@ import type { ValuationResult } from "../api/types"; import { ReferenceNumberLine } from "../components/ReferenceNumberLine"; import { Panel } from "../components/ui"; +import { isXStockValidation, validationTargetPrice } from "../lib/semantics"; -// Makes disagreement obvious by plotting every price on an interval-relative -// axis. No composite score hides the outlier. +// Shows the selected observation relative to its own valuation interval. export function ReferenceComparison({ r }: { r: ValuationResult }) { - const unified = r.validation_target === "xstock_observed_price" || r.reference_profile === "unified_xstock_p1ac_xperp_evidence_v1"; - const target = unified ? r.token_price : r.reference_under_test; - const targetInsideRange = target != null && target >= r.fair_value_lower && target <= r.fair_value_upper; - const comparisonBoundary = unified - ? "Unified v2 evidence: xStock is the validation target, P1a-C is a model-based challenger that has assimilated xStock, and exact-time X-Perp is a separate second-market signal." - : r.reference_profile === "legacy_xperp_vs_p1ac" - ? "Legacy NVDAx profile: the reference under test is the separate OKX X-Perp index." - : "The reference profile identifies the source and its relationship to the challenger model inputs."; + const targetPrice = validationTargetPrice(r); + const referenceInsideRange = targetPrice != null && targetPrice >= r.fair_value_lower && targetPrice <= r.fair_value_upper; + const xstockTarget = isXStockValidation(r); return ( - Interval view}> -

    {target == null ? `${unified ? "xStock target" : "Reference price"} unavailable.` : targetInsideRange ? `The ${unified ? "xStock target" : "reference"} is within the P1a-C range.` : `The ${unified ? "xStock target" : "reference"} is outside the P1a-C range.`}

    -

    {comparisonBoundary}

    + Range View}> +

    {targetPrice == null ? `${xstockTarget ? "Observed xStock" : "Reference"} price unavailable.` : referenceInsideRange ? `${xstockTarget ? "Observed xStock" : "Reference"} is within the valuation range.` : `${xstockTarget ? "Observed xStock" : "Reference"} is outside the valuation range.`}

    +

    Evidence State also considers model disagreement, data quality, and X-Perp confirmation.

    ); diff --git a/apps/web/tests/semantics.test.cjs b/apps/web/tests/semantics.test.cjs index f66e0d5..f9f7182 100644 --- a/apps/web/tests/semantics.test.cjs +++ b/apps/web/tests/semantics.test.cjs @@ -8,13 +8,17 @@ const { QueryClient, QueryClientProvider } = require("@tanstack/react-query"); const { load } = require("./load-source.cjs"); const client = load("../src/api/client.ts"); const fixture = require("../src/fixtures/weekend_divergence.json"); +const consoleV2Fixture = require("../src/fixtures/console_weekend_divergence_v2.json"); const { filterOperationalResults, filterHistoricalResults, filterDemoResults, operationalCoverageNotice, OPERATIONAL_HISTORY_MAX } = load("../src/views/OperationalTimeline.tsx"); const { mergeObservations, rebasePosition } = load("../src/lib/playback.ts"); const { ReasonCodes } = load("../src/components/ReasonCodes.tsx"); const { RegistryPanel } = load("../src/components/RegistryPanel.tsx"); const { ReferenceComparison } = load("../src/views/ReferenceComparison.tsx"); +const { ModelEvidence } = load("../src/views/ModelEvidence.tsx"); +const { ReferenceNumberLine } = load("../src/components/ReferenceNumberLine.tsx"); const { ObservationAudit } = load("../src/components/ObservationAudit.tsx"); const { assetAvailabilityLabel, assetDisplayName } = load("../src/components/AssetPicker.tsx"); +const { ObservationRecord } = load("../src/views/ObservationRecord.tsx"); const { Hero } = load("../src/components/Hero.tsx"); const { LandingPage } = load("../src/components/LandingPage.tsx"); const { DocsPage } = load("../src/components/DocsPage.tsx"); @@ -22,13 +26,15 @@ const { MethodologyPage } = load("../src/components/MethodologyPage.tsx"); const { InstrumentPassport, passportStatusFor } = load("../src/components/InstrumentPassport.tsx"); const { PolicyFoundry } = load("../src/components/PolicyFoundry.tsx"); const { DEMO_PASSPORT_ADDRESS, MODEL_EVIDENCE_SUMMARY, POLICY_PROPOSAL } = load("../src/fixtures/prototypeData.ts"); -const { default: App, consoleContextFromSearch } = load("../src/App.tsx"); -const { deliveryStatusLabel, lastUpdatedLabel, pipelineStatusLabel } = load("../src/lib/format.ts"); -const { chartDomain, clampViewport, lowerBoundTimestamp, minimumViewportWidth, panViewport, shouldRenderStateDots, sliceChartDataForViewport, upperBoundTimestamp, wheelGestureIntent, wheelZoomScale, zoomSensitivity, zoomViewport } = load("../src/components/EscalationChart.tsx"); +const { default: App, consoleContextFromSearch, effectiveContextAsset } = load("../src/App.tsx"); +const { coverageLabel, dateTimeUTC, deliveryStatusLabel, lastUpdatedLabel, modelDisplayName, pipelineStatusLabel, sessionLabel } = load("../src/lib/format.ts"); +const { AXIS_MIN, AXIS_MAX, priceToFraction, toBandUnits, unitsToFraction } = load("../src/lib/scale.ts"); +const { modelDistanceLabel, peakModelDistance, evidenceCopy, EVIDENCE_SEMANTICS_V2 } = load("../src/lib/semantics.ts"); +const { buildChartData, chartDomain, chartIntervalLabel, clampViewport, lowerBoundTimestamp, minimumViewportWidth, panViewport, shouldRenderStateDots, sliceChartDataForViewport, upperBoundTimestamp, VALUATION_CHART_LABELS, wheelGestureIntent, wheelZoomScale, zoomSensitivity, zoomViewport } = load("../src/components/EscalationChart.tsx"); const h = React.createElement; const render = (component, props) => renderToStaticMarkup(h(component, props)); -test("Demo returns only the six original backend observations, including original reasons", async () => { +test("Console Demo accepts only the six-row v2 scenario and uses its independent v2 backup", async () => { for (const row of fixture) { assert.equal(row.reference_profile, "unified_xstock_p1ac_xperp_evidence_v1"); assert.equal(row.validation_target, "xstock_observed_price"); @@ -37,7 +43,15 @@ test("Demo returns only the six original backend observations, including origina assert.ok(row.challenger_detector); } const original = global.fetch; - const unusual = fixture.map(row => ({...row, evidence_state: "INCONCLUSIVE", reason_codes: ["CUSTOM_BACKEND_REASON"]})); + const unusual = consoleV2Fixture.map(row => ({...row, reason_codes: ["CUSTOM_BACKEND_REASON"]})); + assert.deepEqual(consoleV2Fixture.map(row => row.evidence_state), [ + "SUPPORTED", "SUPPORTED", "SUPPORTED", "INCONCLUSIVE", "CHALLENGED", "CHALLENGED", + ]); + assert.ok(consoleV2Fixture.every(row => row.asset === "NVDAx" + && row.reference_profile === "unified_xstock_p1ac_xperp_evidence_v1" + && row.evidence_semantics === EVIDENCE_SEMANTICS_V2 + && row.validation_target === "xstock_observed_price" + && row.xperp_role === "second_market_challenger")); try { global.fetch = async () => new Response(JSON.stringify(unusual)); const response = await client.fetchDemoReplay(); @@ -46,8 +60,11 @@ test("Demo returns only the six original backend observations, including origina assert.deepEqual(response.results, unusual); global.fetch = async () => { throw new Error("offline"); }; const fallback = await client.fetchDemoReplay(); - assert.equal(fallback.source, "offline-fixture"); - assert.deepEqual(fallback.results, fixture); + assert.equal(fallback.source, "console-backup"); + assert.deepEqual(fallback.results, consoleV2Fixture); + assert.ok(fallback.results.every(row => row.evidence_semantics === EVIDENCE_SEMANTICS_V2)); + await assert.rejects(client.fetchDemoReplay("SPYx"), /NVDAx-only/); + assert.deepEqual(client.DEMO_REPLAY_QUERY_KEY, ["demo-replay", "NVDAx", "weekend_divergence", EVIDENCE_SEMANTICS_V2]); } finally { global.fetch = original; } }); @@ -126,6 +143,49 @@ test("legacy NVDAx responses are normalized only at the explicit migration bound } finally { global.fetch = original; } }); +test("explicit X Layer binding metadata enables all production assets and missing metadata fails closed", async () => { + const original = global.fetch; + const assets = ["NVDAx", "SPYx", "AAPLx"].map(asset => ({ + asset,token_source:"okx_onchainos",underlying_source:"alpaca", + reference_profile:"unified_xstock_p1ac_xperp_evidence_v1",model_available:true, + api_exposed:true,onchain_binding_configured:true, + })); + try { + global.fetch = async () => new Response(JSON.stringify(assets)); + const normalized = await client.fetchAssets(); + assert.deepEqual(normalized.map(item => item.asset), ["NVDAx", "SPYx", "AAPLx"]); + assert.ok(normalized.every(item => item.onchain_binding_configured)); + + global.fetch = async () => new Response(JSON.stringify(assets.map(({onchain_binding_configured, ...item}) => item))); + const withoutBindingMetadata = await client.fetchAssets(); + assert.deepEqual(withoutBindingMetadata.map(item => item.onchain_binding_configured), [false, false, false]); + } finally { global.fetch = original; } +}); + +test("onchain and enforcement requests are scoped to each explicitly bound asset", async () => { + const original = global.fetch; + const requested = []; + try { + global.fetch = async url => { + const path = new URL(String(url)).pathname; + requested.push(path); + const asset = path.match(/\/api\/onchain\/(NVDAx|SPYx|AAPLx)(?:\/enforcement)?$/)?.[1]; + return new Response(JSON.stringify({asset})); + }; + for (const asset of ["NVDAx", "SPYx", "AAPLx"]) { + assert.equal((await client.fetchOnchain(asset)).asset, asset); + assert.equal((await client.fetchOnchainEnforcement(asset)).asset, asset); + assert.deepEqual(client.assetQueryKeys.onchain(asset), ["onchain", asset]); + assert.deepEqual(client.assetQueryKeys.enforcement(asset), ["onchain", asset, "enforcement"]); + } + assert.deepEqual(requested, [ + "/api/onchain/NVDAx", "/api/onchain/NVDAx/enforcement", + "/api/onchain/SPYx", "/api/onchain/SPYx/enforcement", + "/api/onchain/AAPLx", "/api/onchain/AAPLx/enforcement", + ]); + } finally { global.fetch = original; } +}); + test("Operational windows use timestamps, exclude the boundary and preserve gaps", () => { const latest = Date.parse("2026-09-25T12:00:00Z"); const row = hours => ({...fixture[0], timestamp:new Date(latest-hours*3600000).toISOString()}); @@ -165,7 +225,7 @@ function appWith({result, rows, chain, error, assetList, profile = "legacy_xperp latest_observation_freshness:"unavailable",onchain_binding_configured:true, readiness_error_codes:[], }]); - query.setQueryData(["demo-replay","NVDAx","canonical"],{results:fixture,source:"offline-fixture"}); + query.setQueryData(client.DEMO_REPLAY_QUERY_KEY,{results:consoleV2Fixture,source:"console-backup"}); const operationalKey = client.assetQueryKeys.operational("NVDAx",profile); if (result) query.setQueryData(operationalKey,result); if (rows) query.setQueryData(client.assetQueryKeys.history("NVDAx",OPERATIONAL_HISTORY_MAX,profile),rows); @@ -280,6 +340,21 @@ test("Documentation adapts by role and keeps evidence, policy and scope separate assert.match(fs.readFileSync(path.join(__dirname, "../src/components/DocsPage.tsx"), "utf8"), /cta: "Read the methodology", href: "\/methodology"/); }); +test("Current public X Layer scope names all three bound assets without implying backend publication is browser-driven", () => { + const landing = render(LandingPage); + const docs = render(DocsPage); + const methodology = render(MethodologyPage); + const docsSource = fs.readFileSync(path.join(__dirname,"../src/components/DocsPage.tsx"),"utf8"); + assert.match(landing,/For NVDAx, SPYx, and AAPLx, the machine interface can publish authorized attestations to the deployed X Layer testnet control plane/); + assert.match(docsSource,/shared ValidationRegistry and RiskGuard are deployed on X Layer testnet with asset-specific bindings for NVDAx, SPYx, and AAPLx/); + assert.match(docs,/NVDAx · SPYx · AAPLx · X Layer testnet/); + for (const html of [landing, docs, methodology]) { + assert.match(html,/NVDAx · SPYx · AAPLx/); + assert.doesNotMatch(html,/NVDAx only|Only NVDAx has an X Layer binding/i); + } + assert.match(landing,/browser is read-only:[\s\S]*?sign, or submit transactions/); +}); + test("Methodology is a first-class, source-grounded page with one canonical method", () => { const html = render(MethodologyPage); for (const value of [ @@ -327,13 +402,336 @@ test("Console deep links select a known evidence context and fail closed to Oper assert.equal(consoleContextFromSearch("?view=console&context=unknown"), "Operational"); }); -test("Cold Operational stays unavailable even when Demo is cached", () => { +test("Demo uses canonical NVDAx data, hides selection, and preserves each operational asset selection", () => { + for (const selectedAsset of ["SPYx", "AAPLx", "NVDAx"]) { + assert.equal(effectiveContextAsset("Demo", selectedAsset), "NVDAx"); + assert.equal(effectiveContextAsset("Operational", selectedAsset), selectedAsset); + assert.equal(effectiveContextAsset("Historical", selectedAsset), selectedAsset); + } + + const originalWindow = global.window; + global.window = { location: { search: "?view=console&context=demo", pathname: "/" } }; + try { + const html = appWith({}); + assert.doesNotMatch(html, /asset-picker/); + assert.match(html, /NVDAx Validation Timeline/); + assert.match(html, /Demo Backup · 6 Synthetic Steps/); + assert.match(html, /Demo Policy/); + assert.match(html, /Policy Proposal/); + assert.equal((html.match(/Advanced: Policy Proposal/g) ?? []).length,1); + assert.doesNotMatch(html, /Evidence State v2|X Layer Not Configured/); + assert.doesNotMatch(html, /Research prototype|No transaction capability in this prototype|Demo fixture|backend|fixture/i); + } finally { + if (originalWindow === undefined) delete global.window; + else global.window = originalWindow; + } +}); + +test("Advanced Policy Proposal is one Demo-only full-width row after the primary grid", () => { + const appSource = fs.readFileSync(path.join(__dirname,"../src/App.tsx"),"utf8"); + assert.equal((appSource.match(/Advanced: Policy Proposal/g) ?? []).length,1); + assert.match(appSource,/
    [\s\S]*?[\s\S]*?\s*<\/div>\s*\{context === "Demo" && [\s\S]*?<\/details>\}\s*
    /); + assert.doesNotMatch(appSource,/asset\s*===\s*["'](?:NVDAx|SPYx|AAPLx)["']/); + assert.match(appSource,/assetQueryKeys\.onchain\(contextAsset\), queryFn: \(\) => fetchOnchain\(contextAsset\)[\s\S]*?enabled: backendUp && !!selectedAssetInfo\?\.onchain_binding_configured/); + assert.match(appSource,/assetQueryKeys\.enforcement\(contextAsset\), queryFn: \(\) => fetchOnchainEnforcement\(contextAsset\)[\s\S]*?enabled: backendUp && !!selectedAssetInfo\?\.onchain_binding_configured/); + + const originalWindow = global.window; + try { + global.window = {location:{search:"?view=console&context=operational",pathname:"/"}}; + const operational = appWith({result:fixture[0]}); + assert.doesNotMatch(operational,/Advanced: Policy Proposal/); + global.window = {location:{search:"?view=console&context=historical",pathname:"/"}}; + const historical = appWith({result:fixture[0]}); + assert.doesNotMatch(historical,/Advanced: Policy Proposal/); + global.window = {location:{search:"?view=console&context=demo",pathname:"/"}}; + const demo = appWith({}); + assert.equal((demo.match(/Advanced: Policy Proposal/g) ?? []).length,1); + } finally { + if (originalWindow === undefined) delete global.window; + else global.window = originalWindow; + } +}); + +test("Detector score formatting preserves units and refuses mixed-unit peaks", () => { + assert.equal(modelDistanceLabel("disagreement_z", 0.84), "0.8σ"); + assert.equal(modelDistanceLabel("disagreement_bps", 37.24), "37.2 bps"); + assert.equal(modelDistanceLabel("disagreement_bps", 21.06), "21.1 bps"); + assert.equal(modelDistanceLabel("innovation_abs_z", 1.2), "—"); + assert.equal(modelDistanceLabel("disagreement_z", null), "—"); + assert.equal(modelDistanceLabel("disagreement_z", consoleV2Fixture[0].standardized_deviation), "—"); + assert.equal(peakModelDistance(consoleV2Fixture), "4.2σ"); + assert.equal(peakModelDistance([ + consoleV2Fixture[0], + {...consoleV2Fixture[1], challenger_detector: {...consoleV2Fixture[1].challenger_detector, score_name:"disagreement_bps"}}, + ]), "—"); + assert.equal(peakModelDistance([{...consoleV2Fixture[0], challenger_detector:null}]), "—"); + assert.equal(peakModelDistance([ + {...consoleV2Fixture[0], standardized_deviation:null, challenger_detector:{score_name:"disagreement_bps",score:21.06}}, + {...consoleV2Fixture[1], standardized_deviation:null, challenger_detector:{score_name:"disagreement_bps",score:37.24}}, + ]), "37.2 bps"); +}); + +test("Console Model Distance reads the backend detector score rather than standardized deviation", () => { + const cases = [ + ["NVDAx", "disagreement_z", 0.84, "0.8σ"], + ["SPYx", "disagreement_bps", 37.24, "37.2 bps"], + ["AAPLx", "disagreement_bps", 21.06, "21.1 bps"], + ]; + for (const [asset, scoreName, score, expected] of cases) { + const result = { + ...consoleV2Fixture[0],asset,standardized_deviation:null, + challenger_detector:{...consoleV2Fixture[0].challenger_detector,score_name:scoreName,score}, + }; + const html = appWith({result,profile:result.reference_profile}); + assert.ok(html.includes(expected), `${asset} should show ${expected}`); + } +}); + +test("Peak Model Distance uses the largest compatible detector score and keeps the asset unit", () => { + const rows = [21.06, 37.24, 12].map((score, index) => ({ + ...consoleV2Fixture[index],standardized_deviation:null, + challenger_detector:{...consoleV2Fixture[index].challenger_detector,score_name:"disagreement_bps",score}, + })); + const html = render(ObservationRecord,{results:rows,currentIndex:2,sourceLabelText:"Historical"}); + assert.match(html,/Peak Model Distance[\s\S]*?37\.2 bps/); +}); + +test("Console metrics and interval markers use human-facing model labels and xStock/X-Perp v2 fields", () => { + const v2 = consoleV2Fixture[4]; + const html = appWith({result:v2, profile:v2.reference_profile}); + for (const label of ["Observed xStock", "Valtide Fair Value", "X-Perp", "xStock Vs Model", "Model Distance", "Underlying Anchor"]) assert.match(html, new RegExp(label)); + assert.match(html, /2\.9σ/); + assert.match(html, /xStock ↔ Valtide Model/); + assert.match(html, /Model Move/); + assert.match(html, /Valtide Model · v0\.2\.0/); + assert.doesNotMatch(html, /P1a-C/); + assert.doesNotMatch(html, /Reference under test|Technical diagnostic/); + const numberLine = render(ReferenceNumberLine,{r:v2}); + for (const marker of ["Observed xStock", "X-Perp", "Valtide Fair Value", "90% Valuation Range"]) assert.match(numberLine,new RegExp(marker)); + assert.doesNotMatch(numberLine,/Last Trusted Underlying|Underlying Anchor/); + assert.equal((numberLine.match(/data-price-marker=/g) ?? []).length,3); + for (const label of ["Observed xStock", "Valtide Fair Value", "X-Perp"]) assert.match(numberLine,new RegExp(`data-price-marker="${label}"`)); + const summary = numberLine.slice(numberLine.indexOf("grid-cols-3")); + for (const [label,value] of [["Observed xStock",v2.token_price],["Valtide Fair Value",v2.valtide_fair_value],["X-Perp",v2.xperp_index_price]]) { + assert.match(summary,new RegExp(`${label}[\\s\\S]*?\\$${value.toFixed(2)}`)); + assert.ok(numberLine.includes(`title="${label}: $${value.toFixed(2)}"`), `${label} marker should expose its bound price`); + } + assert.equal((summary.match(/class="min-w-0"/g) ?? []).length,3); + const summaryRows = summary.split('
    ').slice(1); + assert.match(summaryRows[0],/background:var\(--color-series-token\);border-radius:50%[\s\S]*Observed xStock/); + assert.match(summaryRows[1],/background:var\(--color-series-valtide\);border-radius:1px[\s\S]*Valtide Fair Value/); + assert.match(summaryRows[2],/background:var\(--color-series-reference\);border-radius:1px;rotate:45deg[\s\S]*X-Perp/); + assert.match(numberLine,/data-price-marker="Observed xStock"[^>]*>\s*]*>\s*]*>\s* markup.match(new RegExp(`
    ]*>[\\s\\S]*?<\\/div>`))?.[0] ?? ""; + const asymmetric = {...v2,token_price:179.5,valtide_fair_value:180,fair_value_lower:179,fair_value_upper:182,xperp_index_price:181}; + const asymmetricMarkup = render(ReferenceNumberLine,{r:asymmetric}); + const fairFraction = priceToFraction(asymmetric.valtide_fair_value,asymmetric); + const lowerFraction = priceToFraction(asymmetric.fair_value_lower,asymmetric); + const upperFraction = priceToFraction(asymmetric.fair_value_upper,asymmetric); + assert.ok(lowerFraction < fairFraction && fairFraction < upperFraction); + assert.notEqual(fairFraction,(lowerFraction+upperFraction)/2,"asymmetric intervals must preserve Fair Value's proportional position"); + for (const [label,price] of [["Observed xStock",asymmetric.token_price],["Valtide Fair Value",asymmetric.valtide_fair_value],["X-Perp",asymmetric.xperp_index_price]]) { + assert.ok(markerMarkup(asymmetricMarkup,label).includes(`left:${priceToFraction(price,asymmetric)*100}%`), `${label} must use the shared interval-relative scale`); + } + const fairLeft = `${fairFraction*100}%`; + assert.ok(markerMarkup(asymmetricMarkup,"Valtide Fair Value").includes(`left:${fairLeft}`)); + assert.ok(asymmetricMarkup.includes(`class="absolute top-[32px] h-14 w-px" style="left:${fairLeft};`),"Fair Value line must share the square's raw-price position"); + assert.ok(asymmetricMarkup.includes(`class="absolute top-0 -translate-x-1/2 whitespace-nowrap text-center text-[11px]" style="left:${fairLeft};`),"Fair Value label must share the square and line position"); + const bandMatch = asymmetricMarkup.match(/class="absolute top-\[38px\] h-11 rounded" style="left:([^;]+);width:([^;]+);/); + assert.ok(bandMatch); + assert.ok(Math.abs(Number.parseFloat(bandMatch[1])/100-unitsToFraction(-1))<1e-12); + assert.ok(Math.abs(Number.parseFloat(bandMatch[2])/100-(unitsToFraction(1)-unitsToFraction(-1)))<1e-12); + const coincident = {...v2,token_price:180,valtide_fair_value:180,fair_value_lower:179,fair_value_upper:181,xperp_index_price:180}; + const coincidentMarkup = render(ReferenceNumberLine,{r:coincident}); + for (const [label,zIndex,shape] of [["Observed xStock",1,"]*>—<\/div>]*>—<\/div>/); + + const xstockInside = render(ReferenceComparison,{r:{...v2,token_price:100,xperp_index_price:120, fair_value_lower:99,fair_value_upper:101}}); + assert.match(xstockInside,/Observed xStock is within the valuation range/); + const xstockOutside = render(ReferenceComparison,{r:{...v2,token_price:102,xperp_index_price:100, fair_value_lower:99,fair_value_upper:101}}); + assert.match(xstockOutside,/Observed xStock is outside the valuation range/); + assert.match(xstockInside,/Range View/); + assert.equal((xstockInside.match(/Evidence State also considers model disagreement, data quality, and X-Perp confirmation\./g) ?? []).length,1); + assert.doesNotMatch(xstockInside,/P1a-C|SUPPORT|WATCH|REVIEW|not two fully independent observations/); +}); + +test("Range View uses fixed interval-relative geometry independent of absolute prices and timeline span", () => { + const base = consoleV2Fixture[0]; + const observations = [ + {...base,timestamp:"2026-10-01T12:00:00Z",valtide_fair_value:100,fair_value_lower:99,fair_value_upper:101,token_price:100.4,xperp_index_price:99.8,interval_coverage_target:0.9}, + {...base,timestamp:"2026-10-01T12:05:00Z",valtide_fair_value:200,fair_value_lower:199,fair_value_upper:201,token_price:201.5,xperp_index_price:199.3,interval_coverage_target:0.95}, + {...base,timestamp:"2026-10-01T12:10:00Z",valtide_fair_value:503,fair_value_lower:500,fair_value_upper:510,token_price:499,xperp_index_price:508,interval_coverage_target:0.9}, + ]; + const markerBlock = (markup,label) => markup.match(new RegExp(`
    ]*>[\\s\\S]*?<\\/div>`))?.[0] ?? ""; + const markerFraction = (markup,label) => { + const match = markerBlock(markup,label).match(/left:([^;]+);/); + assert.ok(match,`${label} marker should have an interval-relative position`); + return Number.parseFloat(match[1])/100; + }; + const rangePosition = (markup) => { + const match = markup.match(/class="absolute top-\[38px\] h-11 rounded" style="left:([^;]+);width:([^;]+);/); + assert.ok(match,"valuation band should use fixed interval-relative boundaries"); + return {left:Number.parseFloat(match[1])/100,width:Number.parseFloat(match[2])/100}; + }; + const close = (actual,expected,message) => assert.ok(Math.abs(actual-expected)<1e-12,message); + const expectedBand = {left:unitsToFraction(-1),width:unitsToFraction(1)-unitsToFraction(-1)}; + const rendered = observations.map((r) => render(ReferenceNumberLine,{r})); + + for (let index=0; index]*>\$100\.00/); + assert.match(rendered[1],/Valtide Fair Value ]*>\$200\.00/); + + const asymmetric = {...base,token_price:179.5,valtide_fair_value:180,fair_value_lower:179,fair_value_upper:182,xperp_index_price:181}; + const asymmetricMarkup = render(ReferenceNumberLine,{r:asymmetric}); + const lower = priceToFraction(asymmetric.fair_value_lower,asymmetric); + const fair = priceToFraction(asymmetric.valtide_fair_value,asymmetric); + const upper = priceToFraction(asymmetric.fair_value_upper,asymmetric); + assert.ok(lower < fair && fair < upper); + assert.notEqual(fair,(lower+upper)/2,"asymmetric bounds preserve Fair Value's proportional position"); + close(markerFraction(asymmetricMarkup,"Valtide Fair Value"),fair); + close(markerFraction(asymmetricMarkup,"Observed xStock"),priceToFraction(asymmetric.token_price,asymmetric)); + close(markerFraction(asymmetricMarkup,"X-Perp"),priceToFraction(asymmetric.xperp_index_price,asymmetric)); + close(rangePosition(asymmetricMarkup).left,expectedBand.left); + close(rangePosition(asymmetricMarkup).width,expectedBand.width); + + const ascending = {...base,token_price:179,valtide_fair_value:180,xperp_index_price:181,fair_value_lower:178,fair_value_upper:182}; + assert.ok(priceToFraction(ascending.token_price,ascending)priceToFraction(descending.valtide_fair_value,descending)); + assert.ok(priceToFraction(descending.valtide_fair_value,descending)>priceToFraction(descending.xperp_index_price,descending)); + + const outside = {...base,token_price:182,valtide_fair_value:180,xperp_index_price:180.5,fair_value_lower:179,fair_value_upper:181}; + const outsideMarkup = render(ReferenceNumberLine,{r:outside}); + const outsideBand = rangePosition(outsideMarkup); + assert.ok(markerFraction(outsideMarkup,"Observed xStock")>outsideBand.left+outsideBand.width,"out-of-range price stays outside the band"); + assert.ok(markerFraction(outsideMarkup,"Observed xStock")<1,"clamping applies only at the viewport boundary"); + + const coincident = {...base,token_price:180,valtide_fair_value:180,xperp_index_price:180,fair_value_lower:179,fair_value_upper:181}; + const coincidentMarkup = render(ReferenceNumberLine,{r:coincident}); + const coincidentFractions = ["Observed xStock","Valtide Fair Value","X-Perp"].map((label) => markerFraction(coincidentMarkup,label)); + assert.deepEqual(coincidentFractions,[0.5,0.5,0.5]); + assert.equal((coincidentMarkup.match(/data-price-marker=/g)??[]).length,3); + + for (const invalid of [ + {...coincident,fair_value_lower:180,fair_value_upper:180}, + {...coincident,fair_value_lower:181,fair_value_upper:179}, + ]) { + const invalidMarkup = render(ReferenceNumberLine,{r:invalid}); + assert.doesNotMatch(invalidMarkup,/NaN|Infinity/); + assert.match(invalidMarkup,/style="left:50%;width:0%;/); + assert.equal(priceToFraction(invalid.valtide_fair_value,invalid),0.5); + } + + const legacyFallback = {...ascending,evidence_semantics:"p1a_xstock_challenger_xperp_second_market_v1",xperp_index_price:null,reference_under_test:184}; + assert.equal(priceToFraction(184,legacyFallback),markerFraction(render(ReferenceNumberLine,{r:legacyFallback}),"X-Perp")); + + const selected = {...observations[0]}; + const distant = {...selected,fair_value_lower:1,fair_value_upper:1_000_000,token_price:800_000,xperp_index_price:900_000}; + const selectedMarkup = render(ReferenceComparison,{r:selected}); + assert.equal(render(ReferenceComparison,{r:selected,domainResults:[selected,distant]}),selectedMarkup,"unrelated timeline rows cannot alter the selected-observation Range View"); + const appSource = fs.readFileSync(path.join(__dirname,"../src/App.tsx"),"utf8"); + assert.match(appSource,//); + assert.doesNotMatch(appSource,/domainResults=/); +}); + +test("Equal-height Timeline card alignment keeps the chart fixed and Policy Proposal independent", () => { + const appSource = fs.readFileSync(path.join(__dirname,"../src/App.tsx"),"utf8"); + const replaySource = fs.readFileSync(path.join(__dirname,"../src/views/HistoricalReplay.tsx"),"utf8"); + const chartSource = fs.readFileSync(path.join(__dirname,"../src/components/EscalationChart.tsx"),"utf8"); + assert.match(appSource,/grid items-stretch gap-4 xl:grid-cols-\[minmax\(0,1\.3fr\)_minmax\(0,1fr\)\]/); + assert.match(replaySource,/className="flex min-w-0 flex-col"/); + assert.doesNotMatch(replaySource,/className="flex h-full min-w-0 flex-col"/); + assert.match(replaySource,/
    \s*/); + assert.match(replaySource,/className="mt-auto flex flex-wrap items-center gap-3 border-t pt-3"/); + const chartRoot = chartSource.match(/className="([^"]*h-\[320px\][^"]*)"/)?.[1]; + assert.ok(chartRoot,"EscalationChart root retains an explicit fixed height"); + assert.match(chartRoot,/^h-\[320px\] min-h-\[280px\] w-full xl:h-\[360px\]$/); + assert.doesNotMatch(chartRoot,/(?:^|\s)(?:flex-1|h-full|grow)(?:\s|$)/); + assert.doesNotMatch(chartSource,/(?:^|\s)(?:flex-1|h-full|grow)(?:\s|$)/); + assert.match(appSource,/\{context === "Demo" && [\s\S]*?<\/details>\}/); + assert.match(appSource,/<\/div>\s*\{context === "Demo" && \}\s*
    /); +}); + +test("Current semantic copy is shared and old explicit rule generations stay recorded", () => { + const current = evidenceCopy(consoleV2Fixture[0]); + assert.equal(current.title,"Observed xStock Is Supported"); + assert.equal(current.detail,"Model disagreement is low and required market data passes quality checks."); + assert.equal(evidenceCopy(consoleV2Fixture[3]).detail,"Model disagreement is elevated, evidence conflicts, or a required market check is unavailable."); + assert.equal(evidenceCopy(consoleV2Fixture[4]).detail,"Model disagreement is high and X-Perp independently supports the model-side challenge. This does not prove the xStock price is wrong."); + const oldRecord = {...consoleV2Fixture[0], evidence_state:"CHALLENGED", reason_codes:["OLD_RECORDED_REASON"], evidence_semantics:"p1a_xstock_challenger_xperp_second_market_v1"}; + const old = evidenceCopy(oldRecord); + assert.match(old.title,/Recorded challenged evidence/); + assert.match(old.detail,/not been reclassified/); + assert.equal(oldRecord.evidence_state,"CHALLENGED"); + assert.deepEqual(oldRecord.reason_codes,["OLD_RECORDED_REASON"]); +}); + +test("Cold Operational never falls back to cached Demo evidence", () => { const html = appWith({error:"503 data_unavailable"}); - assert.match(html,/Operational unavailable/); + assert.match(html,/Operational (?:Loading|Unavailable)/); assert.doesNotMatch(html,/Demo Fixture · 6 Observations|Scenario policy|Example demo policy/); }); -test("Validation Console exposes the three production catalog identities without implying readiness", () => { +test("Validation Console exposes only the three API-enabled production assets", () => { const base = { token_source:"okx_onchainos",underlying_source:"alpaca",registered:true, api_exposed:true,model_available:false,quant_artifact_ready:false, @@ -348,31 +746,60 @@ test("Validation Console exposes the three production catalog identities without ["SPYx","unified_xstock_p1ac_xperp_evidence_v1"], ["AAPLx","unified_xstock_p1ac_xperp_evidence_v1"], ].map(([asset,reference_profile]) => ({...base,asset,reference_profile})); + catalog.push({...base,asset:"QQQx",reference_profile:"xstock_vs_p1ac_challenger",api_exposed:false}); + catalog.push({...base,asset:"TSLAx",reference_profile:"xstock_vs_p1ac_challenger",api_exposed:false}); const html = appWith({assetList:catalog}); assert.match(html,/aria-haspopup="listbox"/); - assert.match(html,/aria-label="Search assets"/); + assert.match(html,/aria-label="Search Assets"/); + assert.match(html,/aria-label="Available Assets"/); assert.match(html,/asset-picker__chevron/); assert.match(html,/viewBox="0 0 16 16"/); assert.doesNotMatch(html,/⌄/); for (const asset of ["NVDAx","SPYx","AAPLx"]) { assert.match(html,new RegExp(`>${asset}<`)); } - assert.doesNotMatch(html,/>QQQxQQQxTSLAx { assert.equal(assetDisplayName("NVDAx"), "NVIDIA Tokenized Equity"); - assert.equal(assetDisplayName("UNKNOWNx"), "Tokenized equity"); + assert.equal(assetDisplayName("UNKNOWNx"), "Tokenized Equity"); assert.equal(assetAvailabilityLabel(true), "Available"); - assert.equal(assetAvailabilityLabel(false), "Coming soon"); + assert.equal(assetAvailabilityLabel(false), "Coming Soon"); assert.equal(assetAvailabilityLabel(undefined), "Checking"); }); +test("Historical evidence summary uses the selected asset backtest without deriving new states", () => { + const query = new QueryClient({defaultOptions:{queries:{retry:false}}}); + const asset = "SPYx"; + const profile = "unified_xstock_p1ac_xperp_evidence_v1"; + query.setQueryData(client.assetQueryKeys.backtest(asset, profile), { + asset,source:"historical",n_observations:4110, + evidence_state_counts:{SUPPORTED:4009,INCONCLUSIVE:30,CHALLENGED:71}, + n_evaluable:3000,mae:1.2,rmse:2.1,interval_coverage:0.9, + window_start:"2026-09-21T00:00:00Z",window_end:"2026-10-05T06:25:00Z", + model_id:"P1a-C",model_version:"0.3.0",note:"Retrospective diagnostics.", + }); + const html = renderToStaticMarkup(h(QueryClientProvider,{client:query},h(ModelEvidence,{asset,profile}))); + query.clear(); + for (const label of [ + "Selected Historical Evidence", "Evidence States Across Historical Observations", + "Observations", "Observations With A Contemporaneous Benchmark", "Benchmark Coverage", + "Advanced Point-Error Diagnostics", "Mean Absolute Error", "Root Mean Squared Error", + ]) assert.ok(html.includes(label), `missing ${label}`); + assert.match(html,/SUPPORTED 4009/); + assert.match(html,/INCONCLUSIVE 30/); + assert.match(html,/CHALLENGED 71/); + assert.doesNotMatch(html,/James|research dashboard|Threshold Selection/); +}); + test("Operational failure preserves cached evidence with a degraded label", () => { const html = appWith({result:fixture[0],error:"offline"}); assert.match(html,/Operational degraded/); @@ -384,7 +811,7 @@ test("Prior evidence is not paired with current enforcement", () => { const policy = {on_supported:"ALLOW",on_inconclusive:"REQUIRE_REVIEW",on_challenged:"RESTRICT_NEW_RISK",on_stale:"REQUIRE_REVIEW",max_age:900}; const chain = {policy,policy_action:"RESTRICT_NEW_RISK",evidence_state:"CHALLENGED",exists:true,fresh:true,network:"Testnet",chain_id:1952,attestation:null}; const html = appWith({result:fixture[1],rows:fixture.slice(0,2),chain}); - assert.match(html,/Prior evidence → current policy/); + assert.match(html,/Current Policy Mapping/); assert.match(html,/Current deployed state — not historical chain state/); assert.doesNotMatch(html,/Current RiskGuard ·/); }); @@ -393,21 +820,166 @@ test("Current evidence mapping and stale RiskGuard enforcement remain separate", const policy = {on_supported:"ALLOW",on_inconclusive:"REQUIRE_REVIEW",on_challenged:"RESTRICT_NEW_RISK",on_stale:"REQUIRE_REVIEW",max_age:900}; const chain = {policy,policy_action:"REQUIRE_REVIEW",evidence_state:"SUPPORTED",exists:true,fresh:false,network:"Testnet",chain_id:1952,attestation:{publishedAt:Math.floor(Date.now()/1000)-7200}}; const html = appWith({result:fixture[0],chain}); - assert.match(html,/Current evidence → policy action/); + assert.match(html,/Current Policy Mapping/); assert.match(html,/Reason/); - assert.match(html,/Evidence supports the validation target/); - assert.match(html,/RiskGuard data · Stale/); - assert.match(html,/Last updated 2h ago/); - assert.match(html,/Technical details/); - assert.match(html,/Evidence state/); - assert.match(html,/Mapped policy action/); - assert.match(html,/RiskGuard state/); - assert.match(html,/Current RiskGuard action/); + assert.match(html,/Observed xStock Is Supported/); + assert.match(html,/RiskGuard Status/); + assert.match(html,/Evidence State/); + assert.match(html,/Policy Mapping/); + assert.match(html,/Enforced Action/); + const policyStart = html.indexOf(">Policy Action"); + const policyEnd = html.indexOf("
", policyStart); + assert.ok(policyStart >= 0 && policyEnd > policyStart); + assert.doesNotMatch(html.slice(policyStart, policyEnd),/Technical Details/); assert.match(html,/ALLOW/); assert.match(html,/REQUIRE_REVIEW/); assert.doesNotMatch(html,/Raw policy value/); }); +test("Short Console labels and policy actions use consistent title case", () => { + const policy = {on_supported:"ALLOW",on_inconclusive:"MONITOR",on_challenged:"REQUIRE_REVIEW",on_stale:"REQUIRE_REVIEW",max_age:900}; + const chain = {policy,policy_action:"ALLOW",evidence_state:"SUPPORTED",exists:true,fresh:true,network:"Testnet",chain_id:1952,attestation:null}; + for (const [state,action] of [ + ["SUPPORTED","Allow New Borrowing"], + ["INCONCLUSIVE","Continue Monitoring"], + ["CHALLENGED","Pause And Review"], + ]) { + const html = appWith({result:{...fixture[0],evidence_state:state},chain}); + assert.ok(html.includes(action), `missing action ${action}`); + assert.match(html,/Current Finding/); + assert.match(html,/Policy Action/); + } + const html = appWith({result:fixture[0],chain}); + for (const phrase of ["Publication Status","Valuation Range","Range View","Peak Model Distance","Observation Details","Source Provenance","Market State"]) assert.ok(html.includes(phrase), `missing ${phrase}`); +}); + +test("Policy Action exposes its core rows without a disclosure and keeps missing policy non-alarming", () => { + const policy = {on_supported:"ALLOW",on_inconclusive:"REQUIRE_REVIEW",on_challenged:"RESTRICT_NEW_RISK",on_stale:"REQUIRE_REVIEW",max_age:900}; + const chain = {policy,policy_action:"REQUIRE_REVIEW",evidence_state:"SUPPORTED",exists:true,fresh:true,network:"Testnet",chain_id:1952,attestation:null}; + const bound = appWith({result:consoleV2Fixture[0],profile:consoleV2Fixture[0].reference_profile,chain}); + for (const row of ["Evidence State", "Policy Mapping", "RiskGuard Status", "Enforced Action"]) assert.match(bound, new RegExp(row)); + const policyStart = bound.indexOf(">Policy Action"); + const policyEnd = bound.indexOf("", policyStart); + assert.ok(policyStart >= 0 && policyEnd > policyStart); + assert.doesNotMatch(bound.slice(policyStart, policyEnd),/Technical Details/); + + const noBindingAsset = { + asset:"NVDAx",token_source:"okx_onchainos",underlying_source:"alpaca", + reference_profile:consoleV2Fixture[0].reference_profile,registered:true,api_exposed:true, + model_available:true,quant_artifact_ready:true,historical_data_available:true, + live_data_configured:true,runtime_ready:true,operational_ready:true, + operational_scheduler_enabled:true,latest_observation_timestamp:consoleV2Fixture[0].timestamp, + latest_observation_age_seconds:0,latest_observation_freshness:"fresh", + onchain_binding_configured:false,readiness_error_codes:[], + }; + const unbound = appWith({result:consoleV2Fixture[0],profile:consoleV2Fixture[0].reference_profile,assetList:[noBindingAsset]}); + assert.match(unbound,/No Policy Connected/); + assert.match(unbound,/No curator policy is connected for this asset\./); + assert.doesNotMatch(unbound,/X Layer Connected|X Layer Unavailable|X Layer Not Configured|Optional Protocol Deployment|Not Configured|Registry Attestation/); + assert.equal(render(RegistryPanel,{bindingConfigured:false}),""); +}); + +test("RegistryPanel is asset-agnostic across the three API-bound production assets", () => { + const policy = {on_supported:"ALLOW",on_inconclusive:"REQUIRE_REVIEW",on_challenged:"RESTRICT_NEW_RISK",on_stale:"REQUIRE_REVIEW",max_age:900}; + const vaults = { + NVDAx:"0x1111111111111111111111111111111111111111", + SPYx:"0x2222222222222222222222222222222222222222", + AAPLx:"0x3333333333333333333333333333333333333333", + }; + for (const [asset,demo_vault] of Object.entries(vaults)) { + const controlPlane = { + asset,policy,policy_action:"ALLOW",evidence_state:"SUPPORTED",exists:true,fresh:true, + network:"X Layer Testnet",chain_id:1952,attestation:null,publication_compatible:true, + configured:true,deployed:true,registry:`registry-${asset}`,risk_guard:`guard-${asset}`, + demo_vault,asset_id:`id-${asset}`,reference_id:`reference-${asset}`,model_version:"0.3.0",registry_fresh:true, + }; + const runtime = {asset,auto_publish_enabled:true,last_publish_status:"published",last_publish_error:null}; + const enforcement = {asset,exists:true,fresh:true,expected_revert:false,reverted:false,returned_action_code:0,passed:true}; + const html = render(RegistryPanel,{controlPlane,runtime,enforcement,bindingConfigured:true}); + for (const label of ["X Layer Testnet","ValidationRegistry","RiskGuard","DemoVault","Automatic Publishing","Publication Compatibility","Delivery Status","Enabled","Compatible","Published"]) assert.ok(html.includes(label),`${asset} panel missing ${label}`); + const ownVault = `${demo_vault.slice(0,8)}…${demo_vault.slice(-6)}`; + assert.ok(html.includes(ownVault),`${asset} panel should show its API-provided DemoVault`); + for (const [otherAsset,otherVault] of Object.entries(vaults)) { + if (otherAsset === asset) continue; + assert.ok(!html.includes(`${otherVault.slice(0,8)}…${otherVault.slice(-6)}`),`${asset} panel must not show ${otherAsset}'s DemoVault`); + } + assert.doesNotMatch(html,/Read Only/); + } +}); + +test("Observation Details humanizes current timestamps and separates operational health from history", () => { + const result = { + ...consoleV2Fixture[0], + timestamp:"2026-10-06T17:20:00Z", + token_observed_at:"2026-10-06T17:20:00Z", + xperp_index_ts:"2026-10-06T17:20:00Z", + source_provenance:{token_source:"okx_onchainos",underlying_source:"alpaca",scenario:"weekend_divergence"}, + }; + const runtime = {scheduler_enabled:true,last_tick_status:"success",last_tick_attempt_at:"2026-10-06T17:20:05Z",last_result_timestamp:"2026-10-06T17:20:00Z",last_error:null}; + const controlPlane = {fresh:true}; + const operational = render(ObservationAudit,{result,context:"Operational",runtime,controlPlane}); + assert.match(operational,/Observation Details · Operational · 2026-10-06 17:20 UTC/); + for (const label of ["Observation Time","xStock Source","xStock Observed","X-Perp Source","X-Perp Observed","X-Perp Age","Underlying Anchor","Underlying Source","Anchor Age","Observation Age","Model","Current RiskGuard Status","Feed Status","Latest Observation","Token Source","Scenario"]) assert.match(operational,new RegExp(label)); + assert.match(operational,/Valtide Model · v0\.2\.0/); + assert.match(operational,/2026-10-06 17:20 UTC/); + assert.match(operational,/weekend_divergence/); + assert.doesNotMatch(operational,/2026-10-06T17:20:00Z|P1a-C|Calibration|Evidence Rule|Last Update Attempt|Feed Error/); + assert.match(operational,/Underlying Anchor[\s\S]*\$180\.00/); + assert.match(operational,/Underlying Source[\s\S]*alpaca/); + assert.match(operational,/Anchor Age[\s\S]*18h/); + + const withoutUnderlyingSource = render(ObservationAudit,{result:{...result,source_provenance:{scenario:"weekend_divergence"}},context:"Historical"}); + assert.match(withoutUnderlyingSource,/Underlying Source[\s\S]*—/); + const missingCurrentXperp = render(ObservationAudit,{result:{...result,xperp_index_source:null,xperp_index_ts:null,reference_under_test_source:"legacy_alias",reference_under_test_ts:"2026-10-05T00:00:00Z"},context:"Historical"}); + assert.match(missingCurrentXperp,/X-Perp Source[\s\S]*—/); + assert.doesNotMatch(missingCurrentXperp,/legacy_alias|2026-10-05 00:00 UTC/); + + const failedRuntime = {...runtime,last_tick_status:"failure",last_error:"feed timeout"}; + const failed = render(ObservationAudit,{result,context:"Operational",runtime:failedRuntime}); + assert.match(failed,/Last Update Attempt/); + assert.match(failed,/Feed Error/); + assert.match(failed,/feed timeout/); + + const historical = render(ObservationAudit,{result,context:"Historical",runtime,controlPlane}); + const demo = render(ObservationAudit,{result,context:"Demo",runtime,controlPlane}); + assert.match(historical,/Observation Details · Historical · 2026-10-06 17:20 UTC/); + assert.match(demo,/Observation Details · Demo · 17:20 UTC/); + for (const view of [historical,demo]) assert.doesNotMatch(view,/Feed Status|Latest Observation|Current RiskGuard Status|Last Update Attempt|Feed Error/); + + const oldV1 = render(ObservationAudit,{result:{...result,evidence_semantics:"p1a_xstock_challenger_xperp_second_market_v1"},context:"Historical"}); + assert.match(oldV1,/Classification Version/); + assert.match(oldV1,/Earlier Rule/); + assert.doesNotMatch(oldV1,/p1a_xstock_challenger_xperp_second_market_v1|Evidence Rule|Calibration/); +}); + +test("Human model, session and reason labels preserve underlying identifiers", () => { + assert.equal(modelDisplayName("0.3.0"),"Valtide Model · v0.3.0"); + assert.equal(modelDisplayName(null),"Valtide Model"); + assert.equal(sessionLabel("regular"),"Regular Session"); + assert.equal(sessionLabel("premarket"),"Extended Hours"); + assert.equal(sessionLabel("afterhours"),"Extended Hours"); + assert.equal(sessionLabel("overnight"),"Overnight"); + assert.equal(sessionLabel("closed"),"Market Closed"); + assert.equal(dateTimeUTC("2026-10-06T17:20:00Z"),"2026-10-06 17:20 UTC"); + + const cases = [ + ["P1A_XSTOCK_SUPPORT_BAND","Low Model Disagreement"], + ["P1A_XSTOCK_WATCH_BAND","Moderate Model Disagreement"], + ["P1A_XSTOCK_REVIEW_BAND","High Model Disagreement"], + ["XPERP_CORROBORATES_XSTOCK","X-Perp Supports xStock"], + ["XPERP_CORROBORATES_P1A","X-Perp Supports Model Challenge"], + ["P1A_XSTOCK_DETECTOR_UNAVAILABLE","Model Disagreement Signal Unavailable"], + ["P1A_XSTOCK_SUPPORT_NOT_PROMOTED","Support Signal Not Enabled"], + ["P1A_XSTOCK_CHALLENGE_NOT_PROMOTED","Challenge Signal Not Enabled"], + ["CALIBRATION_GLOBAL_FALLBACK","Global Calibration Applied"], + ]; + for (const [code,label] of cases) { + const html = render(ReasonCodes,{codes:[code],evidenceState:"INCONCLUSIVE"}); + assert.match(html,new RegExp(`title="${code}"`)); + assert.match(html,new RegExp(label)); + } +}); + test("RiskGuard recency uses its publication timestamp and omits unavailable values", () => { const now = Date.parse("2026-10-06T12:00:00Z"); assert.equal(lastUpdatedLabel(now / 1000 - 30, now), "Last updated just now"); @@ -423,43 +995,51 @@ test("Null reference, all reasons and unavailable policy remain truthful", () => const html = appWith({result}); assert.doesNotMatch(html,/NaN|challenge threshold not met|Example demo policy/); for (const code of result.reason_codes) assert.ok(html.includes(code)); - assert.match(html,/UNAVAILABLE/); - assert.match(render(ReasonCodes,{codes:result.reason_codes,evidenceState:result.evidence_state}),/Global fallback calibration/); + assert.match(html,/No Policy Connected/); + assert.match(render(ReasonCodes,{codes:result.reason_codes,evidenceState:result.evidence_state}),/Global Calibration Applied/); }); -test("unified comparison labels the validation target and source dependence", () => { - const xstock = render(ReferenceComparison, { r: fixture[0] }); - assert.match(xstock, /Unified v2 evidence/); - assert.match(xstock, /xStock is the validation target/); - assert.match(xstock, /P1a-C is a model-based challenger that has assimilated xStock/); - assert.match(xstock, /exact-time X-Perp is a separate second-market signal/); +test("Valuation Range is concise and does not repeat model-dependence methodology", () => { + const xstock = render(ReferenceComparison, { + r: {...fixture[0], reference_profile:"xstock_vs_p1ac_challenger"}, + }); + assert.match(xstock, /Observed xStock is within the valuation range/); + assert.match(xstock, /Evidence State also considers model disagreement, data quality, and X-Perp confirmation\./); + assert.doesNotMatch(xstock, /Model-based challenger evidence|P1a-C assimilates|not two fully independent observations|SUPPORT|WATCH|REVIEW/); const legacy = render(ReferenceComparison, { r: {...fixture[0], reference_profile:"legacy_xperp_vs_p1ac", validation_target:"reference_under_test", evidence_semantics:"legacy_reference_under_test_v1"}, }); - assert.match(legacy, /separate OKX X-Perp index/); - assert.doesNotMatch(legacy, /xStock observation/); + assert.match(legacy, /Reference is within the valuation range/); + assert.doesNotMatch(legacy, /Observed xStock/); }); -test("Decision summary explains unified tri-source evidence while retaining legacy compatibility", () => { - const xstock = appWith({ result: fixture[0], profile:fixture[0].reference_profile }); - assert.match(xstock, /Tri-source evidence supports the observed xStock price/); - assert.match(xstock, /not proof from two independent votes/); - assert.match(xstock, /Current finding/); +test("Decision summary uses concise current language and preserves old recorded states", () => { + const xstock = appWith({ + result: {...consoleV2Fixture[0], reference_profile:"unified_xstock_p1ac_xperp_evidence_v1"}, + profile:"unified_xstock_p1ac_xperp_evidence_v1", + }); + assert.match(xstock, /Observed xStock Is Supported/); + assert.match(xstock, /Model disagreement is low and required market data passes quality checks\./); + assert.doesNotMatch(xstock, /P1a-C|SUPPORT band|not two fully independent observations/); + assert.match(xstock, /Evidence Assessment/); assert.doesNotMatch(xstock, /Current finding · Operational/); const legacy = appWith({result: {...fixture[0], reference_profile:"legacy_xperp_vs_p1ac", validation_target:"reference_under_test", evidence_semantics:"legacy_reference_under_test_v1"}}); - assert.match(legacy, /Available independent evidence/); + assert.match(legacy, /Recorded supported evidence/); + assert.match(legacy, /has not been reclassified by the current Console/); }); test("Observation and delivery audit survives unavailable X Layer reads", () => { const runtime = {scheduler_enabled:true,last_tick_status:"failure",last_tick_attempt_at:"2026-09-25T10:01:00Z",last_error:"source missing",auto_publish_enabled:true,last_publish_status:"failed",last_publish_attempt_at:"2026-09-25T10:02:00Z",last_publish_observation_ts:"2026-09-25T09:55:00Z",last_published_observation_ts:"2026-09-25T09:50:00Z",last_published_at:1790325969,last_publish_tx_hash:"0xFULL_TRANSACTION_HASH",last_publish_error:"delivery failed"}; const audit = render(ObservationAudit,{result:fixture[0],context:"Operational",runtime}); - for (const label of ["5-minute operational observation", "Reference source lag", "Trusted-anchor age", "Source provenance", "Model and version", "Last attempt"]) assert.ok(audit.includes(label)); + for (const label of ["Observation Details · Operational · 2026-09-19 14:00 UTC", "X-Perp Age", "Underlying Anchor", "Underlying Source", "Anchor Age", "Source Provenance", "Model", "Last Update Attempt", "Feed Status", "Latest Observation"]) assert.ok(audit.includes(label)); assert.match(audit,/source missing/); + assert.match(audit,/2026-09-25 10:01 UTC/); + assert.doesNotMatch(audit,/2026-09-19T14:00:00Z|Calibration|Evidence Rule|Operational Feed Error/); const chain = render(RegistryPanel,{isError:true,mode:"historical",runtime}); assert.doesNotMatch(chain,/DEMO MAPPING/); - for (const value of [runtime.last_publish_attempt_at,runtime.last_published_observation_ts,runtime.last_publish_tx_hash,runtime.last_publish_error]) assert.ok(chain.includes(value)); + for (const value of ["2026-09-25 10:02 UTC","2026-09-25 09:50 UTC",runtime.last_publish_tx_hash,runtime.last_publish_error,"Read Only"]) assert.ok(chain.includes(value)); }); test("Historical ranges use timestamps and Demo ranges never add observations", () => { @@ -471,7 +1051,7 @@ test("Historical ranges use timestamps and Demo ranges never add observations", assert.ok(filterDemoResults(fixture, "10M").every((row) => fixture.includes(row))); }); -test("Instrument Passport validates addresses and resolves only the labelled fixture", () => { +test("Instrument Passport validates addresses and resolves only the labelled Demo address", () => { assert.equal(passportStatusFor(""), "idle"); assert.equal(passportStatusFor("0xnot-an-address"), "invalid"); assert.equal(passportStatusFor("0x2222222222222222222222222222222222222222"), "unknown"); @@ -479,32 +1059,35 @@ test("Instrument Passport validates addresses and resolves only the labelled fix const invalid = render(InstrumentPassport, { initialAddress: "0xnot-an-address" }); assert.match(invalid, /exactly 40 hexadecimal characters/); const unknown = render(InstrumentPassport, { initialAddress: "0x2222222222222222222222222222222222222222" }); - assert.match(unknown, /No verified passport fixture/); + assert.match(unknown, /No demo metadata is available/); assert.doesNotMatch(unknown, /SHAREHOLDER RIGHTS/); const resolved = render(InstrumentPassport, { initialAddress: DEMO_PASSPORT_ADDRESS }); - for (const value of ["Price exposure", "VERIFIED", "FIXTURE ASSERTION", "Shareholder rights", "NONE", "BALANCE ADJUSTMENT", "xSTOCKS WITHDRAWAL", "Rights profile", "differs from a share"]) assert.match(resolved, new RegExp(value, "i")); - assert.match(resolved, /not live address resolution/i); + for (const value of ["Price Exposure", "VERIFIED", "Demo Assertion", "Shareholder Rights", "NONE", "BALANCE ADJUSTMENT", "xSTOCKS WITHDRAWAL", "Rights Profile · Differs From A Share"]) assert.match(resolved, new RegExp(value, "i")); + assert.match(resolved, /Demo Data · No Live Address Lookup/); assert.match(resolved, /type="submit"/); + for (const value of ["Token Rights Metadata", "Demo Data", "Check Address", "Load Demo Address", "Collateral Identity", "Dividend Treatment", "Redemption"]) assert.match(resolved, new RegExp(value)); + assert.doesNotMatch(resolved, /fixture|precomputed|example metadata/i); }); test("Policy Foundry renders a deterministic diff and read-only approval boundary", () => { const html = render(PolicyFoundry); - for (const value of ["Precomputed policy proposal", "not generated live", "900s", "600s", "REQUIRE_REVIEW", "MONITOR", "RESTRICT_NEW_RISK", "Unsigned calldata", "No transaction capability in this prototype"]) assert.match(html, new RegExp(value, "i")); + for (const value of ["Policy Proposal", "deterministic demo policy for review", "900s", "600s", "REQUIRE_REVIEW", "MONITOR", "RESTRICT_NEW_RISK", "Unsigned Calldata", "Reference ABI", "Review Only · No Transaction Submission", "This demo does not sign or submit transactions."]) assert.match(html, new RegExp(value, "i")); assert.doesNotMatch(html, /Agent Council|ABI SHAPE VERIFIED|Human Approval Required/); - assert.match(html, /Not deployed/i); + assert.match(html, /Not Deployed/); + assert.doesNotMatch(html, /fixture|prototype|--example/i); assert.match(POLICY_PROPOSAL.calldata, /^0xf5b39423[0-9a-f]{320}$/); }); test("Machine publication statuses use the requested display casing", () => { - assert.equal(pipelineStatusLabel("published"), "PUBLISHED"); + assert.equal(pipelineStatusLabel("published"), "Published"); assert.equal(deliveryStatusLabel("published"), "Published"); assert.equal(deliveryStatusLabel("failed"), "Failed"); }); test("Historical observation audit is labelled as historical evidence", () => { - const audit = render(ObservationAudit, { result: fixture[0], context: "Historical" }); - assert.match(audit, /Historical observation/); - assert.doesNotMatch(audit, /5-minute operational observation/); + const audit = render(ObservationAudit, { result: fixture[0], context: "Historical", runtime:{scheduler_enabled:true,last_tick_status:"success",last_result_timestamp:"2026-10-06T17:20:00Z"}, controlPlane:{fresh:true} }); + assert.match(audit, /Observation Details · Historical · 2026-09-19 14:00 UTC/); + assert.doesNotMatch(audit, /Feed Status|Latest Operational Observation|Current RiskGuard Status|Last Update Attempt|Feed Error|2026-09-19T14:00:00Z/); }); test("Chart viewport zooms around an anchor and pans within the full domain", () => {