- 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 |