Skip to content

Latest commit

 

History

History
256 lines (191 loc) · 28 KB

File metadata and controls

256 lines (191 loc) · 28 KB

2026-09-05 · v0.19 反馈批设计:焦点采集/标题/开关/拖拽/挂体系/列表交互/体系生长/精修加速

状态:待实施(2026-09-05 用户逐项裁决立项;系列拆版建议见 §3) 依据:用户 9 点反馈批逐项讨论裁决(焦点复现=双屏分屏/抖音客户端 Win11 · 标题内容化 · 画面理解开关入精修弹层 · 拖拽"加速" · 挂体系内联建节点 · 笔记列表交互重构 · 体系再深挖=D1/D2 · 目标智能体=执行型[另文档] · AI 精修速度=①流式②输出预算) 关联理念:产品哲学(product-design-philosophy)· 知识体系哲学(knowledge-system-design-philosophy,原则 4 AI 只建议不生成)· ui-ux-system 调研底稿:5 路子代理调研(窗口捕获技术语义 / 会议产品命名 / 桌面列表选择交互 / clarify-then-plan 与目标产品 / 行内快捷新建与开关分层),链接见各节


0. 批次裁决记录(用户原话要点 → 裁决)

# 主题 用户裁决
1 焦点/画面停更 双屏复现:点非采集窗口→参考画面停更、ASR 继续;肉眼确认视频本身在动→按我方捕获链路停更修复
2 会话标题内容化 零 AI 规则层先行 + AI 建议标题(AI 增强必须可选=独立开关默认关);时机待确认默认案=会话结束即生成、精修采纳后刷新(§2.2.3)
3 画面理解开关入精修发起弹层 仅本次覆写 + 显式"设为默认"(不双向同步)
4 侧栏拖拽加速 直接修(根因=累计位移当增量用,已 100% 定位)
5 挂体系弹层内新建 问题/概念/模型三类都可轻建(名称级,详情后补)
6 笔记列表交互重构 去行内 checkbox;单击=选中+右栏读;Ctrl/Shift 修饰多选+批量选择模式;拖=跨组/组内位置、即时拖(无 500ms 死区,用户"长按"语义=按住即拖);划过加选=空白锚点;交互矩阵 §2.6
7 体系再深挖 按推荐方案:D1 证据反推生长 + D2 节点缺口仪表;D3 先修关系作为执行型 agent 的配套后续(另文档 §依赖)
8 目标智能体 执行型 agent,本批立项+完整规划 → 2026-09-05-goal-execution-agent-design.md
9 AI 精修速度 ① 片内流式 + ② 输出预算化(直连确认:客户端直连 OpenAI 兼容端点,无自建中转)

1. 总则:AI 增强一律可选(本批所有 AI 能力的公共条款)

本地优先铁律在 AI 增强上的可操作化,每条 AI 能力必须同时满足:

  1. 独立开关且默认关:不得捆绑在"AI 功能开关"或授权里隐形开启;每条新能力新增独立设置位(AiSettings JSON 增量字段 + read-modify-write 最小面 setter,仿 ai_set_goal_plan/ai_set_vision_refine)。
  2. 建议制:AI 产出永远是可丢弃建议(落地提示、采纳/忽略),不自动写库、不自动改用户数据。
  3. 离线/降级完整:关闭或失败时本地规则路径完整可用(如标题=来源名/首句;缺口清单=纯规则现算)。
  4. 审计与成本:新增 AI 调用走 ai_tasks 任务化(op_type 扩展白名单)+ 审计 + 预算硬顶复用。
  5. 语音/图像不出本机红线延续;纯文本上云仅在有 AI 授权前提下。

2. 修复规格

2.1 焦点问题 → 画面停更检测与捕获会话自愈(#1)

背景证据:Rust 捕获链无按焦点暂停逻辑(已全仓核查);三级后端 WGC→DXGI→GDI(ADR-022);WindowLost 仅 GetWindowRect 失败触发;ScreenStats 已有 no_change/capture_err 计数但未外露。用户复现=Win11/抖音桌面客户端/双屏;冻结时视频肉眼在动 → 我方捕获会话静默失效(WGC 会话失活但未被重建的高嫌疑)。

修复 = 三件套(可独立交付,先 ① 后 ②③):

  1. 帧心跳观测(先落地,真机复现确认后进 ②):
    • 采集期间 Rust 每 2s emit live:frame-heartbeat:{backend, gotNewFrame, noChangeCount, captureErrCount, targetVisible, targetIconic, wgcSessionMs, lastError};
    • 前端课堂页在开发/诊断态显示(或仅日志);一次复现即可区分"无新帧 vs 帧全错/错误累积"。
  2. WGC 静默自愈 watchdog(纯状态机可单测):
    • 条件:backend=Wgc 且目标窗口 visible 且非 iconic 且无新帧持续 > WGC_STALL_MS(5s) → 重建 WGC 会话(WgcState::create(hwnd) 重试);
    • 节流:重建失败后按 30s 周期重试(沿用 DXGI_RECREATE_INTERVAL 既有节奏);连续失败升级为 ② 的停更提示;
    • 边界:DXGI/GDI 路径"桌面无变化=Ok(None)"属正常分支不触发重建(与 WGC 语义区分开)。
  3. 停更提示与末帧保留:
    • 末帧保留现状已有(latest_frame 共享缓存)——冻结期不黑屏;
    • 新增 live:frame-stalled 轻提示横幅(区别于真窗口丢失的 window-lost):文案"画面源已 Ns 无新帧(可能播放器暂停渲染)——检测到恢复自动消失";帧恢复自动清除。

文件:live_frame_process.rs(心跳统计/上报)· live_session_loop.rs(watchdog 调度)· dxgi_capture.rs/wgc_capture.rs(backend_name/重建接口已有)· types/live.ts · ClassroomPage.tsx(横幅)· 新纯函数模块 frame_watchdog.rs(状态机+单测)。 验收:单测=watchdog 判定矩阵(静默超时/可见性变化/错误累积/正常无变化不重建);真机=双屏复现前后对比,恢复时间 ≤ 5s+重建耗时。

2.2 会话标题内容化(#2)

A 层(零 AI,先交付,直接修"两条都叫抖音")

  1. 来源名净化 + 同源去重:创建会话时若归一化标题(去平台尾缀白名单,如 " - 抖音"/"- Douyin")与近 90 天既有会话相同 → 追加序号「抖音 #2」;纯函数 dedupe_session_title(查询入参=现同名集合)+ 单测。
  2. 首句自动升级:会话结束融合完成时,若 title_kind=source(未被人工改)且首个稳定转写段可用(长度 8–40 字、过 UI 垃圾过滤、非开场杂句)→ 截断升级标题;纯函数 first_line_title(segments, ui_junk) + golden 单测(含纯音乐无文本=不升级)。
  3. 改名入口补齐:会话详情头部标题行内改名(Enter 保存/Esc 取消,复用 GroupSidebarRow 重命名模式)+ update_session_title 命令 + data:sessions-changed 广播;改名即 title_kind=manual(此后 A/B 自动升级均不覆写)。
  4. DB:sessions.title_kind TEXT NOT NULL DEFAULT 'source'(幂等加列迁移,零表重建)。

B 层(AI 建议标题,默认关)

  • 开关:AiSettings.titleSuggestEnabled(默认 false)+ ai_set_title_suggest;前置=AI 已开启且已授权(content_gate 双闸门沿用)。
  • 时机(默认案):会话结束融合完成即触发轻任务(op_type title_suggest,输入=前 3000 字清洗转写,预算 ≤1K token,输出 JSON {"title": "≤20字"},解析失败=无建议静默);精修采纳后刷新:若该会话随后有笔记被 AI 精修采纳(data:notes-changed 钩子 + 会话→笔记关联反查)且建议未曾被采纳 → 基于精修稿首段再生成一次替换旧建议(质量更高,不重复整篇上云)。本刷新为第 2 步实现(同批或紧随)。
  • UI:会话列表/详情卡显示「💡 AI 标题建议:xxx [采纳] [忽略]」;采纳→改名(title_kind=ai);忽略→该会话不再提示。
  • 失败/离线:无建议、无调用、零阻断(A 层照常)。

文件:Rust commands_session.rs(改名/去重/升级钩子)· db_sessions.rs/迁移 · title_rules.rs 新纯函数 · ai_refine_task/ai_tasks op 白名单扩展 · prompts/title_suggest.json · FE SessionListPanel/SessionDetailPanel 徽标与改名 · types/ai.ts。 验收:A 层 golden 单测(抖音双会话/文件名导入/人工改名不被覆写);B 层任务化协议单测 + mock 模式端到端(采纳/忽略两路径)。

2.3 画面理解开关进入精修发起弹层(#3)

  • 交互(已裁决):RefineLaunchDialog(会话级模式 isNote=false 才显示)成本行上方新增「画面理解」行:checkbox 初值=全局 visionRefineEnabled;勾选变化=本次任务级覆写(随 ai_refine_start 传 visionRefine?: boolean,不写全局);行内小链接「记住为默认」显式调 ai_set_vision_refine 写回全局(单向下发,无双向同步);副文案提示"开启将显著增加耗时与费用(与精修加速第 9 项联动提示)"。笔记级精修(无关键帧语境)不显示。
  • 后端:ai_refine_start 增可选参 + 任务上下文解析纯函数 resolve_vision(override, settings)(覆写优先,缺省=全局);任务轨迹/审计记录生效来源(本次覆写 or 全局)。
  • 设置页 AiServicePanel 保持为全局管理/撤销总入口不变。
  • 文件:RefineLaunchDialog.tsx · commands_ai_refine.rs · ai_refine_task.rs(ResolvedDims 增 vision 解析)· types/ai.ts · 测试(对话框契约 + 解析优先级单测)。

2.4 列拖拽"加速"修复(#4)

  • 根因:ColumnResizer.onPointerMove 传距起点累计位移(clientX - startXRef),useColumnLayout.resizeBy 为增量语义(cur + delta)→ 每次 move 重复累加全程 → "加速"。影响全站(笔记/会话/课堂/知识四页共用)。
  • 修复:ColumnResizer 增加 lastXRef,move 传相邻增量 dx = clientX - lastX(side 符号逻辑不变);结构不动。
  • 测试:新 ColumnResizer 单测——pointer 序列(50→70→80)断言 onResize 回调增量为 [20,10](非累计);双击 reset 不变;useColumnLayout 既有测试保留。
  • 验收:四页各拖一次,宽度严格跟手、无回弹。

2.5 挂体系弹层内联轻建(#5)

UI 重构(NoteLinkToSystem):

  1. 体系下拉保留;实体区由"Tab+第二下拉"改为"Tab + 搜索式列表":输入即过滤(标题/文本子串,纯前端,本地数据已在手);列表行=树形缩进展示问题节点(可展开折叠,选中即父锚点),概念/模型平铺;
  2. 新建语义(已裁决三类都可建):输入非空且零命中(或无匹配想新建)→ 列表尾固定高对比「+ 新建『{输入}』」:问题=建于所选父节点下(默认体系根),概念/模型=体系级平铺;Enter 快捷键=命中即选、零命中即建(tagging 惯例);
  3. 轻建=名称级(问题 text/概念 name+三问留空/模型 name+留空),建后自动选中当前笔记的挂接目标,一键「确认挂接」收尾;详情补全回体系页既有对话框(KnowledgeConceptDialog 等已有编辑能力,零新流程);
  4. 空体系文案改为引导按钮「去建体系」(跳体系页向导,v0.13 向导复用,不做弹层内建体系——YAGNI)。

后端:复用/新增轻建命令(问题 create_knowledge_node 需含 parent 语义;概念/模型轻建=空可选字段默认值),全部幂等风格+入参长度校验;变更走既有 data:knowledge-changed。 文件:NoteLinkToSystem.tsx 重构 · 新 SearchSelectList.tsx(通用无头,≈120 行,可复用会话/体系其它选择器)· commands_knowledge_core.rs · 测试(NoteLinkToSystem 既有测试更新 + 新建即选契约)。 验收:空体系场景、有体系无节点场景、零命中新建场景、Enter/点击两路径。

2.6 笔记列表交互重构(#6,最大项)

交互矩阵(已裁决基线 + 本批补全)

起点/动作 行为 备注
行身单击 选中 + 右栏读(现状保留,Outlook 式) 三栏架构下"单击选中"天然兼"预览读"
Ctrl+单击 / Shift+单击 加选/区间选,不换右栏 桌面标准主通道
行身按住拖动(位移 >6px 激活,即时无延迟) 拖拽:单行或整组多选行 替代用户所述"长按拖拽"(澄清=按住即拖)
行首 4px 色条区 同为拖拽手柄语义 防未来图文混排时与划词冲突的保留锚点
组标题空白/行间空隙/空列表区按住拖动 划过加选(marquee:半透明选区框反馈) 行内不做划选;命中率不足则回退 Shift 为主(诚实边界,代码保留)
拖到左侧组行 / 中部组标题 跨组移动(drop target 双处) 中部组标题落点=新入口(现仅左侧组行)
拖到同组行上/下沿 组内位置移动 该组须为手动排序;自动排序组首次拖=提示后自动切换并快照当前序
拖到自动排序组内行 禁入反馈(not-allowed) Notion 排序锁定同款
右键在选集内行 菜单作用于整个选集(移动到组/删除 N 项/固定) Outlook 同款
右键在选集外行 先单选该行再出单项菜单 现状保留
Esc / 点击空白 清空选择 —
搜索/标签/排序(非手动)平铺态 禁拖拽排序(锁定),跨组拖仍可用 —
列表头「批量选择」按钮 勾选模式:单击行=勾选,批量栏浮现,Esc/完成退出 触屏/精确兜底,Gmail/Notion 同款

实现要点:

  1. 行内 checkbox 移除(NoteListRow);选中视觉=行背景 + 左色条实心;多选集状态从 NoteListView 上提为列表级受控 state(仍留在 NoteListView 内,NotesPage 不感知,批量动作经回调上抛——沿用现有 onBatchDelete 模式)。
  2. 批量操作栏扩为删除 + 移动到组(新 BatchActionBar;移动组复用组选择小弹层,归组命令循环调 move_note_to_group 幂等语义;只删可见子集守卫沿用 v0.12.8 审查口径)。
  3. 手动排序模型(DB):note_groups.order_mode TEXT NOT NULL DEFAULT 'auto'('auto'|'manual')+ notes.order_index INTEGER NULL(同组内排序键,未分组区用伪组键处理);命令:enable_group_manual_order(group_id)(快照当前排序为初始 order_index,事务内)、disable_group_manual_order(置 auto + 清 order_index)、move_note_position(group_id, note_id, before_note_id)(纯函数步进+单测);list_notes 排序扩展:manual 组按 order_index 排(SQL 联合或 Rust 分组后归并,选实现成本低者)。收件箱碎片列表不涉及。
  4. 拖拽实现:保留既有 HTML5 DnD 行→左侧组行(已上线可用),新增目标=组标题 drop + 同组行间落点指示线 + dragOver 高亮;组内行间落点解析为 move_note_position。WebView2 HTML5 DnD 已知不稳的迁移(pointer events 自实现)登记为观察项(真机若拖拽异常再立项迁移,不本批扩面)。
  5. 划过加选:容器空白指针起点(组标题/空隙/空区)→ 自实现轻量 marquee(~100 行,矩形与行 rect 相交判定 + 视觉框),无新依赖;与拖拽起点互斥由"起点是否在行 DOM 内"决定。

文件:NoteListView.tsx(选择模型重构)· NoteListRow.tsx(去 checkbox/视觉/拖拽源)· NoteTreeSection.tsx(组头 drop target)· 新 BatchActionBar.tsx / selectionMarquee.ts / dropPosition.ts(纯函数) · GroupSidebar.tsx(drop 保持)· Rust commands.rs/note_filter.rs 排序扩展 + 迁移 · 测试(选择模型矩阵/落点解析/划选相交/move_note_position 步进 golden)。 验收:真机手势矩阵逐行过(两屏拖拽/Shift 区间/划选/批量栏);重点回归=引用跳转 focusNoteId 滚动(行 id 不变)、右键菜单既有用例。

2.7 体系生长:D1 证据反推 + D2 节点缺口(#7)

D1 证据反推生长(建议制):

  • 命令 kb_evidence_clusters(systemScope):候选=未挂接体系的问题树证据源(笔记/碎片,排除已链接知识_links 命中者,session 转写内容作为 note 已入链不算)→ 本地 embedding 聚类(复用 kb 引擎;引擎未就绪=诚实提示需先启用语义引擎/降级关键词共现簇并标注"近似")→ 输出建议簇:代表标题列表 + 共同关键词 + 拟新问题表述(规则拼装,非生成) + 现有体系内最相似节点(查重提示,防重复建);
  • UI:体系页全局区「🌱 生长建议」卡片列表:每条=「这 6 条证据似乎都在说同一件事」+ 候选问题文案可改 + [基于此新建问题] [忽略];确认后走既有节点创建命令(证据随后由用户按现有挂接通道手动挂,不自动挂——AI 只建议不生成红线);
  • 依据证据=体系生长的唯一真实来源(哲学原则 1),解决冷启动与"树不生长"。

D2 节点缺口仪表:

  • 命令 system_node_gaps(system_id):每节点现算——证据数(note/card/fragment 引用计数分型)、最近引用时间、90/180 天 stale 状态(复用 concept_stale 判据理念)、概念"三问未填"标记、模型"无应用记录";纯只读聚合零双写;
  • UI:节点详情新增「缺口」卡:缺口清单(如"有概念无证据:0 条引用 / 90 天未用")+ 每缺口旁 [加入目标]:目标选择小弹层(复用目标列表)→ 调既有里程碑新增命令落草稿(目标侧人工审批流程不变,不直写里程碑状态);
  • 产出同时是执行型 agent(另文档 P0)的每日输入源。

文件:Rust kb_evidence.rs/system_gaps.rs(纯函数+聚合)· commands_kb.rs 扩展 · FE KnowledgePage.tsx/KnowledgeDetailPanel.tsx 卡片 · prompts 不需要(零生成,规则拼装)。 验收:聚类/查重/缺口聚合 golden 单测(fixtures 用本地样例);真机=真实笔记库跑通一次"建议→建节点→手动挂证据"。

2.8 AI 精修加速:①片内流式 + ②输出预算化(#9)

现状证据:精修=切片并发(≤8000 字/片、CONCURRENCY=3、每片独立非流式请求、SLICE_RETRY=1);单请求 max_tokens 上限 20000;DeepSeek 长输出实测 ~110s@20k token(ai_client 注释实证);前端已有 ai:refine-stream 帧协议与 useRefineStream。直连无中转。

① 片内流式:

  • 后端:refine adapter 请求改 stream:true(SSE 解析复用 ai_chat.rs::parse_sse_line);帧协议扩展 RefineStreamFrame::Delta { sliceIndex, text }(增量随到随推);
  • 顺序呈现规则(并发执行、顺序展示):每片文本按其 sliceIndex 归槽;展示层只渲染"连续前缀 + 当前正在流式的片"——片 1 从 ~2s 起打字机式增长(体感核心),片 2/3 后台并行;某片完成后接续展示下一片(若其已流完则直接整片落位);最终 diff/采纳仍走整片 validate 后的规范结果(流式仅为呈现,validate/审计语义不变,原料不可变红线不破);
  • 前端:useRefineStream 扩展 Delta 槽模型;RefineWorkbench 预览区增量渲染(文本追加,节流帧渲染参照 REQ-275 既有帧级批量渲染);
  • mock 路径同步支持流式帧(mock 可配分片吐字延迟)。

② 输出预算化:

  • prompts/note_refine.json v3(或新 strategy meta 段)为每档位声明 output_budget_chars(L1 轻改写档最小……L4 极简最小;自定义档=默认档值);系统提示词尾附"输出控制在 X 字内,删冗余不改事实";
  • 单请求 max_tokens 由 20000 收敛为 clamp(档位预算换算, 8k, 20k)——防止模型空转长尾,直接省生成时长;
  • 既有 L3"表达改写但事实红线不动"等约束不受影响。

埋点(REQ-275 基线收尾):每片记录 t0/首 delta 时刻/结束时刻 → 任务轨迹(trajectory_json 增字段或新 eprintln 汇总行);ai_tasks.elapsed_ms 既有;设置/开发日志可读。先埋点后调参——①上线前后各取 3 条真实会话做 A/B 记录(真机验收待办)。

文件:ai_refine_task.rs(adapter 流式调用/帧)· ai_chat.rs/ai_chat_stream.rs(SSE 复用)· commands_ai_refine.rs/prompt 资产 · types/live.ts/useRefineStream.ts/RefineWorkbench · 测试(SSE 行解析复用既有、帧序模型纯函数、预算 clamp)。 验收:单测=流式帧归槽模型(乱序到达/前缀规则);真机=3 条会话 A/B(首 token 时间、总耗时、字数、成本)。

2.9 交互矩阵完整性补齐(2026-09-05 用户追加:逐交互面审计)

审计维度:输入设备(鼠标/键盘)/ 状态覆盖(空·加载·错误·忙碌·部分成功)/ 冲突对 / 退出与撤销 / 键盘可达性 / 可发现性。第 6 项矩阵见 §2.6;本节补齐其余各面。

通用约定:Esc=先退最内层(输入/浮层)再退多选;toast 撤销窗口 3s;AI 建议类徽标一律带"依据来源"悬停说明(转写片段/精修稿);按钮/控件保持原生键盘可达。

交互面 矩阵(动作→反馈→边界)
会话标题改名(2.2A) 详情头 ✎ → 行内输入(Enter 保存/Esc 取消,失焦保存同 GroupSidebarRow 先例);行单击=打开详情,不做行内改名(零冲突);改名→kind=manual 永久停止自动覆写;空标题拒绝保存(提示沿用原标题)
AI 建议标题采纳(2.2B) 徽标 [采纳]=应用+toast「已采用 AI 标题(可撤销)」3s;[忽略]=本会话不再提示(不落库);悬停=依据来源;精修采纳后刷新=旧建议替换(若已采纳过则不再打扰)
精修弹层画面理解行(2.3) checkbox 原生键盘可达;行内状态文案实时=「生效:本次开/关 · 全局:开/关」(覆写时才显示"本次"段);「设为默认」直写全局+toast(设置页仍可关,无二次确认);busy 期间禁用
挂体系选择器(2.5) ↑↓ 遍历;Enter=有命中选首项 / 零命中即新建;Esc=先清输入再关浮层;轻建成功→自动置为挂接目标+「确认挂接」高亮(一步收尾);超长列表面板内滚动(既有 REQ-276 钳制保持)
体系生长建议卡 D1(2.7) [基于此新建问题]=建节点成功→卡折叠「已建 ✓(证据请手动挂接)」;[忽略]=会话级软隐藏;「相似节点」点击=跳体系页定位(focusSystemId);候选文案可编辑后新建
节点缺口卡 D2(2.7) [加入目标]→目标选择小弹层→落里程碑草稿→toast「已加入目标 X 里程碑草稿」→目标页审批流(既有语义,不直写状态);纯只读现算无加载态竞态
ColumnResizer(2.4) 补 tabIndex=0 + role=separator:←/→ 步进 ±16px(Shift ±8px)夹取 min/max;双击复位+轻提示;pointer 拖拽增量语义(§2.4)
列表键盘导航 观察项不做(checkbox 模式退场后重评估整列键盘导航;Tab 可达性仍靠批量按钮/搜索/右键菜单入口)——边界如实标注

2.10 视频暂停随播随停:声画双通道即时检测(REQ-291,2026-09-05 用户追加)

目标:用户暂停视频时采集同步暂停(画面链冻结+时间轴扣除暂停段+末帧保留,沿用 P2 自动暂停语义),恢复随即跟上——"即停即知≈1s / 恢复≤0.5s"。同时作 REQ-281 watchdog 的互斥门(真暂停不误报停更),并替代 player_behavior 5s OCR 判定成为主通道。

信号(全部现成零新采集成本):

  • 音频:系统环回 200ms/块 RMS(audio_loopback 现成)→ 新增共享槽 audio_active(阈值 MEDIA_AUDIO_ACTIVE_RMS,区别于 VAD 的语音阈值——"有任何声音"而非"有人说话");
  • 画面:屏幕 worker 现有网格 diff 计数(stats.diff_pass 每 ~1s 增长=画面在动)。

判定(media_state.rs 纯状态机,输入=audio_active/画面动/时间):

playing ──音频连续静默 ≥3 块(≈0.6s)──▶ suspect_paused
suspect ──下一画面 tick(≤1s)无变化──▶ paused(确认)→ 触发既有自动暂停机制
suspect ──画面仍动(静音无音轨视频)──▶ playing(撤销,不真冻结)
paused ──声或画任一恢复──▶ playing(≤0.5s 恢复)

滞回:缓冲转圈/进度条动画等短暂画面活动不打断 suspect→paused(等待期≈1 tick);进入 playing 需稳定 ≥2 tick。

接线与输出:

  1. audio_loopback 每块更新 audio_active;screen worker 侧喂画面信号(liveness 采样点已有 got_frame/diff);
  2. live:media-paused/resumed 事件 + 课堂页「⏸ 已随视频暂停」徽标(与手动暂停区分);
  3. 暂停触发沿用 P2 SessionPause 机制(live:paused 语义不变,时间轴扣除暂停段——用户裁决"扣除");player_behavior OCR 判定降级为辅助/移除;
  4. watchdog(§2.1)仅在非 paused 态评估(互斥门——静态讲解画面不误报停更);
  5. 阈值真机标定(MEDIA_AUDIO_ACTIVE_RMS/滞回)一次 A/B 自验证。

文件:新 media_state.rs(纯函数+单测)· audio_loopback.rs(槽更新)· live_session_frame.rs/worker(喂信号+暂停/恢复动作)· live_session.rs(共享槽装配)· 事件类型与 ClassroomPage.tsx(徽标)· 既有自动暂停路径审计(去重冲突)。 验收:状态机单测(含静音无音轨撤销/缓冲滞回/恢复边沿);真机=抖音播放→暂停→恢复三拍,采集冻结/恢复时间记录。

3. 版本切分建议(v0.19 线,随实施进度微调)

版本 内容 依赖
v0.19.6 2.1 帧心跳→watchdog+提示 / 2.4 拖拽修复 / 2.2A 标题零 AI 层 / 2.8 埋点先行 无
v0.19.7 2.3 开关入弹层 / 2.5 挂体系轻建 / 2.6 列表交互重构 / 2.8 片内流式+输出预算化 / 2.10 随播随停(REQ-291) 2.8 埋点基线(v0.19.6 已取)
v0.19.8 2.2B AI 建议标题 / 2.7 D1+D2 kb 引擎真机就绪(v0.19.5 待办);2.6 手动排序命令
(另线) 目标执行智能体系列 另文档 §排期

4. REQ 分配(登记用,实施立项时写入 requirements-pool)

REQ 需求 优先级 目标版本
REQ-281 画面停更检测与捕获会话自愈(帧心跳/watchdog/停更提示) P1 v0.19.6
REQ-282 会话标题内容化 A 层(来源净化+同源去重/首句升级/改名入口/title_kind) P1 v0.19.6
REQ-283 会话标题 AI 建议层(默认关/结束触发/精修后刷新/采纳忽略) P2 v0.19.8
REQ-284 画面理解开关入精修发起弹层(任务级覆写+设为默认) P1 v0.19.7
REQ-285 ColumnResizer 增量拖拽修复(全站) P1 v0.19.6
REQ-286 挂体系弹层搜索+三类内联轻建 P1 v0.19.7
REQ-287 笔记列表交互重构(去勾选框/修饰多选/拖拽矩阵/手动排序/批量栏扩展/划选) P1 v0.19.7
REQ-288 体系 D1 证据反推生长建议(聚类建议制) P2 v0.19.8
REQ-289 体系 D2 节点缺口仪表与加入目标 P2 v0.19.8
REQ-290 AI 精修片内流式 + 档位输出预算化 + 链路埋点 P1 v0.19.6/7 随 2.8 分批
REQ-291 视频暂停随播随停(声画双通道即时检测,2026-09-05 用户追加裁决) P1 v0.19.7

5. 红线与公共约束

  • 原料层(session_segments 原文)永不可变;精修流式仅呈现增强,validate/审计/采纳语义零变化;
  • AI 建议永不自动落库(§1 总则);标题/体系建议/任务建议三处同守;
  • 语音/图像不出本机;纯文本上云需既有 AI 授权;
  • 模型文件不入库;无新第三方运行时依赖(划选/搜索选择器均自实现零依赖);
  • SQLite 迁移全部幂等加列;不重建表。

6. 真机验收待办(登记)

  • 2.1:双屏复现一次(帧心跳日志)→ watchdog 生效对比(恢复 ≤5s+重建)
  • 2.2:抖音连续两条会话→「抖音」「抖音 #2」/首句升级;改名后不再被覆写
  • 2.3:会话精修弹层开/关/设为默认三路径;笔记精修不出现
  • 2.5:空体系/空节点/零命中三场景走查
  • 2.6:交互矩阵逐格真机走查 + 引用跳转回归
  • 2.8:3 条真实会话 A/B(实施前基线已取)