Files
story/docs/com6-controls-progress-20260922.md
Codex Local bf1233d5df
ci / verify (push) Canceled after 0s
feat: expand companion platform, device controls, and memoir workflows
Add customer and operator login, BLE provisioning, device fleet controls, call memory, memoir generation, and refreshed family and maintenance portals. Include API contracts, migrations, firmware sources, tests, assets, and deployment documentation.
2026-10-08 10:06:44 +08:00

133 lines
22 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# COM6 设备能力实现与验收
目标设备:COM6,ESP32-S3,MAC B4:3A:45:16:34:A8,16 MB Flash。
目标包含现有 SaaS 和小程序列出的设备能力,以及前面识别的重启、名称设置、恢复出厂和待机控制缺口。不得用页面提交成功代替实机执行成功。
最新状态(2026-09-22 03:57 UTC):线上 API/Web 为 `0.99.10-rc.device-transfer1`,COM6 为 `1.7.0-controls.8`。以下按时间追加的旧版本、旧分区说明均为历史基线,不能作为当前状态。真实 OTA/回滚、蓝牙全流程、恢复出厂、小程序发布及登录页面端到端验收仍未完成。
## 验收清单(未完成项不得标记完成)
- [x] 实机完整 Flash 备份及哈希;未修改出厂身份、Wi-Fi 和平台归属。
- [ ] MQTT 心跳、断线/重连、两端在线状态一致(controls.7 实机主动重启的离线/重连已验证;两端登录页面展示及非主动断网仍待验收)。
- [x] 云端音量配置应用到编解码器,实际值回传,重启后恢复。
- [ ] 音频、网络、存储诊断真实采集;命令领取、回执、重复投递去重。
- [x] 重启命令持久化,重启后回报;忙碌时拒绝或延后。
- [ ] 名称配置及两端展示(SaaS、设备持久化和回传已验证;小程序代码完成,正式发布与真机页面验收待完成)。
- [x] COM6 待机/唤醒执行、停止采音、熄屏、启动保持待机及通话期间延后执行。
- [ ] 待机/唤醒两端登录页面的端到端验收、小程序正式发布。
- [ ] 恢复出厂的设备执行、权限、状态及可恢复验证。
- [ ] A/B 分区、OTA 大小/摘要/型号/版本校验、任务去重、重启验证和失败恢复。
- [ ] SaaS 重新配网、账号先添加、OTA、命令结果入口。
- [ ] 小程序新增控制入口,现有配网、解绑、老人转移回归。
- [ ] 实机聊天和声音回归;核对平台绑定、固件、命令和配置最终状态。
- [ ] 线上部署和微信版本状态说明。
2026-09-22 基线:在线 Web 为 0.99.4-rc.login1;上述四个关键页面源文件哈希与本地一致。COM6 的 USB 诊断显示 RTC 任务存在,内部可用内存约 6 KB;需控制新增任务和缓冲的内部 RAM 占用。当前分区仅有 factory 应用,没有 OTA 槽。
本文件仅记录验收进度,不构成完成证明。
整片备份:本机受限目录 `.local-evidence/com6-controls-20260922/before-controls-16mb.bin`,16,777,216 字节,SHA256 `df426d931d3208ea3714f3393e65c06de75da31606dd6668d9afa027e4d0a187`。esptool 已确认板上 MAC;读取后硬件复位。备份含凭据,不纳入版本库或公开发布。
## 本轮已得到的实机证据
- 已部署 API `0.99.5-rc.device-controls1`,基于线上源码仅覆盖设备控制接口、OTA HTTPS 清单和 SaaS 在线状态读取。部署清单位于服务器新 release 的 `device-controls-release.json`。Web、worker、callbacks、gateway、数据库、Redis、MinIO 容器 ID 未变化。
- 已烧录新的 bootloader、A/B 分区表、初始 OTA 数据和移动后的唤醒模型。普通 NVS、coredump、storage、eaf 和出厂身份分区未擦写;平台绑定数保持 1。
- 首轮烧录应用 `1.7.0-controls.1`:3,749,408 字节;SHA256 `1d90bd68c3cde076ffa84203fc427f6fddde99515720338706ebc26b6a7b3aa7`。随后从 COM6 实际读回应用,哈希一致,保留在受限证据目录 `controls1-app.bin`。
- 2026-09-22 00:46 UTC:COM6 串口 `mqtt=1 speaker=60 revision=2 ota=1 internal_free=19047`;RTC 任务存在,栈剩余 42,688 字节。
- 同时平台查询:期望音量 60、实际音量 60、期望版本 2、已应用版本 2;固件 `1.7.0-controls.1`,MQTT 在线,OTA 支持标记 true。这是设备实际读取 codec 音量后的上报,不是云端复制期望值。
- 原播放器只在通话中存在。控制逻辑已改用常驻 codec,避免空闲时无法应用音量,也避免控制线程访问正在销毁的播放器。AI 服务任务使用 PSRAM 栈,启动失败会记录错误。
- 后端 onboarding、devicefleet、saas 隔离数据库集成测试通过;包括忙碌不投递、命令设备隔离、终态幂等、配置版本冲突、HTTPS OTA 清单与票据隔离。
- 实际 C 的聊天适配器、配置应用和 OTA 同源检查在 ASan/UBSan 下通过;覆盖 codec 失败、NVS 提交失败不误报已应用、重复配置不重复写 Flash、维护状态阻止开始聊天。
- 00:48 UTC:诊断命令 `5005088a-bd44-4392-9267-983996f4417e` 首次投递后 SUCCEEDED;codec 就绪、实际音量 60、网络已连接,NVS 实际写入/提交/读取检查成功。随后重启命令 `a39e0493-ff4c-4346-b32e-8ed5300290ad` 在启动后回传 SUCCEEDED,音量 60、配置版本 2 和绑定保留。
- 已部署 API 与 Web `0.99.6-rc.device-pages1`。网页新增固件状态/OTA、重启及最近命令结果;重新配网不生成绑定令牌,目标设备必须与蓝牙选择匹配;添加设备可不指定老人,账号设备不再被家庭筛选隐藏,支持后续绑定老人。后台复用既有设备归属服务,新增网页的状态与指定老人路由。
- 网页蓝牙协议测试 5 项通过;onboarding 全包隔离数据库测试通过(12.649 秒),包括网页与小程序先添加再分配流程、跨账号拒绝、CSRF/Origin 检查和绑定代次保持。独立线上基线候选的 TypeScript 与 Vite 构建通过。
- 本地浏览器检查了无家庭、待绑定老人、重新配网面板、未选择老人时禁止提交以及服务失败时保留选择。此检查使用本地页面数据,不代替 COM6 蓝牙实机验收。
- 发布后已验证线上首页、JS/CSS 的 SHA256 与候选完全一致,运行配置保持原值,新接口匿名访问返回 401;worker/callbacks/gateway/数据库/Redis/MinIO 未重建。首次发布探测漏带 X-Request-ID 导致 400,自动回退成功;补齐探测请求后重新发布成功。失败候选保留为 `.probe-rollback` 目录。
- 01:15–01:18 UTC 语音回归未通过:平台 chat/start HTTP 200,但语音 SDK 连接失败,`mbedtls_net_connect` 返回 `-0x42`(创建 socket 失败),没有下行 PCM/播放记录。结束已确认,未保存语音文本。正在排查 socket 容量与内存,不能据此宣称真实聊天正常。
- 01:23 UTC 已烧录 `1.7.0-controls.2`:3,749,728 字节,SHA256 `f7532cbb0cb83ee8dec90ce0208daacc9e624d87a3d5462fc7d7910b43c12bda`,仅写活动应用槽,烧录哈希校验成功。将 lwIP socket 上限从 10 调整至 16,加入活动 socket 数和连接 errno 诊断;OTA 启动确认增加真实 SDK 初始化成功条件。
- `controls.2` 固定语句回归成功建立语音连接并收到持续下行 PCM,播放器实际写入,解码/写入错误均为 0,40 秒后主动结束并收到成功回执。通话中 socket 数为 10 / 上限 16(临时语音服务 HTTPS 请求还需要额外连接),内部剩余内存 9,483 字节。证据 `voice-20260922T012415Z.log`。这证明软件音频通路恢复,不代替扬声器听感和麦克风真实收音确认。
- 通过受限 COM6 操作工具调用实际 SaaS Service 验证音量 `60→55→60`:设备实际 codec 上报分别匹配配置版本 3、4。随后重启命令 `67c37ad7-b430-4fa1-b264-7718b78d0b55` 首次投递,01:26:18 UTC 回传 SUCCEEDED。最终在线、音量 60、期望/实际配置版本均为 4、绑定数 1、未完成命令 0。串口 RTC 任务存在,内部剩余 16,307 字节,栈剩余 43,232 字节。
## 仍未完成
在线 OTA 安装及失败回滚、真实聊天声音/麦克风回归、名称和待机的小程序发布验收、恢复出厂、两端蓝牙回归及小程序正式发布状态仍未完成。`ota_supported=true` 表示代码和分区具备能力,不能替代实物 OTA 成功的验收记录。
工作目录 `.tmp-com6-deploy`、`.tmp-device-web-deploy` 包含线上基线、构建候选、增量发布脚本和只读 COM6 状态查询脚本。COM6 串口观察脚本为 `tools/observe-com6-controls.py`,固定测试语句回归为 `tools/com6_voice_acceptance.py`,输出仅包含运行元数据。当前尚未执行 OTA,活动槽仍为 `ota_0` / `0x10000`;一旦执行过 OTA,后续串口烧录必须先确认活动槽。不要再次运行首次分区迁移脚本清空正在使用的 OTA 状态。
## 2026-09-22 设备名称实现与实机验收
- API 与 Web 已发布 `0.99.7-rc.device-name1`,基于线上 `0.99.6-rc.device-pages1` 的源码构建,只有清单中的 10 个文件发生变化。独立候选构建和首页、JS/CSS SHA256 校验通过,其他服务容器保持原值;没有数据库迁移。部署清单为服务器 release 内 `device-name-release.json`。
- 配置契约为 `desired_config.identity.display_name`;空字符串恢复默认名称。后端限制 UTF-8 最多 96 字节,无首尾空白及控制字符。沿用设备管理权限和 If-Match 配置版本检查。设备通过 DEVREQ1 同步接口回传实际名称,旧固件不回传时不会伪造确认。
- SaaS 设备详情提供名称编辑、保存和放弃修改刷新;分别显示已保存名称及设备确认值。保存成功保留详情页面;后台刷新保留正在编辑的版本,避免覆盖其他人的修改。
- 小程序设备列表/管理和家庭设备工具显示名称;设备管理提供修改与恢复默认。新增用例覆盖版本冲突保留输入、重复点击、隐藏页面后的异步结果和非法名称拒绝;3 项新测试、19 项已有设备流程回归通过,9 页 WXML 与 10 个 WXSS 编译通过。小程序正式发布状态仍未确认。
- 后端 onboarding 全包隔离数据库测试通过(12.699 秒);HTTP 配置校验、名称边界测试通过。实际 C 配置函数在 ASan/UBSan 下验证名称存储提交失败、读回失败不确认配置、中文名称、超长名称、清空和重复同步不重复写入。
- COM6 已更新 `1.7.0-controls.3`,3,750,192 字节,SHA256 `9ab5da3913661b93a30ecd02a90fa51430e71f5334431ea955fb6f4192d8bc2b`。OTA 数据读回表明 ota_0 / 0x10000 为当前有效槽;烧录前检查设备空闲、绑定数为 1,只更新该应用槽。烧录校验成功。
- 通过受限 COM6 工具调用实际 SaaS Service,名称“COM6陪伴设备”下发并由设备回传,期望/实际配置均为 5。重启命令 `e29b45c4-5e28-4f6d-892b-cb15172510ac` 成功;01:55:45 UTC 首次启动上报的配置版本尚为 0(接口显示 null),名称已从 NVS 恢复,随后实际版本同步到 5。该证据排除了单纯从云端重新应用名称来冒充持久化。
- 01:56 UTC 已恢复默认名称,期望/实际配置均为 6;COM6 在线,实际音量 60,绑定数 1,未完成命令 0。验收记录保存在受限目录 `name-acceptance.json`,应用和烧录记录为 `controls3-app.bin`、`flash-controls3.json`。当前仍未执行实物 OTA。
- 浏览器验证了名称表单、输入验证和模拟接口失败后保留输入;线上家属账号尚未登录完成,因此上述 Service 实机验收不能作为网页/小程序点击操作的端到端证明。待机/唤醒、恢复出厂、OTA 安装回滚、蓝牙全流程及小程序发布继续保留在总验收范围内。
## 2026-09-22 待机与唤醒实机验收
- API 与 Web 已发布 `0.99.8-rc.device-power1`;2026-09-22 再次读取服务器 current 链接确认。SaaS 详情显示实际状态、待同步状态与确认操作。小程序对应代码已实现,正式发布和登录页面实测尚未完成。
- COM6 当前应用为 `1.7.0-controls.4`,3,750,096 字节,SHA256 `636103c1016fcda6146dd4511567cf532e8f009fe29b48a03ca2cfd29edbaf88`。仅更新 ota_0 应用槽,未做实际 OTA。固件暂停 AFE 和麦克风读取、关闭背光、阻止待机期间开始通话;保持网络以接收唤醒。待机状态写入 NVS,并在启动采音前恢复。
- `power-acceptance.json`:待机后实际背光 0、麦克风暂停;跨两次新上报,麦克风读取次数保持 968。待机时发送诊断聊天启动请求,云端通话数量仍为 19。随后重启的第一份报告已经是待机,麦克风读取次数为 0,排除了启动后重新从云端应用才停止采音。唤醒后背光 80、采音恢复,音量仍为 60。
- 首次人工交错的通话/待机检查未捕获到 busy=true,不作为通过证据。新增 `.tmp-power-controls/verify_busy_power.py` 在真实语音下行出现时自动发起待机,再核对云端通话状态和设备实际配置。
- 自动检查证据 `standby-during-call-v2.json`:02:27:07、02:27:11、02:27:15 UTC 三次均为通话忙碌、期望版本 11/standby、实际版本 10/active、背光 80、采音继续。挂断后 02:27:55 实际版本 11、standby、背光 0、采音暂停。证明待机请求不会提前中断本次通话,挂断后会被执行。
- 操作工具自身等待窗口为 40 秒,因此在这次 40 秒通话结束并同步前报告 `power transition timeout`;这是验收工具观察超时,不是设备任务终态。验收以随后带新上报时间的实际状态和匹配版本为依据,不以该工具退出码判断执行成功。该限制明确保留在证据中。
- 同次 `voice-20260922T022756Z.log` 包含持续下行 PCM、播放器写入和挂断确认,保存的仅是运行元数据。这仍不能替代扬声器听感和麦克风真实收音确认。
- 02:28:08 UTC 最终读取:设备在线,实际/期望版本均为 12,active、背光 80、采音恢复,实际音量 60。测试期间绑定数始终为 1。
- 完整目标仍未完成:恢复出厂、OTA 安装/失败回滚、蓝牙及归属变更实机回归、两端登录操作验收、小程序正式发布和真实收音/听感确认继续保留。恢复出厂须遵循现有 physical_confirm 设备先经账号授权解绑的约束,不能通过擦除工厂身份绕过归属。
## 2026-09-22 恢复出厂实现与发布(实物清空待验收)
已完成 DEVREQ1 重置接口适配、云端旧配置清理及通话/OTA 保护,并通过 devicereset、onboarding 隔离数据库测试。固件新增持久化重置日志、批准后清理、启动恢复,以及需要实体轻触确认的 BLE `factory_reset` 命令;真实 C 重置与 BLE endpoint 在 ASan/UBSan 下通过。
两端入口已实现,API/Web 发布于 `0.99.9-rc.device-reset1`;COM6 已仅更新活动应用槽至 `1.7.0-controls.5`(3,753,168 字节,SHA256 `6a898dc76fb2f916d212f6b7a8137f2445929700046405c5a693d718fa645647`)。烧录校验、线上资产校验和匿名访问拒绝检查通过。`voice-20260922T030755Z.log` 证明更新后持续下行 PCM、播放写入和结束成功回执,仍不等同于现场听感/收音验收。未对 COM6 清空设置,原绑定和音量保留;详见 [恢复出厂实现进度](device-factory-reset-controls-20260922.md)。
## 2026-09-22 更换使用老人流程与发布
- 原按钮调用旧版直接转移接口,被 COM6 的实体确认要求拒绝。现已增加附近蓝牙转移:选择新老人、检查影响、发送绑定版本受限的令牌,再由设备轻触确认。确认前原归属保持有效,事务失败完整回退,历史聊天仍归原老人。
- 复用现有 BLE 协议和数据库 claim guard,无迁移,无需再次烧录 COM6。两边家庭权限在申请和设备确认时都检查;通话/命令/OTA 期间拒绝;与 direct-call 共用事务锁,避免并发开始通话。
- onboarding 最新全包隔离测试通过(15.232 秒),saas 和 callmemory 集成测试通过;验证源权限独立撤销、重试、写入故障回滚及语音身份只注册一次。小程序 59 项相关测试和 9 页 WXML / 10 个 WXSS 原生编译通过;浏览器验证使用真实组件的模拟等待/成功/冲突流程。
- API/Web 已发布 `0.99.10-rc.device-transfer1`,基于线上 `0.99.9` 只覆盖 9 个清单文件;未部署本地其他改动。发布包 SHA256 `1a546d2f3eaf42c5e0e9fa0320c3787b32d8f1ef4addbd0f77c66a8b6bf495be`。首页和 JS/CSS 哈希、版本、运行配置及匿名拒绝检查通过,worker/callbacks/gateway/数据库/Redis/MinIO 未重建。
- 03:28 UTC 发布后 COM6 上报:`controls.5`,MQTT 已连接,绑定数 1,实际/期望音量 60,实际/期望配置版本 12,未完成命令 0。未更改真实使用老人。
- 实物转移、恢复出厂后重绑、真实 OTA/回滚、两端登录后的设备操作、小程序正式发布、声学听感及收音仍未完成。已请求家属账号登录、现场轻触配合及真实设置清除授权,尚未收到答复;仍可继续推进其他独立工作。详见 [实体确认转移](device-physical-transfer-20260922.md)。
## 2026-09-22 OTA 恢复修复与 controls.6 实机回归
- OTA 安装版本改为分槽保存,避免启动确认失败后覆盖旧固件版本;健康计时器创建/启动失败立即请求回退;数值转换检查整数与范围;记录损坏或读失败时停用 OTA 并保留待确认固件的超时保护。
- 真实生产 OTA C 全部故障注入测试通过 ASan/UBSan/float-cast-overflow 检查;ESP-IDF 编译通过。替身测试不算实物 OTA 或 bootloader 回滚通过。
- COM6 已仅更新活动应用槽至 `1.7.0-controls.6`,3,753,536 字节,SHA256 `25f2b93354b6f30492ab68a5c179359601da4cc4710852397366b699e772a0a9`;烧录校验成功,原绑定和设置保留。
- `voice-20260922T034336Z.log`:持续音频下行和实际播放器写入,观察到的错误为 0,结束通话收到成功回执。03:43:56 UTC 云端确认固件 controls.6、MQTT 已连接、绑定数 1、音量 60、配置版本 12、未完成命令 0。
- 尚未完成真实在线安装、A/B 切换和回滚;版本代码仍为 0。详细修复、证据边界和剩余验收见 [OTA 恢复记录](device-ota-recovery-20260922.md)。
## 2026-09-22 主动重启的 MQTT 离线状态修复
- controls.6 实测重启成功、MQTT 会话更换,但约 0.3 秒间隔采样没有观察到离线;快速重启时旧 TCP 会话未及时关闭,平台持续显示在线。证据 `reconnect-20260922T034715Z.jsonl`,命令 `99a040d1-21b4-4a05-9789-580c8dc9fbf5`。
- 新增应用任务使用的 `device_control_prepare_restart`:停止心跳并调用 ESP-IDF MQTT stop,在重启前发送 DISCONNECT、关闭连接。重启命令仍先持久化回执,再关闭 MQTT;启动后才发送成功回执。OTA 安装后的正常重启也使用此路径;早期启动回退和异常断电仍依赖原连接超时机制。
- 生产重启命令 C 测试通过 ASan/UBSan:覆盖持久化与断开顺序、忙碌、ACK 失败、存储失败、无 MQTT 客户端及 MQTT stop 失败。完整 OTA C 故障测试通过;ESP-IDF 编译通过。未修改在线 API/Web。
- COM6 仅更新 ota_0 至 `1.7.0-controls.7`,3,753,648 字节,SHA256 `31d154591f37daf7816ba964a5b477c47f2b0065802fe80762f2e03b3fbb831e`;写入校验成功,OTA 数据、出厂身份、NVS 保留。
- 复测命令 `fe9f342d-b802-4064-8ecb-277f49864a53`:03:51:36 UTC 观察到 `connected=false / online=false`(请求后 2.894 秒),03:51:50 UTC 新会话恢复在线(请求后 16.696 秒),命令首次投递后 SUCCEEDED。期望/实际配置仍为 12,音量 60、active、绑定数 1,未完成命令 0。证据 `reconnect-20260922T035132Z.jsonl`。
- 该检查使用真实 SaaS Service 下发命令和真实 MQTT 数据库状态,不等同于浏览器/手机页面的登录端到端验收。两端在线读取代码均使用 `fleet_presence` 的连接标志和 90 秒心跳有效期;实际 UI 刷新显示仍待账号登录验证。异常断网、真实 OTA/回滚及其他既有未完成项继续保留。
## 2026-09-22 持久化命令回执故障保护
- 新增 `tests/device-receipt-host.cjs`,编译生产 `save_result`、`flush_result`、`ack` 与真实 cJSON,注入 NVS 打开/读/写/提交失败和网络回执丢失。修复前,NVS 命名空间读取失败被当作没有待补发回执,`open-error` 场景断言失败;这会允许控制任务继续领取命令。
- 修复后只将 `ESP_ERR_NVS_NOT_FOUND` 视为没有记录;其他打开/读取失败阻止继续领取。收紧记录长度范围,并按实际读取长度解析 JSON。回执提交前仍要求重启标识变化;网络失败、删除提交失败保留同一回执重试。
- ASan/UBSan 下 `open-error` 及完整回执场景通过,覆盖同一次启动不提前确认、重启后补发、丢失响应、删除失败、无记录、损坏记录、终态冲突和普通诊断回执。此故障注入不等于实机人为损坏 NVS 或真实丢包验收。
- ESP-IDF 编译通过,COM6 仅写 ota_0 至 `1.7.0-controls.8`,3,753,664 字节,SHA256 `c5166683a9db25d050fae602441e3163e8a59f34813bf934a6333e78094fe670`;烧录校验成功。
- 实际诊断命令 `00302a24-33fd-46e4-a5f1-44d42dd9c475` 首次投递后 SUCCEEDED:codec 就绪、音量 60、网络已连接、NVS 可读且写入/提交/读回成功。证据 `diagnostics-controls8.jsonl`。
- 实际重启命令 `2e03ddf3-4fe6-429d-b066-ff791296ab9f` 首次投递后 SUCCEEDED。请求后 4.922 秒观察到离线,17.430 秒新会话上线;最终配置版本 12、音量 60、active 和绑定数 1 保留。证据 `reconnect-20260922T035730Z.jsonl`。
## 剩余工作与阻塞核对
本轮实现和可独立执行的故障保护验证有实质进展,但整体目标仍不能判定完成。登录和现场确认的缺口已连续多轮存在,未获得新的用户答复。
- 已重新读取当前浏览器:线上仍在维护中心登录页,手机号与短信验证码未填写;没有可用于家属端 OTA、蓝牙归属和控制 UI 验收的登录会话。不能通过伪造会话或绕过权限来代替。
- 添加/重新配网、更换老人、解绑后恢复出厂和重新绑定需要设备现场轻触。清除真实 Wi-Fi 和用户设置的测试仍未收到确认,未执行。
- 声学听感和真实麦克风收音需要现场反馈;音频下行和播放器写入记录只能证明软件通路。
- 小程序当前工程为 `C:/Users/19926/WeChatProjects/voicelink`、AppID `wx4553119e05f11660`。README 与设备接口文档仍记录 IP 后端及正式发布所需的合法域名/权限准备;没有当前正式版发布证据。构建、测试、原生编译不能替代开发者账号上传、微信配置和手机操作验收。
- 真实 OTA 安装及受控失败回滚、异常断网恢复、丢包后的实物命令重试仍保留在完整验收范围中;不以 USB 烧录和主机故障测试替代。
下一步需要用户完成家属账号登录,明确是否可现场操作及是否允许恢复出厂测试,并提供可用的小程序发布环境。之后继续原范围验收,不将未验收项删减为已完成。