feat(web): refine operator navigation IA
This commit is contained in:
@@ -69,6 +69,11 @@
|
||||
"classicAICenter": "經典 AI 中心",
|
||||
"governance": "AI 治理",
|
||||
"awooop": "AwoooP",
|
||||
"awooopHome": "AwoooP 總覽",
|
||||
"workItems": "工作鏈路",
|
||||
"runMonitor": "Run 監控",
|
||||
"approvalQueue": "審批佇列",
|
||||
"operationsOverview": "營運總覽",
|
||||
"iwooos": "IwoooS",
|
||||
"iwooosSecurityCompliance": "IwoooS 安全合規"
|
||||
},
|
||||
@@ -1354,6 +1359,9 @@
|
||||
}
|
||||
},
|
||||
"navSection": {
|
||||
"queues": "處理佇列",
|
||||
"truth": "真相與治理",
|
||||
"legacy": "系統與相容",
|
||||
"aiCore": "AI 核心",
|
||||
"monitoring": "監控與安全",
|
||||
"ops": "運維管理",
|
||||
@@ -2221,7 +2229,11 @@
|
||||
"actionGoSettings": "前往設定",
|
||||
"actionGoTerminal": "前往終端頁面",
|
||||
"actionGoApprovals": "前往授權中心",
|
||||
"actionGoIwooos": "前往 IwoooS 資安主控台"
|
||||
"actionGoIwooos": "前往 IwoooS 資安主控台",
|
||||
"actionGoAwoooP": "前往 AwoooP 總覽",
|
||||
"actionGoWorkItems": "前往工作鏈路",
|
||||
"actionGoRuns": "前往 Run 監控",
|
||||
"actionGoApprovalQueue": "前往審批佇列"
|
||||
},
|
||||
"aiopsTimeline": {
|
||||
"title": "AIOps 全景時序",
|
||||
@@ -2652,6 +2664,21 @@
|
||||
}
|
||||
},
|
||||
"awooop": {
|
||||
"shell": {
|
||||
"title": "AwoooP 操作控制台",
|
||||
"subtitle": "控制平面",
|
||||
"mode": "影子模式優先",
|
||||
"operator": "操作員",
|
||||
"navLabel": "AwoooP 工作流導航",
|
||||
"nav": {
|
||||
"overview": "總覽",
|
||||
"workItems": "工作鏈路",
|
||||
"runs": "Run 監控",
|
||||
"approvals": "審批佇列",
|
||||
"contracts": "合約",
|
||||
"tenants": "租戶"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"eyebrow": "AI 自動化飛輪控制面",
|
||||
"title": "AwoooP 治理總覽",
|
||||
|
||||
@@ -69,6 +69,11 @@
|
||||
"classicAICenter": "經典 AI 中心",
|
||||
"governance": "AI 治理",
|
||||
"awooop": "AwoooP",
|
||||
"awooopHome": "AwoooP 總覽",
|
||||
"workItems": "工作鏈路",
|
||||
"runMonitor": "Run 監控",
|
||||
"approvalQueue": "審批佇列",
|
||||
"operationsOverview": "營運總覽",
|
||||
"iwooos": "IwoooS",
|
||||
"iwooosSecurityCompliance": "IwoooS 安全合規"
|
||||
},
|
||||
@@ -1354,6 +1359,9 @@
|
||||
}
|
||||
},
|
||||
"navSection": {
|
||||
"queues": "處理佇列",
|
||||
"truth": "真相與治理",
|
||||
"legacy": "系統與相容",
|
||||
"aiCore": "AI 核心",
|
||||
"monitoring": "監控與安全",
|
||||
"ops": "運維管理",
|
||||
@@ -2221,7 +2229,11 @@
|
||||
"actionGoSettings": "前往設定",
|
||||
"actionGoTerminal": "前往終端頁面",
|
||||
"actionGoApprovals": "前往授權中心",
|
||||
"actionGoIwooos": "前往 IwoooS 資安主控台"
|
||||
"actionGoIwooos": "前往 IwoooS 資安主控台",
|
||||
"actionGoAwoooP": "前往 AwoooP 總覽",
|
||||
"actionGoWorkItems": "前往工作鏈路",
|
||||
"actionGoRuns": "前往 Run 監控",
|
||||
"actionGoApprovalQueue": "前往審批佇列"
|
||||
},
|
||||
"aiopsTimeline": {
|
||||
"title": "AIOps 全景時序",
|
||||
@@ -2652,6 +2664,21 @@
|
||||
}
|
||||
},
|
||||
"awooop": {
|
||||
"shell": {
|
||||
"title": "AwoooP 操作控制台",
|
||||
"subtitle": "控制平面",
|
||||
"mode": "影子模式優先",
|
||||
"operator": "操作員",
|
||||
"navLabel": "AwoooP 工作流導航",
|
||||
"nav": {
|
||||
"overview": "總覽",
|
||||
"workItems": "工作鏈路",
|
||||
"runs": "Run 監控",
|
||||
"approvals": "審批佇列",
|
||||
"contracts": "合約",
|
||||
"tenants": "租戶"
|
||||
}
|
||||
},
|
||||
"home": {
|
||||
"eyebrow": "AI 自動化飛輪控制面",
|
||||
"title": "AwoooP 治理總覽",
|
||||
|
||||
@@ -8,8 +8,9 @@
|
||||
|
||||
import { AppLayout } from "@/components/layout";
|
||||
import { Link, usePathname } from "@/i18n/routing";
|
||||
import { Activity, BrainCircuit, Building2, ClipboardList, FileText, ShieldCheck } from "lucide-react";
|
||||
import { Activity, BrainCircuit, Building2, ClipboardList, FileText, LayoutDashboard, ShieldCheck } from "lucide-react";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
// =============================================================================
|
||||
// 導航設定
|
||||
@@ -17,30 +18,36 @@ import { cn } from "@/lib/utils";
|
||||
|
||||
const navItems = [
|
||||
{
|
||||
label: "工作鏈路",
|
||||
labelKey: "overview",
|
||||
href: "/awooop" as const,
|
||||
icon: LayoutDashboard,
|
||||
exact: true,
|
||||
},
|
||||
{
|
||||
labelKey: "workItems",
|
||||
href: "/awooop/work-items" as const,
|
||||
icon: ClipboardList,
|
||||
},
|
||||
{
|
||||
label: "租戶管理",
|
||||
href: "/awooop/tenants" as const,
|
||||
icon: Building2,
|
||||
},
|
||||
{
|
||||
label: "合約儀表板",
|
||||
href: "/awooop/contracts" as const,
|
||||
icon: FileText,
|
||||
},
|
||||
{
|
||||
label: "執行監控",
|
||||
labelKey: "runs",
|
||||
href: "/awooop/runs" as const,
|
||||
icon: Activity,
|
||||
},
|
||||
{
|
||||
label: "審批佇列",
|
||||
labelKey: "approvals",
|
||||
href: "/awooop/approvals" as const,
|
||||
icon: ShieldCheck,
|
||||
},
|
||||
{
|
||||
labelKey: "contracts",
|
||||
href: "/awooop/contracts" as const,
|
||||
icon: FileText,
|
||||
},
|
||||
{
|
||||
labelKey: "tenants",
|
||||
href: "/awooop/tenants" as const,
|
||||
icon: Building2,
|
||||
},
|
||||
];
|
||||
|
||||
// =============================================================================
|
||||
@@ -55,6 +62,7 @@ export default function AwoooPLayout({
|
||||
params: { locale: string };
|
||||
}) {
|
||||
const pathname = usePathname();
|
||||
const t = useTranslations("awooop.shell");
|
||||
|
||||
return (
|
||||
<AppLayout locale={params.locale} showBackground={false}>
|
||||
@@ -67,31 +75,31 @@ export default function AwoooPLayout({
|
||||
</span>
|
||||
<div>
|
||||
<h1 className="text-lg font-semibold tracking-normal text-[#141413]">
|
||||
AwoooP 操作控制台
|
||||
{t("title")}
|
||||
</h1>
|
||||
<div className="mt-1 flex items-center gap-2 text-xs text-[#77736a]">
|
||||
<span>控制平面</span>
|
||||
<span>{t("subtitle")}</span>
|
||||
<span className="h-1 w-1 rounded-full bg-[#d97757]" />
|
||||
<span>影子模式優先</span>
|
||||
<span>{t("mode")}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<span className="inline-flex items-center gap-2 border border-[#d8d3c7] bg-white px-3 py-1.5 text-xs font-semibold text-[#141413]">
|
||||
<span className="h-1.5 w-1.5 rounded-full bg-[#22c55e]" />
|
||||
操作員
|
||||
{t("operator")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<nav
|
||||
className="mt-4 flex flex-wrap gap-1"
|
||||
className="mt-4 flex max-w-full gap-1 overflow-x-auto pb-1"
|
||||
role="navigation"
|
||||
aria-label="AwoooP 主要導航"
|
||||
aria-label={t("navLabel")}
|
||||
>
|
||||
{navItems.map((item) => {
|
||||
const Icon = item.icon;
|
||||
const isActive =
|
||||
pathname === item.href ||
|
||||
pathname?.startsWith(item.href + "/");
|
||||
(!item.exact && pathname?.startsWith(item.href + "/"));
|
||||
|
||||
return (
|
||||
<Link
|
||||
@@ -99,14 +107,14 @@ export default function AwoooPLayout({
|
||||
href={item.href}
|
||||
aria-current={isActive ? "page" : undefined}
|
||||
className={cn(
|
||||
"inline-flex items-center gap-2 border px-3 py-2 text-sm font-medium transition-colors",
|
||||
"inline-flex shrink-0 items-center gap-2 border px-3 py-2 text-sm font-medium transition-colors",
|
||||
isActive
|
||||
? "border-[#d97757] bg-white text-[#141413]"
|
||||
: "border-transparent text-[#77736a] hover:border-[#d8d3c7] hover:bg-white hover:text-[#141413]"
|
||||
)}
|
||||
>
|
||||
<Icon className="h-4 w-4" aria-hidden="true" />
|
||||
{item.label}
|
||||
<span>{t(`nav.${item.labelKey}`)}</span>
|
||||
</Link>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -17,7 +17,21 @@ import React, { useEffect, useRef, useState, useCallback } from 'react'
|
||||
import { useTranslations } from 'next-intl'
|
||||
import { useRouter, usePathname } from 'next/navigation'
|
||||
import { useLocale } from 'next-intl'
|
||||
import { Search, Terminal, Home, Activity, Wrench, BookOpen, Settings, Zap, GitBranch, Radar } from 'lucide-react'
|
||||
import {
|
||||
Activity,
|
||||
BookOpen,
|
||||
BrainCircuit,
|
||||
ClipboardList,
|
||||
GitBranch,
|
||||
Home,
|
||||
Radar,
|
||||
Search,
|
||||
Settings,
|
||||
ShieldCheck,
|
||||
Terminal,
|
||||
Wrench,
|
||||
Zap,
|
||||
} from 'lucide-react'
|
||||
import { useTerminalStore } from '@/stores/terminal.store'
|
||||
import { Z_INDEX } from '@/lib/constants/z-index'
|
||||
|
||||
@@ -83,6 +97,38 @@ export function CommandPalette() {
|
||||
action: () => nav('/observability'),
|
||||
keywords: ['observability', '可觀測性', 'monitor', '監控'],
|
||||
},
|
||||
{
|
||||
id: 'awooop-home',
|
||||
label: t('actionGoAwoooP'),
|
||||
group: t('groupNav'),
|
||||
icon: <BrainCircuit size={14} />,
|
||||
action: () => nav('/awooop'),
|
||||
keywords: ['awooop', 'operator', 'console', '操作控制台', '總覽'],
|
||||
},
|
||||
{
|
||||
id: 'awooop-work-items',
|
||||
label: t('actionGoWorkItems'),
|
||||
group: t('groupNav'),
|
||||
icon: <ClipboardList size={14} />,
|
||||
action: () => nav('/awooop/work-items'),
|
||||
keywords: ['work items', '工作鏈路', '工作項', 'recurrence'],
|
||||
},
|
||||
{
|
||||
id: 'awooop-runs',
|
||||
label: t('actionGoRuns'),
|
||||
group: t('groupNav'),
|
||||
icon: <Activity size={14} />,
|
||||
action: () => nav('/awooop/runs'),
|
||||
keywords: ['runs', 'run monitor', '執行監控', 'run 監控'],
|
||||
},
|
||||
{
|
||||
id: 'awooop-approvals',
|
||||
label: t('actionGoApprovalQueue'),
|
||||
group: t('groupNav'),
|
||||
icon: <ShieldCheck size={14} />,
|
||||
action: () => nav('/awooop/approvals'),
|
||||
keywords: ['approval queue', '審批佇列', '人工閘門', 'approve'],
|
||||
},
|
||||
{
|
||||
id: 'automation',
|
||||
label: t('actionGoAutomation'),
|
||||
|
||||
@@ -1,20 +1,18 @@
|
||||
'use client'
|
||||
|
||||
/**
|
||||
* Sidebar - Phase 7.0 極簡五柱導航
|
||||
* =================================
|
||||
* Sidebar - Operator workflow navigation
|
||||
* ======================================
|
||||
* Nothing.tech 視覺憲法:
|
||||
* - 純白背景 (bg-white)
|
||||
* - 極細右邊框 (border-r-[0.5px] border-neutral-200)
|
||||
* - 無陰影
|
||||
* - 單色圖示
|
||||
*
|
||||
* 5 大核心樞紐:
|
||||
* 1. 全局戰情室 (/)
|
||||
* 2. 授權中心 (/authorizations) - 含動態徽章
|
||||
* 3. 行動日誌 (/action-logs)
|
||||
* 4. 知識殿堂 (/knowledge-base)
|
||||
* 5. 系統設定 (/settings)
|
||||
* IA v2 (2026-06-04):
|
||||
* - 頂層按照 operator 工作流排序,不按照技術模組排序。
|
||||
* - AwoooP / Runs / Work Items / Approvals / Alerts 直接成為全域入口。
|
||||
* - 頁內 tabs 只保留同一頁的視角切換,避免把任務入口藏在第二層。
|
||||
*
|
||||
* Phase 19: 使用 Z_INDEX.SIDEBAR (40)
|
||||
* @see lib/constants/z-index.ts
|
||||
@@ -28,12 +26,26 @@ import { usePathname } from 'next/navigation'
|
||||
import Link from 'next/link'
|
||||
import { cn } from '@/lib/utils'
|
||||
import {
|
||||
LayoutDashboard, ShieldCheck, Bell, Monitor, Activity,
|
||||
Bug, GitBranch, Shield, ClipboardCheck,
|
||||
Wrench, Package, Ticket, DollarSign, Zap, FileText,
|
||||
BookOpen, Terminal, AppWindow, Server,
|
||||
Users, BellRing, CreditCard, HelpCircle, Settings,
|
||||
ChevronLeft, ChevronRight, Diff, BrainCircuit, Radar,
|
||||
Activity,
|
||||
Bell,
|
||||
BookOpen,
|
||||
BrainCircuit,
|
||||
ChevronLeft,
|
||||
ChevronRight,
|
||||
ClipboardList,
|
||||
DollarSign,
|
||||
GitBranch,
|
||||
HelpCircle,
|
||||
LayoutDashboard,
|
||||
Monitor,
|
||||
Package,
|
||||
Radar,
|
||||
Route,
|
||||
Settings,
|
||||
ShieldCheck,
|
||||
Terminal,
|
||||
Ticket,
|
||||
Wrench,
|
||||
} from 'lucide-react'
|
||||
// Phase 8.0 #15: 改用 approval store SSE (移除 polling)
|
||||
import { useApprovalStore } from '@/stores/approval.store'
|
||||
@@ -56,55 +68,67 @@ type NavItemConfig = {
|
||||
labelKey: string
|
||||
Icon: typeof LayoutDashboard
|
||||
aliases?: string[]
|
||||
exact?: boolean
|
||||
badge?: boolean // 是否顯示動態徽章
|
||||
}
|
||||
|
||||
type NavSection = {
|
||||
sectionKey: string
|
||||
sectionLabel: string
|
||||
items: NavItemConfig[]
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Sprint 5: 精簡導航 6+2+經典(統帥批准 2026-04-08)
|
||||
// 2026-06-04: Operator-first IA
|
||||
// ============================================================
|
||||
// 整合對照:
|
||||
// 指令中心 / → 整合: 儀表板 + 授權 + 告警 + 報表 (4 Tab)
|
||||
// 可觀測性 /observability → 整合: 監控 + APM + 錯誤 + 應用 + 服務 (5 Tab) [暫指 /monitoring]
|
||||
// 自動化 /automation → 整合: 自動修復 + 神經指揮 + Drift (3 Tab) [暫指 /auto-repair]
|
||||
// 營運 /operations → 整合: 部署 + 工單 + 成本 + 行動日誌 + 計費 (5 Tab) [暫指 /deployments]
|
||||
// IwoooS /iwooos → 單一資安主入口;/security-compliance 保留相容高亮
|
||||
// 知識 /knowledge → 知識庫 [暫指 /knowledge-base]
|
||||
// 參考 Material / Atlassian / Carbon 的 app shell 模式:
|
||||
// 側欄放高頻任務與產品導航,Header 留給搜尋與全域工具。
|
||||
// ============================================================
|
||||
|
||||
const NAV_SECTIONS: NavSection[] = [
|
||||
{
|
||||
sectionKey: 'main',
|
||||
sectionLabel: '',
|
||||
sectionKey: 'queues',
|
||||
items: [
|
||||
{ id: 'command-center', href: '/', labelKey: 'commandCenter', Icon: LayoutDashboard },
|
||||
{ id: 'observability', href: '/observability', labelKey: 'observability', Icon: Monitor },
|
||||
{ id: 'automation', href: '/automation', labelKey: 'automation', Icon: Wrench },
|
||||
{ id: 'operations', href: '/operations', labelKey: 'operations', Icon: Package },
|
||||
{ id: 'iwooos-security', href: '/iwooos', labelKey: 'iwooos', Icon: Radar, aliases: ['/security-compliance'] },
|
||||
{ id: 'knowledge', href: '/knowledge', labelKey: 'knowledge', Icon: BookOpen },
|
||||
{ id: 'governance', href: '/governance', labelKey: 'governance', Icon: ShieldCheck },
|
||||
{ id: 'awooop', href: '/awooop/work-items', labelKey: 'awooop', Icon: BrainCircuit },
|
||||
{ id: 'command-center', href: '/', labelKey: 'commandCenter', Icon: LayoutDashboard },
|
||||
{ id: 'awooop-home', href: '/awooop', labelKey: 'awooopHome', Icon: BrainCircuit, exact: true },
|
||||
{ id: 'awooop-work-items', href: '/awooop/work-items', labelKey: 'workItems', Icon: ClipboardList },
|
||||
{ id: 'awooop-runs', href: '/awooop/runs', labelKey: 'runMonitor', Icon: Activity },
|
||||
{ id: 'awooop-approvals', href: '/awooop/approvals', labelKey: 'approvalQueue', Icon: ShieldCheck, badge: true },
|
||||
{ id: 'alerts', href: '/alerts', labelKey: 'alerts', Icon: Bell },
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionKey: 'truth',
|
||||
items: [
|
||||
{ id: 'observability', href: '/observability', labelKey: 'observability', Icon: Monitor },
|
||||
{ id: 'automation', href: '/automation', labelKey: 'automation', Icon: Wrench },
|
||||
{ id: 'governance', href: '/governance', labelKey: 'governance', Icon: ShieldCheck },
|
||||
{ id: 'knowledge', href: '/knowledge', labelKey: 'knowledge', Icon: BookOpen },
|
||||
{ id: 'iwooos-security', href: '/iwooos', labelKey: 'iwooos', Icon: Radar, aliases: ['/security-compliance'] },
|
||||
],
|
||||
},
|
||||
{
|
||||
sectionKey: 'ops',
|
||||
items: [
|
||||
{ id: 'operations', href: '/operations', labelKey: 'operationsOverview', Icon: Package },
|
||||
{ id: 'topology', href: '/topology', labelKey: 'topology', Icon: Route },
|
||||
{ id: 'deployments', href: '/deployments', labelKey: 'deployments', Icon: GitBranch },
|
||||
{ id: 'tickets', href: '/tickets', labelKey: 'tickets', Icon: Ticket },
|
||||
{ id: 'cost', href: '/cost', labelKey: 'cost', Icon: DollarSign },
|
||||
],
|
||||
},
|
||||
{
|
||||
// Legacy: 經典 AI 中心 (統帥指示保留)
|
||||
sectionKey: 'legacy',
|
||||
sectionLabel: 'legacy',
|
||||
items: [
|
||||
{ id: 'classic', href: '/classic', labelKey: 'classicAICenter', Icon: LayoutDashboard },
|
||||
{ id: 'terminal', href: '/terminal', labelKey: 'terminal', Icon: Terminal },
|
||||
{ id: 'settings', href: '/settings', labelKey: 'settings', Icon: Settings },
|
||||
{ id: 'classic', href: '/classic', labelKey: 'classicAICenter', Icon: LayoutDashboard },
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const BOTTOM_NAV_ITEMS: NavItemConfig[] = [
|
||||
{ id: 'terminal', href: '/terminal', labelKey: 'terminal', Icon: Terminal },
|
||||
{ id: 'settings', href: '/settings', labelKey: 'settings', Icon: Settings },
|
||||
{ id: 'help', href: '/help', labelKey: 'help', Icon: HelpCircle },
|
||||
]
|
||||
|
||||
// =============================================================================
|
||||
@@ -119,7 +143,6 @@ export function Sidebar({
|
||||
className,
|
||||
}: SidebarProps) {
|
||||
const t = useTranslations('nav')
|
||||
const tBrand = useTranslations('brand')
|
||||
const tSection = useTranslations('navSection')
|
||||
const tSidebar = useTranslations('sidebar')
|
||||
const pathname = usePathname()
|
||||
@@ -134,16 +157,19 @@ export function Sidebar({
|
||||
setMounted(true)
|
||||
}, [])
|
||||
|
||||
const isRouteActive = (href: string) => {
|
||||
const isRouteActive = (href: string, exact = false) => {
|
||||
const fullHref = `/${locale}${href === '/' ? '' : href}`
|
||||
if (href === '/') {
|
||||
return pathname === `/${locale}` || pathname === `/${locale}/`
|
||||
}
|
||||
if (exact) {
|
||||
return pathname === fullHref || pathname === `${fullHref}/`
|
||||
}
|
||||
return pathname === fullHref || pathname.startsWith(fullHref + '/')
|
||||
}
|
||||
|
||||
const isActive = (item: NavItemConfig) => (
|
||||
isRouteActive(item.href) || item.aliases?.some(alias => isRouteActive(alias)) === true
|
||||
isRouteActive(item.href, item.exact) || item.aliases?.some(alias => isRouteActive(alias)) === true
|
||||
)
|
||||
const sidebarWidth = compact && collapsed ? 48 : collapsed ? 64 : 224
|
||||
|
||||
@@ -164,13 +190,11 @@ export function Sidebar({
|
||||
}}
|
||||
>
|
||||
|
||||
{/* 導航列表 - AI中心 v6 4分區 */}
|
||||
{/* 導航列表 - Operator workflow sections */}
|
||||
<nav className="flex-1 py-2 overflow-y-auto">
|
||||
{/* 4 分區菜單 */}
|
||||
{NAV_SECTIONS.map(section => (
|
||||
<div key={section.sectionKey} style={{ marginBottom: 4 }}>
|
||||
{/* 分區標題 — main 不顯示,legacy 顯示分隔線+標題 */}
|
||||
{!collapsed && section.sectionLabel && (
|
||||
{!collapsed && (
|
||||
<div style={{
|
||||
fontSize: 10,
|
||||
color: '#b0ad9f',
|
||||
@@ -181,7 +205,7 @@ export function Sidebar({
|
||||
borderTop: '0.5px solid #e0ddd4',
|
||||
marginTop: 4,
|
||||
}}>
|
||||
{section.sectionLabel}
|
||||
{tSection(section.sectionKey)}
|
||||
</div>
|
||||
)}
|
||||
{section.items.map(item => {
|
||||
@@ -191,6 +215,7 @@ export function Sidebar({
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/${locale}${item.href === '/' ? '' : item.href}`}
|
||||
title={collapsed ? t(item.labelKey) : undefined}
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@@ -205,10 +230,15 @@ export function Sidebar({
|
||||
textDecoration: 'none',
|
||||
transition: 'all 0.15s',
|
||||
position: 'relative' as const,
|
||||
minHeight: collapsed ? 36 : 32,
|
||||
}}
|
||||
>
|
||||
<item.Icon size={15} />
|
||||
{!collapsed && <span>{t(item.labelKey)}</span>}
|
||||
<item.Icon size={15} aria-hidden="true" />
|
||||
{!collapsed && (
|
||||
<span style={{ minWidth: 0, overflowWrap: 'anywhere' }}>
|
||||
{t(item.labelKey)}
|
||||
</span>
|
||||
)}
|
||||
{item.badge && count > 0 && (
|
||||
<span style={{
|
||||
marginLeft: 'auto',
|
||||
@@ -238,6 +268,7 @@ export function Sidebar({
|
||||
<Link
|
||||
key={item.id}
|
||||
href={`/${locale}${item.href === '/' ? '' : item.href}`}
|
||||
title={collapsed ? t(item.labelKey) : undefined}
|
||||
style={{
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
@@ -251,10 +282,15 @@ export function Sidebar({
|
||||
background: active ? 'rgba(217,119,87,0.08)' : 'transparent',
|
||||
textDecoration: 'none',
|
||||
transition: 'all 0.15s',
|
||||
minHeight: collapsed ? 34 : 30,
|
||||
}}
|
||||
>
|
||||
<item.Icon size={15} />
|
||||
{!collapsed && <span>{t(item.labelKey)}</span>}
|
||||
<item.Icon size={15} aria-hidden="true" />
|
||||
{!collapsed && (
|
||||
<span style={{ minWidth: 0, overflowWrap: 'anywhere' }}>
|
||||
{t(item.labelKey)}
|
||||
</span>
|
||||
)}
|
||||
</Link>
|
||||
)
|
||||
})}
|
||||
|
||||
@@ -28802,3 +28802,48 @@ production browser smoke:
|
||||
- Frontend design system / i18n:約 46%;盤點完成,但 primitives 與 AwoooP i18n 大掃除尚未實作。
|
||||
- 完整自動修復 production claim:約 3.5%;本輪是 UX/可視化進展,未提高 verified auto-repair execution success。
|
||||
- 完整 AI Agent 自動化飛輪:約 66%;可視化與產品入口改善,但真正自動執行、驗證、學習閉環仍需下一波 API + executor + governance 工作。
|
||||
|
||||
## 2026-06-04 — 導航 IA 第一波與 AI 飛輪工作推進清單
|
||||
|
||||
**背景**:
|
||||
- 使用者批准繼續,要求優化目前導航列排列順序,解決「導航列菜單裡又有多個分頁」造成的使用體驗問題。
|
||||
- 同時要求把新 session handoff 收斂成可執行 MD,定義 P0/P1/P2 優先順序、細化工作項,且每階段完成後同步完成度與狀態。
|
||||
|
||||
**本輪完成**:
|
||||
- 新增 `docs/workplans/2026-06-04-navigation-and-ai-flywheel-workplan.md`:
|
||||
- 整合目前基線、Gitea push 規則、P0/P1/P2 phase、細項、驗收標準與完成度回報規則。
|
||||
- Phase 0 導航 IA 本地驗證完成,完成度先推進到 `92%`,保留 Gitea / production 證據待推版後補齊。
|
||||
- 全域 Sidebar 改成 operator-first IA:
|
||||
- 第一區改為處理佇列:指令中心、AwoooP 總覽、工作鏈路、Run 監控、審批佇列、告警。
|
||||
- 第二區改為真相與治理:可觀測性、自動化、AI 治理、知識殿堂、IwoooS。
|
||||
- 第三區改為營運:營運總覽、拓撲圖、部署管理、工單、成本分析。
|
||||
- 系統與相容區保留終端、設定、經典 AI 中心;說明移到底部工具位。
|
||||
- AwoooP shell 改為 i18n,移除硬編 UI 文案。
|
||||
- AwoooP 二級導航改成工作流順序:總覽、工作鏈路、Run 監控、審批佇列、合約、租戶。
|
||||
- Command Palette 補 AwoooP 總覽、工作鏈路、Run 監控、審批佇列,避免快捷導航與 Sidebar 分叉。
|
||||
|
||||
**參考設計原則**:
|
||||
- Material Design:5 個以上 top-level destinations / 兩層以上 hierarchy 適合用 navigation drawer。
|
||||
- Atlassian 新導航:sidebar 承載高密度工作流,top bar 留給 search / create 等 universal actions。
|
||||
- IBM Carbon UI shell:header 是最高層,left panel 承載產品導航,右側留給全域 utilities。
|
||||
|
||||
**驗證**:
|
||||
- `node -e "JSON.parse(...zh-TW.json); JSON.parse(...en.json); console.log('json ok')"` → `json ok`
|
||||
- `pnpm --filter @awoooi/web typecheck` → success
|
||||
- `NEXT_PUBLIC_API_URL=https://awoooi.wooo.work NEXT_PRIVATE_BUILD_WORKER_COUNT=1 pnpm --filter @awoooi/web build` → success;92 static pages generated。
|
||||
- Local production server:`http://127.0.0.1:3115`
|
||||
- Desktop 1440:Sidebar 順序為 `指令中心 / AwoooP 總覽 / 工作鏈路 / Run 監控 / 審批佇列 / 告警`,section labels 顯示 `處理佇列 / 真相與治理 / 運維管理 / 系統與相容`。
|
||||
- Desktop AwoooP subnav:`總覽 / 工作鏈路 / Run 監控 / 審批佇列 / 合約 / 租戶`,`總覽` 為 active。
|
||||
- Desktop `horizontalOverflow=0`。
|
||||
- Mobile 390:Sidebar collapsed titles 含 `指令中心 / AwoooP 總覽 / 工作鏈路 / Run 監控 / 審批佇列 / 告警`,AwoooP subnav 可橫向滾動。
|
||||
- Mobile `horizontalOverflow=0`。
|
||||
- `git diff --check` → pass。
|
||||
|
||||
**目前狀態**:
|
||||
- Phase 0 導航 IA:`92%`;本地完整驗證完成,待 commit / Gitea main / production smoke 後補到 `100%`。
|
||||
- 首頁產品化入口:維持 `88%`。
|
||||
- AI provider readability:維持 `88%`。
|
||||
- Runs visibility:`88% → 90%`,因 Run 監控已成為全域一級入口。
|
||||
- Work Items readability:`84% → 88%`,因工作鏈路已成為全域一級入口。
|
||||
- Design system:`54% → 58%`,因 Sidebar / AwoooP shell / Command Palette 導航語意與 i18n 開始收斂。
|
||||
- 完整 AI 自動化飛輪:維持 `69%`,本輪是 IA 與工作推進清單,不宣稱自動執行閉環進步。
|
||||
|
||||
229
docs/workplans/2026-06-04-navigation-and-ai-flywheel-workplan.md
Normal file
229
docs/workplans/2026-06-04-navigation-and-ai-flywheel-workplan.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# 2026-06-04 導航 IA 與 AI 自動化飛輪推進清單
|
||||
|
||||
> 本文件是本輪工作推進 handoff 與執行清單。AI 自動化飛輪的架構事實仍以 `docs/superpowers/specs/2026-04-15-MASTER-ai-autonomous-flywheel-v2.md` 為唯一事實來源;本文件只負責排序、拆工、驗收與狀態追蹤。
|
||||
|
||||
## 目前基線
|
||||
|
||||
| 項目 | 狀態 |
|
||||
| --- | --- |
|
||||
| Repo/worktree | `/private/tmp/awoooi-iwooos-next-gate-20260604` |
|
||||
| 推版規則 | 只推 Gitea:`git push gitea HEAD:main`;GitHub 只讀備份 |
|
||||
| 最新完成 commit | `e5230c92 feat(web): compact homepage diagram atlas` |
|
||||
| 最新 LOGBOOK commit | `30670c79 docs(logbook): record homepage diagram atlas rollout [skip ci]` |
|
||||
| 正式站驗證 | `https://awoooi.wooo.work/zh-TW?_v=e5230c92-diagram-atlas-prod` |
|
||||
| 首頁產品化入口 | 88% |
|
||||
| AI provider readability | 88% |
|
||||
| Runs visibility | 88% |
|
||||
| Work Items readability | 84% |
|
||||
| Design system | 54% |
|
||||
| 完整 AI 自動化飛輪 | 69% |
|
||||
|
||||
## Session 啟動固定檢查
|
||||
|
||||
- [x] `git fetch gitea main`
|
||||
- [x] `git status --short`
|
||||
- [x] `git log --oneline -8`
|
||||
- [x] 讀 MASTER §0 / §1 / §8、`docs/HARD_RULES.md`、`docs/LOGBOOK.md`
|
||||
- [x] `project_current_status.md` 超過 2 天,需先做狀態同步
|
||||
|
||||
## 導航 IA 原則
|
||||
|
||||
| 原則 | 本輪落地 |
|
||||
| --- | --- |
|
||||
| 主入口按工作流排序,不按技術模組排序 | 先放指令中心、AwoooP、工作鏈路、Runs、審批、告警 |
|
||||
| 左側導覽承載跨頁任務入口 | 把高頻 AwoooP 子頁與告警入口提到全域側欄 |
|
||||
| 頁內 tabs 只表示同一頁的視角 | Observability / Automation / Operations 的 tabs 後續逐步拆成可掃描子入口 |
|
||||
| Header 保留全域動作 | Search / command palette / profile / notification 維持在 header 或快捷指令 |
|
||||
| Mobile 不藏真任務 | 側欄保持可滾動,長標籤需可換行或收合顯示 |
|
||||
|
||||
參考來源:
|
||||
- Material Design navigation drawer:5 個以上 top-level destinations 與兩層以上導航階層,適合用 drawer。
|
||||
- Atlassian navigation redesign:用 sidebar 提升跨專案工作效率,top bar 留給 search / create 等 universal actions。
|
||||
- IBM Carbon UI shell:header 是最高層導航,left panel 承載產品導航,右側留給全域 utilities。
|
||||
|
||||
## 推進規則
|
||||
|
||||
1. 每個 phase 完成後更新本文件的完成度與狀態。
|
||||
2. 每個可部署 phase 都更新 `docs/LOGBOOK.md`。
|
||||
3. 前端變更必跑 i18n JSON parse、TypeScript、build 與 Browser desktop/mobile smoke。
|
||||
4. 涉及正式站聲明必用 production API / browser / Gitea run 證據,不引用舊報告。
|
||||
5. 每個 phase 完成後推 `gitea main`,除非該 phase 明確標記為純本地盤點且不可部署。
|
||||
|
||||
## Phase 0 - 導航 IA 第一波
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P0 |
|
||||
| 目標 | 先修目前最直觀的 UX 阻塞:全域導航排序混亂、AwoooP 頁內入口難掃描、部分 UI 文字硬編。 |
|
||||
| 狀態 | 本地驗證完成,待 Gitea 推版 |
|
||||
| 完成度 | 92% |
|
||||
|
||||
細項:
|
||||
- [x] 以「處理佇列 / 真相與治理 / 營運 / 系統」重排 Sidebar。
|
||||
- [x] 將 `AwoooP 總覽`、`工作鏈路`、`Run 監控`、`審批佇列`、`告警` 提升為全域可見入口。
|
||||
- [x] AwoooP shell 改為 i18n,移除硬編文案。
|
||||
- [x] AwoooP 二級導航改為工作流順序:總覽 → 工作鏈路 → Run 監控 → 審批佇列 → 合約 → 租戶。
|
||||
- [x] 保留 `classic` 相容入口,但移入系統區。
|
||||
- [x] 驗證 desktop / mobile 無水平溢出,導航可見。
|
||||
|
||||
驗收:
|
||||
- [x] `node -e "JSON.parse(...zh-TW.json); JSON.parse(...en.json)"`
|
||||
- [x] `pnpm --filter @awoooi/web typecheck`
|
||||
- [x] `NEXT_PUBLIC_API_URL=https://awoooi.wooo.work NEXT_PRIVATE_BUILD_WORKER_COUNT=1 pnpm --filter @awoooi/web build`
|
||||
- [x] Browser desktop 1440px:Sidebar 顯示新順序,AwoooP secondary nav 顯示新順序。
|
||||
- [x] Browser mobile 390px:`horizontalOverflow=0`。
|
||||
- [ ] 推 `gitea main` 並記錄 run / production 證據。
|
||||
|
||||
## Phase 1 - P0 AI 自動化飛輪真相盤點
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P0 |
|
||||
| 狀態 | 未開始 |
|
||||
| 目標完成度 | 完整 AI 自動化飛輪 69% → 75% |
|
||||
|
||||
細項:
|
||||
- [ ] 查 `auto_execute_success_rate` SLO 違反原因,對照最近自動修復任務。
|
||||
- [ ] 盤點流程是否真跑完:alert ingest → classify → rule match → MCP evidence → PlayBook → approval gate → Ansible/repair → verifier → KM → postmortem。
|
||||
- [ ] 補 timeline event:每個 incident 必須看到 stage、handler、AI action、manual need。
|
||||
- [ ] Telegram 告警補 stage、next action、blocked reason、auto/manual。
|
||||
- [ ] 建立風險分級與 approval gate 對照表,釐清中低風險是否允許 AI 自動修復。
|
||||
- [ ] 確認 MCP / 自建 MCP 實際 tool call、evidence、result 有被前端顯示。
|
||||
|
||||
驗收:
|
||||
- [ ] DB / API / browser 都能查到同一 incident 的 stage timeline。
|
||||
- [ ] Telegram 訊息可不開前端判斷目前流程狀態。
|
||||
- [ ] 低風險自動修復權限與人工 gate 條件有可驗證表格。
|
||||
|
||||
## Phase 2 - P0 告警資料鏈路
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P0 |
|
||||
| 狀態 | 未開始 |
|
||||
| 目標完成度 | 告警資料鏈路可判讀性 → 90% |
|
||||
|
||||
細項:
|
||||
- [ ] 所有 Telegram 告警完整寫入 DB,不只送訊息。
|
||||
- [ ] 告警關聯 Sentry、SigNoz、Alertmanager、K8s、host logs、run timeline。
|
||||
- [ ] 建立告警 dedupe / fingerprint / recurrence 統計,降低重複轟炸。
|
||||
- [ ] 修「詳情 / 歷史」HTTP 400 或查不到事件。
|
||||
- [ ] 修 postmortem 瞬間大量重複通知。
|
||||
- [ ] 修 Config Drift 重複告警,確認 PR 已建立後的採納 / 關閉 / baseline / TTL 狀態。
|
||||
|
||||
驗收:
|
||||
- [ ] 同一 fingerprint 可看到 recurrence 次數、最新來源、處置狀態。
|
||||
- [ ] 詳情 / 歷史連結不再 400。
|
||||
- [ ] 重複通知有 DB 證據與 TTL 判讀。
|
||||
|
||||
## Phase 3 - P0 AI Provider / Agent 主責
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P0 |
|
||||
| 狀態 | 未開始 |
|
||||
| 目標完成度 | AI provider readability 88% → 95% |
|
||||
|
||||
細項:
|
||||
- [ ] 強制確認 Ollama 使用順序:GCP-A → GCP-B → 111 → Gemini fallback。
|
||||
- [ ] 查為什麼會跑到 111 Ollama,而不是先 GCP-A/GCP-B。
|
||||
- [ ] Gemini 僅 fallback,不禁用。
|
||||
- [ ] Hermes 作 KM / E7 自動知識主責。
|
||||
- [ ] OpenClaw 作告警分類、規則匹配、PlayBook 脈絡摘要,不直接批量改 KM。
|
||||
- [ ] ElephantAlpha 作 read-only 稽核與高風險 review。
|
||||
- [ ] 前端顯示每次 AI route:provider、model、fallback 原因、token、latency、result。
|
||||
|
||||
驗收:
|
||||
- [ ] `/api/v1/platform/ai-route-status` 與 run detail 顯示同一 route truth。
|
||||
- [ ] 任何 fallback 都有原因與 latency。
|
||||
- [ ] 前端不再只顯示概念性 provider 文案。
|
||||
|
||||
## Phase 4 - P0 KM 劣化治理
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P0 |
|
||||
| 狀態 | 未開始 |
|
||||
| 目標完成度 | KM / Governance workflow 58% → 80% |
|
||||
|
||||
細項:
|
||||
- [ ] 處理 `knowledge_degradation`:stale KM ratio 需低於 20%。
|
||||
- [ ] 建立 `run_kb_growth_healthcheck` 真正排程與執行紀錄。
|
||||
- [ ] Hermes 反查 Incident / Sentry / SigNoz / PlayBook,產生 KM 更新草稿。
|
||||
- [ ] 高影響 KM 必須 owner review 後寫入。
|
||||
- [ ] Work Items / Knowledge Base 顯示 stale 條目、owner、來源、引用次數、下一步。
|
||||
- [ ] Telegram 文案改成白話治理品質警報,避免誤判為服務故障。
|
||||
|
||||
驗收:
|
||||
- [ ] stale 候選有 owner review queue。
|
||||
- [ ] healthcheck 有 schedule / last run / result。
|
||||
- [ ] KM 草稿與採納狀態可從前端查到。
|
||||
|
||||
## Phase 5 - P1 前端產品化
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P1 |
|
||||
| 狀態 | 未開始 |
|
||||
| 目標完成度 | 首頁產品化入口 88% → 95%;Design system 54% → 70% |
|
||||
|
||||
細項:
|
||||
- [ ] 首頁繼續從大量文字改成圖、表、流程、矩陣。
|
||||
- [ ] 抽共用 visual components:swimlane、matrix、diagram atlas、timeline、state machine、topology。
|
||||
- [ ] AwoooP Runs 補完整事件時間線、AI route、MCP evidence、repair/verifier result。
|
||||
- [ ] Work Items 補 owner review rail、KM task、blocking reason、next step。
|
||||
- [ ] Approvals 補風險門、批准後實際是否執行、執行結果。
|
||||
- [ ] Alerts 補 recurrence、fingerprint、Sentry/SigNoz/K8s 關聯。
|
||||
- [ ] Monitoring / Cost / Tickets 接真實資料,移除空洞文案。
|
||||
- [ ] 所有文案 i18n,不硬編中文/英文。
|
||||
- [ ] 禁用 emoji 當 UI icon,改 lucide/icons。
|
||||
- [ ] 確認首頁與各頁 mobile 可上下滾動、`horizontalOverflow=0`。
|
||||
|
||||
## Phase 6 - P1 Ansible / PlayBook / Auto Repair
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P1 |
|
||||
| 狀態 | 未開始 |
|
||||
| 目標完成度 | Ansible / AutoRepair gate 可視化 52% → 80% |
|
||||
|
||||
細項:
|
||||
- [ ] 盤點 Ansible 是否真正被 AI automation 使用,而不是只存在 repo。
|
||||
- [ ] PlayBook 要有 trust score、成功 / 失敗回寫、版本、owner、適用條件。
|
||||
- [ ] 自動修復不能只推薦重啟,要依 MCP evidence 與 PlayBook trust 決策。
|
||||
- [ ] 自動修復完成後 verifier 驗證,失敗才升級人工。
|
||||
- [ ] 每次修復都回寫 KM / PlayBook / incident timeline。
|
||||
|
||||
## Phase 7 - P1 既有紅燈驗證
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P1 |
|
||||
| 狀態 | 未開始 |
|
||||
|
||||
細項:
|
||||
- [ ] Production PostgreSQL 直接查 RLS policy,不引用舊報告。
|
||||
- [ ] 查 `.claude/settings.json` token 是否真在 repo/worktree;若有,移除並輪換。
|
||||
- [ ] 查 110 swap、188 certbot、188 memory、GCP-B live usage。
|
||||
- [ ] 查 GitHub workflow 是否仍可能觸發競爭 K3s。
|
||||
- [ ] 查 188 local Ollama 是否仍有 direct `OLLAMA_URL` caller,確認後再清理,不直接 uninstall。
|
||||
|
||||
## Phase 8 - P2 技術債 / 清理
|
||||
|
||||
| 欄位 | 內容 |
|
||||
| --- | --- |
|
||||
| 優先級 | P2 |
|
||||
| 狀態 | 未開始 |
|
||||
|
||||
細項:
|
||||
- [ ] 清理前端舊版本、空洞首頁、無效進度條、小龍蝦進度條資料源。
|
||||
- [ ] 清掉假資料、硬編 IP、舊 fallback copy、舊 navigation 版本差異。
|
||||
- [ ] 把已完成與推進中的工作同步到前端,不把聊天內容原文寫成頁面文案。
|
||||
- [ ] LOGBOOK 持續記錄每階段:完成項、commit、Gitea run、正式站證據、整體進度。
|
||||
|
||||
## 狀態更新紀錄
|
||||
|
||||
| 時間 | Phase | 完成度 | 狀態 |
|
||||
| --- | --- | --- | --- |
|
||||
| 2026-06-04 | Phase 0 | 0% | 建立工作清單,開始導航 IA 第一波 |
|
||||
| 2026-06-04 | Phase 0 | 92% | 導航 IA 本地驗證完成,待 Gitea 推版與正式站證據 |
|
||||
Reference in New Issue
Block a user