P0.UA13-realtime-run-store-toolbar · ADR-13 顶栏单按钮 + realtimeRunStore(议题 3.1)
Worker:ClaudeA · 前端 / 预计:0.5d / 优先级:P1 / 状态:dispatched 隔离:🧵 文件隔离(同 worktree 同 branch · 与 ADR-13 fork ½/⅗/6 + ADR-09 4 active fork + P0.UH12 等所有 active 文件路径完全正交)
🔍 触发与解锁链
| 触发 | 状态 | 影响 |
|---|---|---|
| ADR-AIOS-13 v1.0 accepted(2026-06-01 19:21) | ✅ user accept | 8 fork ready · Phase 2 fork 4 |
fork 1 P5.UA13-realtime-session-service zombie(92445f5) |
✅ 后端 API/WS 已就位 | 本 fork 直接调 /api/realtime/{start,stop,state} + WS /ws/realtime/state |
| fork 3 P5.UA13-audio-device-bypass-mode dispatched(未 zombie · 0.5d 即将) | ⚠️ PCM 通道未端到端验证 | 本 fork 不直接依赖 fork 3 内部实现(只维护 store + toolbar)· widget 端到端 PCM 联调留 fork 7 |
| ⭐ 用户拍板提前派发(2026-06-02 10:33) | ✅ "马上结束了 我们先提前继续这个 prompt" | 放宽 §5.4 fork 1+3 双 zombie 严格约束 · 提前推进 fork 4 |
fork 6 P0.UA13-storage-engine-v2-captures zombie(92445f5) |
✅ capture schema 已就位 | 顶栏 capture/recapture 按钮 id 注册占位即可 · 实施 fork 7 |
→ 本 fork zombie 解锁:Phase 3 fork 7 P0.UA13-capture-toolbar-multi-widget(直接监听 toolbar:click 事件 + 读 realtimeRunStore.isRunning)+ fork 8 e2e 真值。
任务定义(基于 ADR-AIOS-13 v1.0 §2.5 + §2.6 + §3.3)
新建 realtimeRunStore Pinia(范式参考 xilink engineStore b4a8ea2)· 替换 xitest stage 顶栏 3 个死按钮为 realtime 三按钮 · watchEffect 同步 ▶/■ icon · eventBus 监听 toolbar:click。
核心范围:
1. realtimeRunStore Pinia(stores/realtimeRunStore.ts 新建):state(isRunning / activeMode / inputDeviceId / outputDeviceId / signalConfig / error)+ actions(start() POST /api/realtime/start · stop() POST /api/realtime/stop · connectWS() 订 /ws/realtime/state 推送)
2. xitest 顶栏改造(stages/xitest/index.vue · L70-72 死按钮区):
- 删旧 xitest:run-suite / xitest:stop 死按钮 emit(LEGACY_EVENTBUS 旧按钮无监听者 · 直接删)
- 新增 3 ToolbarButton:realtime-run(▶ · watchEffect 切 ■)+ realtime-capture(📸 · 注册占位 · 实施 fork 7)+ realtime-recapture(🔄 · 注册占位 · 实施 fork 7)
- watchEffect 监听 realtimeRunStore.isRunning → shellSlots.setToolbarButtonProps('realtime-run', { icon, tip })
- eventBus.on('toolbar:click', ...) 仅处理 realtime-run(start/stop 互斥) · capture/recapture id 抛事件 fork 7 接管(本 fork 不实施 handler)
- onMounted 调 realtimeRunStore.connectWS() · onUnmounted 关 WS
3. vitest 单测(stores/__tests__/realtimeRunStore.spec.ts 新建):store state/actions 基础用例(start/stop/error/WS 推送 mock · 不需 e2e)
4. Ximind 兼容性 5 项(ADR §11):store state 字段 camelCase 自描述 · activeMode 含 'hardware'|'loopback' 语义 · error structured(code + message + recoveryHints[])
不在本 fork 范围:
- ❌ 不实施 capture/recapture 弹框 UI(fork 7 范围 · 本 fork 仅注册按钮 id)
- ❌ 不实施多 widget 同 groupId 抓取逻辑(fork 7 范围)
- ❌ 不实施 LeftDock § Engine 段 input/output device 选择 UI(fork 5 范围)
- ❌ 不动后端 / contracts / dsp_algo 任何代码(0 后端依赖 · fork 1 已落 API)
- ❌ 不端到端联调 fork 3 PCM /ws/realtime/stream(widget 层用 · 留 fork 7)
完整 prompt(直接复制粘贴 worker 终端)
[U-thread] P0.UA13-realtime-run-store-toolbar
[部门] 前端 P0-xishell · 推荐 skill: vuejs-typescript-best-practices
[Worker CWD] d:/work/25_claude/workspace/AlgoDepartment/04_development/
[Occupies] P0.K-realtime-run-store(写 · 新建 Pinia)+ P0.K-xitest-stage-toolbar(写 · 替死按钮 + 注册三按钮 id)
[隔离] 🧵 文件隔离 · 仅写:
- frontend_vue3/src/stores/realtimeRunStore.ts(新建 · Pinia · 范式参考 engineStore b4a8ea2)
- frontend_vue3/src/stages/xitest/index.vue(扩展 · TOOLBAR 死按钮替换 + watchEffect + eventBus 监听 · 行号正交其他段)
- frontend_vue3/src/stores/__tests__/realtimeRunStore.spec.ts(新建 vitest)
与 ADR-13 fork 1/2/3(后端 backend_csharp/)+ fork 5(stages/xitest/drawers/EnginePanel.vue)+ fork 6(storage/types · 已 zombie)+ ADR-09 4 active + P0.UH12(同 stages/xitest/ 但行号正交)文件路径完全正交
[优先级] P1 · 0.5d · ⚠️ 用户拍板提前派发(放宽 §5.4 fork 1+3 双 zombie 依赖 · fork 1 已 zombie 92445f5 · fork 3 即将 zombie)
[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.5 realtimeRunStore + 顶栏单按钮 watchEffect 完整代码 + §2.6 capture/recapture 按钮注册占位 + §3.3 议题 3 业务行为契约 5 子段 + §11 Ximind 兼容性)
[业务行为契约引用] ADR-13 §3.3(① realtimeRunStore state schema + 与 xilink 互斥 API 行为 + ② 顶栏按钮切换 100ms / WS 帧 < 500ms / 互斥成功判据 + ③ WS 断开 / xilink stuck 失败回退 + ④ 用户操作流(正常+互斥)+ ⑤ e2e exclusion 真值)
[参考文档](绝对路径 · 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.4 后端 RealtimeSessionService API + WS schema(本 fork 调用 · fork 1 已落)
· §2.5 完整 realtimeRunStore + xitest TOOLBAR + watchEffect + eventBus 代码(本 fork 抄)
· §2.6 capture/recapture 按钮 schema(本 fork 仅注册 id · handler 留 fork 7)
· §3.3 议题 3 业务行为契约 5 子段(verify 必跑)
· §11.1+§11.2 Ximind 可读状态(realtimeRunStore.isRunning/activeMode/error)+ 可写操作(start/stop)
- 范式参考(已 zombie · ClaudeA 同部门标本):
· d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/prompts/done/P0.U-engine-session-snapshots--b4a8ea2.md
(⭐ xilink engineStore Pinia 范式 · LeftDock § Engine + Session + Snapshots 三段 · 本 fork realtimeRunStore 直接对标 engineStore 结构)
· d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/prompts/done/P0.U-measurement-recorder-real--824b2a5.md
(⭐ widget 内 watchEffect + 顶栏按钮 props 同步范式)
- parent zombie(必读 · 本 fork 直接调用其 API):
· d:/work/25_claude/workspace/AlgoDepartment/06_docs/site-build/docs/08-implementation/40-aios/prompts/done/P5.UA13-realtime-session-service--92445f5.md
(后端 RealtimeSessionService · /api/realtime/start/stop/state · WS /ws/realtime/state · 与 xilink 互斥逻辑封装在后端)
- 现状必读(主仓真值核查 · Step 1 必跑):
· frontend_vue3/src/stores/engineStore.ts(全文必读 · ⭐ 抄 Pinia 结构:state/actions/connectWS · b4a8ea2 已落)
· frontend_vue3/src/stages/xitest/index.vue(全文必读 · 重点看 TOOLBAR 死按钮当前位置 L70-72 + 现有 toolbar:click 监听是否已存在 + onMounted/onUnmounted 钩子)
· frontend_vue3/src/types/shell.ts 或 toolbar.ts(必读 · 看 ToolbarButton 接口字段)
· frontend_vue3/src/utils/eventBus.ts(必读 · 看 toolbar:click 事件 schema)
· frontend_vue3/src/composables/useShellSlots.ts(若存在 · 必读 · setToolbarButtonProps API 签名)
【背景】
ADR-AIOS-13 v1.0 accepted(2026-06-01 19:21)。议题 3.1 决议:xitest 顶栏单按钮 + realtimeRunStore Pinia · 复用 xilink engineStore 范式 · 与 xilink user project 互斥(后端封装)。
⚠️ 用户拍板提前派发(2026-06-02 10:33 原话:"马上结束了 我们先提前继续这个 prompt")· 放宽 ADR §5.4 fork 1+3 双 zombie 严格约束:
- fork 1 P5.UA13-realtime-session-service 已 zombie(`92445f5` · 后端 API/WS 完整就位)
- fork 3 P5.UA13-audio-device-bypass-mode 已 dispatched(2026-06-02 10:21 · 0.5d · 即将 zombie · 不阻塞本 fork)
- 本 fork 仅维护 store + toolbar 状态机 · 不直接调 fork 3 PCM 通道(`/ws/realtime/stream` 是 widget 层调用 · 留 fork 7)
- 后端互斥逻辑(realtime start → 自动 stop xilink)封装在 RealtimeSessionService(fork 1 已落)· 前端只读 WS 推送即可
3 路真值核查锚点:
① engineStore.ts `b4a8ea2` 已落 · 含 connectWS / start / stop · 本 fork 直接抄结构
② stages/xitest/index.vue L70-72 现有死按钮(`xitest:run-suite` / `xitest:stop` emit · 无监听者 · 安全删)
③ ADR §3.3 ⑤ e2e exclusion 真值脚本(xilink running → start realtime → xilink should stop)留 fork 8 跑 · 本 fork 仅落 store + toolbar
本 fork 核心:realtimeRunStore Pinia + xitest TOOLBAR 三按钮 + watchEffect ▶/■ + eventBus 监听 + vitest 基础用例 · 0 破坏现有 xitest 行为(死按钮删除 · 真按钮接管)。
【执行步骤】(7 步 · 总 0.5d)
Step 1 · 真值核查 + git pull(必跑 · 0.05d)
- git status / git pull origin xistudio --no-rebase
- cat frontend_vue3/src/stores/engineStore.ts(全文 · 输出关键段:state 字段名 + actions 签名 + connectWS 实现风格)
- cat frontend_vue3/src/stages/xitest/index.vue(全文 · 输出 L70 附近 TOOLBAR 数组当前内容 + onMounted/onUnmounted 当前钩子内容 + 是否已 import realtimeRunStore)
- cat frontend_vue3/src/types/shell.ts 或 grep 'ToolbarButton'(确认接口字段)
- cat frontend_vue3/src/utils/eventBus.ts(确认 toolbar:click 事件 payload schema)
- 输出真值核查到 commit message body:
· engineStore.ts state 字段 = ???
· engineStore.ts actions 签名 = ???
· stages/xitest/index.vue TOOLBAR 死按钮当前 ids = ???
· ToolbarButton 接口字段 = ???
· eventBus toolbar:click payload = ???
· ⭐ /api/realtime/start 后端响应 schema(读 fork 1 zombie commit `92445f5` 验证)= ???
Step 2 · 落 realtimeRunStore Pinia(0.15d)
- frontend_vue3/src/stores/realtimeRunStore.ts(新建 · 抄 ADR §2.5 + 对齐 engineStore 风格):
import { defineStore } from 'pinia'
export type ActiveMode = 'hardware' | 'loopback'
export interface SignalConfig {
type: 'sine' | 'pink-noise' | 'white-noise' | 'sweep'
frequency?: number
amplitudeDbfs: number
}
export interface RealtimeError {
code: string // 'WS_DISCONNECTED' | 'XILINK_STOP_FAILED' | 'DEVICE_BUSY' | ...
message: string // 自然语言描述(Ximind)
recoveryHints: string[] // 恢复建议(Ximind)
}
export const useRealtimeRunStore = defineStore('realtimeRun', {
state: () => ({
isRunning: false,
activeMode: null as ActiveMode | null,
inputDeviceId: null as string | null,
outputDeviceId: null as string | null,
signalConfig: null as SignalConfig | null,
error: null as RealtimeError | null,
wsConnected: false,
}),
actions: {
async start(payload: { mode: ActiveMode; inputDeviceId: string; outputDeviceId?: string; signalConfig?: SignalConfig }) {
// POST /api/realtime/start · 失败 set error · 成功等 WS state 推送 set isRunning
// 后端封装互斥(若 xilink running → 自动 stop xilink → 再 start) · response.body.previousSessionStopped 可能存在
},
async stop() {
// POST /api/realtime/stop · 失败 set error · 成功等 WS 推送 set isRunning=false
},
connectWS() {
// ws://.../ws/realtime/state · onmessage:更新 isRunning/activeMode/inputDevice/outputDevice/error
// onclose:set wsConnected=false · 自动重连(参考 engineStore 范式)
},
disconnectWS() { /* 清理 */ },
clearError() { this.error = null },
},
})
- 关键点:
· 后端 API/WS schema 严格对齐 fork 1 `92445f5` 实现(Step 1 真值核查)· 字段不能脑补
· activeMode null 表示未 running · 'hardware'/'loopback' 由 WS 推送决定
· error structured · code + message + recoveryHints[](Ximind)
· connectWS 重连策略对齐 engineStore.ts(若 b4a8ea2 用 exponential backoff · 抄)
Step 3 · 改 stages/xitest/index.vue 顶栏(0.15d)
- 删 L70-72 附近旧 TOOLBAR 死按钮(`xitest:run-suite` + `xitest:stop`)· grep 全工程确认无监听者(应 0 个 · 死按钮)· 若发现 LEGACY 监听 → 加 LEGACY_EVENTBUS_MAP 注释(7 天宽限)
- 新 TOOLBAR 数组(抄 ADR §2.5 + §2.6):
const TOOLBAR: ToolbarButton[] = [
{ id: 'realtime-run', icon: '▶', tip: '启动 realtime 测量' },
{ id: 'realtime-capture', icon: '📸', tip: 'Capture · 抓取当前所有曲线' }, // fork 7 实施 handler
{ id: 'realtime-recapture', icon: '🔄', tip: 'Recapture · 用当前数据更新选中历史 capture' }, // fork 7 实施 handler
]
- watchEffect(onMounted 内或 setup 顶层 · 对齐工程现有风格):
watchEffect(() => {
const running = realtimeRunStore.isRunning
shellSlots.setToolbarButtonProps('realtime-run', {
icon: running ? '■' : '▶',
tip: running ? '停止 realtime 测量' : '启动 realtime 测量',
})
})
- eventBus 监听(仅 realtime-run handler · capture/recapture 抛事件 fork 7 接管):
const handleToolbarClick = ({ stage, id }) => {
if (stage !== 'xitest') return
if (id === 'realtime-run') {
if (realtimeRunStore.isRunning) {
realtimeRunStore.stop()
} else {
// ⭐ 启动需 mode + inputDevice · 暂从 LeftDock § Engine 状态读(fork 5 落 UI · 本 fork 用降级)
// 降级方案:若 store 字段未 ready → 弹 console.warn 提示用户先在 LeftDock 选 device
// fork 5 zombie 后由 fork 5 prompt 在 panel save 时填 store · 自然衔接
const cfg = {
mode: realtimeRunStore.activeMode ?? 'hardware',
inputDeviceId: realtimeRunStore.inputDeviceId ?? '',
outputDeviceId: realtimeRunStore.outputDeviceId ?? undefined,
signalConfig: realtimeRunStore.signalConfig ?? undefined,
}
if (!cfg.inputDeviceId) {
console.warn('[realtime-run] inputDeviceId 未设置 · 请先在 LeftDock § Engine 选 input device')
return
}
realtimeRunStore.start(cfg)
}
}
// capture / recapture 不在本 fork handler · fork 7 接管
}
eventBus.on('toolbar:click', handleToolbarClick)
onUnmounted(() => eventBus.off('toolbar:click', handleToolbarClick))
- onMounted/onUnmounted 钩子加 connectWS()/disconnectWS()
⚠️ 行号正交:仅改 TOOLBAR 数组段 + onMounted/setup 内 watchEffect/eventBus 段 · 不动 widget 渲染段 / LeftDock 段 / 任何 ADR-12 已落业务
Step 4 · vitest 单测(0.1d)
- frontend_vue3/src/stores/__tests__/realtimeRunStore.spec.ts(新建):
· initial state · isRunning=false / activeMode=null / error=null
· start() 调用 fetch /api/realtime/start · 成功 · 等 WS 推送
· start() 调用失败 · set error structured(code + message + recoveryHints)
· stop() 调用 fetch /api/realtime/stop · 成功 · WS 推 isRunning=false
· WS message {status:'running', mode:'hardware', ...} → state 同步
· WS close → wsConnected=false + 自动重连(可 fake timer)
· clearError() · 清 error
- 期望 +8~10 用例
- mock fetch 用 vi.spyOn(global, 'fetch') · mock WebSocket 用 vitest-websocket-mock 或自实现 mock(对齐 engineStore.spec 风格)
Step 5 · build + test + 浏览器手动验证(0.1d)
- cd frontend_vue3
- npm run typecheck(零错误)
- npm run test:unit(基线 376~381/3 · 本 fork +8~10 = 384~391/3)
- 浏览器手动:
· 启后端(主仓 backend_csharp 跑起 · fork 1 92445f5 已落)· npm run dev
· 打开 xitest stage · 顶栏看 ▶/📸/🔄 三按钮(死按钮已替换)
· DevTools Network → ws://.../ws/realtime/state 已连
· 暂用 console 调 useRealtimeRunStore().start({mode:'hardware', inputDeviceId:'<某 deviceId>'}) · 顶栏 ▶ → ■(若 fork 5 未落 · 用 console 直接调 store)
· 调 stop() · 顶栏 ■ → ▶
· 关后端 → WS close · console 看到 wsConnected=false
- ⚠️ 端到端 PCM 联调(WS /ws/realtime/stream)留 fork 7 验证 · 本 fork 仅验 store + toolbar
- ⚠️ 若 fork 3 未 zombie · 后端 PCM 通道可能未启 · 不影响本 fork(本 fork 不订 stream WS)
Step 6 · grep 残留 + 形式合规(0.025d)
- grep -r 'xitest:run-suite' frontend_vue3/src/ · 期望 0 命中(死按钮 emit 已清)
- grep -r 'xitest:stop' frontend_vue3/src/ · 期望 0 命中
- 若有残留监听 · 加 LEGACY_EVENTBUS_MAP 注释(7 天宽限)
Step 7 · commit + push(0.025d)
- git add frontend_vue3/src/stores/realtimeRunStore.ts frontend_vue3/src/stores/__tests__/realtimeRunStore.spec.ts frontend_vue3/src/stages/xitest/index.vue
- git commit(三元组 trailer 见下) · git push origin xistudio
【验收】
形式合规:
- [ ] npm run typecheck 零错误
- [ ] npm run test:unit 全绿(基线 +8~10)
- [ ] 仅 3 文件修改(1 store + 1 stage 扩展 + 1 测试)
- [ ] 不动 ADR-12 §3 7 类 MeasurementNode 实施 / LeftDock 任何段 / widget 渲染段
- [ ] 不动后端 / contracts / dsp_algo 任何代码
- [ ] 不引入新 NPM 依赖
- [ ] grep 旧死按钮 emit 0 残留(xitest:run-suite / xitest:stop)
- [ ] capture / recapture 按钮 id 已注册 · handler 留空(fork 7 接管)
业务行为契约(ADR §3.3):
- [ ] realtimeRunStore state schema 完整(7 字段 + RealtimeError structured · ADR §3.3 ①)
- [ ] start() 调用后 isRunning 由 WS 推送同步切 true(非 optimistic update)· 切换 100ms 内(ADR §3.3 ②)
- [ ] stop() 调用后 isRunning 由 WS 推送切 false
- [ ] WS 断开 · wsConnected=false · 自动重连尝试(ADR §3.3 ③ · UI 灰由 fork 5 panel 实施)
- [ ] error.code='XILINK_STOP_FAILED' 时 message + recoveryHints 完整(ADR §3.3 ③)
- [ ] 顶栏 watchEffect 切 ▶↔■ icon + tip 同步(ADR §3.3 ②)
- [ ] eventBus 'toolbar:click' { stage:'xitest', id:'realtime-run' } 触发 start/stop 互斥(ADR §3.3 ④)
- [ ] (留 fork 8)e2e exclusion · xilink running → start realtime → xilink auto stop(本 fork 仅准备 store · e2e fork 8 跑)
Ximind 兼容性(ADR §11):
- [ ] state 字段 camelCase 自描述(isRunning / activeMode / inputDeviceId / signalConfig · 无缩写)
- [ ] activeMode 含语义('hardware'|'loopback')· 大模型可解释
- [ ] error structured(code + message + recoveryHints[] · 大模型可基于 hints 自主重试 / 求助用户)
- [ ] start() payload 含 mode + signalConfig 自然语言描述字段
- [ ] WS 推送 frame 含 status / mode / errorEvent 语义字段(对齐 fork 1 后端 schema)
【commit】
subject:`feat(P0.UA13-realtime-run-store-toolbar): realtimeRunStore + xitest TOOLBAR ▶/📸/🔄 + watchEffect + eventBus · ADR-13 §2.5 §2.6 §3.3 §11`
trailer(必须精确 · 三元组):
[step=7/7] [pid=P0] [uid=UA13-realtime-run-store-toolbar] [occupies=P0.K-realtime-run-store, P0.K-xitest-stage-toolbar]
[files=frontend_vue3/src/stores/realtimeRunStore.ts, frontend_vue3/src/stages/xitest/index.vue, frontend_vue3/src/stores/__tests__/realtimeRunStore.spec.ts]
[isolation] file(同 worktree 同 branch · 与 ADR-13 fork 1/2/3/5/6 + ADR-09 4 active + P0.UH12 文件路径完全正交)
[derived_from] ADR-AIOS-13 v1.0 §2.5 + §2.6 + §3.3 + §11 · parent zombie 92445f5(fork 1 P5.UA13-realtime-session-service 后端 API/WS) · 范式 b4a8ea2(engineStore Pinia)
[user-decision] 2026-06-02 10:33 用户原话"马上结束了 我们先提前继续这个 prompt" · 放宽 §5.4 fork 1+3 双 zombie 依赖 · fork 3 dispatched 未 zombie 不阻塞(本 fork 不调 PCM 通道)
[truth-check] engineStore state=??? · TOOLBAR 现 ids=??? · ToolbarButton 字段=??? · /api/realtime/start 响应 schema=???(Step 1 输出)
[acceptance] store 7 字段 + 4 actions 全过 · TOOLBAR 三按钮注册 · watchEffect ▶↔■ · eventBus realtime-run handler · vitest +8~10 全绿 · grep 死按钮 0 残留
[ximind] 5 项检查清单全过(camelCase / activeMode 语义 / error structured + recoveryHints / mode signalConfig 描述字段)
【禁止】(7 条红线)
1. ❌ 不实施 capture/recapture 弹框 UI 或 handler(fork 7 范围 · 本 fork 仅注册 id)
2. ❌ 不实施 LeftDock § Engine 段 input/output device 选择 UI(fork 5 范围)
3. ❌ 不动 ADR-12 §3 7 类 MeasurementNode 业务行为契约(只在 stages/xitest/index.vue TOOLBAR + onMounted 段改)
4. ❌ 不动后端 / contracts / dsp_algo 任何代码(0 后端依赖 · fork 1 已落 API)
5. ❌ 不订 WS /ws/realtime/stream(PCM 通道 · widget 层调用 · fork 7 范围)
6. ❌ 不写后端互斥逻辑(realtime start 自动 stop xilink 已封装在 fork 1 RealtimeSessionService)
7. ❌ 不省略 Step 1 真值核查报告(commit body 必含 engineStore state / TOOLBAR ids / ToolbarButton 字段 / /api/realtime/start 响应 schema)
解锁链(本任务 zombie 后)
- ✅ Phase 3 fork 7 P0.UA13-capture-toolbar-multi-widget(直接接管 toolbar:click 事件 capture/recapture id + 读 realtimeRunStore.isRunning + 调 storageEngine.saveCapture(fork 6 已落))
- ✅ Phase 3 fork 8 P_e2e.UA13-truth(e2e exclusion 真值:xilink running → start realtime → xilink auto stop · 本 fork store 已准备)
- ✅ ADR-13 §3.3 议题 3 业务行为契约 5 子段(本 fork ①②③④ 验收 · ⑤ e2e 留 fork 8)
风险评估
| 风险 | 缓解 |
|---|---|
| ⚠️ 用户拍板提前派发 · fork 3 未 zombie · PCM 通道未端到端验证 | 本 fork 不订 /ws/realtime/stream(widget 层用)· 仅订 /ws/realtime/state(fork 1 已落)· 端到端 PCM 联调留 fork 7 |
| ⚠️ realtimeRunStore.start payload 需 inputDeviceId · 但 fork 5(LeftDock device 选择 UI)未派 | 降级方案:store 字段 null 时 console.warn 提示用户 · fork 5 zombie 后 panel 自然填 store · 不破坏体验 · console 调 store 可手测 |
| ⚠️ engineStore Pinia 风格不一致(connectWS 重连策略 / 错误结构) | Step 1 真值核查 engineStore.ts 全文 · 严格对齐(connectWS 实现 · state 字段命名 · actions 签名风格) |
| ⚠️ TOOLBAR 死按钮删除可能破坏 LEGACY 监听 | grep 全工程 xitest:run-suite / xitest:stop · 期望 0 监听者(死按钮)· 若有 → 加 LEGACY_EVENTBUS_MAP 注释 7 天宽限 |
| ⚠️ watchEffect 在 setup 顶层 vs onMounted 内位置 | 对齐工程现有 stages/xitest/index.vue 风格(Step 1 真值核查) · 不脑补 |
| ⚠️ /api/realtime/start 后端响应 schema 不熟 | Step 1 必读 fork 1 zombie commit 92445f5 · 字段严格对齐(若不一致 typecheck 报错时立即停 · 用 grep 在主仓核查) |
| ⚠️ vitest WebSocket mock 风格 | 对齐工程现有 engineStore.spec(若不存在 · 用 vi.fn 简单 mock · 不引入新依赖) |
历史
| 时间 | 事件 | hash |
|---|---|---|
| 2026-06-02 10:37 | dispatched · 用户拍板提前派发(原话"马上结束了 我们先提前继续这个 prompt")· 放宽 ADR §5.4 fork 1+3 双 zombie 严格依赖 · fork 1 已 zombie(92445f5)· fork 3 dispatched 即将 zombie · 本 fork 不调 PCM 通道(widget 层 fork 7 用)· ClaudeA 0.5d 🧵 file · 范式参考 engineStore b4a8ea2 + recorder 824b2a5 · 解锁 Phase 3 fork 7+8 |
— |