feat(governance): refresh AI agent market radar
Some checks failed
Code Review / ai-code-review (push) Successful in 15s
CD Pipeline / tests (push) Successful in 1m42s
CD Pipeline / build-and-deploy (push) Successful in 3m58s
CD Pipeline / post-deploy-checks (push) Has been cancelled
Ansible / Reboot Recovery Contract / validate (push) Has been cancelled

This commit is contained in:
Your Name
2026-06-26 11:54:35 +08:00
parent 81f763bebd
commit 889b7b4229
29 changed files with 5096 additions and 131 deletions

View File

@@ -59,6 +59,15 @@ type ProfessionalJudgmentPreset = {
question: string
escalation: string
}
type TechnologyReviewLabels = {
nextGate: string
reviewNeeds: string
cost: string
dependency: string
security: string
awoooiGate: string
agentAssignment: string
}
function formatDateTime(value: string): string {
const date = new Date(value)
@@ -88,6 +97,14 @@ function formatTechnologyArea(value: string): string {
return TECHNOLOGY_AREA_LABELS[value] ?? value.replace(/_/g, ' ')
}
function formatSourceHost(value: string): string {
try {
return new URL(value).hostname.replace(/^www\./, '')
} catch {
return value
}
}
function normalizeAgentName(value: string): string {
const normalized = value.toLowerCase()
if (normalized.includes('openclaw')) return 'openclaw'
@@ -396,6 +413,84 @@ function ProfessionalAgentRoleCard({ role }: { role: AiTechnologyRadarReadback['
)
}
function HighPriorityReviewCard({
item,
labels,
}: {
item: AiTechnologyRadarReadback['high_priority_review_queue'][number]
labels: TechnologyReviewLabels
}) {
return (
<div style={{
minWidth: 0,
padding: 12,
border: '0.5px solid #e0ddd4',
borderRadius: 7,
background: '#fff',
display: 'flex',
flexDirection: 'column',
gap: 9,
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 10, alignItems: 'flex-start', minWidth: 0 }}>
<div style={{ display: 'flex', flexDirection: 'column', gap: 6, minWidth: 0 }}>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 700, color: '#141413' }}>
{item.display_name}
</span>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, minWidth: 0 }}>
<CandidatePill value={formatTechnologyArea(item.technology_area)} />
<CandidatePill value={item.evaluation_priority} muted />
</div>
</div>
<CandidatePill value={item.gate_status} muted />
</div>
<DetailRow label={labels.nextGate}>
{item.next_gate}
</DetailRow>
<DetailRow label={labels.reviewNeeds}>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 6, minWidth: 0 }}>
<CandidatePill value={`${labels.cost}=${item.requires_cost_approval}`} muted />
<CandidatePill value={`${labels.dependency}=${item.requires_dependency_approval}`} muted />
<CandidatePill value={`${labels.security}=${item.requires_security_review}`} muted />
</div>
</DetailRow>
</div>
)
}
function PrimarySourceAlignmentCard({
item,
labels,
}: {
item: AiTechnologyRadarReadback['primary_source_alignment'][number]
labels: TechnologyReviewLabels
}) {
return (
<div style={{
minWidth: 0,
padding: 12,
border: '0.5px solid #e0ddd4',
borderRadius: 7,
background: '#fff',
display: 'flex',
flexDirection: 'column',
gap: 9,
}}>
<div style={{ display: 'flex', justifyContent: 'space-between', gap: 10, alignItems: 'flex-start', minWidth: 0 }}>
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 700, color: '#141413', lineHeight: 1.35 }}>
{item.practice}
</span>
<CandidatePill value={formatSourceHost(item.source)} muted />
</div>
<DetailRow label={labels.awoooiGate}>
<CandidatePill value={item.awoooi_gate} />
</DetailRow>
<DetailRow label={labels.agentAssignment}>
{item.agent_assignment}
</DetailRow>
</div>
)
}
function ReportCadenceCard({ cadence }: { cadence: AiTechnologyReportCadenceReadback['report_cadences'][number] }) {
return (
<div style={{
@@ -1119,6 +1214,15 @@ export function AgentMarketTab() {
escalation: t('technologyReports.professionalJudgment.presets.reviewer.escalation'),
},
}
const technologyReviewLabels: TechnologyReviewLabels = {
nextGate: t('technologyRadar.reviewLabels.nextGate'),
reviewNeeds: t('technologyRadar.reviewLabels.reviewNeeds'),
cost: t('technologyRadar.reviewLabels.cost'),
dependency: t('technologyRadar.reviewLabels.dependency'),
security: t('technologyRadar.reviewLabels.security'),
awoooiGate: t('technologyRadar.reviewLabels.awoooiGate'),
agentAssignment: t('technologyRadar.reviewLabels.agentAssignment'),
}
const allApprovals =
summary.priority_upgrades_approved +
summary.market_scorecard_updates_approved +
@@ -1308,6 +1412,52 @@ export function AgentMarketTab() {
})}
</DetailRow>
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
<AlertTriangle size={14} style={{ color: '#F59E0B', flexShrink: 0 }} />
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 700, color: '#141413' }}>
{t('technologyRadar.highPriorityTitle')}
</span>
</div>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
gap: 10,
}} className="agent-market-radar-review-grid">
{technologyRadar.high_priority_review_queue.length > 0 ? (
technologyRadar.high_priority_review_queue.map(item => (
<HighPriorityReviewCard
key={item.technology_id}
item={item}
labels={technologyReviewLabels}
/>
))
) : (
<DetailRow label={t('technologyRadar.highPriorityTitle')}>
<CandidatePill value={t('technologyRadar.emptyReviewQueue')} muted />
</DetailRow>
)}
</div>
<div style={{ display: 'flex', alignItems: 'center', gap: 8, minWidth: 0 }}>
<ListChecks size={14} style={{ color: '#d97757', flexShrink: 0 }} />
<span style={{ fontFamily: 'Syne, sans-serif', fontSize: 13, fontWeight: 700, color: '#141413' }}>
{t('technologyRadar.primarySourceTitle')}
</span>
</div>
<div style={{
display: 'grid',
gridTemplateColumns: 'repeat(2, minmax(0, 1fr))',
gap: 10,
}} className="agent-market-radar-source-grid">
{technologyRadar.primary_source_alignment.map(item => (
<PrimarySourceAlignmentCard
key={`${item.awoooi_gate}-${item.source}`}
item={item}
labels={technologyReviewLabels}
/>
))}
</div>
</div>
</GlassCard>
@@ -2059,6 +2209,8 @@ export function AgentMarketTab() {
.agent-market-kpi-grid,
.agent-market-radar-metrics-grid,
.agent-market-radar-contract-grid,
.agent-market-radar-review-grid,
.agent-market-radar-source-grid,
.agent-market-radar-domain-grid,
.agent-market-radar-rolling-grid,
.agent-market-radar-role-grid,

View File

@@ -1134,7 +1134,17 @@ export interface AiTechnologyRadarReadback {
changed_count: number
representative_technologies: string[]
}>
high_priority_review_queue: Array<Record<string, unknown>>
high_priority_review_queue: Array<{
technology_id: string
display_name: string
technology_area: string
evaluation_priority: string
gate_status: string
next_gate: string
requires_cost_approval: boolean
requires_dependency_approval: boolean
requires_security_review: boolean
}>
professional_agent_roles: Array<{
agent: string
professional_role: string
@@ -1148,6 +1158,12 @@ export interface AiTechnologyRadarReadback {
output: string
gate: string
}>
primary_source_alignment: Array<{
practice: string
source: string
awoooi_gate: string
agent_assignment: string
}>
integration_candidates: Array<{
technology_id: string
display_name: string