EdgeHippo · MVP 产品设计与软件开发任务书

代号 EdgeMemory-MVP | 载体:ESP32-S3 N16R8(板 B)+ N8R8(板 A) | v1.2 | 2026-10-26
上游输入:《EdgeMemory 市场与产品战略报告 v1.0》(2026-10-26)
本文档把该报告的战略结论转译为可执行的工程任务:硬件分工、软件分层、数据模型、任务清单(WBS)、三场景知识库规格与测试用例集。

修订说明(v1.0 → v1.1 → v1.2)

本版针对三条反馈做了修订,其中第一条的结论与直觉相反:OTA 对容量的影响不是「要不要」的问题,而是「槽开多大」的问题。

反馈v1.0 的做法v1.1 的修订与结论
① OTA 是否保留未分析,默认沿用现有双槽(各 4 MB)建议保留 OTA,但把 app 槽从 4 MB 压到 2 MB。实测固件 1.59 MB 却占着两个 4 MB 槽,白扔 4.8 MB。压缩后 edgehippom 从 7.875 MB 提到 11.875 MB,容量 8,000 → 14,448 条(推算、未实测;v1.1 当时按旧几何推算是 12,900 条),且 OTA 能力完整保留。详见新增 3.5 节
② MVP 不接传感器W4-01 要求板 A 挂振动/温度/电流传感器全部改为确定性合成数据源。MVP 只用基础主板,不接任何外设传感器。收益:可复现、可回归、零接线工作量、不占 RAM。代价:真实采集吞吐验证推迟到 P1。详见 6.4 节与 S1 场景修订
③ eXtremeDB 优势必须保留只说「emdb 后端替换,接口不变」新增 4.4 节「优势保留矩阵」:把 eXtremeDB 的 14 项能力逐条映射到 emlite 的设计约束与验收点,确保替换前后行为与性能特征一致。尤其锁定三条 Andrei Gorine 反复强调的硬约束:malloc-free、事务感知的 flash 管理、截止时间可分析
关于「每日邮件」中 Andrei 与 Steve 的材料:本地文件与邮件中均未检索到原文存档(已全盘检索 D:\OneDrive\文档\SmartEDB 与邮箱,无 Andrei/Steve 关键字命中)。本版改以两人的公开发表材料为依据:
· Steve Graves(CEO):2026-09-01《How eXtremeDB ANN indexes and time series / sensor data fusion work together》;《Justifiably Taboo: Avoiding malloc-free APIs In Military/Aerospace Embedded Code》。
· Andrei Gorine(CTO / 联合创始人):eXtremeDB/rt 2.0 发布声明(2025-10-23,xFile / xFlash / TFTL / 截止时间策略);ODBMS.org 深度访谈《When a Millisecond Is a Promise》;Dr. Dobb's 内存管理文章(eXtremeDB 运行时不调用 malloc);eXtremeDB/rt 服务版发布(2026-06-15,1 GB flash 库仅需 40 KB 内存)。
若手头那批「每日邮件」能导出存档,可据此再校核一轮——尤其关注是否有未公开的 ANN 参数与 MCU 端 footprint 数据。

v1.1 → v1.2 修订(方案 C 专项评估)

问题v1.1 的假设v1.2 的实测与结论
方案 C(app 槽 1.5 MB)是否更合适评价为「⚠️ 固件余量仅 0.3 MB,加回功能模块即爆」——按裁剪后固件 ≈ 1.2 MB 估算实测推翻该估算,方案 C 应从「激进」改判为「不可行」。实测裁剪 cam/mic/gps 只能省约 120 KB(而非 400 KB):三个自有模块 .text 合计仅 8.4 KB,大头是 esp32-camera 组件 83.7 KB + I2S 驱动 31.1 KB。MVP 完整态固件预计 ≈1.45 MiB,1.5 MB 槽余量 <5%,且 MVP 还要新增 TinyUSB(+60–100 KB)与 emlite(+30–50 KB)。结论:维持方案 B(2 MB 槽)。详见新增 3.5.7 节

一、执行摘要:三条硬发现与产品定义

硬发现 ①|eXtremeDB SDK 目前不在开发机上。已全盘检索 C:\emgw-build 与 C:\Espressif,未找到任何 McObject / eXtremeDB 的头文件、库或组件(components/ 下只有 esp32-camera)。这意味着「引擎层」不能作为 MVP 的前置依赖,否则整个项目会被授权谈判单方面卡死。

工程对策:引擎层做成双后端 HAL。先自研 emlite 后端(纯 C,flash-backed HNSW + 列式时序环 + WAL 事务),让 P0 全部闭环可以在不等授权的情况下跑通并拿到实测数据;eXtremeDB 到位后作为 emdb 后端替换,接口不变。这样授权谈判从「阻塞全部」降级为「性能与成本优化项」。
硬发现 ②|真实可用容量比战略报告推算的少 30%。报告第 6 章按「Flash − 固件」粗算,给出 N16R8 ≈ 11 MB 可用。但按本机实际分区表 partitions_emgw_16m.csv,引擎分区(旧线性库分区)只有 0x7E0000 = 7.875 MB;8 MB 版更是只有 0x200000 = 2.0 MB。重新测算后,容量档位应从「16,000 / 6,000 条」下修为 「10,000 / 2,500 条」。

工程对策:① v1.1 进一步发现:容量损失主要不是来自 flash 总量,而是 app 槽开太大——固件只有 1.52 MB 却占着两个 4 MB 槽。压缩到 2 MB ×2 后,edgehippom 提到 11.875 MB / 3.875 MB,档位上修为 14,448 / 3,419 条(推算、未实测,口径 rec_pages×4080×85%/644;v1.1 旧推算为 12,900 / 3,700),且 OTA 完整保留。详见 3.5 节;② 所有对外叙事一律用实测口径,不要用报告里的推算值。
硬发现 ③|好消息:双板互联已经跑通了。现有 link_mgr.c(1459 行)+ NimBLE 已实现双板互联与碎片同步,A/B 两板分别固化形态标识(Dev-A = form=gamma-card,Dev-B = form=usb-dongle,均为对等外设本体、无上下级),MAC 与设备 ID 已写入 eFuse。也就是说 MVP 的 α 形态(模组嵌入宿主)验证不需要新增任何硬件工作,直接复用。此外 em_store.c 已实现 edgehippom 分区的 append-only 记录日志与导出/压缩,可作为 emlite 的存储底座改造起点。
v1.2 补注(ADR-018):本条原始描述为「1 gateway + 2 edge」「A/B 固化 role=edge / role=gateway」,那是上一代 EdgeMemory Gateway 架构的上下级分层残留,已废止。现行口径:两块板都是 EdgeHippo 外设本体,板级一律用形态表达,对等无层级。

1.1 产品定义(一句话)

EdgeMemory-MVP = 一块 N16R8 板 + 一条 USB 线 + 一个拖进去的 .emf 包 = 一台完全离线可用的记忆外设;再用一块 N8R8 板作为宿主,证明这套能力可以作为「器官」被嵌进别人的设备。
要素MVP 定义
产品名EdgeHippo(EdgeMemory),MVP 版本 v0.1(内部代号 EdgeMemory-MVP)
形态β 原型(USB Dongle)= 板 B(form=usb-dongle);γ 磁吸卡形态原型 = 板 A(form=gamma-card)。两者跑同一套固件,仅形态标识(form)与容量档不同,对等无上下级(ADR-018)
核心交易宿主提供查询向量 → 板上做「相似度 + 时间 + 精确条件」的混合检索 → 返回命中的记忆条目与可回溯的时序证据 → 结果回写为新记忆(闭环)
唯一杀手级 UX拖拽即灌库:USB 上同时呈现一个串口和一个虚拟 U 盘,把 .emf 碎片包像拷 MP3 一样拖进去,设备自动校验 → 合并 → 建索引。零驱动、免安装、免联网
不可妥协的规格断网状态下全部核心能力完整可用;检索路径不经过任何网络

1.2 与战略报告的对应关系

战略报告结论本任务书如何落地
卖「能力」不卖「算力」板侧不做 embedding、不跑模型;W4 只做统计/频谱特征,ML 特征一律由 Host/Hub 回写
单机即有完整价值Go/No-Go ① 的验收全部在单板断网条件下执行(见第 10 章 N 组测试)
碎片必须自洽、离线可验签.emf 结构(第 5 章)+ W5-02/W5-03 打包器与校验器 + TC-F-* 验签测试
优先暴露 MCP,不做私有 APIW3-05 MCP shim,三个场景统一走 MCP 查询接口,CDC 行协议只作调试面
必须绑定单一杀手场景第 7–9 章三个场景各有独立验收与 Go/No-Go 判据,M9 由产品负责人基于实测拍板,不由市场部选
β 形态(¥399)为首个 SKU板 B 就是 β 原型;S3 场景(私域知识库)即其定价锚验证载体

二、MVP 边界:做什么 / 明确不做什么

✅ 做(MVP 范围内)

  • 板侧 flash-backed ANN 检索(int8 / 384d / HNSW + IVF 粗划分)
  • 板侧 时序写入与三级留存(L0 原始环 / L1 分钟聚合 / L2 特征向量)
  • 混合查询:相似度 + 时间范围 + 设备/碎片/标签等精确条件,同一事务内
  • 事务:WAL + commit/rollback,随机掉电后库可开
  • 记忆策略层:工作/短期/长期三态、遗忘淘汰、近重复去重、重要性评分
  • 闭环回写:检索结果(含成功/失败)写回为新记忆
  • USB 复合设备 CDC + MSC;拖拽 .emf 灌库
  • MCP 接口暴露记忆资源
  • PC 侧工具链:embedding → 构图 → 打包 → 灌库 → 基准测试
  • 三场景知识库与测试用例

❌ 不做(明确划出边界)

  • 板侧 embedding / LLM 推理——上一版报告已论证 S3 上无实用价值
  • 算力共享、token 积分、任何形式的结算——合规红线且战略已否决
  • 检索路径上的 任何网络依赖(Wi-Fi/BLE 只用于搬运与管理)
  • γ 磁吸卡(iOS USB 限制)、δ SD 卡形态(SDIO slave 待验证)——列为 P2 期权
  • 多节点一致性、分布式事务
  • 摄像头 / 麦克风 / GPS——MVP 阶段从固件裁剪掉,见 W0-04(这三个模块占用大量 RAM 与 Flash,是容量与延迟的主要干扰项)
  • 任何外接传感器(振动、温湿度、电流、加速度计、ADC/I2C/SPI 外设)——v1.1 明确:MVP 只用基础主板,一根线不接。时序数据一律用确定性合成数据源注入板 A,详见 6.2 节
  • 外壳、电池、量产认证(EMC/CE)——P2 阶段
关于裁剪摄像头/麦克风/GPS 的说明:现有固件 cam_mgr.c(375) + mic_mgr.c(361) + gps_mgr.c(277) 加上 merged-*.bin 已达 1.59 MB,且 cam/mic 需要大量 PSRAM 缓冲。MVP 的目标是把尽量多的 RAM 让给 ANN 工作集(报告第 6 章:成本主导项是 I/O 与 cache 命中,不是 CPU)。这三个模块在 α 形态评估阶段可按需重新启用,但不进 MVP。

2.1 MVP 验收总判据(Go/No-Go ①)

#判据阈值(全部必须达成)
G1容量:N16R8 单板装入的记忆条数可行性门槛 ≥ 8,000 条;按 3.5 节方案 B 分区(edgehippom 11.875 MB)目标 ≥ 12,000 条(v1.1 上调;按新几何推算稳态约 14,448 条,未实测)。库须可正常打开并检索
G2延迟:12,000 条库上混合查询P50 < 10 ms,P99 < 30 ms(板侧,不含 USB 往返),且 P99/P50 < 4(抖动可控)
G3内存:检索过程 RAM 峰值PSRAM 占用 ≤ 5 MB,内部 DRAM 峰值 ≤ 180 KB(给 Wi-Fi/BLE/协议栈留余量)
G4闭环:时序 → 特征 → ANN → 回写全链路跑通,且回写的新记忆在下一次检索中可被命中
G5UX:拖拽灌库拖入 .emf 后 ≤ 60 s 完成 12,000 条合并并可查询(含校验);错误包必须被拒绝且不损坏原库
G6断网:飞行模式关闭 Wi-Fi/BLE 后,G1–G5 全部复测通过
G7事务:随机掉电 100 次库 100% 可打开,无条目数异常增长/丢失,最多丢失最后一次未 commit 事务
若 G1–G7 任一项未过:按战略报告第 11 章的处理——回退为纯软件授权路线,不做硬件。但注意本任务书的对策:若未过项是容量或延迟,且原因是 emlite 自研后端实现不佳,则应先尝试接入 emdb(eXtremeDB)后端再判;只有双后端都未过,才判硬件路线不成立。

三、硬件基线:双板分工与容量实测口径

3.1 双板分工(沿用现有资产,不新增硬件)

项目板 A:Seeed XIAO ESP32-S3板 B:S3-N16R8-DevKit
规格8 MB Flash + 8 MB PSRAM16 MB Flash + 8 MB PSRAM
MVP 形态(form)gamma-card γ 磁吸卡形态原型usb-dongle β USB Dongle 形态原型(首个自销 SKU)
形态代号γ 磁吸卡形态原型β USB Dongle 形态原型(首个 SKU 的原型)
MAC / 设备 ID44:BD:8D:71:FA:C8 → EME-71FAC814:C1:9F:21:E9:80 → EME-21E980
现网 IP192.168.1.46192.168.1.5(知识库 4343 条 / 946 KB,改前必须 --backup)
app1 偏移(W0-05 后两板同构;旧 0x300000 / 0x410000 作废)0x2100000x210000
LEDGPIO21(低电平点亮)WS2812 实测 GPIO48(勿试 38)
MVP 主接口BLE(与 B 互联,复用 link_mgr)+ 传感器输入USB-OTG GPIO19(D−)/GPIO20(D+) 复合设备 + BLE
容量档位(推算、未实测;按改分区表前的旧分区表)LITE ≈ 2,500 条(扩容后 4,500 条)BASE ≈ 10,000 条(扩容后 13,700 条)
两块板都是外设本体,差别只在形态与容量:8 MB 版 edgehippom 为 3.875 MB,稳态约 3,419 条(推算、未实测),装一个 1,800 条的专科专家包后仍有一倍余量,足以演示「专科大夫」这一叙事。差异只在容量与接口:β 形态(板 B)走 USB-OTG 直插电脑,是首个自销 SKU;γ 形态(板 A)走磁吸卡贴附。两板对等、无上下级——旧的「A 做 HOST 宿主、模拟客户主控去调用 B」是上一代 EdgeMemory Gateway 的上下级分层残留,已废止(ADR-018)。

3.2 容量实测口径(按现状分区表重算,替换报告第 6 章推算值)

v1.1 注:下表是按现状分区表(app 槽 4 MB / 2.94 MB)算出的保守值。按 3.5 节方案 B 压缩 app 槽后,实际档位应上修为 N16R8 ≈ 12,900 条、N8R8 ≈ 3,700 条(均为推算、未实测),后续章节的容量数字以方案 B 为准。
v1.2 补注(W0-05 已执行):按新几何重算的权威值为 N16R8 ≈ 14,448 条、N8R8 ≈ 3,419 条(同为推算、未实测,口径 rec_pages×4080×85%/644);本表(0x810000 / 0x5F0000)为改分区表之前的历史账,已不再适用。

单条记忆成本:int8 向量 384 B + HNSW 链接(M=16) 128 B + 摘要 ≤150 B = 662 B;页/索引/元数据开销按 12% 计。

板edgehippom 分区字节理论条数规划口径扩容选项
N16R8(B)0x810000 / 0x7E00008,257,53610,97610,000 条app 槽 4 MB → 2.5 MB,edgehippom → 9.875 MB ≈ 13,700 条
N8R8(A)0x5F0000 / 0x2000002,097,1522,7872,500 条app 槽 2.94 MB → 2.25 MB,edgehippom → 3.375 MB ≈ 4,500 条

v1.2 修订(实测):app 镜像实测 edgehippom-<board>-<ver>.bin = 1,530,080 B(1.459 MiB),merged-devkit-16m.bin = 1,595,616 B。v1.1 假设「裁剪 cam/mic/gps 后降至 ~1.1 MB」不成立——按 .map 逐段统计,可裁剪部分仅约 120 KB(esp32-camera 83.7 KB + I2S 驱动 31.1 KB + cam/mic/gps 三个自有模块 8.4 KB),裁剪后约 1.34 MiB;MVP 还要新增 TinyUSB 与 emlite,完整态预计 ≈1.45 MiB。因此 app 槽下限应为 2 MB(余量 ≈38%),1.5 MB 槽不可行。详见 3.5.7 节。

3.3 碎片容量规划(由此倒推叙事)

碎片类型条目规模N16R8 可装N8R8 可装典型内容
专家记忆包1,500–2,5004–6 个1 个某人的会议/偏好/决策历史
设备档案包400–1,00010–25 个3–6 个某型号设备故障模式、工况参数、维修记录
域知识包5,000–8,0001–2 个—产品线 SOP、区域法规、质检标准
感知模式包持续生长按留存策略按留存策略闭环产出的时序特征向量
对外叙事必须诚实:卖的不是「随身带一个图书馆」,而是「随身带一个记得你 / 记得这台机器 / 记得这套工艺的专科大夫」。

3.4 引脚分配(MVP)

功能板 B(usb-dongle)板 A(gamma-card)说明
USB-OTGGPIO19 D− / GPIO20 D+—β 形态命脉。与 USB-Serial-JTAG 共用同一 PHY,同一时间只能一个工作
Console / 下载UART0 GPIO43/44UART0 GPIO43/44MVP 把 console 从 USB-Serial-JTAG 切到 UART0,把 GPIO19/20 完整让给 OTG
板间互联(主)NimBLE(现有 link_mgr)NimBLE已跑通,零新增硬件
板间互联(备)UART1 GPIO17 TX / GPIO18 RXUART1 GPIO17 TX / GPIO18 RXα 形态模组评估用(SPI 方案 P1 评估)。须在 boards/BOARD_*.md 核对实际引出情况
传感器输入—不接(v1.1 修订)改用确定性合成数据源在板内生成,见 6.2 节。真实采集推迟到 P1(W4-07)
LEDWS2812 GPIO48GPIO21(低电平点亮)沿用现有状态机
USB 通道切换的三个坑(本项目已有实战经验,必须在 W0-02 一次性处理干净):
  1. PHY 冲突:ESP32-S3 的 USB-OTG 与 USB-Serial-JTAG 共用 GPIO19/20 与同一个 PHY。要跑 TinyUSB 复合设备就必须让出 PHY。后果是不能再通过 USB 串口烧录和看日志——因此 W0-02 必须先把 console 切到 UART0,并在板 B 上接一个 USB-UART 转换器(CP2102/CH343)用于开发与排障。
  2. sdkconfig 写法的坑:CONFIG_ESP_CONSOLE_* 是一个 choice 组。在 sdkconfig.defaults 里给其它成员写 =n 会导致整组失效、回退到默认 UART。正确做法是只给目标成员写 =y,绝不给其它成员写 =n。
  3. VBUS 监测:自供电设备需通过分压或比较器检测 VBUS(S3 引脚 3.3 V 耐压,不能直接接 5 V)。β 形态量产前必须处理。

3.5 OTA 与分区决策(v1.1 新增 / v1.2 修订)

v1.2 补注(2026-10-28 · W0-05 已执行):分区表方案 B 已落地,本章口径以本节为准。
  1. 分区名:旧 edgemem(动态记忆分区)与 kb_static(静态知识库分区) 已删除并合并为单一引擎分区 edgehippom(subtype 0x42,起始 0x410000)。 两板分区表同构,只有 edgehippom 大小不同: Dev-B(N16R8)= 0xBE0000 = 11.875 MB = 3,040 页; Dev-A(N8R8)= 0x3E0000 = 3.875 MB = 992 页。
  2. 烧录偏移:0x0 bootloader / 0x8000 partition / 0xe000 ota_data / 0x10000 app0 / 0x210000 app1。 旧的 app1 偏移 8MB 板 0x300000、16MB 板 0x410000 全部作废。
  3. 容量(★推算、未实测★):口径 rec_pages × 4080 × 85% / 644。 Dev-B rec_pages = 2,683 → 稳态约 14,448 条; Dev-A rec_pages = 635 → 稳态约 3,419 条。 本章其余各处出现的 12,900 / 3,700 条是 v1.1 按旧几何推算的旧值,同为推算、未实测,尚未按新几何逐表重算(见下面 3.5.2 / 3.5.3 表下的口径说明)。
  4. 不可逆代价已发生:改分区表 = 已灌记忆全部作废、必须整片重烧 + 重灌。 执行前已整分区镜像备份 C://emgw-build//backup_20261028//devb_edgemem_4MB.bin(4,343 条真实遥测)。
先给结论:OTA 强烈建议保留,而且它几乎不牺牲容量——真正吃掉容量的是「app 槽开得过大」。

现网固件实测 merged-devkit-16m.bin = 1,595,616 B ≈ 1.52 MB,却被塞进两个 4 MB 的 OTA 槽,白扔了约 4.8 MB(相当于 5,900 条记忆)。把槽压到 2 MB 后,edgehippom 从 7.875 MB 提到 11.875 MB,容量从 8,000 条涨到 14,448 条(推算、未实测;v1.1 旧推算 12,900 条),而 OTA 能力完整保留。

3.5.1 分区账怎么算

Flash 可用空间 = 总容量 − 头部(bootloader 0x0 + 分区表 0x8000 + nvs + otadata = 0x10000)− 尾部余量(0x10000)。
换算系数:1 MB edgehippom ≈ 1,227 条(推算、未实测)(662 B/条含 12% 开销 → 752 B/条)。时序区按 N16R8 = 1.375 MB、N8R8 = 0.875 MB 预留。

3.5.2 N16R8(板 B,16 MB)四种方案

方案app 槽 ×2edgehippom记忆库容量(推算、未实测)评价
A 现状4 MB ×2 = 8 MB7.875 MB6.5 MB8,000❌ 浪费 4.8 MB,无理由维持
B 推荐2 MB ×2 = 4 MB11.875 MB10.5 MB12,900✅ +61% 容量,OTA 完整保留,代码零改动
C 激进1.5 MB ×2 = 3 MB12.875 MB11.5 MB14,100❌ v1.2 改判:不可行。实测裁剪后固件 ≈1.34 MiB,MVP 完整态 ≈1.45 MiB,1.5 MB 槽余量 <5%。只比 B 多 1,200 条(+9.3%)却承担爆槽风险
D 去掉 OTA单槽 2 MB13.875 MB12.5 MB15,300⚠️ 只比 B 多 2,400 条,却失去回滚能力

OTA 的真实净代价 = B vs D = 2,400 条(−15.7%)。而 B 相对现状 A 的收益是 +4,900 条(+61%)。也就是说:容量问题 87% 来自槽开大了,只有 13% 来自 OTA 本身。

推算口径说明(2026-10-28):上表「容量」列为 推算值、未实测(记忆库 MB × 1,227 条/MB)。W0-05 执行后按 rec_pages × 4080 × 85% / 644 重算,方案 B 的权威值应为 14,448 条;与表内 12,900 条的差异来自 ADR-015 压缩时序区后记录区占比提高,本表尚未按新几何重算——以本节开头的 v1.2 补注为准。

3.5.3 N8R8(板 A,8 MB)四种方案

方案app 槽 ×2edgehippom记忆库容量(推算、未实测)评价
A 现状2.94 MB ×2 = 5.88 MB2.0 MB1.4 MB1,700❌ 8 MB 板上最严重的浪费
B 推荐2 MB ×2 = 4 MB3.875 MB3.0 MB3,700✅ +118%,余量 0.8 MB 仍充足
C 激进1.75 MB ×2 = 3.5 MB4.375 MB3.5 MB4,300❌ v1.2 改判:不推荐。1.75 MB 槽余量 ≈0.3 MiB(<20%);而板 A 只需装 1,800 条专家包,B 方案(推算 3,419 条、未实测)已有一倍余量,多 600 条无实际价值
D 去掉 OTA单槽 2 MB5.875 MB5.0 MB6,100⚠️ 多 2,400 条,失去回滚

推算口径说明(2026-10-28):上表「容量」列为 推算值、未实测。方案 B 的权威值应为 3,419 条(rec_pages × 4080 × 85% / 644);表内 3,700 条为 v1.1 旧推算,尚未按新几何重算——以本节开头的 v1.2 补注为准。

3.5.4 推荐分区表(可直接替换)

# partitions_emgw_16m.csv —— v1.1 方案 B(N16R8)
nvs,        data, nvs,     0x9000,    0x5000,
otadata,    data, ota,     0xe000,    0x2000,
app0,       app,  ota_0,   0x10000,   0x200000,
app1,       app,  ota_1,   0x210000,  0x200000,
edgehippom, data, 0x42,    0x410000,  0xBE0000,
#  0x410000 + 0xBE0000 = 0xFF0000,尾部留 64 KB 余量
#  edgehippom subtype = 0x42(旧 edgemem/kb_static 的 0x40/0x41 已废止)
#  稳态容量约 14,448 条(rec_pages 2,683 × 4080 × 85% / 644)—— 推算、未实测

# partitions_emgw.csv —— v1.1 方案 B(N8R8)
nvs,        data, nvs,     0x9000,    0x5000,
otadata,    data, ota,     0xe000,    0x2000,
app0,       app,  ota_0,   0x10000,   0x200000,
app1,       app,  ota_1,   0x210000,  0x200000,
edgehippom, data, 0x42,    0x410000,  0x3E0000,
#  0x410000 + 0x3E0000 = 0x7F0000,尾部留 64 KB 余量
#  edgehippom subtype = 0x42(旧 edgemem/kb_static 的 0x40/0x41 已废止)
#  稳态容量约 3,419 条(rec_pages 635 × 4080 × 85% / 644)—— 推算、未实测

3.5.5 三条必须知道的配套事实

事实含义
OTA 不碰知识库edgehippom 是独立分区,OTA 只写 app0/app1。升级固件不会破坏已灌入的记忆——这对「记忆资产」类产品是底线要求,现有 ota_mgr 已满足
OTA 代码已经写好现有 main/ota_mgr.c 已实现:双 OTA 槽 + BOOTLOADER_APP_ROLLBACK_ENABLE + 启动 5 s 后 em_ota_mark_valid() 自证 + POST /ota(X-OTA-Token)+ ota_upload.py。保留 OTA = 零工作量;去掉 OTA 反而要改代码
槽大小有硬下限槽必须 ≥ 固件镜像大小。v1.2 实测:现状 1.459 MiB,裁剪后 ≈1.34 MiB,MVP 完整态 ≈1.45 MiB → 2 MB 槽余量 ≈0.55 MiB(38%)。建议设一条构建期硬门槛:app 镜像 > 槽 × 0.8 即告警、> 槽 × 0.9 即失败(见 W0-06)。一旦加回任一功能模块,必须重新评估
改槽的成本是不可逆的app 槽变小 → app1 结束地址前移 → edgehippom 起始偏移改变 → 已灌入的库全部作废,必须整片重烧 + 重灌。分区不能向后增长。所以「先用 B、容量不够再改 C」这条路是有代价的,不能当作免费选项
给 β 形态留的第三选项(P1 评估):UF2 拖拽升级替代 OTA 双槽。 ESP-IoT-Solution 有官方「Virtual USB Flash Drive UF2 OTA」方案——既然 β 形态本来就要做虚拟 U 盘,拖固件升级和拖 .emf 灌库可以用同一套交互,UX 上更统一,还能省下整个第二槽(N16R8 → 15,300 条)。
但风险要写清楚:单槽写入中断 = 变砖,只能串口救砖。由于 β 形态插在用户电脑上、USB 在手,风险可接受;α 模组形态(焊在客户设备里)绝不可采用,必须保留双槽 OTA。

3.5.6 决策与执行

阶段采用方案理由
MVP(P0)方案 B:双槽 OTA,槽 2 MB迭代频繁,回滚能力是刚需;已验证的代码零改动;容量 +61% / +118%
P1(β 工程样机)评估 UF2 拖拽升级 vs 保留双槽取决于变砖风险接受度与 UX 统一价值
P2(α 模组量产)强制保留双槽 OTA焊死在客户设备内,无 USB 救援通道
执行注意事项(沿用现有铁律):分区表是板级配置,两板各有各的 CSV,禁止跨板拷贝 sdkconfig;改分区表后必须整片重新烧录(分区表变了,OTA 无法跨分区布局升级),所以这个改动要在正式灌库前做掉,之后不要再动。改完先用 esptool flash-id 确认 Flash 容量,再核对 sys.info 输出的分区信息。

3.5.7 方案 C 专项评估(v1.2 新增)

v1.1 把方案 C 标为「激进但可行」,理由是「裁剪后固件约 1.2 MB,1.5 MB 槽余量 0.3 MB」。这个 1.2 MB 是估的,v1.2 用实机 .map 把它测出来了,结论相反。

实测:裁剪 cam/mic/gps 到底能省多少

数据源:C:\emgw-build\fw_ascii\build_devkit_16m\edgehippom-<board>-<ver>.map(devkit/16m 变体,逐段统计 .text + .rodata + .dram)。

可裁剪项实测占用说明
esp32-camera 组件83.7 KB唯一的大头。三个自有模块只是它的薄封装
I2S 驱动(esp_driver_i2s)31.1 KB麦克风用;若合成源与音频都去掉可全额释放,保守按 25 KB 计
cam_mgr.c3.1 KB自有代码
mic_mgr.c2.9 KB自有代码
gps_mgr.c2.4 KB自有代码
可省合计(保守)≈ 115–123 KB远小于 v1.1 假设的 400 KB

对比参照:cli_json.c 一个文件就 13.8 KB,link_mgr.c 10.3 KB。真正的 flash 大头是 WiFi/BLE/mbedTLS(libnet80211、libbtdm_app、psa_crypto 等都在 20–57 KB 量级),这些 MVP 一样也砍不掉。

MVP 完整态固件尺寸预算

构成尺寸(MiB)依据
现状 app 镜像1.459edgehippom-<board>-<ver>.bin = 1,530,080 B(实测)
− 裁剪 cam/mic/gps−0.115上表实测
+ TinyUSB 复合设备(CDC + MSC)+0.06 ~ 0.10device stack + class driver 量级估算,待 W0-03 冒烟后实测
+ emlite 引擎(HNSW + 时序 + WAL)+0.03 ~ 0.05目标 .text ≤ 60 KB(见 4.4 节)
+ 调试命令 / 性能计数器+0.01 ~ 0.02MVP 必带
MVP 完整态预计≈ 1.44 – 1.49 MiB中位 1.45 MiB

三个方案按实测重算

方案槽余量(MiB)余量 %判定
B(N16R8)2.0 MB0.51 ~ 0.5634–38%✅ 安全,采用
C(N16R8)1.5 MB0.01 ~ 0.061–4%❌ 基本等于零余量,且现有固件就已超出(1.459 > 1.5 减去对齐开销后装不下)
C(N8R8)1.75 MB0.26 ~ 0.3115–18%❌ 过紧;板 A 只需 1,800 条,B 方案(推算 3,419 条)已够
结论:方案 C 不合适,两板都不采用。
① 收益极小:N16R8 只多 1,200 条(+9.3%),N8R8 只多 600 条(+16%)。容量判据 G1 的门槛是 8,000 条、目标 12,000 条,方案 B 的 14,448 条已经超额(推算、未实测),多出来的 9% 不改变任何产品叙事(对外都是「万条级」)。
② 风险极大且不可逆:槽爆了不是「功能降级」,而是现场设备永远停在旧固件——esp_ota 在写入前校验失败会拒绝升级,设备带病运行且无法远程修复。对 β 形态(插在用户电脑上、靠 OTA 迭代)这是致命的。
③ 改槽要重灌库:edgehippom 起始偏移会变,已灌入的记忆全部作废。为了 9% 的容量赌一次不可逆操作,期望值为负。
真正值得去争的容量杠杆,不在 app 槽上。三个按性价比排序:
  1. 每条字节数(杠杆最大,可达 +50% ~ +150%)。当前口径 662 B/条 = 384 B 向量(int8 × 384 维)+ 150 B 摘要 + 索引开销。若改用 256 维 embedding,或把向量再做一次 PQ/SQ 量化(384 B → 96–128 B),容量直接翻倍以上。代价是召回率与延迟,必须用 S1/S3 场景实测换(已列为 WBS 任务 W1-14)。这一项的量级远超方案 C 的 9%。
  2. 时序区预算重分配(+1,100 条,零风险)。方案 B 给 N16R8 预留 1.375 MB 时序区。但 v1.1 已决定 L0 原始波形放 PSRAM 不落 flash,L1 是分钟级聚合,L2 是特征向量 —— 实际用量很可能远小于 1.375 MB。实测后若只用到 0.5 MB,可把 0.875 MB 划回记忆库,+1,100 条。
  3. 把「记忆库 / 时序区」的比例从分区表静态切分,改成 edgehippom 分区内部动态分配。这样将来调比例不用改分区表、不用整片重烧,只需重灌。强烈建议在 emlite 设计里就这么做(W1-02)。

四、软件架构:五层 + 双后端引擎 HAL

4.1 分层

L4  接口层   usb_cdc(行协议)  usb_msc(拖拽灌库)  ble(link_mgr)  mcp_shim  http(仅灌库/OTA)
L3  策略层   EdgeMemory:生命周期(工作/短期/长期) / 遗忘淘汰 / 冲突消解 / 去重 / 重要性
L2  引擎层   EM Engine HAL  ← 单一真源接口,两套可替换后端
               ├─ emdb   : eXtremeDB 后端(目标形态,授权到位后启用)
               └─ emlite : 自研 flash-backed HNSW + 列式时序环 + WAL(P0 立即可用)
L1  存储层   edgehippom 分区 / PSRAM cache / 页管理 / CRC32 / 磨损均衡
L0  平台层   ESP-IDF v6.1 + FreeRTOS + TinyUSB + NimBLE
为什么必须做双后端(这是本设计最重要的一个决定):战略报告把「McObject 的 MCU 端授权条款」列为阻塞全部的第一待验证项。如果不做 HAL,MVP 会在 W1 第一天就停下来等律师和商务。做了 HAL 之后:
① eXtremeDB 变成性能优化项而非前置阻塞项;
② 手上有了 emlite 的实测数据,与 McObject 谈授权时议价地位完全不同(能拿出真实的容量/延迟数字,而不是求人给方案);
③ 万一授权谈崩,产品仍然成立——只是容量与延迟差一档。

4.2 引擎 HAL 接口(em_engine.h,单一真源)

/* 生命周期 */
em_err_t em_open (const em_cfg_t *cfg, em_db_t **out);
em_err_t em_close(em_db_t *db);

/* 事务 */
em_err_t em_txn_begin (em_db_t *db);
em_err_t em_txn_commit(em_db_t *db);      /* 掉电安全:要么全见,要么全不见 */
em_err_t em_txn_abort (em_db_t *db);

/* 记忆条目 */
em_err_t em_mem_put   (em_db_t *db, const em_mem_t *m, uint64_t *id);
em_err_t em_mem_get   (em_db_t *db, uint64_t id, em_mem_t *out);
em_err_t em_mem_del   (em_db_t *db, uint64_t id);

/* 混合查询:向量 + 精确条件 + 时间范围,同一事务 */
em_err_t em_query(em_db_t *db, const em_query_t *q, em_hit_t *hits,
                  size_t max_hits, size_t *n_out);
/*  em_query_t {
      const int8_t *vec;      uint16_t dim;      /* 宿主提供,板侧不 embedding */
      uint16_t topk;          uint16_t ef_search;
      uint16_t frag_mask;     /* 限定碎片 */
      uint32_t t0, t1;        /* 时间范围(时序/记忆共用) */
      uint16_t dev_id;        uint8_t  level;    /* 精确条件 */
      float    min_salience;
    } */

/* 时序 */
em_err_t em_ts_append(em_db_t *db, uint16_t dev_id, uint8_t ch, uint32_t ts, float v);
em_err_t em_ts_agg   (em_db_t *db, uint32_t win_ms);   /* L0 → L1 分钟聚合 */

/* 碎片 */
em_err_t em_frag_install(em_db_t *db, const char *path);  /* 灌库 */
em_err_t em_frag_list   (em_db_t *db, em_frag_t *out, size_t *n);
em_err_t em_frag_remove (em_db_t *db, uint16_t frag_id);

/* 运维 */
em_err_t em_stat(em_db_t *db, em_stat_t *out);   /* 条数/字节/RAM峰值/命中率 */
em_err_t em_gc  (em_db_t *db, float water_mark); /* 遗忘淘汰 */

emdb 与 emlite 必须同时通过上述同一组接口的一致性测试(W1-08),否则 HAL 形同虚设。

4.3 目录结构(在现有 fw_ascii 上增量,不推倒重来)

main/
├── app_main.c            (现有,改:形态标识 form;旧 role 已废止)
├── em_engine.h           ★ 新增:HAL 接口单一真源
├── em_engine_lite.c      ★ 新增:emlite 后端(页管理 + HNSW + 时序环 + WAL)
├── em_engine_db.c        ★ 新增:emdb 后端(eXtremeDB,授权到位后填)
├── em_ann.c              ★ 新增:int8 距离核 + HNSW 遍历 + IVF 粗划分
├── em_ts.c               ★ 新增:列式时序 L0/L1/L2
├── em_wal.c              ★ 新增:事务日志与崩溃恢复
├── em_mem.c              ★ 新增:策略层(生命周期/遗忘/去重/重要性)
├── em_frag.c             ★ 新增:.emf 碎片包解析、校验、安装
├── em_mcp.c              ★ 新增:MCP shim
├── usb_dev.c             ★ 新增:TinyUSB 复合设备 CDC+MSC
├── usb_msc_disk.c        ★ 新增:虚拟 U 盘 + 拖拽灌库
├── em_store.c            (现有,改造:底层改用 em_engine,保留 store.map 诊断)
├── cli_json.c            (现有,扩展:mem.* / frag.* / ts.* / ann.* 命令)
├── link_mgr.c            (现有,复用:板间 BLE 互联与碎片接力)
├── led_mgr.c wifi_mgr.c ble_mgr.c ota_mgr.c kb_ota.c http_srv.c   (保留)
└── cam_mgr.c mic_mgr.c gps_mgr.c  (MVP 裁剪:Kconfig 控制,默认 n)
固件分层纪律(沿用现有约定):通用层(main/ 框架与协议)改动必须两板回归;板级差异一律走 boards/sdkconfig.<board_id> + 分区表 + CONFIG_EMGW_*,禁止跨板拷贝 sdkconfig。构建唯一入口 build_board.ps1 -Board xiao|devkit|all,升级前先问清是哪块板。

4.4 eXtremeDB 优势保留矩阵(v1.1 新增)

emlite 先行不代表可以随便写一个「能跑就行」的向量检索——那样到替换时等于重写一遍。本节把 eXtremeDB 的公开能力逐条映射为 emlite 的设计约束与验收点,确保替换前后行为语义一致、性能特征连续。以下能力描述均取自 McObject 官方技术规格页、Steve Graves 技术文章与 Andrei Gorine 的公开发表材料(见修订说明中的来源清单)。

4.4.1 先锁定三条来自 Andrei Gorine 的硬约束

这三条是 eXtremeDB 区别于「普通嵌入式 KV 存储」的根本,也是 emlite 最容易做错的地方,必须写进设计约束而不是事后优化:
  1. 运行时不调用 malloc。eXtremeDB 核心运行时实现自有内存管理器,不使用系统 malloc(Andrei Gorine, Dr. Dobb's;McObject FAQ 明确答复)。emlite 必须全部预分配内存池——这不只是性能问题,它直接决定 P99 抖动,也正呼应 Steve Graves《Justifiably Taboo: Avoiding malloc-free APIs》的论点。
  2. flash 的不可预测性来自介质之上的层,不是 flash 本身。NAND/SPI flash 的读、编程、擦除在物理层有明确时序;不可预测性来自 FTL 与文件系统(缓冲、日志、写重排、延迟分配)。emlite 必须做「事务感知的 flash 管理」:擦除与 GC 只在事务边界之外或后台执行,查询关键路径上只允许读和顺序写。这与白皮书「成本主导项是 I/O」完全一致。
  3. 回滚成本必须绑定到已知写集。eXtremeDB/rt 用 CoW 显式跟踪修改页,使回滚时间可分析;并在 flash I/O、页管理、锁等待周围布高分辨率时序检查点,让内核能在执行期间判断事务是否还能满足截止时间。emlite 的 WAL 必须记录写集,且 em_txn_abort 的耗时必须可预测并被实测。
一个互相印证的判断:Andrei 说「控制时间比收集每一条数据更重要——航电中用已经过期的传感器数据,可能比直接跳过它更危险」;官方白皮书说「为可预测性调优,而非峰值召回」。两句话是同一个原则的两种表述,它同时是 emlite 的调优准则和 G2 判据里「P99/P50 < 4」这条的来源。

4.4.2 优势保留矩阵(14 项)

#eXtremeDB 能力emlite 必须如何体现验收点替换后
1原生 ANN 索引(HNSW/Vamana),事务一致——官方强调「不是 bolted-on 外部库,不参与其余数据流」ANN 索引更新必须走同一个 WAL 事务;commit 时数据与索引同时生效,abort 时索引一并回滚。禁止「先写数据、再异步建索引」TC-C-04/05 事务测试必须覆盖索引;索引与数据不一致即判失败直接切 HNSW/Vamana
2sequence 列式时序存储(官方规格列出的专用类型)时序按列存储 + delta 压缩,Chunk 按时间分区;不用行式TC-C-06;写入吞吐 ≥1600 点/s改用 sequence 类型
3混合查询:ANN + B-tree/Hash/R-tree/KD-tree/Patricia/Trigram/User-defined 同引擎同事务至少实现 B-tree(时间/dev_id/frag_id)+ Trigram(文本模糊)+ ANN;必须保留 user-defined 索引接口TC-C-03 混合查询正确性;与「先 ANN 后过滤」参考实现一致补全其余索引类型
4ACID + 三种事务管理器(MURSIW / Exclusive / MVCC)+ 事务优先级 + delayed commit实现 MURSIW(多读单写)——最契合 FreeRTOS 单写者模型;事务优先级映射到 FreeRTOS 任务优先级TC-C-04/05 + TC-N-07MVCC 为 emdb 增量优势
5事务日志 + CRC;CRC 兼作未授权篡改检测WAL + CRC32;同一套 CRC 用于 .emf 碎片验签(离线、无网)TC-N-07 掉电;TC-F-03 篡改包必须被拒直接对应
6极小 footprint:Edge Client ≤8 KB;核心运行时约 200 KB;rt 服务版实测 1 GB flash 库仅需 40 KB 内存(元数据+缓存+栈)把「代码体积 + RAM 占用」列为硬指标而非副产品。8 MB 分区的 RAM 占用应远低于 PSRAM 5 MB 上限新增 TC-N-11:记录 emlite 的 .text 体积与峰值 RAM,作为替换收益的基线预期数量级改善
7运行时不调用 malloc(自研内存管理器)全预分配池:页缓存池、HNSW 遍历栈、查询结果缓冲均在 em_open 时按 cfg 分配完毕代码审查 + 运行期 heap_caps 水位监测(稳态无增长)行为一致
8compact data layout(内部引用压到 16 bit)条目内引用用 uint16;frag_id/dev_id 用定宽字段,不用指针单条成本实测 ≤ 752 B(含开销)编译时开关
9类型安全 API(编译期捕获类型错误,避免 void*)schema 生成强类型 C 结构体;HAL 接口不用 void* 传数据编译期;em_query_t 等结构全字段显式DDL 编译期生成
10Active Replication Fabric:边→服多层复制、断网排队、双向MVP 不实现复制,但 HAL 必须预留 em_sync_* 接口与出队/入队语义,空实现即可接口存在且语义与 ARF 对齐(write-first → commit → 上行 → 回收本地)直接启用,Hub 中继与碎片同步即基于此
11确定性 / 硬实时:CoW deadline-aware 事务模型 + 多档截止时间策略事务 API 预留 deadline_us 参数;超时按策略中止而非无限等待TC-N-02 的 P99;abort 耗时可预测(新增 TC-N-12)eXtremeDB/rt 全部能力
12TFTL 事务感知 flash 管理:磨损均衡/GC/坏块与事务调度协同擦除与 GC 只在事务边界外执行;查询路径只读 + 顺序写;坏块表预建TC-N-02 抖动指标;TC-N-08 磨损均衡分布交由内核
13引擎内特征提取:array/math/statistical 函数;多速率传感器按共同时间窗对齐/重采样em_ts 提供窗口统计(min/max/mean/rms/峰度 + FFT 频段能量);多速率对齐在引擎内完成TC-C-06;W4-02 单窗口 ≤15 ms改用内建函数
14混合存储(按表指定 in-memory / persistent)+ 事务内快照热碎片常驻 PSRAM、冷数据落 flash 按表配置;em_snapshot 在事务内产出一致镜像em_stat 能分表报告;快照可回灌直接对应

4.4.3 emlite 的自有硬指标(三个不可退让的数字)

指标目标说明
代码体积(.text)≤ 60 KBeXtremeDB 核心约 200 KB、Edge Client ≤8 KB。emlite 是裁剪版,理应更小;超过 100 KB 说明实现膨胀,需重审
运行期动态内存分配0 次em_open 之后到 em_close 之前,不允许 malloc/free
abort 耗时可预测性P99 ≤ 2×P50写集显式跟踪 → 回滚时间与写集大小线性相关,不得出现长尾

这三个数字同时是「替换收益」的度量基线:接入 emdb 后重测同一组指标,差值即为授权谈判中值得付出的溢价。

4.4.4 一个值得抄的工程做法:flash 仿真层

eXtremeDB/rt 服务版提供了「硬件无关 flash 仿真」——用事务文件映射模拟 raw flash / managed NAND / eMMC / SD 卡的访问行为,让团队在拿到物理硬件之前就能调优存储布局与缓存参数。

emlite 应照做:把 L1 存储层抽象出一个 em_flash_io 接口(读页 / 写页 / 擦除块),除真实 esp_partition 实现外,再提供一个基于文件的仿真实现(可注入人为延迟与坏块)。收益有三:
① W6-01 的单元测试全部可以在 PC 上跑,不必依赖硬件,85% 覆盖率的引擎层单测变得现实;
② 掉电测试(TC-N-07)可以在仿真层精确控制断电时刻,比物理断电更容易复现与定位;
③ 可以在没有第二块板的情况下评估不同 flash 布局对 P99 的影响。

4.4.5 替换验收清单(W1-13 的细化)

#验收项判据
1同一数据集在两后端上的 top-k 结果集合完全一致(排序容差 ±1 位)
2事务语义(原子/一致/隔离/持久)TC-C-04/05 + TC-N-07 两后端均通过
3混合查询语义(ANN + 精确条件 + 时间窗)TC-C-03 结果一致
4三条硬约束malloc-free、事务感知 flash 管理、abort 可预测——emdb 必须不劣于 emlite
5容量与延迟同分区下 emdb 的容量 ≥ emlite、P99 ≤ emlite。否则不切换
6策略层与接口层零改动切换后端只需改一行构建配置,em_mem.c / em_frag.c / em_mcp.c 不动

五、数据模型:schema 草案

用统一的 schema 语言描述,emdb 后端直接编译成 eXtremeDB DDL,emlite 后端映射为等价 C 结构体 + 定长页布局。两份定义必须同源同构——这是报告第 7.1 节「模式统一」原则的工程落实,避免 PC 侧打包器与板侧布局漂移。

5.1 记忆表 Memory(核心)

class Memory {
    uint64   id;               /* 全局唯一,单调递增 */
    uint32   ts_ms;            /* 创建时间 */
    uint16   frag_id;          /* 所属碎片包 —— 物理接力与卸载的最小单位 */
    uint8    level;            /* 0=工作记忆 1=短期 2=长期 */
    uint8    src;              /* 来源:0灌库 1时序闭环 2宿主写入 3接力 */
    float    salience;         /* 重要性 0..1,遗忘淘汰的输入 */
    uint32   access_cnt;       /* 命中次数 */
    uint32   last_access_ms;   /* 最近命中,LRU 输入 */
    uint16   dev_id;           /* 关联设备(精确条件) */
    uint16   tags;             /* 标签位图(精确条件) */
    char     payload[150];     /* 摘要正文,UTF-8,硬上限 150 B */
    vector<int8, 384> emb;     /* int8 量化向量 */

    unique tree<uint64>            pk;
    tree<uint16, uint64>           by_frag;
    tree<float, uint64>            by_salience;
    tree<uint32, uint64>           by_time;
    ann<cosine, 384>               ann_idx;   /* HNSW,M=16,ef_construct=200 */
};
payload 150 B 是硬约束,不是建议值。中文一字 3 字节,150 B ≈ 50 个汉字。打包器(W5-02)必须做截断并留 4 B 终止符,且绝不能在多字节字符中间截断——否则会产生非法 UTF-8,在 JSON 输出时整帧损坏(本项目已有此坑:JSON 缓冲含中文不能用 256 B,须 768 B)。

5.2 时序三表(闭环的物理载体)

class Sample {                 /* L0 原始:环形,必然被覆盖 */
    uint64 id;  uint32 ts_ms;  uint16 dev_id;  uint8 ch;  float val;
    unique tree<uint64> pk;    tree<uint32, uint64> by_time;
};
class Window {                 /* L1 分钟聚合:趋势追溯、合规留痕 */
    uint64 id;  uint32 win_start;  uint16 dev_id;
    float  min[16], max[16], mean[16], rms[16];
    unique tree<uint64> pk;    tree<uint32, uint64> by_time;
};
class Pattern {                /* L2 特征向量:闭环产物,长期资产 */
    uint64 id;  uint32 win_start;  uint16 dev_id;  uint8 label;
    float  confidence;
    vector<int8, 384> emb;
    uint64 src_win_id;         /* ★ 可回溯到产生它的那段时序 */
    ann<cosine, 384> ann_idx;
    unique tree<uint64> pk;    tree<uint32, uint64> by_time;
};

src_win_id 这一列是整个方案的技术内核:ANN 命中后能直接回溯到生成它的那一段传感器历史——这正是 McObject 官方文章给出的路径终点,也是「记忆」区别于「硬盘」的地方。

5.3 碎片表 Fragment 与账本

class Fragment {
    uint16 frag_id;   char  name[24];   uint32 version;
    uint32 count;     uint32 bytes;     uint32 crc32;
    uint8  sig[64];                    /* 来源签名(离线可验签) */
    uint32 install_ms;  uint8 state;   /* 0安装中 1就绪 2损坏 3卸载中 */
    unique tree<uint16> pk;
};

5.4 .emf 碎片包结构(与 schema 同源)

memory-fragment.emf            一个自洽、可离线验证的记忆单元
├── manifest.json              schema 版本 / 条数 / 维度 / 量化方式 / 领域标签 / 时间范围
├── vectors.bin                int8 向量,【按 IVF 簇顺序排列】
├── graph.bin                  HNSW 链接,离线构建,已优化落盘顺序
├── payload.bin                每条 ≤150 B 摘要(可选加密)
├── timeseries.bin             附带的时序特征历史(可选)
└── signature                  来源签名 + CRC32(离线可验签)
三原则(报告 7.1,工程化为强制校验项):
① 自洽:一个包必须能独立加载、独立检索、独立验证。em_frag_install 必须拒绝任何声明外部依赖的 manifest。
② 离线可验签:无网、无 Hub 也能校验完整性与来源——这是「物理接力」成立的前提。
③ 模式统一:打包必须用与板侧同源的 schema 定义,禁止 PC 侧另写一份。

5.5 三级留存策略(遗忘机制的物理实现)

层级粒度速率7.875 MB 可存作用
L0 原始100 Hz × 16 CH≈ 2.4 KB/s≈ 80 分钟环形缓冲,只服务事后取证,必然被覆盖
L1 分钟聚合1 min × 16 CH≈ 15 KB/h≈ 30 天趋势追溯、合规留痕
L2 特征向量每 10 s 一窗,按 5% 保留≈ 220 KB/天≈ 50 天且持续生长识别出的工况模式、异常指纹 —— 长期资产
「原始波形只留 80 分钟,但它提炼出来的模式会留很久。就像人忘记三年前某顿饭吃了什么,却记得那次食物中毒。」

这组对比同时回答三个常被追问的问题:为什么不上云、为什么能长期学习、以及「记忆」和「硬盘」的区别是什么(硬盘什么都留,记忆会挑)。

5.6 修正:L0 不落 flash,L2 靠去重收敛(Flash 预算分配)

对战略报告 6.6 节的一处必要修正。原表把 L0 原始波形算进 11 MB flash 预算,得出「80 分钟」。但引擎分区实测只有 7.875 MB,且必须与向量库共享;按原分配,L0 只能分到不到 1 MB(约 7 分钟),而 L1「30 天」需要 10 MB 以上——两个数字都不成立。修正如下:
  1. L0 原始波形放在 PSRAM 环形缓冲,不落 flash。10 s 窗口 @ 4 kHz × 3 轴 × int16 = 240 KB,PSRAM 完全吃得下。窗口特征化在 RAM 内完成。只有被判定为异常的窗口才转存 flash 取证区(降采样包络 12 KB/窗)。这既正确也更省。
  2. L2 不做无限生长,靠去重收敛。新 Pattern 入库时若与已有条目余弦 > 0.95,则合并更新而非新增(复用 W2-03 的去重器)。稳态下 L2 收敛为该设备的「工况模式字典」,经验规模 500–2,000 条。去重机制就是 L2 的容量控制阀——这也正好是「记忆会挑」的工程实现。
区域MVP 预算单位成本承载量说明
记忆向量库(Memory + ANN)6.5 MB662 B/条,含 12% 开销 → 752 B≈ 8,200 条MVP 主验证对象,预算优先给它
L1 五分钟聚合0.6 MB5 CH × 4 统计量 × 4 B / 5 min = 960 B/h≈ 27 天趋势追溯、合规留痕
L2 特征向量0.5 MB384 B + 链接 128 B = 512 B(含开销 582 B)≈ 900 条去重收敛后稳态 ≤ 600 条
异常取证波形0.2 MB降采样包络 12 KB/窗≈ 16 个事件配合 L1 时间索引定位
元数据 / 预留0.075 MB——碎片表、WAL 区等
合计7.875 MB分区扩容到 9.875 MB 后,记忆向量库可提到 8.5 MB ≈ 11,000 条

量产平衡方案(时序权重更高时):记忆 5.0 MB(≈6,300 条)/ L1 1.2 MB(≈54 天)/ L2 1.2 MB(≈2,100 条)/ 取证 0.4 MB。各区大小应为 Kconfig 可配,不由代码写死。

5.7 计算分层(明确每一层算力从哪来)

计算任务在哪里做频率说明
Embedding(文档原文)PC / Hub灌库时离线预计算核心;可换任意小模型而无需改板侧
ANN 索引构建PC / Hub灌库时聚簇 + 构图 + 压缩 + 顺序布局,产出 .emf
查询侧 EmbeddingHost 提供每查询宿主/Hub 算好向量下发,板侧不做 embedding
相似度检索板上每查询核心能力,目标 < 30 ms
时序写入 / 窗口聚合板上持续多速率对齐由引擎处理
窗口特征化板上(Hub 兜底)持续统计量/频谱板上可算;需 ML 则由 Hub 算后回写
记忆策略(遗忘/冲突)板上持续策略必须贴着数据,不依赖网络
LLM 推理 / 生成不做—明确划出边界

六、软件开发任务总表(WBS)

共 7 个工作包(WP0–WP6)、51 项任务。优先级:P0 阻塞P1 主路径P2 增强。人日为单人估算(含自测),未含评审与返工缓冲(建议按 ×1.3 计)。

WP0 · 基建与基线(Board Bring-up)先做,建立信心

战略报告提示:USB 复合设备有两个官方示例可参考,风险最低,应最先做。本工作包先把它前面的路铺平。

编号任务交付物验收标准依赖人日
W0-01建立 EdgeHippo 构建变体:按形态区分(form=usb-dongle(B) / form=gamma-card(A)),变体 usb-dongle-16m(B) / gamma-card-8m(A)sdkconfig.usb_dongle_16m、sdkconfig.gamma_card_8m、BOARD_*.md 更新build_board.ps1 可分别产出两板固件;sys.info 的 form 字段正确(gamma-card / usb-dongle);两板均能启动—2
W0-02USB 通道切换:console 从 USB-Serial-JTAG 切到 UART0,启用 TinyUSBsdkconfig 变更集 + 板 B 外接 USB-UART 转换器接线说明板 B 通过 GPIO19/20 枚举为 USB 设备;UART0 日志正常;USJ 不再占用 PHY。注意 choice 组只能写 =yW0-013
W0-03TinyUSB 复合设备冒烟:CDC + MSC 同时枚举(官方示例移植)usb_dev.c 骨架Windows / macOS / Linux 均无需驱动;串口与虚拟盘同时可用;D+ = GPIO20、D− = GPIO19W0-023
W0-04固件裁剪:cam / mic / gps 由 Kconfig 控制,MVP 默认关闭Kconfig 开关 + 裁剪后 binbin ≤ 1.2 MB;启动后可用堆增加 ≥ 300 KB;store.map 显示 RAM 水位下降W0-012
W0-05 v1.1改 已执行 2026-10-28分区表改方案 B(见 3.5 节):两板 app 槽均压到 2 MB ×2,edgehippom 提到 11.875 MB / 3.875 MBpartitions_emgw.csv / _16m.csv v2OTA 双槽仍可用且实测升级成功;store.map 报出新 edgehippom 容量。必须在任何正式灌库前完成W0-042
W0-06性能基线测量:内部 DRAM / PSRAM 可用量、heap 水位、flash 顺序写与页读吞吐baseline.md(实测数字)给出四个实测值:PSRAM 可用、DRAM 峰值余量、flash 4 KB 页读延迟、1 MB 顺序写耗时。后续所有容量/延迟推算以本基线为准W0-042
W0-07备份与回滚预案:板 B 现网 4343 条知识库导出归档kb/export 备份文件 + 恢复脚本可在 10 分钟内把板 B 恢复到当前状态—1
W0-06 v1.2新增构建期槽位余量硬门槛:脚本解析 app 镜像大小,与分区表 app 槽比对build_board.ps1 增加检查步骤> 槽 × 0.8 告警、> 槽 × 0.9 构建失败。防止方案 C 式的爆槽在无人察觉时发生(见 3.5.7)W0-051
WP0 小计16

WP1 · 引擎层(EM Engine HAL)核心,最长

编号任务交付物验收标准依赖人日
W1-01定义 HAL 接口 em_engine.h(第 4.2 节全部 API)头文件 + 接口文档 + 空实现桩两后端共用同一头文件;编译期可切换后端;接口评审通过W0-012
W1-02存储层:edgehippom 分区页管理(4 KB 页)、CRC32、坏页标记、简易磨损均衡em_store 底层改造 + 单元测试1 万次随机读写后无坏页累积;掉电后已 commit 页数据完整W0-055
W1-03int8 距离核:384 维 int8 余弦/内积,Xtensa 优化em_ann.c 距离核 + 微基准单次距离计算 ≤ 1.2 μs(240 MHz);与朴素实现结果一致(误差 0)W1-013
W1-04flash-backed HNSW:M=16 / ef_construct=200,页式图存储 + PSRAM 缓存em_ann.c HNSW 实现10,000 条构建成功;单条内存占用 ≤ 512 B(向量+链接);工作集尽量常驻 PSRAMW1-02, W1-0310
W1-05IVF 粗划分:离线聚簇 + 查询时只触及 top-n 簇(MCU 级推荐做法)IVF 索引 + 簇元数据开启 IVF 后 P99 抖动下降(对比测试);命中率损失 ≤ 3%W1-046
W1-06列式时序 L0 环形缓冲:16 CH × 100 Hz,delta 压缩em_ts.c写入吞吐 ≥ 1600 点/s;环形覆盖正确;7.875 MB 下 ≥ 80 分钟W1-024
W1-07L1 分钟聚合 + L2 特征向量写入聚合器 + Pattern 表整分触发聚合,误差 ≤ 1e-5;L2 只保留判定为「有意义」的窗口W1-064
W1-08WAL 事务:begin/commit/abort,崩溃恢复em_wal.c随机掉电 100 次,库 100% 可打开;未 commit 事务完全回滚W1-026
W1-09混合查询:ANN + 时间范围 + dev_id/frag_id/tags/level 精确过滤,同事务em_query 实现过滤条件与 ANN 结果交集正确;src_win_id 可回溯;先过滤后精排路径可用W1-05, W1-076
W1-10碎片管理:em_frag_install/list/remove,manifest 解析与签名校验em_frag.c损坏包 / 越界包 / 依赖外部的包 全部被拒绝且不损坏原库W1-095
W1-11运维接口:em_stat(条数/字节/RAM 峰值/缓存命中率)+ em_gc统计与淘汰store.map 能输出全部指标;GC 按 salience + LRU 淘汰到水位线以下W1-093
W1-12 P2emdb 后端:接入 eXtremeDB,替换 emliteem_engine_db.c通过 W1-13 一致性测试;容量与延迟优于 emlite(否则不切换)授权到位12
W1-13 P2双后端一致性测试:同一数据集在两后端上的查询结果逐条比对一致性测试套件top-k 结果集合完全一致(排序容差 ±1 位);事务语义一致W1-124
W1-14 v1.2新增向量降维 / 量化实验:384d int8 基线 vs 256d vs PQ/SQ 量化,测召回率与容量离线实验脚本 + 板侧实测给出「每条字节数 × 召回率 × P99 延迟」三维对照表;若 256d 或量化后召回率下降 ≤5% 而容量提升 ≥40%,则采纳(这是比压 app 槽高一个量级的容量杠杆,见 3.5.7)W1-045
WP1 小计(emlite 路径 W1-01…W1-11 + W1-14)59
WP1 小计(含 emdb 后端 W1-12/W1-13/W1-14)75
W1 的三条工程铁律(来自官方白皮书,必须遵守):
① 内存型 HNSW 在 MCU 上不实用,必须走 flash-backed,由 DBMS 管理页与缓存;
② Vamana 比 HNSW 更脆——工作集超出 cache 就断崖式下降,HNSW 是渐进退化。约束设备上优先 HNSW;
③ 成本主导项是 I/O 而不是返回数据量,优化方向是顺序布局与减少随机读,不是缩小结果集。
如果 P0 实测 P99 > 50 ms,先调这三项(IVF 削减 + 离线按簇顺序落盘 + 热碎片常驻),不要换 MCU。

WP2 · 策略层(EdgeMemory)差异化所在

ObjectBox 核心数据库免费,纯「嵌入式向量库」会撞上免费壁垒。差异必须建立在策略层——遗忘、冲突消解、闭环回写,这些是需要真实长期运行才能调对的东西。

编号任务交付物验收标准依赖人日
W2-01记忆生命周期状态机:工作 → 短期 → 长期,迁移条件与阈值状态机 + 迁移规则表三态可观测(mem.stats 分态计数);迁移阈值可按碎片配置W1-094
W2-02遗忘与淘汰:salience 时间衰减 + 访问频率加权 + 容量水位触发 GC遗忘策略库达 95% 水位时自动淘汰到 85%;高 salience 与近期命中条目不被淘汰(回归测试)W1-11, W2-015
W2-03近重复去重与冲突消解:余弦相似度阈值判定 + 版本保留策略去重器灌入 500 条含 100 条近重复的数据,重复率下降 > 90%;冲突条目保留新版本且可回溯旧版本W1-095
W2-04闭环回写:检索结果(含成功/失败标签)写回为新记忆,并影响后续检索权重回写逻辑回写的新记忆在下一次检索中可被命中(这判定了闭环是否真成立)W2-015
W2-05记忆健康检查:碎片完整度、孤立向量、过期条目、索引一致性mem.check 命令 + Hub 上报字段人为损坏一个碎片后能被检出并报出 frag_idW1-113
WP2 小计22

六、软件开发任务总表(WBS)· 续

WP3 · 接口层产品感知面

编号任务交付物验收标准依赖人日
W3-01CDC 行协议扩展:mem.put/get/query/del、frag.install/list/remove/verify、ts.append/agg/query、ann.benchcli_json.c 扩展沿用单行 JSON {"id":n,"cmd":"name","args":{}};全部命令有 help;中文 msg 缓冲 ≥ 768 BW1-095
W3-02MSC 虚拟 U 盘 + 拖拽灌库:写入 .emf → 自动校验 → 合并索引usb_msc_disk.c拖入后 ≤ 60 s 完成 10,000 条合并并可查;错误包拒绝且不坏原库;全平台零驱动W0-03, W1-108
W3-03U 盘状态回写:把灌库结果/错误写成 STATUS.TXT 放在虚拟盘上状态文件生成用户拖入后不接串口也能知道成功与否W3-022
W3-04BLE 碎片接力:基于现有 link_mgr 做 .emf 点对点传输接力协议扩展两板间传输 1 MB 碎片包成功;断点续传;接收方离线验签通过W1-106
W3-05MCP shim:把记忆资源暴露为 MCP 接口(不做私有 API)em_mcp.c + 协议文档标准 MCP 客户端可直接查询;三个场景统一走此接口W3-016
W3-06断网自检模式:sys.offline 一键关闭 Wi-Fi/BLE,仅留 USB 供电自检命令 + LED 指示执行后 G1–G5 全部可复测;LED 进入「离线就绪」态W3-012
W3-07Nagle + 延迟 ACK 处理:响应合并成一次 send,httpd open_fn 设 TCP_NODELAY传输层修正连续查询帧率不塌陷(本项目已有此坑:不处理会从 10 fps 掉到 0.33 fps)W3-011
W3-08 P2Host SDK:Python / Node.js 封装(CDC + MCP 双通道)SDK 包 + 示例10 行代码完成「灌库 → 查询」W3-055
WP3 小计(MVP 范围 W3-01…W3-07)30

WP4 · 时序闭环(场景侧)技术内核

编号任务交付物验收标准依赖人日
W4-01 v1.1改多速率合成数据源:板内确定性生成 3 轴振动(4 kHz) + 温度(1 Hz) + 电流(10 Hz),不接任何硬件em_sim_src.c + ts.inject 命令三速率按共同时间窗对齐;同一 seed 逐字节可复现;吞吐打满 W1-06 写入上限W1-063
W4-02窗口特征化:每 10 s 窗口计算统计量(min/max/mean/rms/峰度)+ FFT 频段能量特征化器单窗口特征化 ≤ 15 ms(否则撑不住 10 s 周期下的多设备);FFT 结果可复现W4-016
W4-03特征向量组装与归一化:多传感器特征合并为单个 384 维向量向量组装器输出向量与 PC 侧同算法结果一致(误差 ≤ 1e-4)——保证离线/在线两侧可比W4-023
W4-04L2 入库与「有意义」判定:异常度 / 新颖度阈值保留策略稳态数据下保留率 ≤ 5%(否则 7.875 MB 撑不住长期生长)W4-034
W4-05混合查询场景化封装:「这台设备、这个工况、这个时间范围内,历史上最相似的 5 个状态」查询模板 + 示例返回结果含 src_win_id,可回溯原始波形区间W1-093
W4-06结果回写闭环(与 W2-04 打通):命中 → 人工/自动确认 → 新指纹入库闭环演示脚本新写入的指纹在下一次查询中可被命中W2-04, W4-053
W4-07 P2真实传感器采集(v1.1 新增,P1 执行):板 A 挂加速度计 + 温度 + 电流,与合成源跑同一数据集做对照采集任务 + 驱动真实数据下的召回率与误报率,相对合成数据偏差 ≤ 10%;采集吞吐满足写入上限W4-015
WP4 小计(MVP 范围 W4-01…W4-06)22

WP5 · PC / Hub 工具链决定 UX 成败

编号任务交付物验收标准依赖人日
W5-01384 维中文 embedding 选型与验证:候选模型在真实私域语料上的召回对照选型报告 + 固化模型版本对比 768 维基线的召回损失 ≤ 3%;给出「384 够不够用」的明确结论(报告待验证项 3)—5
W5-02.emf 打包器:文件/PDF/Markdown → 分块 → embedding → IVF 聚簇 → HNSW 构图 → 按簇顺序布局 → 签名emf_pack.py(含 --dump)产出的包能被板侧安装;顺序布局可验证(簇内 ID 连续);同一输入的产物可复现(确定性)W5-018
W5-03.emf 校验器:manifest/vectors/graph/payload 一致性、CRC、签名离线验签emf_verify.py能检出「改一个字节」「少一条」「维度不符」「越界 payload」四类注入错误W5-024
W5-04灌库 CLI:CDC 灌库 + MSC 拖拽(两条路径)+ 进度与错误报告emf_upload.py(默认预检、--backup)两条路径等效;失败时能定位到具体条目W3-024
W5-05基准测试工具:批量查询出 P50/P99/吞吐/RAM 峰值/cache 命中率emf_bench.py + 报告模板一次运行产出 Go/No-Go ① 所需的全部数字(G1/G2/G3)W3-014
W5-06三场景语料构建:S1/S2/S3 各一套真实或仿真语料 + 查询集corpus/ 三套 + 查询集(含 ground truth)每套可打包为 .emf;查询集带人工标注的相关条目,用于算召回W5-028
W5-07 P2Hub 控制台:碎片版本管理、批量分发、设备记忆健康检查看板Web 控制台扩展可给 200 台设备下发新版碎片包并看到状态W5-0410
WP5 小计(MVP 范围 W5-01…W5-06)33

WP6 · 测试与验收Go/No-Go 唯一依据

编号任务交付物验收标准依赖人日
W6-01单元测试:距离核 / 页管理 / WAL / 去重 / 遗忘,覆盖边界与异常测试套件(host 侧可跑)覆盖率 ≥ 70%(引擎层 ≥ 85%);CI 可跑W1-*, W2-*5
W6-02三场景集成测试(第 10 章 TC-S1/S2/S3 全部用例)测试报告全部用例通过,或记录为「已知缺陷 + 影响评估」WP1–WP58
W6-03非功能测试:N 组(延迟/容量/掉电/断网/耐久/灌库成功率)实测数据表G1–G7 七项判据全部有实测数字,替换本报告所有「推算」标注W5-056
W6-04Alpha 演示包:三个场景各一段 3 分钟可复现演示脚本演示脚本 + 录屏不联网、不需要解释即可看懂;客户可自助复现W6-023
W6-05Go/No-Go ① 评审包:实测数据 + 缺陷清单 + 决策建议评审文档可支撑产品负责人一次性拍板W6-032
WP6 小计24

6.2 合成数据源规格(v1.1 新增:MVP 不接传感器)

决策:MVP 全程只用基础主板,一根传感器线都不接。时序数据由板内确定性合成数据源生成,或由 PC 侧生成后经 CDC/BLE 注入。

✅ 四条收益

  • 可复现:同一 seed 产出逐字节一致的数据流,回归测试才有意义
  • 可构造边界:「8 类故障各 20 个样本」直接生成即可;真实世界要等故障发生
  • 零硬件工作量:不用选型、布线、调驱动、排查 I2C 时钟拉伸
  • 不占 RAM、不干扰延迟:采集驱动与 DMA 缓冲会挤占 ANN 工作集,而这正是 G2/G3 要测的

⚠️ 两条代价(记为已知局限)

  • 无法验证真实采集吞吐:4 kHz × 3 轴的实际采样能力、ADC 噪声等真实问题推迟
  • 合成与真实数据的分布差异会影响召回率结论的可信度
缓解:W4-07 在 P1 用真实传感器跑同一数据集对照,要求偏差 ≤ 10%。在 W4-07 完成前,对外不得宣称 S1 的召回率已获真实数据验证。
通道速率类型生成模型(确定性,seed 可控)
振动 X / Y / Z4 kHzint16CWRU 风格参数化模型:基频正弦(转频 f₀)+ 2/3 次谐波 + 周期性冲击串(故障特征频率 BPFO / BPFI / BSF)+ 高斯白噪声(SNR 可配)。8 类故障 = 8 组参数
温度1 Hzfloat缓变基线 + 日周期 + 阶跃(异常升温)+ 噪声
电流10 Hzfloat负载周期 + 启动冲击 + 谐波 + 噪声
工况切换事件—按脚本在 8 种稳态工况间切换,模拟真实产线节奏
/* 命令接口 */
{"cmd":"ts.inject","args":{"ch_mask":7,"rate_hz":4000,"seed":12345,
                           "fault":"bpfo","severity":0.6,"dur_s":30}}
/* 同一 seed + 同一参数 ⇒ 任何一块板上产出完全一致的字节流 */

{"cmd":"ts.script","args":{"file":"s1_scenario.json"}}   /* 按脚本跑完整场景 */
关键设计要求:合成源必须放在板内,不能只放在 PC 侧。这样「时序写入吞吐」「窗口特征化耗时」「L0 环形覆盖」这些指标仍然是真实的——数据确实进了 L0 环、确实做了 FFT、确实占了 flash;只有「数据从哪来」是假的。这保住了 WP4 绝大部分的验证价值。

6.3 工时汇总

工作包任务数MVP 人日含 P2 人日说明
WP0 基建与基线71515先做,风险最低,建立信心
WP1 引擎层135470最长。emdb 后端为 P2 增量
WP2 策略层52222差异化所在,需长期运行调参
WP3 接口层83035拖拽灌库是 UX 成败点
WP4 时序闭环72227技术内核。v1.1 改为合成数据源(−2),真实采集移入 P2(+5)
WP5 PC/Hub 工具链73343决定 UX,也决定能否对外演示
WP6 测试与验收52424Go/No-Go 唯一依据
合计54206242按 ×1.3 缓冲:MVP ≈ 268 人日(v1.2 新增 W0-06 / W1-14 共 6 人日)

单人全职约 12–13 个月;2 人并行(固件 1 + 工具链 1)约 6.5 个月,与战略报告 P0(M1–M4)+ P1(M5–M9)的节奏基本吻合。若只做 Go/No-Go ① 所需的最小集(WP0 + W1-01…W1-11 + W3-01/02 + W5-01/02/05 + W6-03),约 130 人日,2 人约 3 个月可拿到第一个实测结论。
v1.1 变化:去掉传感器让 MVP 减少 2 人日,但真实采集验证(W4-07)移入 P2,含 P2 总量 +3 人日。

七、场景 S1|工业设备振动故障指纹库(时序主导 · α 形态)

要素内容
痛点20 台注塑机的智能化改造预算不到 8 万元;非计划停机代价高。边缘侧本地跑异常检测,行业口径非计划停机平均降 30–40%
我们的角色α 模组(记忆器官)嵌入设备主控;Hub 侧批量构建与分发故障指纹包
为什么首选McObject 官方技术文章明确点名工业设备场景;付费方明确(设备制造商 / 工厂);工程验证已存在
板位板 A(N8R8)= 设备主控原型(采集 + 发起查询);板 B(N16R8)= 记忆外设(存指纹库 + 检索)。互联走现有 BLE link_mgr
能力侧重时序主导:时序写入 → 窗口特征 → ANN 检索 → 混合条件过滤 → 回写新指纹

7.1 数据规格

通道速率类型来源与说明
振动 X / Y / Z4 kHzint16板内合成(v1.1):CWRU 风格参数化模型,seed 可控、逐字节可复现。见 6.2 节。MVP 不接加速度计
温度1 Hzfloat板内合成:基线 + 日周期 + 阶跃 + 噪声(模拟油温 / 料筒温度)
电流10 Hzfloat板内合成:负载周期 + 启动冲击 + 谐波(模拟主轴电机电流)
设备数3 台同型号注塑机(dev_id = 1 / 2 / 3),用于验证精确条件过滤
S1 的验证边界要如实写清:本场景在 MVP 阶段验证的是「时序 → 特征 → ANN → 混合查询 → 回写」这条链路本身,不是「真实振动信号能被识别」。在 W4-07(P1 真实传感器对照)完成前,85% 召回率这个数字只能表述为「合成数据集上的召回率」。

7.2 知识库碎片构成(灌入板 B)

frag_id碎片名条数内容来源字节
1fp-inj-v1
故障指纹库
1,2008 类故障 × 150 条窗口特征向量
(轴承内圈/外圈/滚动体、齿轮断齿、不平衡、不对中、松动、螺杆磨损)
CWRU 轴承公开数据集 + 参数化仿真合成0.90 MB
2base-op-v1
工况基线库
6003 型号 × 8 种正常工况的稳态特征现场采集或仿真0.45 MB
3maint-v1
维修记录
800历史工单摘要(现象 / 原因 / 处置 / 结果),每条 ≤150 B工厂 MES 导出后离线 embedding0.60 MB
4spec-v1
工艺参数
300SOP 关键参数与阈值工艺文档0.23 MB
灌库合计2,900装载后剩余约 5,300 条空间给 L2 生长与新指纹回写2.18 MB

7.3 典型查询与闭环

Q1  纯相似      vec=<当前10s窗口特征>, topk=5
                → 返回最相似的 5 个历史状态 + 每个的 src_win_id

Q2  混合查询    vec=<当前特征>, dev_id=2, t0=30天前, t1=now, topk=10
                → 「这台设备、最近一个月内,最相似的 10 个状态」★ 核心卖点

Q3  条件过滤    vec=<当前特征>, tags=温度过高, min_salience=0.6, topk=5
                → 相似度与精确条件在同一事务内完成

闭环  检出异常 → 人工确认为「螺杆磨损」→ 回写为新指纹(level=2, salience=0.9)
      → 30 天后同类特征再次出现时,Q1 应能直接命中该指纹

7.4 场景级判据

八、场景 S2|野外巡检记忆包与物理接力(断网 · β 形态)

要素内容
痛点隧道、船舶、野外无网;巡检经验随人员流失;换班时上下文断裂
我们的角色β 外设本体。巡检员下班把记忆外设带回办公室同步,符合现有工作流
为什么选β 形态的最佳落脚点;物理接力是最难被软件复制的差异化(Oki 的 Memchip 已用同一叙事卖到 $1,799)
板位双板都用上:板 A(N8R8)= 专家的随身记忆卡;板 B(N16R8)= 巡检员的外设。这是唯一需要「接力」的场景
能力侧重纯语义 + 物理接力 + 断网。时序只作辅助(环境读数、点位时间)

8.1 数据规格

通道类型说明
巡检记录文本UTF-8 短文本语音转写或手写录入,每条先截断/摘要到 ≤150 B 后 embedding
点位 ID / 设备编号uint16作为精确过滤条件(tags / dev_id)
时间戳uint32时间范围过滤;也是「上次这个点位什么时候出过问题」的依据
环境读数1 Hz float温湿度、瓦斯浓度等,写入 L1 聚合

8.2 知识库碎片构成

frag_id碎片名条数内容来源字节
1sop-tunnel-v1
规程包
1,200巡检 SOP、判定标准、处置流程工程方规程文件0.90 MB
2defect-v1
历史缺陷包
2,500近 3 年缺陷记录(现象/部位/处置/结果)历史工单导出1.88 MB
3expert-zhang-v1
专家经验包
1,800老张 20 年经验的口述整理(装在板 A 上随身带走)访谈整理1.35 MB
4site-v1
点位拓扑包
400点位关系、易发问题部位图纸 + 台账0.30 MB
板 B 装载(碎片 1/2/4)4,100剩余约 4,100 条给现场新增记录与接力包3.08 MB
板 A 装载(碎片 3,专家随身)1,800N8R8 升级后 3,419 条档位(推算、未实测),装 1,800 条仅占一半,仍有余量接纳现场新增记录1.35 MB

8.3 三种接力的完整演示路径

① 物理接力   专家带着板 A(装着 expert-zhang-v1)到现场
              → 拔下 → 插到巡检员的设备上 → 巡检员的宿主立刻获得老张的经验
              → 最低信任成本,最难被软件复制

② 近场接力   板 A 与板 B 通过 BLE 点对点传输 expert-zhang-v1(1.35 MB)
              → 传输的是几百 KB 的自洽产物,不是 GB 级模型权重
              → 接收方【离线验签】通过后合并入库

③ Hub 中继   回办公室后板 B 插 USB → 同步到 Hub
              → Hub 汇总全天新增记录 → 构建新版 defect-v2 → 次日批量下发全班组

8.4 典型查询

Q1  vec=<"拱顶渗水伴有白色析出物">, topk=5
    → 命中历史缺陷记录 + 老张经验中的相关条目

Q2  vec=<"渗水">, site_id=K12+300, t0=2024-01-01, t1=now, topk=10
    → 「这个点位历史上出过几次同类问题,怎么处置的」

Q3  纯条件(无向量)  site_id=K12+300, tags=结构类, topk=20
    → 验证精确条件路径不依赖 embedding 也能工作

8.5 场景级判据

九、场景 S3|专业私域知识库(纯语义 · 首销 SKU 定价锚)

要素内容
痛点跨设备失忆;私域资料不敢上云(PIPL/DSL);Agent 每次都要重新喂上下文
我们的角色β USB Dongle 成品形态。这是首个 SKU(¥399)的定价锚验证载体
为什么选与 Plaud / 笔记熊 / Oki 直接竞争,保留一个 SKU 作定价锚但不作收入主项;同时它是唯一能压满 N16R8 容量(12,000 条)的场景,正好验证 G1
板位板 B(N16R8)直插 PC;板 A 不参与(或作为第二块随身副本演示)
能力侧重纯语义 RAG:无时序、无传感器,纯文本碎片 + MCP 接口

9.1 知识库碎片构成(压满容量,用于验证 G1)

v1.1 更新:按 3.5 节方案 B,N16R8 记忆库 ≈ 14,448 条(推算、未实测),故 S3 的满载规模从 8,000 条上调到 12,000 条(占记忆库约 83%,推算)。这是唯一能把容量压到判据线附近的场景。

frag_id碎片名条数内容来源字节
1docs-core-v1
技术文档包
9,000产品技术文档、API 手册、规格书(按语义切块,非按页)PDF / Markdown 离线 embedding6.77 MB
2meeting-2026Q3
会议纪要
2,200决策记录与结论(含被后续决策推翻的旧结论,用于测冲突消解)会议记录1.65 MB
3pref-v1
个人偏好
800写作风格、常用术语、忌讳表达人工整理0.60 MB
合计(满载)12,000≈ 9.02 MB —— 落在 G1 的 12,000 条目标上9.02 MB

9.2 灌库与查询路径(全部离线)

灌库   ① PC 侧:docs/ → 切块 → embedding(384d) → IVF聚簇 → HNSW构图 → 顺序布局 → .emf
       ② 拖 .emf 进虚拟 U 盘 → 板侧校验 → 合并 → STATUS.TXT 回写结果
       ③ 全程无外网,可在飞行模式的笔记本上完成

查询   MCP 客户端(或 Host SDK)
       → 宿主侧算查询向量
       → CDC/MCP 下发 {"cmd":"mem.query","args":{"vec":[...],"topk":5}}
       → 板侧返回命中的 payload 摘要 + 相似度 + frag_id
       → 宿主用摘要组装 prompt(原文留在 PC 侧,板侧只存 150 B 摘要)

9.3 典型查询与特殊用例

Q1  常规      vec=<"eXtremeDB 的 ANN 索引支持哪些距离度量">, topk=5
Q2  碎片限定  vec=<"上周关于定价的结论">, frag_id=2, topk=5
Q3  ★冲突消解  vec=<"我们的目标客户是谁">, topk=5
              预期:返回最新结论,且【能指出存在被推翻的旧结论】
              —— 这是策略层相比纯向量库最直观的差异
Q4  去重      灌入 500 条含 100 条近重复的笔记 → 库内重复率应显著下降
Q5  卸载      frag.remove(1) 后,剩余 2,000 条仍可正常检索(碎片自洽性验证)

9.4 场景级判据

9.5 三场景能力覆盖对照(证明「器官」可跨行业复用)

维度S1 工业故障指纹S2 野外巡检S3 私域知识库
主导能力时序 → 特征 → ANN语义 + 接力纯语义 RAG
时序使用核心(L0/L1/L2 全用)辅助(仅 L1 环境)不用
接力模式Hub 中继物理 + 近场 + Hub 三种全用物理(换台电脑)
碎片数量44(跨两板)3
装载量2,900 条(留生长空间)4,100 + 1,800 条12,000 条(满载)
形态α 模组β 外设β 外设(首销 SKU)
验证的判据G4 闭环G6 断网 + 接力G1 容量 + G2 延迟
三个场景共用同一套固件、同一份 schema、同一个 .emf 格式,差异只在灌进去的碎片与宿主是谁。这就是「不做品类,做器官」在工程侧的证明方式。

十、测试用例集

共 52 条用例:核心 TC-C-* 8 条、碎片/灌库 TC-F-* 8 条、场景各 8 条(S1/S2/S3)、非功能 TC-N-* 12 条(v1.1 新增 TC-N-11 footprint 基线、TC-N-12 abort 可预测性)。用例列:前置 → 步骤 → 预期。

10.1 核心引擎(TC-C)

编号用例前置步骤预期
TC-C-01距离核正确性已知 100 组向量与参考结果(PC 侧算好)板侧计算并回传与参考结果误差 = 0(int8 定点,不允许有偏差)
TC-C-02HNSW 召回率1,000 条库;100 条查询向量 + 暴力搜索 ground truthef_search 取 16/32/64 三档ef=32 时 top-10 召回 ≥ 95%;ef=16 ≥ 88%
TC-C-03混合查询正确性库内设 3 个 dev_id、2 个 frag_id、时间跨度 30 天下发 vec + dev_id + 时间范围结果全部满足全部精确条件;与「先 ANN 后过滤」的参考实现一致
TC-C-04事务原子性空库begin → 写 100 条 → 人为断电 → 重启库可打开,条目数 = 0(未 commit 完全回滚)
TC-C-05事务持久性空库begin → 写 100 条 → commit → 立即断电 → 重启条目数 = 100,内容完整(CRC 校验通过)
TC-C-06时序环形覆盖L0 PSRAM 环配置为 10 s持续写入 60 s环内始终为最近 10 s;无越界、无内存泄漏(heap 水位稳定)
TC-C-07L2 去重收敛空库注入 500 个高度相似(余弦 > 0.95)的窗口特征库内条目数 ≤ 50(收敛),且检索仍能命中代表条目
TC-C-08回溯取证已有带 src_win_id 的 L2 条目ANN 命中后按 src_win_id 取时序返回对应时间窗的 L1 聚合数据,时间戳与窗口起点一致

10.2 碎片与灌库(TC-F)

编号用例前置步骤预期
TC-F-01MSC 拖拽灌库(正常)12,000 条 .emf拖入虚拟 U 盘,等待 STATUS.TXT 出现≤ 60 s 完成;STATUS.TXT 报成功与条数;mem.stats 条数一致
TC-F-02CDC 灌库等效性同上 .emf改用 CDC 路径灌入另一块板两板条数、抽样检索结果完全一致
TC-F-03篡改包拒绝把 vectors.bin 改 1 字节拖入拒绝安装;STATUS.TXT 报 CRC 失败;原库条数不变
TC-F-04无网验签合法包 + 篡改包各一关闭 Wi-Fi/BLE,仅 USB 供电,重复 TC-F-01/03结果完全一致 —— 验签不依赖网络
TC-F-05维度不符拒绝manifest 声明 384,实际 768 维拖入拒绝;不写入任何数据;不损坏原库
TC-F-06超长 payload 拒绝payload 中含 200 B 条目拖入拒绝(150 B 硬上限);报告越界条目序号
TC-F-07依赖外部的包拒绝manifest 中声明 depends_on拖入拒绝 —— 自洽性是强制校验项
TC-F-08碎片卸载自洽3 个碎片共 12,000 条frag.remove(1) → 检索剩余 2 个碎片检索完全正常;空间被回收;无孤立向量残留

10.3 场景 S1(TC-S1)

编号用例前置步骤预期
TC-S1-01灌库与装载4 个碎片共 2,900 条逐包灌入板 B条数 2,900;em_stat 字节数与预算表一致(±5%)
TC-S1-02故障识别 top-18 类故障各 20 个测试样本(带标签)逐条查询,取 top-1top-1 命中率 ≥ 85%
TC-S1-03故障识别 top-5同上取 top-5≥ 95%
TC-S1-04稳态误报率10 分钟正常工况连续数据逐窗口查询,统计相似度低于阈值的比例≤ 5%
TC-S1-05混合查询(设备+时间)3 台设备 30 天数据dev_id=2, t0/t1=最近30天结果全部属于 dev 2 且在时间窗内;与参考实现一致
TC-S1-06闭环回写一个被人工确认为「螺杆磨损」的异常窗口回写为新指纹(level=2, salience=0.9)→ 重新灌入同类样本新指纹被命中,且排在 top-3 内
TC-S1-07可回溯取证任一 ANN 命中按 src_win_id 取原始窗口并导出 CSVCSV 可被 PC 侧绘图;时间戳连续、点数正确
TC-S1-08长时间跑机板 A 连续采集,板 B 持续入库连续运行 72 小时无重启、无内存泄漏(heap 水位波动 < 5%)、L2 条目数收敛不发散

10.4 场景 S2(TC-S2)

编号用例前置步骤预期
TC-S2-01双板装载板 B 4,100 条;板 A 1,800 条分别灌库条数正确;板 A 占用 ≤ N8R8 档位(2,500 条)
TC-S2-02语义检索质量50 条带 ground truth 的查询集top-5 检索召回 ≥ 90%(人工标注相关条目)
TC-S2-03物理接力板 A 装着专家包拔下板 A → 插入另一台宿主 → 查询新宿主立刻能检索到专家包内容;结果与原宿主一致
TC-S2-04近场接力(BLE)两板 BLE 已配对板 A → 板 B 传输 1.35 MB 专家包传输成功;接收方条数 +1,800;抽样检索结果与发送方一致
TC-S2-05接力中断续传同上传输到 50% 时人为中断 → 重试续传成功;不产生半包或重复条目
TC-S2-06全程断网两板 Wi-Fi/BLE 关闭(仅 USB 供电)执行 Q1–Q3 全部查询全部可答;延迟与联网时差异 ≤ 5%
TC-S2-07点位+时间混合查询含 site_id 与时间戳的记录site_id=K12+300, t0/t1 + 向量结果全部属于该点位且在时间窗内
TC-S2-08Hub 中继与版本升级Hub 上有 defect-v2板 B 回办公室 → USB 同步 → 下发 v2本地新增记录上传完整;v2 安装后旧版可回滚

10.5 场景 S3(TC-S3)

编号用例前置步骤预期
TC-S3-01满载灌库12,000 条三个碎片拖入并等待完成条数 12,000;占用 ≈ 9.0 MB;em_stat 与预算表一致
TC-S3-02满载延迟同上满载库1,000 次随机查询P50 < 10 ms,P99 < 30 ms(对应 G2)
TC-S3-03语义检索质量100 条带 ground truth 的查询集top-5 检索召回 ≥ 90%
TC-S3-04冲突消解库内含被推翻的旧结论与新结论查询「我们的目标客户是谁」返回最新结论,并标记存在被推翻的旧结论;不得返回两条矛盾结论却不加区分
TC-S3-05近重复去重500 条含 100 条近重复的笔记灌入后统计库内近重复下降 > 90%;代表性条目保留
TC-S3-06碎片限定查询三个碎片frag_id=2 + 向量查询结果全部来自碎片 2;不跨碎片污染
TC-S3-07MCP 端到端标准 MCP 客户端不经自定义协议,纯 MCP 完成一次查询成功返回;证明不依赖私有 API
TC-S3-08飞行模式全流程笔记本飞行模式灌库 → 查询 → 卸载,全流程全部成功;无一次对外网络请求(抓包确认)

10.6 非功能测试(TC-N,直接对应 Go/No-Go ①)

编号对应用例步骤阈值
TC-N-01G1容量实测从 1,000 条起逐步灌入至失败,记录临界条数临界 ≥ 12,000 条(可行性门槛 8,000 条);记录实际值与失败模式(空间不足 / OOM / 超时)
TC-N-02G2延迟分布12,000 条库,1,000 次查询,记录每次板侧耗时P50 < 10 ms,P99 < 30 ms,P99/P50 < 4
TC-N-03G3内存峰值检索过程中采样 PSRAM 与内部 DRAM 峰值PSRAM ≤ 5 MB;内部 DRAM 峰值 ≤ 180 KB
TC-N-04G4闭环成立性回写新记忆 → 下一轮检索是否命中命中,且排在 top-3 内
TC-N-05G5灌库耗时与成功率12,000 条包连续灌 20 次(含 5 次错误包)正常包 100% 成功且 ≤ 60 s;错误包 100% 被拒且不坏原库
TC-N-06G6断网复测sys.offline 后复测 N-01…N-05全部通过,数值偏差 ≤ 5%
TC-N-07G7随机掉电 100 次脚本随机时刻断电,重启后检查库100% 可打开;条目数无异常增长/丢失;最多丢失最后一次未 commit 事务
TC-N-08耐久Flash 磨损10 万次条目的写-删循环无坏页导致的数据丢失;磨损均衡生效(擦写次数分布均匀)
TC-N-09吞吐连续查询吞吐CDC 连续 10,000 次查询≥ 30 QPS(含 USB 往返);不出现 Nagle 塌陷(若 < 5 QPS 即命中该坑)
TC-N-10长稳7×24 小时跑机板 A 持续合成注入 + 板 B 持续入库与查询无自发重启;无内存泄漏;若重启先查栈溢出(抓 Rebooting 前 30 行)
TC-N-11footprint 基线
(v1.1 新增)
记录 emlite 的 .text 体积与运行时峰值 RAM编译后取 .text;运行时采样 PSRAM 与 DRAM 峰值.text ≤ 60 KB;运行期 malloc 次数 = 0(4.4.3 硬指标)。此数据是替换 emdb 后算收益的基线
TC-N-12abort 耗时可预测性
(v1.1 新增)
不同写集大小(10 / 100 / 1000 条)各 abort 200 次记录每次 abort 耗时P99 ≤ 2×P50;耗时与写集大小线性相关,无长尾(Andrei Gorine:回滚成本必须绑定到已知写集)
两个必测的历史坑(本项目已踩过,MVP 必须回归):
① Nagle + 延迟 ACK:板端响应必须合并成一次 send,httpd open_fn 要设 TCP_NODELAY,否则连续查询会从 10 fps 塌到 0.33 fps(TC-N-09 就是为它设的)。
② 周期性自发重启:源码里没有 esp_restart 却定期重启,先查栈溢出。已知:NimBLE host 栈需 ≥ 8192;hub_task 栈 6144 内不得放大缓冲;大数组改用堆分配(TC-N-10)。

十一、里程碑、Go/No-Go 与执行顺序

阶段周期任务出口交付物判据
M1 铺路第 1–3 周WP0 全部 + W1-01(HAL 接口定义)两板构建变体、USB 复合设备冒烟通过、性能基线 baseline.md板 B 在三大平台零驱动枚举成功
M2 引擎第 4–9 周W1-02…W1-09(存储/距离核/HNSW/IVF/时序/WAL/混合查询)emlite 后端可跑;单板 12,000 条可查TC-C-01…08 通过
M3 工具链第 7–11 周
(与 M2 并行)
W5-01/02/03/05(embedding 选型、打包器、校验器、基准工具)可产出 .emf;可跑基准TC-F-03…07 通过(错误包全拒)
M4 接口第 10–13 周W3-01/02/03/06/07(CDC 协议、MSC 拖拽灌库、断网自检)拖 .emf 进 U 盘即灌库TC-F-01/02/04 通过
M5 策略第 12–15 周WP2 全部(生命周期/遗忘/去重/闭环回写/健康检查)策略层可用;mem.check 输出健康度TC-C-07、TC-S3-04/05 通过
M6 闭环第 14–17 周WP4 全部(采集/特征化/L2 入库/回写)S1 端到端闭环演示TC-S1-01…08 通过
M7 三场景第 16–19 周W5-06(语料)+ W6-02(集成测试)+ W3-05(MCP)三场景集成测试报告 + Alpha 演示包TC-S1/S2/S3 全部通过
M8 非功能第 18–21 周W6-03 非功能测试 + W1-11 调优实测数据表(替换所有推算值)TC-N-01…10 通过
M9 决策第 22 周W6-05 评审包Go/No-Go ① 评审G1–G7 全部达成

11.1 Go/No-Go ① 的处置规则

情况处置
G1–G7 全部达成进入 P1(形态与 SDK):β Dongle 工程样机 50 台 + Host SDK + 拜访 ≥10 家客户、落地 ≥3 家 PoC
仅容量或延迟未过(G1/G2),且用的是 emlite先不判死。启用 emdb(eXtremeDB)后端重测后再判。这是双后端 HAL 设计的价值所在
G1/G2 未过,且原因是 I/O 主导调三项再测:① IVF 粗划分削减触及面;② 离线按簇顺序落盘;③ 热碎片常驻 PSRAM。不换 MCU
G5(拖拽灌库)未过单独评估:这是 UX 卖点不是技术内核。若降级为 CDC 灌库仍可用,可判「有条件通过」并记录为风险
G7(掉电一致性)未过一票否决,不得进入 P1。事务一致是这个产品的立身之本,也是否决所有竞品的唯一硬指标
双后端均未过回退纯软件授权路线,不做硬件(战略报告第 11 章既定处置)

11.2 与战略报告路线图的对齐

本任务书覆盖战略报告的 P0(M1–M4 技术闭环验证)并延伸到 P1 前半段。P0 出口即本任务书 M9。差异在于:战略报告 P0 只有 4 个月,本任务书按 2 人并行估到约 5 个月(22 周)——多出的部分主要是双后端 HAL 的额外工作量(W1-12/13 的 16 人日)与三场景语料构建(8 人日)。若授权提前到位且只验证一个场景,可压缩回 4 个月。

十二、风险登记与已知工程坑

12.1 风险登记册

#风险等级缓解触发后的处置
R1McObject 授权条款不利或谈崩高双后端 HAL(emlite 先行)——本任务书的核心对策用 emlite 继续;容量降一档,商业模型仍成立
R2实测容量/延迟达不到 G1/G2高W0-06 先测基线;IVF + 顺序布局 + 常驻三项优化先换后端再判;仍不过则回退软件授权
R3USB PHY 冲突导致开发效率下降中W0-02 一次性切干净;板 B 常备 USB-UART 转换器改用 OTA 更新(现有 ota_mgr)+ UART0 日志
R4384 维中文 embedding 质量不足中W5-01 做召回对照实验,早期就要结论改用 768 维 → 容量减半(12,000 → 6,000 条),需重估叙事
R5场景缺位(Limitless 的死法)高M9 强制绑定单一杀手场景,由产品负责人基于 PoC 数据拍板不做「什么都能记住」的通用 SKU
R6自研 HNSW 实现缺陷(召回/崩溃)中TC-C-02 用暴力搜索做 ground truth 对比;W6-01 单测覆盖 ≥85%降低 ef/M 参数保稳定;优先保 P99 而非峰值召回
R7板 B 现网 4343 条数据丢失中W0-07 先备份再动;--backup 成默认动作10 分钟内可恢复
R8栈溢出 / 内存泄漏导致长稳失败中TC-N-10 七天长稳;启动即打 heap 水位基线按已知坑集合逐项排查(NimBLE 8192、大数组改堆)
R9改分区表后未及时重烧,导致后续灌库全废中把分区表改动排在 W0-05,必须在任何正式灌库之前完成;先 esptool flash-id 确认容量,改后用 sys.info 核对整片重烧 + 重灌知识库(板 B 现网 4343 条须先备份)
R11 v1.2新增固件膨胀撑爆 app 槽:MVP 陆续加入 TinyUSB、emlite、调试命令后,2 MB 槽余量从 38% 被吃掉中W0-06 构建期硬门槛(>0.8 告警 / >0.9 失败);每次合并前看 size 输出。v1.2 实测基线:现状 1.459 MiB,完整态预计 1.44–1.49 MiB先裁 cli_json 的冷门命令与 link_mgr 的 mesh 部分;仍不够则需改分区表(整片重烧 + 重灌)
R10合成数据结论被误当成真实数据对外表述中所有测试报告与对外材料强制标注「合成数据集」;W4-07 完成前不得宣称真实场景召回率W4-07 立即执行,做真实/合成偏差对照
R11emlite 实现膨胀(体积/RAM 超标),削弱替换收益中4.4.3 的三个硬指标(≤60 KB / 0 次 malloc / abort P99 ≤ 2×P50)设为门禁评审实现,必要时裁剪功能而非放宽指标

12.2 已知工程坑清单(本项目实战积累,MVP 必须遵守)

坑正确做法
USB-OTG 与 USB-Serial-JTAG 共用 PHY同一时间只能一个工作。β 形态要并存必须:① 用外部 PHY,或 ② 烧 eFuse 切 JTAG。PCB 阶段决定,事后不可改。MVP 先把 console 切 UART0
sdkconfig 的 choice 组给非目标成员写 =n 会导致整组失效并回退默认值。只给目标成员写 =y
Nagle + 延迟 ACK响应合并成一次 send;httpd open_fn 设 TCP_NODELAY。否则 10 fps → 0.33 fps
中文 JSON 缓冲含中文 msg 不能用 256 B(一字 3 字节会切出非法 UTF-8),用 768 B
payload 截断150 B 硬上限,绝不能在多字节字符中间截断
周期性自发重启源码无 esp_restart 却重启 → 先查栈溢出(抓 Rebooting 前 30 行)。NimBLE host 栈 ≥ 8192;hub_task 6144 内不得放大缓冲
esp_partition_next()末尾自 release,调用方不可再 release(double free → tlsf assert → 重启)
构建退出码被吞idf.py build 2>&1 | while read 会吞退出码导致旧 bin 被误判成功。验证是否上新板看 sys.info 的 build_time,不看 exit code
多任务共串口必须单锁整行原子写(cmd_console_write() + esp_log_set_vprintf()),各源各把锁无效
板级配置纪律boards/ 是唯一真源,禁止跨板拷贝 sdkconfig;升级先问清是哪块板;固件更新首选 OTA,串口只用于首刷与排障

12.3 下一步的四个动作(本周可做,零成本)

#动作产出与意义
1向 McObject 发书面询问:MCU 端分发授权条款 + eXtremeDB 9.0 的 ANN / Edge Client / Active Replication Fabric 是否在现有授权内 + 千片/万片阶梯价仍是唯一的全局阻塞项。但现在不是"阻塞全部"了——手上有了 emlite 计划,谈判地位不同
2跑 W0-06 性能基线:板 B 上实测 PSRAM 可用量、flash 4 KB 页读延迟、1 MB 顺序写耗时半天就能出结果。这一个数字能把本任务书所有"推算"标注换成实测起点
3跑 W0-03 USB 复合设备冒烟(官方示例直接移植)风险最低、信心价值最高。拖文件即灌库这个 UX 一旦跑通,整个产品的说服力立刻成立
4改分区表为方案 B(app 槽 4 MB → 2 MB,见 3.5 节)零成本换来 +61% / +118% 容量。两行 CSV 的事,风险极低。但必须赶在正式灌库之前做——分区表变了要整片重烧,之后再动就得重灌所有知识库