ADR-AIOS-17-R1/R2 · Realtime Stage 5 Widget 可视化层实装(R2 数据源边界澄清)
状态:v0.2 accepted · 2026-06-13 10:23(用户 2026-06-13 双线并行拍板 A · 同步起 ADR-AIOS-21)· R2 6 fork ready 解锁派发 R2 触发:用户 2026-06-07 16:10 关键纠错(详见 §0 修订记录)— 澄清"xitest realtime widget = 可视化层 + 消费现有数据源(物理输入 P5+P7 / xilink log module PCM)" · 不是再造 P7 新算法层 范围:仅修订 ADR-17 §3.4 7 widget 实装盲区 · 不动 ADR-17 §3.1/§3.2/§3.3 已 fulfilled 部分 · 不动 ADR-12 §3 7 widget 业务契约标杆 · 不动 ADR-18 xilink 算法库 plugin
0. 修订记录(Revision History)
| 版本 | 日期 | 修订人 | 触发 | 核心变化 |
|---|---|---|---|---|
| v0.1 | 2026-06-07 10:35 proposed → 11:03 accepted | Cline-AIOS | 用户 2026-06-06 21:09 第二次原话(symptom 原地踏步) | 初次起草 5 widget 算法实装跨栈 6 fork 12d · 设计为"NEW P7 sidecar 端点 /analyze/{phase_meter,transfer_function,spectrogram,thd,loudness_bs1770} + P5 路由 + WS frame 5 type" |
| v0.2 | 2026-06-07 16:30 proposed-revision | Cline-AIOS | 用户 2026-06-07 16:10 关键纠错 | 架构边界澄清:① v0.1 §3.5 5 widget 的"NEW P7 端点"设计与 xilink 算法库职责重叠(rms/fft/scope 已在 xilink 内部 · ADR-18 落地)② xitest realtime widget 实际范围 = 可视化层 + 数据源消费(数据源 A 物理输入 P5+P7 现有 19 端点 / 数据源 B xilink log module PCM 半实时分析)③ R2 §3.5 5 widget × ① 段全改 · 明确"消费现有 P7 endpoint / xilink log module frame" · 不再造 P7 新算法 ④ §4 fork 表 F1/F2/F4/F5 重新设计(前端为主 · 后端只补现有端点 gap · 不新建 endpoint)⑤ F1 已 dispatched 11:03 · 用户 16:25 拍板 abort F1 + 保留 F3(F3 范围本来就前端 UI · R2 仅补数据源说明)⑥ §9 加教训 #4(可视化层 vs 算法库边界澄清) |
用户 2026-06-07 16:10 关键纠错原话(verbatim)
"我看你的这些任务怎么很奇怪啊;这个显示和 DSP 有什么关系;xilink 中的 rms fft 还有 scope 是由算法库来实现,xitest 中的所有频响 相位等曲线显示都是要么是输入设备的数据由后端和 pysidecar 来直接分析得出结果,要么是通过 xilink 中的 logmodule 返回的 pcm 数据进行半实时分析得到;我现在让你确认的是 xitest 中所有 realtime 的测量组件的实现,不是让你去实现 xilink 中的监控 module"
架构边界图(R2 锁定)
┌─────────────────────────────────────────────────────────────────────┐
│ xitest realtime stage(5 widget 可视化层 · R2 范围) │
│ │
│ ┌──────────────┬──────────────┬──────────────┬──────────────┐ │
│ │ PhaseChart │ TransferChart│ ScopePanel │ Spectrogram │ ... │
│ │ (F1 R2) │ (F2 R2) │ (F3 不变) │ (F4 R2) │ │
│ └──────┬───────┴──────┬───────┴──────┬───────┴──────┬───────┘ │
│ │ │ │ │ │
│ └──────────────┴──────────────┴──────────────┘ │
│ │ │
│ 数据源订阅(WS frame 消费 · 前端零数学) │
└─────────────────────────────┬───────────────────────────────────────┘
│
┌─────────────────────┴─────────────────────┐
│ │
数据源 A(物理输入) 数据源 B(xilink log module)
┌────────────────────┐ ┌──────────────────────────┐
│ P5 backend │ │ ADR-17 F5(已 zombie 🏆) │
│ └─ MeterTapService│ │ └─ log_module_v1 frame │
│ P7 pysidecar │ │ (PCM 半实时分析输出)│
│ └─ /analyze/* │ │ │
│ 19 现有端点 │ │ R2 F1/F2 消费此 frame │
│ (覆盖现状?) │ │ 做半实时频响/相位分析 │
│ │ │ │
│ R2 F1/F2/F5 消费 │ │ │
│ · 仅补 gap endpoint│ │ │
│ · 不再造 NEW 端点 │ │ │
└────────────────────┘ └──────────────────────────┘
──────────────────────────────────────────────────────────────────────
xilink 算法库(独立 · R2 不重叠 · ADR-18 落地中):
├─ rms-meter-module / scope-module(ADR-17 F5/F6 已 plugin 注册 🏆)
├─ fft-module(ADR-18 H2 注册 + ADR-18 F5+F6+F7 全栈实装 active running)
└─ DSP 算法实装在 dsp_algo/modules/(ADR-18 F7)
R2 三层分工铁律重申(ADR-07 §1.3.4 · 不变): - L1 P5 (.NET):零数学 · 仅做 MeterTapService 路由 + WS frame 派发(R2 不新增 toolKind · 复用现有 + 配 widget endpoint selector) - L2 P7 (pysidecar):全部 numpy/scipy 计算 · R2 不新增 endpoint · 仅在真值核查发现"现有 19 端点不覆盖"时补 1-2 个 gap 端点(单测覆盖) - L3 前端 (Vue):零数学 · R2 主战场 · 5 widget vue 组件 + composable 订阅 WS frame + canvas/WebGL 渲染 + Inspector 配置面板
1. 背景与动机(Context & Motivation · 不变)
1.1 触发事件(verbatim 原话三对照 · R2 加 16:10 第三次原话)
第一次原话(2026-06-04 12:37 · 触发 ADR-17 起草):
"stop P0.A13.H3-realtime-widgets-and-loopback-source commit 900432b · 但是问题并没有解决,目前只有 fft 和 rms 有效果,其他都没实装,感觉是之前的决议中没有彻底执行完,很多都显示 phase2 占位,phase 等没信号;..."
第二次原话(2026-06-06 21:09 · 触发本 R1 起草):
"确认一下 ADR 和 ADR17 的进度,当前由于错误理解了 xilink 的 rms 位置等问题,现在已经在智能体中进行整体修复了,但是关于 xitest 中的 realtime 和 xilink-analyze 的进展好像被中断了... 目前看测量插件只有 fft 和 rms 可用,其他的还是无法使用"
第三次原话(2026-06-07 16:10 · 触发 R2 修订):
见 §0 修订记录 verbatim 原话块
→ 2.5 天 + 5 小时间隔 · 三次原话症状均指向"5 widget 不可用" · R1→R2 修正点不在 fork 数量 · 而在边界(R1 把"算法实装"理解为新建 P7 端点 · R2 修正为"消费现有数据源 + 前端可视化")。
1.2 根因核查(不变 · R1 原文保留)
ADR-17 §3.4 line 517-519 假设 ADR-12 时代 7 widget 算法已 fulfilled · 真值核查反例(ADR-13 H1/H2/H3 触底报告 + 用户实测)证伪此假设 · 详细见 R1 v0.1 已存档段(本 R2 不复述)。
R2 补充根因(用户 16:10 纠错暴露):Cline-AIOS R1 v0.1 起草时未充分理解 xilink 算法库 vs xitest 可视化层的边界 · 直接套用 ADR-12 §3 业务契约模板时把所有计算都堆到 P7 sidecar · 与 xilink 算法库职责(ADR-18 落地中)重叠。
1.3 用户期望(R2 收敛目标 · 调整)
| Widget | ADR-12 §3 业务契约 | 当前状态(2026-06-06) | R2 目标(可视化层) |
|---|---|---|---|
| RMS Meter | §3.1 | ✅ 已实装(ADR-13 H2/H3 + ADR-17 F6 弹窗) | 基线保留 · 不动 |
| FFT Analyzer | §3.2 | ✅ 已实装(ADR-13 H2/H3) | 基线保留 · 不动 |
| Transfer Function | §3.3 | ❌ stub 占位 · Smaart 核心 | ✅ R2 实装可视化层 + 消费现有数据源 / log module PCM |
| Phase Meter | §3.4 | ❌ stub 占位 · 用户原话直接点名 | ✅ R2 实装可视化层 + 消费现有数据源 / log module PCM |
| Waveform Scope | §3.5 | ❌ stub 占位 | ✅ R2 实装(F3 不变)+ ADR-13 H1 buffer endpoint 已就位 |
| Spectrogram | §3.5 扩展(用户原话点名) | ❌ stub 占位 | ✅ R2 实装可视化层 + STFT 半实时(若现有 P7 STFT endpoint 缺 → 补 1 个 gap endpoint) |
| Electrical Meter(THD/SINAD/Loudness/PeakHold) | §3.6 + §3.1 扩展 | ❌ stub 占位 | ✅ R2 实装可视化层 + 消费现有 P7 端点(LUFS/THD)+ 前端 RMS endpoint 加 peakHold/crest 增量字段 |
R2 收敛 5 widget(去重合并 · 复用 ADR-12 业务契约 · 范围调整): 1. Phase Meter(§3.4 · 含 wrapped/unwrapped/groupDelay · 可视化层 + 数据源订阅) 2. Transfer Function(§3.3 · Smaart 风格 · 可视化层 + 数据源订阅) 3. Waveform Scope(§3.5 · 含 trigger/preroll/freeze · F3 不变 · 后端 buffer endpoint ADR-13 H1 已就位) 4. Spectrogram(§3.5 扩展 · 时频热图 · 可视化层 + STFT 数据源) 5. Electrical Meter(§3.6 · THD/SINAD/SNR/Loudness LUFS/PeakHold + Crest Factor · 可视化层 + 数据源订阅)
2. 决议(Decision · R2 调整核心)
2.1 R2 核心决议
ADR-AIOS-17-R1/R2 增补 ADR-17 §3.5 widget 可视化层实装清单:
5 widget 可视化层实装跨栈 5 fork × 平均 1.8d ≈ 9d(前端 P0 主战场 + 后端 P5/P7 仅补 gap endpoint + 数据源消费两条路径 + e2e 全矩阵真值)
严守三层分工铁律(ADR-07 §1.3.4 · R2 重申): - L1 I/O(P5):不新增 toolKind · 复用现有 MeterTapService + 配 widget endpoint selector(ADR-17 F6 已就位 4 类)+ 若现有 frame schema 缺字段则向后兼容扩展(如 RMS frame 加 peakHoldDb/crestFactor/lufsIntegrated 增量字段) - L2 数学(P7-pysidecar):优先消费现有 19 端点 · Step 0 真值核查后若发现 gap(如 transfer function 双通道分析 / spectrogram STFT 时频矩阵)则补 ≤ 2 个 gap endpoint · 不允许新建 5 个 NEW 端点 - L3 显示(P0 前端):R2 主战场 · 5 widget vue 组件 + composable 订阅 + canvas/WebGL Canvas 渲染 + Inspector 配置面板 + Step 0 强制核查现有 widget stub(如 PhaseChart / TransferChart / WaveformChart / SpectrumChart)的真签名
2.2 数据源两条路径(R2 锁定)
| 路径 | 数据源 | 触发条件 | 适用 widget |
|---|---|---|---|
| A · 物理输入 | P5 backend MeterTapService 30fps + P7 pysidecar /analyze/* 19 端点 | 用户在 widget endpoint selector 选 physical-input 或 sink-pre |
全 5 widget(F1/F2/F3/F4/F5 均支持) |
| B · xilink log module | ADR-17 F5 已 zombie 的 log_module_v1 frame(PCM 数据)+ 前端 composable 半实时分析(轻量 STFT/FFT) | 用户在 widget endpoint selector 选 log-module 或 xitune-module |
F1 phase / F2 transfer / F4 spectrogram(F3 scope 直接用 PCM 时域 · F5 electrical 走 P7 端点) |
R2 关键澄清: - 数据源 B 的"半实时分析" = 前端 composable 用 Web Audio API AnalyserNode 或 fft.js 做轻量分析(L3 前端零数学铁律例外:仅做"消费 PCM → bin magnitude"轻量计算 · 不做 phase unwrap/coherence/GCC-PHAT 等复杂算法) - 若复杂算法需求(如 transfer function GCC-PHAT)→ 仍走数据源 A 路径(P7 端点 · L2 数学层) - 用户在 widget endpoint selector 切换路径 → composable 自动切订阅源
2.3 与 ADR-12 §3 7 widget 业务契约关系(R2 不变)
不变 · R2 不重写业务契约 · 仅实装可视化层。
2.4 与 ADR-13 三轮 hotfix 教训承接(R2 不变)
不变 · R2 仍走 ADR R 修订路径 · 不走 hotfix。
2.5 与 ADR-18 xilink 算法库 plugin 关系(R2 新增)
| ADR | 范围 | R2 关系 |
|---|---|---|
| ADR-18(active running) | xilink 算法库 plugin(rms-meter-module / fft-module / scope-module · DSP 算法实装在 dsp_algo/modules/) | R2 不重叠 · xilink 内部算法库由 ADR-18 落地 · R2 仅消费 xilink log module 输出的 PCM frame |
| ADR-17 F5 🏆 | xilink log_module_v1 frame 协议(已 zombie) | R2 数据源 B · F1/F2/F4 消费此 frame |
| 本 R2 | xitest realtime widget 可视化层 · 消费数据源 A/B · 前端为主 + 后端补 gap | 与 ADR-18 完全正交 |
3. 业务行为契约(Business Behavior Contract · §3.5 R2 重写 5 widget × ① 段)
R2 §3.5 重写要点:5 widget 各 ① 输入/输出契约 段 = "数据源订阅描述 + 现有 schema 复用 + 前端组件渲染数据" · ②③④⑤ 段沿用 ADR-12 §3 已锁定段(不动)
3.5.1 Phase Meter(R2 fork F1 · 引用 ADR-12 §3.4)
① 输入/输出契约(R2 重写)
前端组件:PhaseMeterPanel.vue(NEW)+ usePhaseMeter composable(NEW)
数据源订阅(两条路径):
| 路径 | 数据源 | composable 行为 |
|---|---|---|
| A · 物理输入 | P5 MeterTapService 30fps · phase_v1 WS frame(若现有 frame 缺 → Step 0 真值核查 · 若 gap 则 R2 F1 补 1 个 P7 endpoint /analyze/phase_meter 单端点 · ≤ 4 case 单测) |
订阅 phase:<chainId>:<channelId> topic · 直接消费 freqs/phaseWrapped/phaseUnwrapped/groupDelay 字段渲染 |
| B · xilink log module | ADR-17 F5 log_module_v1 PCM frame · 前端 composable 用 Web Audio API AnalyserNode 做轻量 FFT + numpy 风格 unwrap(纯前端 js · 复用 ADR-13 H2 useFFTAnalysis 已就位 composable 风格) |
订阅 log-module:<moduleId> topic · 消费 PCM samples · 前端做 FFT + phase = atan2(im, re) + 简单 unwrap(不做 groupDelay · 仅 wrapped/unwrapped 模式) |
输出 schema(复用 ADR-12 §3.4 ① line 750-768 · MeterFrame_Phase · 字段不变):
- freqs / phaseWrapped / phaseUnwrapped / groupDelay / averagedCount / resolution
- 单位:phase = degree(°)· groupDelay = ms · resolution = Hz/bin
R2 关键澄清:
- 数据源 A 时:groupDelay 来自 P7 后端 numpy.gradient(完整 3 模式)
- 数据源 B 时:groupDelay 字段为 null(前端不做复杂算法 · UI 自动隐藏 groupDelay 模式选项)
- 前端 widget endpoint selector 切换时 · composable 自动切订阅源 + UI 模式选项联动
②③④⑤ 段(沿用 ADR-12 §3.4 已锁定段 + R1 v0.1 已写收敛/失败/操作流/e2e · R2 不变)
详见 R1 v0.1 §3.5.1 ②③④⑤ 段(line 141-194)· R2 不复述。
3.5.2 Transfer Function(R2 fork F2 · 引用 ADR-12 §3.3 · Smaart 核心)
① 输入/输出契约(R2 重写)
前端组件:TransferFunctionPanel.vue(NEW)+ useTransferFunction composable(NEW)
数据源订阅:
| 路径 | 数据源 | composable 行为 |
|---|---|---|
| A · 物理输入双通道(主路径) | P5 MeterTapService + P7 pysidecar 现有 transfer 端点(Step 0 真值核查 · 若现有 19 端点不覆盖 → R2 F2 补 1 个 gap endpoint /analyze/transfer_function 含 GCC-PHAT delay finder + cross-spectral density coherence · ≤ 5 case 单测) |
订阅 transfer:<chainId>:<refCh>:<measureCh> topic · 消费 magnitudeDb/phaseWrapped/coherence/delayLocked/delayFinderMs 等字段 |
| B · xilink log module | 不适用(双通道场景 + GCC-PHAT 算法复杂度高 · 必须走数据源 A · UI 自动禁用 log-module endpoint 选项) | - |
输出 schema(复用 ADR-12 §3.3 ① line 642-669 · MeterFrame_Transfer · 字段不变)。
R2 关键澄清:F2 仍是 R2 唯一可能新建 P7 endpoint 的 fork(因 GCC-PHAT delay finder 算法复杂度高 · 不适合前端轻量分析)· 前提是 Step 0 真值核查证明现有 19 端点不覆盖。
②③④⑤ 段(沿用 ADR-12 §3.3 已锁定段 line 674-742 · R1 v0.1 §3.5.2 已引用 · R2 不变)
3.5.3 Waveform Scope(R2 fork F3 · 引用 ADR-12 §3.5 · F3 范围本来就前端 UI · R2 仅补数据源说明)
① 输入/输出契约(R2 重写 · 仅澄清数据源)
前端组件:WaveformScopePanel.vue(NEW)+ useWaveformScope composable(NEW)
数据源订阅:
| 路径 | 数据源 | composable 行为 |
|---|---|---|
| A · 物理输入(主路径) | ADR-13 H1 bcd9a74 已就位 buffer-capture endpoint GET /api/realtime/buffer-capture?chainId=&channelId=&durationMs= 返回 PCM samples + sampleRate + bufferSize |
composable 触发 buffer 抓取 · trigger UI 在前端做 level/edge/preroll 检测(纯前端 js)· canvas 绘时域波形 |
| B · xilink log module | ADR-17 F5 log_module_v1 PCM frame(连续推流) |
composable 订阅 log-module:<moduleId> topic · 用 Web Audio API ring buffer 缓存最近 5s · trigger/freeze 同 A 路径 |
输出 schema(复用 ADR-12 §3.5 ① line 805-825 · MeterFrame_Waveform · 字段不变)。
R2 关键澄清(F3 vs R1 v0.1 不变): - F3 范围本来就是前端 UI + canvas 渲染 + trigger 前端检测 · R1 v0.1 §3.5.3 设计正确 · R2 仅在 prompt 中补充"数据源 B 也可订阅 log_module_v1 PCM"说明 - F3 已 dispatched 11:03(用户 16:25 拍板保留)· R2 accepted 后 ClaudeA 拿到 prompt 直接执行 · 无需重派 - F3 prompt 在 R2 accepted 后单独追加数据源 B 说明段(append-only · 不改 frontmatter)
②③④⑤ 段(沿用 ADR-12 §3.5 已锁定段 line 829-862 · R1 v0.1 §3.5.3 已引用 · R2 不变)
3.5.4 Spectrogram(R2 fork F4 · ADR-12 §3.5 扩展 · 时频热图)
① 输入/输出契约(R2 重写)
前端组件:SpectrogramPanel.vue(NEW)+ useSpectrogram composable(NEW)+ WebGL Canvas heatmap renderer
数据源订阅:
| 路径 | 数据源 | composable 行为 |
|---|---|---|
| A · 物理输入(主路径) | Step 0 真值核查 · 若现有 P7 19 端点缺 STFT 时频矩阵 → R2 F4 补 1 个 gap endpoint /analyze/spectrogram(STFT ring buffer + hop size + window 重叠帧 · ≤ 4 case 单测) |
订阅 spectrogram:<chainId>:<channelId> topic · 消费增量帧(每帧一列)+ 前端 ring buffer 累计 windowMs |
| B · xilink log module | ADR-17 F5 log_module_v1 PCM frame |
composable 用 fft.js 在前端做 STFT(轻量 · 复用现有 SpectrumChart 已就位的 FFT pipeline)+ 累计 ring buffer |
输出 schema(R1 v0.1 §3.5.4 已定义 MeterFrame_Spectrogram · 字段不变 · 见 R1 v0.1 line 244-263):
- freqs / timeMs / magsDb(单时刻 fftSize/2+1 bin)/ dbRange / colormap / resolution
R2 关键澄清:F4 是 R2 第 2 个可能新建 P7 endpoint 的 fork(若 Step 0 真值核查证明现有端点不覆盖 STFT 时频矩阵)· 但若数据源 B 路径前端 fft.js 已能满足轻量场景 → 可不新建 endpoint · 仅前端实装。
②③④⑤ 段(沿用 R1 v0.1 §3.5.4 ②③④⑤ line 266-314 · R2 不变)
3.5.5 Electrical Meter(R2 fork F5 · 引用 ADR-12 §3.6 · 含 THD/SINAD/SNR/Loudness LUFS/PeakHold/Crest)
① 输入/输出契约(R2 重写)
前端组件:ElectricalMeterPanel.vue(NEW)+ useElectricalMeter composable(NEW)
数据源订阅:
| 路径 | 数据源 | composable 行为 |
|---|---|---|
| A · 物理输入(主路径) | Step 0 真值核查 · ① 若现有 P7 端点已覆盖 LUFS BS.1770 / THD 谐波检测 → 直接消费 ② 若 gap → R2 F5 补 1-2 个 gap endpoint(/analyze/loudness_bs1770 用 pyloudnorm 库 + /analyze/thd 谐波检测 · ≤ 4 case 单测)③ 现有 RMS frame schema 加增量字段 peakHoldDb / crestFactor / lufsIntegrated(向后兼容 · contract-v1.0 frozen 通过 additive 扩展) |
订阅 electrical:<chainId>:<channelId> 或现有 meter:rms topic · 消费 vrms/dbu/thd/sinad/lufs/peakHold/crest 7 字段 |
| B · xilink log module | 不适用(LUFS BS.1770 K-weighting 滤波 + 门限处理算法复杂 · 必须走数据源 A · UI 自动禁用 log-module endpoint 选项) | - |
输出 schema(复用 R1 v0.1 §3.5.5 已定义 MeterFrame_Electrical_R1 合并 schema · 字段不变 · 见 R1 v0.1 line 325-345)。
R2 关键澄清:F5 是 R2 第 3 个可能补 gap endpoint 的 fork(LUFS / THD)· 前提是 Step 0 真值核查 · 不允许直接假设需要新建。
②③④⑤ 段(沿用 R1 v0.1 §3.5.5 ②③④⑤ line 347-405 · R2 不变)
4. 实施清单(Implementation · v1.9 fork 表 · R2 重新设计)
| F# | UID | 部门 | CPU | 工作量 | 描述(R2 调整后) | 状态 |
|---|---|---|---|---|---|---|
P_dsp.A17R1.F1-phase-meter-algorithm |
aborted | |||||
| F1 R2 | P0.A17R2.F1-phase-meter-ui-and-data-source |
前端 P0(+ P7 gap endpoint 若需) | ClaudeA(主)+ ClaudeB(P7 gap 若需) | 1.5d | PhaseMeterPanel.vue + usePhaseMeter composable(主战场)+ widget endpoint selector(复用 ADR-17 F6)+ 数据源 A/B 双路径订阅 + Step 0 真值核查现有 P7 phase 端点 · 若现有不覆盖则补 1 个 gap endpoint(≤ 4 case 单测)· 业务契约 §3.5.1 完整 5 段 | ready(等 R2 accepted) |
| F2 R2 | P0.A17R2.F2-transfer-function-ui-and-gcc-phat |
前端 P0(+ P7 gap endpoint 若需) | ClaudeA(UI 主)+ ClaudeB(P7 GCC-PHAT 算法若需 1.0d) | 2.5d | TransferFunctionPanel.vue + useTransferFunction composable + Smaart 风格 mag/phase/coherence/delay 4 chart + 双通道 ref/measure UI · 数据源 A 主路径 · Step 0 真值核查 · 若现有 19 端点缺 GCC-PHAT 双通道 transfer → 补 1 个 gap endpoint(≤ 5 case 单测 · pyroomacoustics 或 librosa.feature.gcc_phat)· 业务契约 §3.5.2 引用 ADR-12 §3.3 | ready(等 R2 accepted) |
| F3 R2 | P0.A17R1.F3-waveform-scope-ui-and-trigger(原 UID 不变 · 已 dispatched) |
前端 P0 | ClaudeA | 1.5d | 保留 R1 v0.1 设计(本来就前端 UI · 范围正确)· R2 accepted 后 prompt append-only 追加数据源 B 说明段(订阅 log_module_v1 PCM · 半实时 ring buffer)· 后端 buffer endpoint ADR-13 H1 bcd9a74 已就位 · 业务契约 §3.5.3 引用 ADR-12 §3.5 |
dispatched(11:03 · 保留) |
| F4 R2 | P0.A17R2.F4-spectrogram-ui-and-stft |
前端 P0(+ P7 gap endpoint 若需) | ClaudeA(UI WebGL 主)+ ClaudeB(P7 STFT gap 若需) | 2.0d | SpectrogramPanel.vue + useSpectrogram composable + WebGL Canvas heatmap renderer + colormap viridis/magma/inferno/plasma 预生成 LUT + ring buffer 滚动 · 数据源 A/B 双路径 · Step 0 真值核查 · 若数据源 B 前端 fft.js STFT 满足 → 不新建 P7 endpoint(纯前端实装)· 否则补 1 个 gap endpoint(≤ 4 case 单测)· 业务契约 §3.5.4 完整(用户原话点名) | ready(等 R2 accepted) |
| F5 R2 | P0.A17R2.F5-electrical-meter-ui-and-lufs-thd |
前端 P0(+ P7 gap endpoint 若需) | ClaudeA(UI)+ ClaudeB(P7 LUFS/THD gap 若需 1.0d) | 2.0d | ElectricalMeterPanel.vue + useElectricalMeter composable + 7 字段表格(vrms/dbu/thd/sinad/lufs/peakHold/crest)+ Inspector calibration 入口 + Pass/Fail mask · 数据源 A 主路径 · Step 0 真值核查 · 若现有 P7 端点不覆盖 LUFS BS.1770(pyloudnorm)/ THD 谐波检测 → 补 1-2 个 gap endpoint + 现有 RMS frame schema additive 扩展 peakHoldDb/crestFactor/lufsIntegrated · 业务契约 §3.5.5 引用 ADR-12 §3.6 + §3.1 合并 | ready(等 R2 accepted) |
| F6(收尾) | P_e2e.A17R1.F6-truth-e2e-5-widgets-algorithm(UID 不变) |
测试编排 | ClaudeC | 2.0d | playwright e2e 5 widget × 业务契约 ⑤ 段全跑(case 不变 · 但断言数据源路径 A/B 双路径覆盖)· F1 phase 1kHz std<5° + F2 transfer delay 4ms 锁定 + F2 PEQ -3dB@1kHz · F3 scope 1kHz 方波 trigger period · F4 spectrogram 0→10kHz sweep 对角线 · F5 electrical 1kHz THD<0.01% + -23LUFS 积分 + 方波 PeakHold 锁定 · 共 ≥ 12 case 真值断言 · 解锁 ADR-17-R1 fulfilled 🏆 | ready(等 F1+F2+F3+F4+F5 全 zombie) |
| 合计 | 11.5d ≈ 1.5-2 周(6 fork 跨栈 · R2 比 R1 v0.1 12.0d 减 0.5d · 因前端为主减少新 P7 endpoint 数量) |
关键路径(R2 调整):F1 R2 phase UI → F2 R2 transfer UI → F4 R2 spectrogram UI → F5 R2 electrical UI → F6 e2e 并行路径(R2 不变):F3(已 dispatched · ClaudeA 在跑)与 F1 R2 文件正交可并行(F3 是 WaveformScopePanel.vue · F1 R2 是 PhaseMeterPanel.vue)
R2 Phase 派发计划: - 当前(2026-06-07 16:30):F3 dispatched 在跑(ClaudeA · 1.5d)· F1+F2+F4+F5+F6 等 R2 accepted 后 ready - R2 accepted 后 Phase 1:F1 R2 phase UI(ClaudeA 1.5d · 与 F3 串行 · 同 worker)+ ClaudeB Step 0 真值核查 P7 端点(若 gap → 补 phase endpoint 0.5d 后端) - Phase 2:F2 R2 transfer UI(ClaudeA 2.5d 主)+ ClaudeB GCC-PHAT 后端 gap(若需 1.0d) - Phase 3:F4 R2 spectrogram UI(ClaudeA 2.0d · 优先尝试纯前端 fft.js 路径) - Phase 4:F5 R2 electrical UI(ClaudeA 2.0d)+ ClaudeB LUFS/THD gap(若需 1.0d) - Phase 5:F6 e2e(ClaudeC 2.0d 收尾 🏆)
5. 风险与缓解(R2 调整)
| 风险 | 缓解 |
|---|---|
| 复发 ADR-13 H1/H2/H3 触底循环(再走"半实装 stub" hotfix 模式) | 业务契约 5 必填段硬阻塞 + F6 e2e 真值断言 + ADR-12 §3 业务契约标杆复用(R2 不变) |
| R2 重新理解架构边界 · 仍可能再次错位(如某 widget 设计被误归类到 xilink 算法库) | 每个 fork prompt Step 0 强制真值核查:① grep 现有 P7 19 端点 ② grep 现有 widget stub 真签名 ③ grep ADR-18 xilink module 范围确认不重叠 · 三层核查记录 commit message · 派发前自查清单 |
| Step 0 真值核查发现现有 P7 端点不覆盖 → 必须补 gap endpoint · 但补几个不可控 | R2 §4 fork 表已预设 gap endpoint 上限(F1 ≤ 1 · F2 ≤ 1 · F4 ≤ 1 · F5 ≤ 2 · 共 ≤ 5 个 · 若超过则升 R3 修订)+ 每个 gap endpoint ≤ 5 case 单测硬门槛 |
| 数据源 B 前端轻量分析 vs 后端复杂算法 · 性能 / 准确性平衡 | R2 §2.2 已锁定:复杂算法(GCC-PHAT / coherence / phase unwrap groupDelay / LUFS BS.1770)走 P7 后端 · 轻量(单通道 FFT / phase atan2)允许前端 · widget endpoint selector UI 自动禁用不适用路径 |
| Smaart 风格 transfer function GCC-PHAT delay finder 复杂度(R2 仍可能补 P7 gap endpoint) | F2 给 ClaudeB 充足 1.0d 后端 + 2.5d 前端 ClaudeA · 参考 librosa.feature.gcc_phat / pyroomacoustics.experimental · 单测 4ms 延时夹具 sample-accurate(R1 v0.1 风险条目保留) |
| LUFS BS.1770 算法易错(K-weighting 滤波 + 门限处理) | F5 R2 直接用 pyloudnorm 库(已工业标准实装)· 不自造轮子 · 单测 -23LUFS 校准信号(R1 v0.1 风险条目保留) |
| Spectrogram WebGL Canvas 性能(浏览器兼容性) | F4 R2 双轨实现(WebGL 主路径 + Canvas 2D 降级)+ ring buffer 限流 30fps + 颜色映射 4 种预生成 LUT(R1 v0.1 风险条目保留) |
| ADR-12 §3 业务契约 v2.3 锁定后 R1/R2 不能改 | R1/R2 仅算法/可视化层实装 · 业务契约直接引用 ADR-12 §3.3-§3.6 段号 · 严禁任何字段重写(R1 v0.1 不变) |
| R2 修订期间 F3 仍在跑 · 数据源 B 说明 append-only 追加是否影响 ClaudeA 当前实施 | F3 R1 v0.1 §3.5.3 ① 已含数据源描述(只是不够明确)· R2 append 是补充说明 · 不改 frontmatter / 不改任务定义 / 不影响 ClaudeA 已开工内容 · ClaudeA commit 时若已含数据源 B 路径 → 直接 zombie 入账 · 若未含 → R2 accepted 后 hotfix 补一次即可(< 0.5d) |
6. 决议者签名
- proposed by:Cline-AIOS(2026-06-07 10:35 v0.1 → 2026-06-07 16:30 v0.2 R2)
- review by:user(v0.1 11:03 accepted · v0.2 等 2026-06-07 拍板 accept)
- accepted by:v0.1 user 2026-06-07 11:03 · v0.2 待
- 后续修订:ADR-AIOS-17-R3(若 R2 实施期间 Step 0 真值核查发现 gap endpoint 数量超 5 个或边界仍模糊)
7. 状态流转(R2 加 4 行)
| 时间 | 事件 | 备注 |
|---|---|---|
| 2026-06-04 12:37 | 用户原话触发 ADR-17 v0.1 起草 | "phase 等没信号 · phase2 占位"(原话存档 ADR-17 §1.1.1) |
| 2026-06-04 15:18 | ADR-17 v0.2 accepted | 7 fork ready · §3.4 line 517-519 假设 7 widget 算法已 fulfilled |
| 2026-06-06 16:28 | ADR-17 7 fork 全 zombie 🏆 | F1+F3+F4+F5+F6+F7 全 zombie · ⚠️F2 修错(用户自修) |
| 2026-06-06 21:09 | 用户第二次原话 + Cline-AIOS 真值核查暴露 §3.4 line 517-519 盲区 | DASHBOARD v4.0.29 关键盲区诊断入账 |
| 2026-06-07 10:35 | proposed v0.1 | Cline-AIOS 起草 · 用户拍板路径 (A) ADR-17-R1 修订 |
| 2026-06-07 11:03 | accepted v0.1 | 用户拍板 accept ADR-AIOS-17-R1 · 6 fork 状态 blocked-by-accept → ready · 解锁派发 |
| 2026-06-07 11:03 | start F1 v0.1 + F3 | ClaudeB F1 phase + ClaudeA F3 scope 文件正交并行 |
| 2026-06-07 16:10 | 用户第三次原话纠错 | 架构边界错位反馈 · 触发 R2 修订 |
| 2026-06-07 16:25 | abort F1 v0.1 | 用户拍板组合 1(A1+B1)· F1 v0.1 → done/ADR-AIOS-17-R1/.aborted-2026-06-07.md |
| 2026-06-07 16:30 | proposed-revision v0.2 R2 | Cline-AIOS 起草 R2 · §3.5 5 widget × ① 段重写 · §4 fork 表 F1/F2/F4/F5 重新设计为前端为主 + 后端补 gap |
| 2026-06-13 10:23 | accepted v0.2 R2 🆕 | 用户双线并行拍板 A · accept ADR-AIOS-17-R1(R2 版本)· 同步起 ADR-AIOS-21(xilink 侧)· 5 fork ready(F1+F2+F4+F5+F6 · F3 dispatched 中保留) |
| (待) | impl Phase 1 R2 | F1 R2 phase UI + ClaudeB Step 0 P7 gap 真值核查 |
| (待) | impl Phase 2-4 R2 | F2/F4/F5 |
| (待) | impl Phase 5 R2 | F6 e2e ≥ 12 case 真值断言 |
| (待) | fulfilled 🏆 | 7 widget × 业务契约 ⑤ 段全锁 · 用户验收 |
8. 关联文档
- ADR-AIOS-17 主决议(本 R1/R2 修订其 §3.4 盲区 · F5 log_module_v1 frame 是 R2 数据源 B)
- ADR-AIOS-12 业务契约标杆(本 R1/R2 §3.5 直接引用其 §3.3-§3.6)
- ADR-AIOS-13 deferred-by-ADR-17(H1+H2+H3 触底教训源头 · H1 buffer endpoint
bcd9a74是 R2 F3 数据源) - ADR-AIOS-07 三层分工铁律(L1/L2/L3 分工 · 前端零数学 · R2 重申)
- ADR-AIOS-18 xilink 算法库 plugin(active running · R2 不重叠 · rms/fft/scope 在 xilink 内部)
- DASHBOARD v4.0.29 § 关键盲区诊断行(2026-06-06 21:09 入账)
- DASHBOARD v4.0.32 → v4.0.33(2026-06-07 16:30 R2 propose 入账 · 待)
9. 教训沉淀(Lessons Learned · R2 加 #4)
9.1 教训 #1:架构层 fulfilled ≠ 用户感知 fulfilled(R1 不变)
ADR-17 7 fork 13.5d 全 zombie 🏆 + F7 e2e 30 tests 全过 · 但用户 2.5 天后实测原话症状未改变。
根因:F7 e2e "全矩阵 7 widget × 2 mode = 14 cell smoke"仅断言渲染不崩溃 · 不断言数据准确性。架构正确 + 渲染不崩 ≠ 算法正确。
铁律(本 R1/R2 落地):任何 widget e2e 必须含 expect(数据值).toBeCloseTo(真值, 容差) 断言 · 不只 expect(canvas).toBeVisible()。F6 ≥ 12 case 真值断言示范该铁律。
9.2 教训 #2:ADR §"正交不动"假设是高危盲区源(R1 不变)
ADR-17 §3.4 line 517-519 用"与 ADR-12 §3 7 widget MeterTapService 30fps 老路径正交不动"假设 7 widget 算法已 fulfilled · 但 ADR-13 H1/H2/H3 触底已证伪此假设。
铁律:ADR 中"与某 ADR 正交不动"假设必须附核查记录 · 写明"已 grep / read / e2e 验证该 ADR 实际状态"· 否则该假设视为风险条目自动加入 §"风险与缓解"章节。
9.3 教训 #3:hotfix 链触底 → 必须升 ADR R 修订(R1 不变)
ADR-13 H1 → H2 → H3 三轮 hotfix 全部触底(从 5/7 到 2/7 widget 半实装 → 全栈架构问题)· 直到升 ADR-17 才解套。
铁律(本 R1/R2 复用):同一业务范围 ≥ 2 次 hotfix 触底 → 强制升 ADR R 修订 + 业务契约 5 必填段防线 · 不允许第 3 次 hotfix 绕过防线。
9.4 教训 #4:可视化层 vs 算法库边界混淆(R2 新增 · 关键)
触发:R1 v0.1 §3.5 5 widget 算法实装设计为"NEW P7 sidecar 5 端点 + P5 路由 + WS frame 5 type" · 用户 2026-06-07 16:10 纠错"xilink 中的 rms fft 还有 scope 是由算法库来实现 · xitest 中的所有频响 相位等曲线显示都是要么是输入设备的数据由后端和 pysidecar 来直接分析得出结果 · 要么是通过 xilink 中的 logmodule 返回的 pcm 数据进行半实时分析得到 · 我现在让你确认的是 xitest 中所有 realtime 的测量组件的实现 · 不是让你去实现 xilink 中的监控 module"。
根因:Cline-AIOS R1 v0.1 起草时未充分理解 xilink(算法库)vs xitest(可视化层 + 数据源消费)边界 · 直接套用 ADR-12 §3 业务契约模板时把所有 DSP 计算都堆到 P7 sidecar 新建端点 · 与 ADR-18 xilink 算法库职责重叠 · 也与 ADR-17 F5 log_module_v1 frame 已就位的"半实时分析"路径混淆。
铁律(本 R2 落地 · 适用所有 widget 类 ADR): 1. 任何 widget 类 ADR §"业务契约 ① 输入/输出"段必须明确 3 项:① 前端组件名称(PanelXxx.vue + useXxx composable)② 数据源订阅路径(枚举 A/B/C 多路径 + 每条路径的 endpoint 或 WS topic)③ 输出 schema(优先复用现有 frame · 仅 additive 扩展不破坏 contract-frozen) 2. 派发 widget 类 fork prompt 时强制 Step 0 三层核查:① grep 现有 P7 端点(找 gap)② grep 现有 widget stub(找真签名)③ grep 相邻 ADR 范围(确认不重叠 · 如本案 ADR-18 xilink 算法库)· 三层核查 commit message 留痕 3. 新建 P7 endpoint 是例外 · 不是默认路径:R2 §4 fork 表预设 gap endpoint 上限(本 R2 ≤ 5 个 · 若超过升 R3)· 优先尝试"消费现有数据源 + 前端轻量分析(数据源 B)"路径 4. widget endpoint selector(ADR-17 F6 已就位)是边界澄清的 UI 入口:不同数据源(physical-input / sink-pre / log-module / xitune-module)对应不同 composable 行为 · UI 联动模式选项(如 phase 数据源 B 时禁用 groupDelay 模式)
下一步:Cline-AIOS 同步 DASHBOARD v4.0.32 → v4.0.33(propose-revision ADR-AIOS-17-R1 v0.2 R2 + §🔥 删 F1 v0.1 行 + §📋 F1 v0.1 dispatched→aborted + §📋 加 F1/F2/F4/F5 R2 blocked-by-accept-R2 + §📅 加 R2 propose 决议行 + §⚡ aborted +1)→ 用户复核 R2 后
accept ADR-AIOS-17-R1(v0.2 R2 版本)→ 派发 Phase 1 R2 F1 phase UI + Step 0 真值核查 P7 端点(ClaudeA + ClaudeB 协作)。