Ship Tier A Week 1–2: posture glossary, delivery mode, freshness UI, canonical tokens.
Some checks failed
Deploy Explorer Live / deploy (push) Failing after 13s
Validate Explorer / frontend (push) Failing after 18s
Validate Explorer / smoke-e2e (push) Has been skipped

Expose mission-control mode on home/bridge/analytics, quiet-chain freshness copy, and a canonical-first indexed token list with WETH9 metadata override and non-canonical warnings.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-05-23 03:48:22 -07:00
parent ab9c1f9f98
commit 763ca75c21
25 changed files with 873 additions and 68 deletions

View File

@@ -75,6 +75,9 @@ export default function ActivityContextPanel({
</Explain>
</div>
<EntityBadge label={resolveLabel(context.state)} tone={tone} />
{context.head_is_idle && context.state === 'low' ? (
<EntityBadge label="quiet chain" tone="info" />
) : null}
</div>
{compact ? (
@@ -130,6 +133,11 @@ export default function ActivityContextPanel({
Open last non-empty block
</Link>
) : null}
{context.block_gap_to_latest_transaction != null ? (
<span>
Block gap to latest visible transaction: {context.block_gap_to_latest_transaction.toLocaleString()}
</span>
) : null}
{context.latest_transaction_timestamp ? (
<span>Latest visible transaction time: {formatTimestamp(context.latest_transaction_timestamp)}</span>
) : null}

View File

@@ -3,10 +3,12 @@ import Navbar from './Navbar'
import Footer from './Footer'
import ExplorerAgentTool from './ExplorerAgentTool'
import { UiModeProvider } from './UiModeContext'
import { PostureGlossaryProvider } from './PostureGlossaryProvider'
export default function ExplorerChrome({ children }: { children: ReactNode }) {
return (
<UiModeProvider>
<PostureGlossaryProvider>
<div className="flex min-h-screen flex-col bg-gray-50 text-gray-900 dark:bg-gray-900 dark:text-gray-100">
<a
href="#main-content"
@@ -21,6 +23,7 @@ export default function ExplorerChrome({ children }: { children: ReactNode }) {
<ExplorerAgentTool />
<Footer />
</div>
</PostureGlossaryProvider>
</UiModeProvider>
)
}

View File

@@ -8,11 +8,15 @@ import {
import { formatRelativeAge } from '@/utils/format'
import { useUiMode } from './UiModeContext'
function buildSummary(context: ChainActivityContext) {
function buildSummary(context: ChainActivityContext, activityState?: string | null) {
if (context.transaction_visibility_unavailable) {
return 'Chain-head visibility is current, while transaction freshness is currently unavailable.'
}
if (activityState === 'quiet_chain' || (context.head_is_idle && context.state === 'low')) {
return 'The chain head is current, but recent head blocks are quiet — this is normal low-activity visibility, not a broken index.'
}
if (context.state === 'active') {
return 'Chain head and latest indexed transactions are closely aligned.'
}
@@ -28,11 +32,21 @@ function buildSummary(context: ChainActivityContext) {
return 'Freshness context is based on the latest visible public explorer evidence.'
}
function buildDetail(context: ChainActivityContext, diagnosticExplanation?: string | null) {
function buildDetail(context: ChainActivityContext, diagnosticExplanation?: string | null, activityState?: string | null) {
if (diagnosticExplanation) {
return diagnosticExplanation
}
if (activityState === 'quiet_chain') {
const latestNonEmptyBlock =
context.last_non_empty_block_number != null ? `#${context.last_non_empty_block_number.toLocaleString()}` : 'unknown'
const blockGap =
context.block_gap_to_latest_transaction != null
? `${context.block_gap_to_latest_transaction.toLocaleString()} blocks`
: 'unknown'
return `Quiet-chain signal: head blocks may be empty while the chain remains current. Block gap to latest visible transaction: ${blockGap}. Last non-empty block: ${latestNonEmptyBlock}.`
}
if (context.transaction_visibility_unavailable) {
return 'Use chain-head visibility and the last non-empty block as the current trust anchors.'
}
@@ -40,9 +54,13 @@ function buildDetail(context: ChainActivityContext, diagnosticExplanation?: stri
const latestTxAge = formatRelativeAge(context.latest_transaction_timestamp)
const latestNonEmptyBlock =
context.last_non_empty_block_number != null ? `#${context.last_non_empty_block_number.toLocaleString()}` : 'unknown'
const blockGap =
context.block_gap_to_latest_transaction != null
? `${context.block_gap_to_latest_transaction.toLocaleString()} blocks`
: null
if (context.head_is_idle) {
return `Latest visible transaction: ${latestTxAge}. Last non-empty block: ${latestNonEmptyBlock}.`
return `Latest visible transaction: ${latestTxAge}. Block gap: ${blockGap || 'unknown'}. Last non-empty block: ${latestNonEmptyBlock}.`
}
if (context.state === 'active') {
@@ -74,13 +92,14 @@ export default function FreshnessTrustNote({
const sourceLabel = resolveFreshnessSourceLabel(stats, bridgeStatus)
const confidenceBadges = summarizeFreshnessConfidence(stats, bridgeStatus)
const diagnosticExplanation = stats?.diagnostics?.explanation || bridgeStatus?.data?.diagnostics?.explanation || null
const activityState = stats?.diagnostics?.activity_state || bridgeStatus?.data?.diagnostics?.activity_state || null
const normalizedClassName = className ? ` ${className}` : ''
if (mode === 'expert') {
return (
<div className={`rounded-2xl border border-gray-200 bg-white/80 px-4 py-3 text-sm dark:border-gray-800 dark:bg-gray-950/40${normalizedClassName}`}>
<div className="flex flex-col gap-2 lg:flex-row lg:items-center lg:justify-between">
<div className="font-medium text-gray-900 dark:text-white">{buildSummary(context)}</div>
<div className="font-medium text-gray-900 dark:text-white">{buildSummary(context, activityState)}</div>
<div className="text-xs text-gray-600 dark:text-gray-400">{sourceLabel}</div>
</div>
<div className="mt-2 flex flex-wrap gap-2 text-xs text-gray-500 dark:text-gray-400">
@@ -99,9 +118,9 @@ export default function FreshnessTrustNote({
return (
<div className={`rounded-2xl border border-gray-200 bg-white/80 px-4 py-3 text-sm dark:border-gray-800 dark:bg-gray-950/40${normalizedClassName}`}>
<div className="font-medium text-gray-900 dark:text-white">{buildSummary(context)}</div>
<div className="font-medium text-gray-900 dark:text-white">{buildSummary(context, activityState)}</div>
<div className="mt-1 text-gray-600 dark:text-gray-400">
{normalizeSentence(buildDetail(context, diagnosticExplanation))}.{' '}
{normalizeSentence(buildDetail(context, diagnosticExplanation, activityState))}.{' '}
{scopeLabel ? `${normalizeSentence(scopeLabel)}. ` : ''}
{normalizeSentence(sourceLabel)}.
</div>

View File

@@ -0,0 +1,76 @@
'use client'
import { Card } from '@/libs/frontend-ui-primitives'
import EntityBadge from '@/components/common/EntityBadge'
import type { MissionControlMode } from '@/services/api/missionControl'
import { formatRelativeAge } from '@/utils/format'
const REASON_LABELS: Record<string, string> = {
live_homepage_stream_not_attached: 'Live homepage stream is not attached; relay posture uses snapshot polling.',
relay_snapshot_only_source: 'Relay monitoring uses snapshot sources while other explorer feeds remain live.',
partial_observability_inputs: 'Some freshness inputs are partial, so posture is reported conservatively.',
}
const SCOPE_LABELS: Record<string, string> = {
relay_monitoring_homepage_card_only: 'Affects relay monitoring and the homepage mission card only.',
bridge_monitoring_and_homepage: 'Affects bridge monitoring and homepage summary surfaces.',
homepage_summary_only: 'Affects homepage summary messaging only.',
}
function humanizeKey(value?: string | null): string {
if (!value) return 'Not specified'
return SCOPE_LABELS[value] || REASON_LABELS[value] || value.replaceAll('_', ' ')
}
function modeTone(kind?: string | null): 'success' | 'warning' | 'info' | 'neutral' {
switch (String(kind || '').toLowerCase()) {
case 'live':
return 'success'
case 'mixed':
return 'warning'
case 'snapshot':
return 'info'
default:
return 'neutral'
}
}
export default function MissionDeliveryModePanel({
mode,
title = 'Delivery mode',
className = '',
}: {
mode?: MissionControlMode | null
title?: string
className?: string
}) {
if (!mode?.kind) return null
const normalizedClassName = className ? ` ${className}` : ''
return (
<Card
className={`border border-indigo-200 bg-indigo-50/60 dark:border-indigo-900/40 dark:bg-indigo-950/20${normalizedClassName}`}
title={title}
>
<div className="flex flex-col gap-3">
<div className="flex flex-wrap items-center gap-2">
<EntityBadge label={`mode ${mode.kind}`} tone={modeTone(mode.kind)} />
{mode.updated_at ? (
<span className="text-xs text-gray-600 dark:text-gray-400">Updated {formatRelativeAge(mode.updated_at)}</span>
) : null}
</div>
{mode.reason ? (
<p className="text-sm leading-6 text-gray-700 dark:text-gray-300">
<span className="font-medium text-gray-900 dark:text-white">Reason:</span> {humanizeKey(String(mode.reason))}
</p>
) : null}
{mode.scope ? (
<p className="text-sm leading-6 text-gray-700 dark:text-gray-300">
<span className="font-medium text-gray-900 dark:text-white">Scope:</span> {humanizeKey(String(mode.scope))}
</p>
) : null}
</div>
</Card>
)
}

View File

@@ -0,0 +1,33 @@
'use client'
import EntityBadge from '@/components/common/EntityBadge'
import { usePostureGlossary } from '@/components/common/PostureGlossaryProvider'
import { resolvePostureTermId } from '@/data/postureGlossary'
export default function PostureBadge({
label,
tone,
className,
}: {
label: string
tone?: 'neutral' | 'success' | 'warning' | 'info'
className?: string
}) {
const { openTerm } = usePostureGlossary()
const termId = resolvePostureTermId(label)
if (!termId) {
return <EntityBadge label={label} tone={tone} className={className} />
}
return (
<button
type="button"
onClick={() => openTerm(termId)}
title="Open posture glossary"
className="rounded-full focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary-500"
>
<EntityBadge label={label} tone={tone} className={className} />
</button>
)
}

View File

@@ -0,0 +1,82 @@
'use client'
import { createContext, useCallback, useContext, useMemo, useState, type ReactNode } from 'react'
import Link from 'next/link'
import { getPostureGlossaryTerm, type PostureGlossaryTermId } from '@/data/postureGlossary'
interface PostureGlossaryContextValue {
openTerm: (termId: PostureGlossaryTermId) => void
close: () => void
}
const PostureGlossaryContext = createContext<PostureGlossaryContextValue | null>(null)
export function PostureGlossaryProvider({ children }: { children: ReactNode }) {
const [activeTermId, setActiveTermId] = useState<PostureGlossaryTermId | null>(null)
const activeTerm = useMemo(
() => (activeTermId ? getPostureGlossaryTerm(activeTermId) ?? null : null),
[activeTermId],
)
const openTerm = useCallback((termId: PostureGlossaryTermId) => {
setActiveTermId(termId)
}, [])
const close = useCallback(() => {
setActiveTermId(null)
}, [])
return (
<PostureGlossaryContext.Provider value={{ openTerm, close }}>
{children}
{activeTerm ? (
<div className="fixed inset-0 z-[80] flex items-end justify-center bg-black/45 p-4 sm:items-center" onClick={close}>
<div
role="dialog"
aria-modal="true"
aria-labelledby="posture-glossary-title"
className="max-h-[85vh] w-full max-w-xl overflow-y-auto rounded-2xl border border-gray-200 bg-white p-6 shadow-2xl dark:border-gray-700 dark:bg-gray-950"
onClick={(event) => event.stopPropagation()}
>
<div className="flex items-start justify-between gap-4">
<div>
<p className="text-xs font-semibold uppercase tracking-wide text-gray-500 dark:text-gray-400">Posture glossary</p>
<h2 id="posture-glossary-title" className="mt-1 text-xl font-semibold text-gray-900 dark:text-white">
{activeTerm.title}
</h2>
</div>
<button
type="button"
onClick={close}
className="rounded-lg border border-gray-300 px-3 py-1.5 text-sm font-medium text-gray-700 hover:bg-gray-50 dark:border-gray-700 dark:text-gray-200 dark:hover:bg-gray-900"
>
Close
</button>
</div>
<p className="mt-4 text-sm leading-6 text-gray-700 dark:text-gray-300">{activeTerm.summary}</p>
<div className="mt-4 rounded-xl border border-sky-200 bg-sky-50/70 p-4 text-sm leading-6 text-sky-950 dark:border-sky-900/50 dark:bg-sky-950/20 dark:text-sky-100">
<p className="text-xs font-semibold uppercase tracking-wide text-sky-700 dark:text-sky-300">Methodology</p>
<p className="mt-2">{activeTerm.methodology}</p>
</div>
<div className="mt-5 flex flex-wrap gap-3 text-sm">
<Link href="/docs/posture-glossary" className="font-medium text-primary-600 hover:underline" onClick={close}>
Full glossary
</Link>
<Link href="/docs/gru" className="font-medium text-primary-600 hover:underline" onClick={close}>
GRU guide
</Link>
</div>
</div>
</div>
) : null}
</PostureGlossaryContext.Provider>
)
}
export function usePostureGlossary() {
const context = useContext(PostureGlossaryContext)
if (!context) {
throw new Error('usePostureGlossary must be used within PostureGlossaryProvider')
}
return context
}