diff --git a/apps/web/messages/en.json b/apps/web/messages/en.json
index 24955526..df54bea6 100644
--- a/apps/web/messages/en.json
+++ b/apps/web/messages/en.json
@@ -1871,7 +1871,7 @@
},
"neuralCommand": {
"title": "神經指揮中心",
- "subtitle": "SSH_COMMAND 指揮權鏈 · OpenClaw 🦞 × NemoTron ⚡",
+ "subtitle": "SSH_COMMAND 指揮權鏈 · OpenClaw × NemoTron",
"lastRefresh": "更新於 {time}",
"refresh": "重新整理",
"preFlightAudit": "Pre-Flight 審查",
@@ -1962,8 +1962,8 @@
"noApprovals": "目前無待審核項目",
"noApprovalsDesc": "所有授權請求已處理完畢",
"chainAlert": "告警觸發",
- "chainRAG": "🦞 OpenClaw RAG 診斷",
- "chainDecide": "⚡ NemoTron 決策",
+ "chainRAG": "OpenClaw RAG 診斷",
+ "chainDecide": "NemoTron 決策",
"chainExec": "Executor 路由",
"chainIdleSub": "等待新告警進入...",
"backToList": "返回列表",
diff --git a/apps/web/messages/zh-TW.json b/apps/web/messages/zh-TW.json
index 24955526..df54bea6 100644
--- a/apps/web/messages/zh-TW.json
+++ b/apps/web/messages/zh-TW.json
@@ -1871,7 +1871,7 @@
},
"neuralCommand": {
"title": "神經指揮中心",
- "subtitle": "SSH_COMMAND 指揮權鏈 · OpenClaw 🦞 × NemoTron ⚡",
+ "subtitle": "SSH_COMMAND 指揮權鏈 · OpenClaw × NemoTron",
"lastRefresh": "更新於 {time}",
"refresh": "重新整理",
"preFlightAudit": "Pre-Flight 審查",
@@ -1962,8 +1962,8 @@
"noApprovals": "目前無待審核項目",
"noApprovalsDesc": "所有授權請求已處理完畢",
"chainAlert": "告警觸發",
- "chainRAG": "🦞 OpenClaw RAG 診斷",
- "chainDecide": "⚡ NemoTron 決策",
+ "chainRAG": "OpenClaw RAG 診斷",
+ "chainDecide": "NemoTron 決策",
"chainExec": "Executor 路由",
"chainIdleSub": "等待新告警進入...",
"backToList": "返回列表",
diff --git a/apps/web/src/app/[locale]/knowledge-base/page.tsx b/apps/web/src/app/[locale]/knowledge-base/page.tsx
index cf66bd1a..a883488c 100644
--- a/apps/web/src/app/[locale]/knowledge-base/page.tsx
+++ b/apps/web/src/app/[locale]/knowledge-base/page.tsx
@@ -17,7 +17,7 @@ import { useTranslations } from 'next-intl'
import { cn } from '@/lib/utils'
import {
Search, BookOpen, FileText, Shield, Cpu,
- Server, Eye, Bot, ChevronRight, Plus, Sparkles,
+ Server, Eye, Bot, ChevronRight, Plus, Sparkles, ClipboardList, TriangleAlert,
} from 'lucide-react'
import ReactMarkdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
@@ -493,13 +493,15 @@ export default function KnowledgeBasePage({
{/* Related links */}
{selectedEntry.related_playbook_id && (
-
- 📋 {t('relatedPlaybook')}: {selectedEntry.related_playbook_id}
+
+
+ {t('relatedPlaybook')}: {selectedEntry.related_playbook_id}
)}
{selectedEntry.related_incident_id && (
-
- ⚠️ {t('relatedIncident')}: {selectedEntry.related_incident_id}
+
+
+ {t('relatedIncident')}: {selectedEntry.related_incident_id}
)}
@@ -534,4 +536,3 @@ export default function KnowledgeBasePage({
)
}
-
diff --git a/apps/web/src/components/ai/openclaw-state-machine.tsx b/apps/web/src/components/ai/openclaw-state-machine.tsx
index 79b78f49..7ba4489e 100644
--- a/apps/web/src/components/ai/openclaw-state-machine.tsx
+++ b/apps/web/src/components/ai/openclaw-state-machine.tsx
@@ -436,7 +436,7 @@ export function OpenClawStateMachine({
setSelectedIndex(null)
setProcessedApproval(null)
}}
- title={processedApproval ? (processedApproval.action === 'approved' ? '✅ 已批准' : '❌ 已拒絕') : '審核詳情'}
+ title={processedApproval ? (processedApproval.action === 'approved' ? '已批准' : '已拒絕') : '審核詳情'}
onPrev={processedApproval ? undefined : handlePrevApproval}
onNext={processedApproval ? undefined : handleNextApproval}
current={selectedIndex !== null && !processedApproval ? selectedIndex + 1 : undefined}
@@ -458,9 +458,12 @@ export function OpenClawStateMachine({
? "bg-status-healthy/20 text-status-healthy"
: "bg-status-critical/20 text-status-critical"
)}>
-
- {processedApproval.action === 'approved' ? '✅' : '❌'}
-
+
+ {processedApproval.action === 'approved'
+ ?
+ :
+ }
+
{processedApproval.action === 'approved' ? '已批准執行' : '已拒絕執行'}
diff --git a/apps/web/src/components/neural-command/NeuralLiveCenter.tsx b/apps/web/src/components/neural-command/NeuralLiveCenter.tsx
index e4ac700c..68416e0f 100644
--- a/apps/web/src/components/neural-command/NeuralLiveCenter.tsx
+++ b/apps/web/src/components/neural-command/NeuralLiveCenter.tsx
@@ -11,7 +11,7 @@
import { useTranslations } from 'next-intl'
import { cn } from '@/lib/utils'
-import { CheckCircle2, Clock, XCircle, Loader2, Inbox } from 'lucide-react'
+import { Bot, CheckCircle2, Clock, Cpu, Inbox, Loader2, Server, Settings, XCircle } from 'lucide-react'
import type { AutoRepairStats, RepairHistoryItem, UriScheme, RepairStatus, ActiveIncident } from './types'
interface Props {
@@ -41,6 +41,13 @@ const NODE_STATE_STYLES = {
waiting: 'border-border opacity-40',
}
+const SEVERITY_DOT_STYLES: Record
= {
+ P0: 'bg-red-500 ring-red-500/20',
+ P1: 'bg-orange-500 ring-orange-500/20',
+ P2: 'bg-yellow-500 ring-yellow-500/20',
+ P3: 'bg-green-500 ring-green-500/20',
+}
+
// 從最新一筆 history 衍生鏈路狀態
function deriveChainNodes(latestItem: RepairHistoryItem | null, t: ReturnType) {
if (!latestItem) {
@@ -72,14 +79,8 @@ function computeAvgDuration(history: RepairHistoryItem[]): string {
return `${(avg / 1000).toFixed(1)}s`
}
-// 嚴重度 → emoji 對應
-function severityEmoji(severity: string): string {
- switch (severity) {
- case 'P0': return '🔴'
- case 'P1': return '🟠'
- case 'P2': return '🟡'
- default: return '🟢'
- }
+function severityDotClass(severity: string): string {
+ return SEVERITY_DOT_STYLES[severity] ?? SEVERITY_DOT_STYLES.P3
}
export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents = [] }: Props) {
@@ -101,7 +102,9 @@ export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents
{/* OpenClaw */}
-
🦞
+
+
+
OpenClaw
{t('agentRoleOC')}
@@ -118,7 +121,9 @@ export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents
{/* NemoTron */}
-
⚡
+
+
+
NemoTron
{t('agentRoleNemo')}
@@ -142,7 +147,11 @@ export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents
'flex items-center gap-2 px-2 py-1.5 rounded-lg cursor-pointer transition-colors',
i === 0 ? 'bg-orange-500/8 border border-orange-500/20' : 'hover:bg-muted',
)}>
-
{severityEmoji(inc.severity)}
+
{inc.incident_id}
{inc.affected_services.join(', ') || inc.status}
@@ -187,16 +196,19 @@ export function NeuralLiveCenter({ stats, history, pendingCount, activeIncidents
{[
- { scheme: 'kubectl://', icon: '☸️', label: 'kubectl', cls: 'border-blue-500/25 bg-blue-500/5' },
- { scheme: 'openclaw://', icon: '🦞', label: 'OpenClaw', cls: 'border-orange-500/25 bg-orange-500/5' },
- { scheme: 'ansible://', icon: '⚙️', label: 'Ansible .188', cls: 'border-purple-500/25 bg-purple-500/5' },
- ].map(b => (
-
-
{b.icon}
-
{b.label}
-
{b.scheme}
-
- ))}
+ { scheme: 'kubectl://', Icon: Server, label: 'kubectl', cls: 'border-blue-500/25 bg-blue-500/5', iconCls: 'text-blue-500' },
+ { scheme: 'openclaw://', Icon: Bot, label: 'OpenClaw', cls: 'border-orange-500/25 bg-orange-500/5', iconCls: 'text-orange-500' },
+ { scheme: 'ansible://', Icon: Settings, label: 'Ansible .188', cls: 'border-purple-500/25 bg-purple-500/5', iconCls: 'text-purple-500' },
+ ].map(b => {
+ const BranchIcon = b.Icon
+ return (
+
+
+
{b.label}
+
{b.scheme}
+
+ )
+ })}
diff --git a/apps/web/src/components/neural-command/NeuralStats.tsx b/apps/web/src/components/neural-command/NeuralStats.tsx
index cff607ab..70ab7473 100644
--- a/apps/web/src/components/neural-command/NeuralStats.tsx
+++ b/apps/web/src/components/neural-command/NeuralStats.tsx
@@ -12,7 +12,8 @@
import { useMemo } from 'react'
import { useTranslations } from 'next-intl'
import { cn } from '@/lib/utils'
-import { Inbox } from 'lucide-react'
+import { Bot, Inbox, Server, Settings } from 'lucide-react'
+import type { LucideIcon } from 'lucide-react'
import type { AutoRepairStats, PlaybookItem, RepairHistoryItem } from './types'
interface DispositionSummary {
@@ -38,10 +39,10 @@ const TYPE_BADGE: Record
= {
openclaw: 'bg-orange-500/10 text-orange-500 border border-orange-500/25',
}
-const SCHEME_ICON: Record = {
- 'kubectl://': { icon: '☸️', color: 'bg-blue-500', textColor: 'text-blue-500', bg: 'bg-blue-500/10' },
- 'openclaw://': { icon: '🦞', color: 'bg-orange-500', textColor: 'text-orange-500', bg: 'bg-orange-500/10' },
- 'ansible://': { icon: '⚙️', color: 'bg-purple-500', textColor: 'text-purple-500', bg: 'bg-purple-500/10' },
+const SCHEME_STYLE: Record = {
+ 'kubectl://': { Icon: Server, color: 'bg-blue-500', textColor: 'text-blue-500', bg: 'bg-blue-500/10' },
+ 'openclaw://': { Icon: Bot, color: 'bg-orange-500', textColor: 'text-orange-500', bg: 'bg-orange-500/10' },
+ 'ansible://': { Icon: Settings, color: 'bg-purple-500', textColor: 'text-purple-500', bg: 'bg-purple-500/10' },
}
export function NeuralStats({ stats, playbooks, history, pendingCount, disposition }: Props) {
@@ -59,7 +60,7 @@ export function NeuralStats({ stats, playbooks, history, pendingCount, dispositi
const total = history.length || 1
return Object.entries(counts).map(([scheme, { count, successCount }]) => ({
scheme,
- ...(SCHEME_ICON[scheme] ?? SCHEME_ICON['kubectl://']),
+ ...(SCHEME_STYLE[scheme] ?? SCHEME_STYLE['kubectl://']),
count,
rate: count > 0 ? Math.round((successCount / count) * 100) : 0,
pct: Math.round((count / total) * 100),
@@ -145,9 +146,13 @@ export function NeuralStats({ stats, playbooks, history, pendingCount, dispositi
{t('schemeBreakdown')}
{schemeStats.length > 0 ? (
- {schemeStats.map(s => (
+ {schemeStats.map(s => {
+ const SchemeIcon = s.Icon
+ return (
-
{s.icon}
+
+
+
{s.scheme}
@@ -155,7 +160,8 @@ export function NeuralStats({ stats, playbooks, history, pendingCount, dispositi
{s.count}
{s.rate}%
- ))}
+ )
+ })}
) : (
diff --git a/docs/LOGBOOK.md b/docs/LOGBOOK.md
index b5d40767..b09819cd 100644
--- a/docs/LOGBOOK.md
+++ b/docs/LOGBOOK.md
@@ -1,3 +1,28 @@
+## 2026-06-03|前端 UI/UX 與素材治理同步盤點啟動
+
+**背景**:統帥追問前端是否也需要同步盤點 UI/UX 與素材。結論:需要,而且必須和 AI 自動化飛輪、AwoooP 操作台、告警流程呈現一起治理;目前問題不只是文案,而是過多文字牆、流程/拓樸/圖表不足、正式 UI 仍混用 emoji 作為產品圖示、可復用素材庫薄弱,導致使用者難以快速判斷「現在跑到哪個階段、誰主責、是否自動修復、何時要人工介入」。
+
+**本次盤點結果**:
+- `apps/web/public` 目前可復用產品素材極少,主要只有 `favicon.svg` 與 DSEG7 字型;缺少正式產品截圖、拓樸圖、架構圖、流程圖素材入口與治理清單。
+- 前端已有 `lucide-react`、`recharts`、`@xyflow/react` 等基礎能力,可以支撐專業圖示、趨勢圖、流程圖與狀態機視覺化;下一步應優先把大量文字段落改成「流程節點、狀態表、時間軸、拓樸關係、風險分佈」。
+- 正式頁仍有 emoji 扮演狀態或服務圖示,會削弱操作台專業感,也不利於建立一致設計語言。
+- `apps/web/src/components/aiops/timeline/mock-data.ts` 仍是前端假資料風險候選,後續要確認是否僅開發殘留,不能讓產品頁誤讀為真實自動化證據。
+
+**本次低風險可見修正**:
+- `NeuralLiveCenter`:告警雷達嚴重度由 emoji 改為一致狀態點;OpenClaw / NemoTron 與 kubectl / OpenClaw / Ansible 分支改用 lucide 圖示。
+- `NeuralStats`:URI scheme 分佈由 emoji 改為一致的圖示膠囊與進度條,保留真實 history 聚合邏輯。
+- `Knowledge Base`:related Playbook / Incident 連結改用 lucide 圖示,避免正式知識頁出現 emoji 標記。
+- `OpenClawStateMachine`:approval 處理結果 modal 移除 `✅ / ❌`,改用 lucide 成功/警示圖示。
+- `neuralCommand` i18n:副標題與鏈路節點文案移除 emoji,`zh-TW` / `en` 鏡像保持一致。
+
+**後續治理方向**:
+- Wave A:全站掃描 emoji-as-icon、硬編碼圖示、文字牆區塊,優先處理 AwoooP Runs / Approvals / Alerts / KM / Monitoring。
+- Wave B:建立 reusable visual primitives:狀態點、流程節點、拓樸節點、證據表、空狀態、資料品質徽章,避免每頁重做。
+- Wave C:補正式素材庫:AI 飛輪架構圖、MCP/Agent 拓樸圖、告警到修復 swimlane、資料來源與證據鏈圖;素材必須對應真實系統與 DB/API 證據,禁止用假圖暗示已完成。
+- Wave D:首頁與核心操作頁改為圖表/表格優先,文字只保留決策摘要與例外原因。
+
+**進度更新**:前端設計系統/i18n/素材治理由 `46%` 上修至 `49%`;首頁產品化入口維持 `80%`;AwoooP/HITL 維持 `99.2%`;完整 AI 自動化飛輪仍維持約 `66%`,本輪 UI 素材治理不代表自動修復能力已新增。
+
## 2026-06-02|IwoooS 進度誠實儀表正式落地
**背景**:統帥持續要求 IwoooS 不要只堆文字,且要讓使用者能理解「為什麼資安網有明顯框架進展,但整體進度不應假性跳點」。本輪延續低摩擦資安框架策略,不提高 enforcement、不啟動 Kali 掃描 / SSH 修復 / 主機更新 / repo mutation,只在首屏新增小型圖表化儀表,明確呈現只讀納管、S4.9 待補證據與執行閘門 0。