diff --git a/docs/superpowers/plans/2026-07-06-stage-2-5-global-frontend-prototype.md b/docs/superpowers/plans/2026-07-06-stage-2-5-global-frontend-prototype.md
new file mode 100644
index 0000000..ca6ae08
--- /dev/null
+++ b/docs/superpowers/plans/2026-07-06-stage-2-5-global-frontend-prototype.md
@@ -0,0 +1,1661 @@
+# Stage 2.5 Global Frontend Prototype Implementation Plan
+
+> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Build a Chinese, shadcn-based, interactive frontend prototype that exposes the full AI ticket platform product map before implementing Stage 3 to Stage 5 backend APIs.
+
+**Architecture:** Keep existing real API-backed pages for tickets, solutions, knowledge, and system management. Add a frontend-only prototype module with typed mock contracts, shared App components, and mock-backed pages for dashboard, model hub, Agents, Skills, and MCP tools. Route everything through the current hash router and sidebar without adding backend models or APIs.
+
+**Tech Stack:** React, Vite, TypeScript, Tailwind CSS, shadcn/ui, Radix UI, lucide-react, existing project-owned `App*` components.
+
+---
+
+## Source Spec
+
+- `docs/superpowers/specs/2026-07-06-stage-2-5-global-frontend-prototype-design.md`
+
+## File Structure
+
+Create:
+
+- `frontend/src/features/prototype/types.ts` - Typed mock contracts that document future API payloads.
+- `frontend/src/features/prototype/mockData.ts` - Realistic Chinese mock data for dashboard, model hub, Agent, Skill, and MCP pages.
+- `frontend/src/components/app/AppMetricCard.tsx` - Reusable metric card for workbench/dashboard/model summaries.
+- `frontend/src/components/app/AppRiskBadge.tsx` - Reusable risk badge for MCP and Agent safety states.
+- `frontend/src/components/app/AppTraceTimeline.tsx` - Reusable execution trace timeline for Agent/tool/model steps.
+- `frontend/src/components/app/AppReferenceCard.tsx` - Reusable citable reference card for knowledge/AI panels.
+- `frontend/src/features/dashboard/DashboardPage.tsx` - Mock-backed operational dashboard.
+- `frontend/src/features/modelhub/ModelProviderPage.tsx` - Mock-backed model provider list and edit dialog.
+- `frontend/src/features/modelhub/ModelTestingPage.tsx` - Mock-backed model comparison/testing page.
+- `frontend/src/features/agents/AgentListPage.tsx` - Mock-backed Agent configuration list.
+- `frontend/src/features/agents/AgentRunsPage.tsx` - Mock-backed Agent run list.
+- `frontend/src/features/agents/AgentRunDetailPage.tsx` - Mock-backed Agent run detail and step trace.
+- `frontend/src/features/skills/SkillListPage.tsx` - Mock-backed Skill list and editing/testing surface.
+- `frontend/src/features/tools/McpToolsPage.tsx` - Mock-backed MCP server/tool/risk page.
+
+Modify:
+
+- `frontend/src/app/router.tsx` - Add Stage 2.5 routes.
+- `frontend/src/components/app/AppSidebar.tsx` - Expose full product map through built-in prototype navigation when backend menus do not include it.
+- `frontend/src/features/workbench/WorkbenchPage.tsx` - Add AI/knowledge/model/tool overview blocks using real tickets plus prototype metrics.
+- `frontend/src/features/tickets/TicketCreatePage.tsx` - Add a future Agent-assisted creation panel.
+- `frontend/src/features/tickets/TicketDetailPage.tsx` - Add consistent AI analysis/reference prototype sections.
+- `docs/frontend/design-system.md` - Document frontend-first prototype rules.
+- `README.md` - Mention Stage 2.5 frontend prototype status.
+- `docs/superpowers/plans/2026-07-06-stage-2-5-global-frontend-prototype.md` - Mark checkboxes during execution.
+
+Do not modify backend files in this stage.
+
+---
+
+### Task 1: Prototype Contracts And Shared App Components
+
+**Files:**
+- Create: `frontend/src/features/prototype/types.ts`
+- Create: `frontend/src/features/prototype/mockData.ts`
+- Create: `frontend/src/components/app/AppMetricCard.tsx`
+- Create: `frontend/src/components/app/AppRiskBadge.tsx`
+- Create: `frontend/src/components/app/AppTraceTimeline.tsx`
+- Create: `frontend/src/components/app/AppReferenceCard.tsx`
+
+- [ ] **Step 1: Create typed mock contracts**
+
+Create `frontend/src/features/prototype/types.ts`:
+
+```ts
+export type PrototypeStatus = 'success' | 'warning' | 'danger' | 'muted'
+
+export type DashboardMetric = {
+ id: string
+ label: string
+ value: string
+ helper: string
+ status: PrototypeStatus
+}
+
+export type ModelProvider = {
+ id: number
+ name: string
+ provider_type: 'openai_compatible' | 'azure_openai' | 'local'
+ base_url: string
+ enabled: boolean
+ model_count: number
+ default_chat_model: string
+ default_embedding_model: string
+ last_test_status: 'passed' | 'failed' | 'untested'
+ updated_at: string
+}
+
+export type ModelTestResult = {
+ id: number
+ provider_name: string
+ model_name: string
+ prompt: string
+ response: string
+ latency_ms: number
+ input_tokens: number
+ output_tokens: number
+ status: 'success' | 'failed'
+ error_message: string
+}
+
+export type AgentDefinition = {
+ id: number
+ name: string
+ agent_type: 'ticket_create' | 'support_analysis' | 'knowledge_distill'
+ description: string
+ enabled: boolean
+ model_name: string
+ knowledge_scope: string
+ tool_scope: string
+ requires_human_confirm: boolean
+ updated_at: string
+}
+
+export type AgentStepType = 'retrieval' | 'skill' | 'model_call' | 'tool_call' | 'human_confirm' | 'artifact'
+
+export type AgentStep = {
+ id: number
+ step_type: AgentStepType
+ step_name: string
+ status: 'success' | 'failed' | 'waiting_confirm' | 'skipped'
+ input_summary: string
+ output_summary: string
+ latency_ms: number
+ created_at: string
+}
+
+export type AgentRun = {
+ id: number
+ agent_name: string
+ run_type: 'ticket_create' | 'support_analysis' | 'knowledge_distill' | 'test'
+ ticket_no: string
+ status: 'running' | 'success' | 'failed' | 'waiting_confirm'
+ trigger_user: string
+ duration_ms: number
+ created_at: string
+ output_summary: string
+ steps: AgentStep[]
+}
+
+export type SkillDefinition = {
+ id: number
+ name: string
+ scenario: 'field_extract' | 'missing_info' | 'solution_recommend' | 'reply_draft' | 'knowledge_draft'
+ description: string
+ enabled: boolean
+ version: string
+ prompt_template: string
+ input_schema: string
+ output_schema: string
+ updated_at: string
+}
+
+export type McpServer = {
+ id: number
+ name: string
+ server_url: string
+ auth_type: 'none' | 'token' | 'basic'
+ connection_state: 'connected' | 'disconnected' | 'error'
+ tool_count: number
+ last_sync_at: string
+}
+
+export type McpTool = {
+ id: number
+ server_id: number
+ name: string
+ description: string
+ risk_level: 'low' | 'medium' | 'high'
+ enabled: boolean
+ requires_human_confirm: boolean
+}
+
+export type ToolCall = {
+ id: number
+ tool_name: string
+ run_id: number
+ input_summary: string
+ output_summary: string
+ status: 'success' | 'failed' | 'blocked' | 'waiting_confirm'
+ confirmed_by: string
+ created_at: string
+}
+
+export type KnowledgeReference = {
+ id: number
+ title: string
+ source_type: 'knowledge_item' | 'solution' | 'document' | 'historical_ticket'
+ content: string
+ score: number
+}
+```
+
+- [ ] **Step 2: Create realistic mock data**
+
+Create `frontend/src/features/prototype/mockData.ts`:
+
+```ts
+import type {
+ AgentDefinition,
+ AgentRun,
+ DashboardMetric,
+ KnowledgeReference,
+ McpServer,
+ McpTool,
+ ModelProvider,
+ ModelTestResult,
+ SkillDefinition,
+ ToolCall
+} from './types'
+
+export const dashboardMetrics: DashboardMetric[] = [
+ { id: 'pending', label: '待处理工单', value: '18', helper: '其中 6 个超过 4 小时未更新', status: 'warning' },
+ { id: 'knowledge', label: '知识命中率', value: '72%', helper: '近 7 天解决方案和知识引用', status: 'success' },
+ { id: 'agent', label: 'Agent 运行', value: '46', helper: '3 次等待人工确认', status: 'muted' },
+ { id: 'risk', label: '高风险工具', value: '2', helper: '均处于人工确认模式', status: 'danger' }
+]
+
+export const modelProviders: ModelProvider[] = [
+ {
+ id: 1,
+ name: 'OpenAI 兼容渠道',
+ provider_type: 'openai_compatible',
+ base_url: 'https://api.example.com/v1',
+ enabled: true,
+ model_count: 4,
+ default_chat_model: 'gpt-4.1',
+ default_embedding_model: 'text-embedding-3-large',
+ last_test_status: 'passed',
+ updated_at: '2026-07-06T09:20:00Z'
+ },
+ {
+ id: 2,
+ name: '本地推理服务',
+ provider_type: 'local',
+ base_url: 'http://model-gateway.internal/v1',
+ enabled: true,
+ model_count: 2,
+ default_chat_model: 'qwen-support-32b',
+ default_embedding_model: 'bge-m3',
+ last_test_status: 'failed',
+ updated_at: '2026-07-05T16:10:00Z'
+ }
+]
+
+export const modelTestResults: ModelTestResult[] = [
+ {
+ id: 1,
+ provider_name: 'OpenAI 兼容渠道',
+ model_name: 'gpt-4.1',
+ prompt: '客户反馈税局采集进度长时间不更新,请给出排查建议。',
+ response: '建议先查询采集任务状态和 Python 日志,确认税局接口是否返回超时或限流,再向客户说明任务仍在采集中。',
+ latency_ms: 1860,
+ input_tokens: 62,
+ output_tokens: 88,
+ status: 'success',
+ error_message: ''
+ },
+ {
+ id: 2,
+ provider_name: '本地推理服务',
+ model_name: 'qwen-support-32b',
+ prompt: '客户反馈税局采集进度长时间不更新,请给出排查建议。',
+ response: '',
+ latency_ms: 30000,
+ input_tokens: 62,
+ output_tokens: 0,
+ status: 'failed',
+ error_message: '模型服务响应超时'
+ }
+]
+
+export const agents: AgentDefinition[] = [
+ {
+ id: 1,
+ name: '建单辅助 Agent',
+ agent_type: 'ticket_create',
+ description: '从自然语言和截图中提取工单字段,并生成缺失信息追问。',
+ enabled: true,
+ model_name: 'gpt-4.1',
+ knowledge_scope: '工单分类、历史相似问题',
+ tool_scope: '只读知识检索',
+ requires_human_confirm: true,
+ updated_at: '2026-07-06T08:30:00Z'
+ },
+ {
+ id: 2,
+ name: '支持分析 Agent',
+ agent_type: 'support_analysis',
+ description: '结合工单上下文、知识库和解决方案生成排查建议。',
+ enabled: true,
+ model_name: 'qwen-support-32b',
+ knowledge_scope: '全部已发布知识库',
+ tool_scope: '日志查询、监控查询',
+ requires_human_confirm: true,
+ updated_at: '2026-07-06T10:05:00Z'
+ }
+]
+
+export const agentRuns: AgentRun[] = [
+ {
+ id: 1001,
+ agent_name: '支持分析 Agent',
+ run_type: 'support_analysis',
+ ticket_no: 'TK202607060018',
+ status: 'waiting_confirm',
+ trigger_user: '技术支持-张敏',
+ duration_ms: 4200,
+ created_at: '2026-07-06T10:12:00Z',
+ output_summary: '已生成排查步骤和客户回复草稿,等待人工确认是否采纳。',
+ steps: [
+ {
+ id: 1,
+ step_type: 'retrieval',
+ step_name: '检索相似知识',
+ status: 'success',
+ input_summary: '查询:税局采集进度长时间不更新',
+ output_summary: '命中 3 条知识引用和 1 个解决方案',
+ latency_ms: 120,
+ created_at: '2026-07-06T10:12:01Z'
+ },
+ {
+ id: 2,
+ step_type: 'model_call',
+ step_name: '生成支持分析',
+ status: 'success',
+ input_summary: '工单详情、知识引用、解决方案',
+ output_summary: '输出可能原因、排查步骤、客户回复草稿',
+ latency_ms: 1830,
+ created_at: '2026-07-06T10:12:03Z'
+ },
+ {
+ id: 3,
+ step_type: 'human_confirm',
+ step_name: '等待人工确认',
+ status: 'waiting_confirm',
+ input_summary: '是否采纳客户回复草稿',
+ output_summary: '等待处理人确认',
+ latency_ms: 0,
+ created_at: '2026-07-06T10:12:05Z'
+ }
+ ]
+ }
+]
+
+export const skills: SkillDefinition[] = [
+ {
+ id: 1,
+ name: '字段抽取',
+ scenario: 'field_extract',
+ description: '从用户描述中抽取标题、系统、环境、优先级和问题分类。',
+ enabled: true,
+ version: 'v1.0.0',
+ prompt_template: '你是技术支持建单助手,请从用户描述中抽取结构化工单字段。',
+ input_schema: '{ "description": "string", "attachments": "array" }',
+ output_schema: '{ "title": "string", "category": "string", "priority": "string" }',
+ updated_at: '2026-07-06T09:00:00Z'
+ },
+ {
+ id: 2,
+ name: '客户回复草稿',
+ scenario: 'reply_draft',
+ description: '根据处理结论生成面向客户的简洁回复。',
+ enabled: true,
+ version: 'v1.1.0',
+ prompt_template: '请根据工单处理记录生成礼貌、准确、可发送给客户的回复。',
+ input_schema: '{ "ticket": "object", "resolution": "string" }',
+ output_schema: '{ "reply": "string", "risk_note": "string" }',
+ updated_at: '2026-07-05T18:30:00Z'
+ }
+]
+
+export const mcpServers: McpServer[] = [
+ {
+ id: 1,
+ name: '日志平台 MCP',
+ server_url: 'https://logs.internal/mcp',
+ auth_type: 'token',
+ connection_state: 'connected',
+ tool_count: 6,
+ last_sync_at: '2026-07-06T08:50:00Z'
+ },
+ {
+ id: 2,
+ name: '配置中心 MCP',
+ server_url: 'https://config.internal/mcp',
+ auth_type: 'token',
+ connection_state: 'error',
+ tool_count: 4,
+ last_sync_at: '2026-07-05T14:20:00Z'
+ }
+]
+
+export const mcpTools: McpTool[] = [
+ {
+ id: 1,
+ server_id: 1,
+ name: 'search_python_logs',
+ description: '按工单编号、客户名称或任务 ID 查询 Python 服务日志。',
+ risk_level: 'medium',
+ enabled: true,
+ requires_human_confirm: false
+ },
+ {
+ id: 2,
+ server_id: 2,
+ name: 'restart_collector_job',
+ description: '重启指定采集任务,仅允许人工确认后执行。',
+ risk_level: 'high',
+ enabled: false,
+ requires_human_confirm: true
+ }
+]
+
+export const toolCalls: ToolCall[] = [
+ {
+ id: 1,
+ tool_name: 'search_python_logs',
+ run_id: 1001,
+ input_summary: '查询任务 TASK-20260706-18 的最近 30 分钟日志',
+ output_summary: '发现税局接口连续 3 次超时',
+ status: 'success',
+ confirmed_by: '',
+ created_at: '2026-07-06T10:12:02Z'
+ },
+ {
+ id: 2,
+ tool_name: 'restart_collector_job',
+ run_id: 1001,
+ input_summary: '尝试重启采集任务 TASK-20260706-18',
+ output_summary: '高风险工具已阻止,需人工确认',
+ status: 'blocked',
+ confirmed_by: '',
+ created_at: '2026-07-06T10:12:04Z'
+ }
+]
+
+export const knowledgeReferences: KnowledgeReference[] = [
+ {
+ id: 1,
+ title: '税局采集进度查询',
+ source_type: 'knowledge_item',
+ content: '采集进度长时间不更新时,先查询 Python 日志确认税局接口状态,再判断是否需要客户等待。',
+ score: 0.91
+ },
+ {
+ id: 2,
+ title: '税局不稳定采集处理中',
+ source_type: 'solution',
+ content: '回复客户税局服务不稳定,当前任务仍在采集中,稍后复查结果。',
+ score: 0.88
+ }
+]
+```
+
+- [ ] **Step 3: Create `AppMetricCard`**
+
+Create `frontend/src/components/app/AppMetricCard.tsx`:
+
+```tsx
+import type * as React from 'react'
+
+import { Badge } from '@/components/ui/badge'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+
+type AppMetricCardProps = {
+ label: string
+ value: string | number
+ helper?: string
+ icon?: React.ReactNode
+ status?: 'success' | 'warning' | 'danger' | 'muted'
+}
+
+const statusLabels = {
+ danger: '需关注',
+ muted: '正常',
+ success: '良好',
+ warning: '预警'
+}
+
+export function AppMetricCard({ label, value, helper, icon, status = 'muted' }: AppMetricCardProps) {
+ return (
+
+
+ {label}
+ {icon}
+
+
+
+
{value}
+
{statusLabels[status]}
+
+ {helper ? {helper}
: null}
+
+
+ )
+}
+```
+
+- [ ] **Step 4: Create `AppRiskBadge`**
+
+Create `frontend/src/components/app/AppRiskBadge.tsx`:
+
+```tsx
+import { Badge } from '@/components/ui/badge'
+
+type AppRiskBadgeProps = {
+ risk: 'low' | 'medium' | 'high'
+}
+
+const riskLabels = {
+ high: '高风险',
+ low: '低风险',
+ medium: '中风险'
+}
+
+export function AppRiskBadge({ risk }: AppRiskBadgeProps) {
+ return {riskLabels[risk]}
+}
+```
+
+- [ ] **Step 5: Create `AppTraceTimeline`**
+
+Create `frontend/src/components/app/AppTraceTimeline.tsx`:
+
+```tsx
+import { CheckCircle2, CircleDashed, Clock, XCircle } from 'lucide-react'
+
+import { Badge } from '@/components/ui/badge'
+import { Card, CardContent } from '@/components/ui/card'
+import { cn } from '@/lib/utils'
+
+export type AppTraceTimelineItem = {
+ id: number | string
+ title: string
+ type: string
+ status: 'success' | 'failed' | 'waiting_confirm' | 'skipped' | 'running'
+ input: string
+ output: string
+ latencyMs?: number
+}
+
+const statusLabels = {
+ failed: '失败',
+ running: '运行中',
+ skipped: '已跳过',
+ success: '成功',
+ waiting_confirm: '待确认'
+}
+
+function getStatusIcon(status: AppTraceTimelineItem['status']) {
+ if (status === 'success') return CheckCircle2
+ if (status === 'failed') return XCircle
+ if (status === 'waiting_confirm') return Clock
+ return CircleDashed
+}
+
+export function AppTraceTimeline({ items }: { items: AppTraceTimelineItem[] }) {
+ return (
+
+ {items.map((item, index) => {
+ const Icon = getStatusIcon(item.status)
+ return (
+
+
+
+
+
+
+
+
+
{index + 1}. {item.title}
+
{item.type}
+
+
+
+ {statusLabels[item.status]}
+ {typeof item.latencyMs === 'number' ? {item.latencyMs} ms : null}
+
+
+
+
+
+ )
+ })}
+
+ )
+}
+```
+
+- [ ] **Step 6: Create `AppReferenceCard`**
+
+Create `frontend/src/components/app/AppReferenceCard.tsx`:
+
+```tsx
+import { Badge } from '@/components/ui/badge'
+import { Card, CardContent } from '@/components/ui/card'
+
+type AppReferenceCardProps = {
+ title: string
+ sourceType: string
+ content: string
+ score?: number
+}
+
+const sourceLabels: Record = {
+ document: '文档',
+ historical_ticket: '历史工单',
+ knowledge_item: '知识条目',
+ solution: '解决方案'
+}
+
+export function AppReferenceCard({ title, sourceType, content, score }: AppReferenceCardProps) {
+ return (
+
+
+
+
{title}
+
{sourceLabels[sourceType] ?? sourceType}
+ {typeof score === 'number' ?
匹配度 {score.toFixed(2)} : null}
+
+ {content}
+
+
+ )
+}
+```
+
+- [ ] **Step 7: Verify Task 1**
+
+Run:
+
+```powershell
+npm run typecheck
+```
+
+Expected: TypeScript completes without errors.
+
+- [ ] **Step 8: Commit Task 1**
+
+Run:
+
+```powershell
+git add frontend/src/features/prototype frontend/src/components/app/AppMetricCard.tsx frontend/src/components/app/AppRiskBadge.tsx frontend/src/components/app/AppTraceTimeline.tsx frontend/src/components/app/AppReferenceCard.tsx
+git commit -m "feat: add frontend prototype contracts"
+```
+
+---
+
+### Task 2: Global Navigation, Dashboard, And Workbench Overview
+
+**Files:**
+- Create: `frontend/src/features/dashboard/DashboardPage.tsx`
+- Modify: `frontend/src/app/router.tsx`
+- Modify: `frontend/src/components/app/AppSidebar.tsx`
+- Modify: `frontend/src/features/workbench/WorkbenchPage.tsx`
+
+- [ ] **Step 1: Create dashboard page**
+
+Create `frontend/src/features/dashboard/DashboardPage.tsx`:
+
+```tsx
+import { Activity, Bot, Database, ShieldAlert } from 'lucide-react'
+
+import { AppMetricCard } from '@/components/app/AppMetricCard'
+import { AppPage } from '@/components/app/AppPage'
+import { AppPageHeader } from '@/components/app/AppPageHeader'
+import { AppSection } from '@/components/app/AppSection'
+import { Badge } from '@/components/ui/badge'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+import { dashboardMetrics, agentRuns, mcpTools, modelProviders } from '@/features/prototype/mockData'
+
+const icons = [Activity, Database, Bot, ShieldAlert]
+
+export function DashboardPage() {
+ return (
+
+
+
+
+ {dashboardMetrics.map((metric, index) => {
+ const Icon = icons[index] ?? Activity
+ return
} />
+ })}
+
+
+
+
+
+ {['税局采集进度', '登录失败', '数据同步延迟', '发票下载异常'].map((name, index) => (
+
+
+ {name}
+ {32 - index * 6} 单
+
+
+
+ ))}
+
+
+
+
+
+
+ 模型健康
+
+
+ {modelProviders.map((provider) => (
+
+ {provider.name}
+
+ {provider.last_test_status === 'passed' ? '通过' : '失败'}
+
+
+ ))}
+
+
+
+
+
+ 待确认事项
+
+
+ Agent 待确认:{agentRuns.filter((run) => run.status === 'waiting_confirm').length} 项
+ 高风险工具:{mcpTools.filter((tool) => tool.risk_level === 'high').length} 个
+
+
+
+
+
+ )
+}
+```
+
+- [ ] **Step 2: Add dashboard route**
+
+Modify `frontend/src/app/router.tsx`:
+
+```tsx
+import { DashboardPage } from '@/features/dashboard/DashboardPage'
+```
+
+Add before the workbench route:
+
+```tsx
+ if (route === '/dashboard') {
+ return
+ }
+```
+
+- [ ] **Step 3: Expand built-in sidebar prototype navigation**
+
+Modify `frontend/src/components/app/AppSidebar.tsx`:
+
+Add lucide imports if absent:
+
+```tsx
+ Activity,
+ BrainCircuit,
+ Boxes,
+ Cpu,
+ FlaskConical,
+ PlugZap,
+ Wrench
+```
+
+Add icon mappings:
+
+```tsx
+ activity: Activity,
+ agents: BrainCircuit,
+ boxes: Boxes,
+ cpu: Cpu,
+ flask: FlaskConical,
+ plug: PlugZap,
+ wrench: Wrench
+```
+
+Replace the current single built-in knowledge group with a `prototypeNavGroups` array:
+
+```tsx
+const prototypeNavGroups: AuthMenu[] = [
+ {
+ id: -100,
+ code: 'prototype_workspace',
+ title: '工作台',
+ path: '#/',
+ icon: 'home',
+ permission_code: 'workspace.view',
+ is_visible: true,
+ is_enabled: true,
+ children: [
+ { id: -101, code: 'workspace_today', title: '今日工作台', path: '#/', icon: 'home', permission_code: 'workspace.view', is_visible: true, is_enabled: true, children: [] },
+ { id: -102, code: 'workspace_dashboard', title: '运营总览', path: '#/dashboard', icon: 'activity', permission_code: 'dashboard.view', is_visible: true, is_enabled: true, children: [] }
+ ]
+ },
+ {
+ id: -200,
+ code: 'prototype_knowledge',
+ title: '知识与方案',
+ path: '#/knowledge',
+ icon: 'book_open',
+ permission_code: 'knowledge.view',
+ is_visible: true,
+ is_enabled: true,
+ children: [
+ { id: -201, code: 'knowledge_bases', title: '知识库', path: '#/knowledge', icon: 'book_open', permission_code: 'knowledge.view', is_visible: true, is_enabled: true, children: [] },
+ { id: -202, code: 'knowledge_search', title: '知识检索', path: '#/knowledge/search', icon: 'search', permission_code: 'knowledge.view', is_visible: true, is_enabled: true, children: [] },
+ { id: -203, code: 'solutions', title: '解决方案', path: '#/solutions', icon: 'library', permission_code: 'solutions.view', is_visible: true, is_enabled: true, children: [] }
+ ]
+ },
+ {
+ id: -300,
+ code: 'prototype_agents',
+ title: 'Agent',
+ path: '#/agents',
+ icon: 'agents',
+ permission_code: 'agents.view',
+ is_visible: true,
+ is_enabled: true,
+ children: [
+ { id: -301, code: 'agents', title: 'Agent 配置', path: '#/agents', icon: 'agents', permission_code: 'agents.view', is_visible: true, is_enabled: true, children: [] },
+ { id: -302, code: 'agent_runs', title: '运行记录', path: '#/agents/runs', icon: 'activity', permission_code: 'agents.view', is_visible: true, is_enabled: true, children: [] },
+ { id: -303, code: 'skills', title: 'Skill 配置', path: '#/skills', icon: 'wrench', permission_code: 'skills.view', is_visible: true, is_enabled: true, children: [] }
+ ]
+ },
+ {
+ id: -400,
+ code: 'prototype_model_tools',
+ title: '模型与工具',
+ path: '#/modelhub/providers',
+ icon: 'cpu',
+ permission_code: 'modelhub.view',
+ is_visible: true,
+ is_enabled: true,
+ children: [
+ { id: -401, code: 'model_providers', title: '模型供应商', path: '#/modelhub/providers', icon: 'cpu', permission_code: 'modelhub.view', is_visible: true, is_enabled: true, children: [] },
+ { id: -402, code: 'model_testing', title: '模型测试', path: '#/modelhub/testing', icon: 'flask', permission_code: 'modelhub.view', is_visible: true, is_enabled: true, children: [] },
+ { id: -403, code: 'mcp_tools', title: 'MCP 工具', path: '#/tools/mcp', icon: 'plug', permission_code: 'tools.view', is_visible: true, is_enabled: true, children: [] }
+ ]
+ }
+]
+```
+
+Then derive `groups` like this:
+
+```tsx
+ const menuGroups = (user?.menus ?? []).filter((menu) => menu.is_visible && menu.is_enabled)
+ const existingPaths = new Set(menuGroups.flatMap((group) => visibleChildren(group).map((item) => item.path)))
+ const supplementalGroups = prototypeNavGroups
+ .map((group) => ({
+ ...group,
+ children: group.children.filter((item) => !existingPaths.has(item.path))
+ }))
+ .filter((group) => group.children.length > 0)
+ const groups = [...menuGroups, ...supplementalGroups]
+```
+
+- [ ] **Step 4: Enhance workbench overview**
+
+Modify `frontend/src/features/workbench/WorkbenchPage.tsx`:
+
+Add imports:
+
+```tsx
+import { Bot, Database, ShieldAlert } from 'lucide-react'
+import { AppMetricCard } from '@/components/app/AppMetricCard'
+import { dashboardMetrics, agentRuns, mcpTools } from '@/features/prototype/mockData'
+```
+
+Replace the current metric card grid with:
+
+```tsx
+
+ {metrics.map((metric) => (
+
+ ))}
+
+
+
+
} />
+
run.status === 'waiting_confirm').length} helper="AI 建议默认等待人工确认" status="warning" icon={} />
+ tool.risk_level === 'high').length} helper="高风险工具不会自动执行" status="danger" icon={} />
+
+```
+
+- [ ] **Step 5: Verify Task 2**
+
+Run:
+
+```powershell
+npm run typecheck
+npm run build
+```
+
+Expected: both commands pass.
+
+- [ ] **Step 6: Commit Task 2**
+
+Run:
+
+```powershell
+git add frontend/src/features/dashboard frontend/src/app/router.tsx frontend/src/components/app/AppSidebar.tsx frontend/src/features/workbench/WorkbenchPage.tsx
+git commit -m "feat: add prototype dashboard navigation"
+```
+
+---
+
+### Task 3: Model Hub Prototype Pages
+
+**Files:**
+- Create: `frontend/src/features/modelhub/ModelProviderPage.tsx`
+- Create: `frontend/src/features/modelhub/ModelTestingPage.tsx`
+- Modify: `frontend/src/app/router.tsx`
+
+- [ ] **Step 1: Create model provider page**
+
+Create `frontend/src/features/modelhub/ModelProviderPage.tsx` with:
+
+```tsx
+import * as React from 'react'
+import { Plus, ServerCog } from 'lucide-react'
+
+import { AppDataTable, type AppDataTableColumn } from '@/components/app/AppDataTable'
+import { AppField } from '@/components/app/AppField'
+import { AppPage } from '@/components/app/AppPage'
+import { AppPageHeader } from '@/components/app/AppPageHeader'
+import { Badge } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
+import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from '@/components/ui/dialog'
+import { Input } from '@/components/ui/input'
+import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
+import { formatDateTime } from '@/lib/format'
+import { modelProviders } from '@/features/prototype/mockData'
+import type { ModelProvider } from '@/features/prototype/types'
+
+const columns: AppDataTableColumn[] = [
+ { key: 'name', header: '供应商', cell: (provider) => {provider.name} },
+ { key: 'type', header: '类型', cell: (provider) => {provider.provider_type === 'local' ? '本地模型' : 'OpenAI 兼容'} },
+ { key: 'models', header: '模型数量', cell: (provider) => provider.model_count },
+ { key: 'default', header: '默认模型', cell: (provider) => {provider.default_chat_model} },
+ { key: 'status', header: '测试状态', cell: (provider) => {provider.last_test_status === 'passed' ? '通过' : provider.last_test_status === 'failed' ? '失败' : '未测试'} },
+ { key: 'updated_at', header: '更新时间', cell: (provider) => {formatDateTime(provider.updated_at)} }
+]
+
+export function ModelProviderPage() {
+ const [open, setOpen] = React.useState(false)
+
+ return (
+
+
+
+
+
+
+
+ 新增模型供应商
+
+
+
+
+ }
+ />
+ provider.id} emptyTitle="暂无模型供应商" />
+
+ )
+}
+```
+
+- [ ] **Step 2: Create model testing page**
+
+Create `frontend/src/features/modelhub/ModelTestingPage.tsx` with prompt input, model selector, parameter selector, and result cards:
+
+```tsx
+import * as React from 'react'
+import { FlaskConical, Play } from 'lucide-react'
+
+import { AppField } from '@/components/app/AppField'
+import { AppPage } from '@/components/app/AppPage'
+import { AppPageHeader } from '@/components/app/AppPageHeader'
+import { AppSection } from '@/components/app/AppSection'
+import { Badge } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+import { Select, SelectContent, SelectGroup, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select'
+import { Textarea } from '@/components/ui/textarea'
+import { modelProviders, modelTestResults } from '@/features/prototype/mockData'
+
+export function ModelTestingPage() {
+ const [running, setRunning] = React.useState(false)
+
+ function runMockTest() {
+ setRunning(true)
+ window.setTimeout(() => setRunning(false), 600)
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {modelTestResults.map((result) => (
+
+
+ {result.provider_name} / {result.model_name}
+ {result.status === 'success' ? '成功' : '失败'}
+
+
+ {result.status === 'success' ? {result.response}
: {result.error_message}
}
+
+ {result.latency_ms} ms
+ 输入 {result.input_tokens}
+ 输出 {result.output_tokens}
+
+
+
+ ))}
+
+
+ )
+}
+```
+
+- [ ] **Step 3: Wire model routes**
+
+Modify `frontend/src/app/router.tsx`:
+
+```tsx
+import { ModelProviderPage } from '@/features/modelhub/ModelProviderPage'
+import { ModelTestingPage } from '@/features/modelhub/ModelTestingPage'
+```
+
+Add routes:
+
+```tsx
+ if (route === '/modelhub/providers') {
+ return
+ }
+
+ if (route === '/modelhub/testing') {
+ return
+ }
+```
+
+- [ ] **Step 4: Verify and commit Task 3**
+
+Run:
+
+```powershell
+npm run typecheck
+npm run build
+```
+
+Expected: both pass.
+
+Commit:
+
+```powershell
+git add frontend/src/features/modelhub frontend/src/app/router.tsx
+git commit -m "feat: add model hub prototype pages"
+```
+
+---
+
+### Task 4: Agent Prototype Pages And Trace Detail
+
+**Files:**
+- Create: `frontend/src/features/agents/AgentListPage.tsx`
+- Create: `frontend/src/features/agents/AgentRunsPage.tsx`
+- Create: `frontend/src/features/agents/AgentRunDetailPage.tsx`
+- Modify: `frontend/src/app/router.tsx`
+
+- [ ] **Step 1: Create Agent list page**
+
+Create `frontend/src/features/agents/AgentListPage.tsx` with `AppDataTable`, `Tabs`, and Chinese Agent metadata. Use `agents` from `mockData.ts`. Required columns: `Agent`, `类型`, `模型`, `知识范围`, `工具范围`, `人工确认`, `状态`.
+
+Implementation pattern:
+
+```tsx
+import { AppDataTable, type AppDataTableColumn } from '@/components/app/AppDataTable'
+import { AppPage } from '@/components/app/AppPage'
+import { AppPageHeader } from '@/components/app/AppPageHeader'
+import { Badge } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
+import { agents } from '@/features/prototype/mockData'
+import type { AgentDefinition } from '@/features/prototype/types'
+
+const typeLabels = {
+ knowledge_distill: '知识沉淀',
+ support_analysis: '支持分析',
+ ticket_create: '建单辅助'
+}
+
+const columns: AppDataTableColumn[] = [
+ { key: 'name', header: 'Agent', cell: (agent) => {agent.name} },
+ { key: 'type', header: '类型', cell: (agent) => {typeLabels[agent.agent_type]} },
+ { key: 'model', header: '模型', cell: (agent) => agent.model_name },
+ { key: 'knowledge', header: '知识范围', cell: (agent) => {agent.knowledge_scope} },
+ { key: 'tools', header: '工具范围', cell: (agent) => {agent.tool_scope} },
+ { key: 'confirm', header: '人工确认', cell: (agent) => {agent.requires_human_confirm ? '需要' : '不需要'} },
+ { key: 'enabled', header: '状态', cell: (agent) => {agent.enabled ? '启用' : '停用'} }
+]
+
+export function AgentListPage() {
+ return (
+
+ (window.location.hash = '/agents/runs')}>查看运行记录} />
+ agent.id} emptyTitle="暂无 Agent" />
+
+ )
+}
+```
+
+- [ ] **Step 2: Create Agent runs page**
+
+Create `frontend/src/features/agents/AgentRunsPage.tsx`:
+
+```tsx
+import { AppDataTable, type AppDataTableColumn } from '@/components/app/AppDataTable'
+import { AppPage } from '@/components/app/AppPage'
+import { AppPageHeader } from '@/components/app/AppPageHeader'
+import { Badge } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
+import { formatDateTime } from '@/lib/format'
+import { agentRuns } from '@/features/prototype/mockData'
+import type { AgentRun } from '@/features/prototype/types'
+
+const statusLabels = {
+ failed: '失败',
+ running: '运行中',
+ success: '成功',
+ waiting_confirm: '待确认'
+}
+
+const columns: AppDataTableColumn[] = [
+ { key: 'id', header: '运行编号', cell: (run) => #{run.id} },
+ { key: 'agent', header: 'Agent', cell: (run) => run.agent_name },
+ { key: 'ticket', header: '工单', cell: (run) => {run.ticket_no} },
+ { key: 'status', header: '状态', cell: (run) => {statusLabels[run.status]} },
+ { key: 'user', header: '触发人', cell: (run) => run.trigger_user },
+ { key: 'duration', header: '耗时', cell: (run) => `${run.duration_ms} ms` },
+ { key: 'created_at', header: '创建时间', cell: (run) => {formatDateTime(run.created_at)} }
+]
+
+export function AgentRunsPage() {
+ return (
+
+ (window.location.hash = '/agents')}>返回配置} />
+ run.id}
+ emptyTitle="暂无运行记录"
+ onRowClick={(run) => (window.location.hash = `/agents/runs/${run.id}`)}
+ />
+
+ )
+}
+```
+
+- [ ] **Step 3: Create Agent run detail page**
+
+Create `frontend/src/features/agents/AgentRunDetailPage.tsx`:
+
+```tsx
+import { AppPage } from '@/components/app/AppPage'
+import { AppPageHeader } from '@/components/app/AppPageHeader'
+import { AppReferenceCard } from '@/components/app/AppReferenceCard'
+import { AppSection } from '@/components/app/AppSection'
+import { AppTraceTimeline } from '@/components/app/AppTraceTimeline'
+import { Badge } from '@/components/ui/badge'
+import { agentRuns, knowledgeReferences } from '@/features/prototype/mockData'
+
+export function AgentRunDetailPage({ runId }: { runId: number }) {
+ const run = agentRuns.find((item) => item.id === runId) ?? agentRuns[0]
+
+ return (
+
+ {run.status === 'waiting_confirm' ? '待确认' : '已完成'}} description={run.output_summary} />
+
+
+ ({
+ id: step.id,
+ title: step.step_name,
+ type: step.step_type,
+ status: step.status,
+ input: step.input_summary,
+ output: step.output_summary,
+ latencyMs: step.latency_ms
+ }))}
+ />
+
+
+
+ {knowledgeReferences.map((reference) => (
+
+ ))}
+
+
+
+
+ )
+}
+```
+
+- [ ] **Step 4: Wire Agent routes**
+
+Modify `frontend/src/app/router.tsx`:
+
+```tsx
+import { AgentListPage } from '@/features/agents/AgentListPage'
+import { AgentRunDetailPage } from '@/features/agents/AgentRunDetailPage'
+import { AgentRunsPage } from '@/features/agents/AgentRunsPage'
+```
+
+Add routes:
+
+```tsx
+ if (route === '/agents') {
+ return
+ }
+
+ if (route === '/agents/runs') {
+ return
+ }
+
+ const agentRunMatch = route.match(/^\/agents\/runs\/(\d+)$/)
+ if (agentRunMatch) {
+ return
+ }
+```
+
+- [ ] **Step 5: Verify and commit Task 4**
+
+Run:
+
+```powershell
+npm run typecheck
+npm run build
+```
+
+Expected: both pass.
+
+Commit:
+
+```powershell
+git add frontend/src/features/agents frontend/src/app/router.tsx
+git commit -m "feat: add agent prototype pages"
+```
+
+---
+
+### Task 5: Skill And MCP Prototype Pages
+
+**Files:**
+- Create: `frontend/src/features/skills/SkillListPage.tsx`
+- Create: `frontend/src/features/tools/McpToolsPage.tsx`
+- Modify: `frontend/src/app/router.tsx`
+
+- [ ] **Step 1: Create Skill list and edit surface**
+
+Create `frontend/src/features/skills/SkillListPage.tsx`:
+
+```tsx
+import * as React from 'react'
+import { Play } from 'lucide-react'
+
+import { AppDataTable, type AppDataTableColumn } from '@/components/app/AppDataTable'
+import { AppField } from '@/components/app/AppField'
+import { AppPage } from '@/components/app/AppPage'
+import { AppPageHeader } from '@/components/app/AppPageHeader'
+import { AppSection } from '@/components/app/AppSection'
+import { Badge } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
+import { Textarea } from '@/components/ui/textarea'
+import { formatDateTime } from '@/lib/format'
+import { skills } from '@/features/prototype/mockData'
+import type { SkillDefinition } from '@/features/prototype/types'
+
+const scenarioLabels = {
+ field_extract: '字段抽取',
+ knowledge_draft: '知识草稿',
+ missing_info: '缺失信息追问',
+ reply_draft: '客户回复',
+ solution_recommend: '方案推荐'
+}
+
+const columns: AppDataTableColumn[] = [
+ { key: 'name', header: 'Skill', cell: (skill) => {skill.name} },
+ { key: 'scenario', header: '场景', cell: (skill) => {scenarioLabels[skill.scenario]} },
+ { key: 'version', header: '版本', cell: (skill) => skill.version },
+ { key: 'enabled', header: '状态', cell: (skill) => {skill.enabled ? '启用' : '停用'} },
+ { key: 'updated_at', header: '更新时间', cell: (skill) => {formatDateTime(skill.updated_at)} }
+]
+
+export function SkillListPage() {
+ const [selected, setSelected] = React.useState(skills[0])
+ const [testing, setTesting] = React.useState(false)
+
+ function runMockTest() {
+ setTesting(true)
+ window.setTimeout(() => setTesting(false), 600)
+ }
+
+ return (
+
+
+
+
skill.id} emptyTitle="暂无 Skill" onRowClick={setSelected} />
+
+
+
+ Prompt 模板
+ Schema
+ 测试输入
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+```
+
+- [ ] **Step 2: Create MCP tools page**
+
+Create `frontend/src/features/tools/McpToolsPage.tsx`:
+
+```tsx
+import * as React from 'react'
+import { ShieldAlert } from 'lucide-react'
+
+import { AppDataTable, type AppDataTableColumn } from '@/components/app/AppDataTable'
+import { AppPage } from '@/components/app/AppPage'
+import { AppPageHeader } from '@/components/app/AppPageHeader'
+import { AppRiskBadge } from '@/components/app/AppRiskBadge'
+import { AppSection } from '@/components/app/AppSection'
+import { Badge } from '@/components/ui/badge'
+import { Button } from '@/components/ui/button'
+import { Dialog, DialogContent, DialogHeader, DialogTitle } from '@/components/ui/dialog'
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
+import { formatDateTime } from '@/lib/format'
+import { mcpServers, mcpTools, toolCalls } from '@/features/prototype/mockData'
+import type { McpServer, McpTool, ToolCall } from '@/features/prototype/types'
+
+const serverColumns: AppDataTableColumn[] = [
+ { key: 'name', header: '服务名称', cell: (server) => {server.name} },
+ { key: 'state', header: '连接状态', cell: (server) => {server.connection_state === 'connected' ? '已连接' : server.connection_state === 'error' ? '异常' : '已断开'} },
+ { key: 'auth', header: '认证方式', cell: (server) => server.auth_type },
+ { key: 'tools', header: '工具数量', cell: (server) => server.tool_count },
+ { key: 'last_sync', header: '最后同步', cell: (server) => {formatDateTime(server.last_sync_at)} }
+]
+
+const callColumns: AppDataTableColumn[] = [
+ { key: 'tool', header: '工具', cell: (call) => call.tool_name },
+ { key: 'input', header: '输入摘要', cell: (call) => {call.input_summary} },
+ { key: 'status', header: '状态', cell: (call) => {call.status === 'blocked' ? '已阻止' : call.status === 'success' ? '成功' : call.status} },
+ { key: 'created_at', header: '调用时间', cell: (call) => {formatDateTime(call.created_at)} }
+]
+
+export function McpToolsPage() {
+ const [confirmOpen, setConfirmOpen] = React.useState(false)
+
+ const toolColumns: AppDataTableColumn[] = [
+ { key: 'name', header: '工具名称', cell: (tool) => {tool.name} },
+ { key: 'description', header: '描述', cell: (tool) => {tool.description} },
+ { key: 'risk', header: '风险等级', cell: (tool) => },
+ { key: 'confirm', header: '人工确认', cell: (tool) => {tool.requires_human_confirm ? '需要' : '不需要'} },
+ { key: 'enabled', header: '启用状态', cell: (tool) => {tool.enabled ? '启用' : '停用'} },
+ { key: 'action', header: '操作', cell: (tool) => tool.risk_level === 'high' ? : null }
+ ]
+
+ return (
+
+
+
+
+ 服务
+ 工具
+ 调用审计
+
+ server.id} emptyTitle="暂无 MCP 服务" />
+ tool.id} emptyTitle="暂无 MCP 工具" />
+ call.id} emptyTitle="暂无工具调用" />
+
+
+ 低风险和中风险工具可在授权 Agent 中自动调用;高风险工具不会自动执行,必须保留人工确认入口。
+
+
+
+ )
+}
+```
+
+- [ ] **Step 3: Wire Skill and MCP routes**
+
+Modify `frontend/src/app/router.tsx`:
+
+```tsx
+import { SkillListPage } from '@/features/skills/SkillListPage'
+import { McpToolsPage } from '@/features/tools/McpToolsPage'
+```
+
+Add routes:
+
+```tsx
+ if (route === '/skills') {
+ return
+ }
+
+ if (route === '/tools/mcp') {
+ return
+ }
+```
+
+- [ ] **Step 4: Verify and commit Task 5**
+
+Run:
+
+```powershell
+npm run typecheck
+npm run build
+```
+
+Expected: both pass.
+
+Commit:
+
+```powershell
+git add frontend/src/features/skills frontend/src/features/tools frontend/src/app/router.tsx
+git commit -m "feat: add skill and mcp prototype pages"
+```
+
+---
+
+### Task 6: Ticket AI Panels And Existing Page Alignment
+
+**Files:**
+- Modify: `frontend/src/features/tickets/TicketCreatePage.tsx`
+- Modify: `frontend/src/features/tickets/TicketDetailPage.tsx`
+- Modify: `frontend/src/features/knowledge/KnowledgeSearchPage.tsx`
+- Modify: `frontend/src/features/solutions/SolutionListPage.tsx`
+
+- [ ] **Step 1: Add Agent-assisted creation panel**
+
+Modify `frontend/src/features/tickets/TicketCreatePage.tsx` to add a side or top `AppSection` titled `AI 建单辅助`. The panel must be prototype-only and should not submit AI data.
+
+Required content:
+
+```tsx
+
+
+
后续建单 Agent 会从问题描述、截图和附件中生成字段草稿。
+
AI 仅提供建议,创建工单前仍由用户确认。
+
+
+```
+
+- [ ] **Step 2: Add AI analysis and reference panels to ticket detail**
+
+Modify `frontend/src/features/tickets/TicketDetailPage.tsx` to include:
+
+- `AI 支持分析`
+- `引用来源`
+- `相似工单`
+
+Use `AppReferenceCard` with `knowledgeReferences`. Do not duplicate existing ticket property fields.
+
+- [ ] **Step 3: Align knowledge search cards**
+
+Modify `frontend/src/features/knowledge/KnowledgeSearchPage.tsx` to replace local result card markup with `AppReferenceCard` where possible. Keep real API result data.
+
+- [ ] **Step 4: Align solution list with prototype fields**
+
+Modify `frontend/src/features/solutions/SolutionListPage.tsx` only if needed to show reusable status, usage count, risk note, and scope consistently. Do not change existing API calls.
+
+- [ ] **Step 5: Verify and commit Task 6**
+
+Run:
+
+```powershell
+npm run typecheck
+npm run build
+```
+
+Expected: both pass.
+
+Commit:
+
+```powershell
+git add frontend/src/features/tickets frontend/src/features/knowledge/KnowledgeSearchPage.tsx frontend/src/features/solutions/SolutionListPage.tsx
+git commit -m "feat: align ticket pages with ai prototype"
+```
+
+---
+
+### Task 7: Documentation, Roadmap, And Final Verification
+
+**Files:**
+- Modify: `README.md`
+- Modify: `docs/frontend/design-system.md`
+- Modify: `docs/superpowers/plans/2026-06-30-ai-ticket-platform-implementation-roadmap.md`
+- Modify: `docs/superpowers/plans/2026-07-06-stage-2-5-global-frontend-prototype.md`
+
+- [ ] **Step 1: Update README current status**
+
+Modify `README.md` current status sentence to include:
+
+```text
+frontend-first Stage 2.5 product prototype
+```
+
+- [ ] **Step 2: Update frontend design system**
+
+Add under `Current Core Screens`:
+
+```markdown
+- Stage 2.5 prototype pages are allowed to use typed frontend mock data only for modules whose backend APIs do not exist yet.
+- Mock-backed pages must still use production-like Chinese content, real interaction states, and the same `App*` component layer as API-backed pages.
+- Model, Agent, Skill, and MCP pages are UI contracts for later backend implementation; they must not pretend to persist changes.
+```
+
+- [ ] **Step 3: Update roadmap**
+
+Modify `docs/superpowers/plans/2026-06-30-ai-ticket-platform-implementation-roadmap.md` Stage Breakdown table to include:
+
+```markdown
+| 2.5 | Global frontend product prototype | Build the full frontend product map with typed mock contracts before Stage 3 backend APIs. | Stage 2 | `docs/superpowers/plans/2026-07-06-stage-2-5-global-frontend-prototype.md` |
+```
+
+Place it between Stage 2 and Stage 3.
+
+- [ ] **Step 4: Run final frontend verification**
+
+Run:
+
+```powershell
+npm run typecheck
+npm run build
+```
+
+Expected: both pass.
+
+- [ ] **Step 5: Spot-check route strings**
+
+Run:
+
+```powershell
+rg "route ===|route.match|window.location.hash" frontend\src\app frontend\src\features frontend\src\components\app
+```
+
+Expected: Stage 2.5 routes are present and no obvious typo exists for:
+
+```text
+/dashboard
+/agents
+/agents/runs
+/modelhub/providers
+/modelhub/testing
+/skills
+/tools/mcp
+```
+
+- [ ] **Step 6: Mark this plan complete**
+
+In `docs/superpowers/plans/2026-07-06-stage-2-5-global-frontend-prototype.md`, mark completed task checkboxes as `[x]` after successful execution.
+
+- [ ] **Step 7: Commit documentation and plan completion**
+
+Run:
+
+```powershell
+git add README.md docs/frontend/design-system.md docs/superpowers/plans/2026-06-30-ai-ticket-platform-implementation-roadmap.md docs/superpowers/plans/2026-07-06-stage-2-5-global-frontend-prototype.md
+git commit -m "docs: sync stage 2.5 frontend prototype"
+```
+
+---
+
+## Final Review Checklist
+
+- [ ] Full product map is reachable from sidebar.
+- [ ] `/dashboard` renders.
+- [ ] `/modelhub/providers` renders.
+- [ ] `/modelhub/testing` renders.
+- [ ] `/agents` renders.
+- [ ] `/agents/runs` renders.
+- [ ] `/agents/runs/:id` renders.
+- [ ] `/skills` renders.
+- [ ] `/tools/mcp` renders.
+- [ ] Existing ticket, solution, knowledge, system, and audit routes still render.
+- [ ] Mock-backed pages use typed mock data from `frontend/src/features/prototype`.
+- [ ] All user-facing frontend text is Chinese.
+- [ ] High-risk MCP tooling uses confirmation-oriented UI.
+- [ ] Agent run detail shows execution trace and references.
+- [ ] `npm run typecheck` passes.
+- [ ] `npm run build` passes.
+- [ ] README, design system docs, roadmap, and this plan are updated.