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
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:
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user