跳转至
  • e4376d9 (Schema 扩展 harmonics + THD design tokens)
  • cdb17d3 (useElectricalMeter composable + unit tests TDD)
  • 3de6f51 (refactor: onMessage singleton 注释 + test gap)
  • 9408f86 (ElectricalMeter.vue APx500 组件 + unit test case 4)
  • 0a75bdf (颜色修正 --xi-color + 测试断言精度)
  • a5ebc04 (e2e 5 段业务契约测试)
  • fe53487 (e2e 强化 · 交叉验证数学 + 真实 viewport)
  • 554ddd1 (里程碑 commit · feature 完整标记) dispatched_reason: | ADR-12 Phase 2 #6/#7 全 zombie(600f0fc + 729327c)· Phase 3 #10 解锁。 本 fork 落地 §3.6 Electrical Meter Node 真业务(THD / THD+N / SINAD / SNR)· 对标 APx500。 必须含全局新增 2 红线(响应式横竖屏 + 主题色系切换 design-token · 用户 2026-05-30 12:50 拍板)。 estimated: 1.5d preempts: [] preempted_by: null unblocks: [ADR-12 Phase 4 e2e 真值 #12] related_zombie:
  • P0.U-measurement-rms-fft-phase (8379de2 · §3.⅓.⅔.4 三组件标杆)
  • P0.U-measurement-electrical-recorder-stub (729327c · §3.6/3.7 ① 输入输出 stub · 本 fork 升级到 ②-⑤ 真业务)

P0.U-measurement-thd-snr · Electrical Meter Node 真业务实施(THD/SINAD/SNR · APx500 对标)

Worker:ClaudeA · 前端主战场 / 部门:前端 P0-xishell / 预计:1.5d / 优先级:P1 / 状态:ready

🔍 触发与解锁链

  • 触发:ADR-12 Phase 2 全闭环(#5/#6/#7 三 fork 全 zombie · 729327c 已落 §3.6 ① 输入输出 stub schema)· 本 fork 升级 ②-⑤ 5 必填段全实施。
  • 解锁条件:本 fork zombie 后,ADR-12 Phase 4 e2e 真值脚本 #12 可纳入 Electrical Meter 验收 case。

任务定义(基于 ADR-AIOS-12 v2.x §3.6 + §2.6 全局红线)

P0.U-measurement-electrical-recorder-stub(729327c)落地的 ElectricalMeterNode stub 升级为真业务实施,对标 APx500:

核心范围(对齐 ADR-12 §3.6): 1. 5 必填段全填 ②-⑤(收敛判据 + 失败回退 + 用户操作流 + e2e 真值)· ① 已在 729327c stub 落 2. THD / THD+N / SINAD / SNR 真业务:依赖 P7 /analyze/thd 端点(ADR-12 §5.2 #9 已 zombie) 3. APx500 风格 UI:Vrms / dBu / Frequency / THD% 数值卡片 + 谐波柱状图 + 校准状态指示 4. Workspace Preset 集成:Electrical Workspace 默认包含本 widget(2x2 第 1 格)

🚨 全局新增 2 红线(用户拍板 2026-05-30 12:50 · 待回写到 ADR-12 §2.6 第 7+8 项): - 响应式适配横竖屏:横屏(宽 ≥ 高)= 数值卡片左 + 谐波图右 / 竖屏(高 > 宽)= 数值卡片上 + 谐波图下 · 用 ResizeObserver + CSS @container query · widgetLayoutStore 暴露 orientation - 主题色系切换:严禁硬编码 hex(#fff / #000 等)· 必须用 var(--xs-color-*) design-token · 对齐 frontend_vue3/src/styles/design-tokens.css

完整 prompt(直接复制粘贴 worker 终端)

[U-thread]: P0.U-measurement-thd-snr
[部门]: 前端 P0-xishell
[Worker CWD]: d:/work/25_claude/workspace/AlgoDepartment/04_development/
[Occupies]: P0.K-shared-meter-dock · P5.K-meter-tap(read)
[优先级]: P1 · 1.5d
[ADR]: docs/08-implementation/40-aios/ADR/ADR-AIOS-12-xitest-realtime-arch.md(v2.1+)
[业务行为契约引用]: 严格对齐 ADR §3.6 Electrical Meter Node 5 必填段(① 输入输出已在 729327c stub · 本 fork 落 ②-⑤)+ §2.6 全局红线第 7+8 项(响应式横竖屏 + 主题切换)
[参考文档]:
  - ADR-AIOS-12 §3.6 Electrical Meter Node 完整 5 段(本 fork 主依据)
  - ADR-AIOS-12 §3.1 RMS Meter Node 5 段标杆(已 zombie 8379de2 · 对照仿写)
  - ADR-AIOS-12 §2.6 全局红线第 7+8 项(响应式 + 主题色系 · 用户 2026-05-30 12:50 拍板 · ⚠️ 若 ADR 文件还没看到 v2.2 §2.6 第 7+8 项 · 以本 prompt 描述为准)
  - 已就位 stub(729327c):frontend_vue3/src/components/measurement/ElectricalMeterStub.vue + types/meter-frame-electrical.ts
  - 已就位标杆(8379de2):frontend_vue3/src/components/measurement-shared/{RMSMeter,SpectrumChart,PhaseChart}.vue + 5 必填段 e2e
  - 已就位 P7 端点(153a109):pysidecar `/analyze/thd`(POST · 输入 samples float[] · 输出 thd / thd_n / sinad / snr / harmonics[])
  - 已就位 P5 多 toolKind 路由(48cf0ba):MeterTapService 支持 toolKind='electrical-meter'

【背景】
ADR-12 Phase 2 #7(`729327c`)落地了 ElectricalMeterNode 的 ① 输入输出契约 schema(stub 占位 · 数值全 0)· 本 fork 升级到 ②-⑤ 5 必填段真业务 · 对标 APx500 风格的 Electrical Meter 显示。

P7 `/analyze/thd` 端点已 zombie(153a109)· 输入 samples + sampleRate · 输出 { thd, thdN, sinad, snr, harmonics: { freq, magDb }[] }。本 fork 直接消费 · 不动 P7。

P5 MeterTapService 已支持 toolKind='electrical-meter' 路由(48cf0ba)· 本 fork 通过 useMeterWs composable 订阅即可。

【执行步骤】(6 步)

Step 1 · 升级 schema + composable(0.2d)
  - 扩 types/meter-frame-electrical.ts:加字段 harmonics: { freq: number; magDb: number }[](来自 P7 /analyze/thd · 默认前 10 阶)
  - 扩 useElectricalMeter.ts composable:订阅 toolKind='electrical-meter' WS · 自动按帧更新 vrms / dbu / frequency / thd / thdN / sinad / snr / harmonics · 失败重连指数退避

Step 2 · ElectricalMeterNode 主组件升级(0.5d · 替换 729327c 的 stub)
  - 路径:frontend_vue3/src/components/measurement-shared/ElectricalMeter.vue(替换 stub)
  - 顶部 4 数值卡片(grid · 响应式):Vrms · dBu · Frequency(Hz)· THD(%)
  - 中部谐波柱状图(SVG / Canvas · 复用 measurement-shared 内部图表风格):基波 + 前 9 阶谐波 · X 轴频率 · Y 轴 dB
  - 底部 4 副指标(横向):THD+N(%)· SINAD(dB)· SNR(dB)· Calibration Status(✅ 已校准 / ⚠️ 未校准)
  - 数值过载/失真颜色梯度:THD < 0.1% 绿 · 0.1-1% 黄 · > 1% 红(用 design-token · 不硬编码 hex)

Step 3 · 响应式横竖屏适配(0.3d · 全局红线 #1)
  - 用 ResizeObserver 监听组件根容器 ref · 计算 aspectRatio
  - aspectRatio ≥ 1(横屏)→ flex-direction: row(数值卡片左 · 谐波图右)
  - aspectRatio < 1(竖屏)→ flex-direction: column(数值卡片上 · 谐波图下 · 副指标折叠)
  - 用 CSS @container query 作为兜底(若浏览器支持)
  - widgetLayoutStore 暴露 orientation 派生 state(供其他 widget 联动)
  - vitest case 验证两种 aspectRatio 渲染正确

Step 4 · 主题色系切换(0.2d · 全局红线 #2)
  - 全组件 CSS 严禁硬编码 hex(grep 验证 component 文件中无 `#[0-9a-fA-F]{3,8}`)
  - 用 design-token:`var(--xs-color-success)` / `var(--xs-color-warning)` / `var(--xs-color-danger)` / `var(--xs-bg-elevated-1)` / `var(--xs-text-primary)` 等
  - 若 design-tokens.css 缺失需要的 token(如 THD 颜色梯度专用)→ 在 design-tokens.css 中先声明再引用 · 不在组件内自造
  - 浅色 / 深色主题切换 e2e 验证(playwright 触发 theme switch · 截图对比)

Step 5 · 业务行为契约 5 必填段 e2e 真值(0.2d)
  - 新增 e2e/electrical-meter-truth.spec.ts(对齐 §3.1 RMSMeter e2e 风格 · 8379de2 标杆)
  - case 1:注入 1kHz -10dBFS 纯正弦 → 断言 frequency ≈ 1000 ± 5 · thd < 0.05% · sinad > 60dB
  - case 2:注入 1kHz + 第 2 阶谐波(2kHz · -50dBFS)→ 断言 thd ≈ 0.3% ± 0.05 · harmonics[1].magDb ≈ -50 ± 1
  - case 3:WS 断开 → 数值卡片应回灰显 + 顶栏红警(失败回退路径)
  - case 4:校准未配置 → Calibration Status 显示 ⚠️ + 数值卡片 vrms 不显示绝对值
  - case 5:横屏 viewport(1920x1080)+ 竖屏 viewport(1080x1920)分别截图 · 断言布局正确切换

Step 6 · 自查 + commit(0.1d)
  - npm run typecheck 全绿
  - npm run test:unit 不退化(基线 356/3)+ 新增 vitest case 全过(预计 +5)
  - npm run test:e2e -- electrical-meter-truth 全过
  - grep "#[0-9a-fA-F]\{3,8\}" frontend_vue3/src/components/measurement-shared/ElectricalMeter.vue · 应 0 命中(主题切换硬约束)
  - commit subject: feat(P0.U-measurement-thd-snr): implement ElectricalMeterNode real business (THD/THD+N/SINAD/SNR + APx500-style UI + responsive landscape/portrait + theme tokens + 5-段 contract e2e)
  - commit trailer 三元组:[step=6/6] [pid=P0] [uid=U-measurement-thd-snr] [occupies=P0.K-shared-meter-dock+P5.K-meter-tap-read] [files=components/measurement-shared/ElectricalMeter.vue,types/meter-frame-electrical.ts,composables/useElectricalMeter.ts,e2e/electrical-meter-truth.spec.ts]

【验收】(stop 前必跑)

形式合规:
  ☐ npm run typecheck 全绿(0 error)
  ☐ npm run test:unit 不退化 + 新增 case 全过
  ☐ npm run test:e2e -- electrical-meter-truth 5 case 全过
  ☐ grep `#[0-9a-fA-F]{3,8}` 在 ElectricalMeter.vue / 新增 .ts 中 0 命中
  ☐ 不动 729327c 已落地的 types schema(仅扩展 harmonics 字段 · 不改既有字段)
  ☐ 不在组件内实装 FFT/THD 数学(沿用 ADR-07 §1.3.4 三层分工铁律)

业务行为契约(端到端真值 · 必跑):
  ☐ 1kHz -10dBFS 纯正弦 → frequency ≈ 1000 ± 5 · thd < 0.05% · sinad > 60dB
  ☐ 1kHz + 2kHz 谐波 → thd ≈ 0.3% ± 0.05 · harmonics[1].magDb ≈ -50 ± 1
  ☐ WS 断开 → 灰显 + 顶栏红警(失败回退第 1 类)
  ☐ 横屏 1920×1080 vs 竖屏 1080×1920 布局正确切换(全局红线 #1)
  ☐ 主题切换浅色 ↔ 深色 → 截图对比无硬编码颜色泄漏(全局红线 #2)

【commit】
- subject + 三元组 trailer 见 Step 6
- 7 天宽限期内三元组缺失仅 warning · 6/2 起 strict mode 硬拒

【禁止】(7 项红线)
1. ❌ 禁止在前端实装 FFT/THD/SINAD 数学计算(沿用 ADR-07 §1.3.4 三层分工铁律 · 数学全交 P7)
2. ❌ 禁止硬编码 hex 色值(`#fff` / `#000` / `rgba(...)` 等 · 必须 var(--xs-color-*) design-token · 全局红线 #2)
3. ❌ 禁止跳过响应式横竖屏 e2e(必须 playwright viewport 1920×1080 vs 1080×1920 各跑一次 · 全局红线 #1)
4. ❌ 禁止动 729327c 已落地的 types/meter-frame-electrical.ts 既有字段(仅扩展 harmonics 字段)
5. ❌ 禁止动 P7 `/analyze/thd` 端点(已 153a109 zombie · 仅消费)
6. ❌ 禁止跳过 e2e 真值(必须 5 case 含 1kHz 正弦 + 谐波注入断言 · 不允许仅 typecheck/test 形式合规通过就 commit)
7. ❌ 禁止越界引入 stages/ 子目录代码(本 fork 仅在 components/measurement-shared/ + composables/ + types/ + e2e/)

解锁链(本任务 zombie 后)

  • ✅ ADR-12 Phase 4 e2e 真值 #12 可纳入 Electrical Meter 验收 case
  • ✅ Workspace Preset 'Electrical' 默认 widget 第 1 格就位

风险评估

风险 缓解
design-tokens.css 缺 THD 颜色梯度专用 token Step 4 在 design-tokens.css 先声明 --xs-meter-thd-good/warn/bad 再引用 · 不在组件内自造
ResizeObserver 浏览器兼容(Electron 26+ 已支持) 用 vueuse @vueuse/core 的 useResizeObserver 兼容封装
P7 /analyze/thd 输出 schema 与 729327c stub 不一致 Step 1 先 read sidecar 端点真实输出 · 必要时与 ClaudeB 协调 schema 微调(走 commit trailer [need:P7])
e2e 谐波注入测试夹具未就绪 用现有 8379de2 测试夹具风格 · injectSine + injectHarmonic 各 1 函数 · 1.0 hr 内可写

历史

时间 事件 hash
2026-05-30 13:00 dispatched · ADR-12 Phase 3 入场首 fork · 含全局新增 2 红线
2026-05-31 13:11 zombie · ClaudeA 完成 8 commit 链路(e4376d9 → cdb17d3 → 3de6f51 → 9408f86 → 0a75bdf → a5ebc04 → fe53487 → 554ddd1)· ElectricalMeter.vue + useElectricalMeter + types/meter-frame-electrical + e2e 5 段契约 + 全局 2 红线落地 · v1.5 铁律 git -C verify + show --stat 真值核查通过(用户首次 hash cbd2c23 错位 · 真实里程碑 554ddd1)· ADR-12 Phase 3 #10 闭环 554ddd1