Collie 第一阶段 Live 审计(历史记录)— 2026-09-06¶
本文保留本轮早期 Live 功能检查的原始记录。以下分支、范围、测试统计和结论只描述当时阶段;整个产品的最终判断见 产品审计,后续执行工作流改进见 工作流记录。
结论与范围¶
Collie 已具备从多端入口、模型/worker 路由到 Mission 执行、权限审批和结果验证的完整结构。 这轮最值得优先改进的是新增 Live Copilot 的运行边界:输入类型、异步结果归属、停止行为、 持久化容量和 Windows 后台进程体验。已有测试数量很多,但基础套件通过并不意味着这些 新边界已经被覆盖。
本轮在 C:\workspace\collie 的 feat/private-adaptive-online 分支工作。开始时已有
16 个跟踪文件被修改,并存在 SenseVoice、Avatar rehearsal 等未跟踪文件;本轮保留这些
工作,追加下述修复、功能完善及测试。用户随后授权检查并提交;本轮提交范围包含这些
已有 Live 改动及新增完善,不发布或重启正在使用的 Collie。
项目结构判断¶
| 层次 | 主要代码 | 判断 |
|---|---|---|
| 用户入口 | cli.py、webapp.py、Web UI、浏览器扩展、原生桌面 |
入口丰富,应共享权限与参数验证规则,减少不同入口的行为差异。 |
| 执行与验证 | loop.py、mission.py、missionweb.py、runner adapters、verification |
已有大量确定性测试;保留“执行证据决定完成”的核心设计。 |
| 持久化与恢复 | Missions、jobs、control plane、Live store | 持久化不仅需要原子写入,也需要容量控制和跨进程事务语义。 |
| Live 感知与交互 | live_copilot.py、sensevoice.py、live_voice_relay.py |
新功能集中处,最需要防止后台结果越过会话和权限边界。 |
当前工作树约有 153 个顶层 Python 模块、9.9 万行 Python 源码。
webapp.py 超过 5,500 行,mission.py 超过 5,300 行,cli.py 超过 4,800 行。
后续应按业务边界逐步拆分,并以跨入口行为测试保护迁移。
已修复的问题¶
| 优先级 | 可复现问题 | 修复后行为 |
|---|---|---|
| P1 | update_permissions(listen="false") 会开启监听,且绕过使用 is True 的同意检查。其他权限也接受字符串、整数等非布尔值。 |
Store 入口和持久化读取严格校验布尔类型;HTTP 和模型工具的启动入口保留原始值交给 Store 校验;无效请求不修改状态。 |
| P1 | 转写完成后先检查 session,再在另一段锁内追加事件;两段之间新建会话时,旧转写可写进新会话。 | 追加每条转写时传入原始 session_id,在实际写入锁内再次校验归属;旧结果被拒绝,临时音频仍被删除。 |
| P1 | 关闭语音对话后,进行中的模型请求仍可追加回答;停止会话未清理 dialogue 的进行中标记。 | 回写前重新检查 voice_dialogue;关闭后丢弃回答并释放标记;停止时清理两条分析通道的进行中标记及领取时间。 |
| P1 | 事件数量上限不能保证 UTF-8 文件大小。1,200 条每条 4,000 个中文字符的合法事件可写出约 14.5 MB 的文件,超过自己的 4 MiB 读取上限。 | 序列化后按实际字节数检查,分批裁剪最旧事件并保留最新事件;其他内容仍超限时,拒绝写入并保留上一份可读状态。 |
| P2 | SenseVoice 启动 ffmpeg 没有传入 Windows 隐藏控制台参数,后台语音处理可能闪出命令窗口。 | 使用现有 plat.no_window_kwargs();跨平台窗口检查通过。 |
| P1 | 语音 relay 播报完成后无条件恢复监听,可能覆盖用户在播报期间手动关闭监听的选择。 | 临时暂停领取单次恢复凭据;显式监听设置使凭据失效,停止或切换会话也不能恢复;不再由 relay 代填同意参数。 |
相关实现:
兼容性细节:权限参数必须是 JSON true / false;启动请求中的 null 也会被拒绝。
权限更新中的 None 仍表示“不修改该项”。旧 share_transcript 字段仍可作为 listen
缺省时的别名;同时提供两者时,以显式 listen 为准。旧的非布尔权限状态会明确报错,
不会通过宽松转换继续开启能力。
已完善的功能:结束会话后的回顾与导出¶
原先停止 Live 后,页面隐藏摘要、提醒和后台任务区,用户难以整理本次协作结果。 现在停止后仍保留回顾,刷新后也可继续查看,已结束会话的实时操作按钮禁用。
- 新增 Markdown 导出,包含起始上下文、AI 摘要、笔记、未隐藏建议和后台任务最后记录状态。
- 上下文日志默认不导出,勾选后导出全部保留事件;音频、截图和 Avatar 连接凭据不进入文件。
- 支持中英文,导出不再调用模型;下载接口要求认证并核对会话编号,旧页面不能下载后来新建的会话。
- 明确提示只保留最近一次会话,应在新建前导出;导出不是完整录音记录,任务记录也不是最新执行结果。
- 新增独立导出模块,避免继续把文本格式处理堆入
webapp.py。
使用方式见 Live 文档。
统一检查中修复的测试问题¶
统一脚本额外暴露了基础 pytest 不能充分反映的七处检查问题。本轮也完成了修复:
test_browserbridge.py的 stub 在记录中加入_timeout,旧断言却只比较命令内容。 现明确校验 8 秒的预检期限;check()失败同时抛出断言,避免 pytest 将失败条件当成通过。test_data_dir.py的“无覆盖配置”场景现在从子进程环境中去掉外部的状态/数据目录变量。test_mcp_catalog.py固定离线 OAuth 元数据,并按现有“Connect 时检查元数据”的行为验证提示; 协议发现与 scopes 的原始实现仍通过模拟 HTTP 单独检查。gui_test.py使用独立临时设置、会话及状态目录,按 Today → 新任务的实际入口验证身份, 并在打开模型选择器前展开它所在的工具菜单。steer_ui_check.py显式选择followup=steer;默认排队模式与插话模式不再被测试混淆。test_map_landing.py使用独立状态目录,避免真实或先前测试保存的地图项目覆盖 fallback 场景。- 平台扫描只查看调用附近六行,未识别
ambient.py更早的 Windows 返回守卫。 将该启动点也改用plat.no_window_kwargs(),统一平台处理并通过扫描;这不是一次已证实的跨平台运行崩溃。
验证证据¶
全部验证使用 mock provider 和 BM25,涉及会话、音频的回归使用临时状态目录和模拟转写。
- 基础 Python 套件:2267 passed, 10 skipped,耗时 313.63 秒。这是在本轮修复前启动的基线检查。
- 新增边界测试先复现失败:第一批 35 failed, 1 passed;容量问题另有 2 failed。
- 修复后相关套件:159 passed,耗时 23.24 秒,覆盖 Live、HTTP 控制面、浏览器桥接和运行选项。
- 本轮共新增 44 个参数化测试用例,其中 38 个在独立边界测试文件,6 个在 HTTP 控制面测试文件。
- 修复后统一脚本中的全量 Python 套件:2311 passed, 10 skipped,耗时 312.98 秒。
- 浏览器扩展 JavaScript 测试:130/130 passed。
- GUI 最终复测:59/59 passed;插话界面复测:全部通过。
- 数据目录、MCP catalog、地图落地独立脚本:最终复测全部通过。
- 浏览器桥接独立脚本:97/97 checks passed;使断言能向 pytest 报错后,再次运行该文件:32 passed。
- Windows 控制台窗口扫描:修复前 1 个违规启动点,修复后 135 个启动点中 0 个违规。
- 平台一致性扫描:最终通过;统一 Ambient 启动封装后,Ambient 与 Live 边界再次验证:39 passed。
- Python 模块语法解析和
git diff --check:通过。 - 第一阶段验证由一轮
tests/run_all.sh和上述七块针对性复测组成。统一脚本首轮因这些问题退出 1; 修复后逐项复测通过。首轮其余检查包括 renderer、VS Code、relay、打包和 41/41 CLI surfaces 均通过。
上述为第一阶段记录。提交复核阶段另新增 7 项导出测试和 8 项语音恢复测试;导出、Live、
HTTP 相关套件 102 passed,语音恢复及导出/边界组合 52 passed。新增的 Playwright
检查已验证停止后回顾、刷新保持、默认下载、可选日志下载、手机布局及无 JavaScript 错误,
并接入 tests/run_all.sh。Windows 原生端编译成功,只有已有的两个未使用键盘 hook 字段警告。
提交复核的统一脚本中,GUI 59/59、新增回顾下载流程、浏览器扩展、打包、CLI 41/41
及其他独立检查全部通过。Python 首轮出现两处测试问题:旧 UI 契约只接受两个 Live 路由,
以及模型 Auto 测试未清除启动时缓存的环境覆盖标记。已更新路由契约并隔离 _HARD_ENV,
保留产品对真实环境变量的优先级;相关两个测试文件复测 86 passed。
最后再次运行完整 Python 套件:2326 passed, 10 skipped,耗时 314.25 秒,退出码 0。
最终证据组合为统一脚本中的全部非 pytest 检查,以及修正后的全量 pytest 复测;统一脚本
首轮退出码 1 保留在日志中。本轮累计新增 59 个参数化 Python 用例及独立浏览器回归流程。
本机验证环境为 Windows、Python 3.14.4。上述回归不能替代 macOS/Linux 的 CI、真实麦克风
识别质量、真实模型延迟或长时间运行验证。原始统一检查日志、GUI 复测日志和改动前源码备份
保存在工作区的 C:\workspace\collie-audit-2026-09-06。
后续优先事项¶
以下来自源码检查,本轮没有进行相关架构改造或声称完成故障复现。
从用户功能完整性看,建议按以下顺序继续:
- 语音准备与故障恢复。 在 Live 内集中显示模型、ffmpeg、播放组件和麦克风状态, 给出测试录音、测试播报、重试入口;补充录音序号与会话归属检查,并配合有界处理队列。 目前神经语音和 SAPI 的音频播放都依赖 ffplay,缺少它时仍需完善回退或明确错误提示。
- 任务结果回流。 Live 会话中的 Mission 显示最后记录状态;应订阅任务完成或失败事件, 提供查看执行证据、失败重试和把结果带回笔记的入口。
- 可选会话历史。 当前已支持主动导出;下一步可让用户自行选择保留历史、关联项目和 删除记录,避免把所有实时上下文默认长期保存。
- Avatar 外部服务生命周期。 补足远程启动中切换会话、自动到期或语音停止时的清理与重试; 在真实提供方验证连接、嵌入与断线恢复后,再视为完整外部服务功能。
工程层面仍需:
- Live 状态的跨进程一致性(P1)。 当前
_LOCK是进程内RLock,多个进程仍可同时 对同一个 JSON 文件执行读—改—写;原子替换只能避免半份文件,不能防止覆盖另一进程的更新。 建议选定单一写入服务,或迁移到带事务和版本校验的 SQLite,并补充真正的多进程竞争测试。 - 音频处理的并发上限(P1)。 当前每个 chunk 都创建一个线程,
pending=min(1000, …)只限制计数字段,并未限制工作数量;SenseVoice 解码锁也不等于入口限流。 建议固定工作线程数和有界队列,队列满时提供可重试错误,并保证拒收不消耗音频序号。 - 统一 Live 参数契约(P2)。 本轮已把布尔校验收敛到 Store;下一步可将时长、时间戳、 音频序号、事件结构等校验也集中定义,减少 HTTP、工具调用和原生入口各自转换参数的情况。
- 逐步拆分大模块(P2)。 优先从
webapp.py提取 Live API 和业务服务,保持路由薄而明确; 使用现有 HTTP 回归确保行为一致,再处理 Mission 与 CLI 的大模块。 - 发布前运行验证。 在 Windows/macOS 上完成 8–12 小时 Live/daemon 运行、睡眠唤醒、 模型超时和磁盘异常的组合验证,记录真实的延迟、峰值线程数、临时音频占用和恢复时间。