跳转至
  • backend_csharp/Services/Meter/AudioDeviceService.cs(扩展 · 加 bypass-xilink 模式 · 行号正交 fork 1+2)
  • backend_csharp/Routes/RealtimeWsRoutes.cs(扩展 · fork 1 已落 /ws/realtime/state · 本 fork 加 /ws/realtime/stream PCM 推流 · 行号正交)
  • backend_csharp/Models/Realtime/RealtimeStreamFrame.cs(新建 · MeterFrame_ + source: "realtime-hardware" 字段)
  • backend_csharp/Program.cs(扩展 · 注册 stream WS 路由 · 行号正交 fork 1+2)
  • backend_csharp/Tests/Services/Meter/AudioDeviceServiceBypassModeTests.cs(新建 · xunit) occupies: [P5.K-services-meter(写 · 扩展 AudioDeviceService bypass), P5.K-services-realtime(read · fork 1 RealtimeSessionService 已就位)] adr: docs/08-implementation/40-aios/ADR/ADR-AIOS-13-xitest-realtime-dual-mode.md ref_section: §2.1 模式 A 真硬件直连(C#+sidecar 三层分工 bypass xilink)+ §3.1 议题 1 业务行为契约 + §11 Ximind 兼容性 created: 2026-06-02 last_modified: 2026-06-02 10:21 dispatched_at: 2026-06-02 10:21 dispatched_reason: | ADR-AIOS-13 v1.0 accepted(2026-06-01 19:21)· 用户 6/2 10:19 拍板方案 A:严守 ADR §5.4 依赖顺序 · 先派 fork 3(Phase 1 最后一个)· 等 fork 3 zombie 后再派 fork 4(Phase 2 第一个 · 严格依赖 fork 1+3 双 zombie)。 Phase 1 fork 1(P5.UA13-realtime-session-service · 92445f5 zombie)+ fork 6(P0.UA13-storage-engine-v2-captures · 92445f5 zombie)已闭环 · 本 fork 是 Phase 1 最后一个 · zombie 后解锁 Phase 2 fork 4(realtimeRunStore + 顶栏)。 与现有 4 active fork(P0.UH12 hotfix · P5.UA13-builtin-link-registry · P6.UB14-load-dynamic-plugins-api · P6.UB14-pc-host-sdk-export)文件路径完全正交。 本 fork 短任务 0.5d · ClaudeB 排期 3.8d → 4.3d(可串行 fork 1 zombie 后接 fork 2 + 本 fork)。 estimated: 0.5d preempts: [] preempted_by: null unblocks:
  • P0.UA13-realtime-run-store-toolbar(fork 4 · 等本 fork + fork 1 zombie · 现 fork 1 已 zombie · 本 fork zombie 后立即解锁)
  • ADR-13 §3.1 议题 1 模式 A 真硬件直连 e2e 验收 related_dispatched:
  • P5.UA13-builtin-link-registry(同 ClaudeB · ADR-13 fork 2 · 不同目录 Services/Link/BuiltinLinks/ vs Services/Meter/ · 文件正交)
  • P6.UB14-load-dynamic-plugins-api(ADR-14 fork 1 · ClaudeB · 不同栈 dsp_algo/framework/ · 文件正交)
  • P6.UB14-pc-host-sdk-export(ADR-14 fork 2 · ClaudeB · 不同栈 dsp_algo/dll/ · 文件正交) related_zombie:
  • P5.UA13-realtime-session-service(92445f5 · ADR-13 fork 1 · 本 fork RealtimeWsRoutes 在 fork 1 已落 /ws/realtime/state 基础上扩 /ws/realtime/stream)
  • P5.U-meter-tap-multi-tool (48cf0ba · ADR-12 #8 · 7 toolKind 路由 schema 复用 · MeterFrame_ 帧定义)

P5.UA13-audio-device-bypass-mode · ADR-13 AudioDeviceService bypass-xilink 模式 + WS PCM 推流(议题 1 模式 A 真硬件直连)

Worker:ClaudeB · 后端 (backend-csharp) / 预计:0.5d / 优先级:P1 / 状态:dispatched 隔离:🧵 文件隔离(同 worktree 同 branch · 与 ADR-13 fork 2(已 dispatched)+ ADR-14 fork 1+2(已 dispatched)+ P0.UH12 hotfix 文件路径完全正交)


🔍 触发与解锁链

触发 状态 影响
ADR-AIOS-13 v1.0 accepted(2026-06-01 19:21) ✅ user accept 8 fork ready · 用户分批 start
用户 6/2 10:19 拍板方案 A 严守 §5.4 依赖顺序 ✅ 10:19 原话 先派 fork 3 · 等 zombie 后再 fork 4
ADR-13 fork 1 P5.UA13-realtime-session-service zombie 92445f5 6/2 09:41 RealtimeSessionService + RealtimeWsRoutes 已就位 · 本 fork 在其上扩 /ws/realtime/stream
真值核查 #1(subagent · 2026-06-01 18:25) ✅ AudioDeviceService C# 已就位 · 已能 bypass xilink 直推 本 fork 仅扩展 bypass-xilink 模式 + 复用 ADR-12 #8 toolKind 路由

→ 本 fork zombie 解锁:Phase 2 fork 4(P0.UA13-realtime-run-store-toolbar · realtimeRunStore + 顶栏)。


任务定义(基于 ADR-AIOS-13 v1.0 §2.1 + §3.1 + §11)

扩展 AudioDeviceService 加 bypass-xilink 模式 + 新建 /ws/realtime/stream PCM 推流(复用 ADR-12 #8 48cf0ba 7 toolKind 路由帧 schema):

核心范围: 1. AudioDeviceService 扩 bypass-xilink 模式(新增 method StartBypassCaptureAsync(StartRealtimeRequest req) · 不走 audioEngineService 单 instance · 直接 WasapiCapture 抓 PCM → sidecar /analyze/* → 前端) 2. RealtimeWsRoutes 扩 /ws/realtime/stream(fork 1 已落 /ws/realtime/state · 本 fork 加 stream 路由 · 推 PCM 数据帧) 3. MeterFrame_ 复用 ADR-12 #8(7 toolKind:fft/rms/transfer/phase/waveform/electrical/recorder · 加 source: "realtime-hardware" 字段区分) 4. 失败回退 3 类(ADR §3.1 ③):设备被占用 / 设备拔出 / sidecar 崩溃 → 结构化 RealtimeError + recovery_hints 5. Ximind 兼容性 5 项(ADR §11):source 字段自描述 / structured error / camelCase / description? / 审计日志

不在本 fork 范围(留 fork 2 / 4 / 5): - ❌ 不实施 BuiltinLinkRegistry(fork 2 范围 · Services/Link/BuiltinLinks/) - ❌ 不实施 RealtimeSessionService 内核逻辑(fork 1 已 zombie · 本 fork 仅在其上扩 capture 数据通道) - ❌ 不实施前端 realtimeRunStore + 顶栏(fork 4 范围) - ❌ 不实施前端 input/output device 选择 UI(fork 5 范围) - ❌ 不动 contract-v1.0(realtime 走 v2 命名空间)


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

[U-thread]   P5.UA13-audio-device-bypass-mode
[部门]       后端 (backend-csharp) · 推荐 skill: dotnet-realtime-communication
[Worker CWD] d:/work/25_claude/workspace/AlgoDepartment/04_development/
[Occupies]   P5.K-services-meter(写 · AudioDeviceService 加 bypass-xilink 模式) + P5.K-services-realtime(read · fork 1 RealtimeSessionService 已就位)
[隔离]       🧵 文件隔离 · 仅写:
             - backend_csharp/Services/Meter/AudioDeviceService.cs(扩展 · 加 StartBypassCaptureAsync method · 行号正交 fork 1+2)
             - backend_csharp/Routes/RealtimeWsRoutes.cs(扩展 · fork 1 已落 /ws/realtime/state · 本 fork 加 /ws/realtime/stream PCM 推流 · 行号正交)
             - backend_csharp/Models/Realtime/RealtimeStreamFrame.cs(新建 · MeterFrame_<toolKind> + source 字段)
             - backend_csharp/Program.cs(扩展 · 注册 stream WS 路由 · 行号正交 fork 1+2)
             - backend_csharp/Tests/Services/Meter/AudioDeviceServiceBypassModeTests.cs(新建 xunit)
             与 ADR-13 fork 2 (Services/Link/BuiltinLinks/) + ADR-14 fork 1+2 (dsp_algo/framework + dll) + P0.UH12 (frontend_vue3/) 文件路径完全正交
[优先级]     P1 · 0.5d · 短任务 · 解锁 Phase 2 fork 4
[ADR]        d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/ADR/ADR-AIOS-13-xitest-realtime-dual-mode.md
             (必读 §2.1 模式 A 真硬件直连 + §3.1 议题 1 业务行为契约 5 子段 + §11 Ximind 兼容性)
[业务行为契约引用] ADR-13 §3.1(① 输入输出契约 + ② 收敛/成功判据 + ③ 失败回退 + ④ 用户操作流 + ⑤ e2e 真值)
[参考文档](绝对路径 · worker 必读)
  - ADR-13:d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/ADR/ADR-AIOS-13-xitest-realtime-dual-mode.md
    · §2.1 模式 A 数据链路图(C# AudioDeviceService L1 I/O · sidecar /analyze/* L2 数学 · 前端 widget L3 显示)
    · §2.9 三层分工铁律(继承 ADR-12 §2.10 + ADR-07 §1.3.4)
    · §3.1 议题 1 业务行为契约 5 子段(本 fork 主战场 · 必含)
    · §11.5 RealtimeError 结构(code/message/human_readable_message/recovery_hints[])
  - PCB:d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/processes/P_arch/ADR-AIOS-13/PROCESS.md
  - 范式参考(已 zombie · ClaudeB 同部门标本):
    · d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/prompts/done/P5.UA13-realtime-session-service--92445f5.md
      (本 fork parent · fork 1 RealtimeSessionService + RealtimeWsRoutes 已落 /ws/realtime/state · 本 fork 在其上扩 /ws/realtime/stream)
    · d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/prompts/done/P5.U-meter-tap-multi-tool--48cf0ba.md
      (ADR-12 #8 · 7 toolKind 路由帧 schema · 本 fork MeterFrame_<toolKind> 完全复用 · 仅加 source 字段)
  - 现状必读(主仓真值核查 · Step 1 必跑):
    · backend_csharp/Services/Meter/AudioDeviceService.cs(全文必读 · 重点看 EnumerateDevices + WasapiCapture 现有实现 + DataAvailable 事件处理)
    · backend_csharp/Services/Realtime/RealtimeSessionService.cs(read · fork 1 已 zombie · 看 _state.Mode "hardware" 切换逻辑 · 本 fork StartBypassCaptureAsync 由其调用)
    · backend_csharp/Routes/RealtimeWsRoutes.cs(read · fork 1 已落 /ws/realtime/state · 本 fork 在末尾追加 /ws/realtime/stream)
    · backend_csharp/Services/Meter/MeterTapService.cs(看 ADR-12 #8 7 toolKind 路由实现 · MeterFrame_<toolKind> 帧序列化范式)
    · backend_csharp/Routes/MeterDevApiRoutes.cs(WS PCM 推流范式 · L46-130 · 本 fork RealtimeWsRoutes /ws/realtime/stream 模仿)

【背景】
ADR-AIOS-13 v1.0 已 accepted(2026-06-01 19:21)。议题 1 决议:realtime 模式 A(真硬件直连)走 C#+sidecar 三层分工 bypass xilink engine,不写 user project,纯监听适用 Smaart 风格基础测量。

3 路 subagent 主仓真值核查(2026-06-01 18:25)发现:
  ① C# AudioDeviceService.cs L25-56 已就位:NAudio MMDeviceEnumerator + EnumerateAudioEndPoints(DataFlow.Capture)
  ② AudioDeviceService.cs L58-102 已就位:WasapiCapture + DataAvailable → MeterDataFrame
  ③ MeterDevApiRoutes.cs L46-130 已就位:WS PCM 推流(已能 bypass xilink 直推)
  ④ ADR-12 #8 P5.U-meter-tap-multi-tool `48cf0ba` 已就位:7 toolKind 路由帧 schema
  ⑤ 缺:bypass-xilink 模式入口(由 RealtimeSessionService 调用 · 非 user project flow)+ /ws/realtime/stream 路由 + source 字段标识

本 fork 核心:在 AudioDeviceService 扩 StartBypassCaptureAsync 入口(由 fork 1 RealtimeSessionService.StartAsync 调用)+ RealtimeWsRoutes 扩 /ws/realtime/stream 路由(复用 ADR-12 #8 帧 schema · 加 source: "realtime-hardware" 字段)。

【执行步骤】(7 步 · 总 0.5d)

Step 1 · 真值核查 + git pull(必跑 · 0.05d)
  - git status / git pull origin xistudio --no-rebase
  - cat backend_csharp/Services/Meter/AudioDeviceService.cs | head -120
    · 输出现有 EnumerateDevices + WasapiCapture + DataAvailable 签名
  - cat backend_csharp/Services/Realtime/RealtimeSessionService.cs | head -50
    · 输出 StartAsync hardware mode 当前是否已调用 AudioDeviceService(可能已留 hook · 也可能未)
  - cat backend_csharp/Routes/RealtimeWsRoutes.cs(全文)· 看 fork 1 落地的 /ws/realtime/state 路由结构
  - cat backend_csharp/Services/Meter/MeterTapService.cs | head -100 · 看 ADR-12 #8 帧序列化范式
  - 输出真值核查到 commit message body:
    · AudioDeviceService 当前是否含 bypass 入口:Yes / No · 现有签名:???
    · RealtimeSessionService.StartAsync hardware mode 是否调用 AudioDeviceService:Yes / No · 调用点:???
    · ADR-12 #8 MeterFrame_<toolKind> schema:??? · 复用方式:???

Step 2 · 落 RealtimeStreamFrame model(0.05d)
  - backend_csharp/Models/Realtime/RealtimeStreamFrame.cs(新建):
    public record RealtimeStreamFrame(
        string SessionId,                    // 永远 = "xitest-realtime"
        string Source,                        // "realtime-hardware" | "realtime-loopback"(fork 5+)
        string ToolKind,                      // "fft"|"rms"|"transfer"|"phase"|"waveform"|"electrical"|"recorder"
        long FrameTimestamp,                  // unix ms
        object Data                           // MeterFrame_<toolKind>(复用 ADR-12 #8 schema · 不重定义)
    );

Step 3 · 扩 AudioDeviceService bypass-xilink 模式(0.15d)
  - 在 AudioDeviceService.cs 末尾追加 method:
    public async Task<IDisposable> StartBypassCaptureAsync(
        string inputDeviceId,
        string toolKind,
        int[] channels,
        int sampleRate,
        Action<RealtimeStreamFrame> onFrame,
        CancellationToken ct)
    {
        // ① 校验 deviceId 存在(EnumerateDevices)
        // ② 校验 toolKind in 7 类
        // ③ 校验 channels.Length > 0 && channels.All(c => c >= 0 && c < 8)
        // ④ new WasapiCapture(device · sampleRate · channels)
        // ⑤ DataAvailable += (s, e) => {
        //      var data = ConvertPcmToToolKindFrame(e.Buffer · toolKind · channels)  // 路由到 MeterTapService.RouteFrame(已 zombie 的 ADR-12 #8 复用)
        //      onFrame(new RealtimeStreamFrame(SessionId="xitest-realtime", Source="realtime-hardware", ToolKind=toolKind, FrameTimestamp=DateTimeOffset.Now.ToUnixTimeMilliseconds(), Data=data))
        //   }
        // ⑥ StartRecording() · 抓 InvalidOperationException → 抛 RealtimeError(AUDIO_DEVICE_BUSY · recovery_hints=["close other audio software", "select different device"])
        // ⑦ 注册 MMDevice.OnPropertyValueChanged · State=NotPresent → 自动 Stop + 触发 onFrame(error)
        // ⑧ 返 IDisposable(stop + dispose 触发清理)
    }
  - 不动现有 EnumerateDevices/WasapiCapture/DataAvailable(零回归)
  - 不写 user project 链路(严守 bypass)

Step 4 · 扩 RealtimeWsRoutes /ws/realtime/stream(0.1d)
  - backend_csharp/Routes/RealtimeWsRoutes.cs(在 fork 1 落地的 /ws/realtime/state 之后追加 method):
    public static void MapRealtimeStreamWs(this WebApplication app)
    {
        app.Map("/ws/realtime/stream", async (HttpContext ctx, IRealtimeSessionService sessionSvc, IAudioDeviceService deviceSvc) =>
        {
            if (!ctx.WebSockets.IsWebSocketRequest) { ctx.Response.StatusCode = 400; return; }
            var state = sessionSvc.GetState();
            if (state.Status != "running" || state.Mode != "hardware") {
                ctx.Response.StatusCode = 400;
                await ctx.Response.WriteAsJsonAsync(new RealtimeError(
                    Code: "SESSION_NOT_RUNNING_HARDWARE_MODE",
                    Message: "Realtime session not in running/hardware state",
                    HumanReadableMessage: "请先启动 realtime 测量(模式 A 硬件直连)",
                    RecoveryHints: new[] { "POST /api/realtime/start with mode=hardware first" },
                    Context: new() { ["currentStatus"] = state.Status, ["currentMode"] = state.Mode ?? "" }
                ));
                return;
            }
            using var ws = await ctx.WebSockets.AcceptWebSocketAsync();
            using var capture = await deviceSvc.StartBypassCaptureAsync(
                inputDeviceId: state.InputDeviceId!,
                toolKind: state.ToolKind ?? "fft",  // fork 1 StartRealtimeRequest 已含 ToolKind 字段
                channels: state.Channels ?? new[] { 0, 1 },
                sampleRate: state.SampleRate ?? 48000,
                onFrame: frame => SendFrameAsync(ws, frame, ctx.RequestAborted).GetAwaiter().GetResult(),
                ct: ctx.RequestAborted);
            // 等 ctx.RequestAborted · capture.Dispose 自动触发
            try { await Task.Delay(Timeout.Infinite, ctx.RequestAborted); } catch { }
        });
    }
    private static async Task SendFrameAsync(WebSocket ws, RealtimeStreamFrame frame, CancellationToken ct) { ... JSON serialize + SendAsync ... }
  - Program.cs 加 1 行 `app.MapRealtimeStreamWs();`(模仿 fork 1 的 MapRealtimeWs 风格 · 行号正交 fork 2 加的 MapBuiltinLinkApi)

Step 5 · 落 xunit 测试(0.1d)
  - backend_csharp/Tests/Services/Meter/AudioDeviceServiceBypassModeTests.cs · 6+ case:
    · StartBypassCaptureAsync_InvalidDeviceId_ThrowsAudioDeviceNotFoundError
    · StartBypassCaptureAsync_InvalidToolKind_ThrowsInvalidRequestError
    · StartBypassCaptureAsync_DeviceBusy_ThrowsAudioDeviceBusyError(模拟 InvalidOperationException · 验证 recovery_hints 含 "close other audio software")
    · StartBypassCaptureAsync_ValidParams_StartsRecording_AndEmitsFrames(用 Mock<IMMDevice> + Mock<WasapiCapture> · 验证 onFrame 被调用 · frame.Source == "realtime-hardware")
    · StartBypassCaptureAsync_DevicePropertyChanged_NotPresent_TriggersStopAndErrorFrame(模拟 MMDevice.OnPropertyValueChanged · State=NotPresent)
    · StartBypassCaptureAsync_Dispose_StopsRecording(验证 IDisposable 触发清理)

Step 6 · build + test + 手动 e2e + commit(0.05d)
  - cd backend_csharp && dotnet build(零错误零警告 · 基线 217+9(fork 1)/0)
  - dotnet test(基线 +6 用例 · 226 → 232)
  - 手动 e2e(可选 · 若 sln 可启动):
    · dotnet run · 先 POST /api/realtime/start mode=hardware inputDeviceId=<some-real-device> toolKind=fft channels=[0] sampleRate=48000
    · 然后 wscat -c ws://localhost:5000/ws/realtime/stream → 应收到 RealtimeStreamFrame 流(source="realtime-hardware" + toolKind="fft" + Data=MeterFrame_fft)
    · POST /api/realtime/stop · WS 连接断开
  - git add backend_csharp/Services/Meter/AudioDeviceService.cs backend_csharp/Routes/RealtimeWsRoutes.cs backend_csharp/Models/Realtime/RealtimeStreamFrame.cs backend_csharp/Program.cs backend_csharp/Tests/Services/Meter/AudioDeviceServiceBypassModeTests.cs
  - git commit(三元组 trailer 见下) · git push origin xistudio

【验收】

形式合规:
- [ ] dotnet build 零错误零警告
- [ ] dotnet test 全绿(基线 +6 用例)
- [ ] 仅 5 文件修改:1 model + 1 service 扩展 + 1 routes 扩展 + Program.cs(注册 1 行)+ 1 测试文件
- [ ] 不动 contract-v1.0 / RealtimeSessionService 内核(fork 1 已 zombie · 只读)/ Services/Link/(fork 2 范围)/ MeterTapService 内核(ADR-12 #8 已 zombie · 只复用 7 toolKind 路由)
- [ ] 0 引入新 NuGet 包(System.Net.WebSockets 已在 .NET 运行时)

业务行为契约(端到端真值 · 必跑 · ADR §3.1):
- [ ] WasapiCapture.StartRecording() 不抛异常 · 5s 内首帧到达(测试 mock 验证)
- [ ] FPS ≥ 25(测试 mock 模拟 buffer · 验证 onFrame 调用频率)
- [ ] channels.length === 用户选定(测试用例覆盖 1/2/4/8 通道)
- [ ] 设备占用 → AUDIO_DEVICE_BUSY + recovery_hints
- [ ] 设备拔出 → 自动 stop + error frame(NotPresent state)
- [ ] sidecar 502 → 不在本 fork 范围(留 fork 4/5 · 前端处理)
- [ ] WS 帧 schema 含 source: "realtime-hardware" 字段

Ximind 兼容性(ADR §11 · 必跑):
- [ ] RealtimeStreamFrame.Source 字段自描述("realtime-hardware" · 大模型可解析)
- [ ] RealtimeStreamFrame.ToolKind 字段(7 类自描述)
- [ ] RealtimeError(code + message + human_readable_message + recovery_hints[])· 复用 fork 1 已落
- [ ] camelCase JSON 序列化
- [ ] 审计日志(可选 · /ws/realtime/stream 连接事件可附 audit · 但不强制)

【commit】
subject:`feat(P5.UA13-audio-device-bypass-mode): AudioDeviceService bypass-xilink + WS /ws/realtime/stream PCM streaming · ADR-13 §2.1 §3.1 §11`

trailer(必须精确 · 三元组):
[step=7/7] [pid=P5] [uid=UA13-audio-device-bypass-mode] [occupies=P5.K-services-meter+P5.K-services-realtime(read)]
[files=Services/Meter/AudioDeviceService.cs, Routes/RealtimeWsRoutes.cs, Models/Realtime/RealtimeStreamFrame.cs, Program.cs, Tests/Services/Meter/AudioDeviceServiceBypassModeTests.cs]
[isolation] file(同 worktree 同 branch · 与 ADR-13 fork 2(Services/Link/BuiltinLinks/)+ ADR-14 fork 1+2(dsp_algo/)+ P0.UH12(frontend_vue3/)文件路径完全正交)
[derived_from] ADR-AIOS-13 v1.0 §2.1 + §3.1 + §11 · parent zombie 92445f5(fork 1 RealtimeSessionService)+ 48cf0ba(ADR-12 #8 7 toolKind 路由)
[truth-check] AudioDeviceService bypass 入口现状=??? · RealtimeSessionService.StartAsync hardware 调用点=??? · ADR-12 #8 MeterFrame schema=???(Step 1 输出真值)
[acceptance] WS /ws/realtime/stream 连接验证 · MeterFrame_<toolKind> + source 字段 · xunit 6+ 用例全绿 · 设备占用/拔出 失败回退验证
[ximind] 5 项检查清单全过(source 自描述 · toolKind 自描述 · structured error · camelCase · audit log)

【禁止】(7 条红线)
1. ❌ 不修改 backend_csharp/Services/Realtime/(fork 1 已 zombie · 只读)
2. ❌ 不修改 backend_csharp/Services/Link/BuiltinLinks/(fork 2 范围)
3. ❌ 不动 contract-v1.0 / MeterTapService 内核(ADR-12 #8 已 zombie · 仅复用 7 toolKind 路由)
4. ❌ 不实施前端 realtimeRunStore + 顶栏(fork 4 范围)
5. ❌ 不实施 user project flow(本 fork 严守 bypass-xilink · 不写 user link)
6. ❌ 不省略 Step 1 真值核查报告(commit body 必含 AudioDeviceService 现状 + RealtimeSessionService hardware mode 调用点)
7. ❌ 不省略 RealtimeStreamFrame.Source 字段(Ximind 铁律 · 大模型基于此区分 hardware vs loopback)

解锁链(本任务 zombie 后)

  • ✅ Phase 2 fork 4 P0.UA13-realtime-run-store-toolbar(fork 1+3 双 zombie 满足 · realtimeRunStore 调 /api/realtime/start + 监听 /ws/realtime/stream)
  • ✅ ADR-13 §3.1 议题 1 模式 A 真硬件直连业务行为契约 5 子段闭环
  • ✅ 后端 Phase 1 三 fork 全 zombie(等 fork 2 P5.UA13-builtin-link-registry zombie 后 · ADR-13 Phase 1 整体闭环)

风险评估

风险 缓解
⚠️ AudioDeviceService 现有 EnumerateDevices/WasapiCapture 可能与 ADR §3.1 假设不符 Step 1 真值核查必跑 · 不一致(eg. 异步签名 / 不同 NAudio 版本)→ commit body 报告 + 适配
⚠️ ADR-12 #8 MeterFrame_ schema 可能在 fork 1 zombie 后已修改 Step 1 read MeterTapService.cs · 验证 7 toolKind 路由 schema 仍可复用 · 若已变 → 适配新 schema
⚠️ WS Channel race condition(stream WS 与 state WS 可能同时连接) 完全独立 endpoint · /ws/realtime/state(fork 1)推元数据 / /ws/realtime/stream(本 fork)推 PCM · 互不干扰
⚠️ 设备拔出事件 MMDevice.OnPropertyValueChanged 在 NAudio 0.x 不一定支持 Step 3 实施前 grep MMDevice.OnPropertyValueChanged 确认 · 不支持则降级:用定时器轮询 device.State
⚠️ 与 fork 2 + ADR-14 fork 1+2 同 PR 合并冲突 Program.cs 4 fork 都改 Program.cs 但行号正交(本 fork 加 MapRealtimeStreamWs · fork 2 加 MapBuiltinLinkApi · ADR-14 fork 1+2 改 dsp_algo 不动 Program.cs)· git pull 自动合并
⚠️ ToolKind 字段在 fork 1 RealtimeSessionState 中可能没保存 若 fork 1 RealtimeSessionState 没 ToolKind 字段 → 本 fork 在 RealtimeStreamFrame 用默认 fft · 用户 6/2 业务补充处理 sequence 时再扩(留 fork 8 e2e 验证)

历史

时间 事件 hash
2026-06-02 10:21 dispatched · 用户 6/2 10:19 拍板方案 A 严守 §5.4 依赖顺序(先派 fork 3 等 zombie 后再 fork 4)· ClaudeB 0.5d 🧵 file 与 ADR-13 fork 2 + ADR-14 fork 1+2 + P0.UH12 文件正交 · parent zombie 92445f5(fork 1 RealtimeSessionService)+ 48cf0ba(ADR-12 #8 7 toolKind)· 解锁 Phase 2 fork 4