fix(web): expose delivery mainline truth
Some checks failed
CD Pipeline / workflow-shape (push) Successful in 0s
CD Pipeline / cancel-stale-cd (push) Has been skipped
CD Pipeline / tests (push) Successful in 30s
CD Pipeline / post-deploy-checks (push) Has been cancelled
CD Pipeline / build-and-deploy (push) Has been cancelled

This commit is contained in:
Your Name
2026-06-30 07:45:11 +08:00
parent 1de80f86cb
commit 5006132024
3 changed files with 396 additions and 19 deletions

View File

@@ -53,6 +53,16 @@ interface DeliveryLane {
Icon: typeof Rocket
}
interface DeliveryFocusRow {
id: string
title: string
action: string
percent: number
blockerCount: number
tone: DeliveryTone
Icon: typeof Rocket
}
const SOURCE_COUNT = 6
const EMPTY_DATA: DeliveryData = {
@@ -164,6 +174,108 @@ function MetricTile({
)
}
function CurrentP0Panel({
workbench,
t,
}: {
workbench: DeliveryClosureWorkbenchSnapshot | null
t: DeliveryTranslator
}) {
if (!workbench) return null
const { readback, rollups, operation_boundaries: boundaries } = workbench
const readiness = clampPercent(readback.current_p0_readiness_percent || rollups.current_p0_readiness_percent)
const blockers = readback.current_p0_active_blockers.length > 0 ? readback.current_p0_active_blockers : workbench.active_blockers
const panelTone: DeliveryTone = blockers.length > 0 ? 'danger' : readiness >= 100 ? 'ok' : 'warn'
const closedP0 = readback.closed_p0_workplan_ids.length > 0
? readback.closed_p0_workplan_ids.join(' / ')
: t('currentP0.closedEmpty')
const truthRows = [
{ key: 'eventGate', value: rollups.current_p0_blocked_by_fresh_reboot_window_only ? t('currentP0.values.yes') : t('currentP0.values.no') },
{ key: 'service', value: rollups.current_p0_service_green ? t('currentP0.values.green') : t('currentP0.values.blocked') },
{ key: 'productData', value: rollups.current_p0_product_data_green ? t('currentP0.values.green') : t('currentP0.values.blocked') },
{ key: 'backup', value: rollups.current_p0_backup_core_green ? t('currentP0.values.green') : t('currentP0.values.blocked') },
{ key: 'stock', value: `${rollups.current_p0_stockplatform_freshness_status} / ${rollups.current_p0_stockplatform_ingestion_status}` },
{ key: 'github', value: readback.github_lane_status },
]
const flagRows = [
{ key: 'runtimeWrite', value: boundaries.runtime_write_allowed || readback.runtime_write_authorized || rollups.runtime_write_authorized },
{ key: 'workflowTrigger', value: boundaries.workflow_trigger_allowed || readback.workflow_trigger_authorized || rollups.workflow_trigger_authorized },
{ key: 'secretCollection', value: boundaries.secret_value_collection_allowed || readback.secret_value_collection_allowed || rollups.secret_values_collected },
{ key: 'remoteWrite', value: boundaries.remote_write_allowed },
{ key: 'repoCreation', value: boundaries.repo_creation_allowed },
{ key: 'activeScan', value: boundaries.active_scan_allowed },
]
return (
<section className="delivery-current-p0" data-testid="delivery-current-p0">
<div className="delivery-section-heading">
<div>
<h2>{t('currentP0.title')}</h2>
<p>{t('currentP0.detail')}</p>
</div>
<StatusPill tone={panelTone} label={readback.current_p0_status} />
</div>
<GlassCard variant="default" padding="md">
<div className="delivery-current-p0-grid">
<div className="delivery-current-p0-main">
<div className="delivery-current-p0-icon">
<ShieldCheck size={22} aria-hidden="true" />
</div>
<div>
<h3>{readback.current_p0_workplan_id}</h3>
<p>{readback.current_p0_safe_next_step || workbench.safe_next_step}</p>
</div>
</div>
<div className="delivery-current-p0-stats">
<div>
<span>{t('currentP0.source')}</span>
<strong>{readback.current_p0_source_id}</strong>
</div>
<div>
<span>{t('currentP0.readiness')}</span>
<strong>{readiness}%</strong>
</div>
<div>
<span>{t('currentP0.closed')}</span>
<strong>{closedP0}</strong>
</div>
</div>
<div className="delivery-current-p0-blockers">
<strong>{t('currentP0.blockers')}</strong>
<div>
{(blockers.length > 0 ? blockers : [t('currentP0.noBlockers')]).map(blocker => (
<StatusPill key={blocker} tone={blockers.length > 0 ? 'danger' : 'ok'} label={blocker} />
))}
</div>
</div>
<div className="delivery-current-p0-truth">
{truthRows.map(row => (
<div key={row.key}>
<span>{t(`currentP0.truth.${row.key}`)}</span>
<strong>{row.value}</strong>
</div>
))}
</div>
<div className="delivery-current-p0-flags">
{flagRows.map(row => (
<StatusPill
key={row.key}
tone={row.value ? 'danger' : 'ok'}
label={`${t(`currentP0.flags.${row.key}`)}: ${row.value ? t('currentP0.values.open') : t('currentP0.values.closed')}`}
/>
))}
</div>
</div>
</GlassCard>
</section>
)
}
function DrillPreflightPanel({
preflight,
locale,
@@ -535,6 +647,55 @@ export default function DeliveryPage({ params }: { params: { locale: string } })
const highRiskBlockers = workbench?.summary.high_risk_blocker_count ?? lanes.reduce((sum, lane) => sum + lane.blockerCount, 0)
const averageCompletion = workbench?.summary.average_completion_percent ?? clampPercent(lanes.reduce((sum, lane) => sum + lane.percent, 0) / Math.max(lanes.length, 1))
const pageTone: DeliveryTone = highRiskBlockers > 0 ? 'danger' : loadedCount === sourceTotal ? 'ok' : 'warn'
const activeExecutionCount = workbench
? [
workbench.operation_boundaries.runtime_write_allowed,
workbench.operation_boundaries.remote_write_allowed,
workbench.operation_boundaries.workflow_trigger_allowed,
workbench.operation_boundaries.secret_value_collection_allowed,
workbench.operation_boundaries.active_scan_allowed,
].filter(Boolean).length
: 0
const focusRows = useMemo<DeliveryFocusRow[]>(() => {
if (workbench?.next_focus?.length) {
return workbench.next_focus.slice(0, 5).map(focus => {
const lane = lanes.find(item => item.id === focus.lane_id)
const percent = clampPercent(focus.completion_percent)
return {
id: focus.lane_id,
title: lane?.title ?? focus.lane_id,
action: focus.next_action,
percent,
blockerCount: focus.blocker_count,
tone: focus.blocker_count > 0 ? 'danger' : resolveTone(0, percent),
Icon: lane?.Icon ?? Rocket,
}
})
}
return lanes
.filter(lane => lane.blockerCount > 0 || lane.percent < 80)
.slice(0, 5)
.map(lane => ({
id: lane.id,
title: lane.title,
action: lane.nextAction || lane.metric,
percent: lane.percent,
blockerCount: lane.blockerCount,
tone: lane.tone,
Icon: lane.Icon,
}))
}, [lanes, workbench])
const boundaryRows = workbench
? [
{ key: 'readOnlyApi', value: workbench.operation_boundaries.read_only_api_allowed, tone: 'ok' as DeliveryTone },
{ key: 'runtimeWrite', value: workbench.operation_boundaries.runtime_write_allowed, tone: workbench.operation_boundaries.runtime_write_allowed ? 'danger' as DeliveryTone : 'ok' as DeliveryTone },
{ key: 'remoteWrite', value: workbench.operation_boundaries.remote_write_allowed, tone: workbench.operation_boundaries.remote_write_allowed ? 'danger' as DeliveryTone : 'ok' as DeliveryTone },
{ key: 'workflowTrigger', value: workbench.operation_boundaries.workflow_trigger_allowed, tone: workbench.operation_boundaries.workflow_trigger_allowed ? 'warn' as DeliveryTone : 'ok' as DeliveryTone },
{ key: 'secretCollection', value: workbench.operation_boundaries.secret_value_collection_allowed, tone: workbench.operation_boundaries.secret_value_collection_allowed ? 'danger' as DeliveryTone : 'ok' as DeliveryTone },
{ key: 'activeScan', value: workbench.operation_boundaries.active_scan_allowed, tone: workbench.operation_boundaries.active_scan_allowed ? 'danger' as DeliveryTone : 'ok' as DeliveryTone },
]
: []
return (
<AppLayout locale={params.locale}>
@@ -582,9 +743,11 @@ export default function DeliveryPage({ params }: { params: { locale: string } })
<MetricTile label={t('metrics.loaded')} value={`${loadedCount}/${sourceTotal}`} detail={t('metrics.loadedDetail')} tone={loadedCount === sourceTotal ? 'ok' : 'warn'} />
<MetricTile label={t('metrics.completion')} value={`${averageCompletion}%`} detail={t('metrics.completionDetail')} tone={averageCompletion >= 80 ? 'ok' : 'warn'} />
<MetricTile label={t('metrics.blockers')} value={highRiskBlockers} detail={t('metrics.blockersDetail')} tone={highRiskBlockers > 0 ? 'danger' : 'ok'} />
<MetricTile label={t('metrics.execution')} value="0" detail={t('metrics.executionDetail')} tone="ok" />
<MetricTile label={t('metrics.execution')} value={activeExecutionCount} detail={t('metrics.executionDetail')} tone={activeExecutionCount > 0 ? 'danger' : 'ok'} />
</section>
<CurrentP0Panel workbench={workbench} t={t} />
<DrillPreflightPanel preflight={drillPreflight} locale={params.locale} t={t} />
{errors.length > 0 && (
@@ -618,19 +781,20 @@ export default function DeliveryPage({ params }: { params: { locale: string } })
</div>
</div>
<div className="delivery-next-list">
{lanes
.filter(lane => lane.blockerCount > 0 || lane.percent < 80)
.slice(0, 5)
.map(lane => (
<div key={lane.id} className="delivery-next-row">
<lane.Icon size={17} aria-hidden="true" />
{focusRows.length > 0 ? (
focusRows.map(row => (
<div key={row.id} className="delivery-next-row">
<row.Icon size={17} aria-hidden="true" />
<div>
<strong>{lane.title}</strong>
<span>{lane.nextAction || lane.metric}</span>
<strong>{row.title}</strong>
<span>{row.action}</span>
</div>
<StatusPill tone={lane.tone} label={`${lane.percent}%`} />
<StatusPill tone={row.tone} label={t('nextFocus.status', { percent: row.percent, blockers: row.blockerCount })} />
</div>
))}
))
) : (
<div className="delivery-next-empty">{t('nextFocus.empty')}</div>
)}
</div>
</div>
@@ -642,13 +806,21 @@ export default function DeliveryPage({ params }: { params: { locale: string } })
</div>
</div>
<div className="delivery-boundary-list">
{['secret', 'production', 'repo', 'data', 'security'].map(key => (
<div key={key} className="delivery-boundary-row">
<Lock size={16} aria-hidden="true" />
<span>{t(`boundaries.${key}`)}</span>
<CheckCircle2 size={16} aria-hidden="true" />
</div>
))}
{boundaryRows.length > 0
? boundaryRows.map(row => (
<div key={row.key} className="delivery-boundary-row">
<Lock size={16} aria-hidden="true" />
<span>{t(`boundaryFacts.${row.key}`)}</span>
<StatusPill tone={row.tone} label={row.value ? t('boundaryFacts.values.open') : t('boundaryFacts.values.closed')} />
</div>
))
: ['secret', 'production', 'repo', 'data', 'security'].map(key => (
<div key={key} className="delivery-boundary-row">
<Lock size={16} aria-hidden="true" />
<span>{t(`boundaries.${key}`)}</span>
<CheckCircle2 size={16} aria-hidden="true" />
</div>
))}
</div>
</div>
</section>
@@ -668,6 +840,97 @@ export default function DeliveryPage({ params }: { params: { locale: string } })
grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
gap: 12px;
}
:global(.delivery-current-p0-grid) {
display: grid;
grid-template-columns: minmax(0, 1.1fr) minmax(300px, 0.9fr);
gap: 14px;
align-items: start;
}
:global(.delivery-current-p0-main) {
display: grid;
grid-template-columns: 44px minmax(0, 1fr);
gap: 12px;
min-width: 0;
}
:global(.delivery-current-p0-icon) {
width: 44px;
height: 44px;
border-radius: 8px;
display: flex;
align-items: center;
justify-content: center;
color: #2f7d54;
background: rgba(47, 125, 84, 0.1);
}
:global(.delivery-current-p0-main h3) {
margin: 0;
font-size: 19px;
font-weight: 900;
color: #141413;
overflow-wrap: anywhere;
}
:global(.delivery-current-p0-main p) {
margin: 6px 0 0;
color: #595852;
font-size: 13px;
line-height: 1.55;
overflow-wrap: anywhere;
}
:global(.delivery-current-p0-stats),
:global(.delivery-current-p0-truth) {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 8px;
}
:global(.delivery-current-p0-truth) {
grid-column: 1 / -1;
grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
}
:global(.delivery-current-p0-stats div),
:global(.delivery-current-p0-truth div) {
min-height: 68px;
border: 0.5px solid #e0ddd4;
border-radius: 8px;
padding: 9px;
background: rgba(255, 255, 255, 0.56);
min-width: 0;
}
:global(.delivery-current-p0-stats span),
:global(.delivery-current-p0-truth span) {
display: block;
color: #706f68;
font-size: 11px;
font-weight: 800;
margin-bottom: 6px;
}
:global(.delivery-current-p0-stats strong),
:global(.delivery-current-p0-truth strong) {
color: #141413;
font-size: 15px;
line-height: 1.3;
overflow-wrap: anywhere;
}
:global(.delivery-current-p0-blockers) {
grid-column: 1 / -1;
display: grid;
gap: 8px;
min-width: 0;
}
:global(.delivery-current-p0-blockers > strong) {
color: #141413;
font-size: 13px;
font-weight: 900;
}
:global(.delivery-current-p0-blockers > div),
:global(.delivery-current-p0-flags) {
display: flex;
flex-wrap: wrap;
gap: 8px;
min-width: 0;
}
:global(.delivery-current-p0-flags) {
grid-column: 1 / -1;
}
:global(.delivery-drill-panel) {
min-width: 0;
}
@@ -824,6 +1087,16 @@ export default function DeliveryPage({ params }: { params: { locale: string } })
flex-direction: column;
gap: 8px;
}
.delivery-next-empty {
min-height: 54px;
border: 0.5px solid #e0ddd4;
background: rgba(255, 255, 255, 0.62);
border-radius: 8px;
padding: 12px;
color: #706f68;
font-size: 13px;
line-height: 1.5;
}
.delivery-next-row,
.delivery-boundary-row {
display: grid;
@@ -855,10 +1128,11 @@ export default function DeliveryPage({ params }: { params: { locale: string } })
overflow-wrap: anywhere;
}
.delivery-boundary-row {
grid-template-columns: 20px minmax(0, 1fr) 20px;
grid-template-columns: 20px minmax(0, 1fr) auto;
}
@media (max-width: 900px) {
.delivery-hero,
:global(.delivery-current-p0-grid),
:global(.delivery-drill-grid),
.delivery-grid-two {
grid-template-columns: 1fr;
@@ -868,6 +1142,9 @@ export default function DeliveryPage({ params }: { params: { locale: string } })
}
}
@media (max-width: 560px) {
:global(.delivery-current-p0-stats) {
grid-template-columns: 1fr;
}
:global(.delivery-drill-metrics) {
grid-template-columns: 1fr;
}