meta:
  page_id: mac-test-workbench
  page_name: Perfowl Mac 测试工作台
  surface: b_end
  page_type: b_dashboard
  anti_slop: pass
  design_plan_ref: design-plan.md
  canvas:
    width: 1440
    height: 900
  figma:
    file_key: ""
    frame_name: "P01-Perfowl-Mac-测试工作台"
    frame_node_id: ""
shell:
  type: none
  title: Perfowl
  nav_items: []
regions:
  - id: titlebar
    type: desktop_titlebar
    label: 标题栏与观测眼状态
    layout: { direction: row, gap: 12, padding: 12 }
    components:
      - { kind: image, label: Perfowl 观测眼 }
      - { kind: text, label: 产品名, sample_value: perfowl }
      - { kind: tag, label: 连接状态, sample_value: 未连接 }
  - id: context_sidebar
    type: device_and_app_context
    label: 设备、App 与详情复合侧栏
    layout: { direction: column, gap: 12, padding: 16 }
    components:
      - { kind: select, label: 请选择设备 }
      - { kind: tab, label: 常规测试 }
      - { kind: tab, label: 深度分析 }
      - { kind: tab, label: 网络测试 }
      - { kind: select, label: 请选择测试应用 }
      - { kind: tab, label: 设备 }
      - { kind: tab, label: 设置 }
      - { kind: tab, label: 关于 }
  - id: device_summary
    type: key_value_table
    label: 设备信息
    layout: { direction: column, gap: 0, padding: 0 }
    components:
      - { kind: table_column, label: 信息, data_key: label }
      - { kind: table_column, label: 数值, data_key: value }
  - id: session_canvas
    type: performance_workspace
    label: 无侵入性能测试画布
    layout: { direction: column, gap: 16, padding: 16 }
    constraints: { primary_actions_max: 1 }
    components:
      - { kind: text, label: 场景名, sample_value: Scene 01 }
      - { kind: button, label: 开始或结束测试, variant: primary, data_key: capture_state }
  - id: screenshot_preview
    type: device_screenshot_preview
    label: 设备截图展示区域
    layout: { direction: column, gap: 8, padding: 12 }
    components:
      - { kind: image, label: 设备屏幕截图, data_key: latest_screenshot, fit: aspect_fit }
      - { kind: empty_state, label: 连接设备后显示屏幕截图 }
      - { kind: text, label: 预览口径, sample_value: 1 秒低频预览，不是实时视频镜像 }
  - id: usb_status_toast
    type: transient_status_overlay
    label: USB 状态
    layout: { direction: column, gap: 12, padding: 20 }
    constraints: { position: screenshot_top_center, visible_after_event_seconds: 1, fade_out: true }
    components:
      - { kind: icon, label: 设备连接或断开图标, data_key: usb_event }
      - { kind: text, label: 设备连接消息, sample_value: 设备 A 已连接 }
      - { kind: text, label: 设备断开消息, sample_value: 设备 A 已断开 }
  - id: live_metric_charts
    type: shared_timeline_metric_panels
    label: 默认指标与多曲线图表
    layout: { direction: column, gap: 12, padding: 16 }
    components:
      - { kind: chart, label: FPS, data_key: fps, series: [fps], default_visible: true }
      - { kind: chart, label: CPU Usage, data_key: cpu_usage, series: [APPCpu, TotalCPU], default_visible: true }
      - { kind: chart, label: Network, data_key: network, series: [Send, Recv], default_visible: true }
      - { kind: quality_state, label: 等待设备或 Unsupported, zero_is_missing: true }
  - id: metric_add_fab
    type: floating_action
    label: 添加指标
    constraints: { position: bottom_trailing, visible_when: device_connected }
    components:
      - { kind: button, label: ＋, variant: primary, action: open_metric_selector }
  - id: metric_selector
    type: metric_selection_overlay
    label: 指标选择面板
    layout: { direction: column, gap: 0, padding: 0 }
    components:
      - { kind: metric_row, label: ScreenShot, support_state: planned, accessory: "采样频率 1 s" }
      - { kind: metric_row, label: "StartupTiming(启动时间)", support_state: unsupported }
      - { kind: metric_row, label: FPS, support_state: supported, selected: true }
      - { kind: metric_row, label: Frame Time, support_state: unsupported }
      - { kind: metric_row, label: CPU Core Usage, support_state: unsupported }
      - { kind: metric_row, label: CPU Usage, support_state: partial, selected: true }
      - { kind: metric_row, label: Memory Usage, support_state: supported }
      - { kind: metric_row, label: GPU Usage, support_state: partial }
      - { kind: metric_row, label: CSwitch, support_state: supported }
      - { kind: metric_row, label: Wakeups, support_state: supported }
      - { kind: metric_row, label: Battery Temperature, support_state: unsupported }
      - { kind: metric_row, label: Disk, support_state: supported }
      - { kind: metric_row, label: Thermal Status, support_state: unsupported }
      - { kind: metric_row, label: Network, support_state: partial, selected: true }
      - { kind: metric_row, label: Battery, support_state: unsupported }
      - { kind: metric_row, label: Energy Usage, support_state: unsupported }
      - { kind: metric_row, label: GPU Counter, support_state: unsupported }
  - id: status_bar
    type: status_and_log_bar
    label: 底部状态与日志入口
    layout: { direction: row, gap: 12, padding: 8 }
    components:
      - { kind: tag, label: 状态, sample_value: 等待设备 }
      - { kind: button, label: 日志, variant: ghost }
states:
  - { id: empty, label: 未连接, description: 引导连接、解锁并信任 iOS 设备 }
  - { id: usb_connected_toast, label: 设备已连接, description: 事件确认后保持 1 秒并淡出 }
  - { id: usb_disconnected_toast, label: 设备已断开, description: 事件确认后保持 1 秒并淡出 }
  - { id: connecting, label: 正在连接, description: 展示阶段、耗时与最大等待时间 }
  - { id: loading_apps, label: 正在读取应用, description: 保持旧缓存时非阻塞刷新 }
  - { id: ready, label: 就绪, description: 设备和 App 都可选 }
  - { id: preparing_capture, label: 准备采集, description: 创建本地 Session 并完成 Sidecar 握手 }
  - { id: waiting_target, label: 等待目标, description: 用户自行运行目标 App 后按 executable 绑定 }
  - { id: collecting, label: 正在采集, description: 锁定设备和 App，实时更新共享时间轴 }
  - { id: stopping, label: 正在保存, description: 停止 Sidecar 并原子完成 manifest 和 quality }
  - { id: completed, label: 已完成, description: 保留曲线与本地 Session 路径 }
  - { id: failed, label: 需要处理, description: 显示可操作的重试与诊断 }
behavior:
  metric_defaults:
    - { panel: FPS, series: [fps] }
    - { panel: CPU Usage, series: [APPCpu, TotalCPU] }
    - { panel: Network, series: [Send, Recv] }
  missing_value_policy: "未连接显示等待设备；不可用显示 Unsupported 与原因；缺值不绘制为 0"
  usb_toast_policy: "后一个 USB 事件替换前一个事件并重置 1 秒计时"
  screenshot_policy: "默认仅内存预览；启用 ScreenShot 后才写入 Session 媒体目录"
