| 判据 | 内容 | 覆盖用例 | 级别 | 负责人 |
|---|---|---|---|---|
| G1 | Dev-B ≥12,000 条 / Dev-A ≥2,500 条 | TC-N-01 | 门槛 | QA + FW-A |
| G2 | P50<10ms / P99<30ms / P99÷P50<4 | TC-N-02 | 门槛 | QA |
| G3 | PSRAM≤5MB / DRAM≤180KB / malloc=0 | TC-N-03, TC-N-04 | 门槛 | FW-A |
| G4 | 时序→ANN→回写闭环 | TC-S1-07, TC-C-07 | 门槛 | FW-A |
| G5 | 四通道灌库耗时 | TC-N-05, TC-N-06 | 门槛 | QA + FW-B |
| G6 | 断网全功能可用 | TC-N-07 | 完整性 | QA |
| G7 | 随机掉电 100 次库 100% 可开 | TC-N-08 | 否决 | QA(台架) |
| G8 | emlite .text≤60KB / malloc 0 / abort P99≤2×P50 | TC-N-09, TC-N-10, TC-N-11 | 完整性 | FW-A |
| G9 | EdgeMesh 三节点接力 + 账本误差 0 | TC-M-03…TC-M-10 | 完整性 | FW-B |
| 台架 | 构成 | 用途 |
|---|---|---|
| TS-1 双板台架 | Dev-A + Dev-B + 交换机 + 双 USB 线 + 2 个 USB-UART 转换器 | 主力。所有板级用例 |
| TS-2 掉电台架 | 程控继电器(或 MOS 开关)+ 脚本,可随机切断供电并记录时刻 | TC-N-08,100 次。不要手工拔线 |
| TS-3 PC 仿真 | em_flash_io 文件仿真 + 引擎层单测(host 编译) | 引擎层全部单测;可精确控制断电字节位置 |
| TS-4 Web 台架 | Chrome + tools/serve.py 8080 + 板子同网段 | TC-W-*;CORS 与 mixed content 验证 |
| TS-5 长稳台架 | 7×24 h 连续运行,串口日志落盘 | TC-N-12 |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-C-01 | 空库启动 → sys.info → store.map | 启动 <800 ms;edgehippom 大小 = 11.875 MB(Dev-B)/ 3.875 MB(Dev-A);build_time 为本次构建 |
| TC-C-02 | mem.put 写入 1 条(含 150 B 摘要)→ mem.get | 返回 id > 0;取回内容一致;字节占用 ≈ 662 B |
| TC-C-03 | mem.put 写入 100 条 → mem.query {k:5} | 返回 5 条,按 score 降序;matched_by 字段正确标注 ANN / FILTER |
| TC-C-04 | 混合查询:向量 + filter="dev_id==3" | 返回结果全部满足过滤条件;ANN 不被过滤条件绕过 |
| TC-C-05 | 写入两条余弦 > 0.95 的条目 | 合并为一条(ADR-007);mem.stat 条数 +1 而非 +2;hit_count 累加 |
| TC-C-06 | 写入语义冲突条目 → mem.query | 保留 ts_ms 更新者;旧条目 flags 含 CONFLICTED 且 prio 下降 |
| TC-C-07 | 事务:em_tx_begin → put ×50 → em_tx_abort | 条数不变;库可正常打开;abort 耗时 P99 ≤ 2×P50(G8) |
| TC-C-08 | mem.del → mem.stat → edgehippom.compact | 删除后条数 −1;compact 后 bytes 下降;耗时 <30 s @ 满库 |
| TC-C-09 | 【ADR-014 拒答-低分】写入 100 条与此话题无关的条目 → 查询该话题,设 min_score_q8 高于全库最高分 | 返回 {hits:[], reject: EM_REJECT_LOW};不得返回任何「最接近但不相关」的条目;宿主可据此输出「不在我的知识范围内」 |
| TC-C-10 | 【ADR-014 拒答-红线】写入一条 meta.refusal=1 的条目 → 查询命中该条目 | 返回 {hits:[], reject: EM_REJECT_REDLINE};响应体中不得出现该条目的任何文本片段(连摘要也不能泄漏) |
| TC-C-11 | 【ADR-014 拒答-过期】写入 ttl_h=1 条目 → 系统时间推进 >1 h → 查询 | 返回 {hits:[], reject: EM_REJECT_EXPIRED},与 LOW / REDLINE / EMPTY 三者可区分 |
| TC-C-12 | 【ADR-014 出处可引用】任意命中查询 | 每条 hit 必带 frag_id / ts_ms / score / src 四字段;缺失任一即判 Fail |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-F-01 | 灌入 1,000 条 v2 碎片(带向量)→ frag.list | 条目数、名称、ver、count 与包内一致;payload_crc32 校验通过 |
| TC-F-02 | 灌入 v1 碎片(无向量)→ 查询 | 成功;dim=0;走文本检索路径(em_kb_search) |
| TC-F-03 | v1 固件读 v2 包(跳过多余字节) | 不崩、不越界;按 rec_len 正确跳到下一条(ADR-010) |
| TC-F-04 | 灌入错误包(magic 错 / CRC 不符 / 条数不符 / text_len>150) | 全部被拒绝;返回明确错误码;已有库完好 |
| TC-F-05 | 灌入同名低版本碎片(ver 更小) | 被拒绝并给出明确错误(OVERWRITE_SAME_NAME 未置位) |
| TC-F-06 | 灌入同名高版本碎片 | 覆盖成功;旧条目释放;条数正确 |
| TC-F-07 | 灌库中途断电(TS-2,第 40% 处) | 重启后库可打开;要么完整、要么完全未生效;无半成品 |
| TC-F-08 | frag.export → 再 frag.import 到另一块板 → 查询 | 往返一致;条数与内容一致;可命中 |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-S1-01 | 灌入 4 个故障指纹碎片(正常 / 内圈 / 外圈 / 滚动体) | 2,900 条全部入库;frag.list 显示 4 项 |
| TC-S1-02 | ts.script {model:"normal", seed:1, dur_s:60} | L0 环形缓冲写入正常;无丢样本 |
| TC-S1-03 | 注入内圈故障(BPFI)合成数据 → 窗口特征化 | 特征化耗时 < 单窗口时长;L1 分钟聚合可查 |
| TC-S1-04 | 特征向量 → mem.query | top-1 命中「内圈故障」;score > 阈值 |
| TC-S1-05 | 三种故障 × 20 次(不同 seed) | top-1 准确率 ≥ 85%;误报 ≤ 5%(合成数据源口径) |
| TC-S1-06 | 注入库中没有的新故障类型 | 返回「不知道」,不编造;走 P5 断网话术 |
| TC-S1-07 | 闭环:命中 → 确认 → 回写新指纹 → 再注入同类数据 | 下次可命中刚写入的指纹(G4) |
| TC-S1-08 | 三种速率数据(4 kHz / 10 Hz / 1 Hz)按时间窗对齐 | 共同时间窗内对齐;dev_id 精确过滤生效(3 台设备) |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-S2-01 | Dev-B 灌入 4,100 条基础包;Dev-A 灌入 1,800 条专家包 | Dev-A 占用约 50%(N8R8 3,700 条档位),仍有余量接纳现场新增 |
| TC-S2-02 | 断开全部网络 → Dev-A 本地检索 | 全部功能可用(G6);响应时间与联网时无显著差异 |
| TC-S2-03 | 现场新增记录(巡检发现)→ Dev-A 本地入库 | 写入成功;可在本地命中 |
| TC-S2-04 | M1 直连接力:Dev-A 向 Dev-B 请求基础包补充 | 六原语时序跑通;分块 CRC 全过 |
| TC-S2-05 | M2 Hub 中转:Dev-B 代持 Dev-A 的专家包 | Dev-A 离线时第三方仍可从 Dev-B 取到 |
| TC-S2-06 | M3 离线投递:USB MSC 拷入 .emf + .emr | ≤60 s 完成;可用;回执文件生成正确 |
| TC-S2-07 | 恢复联网 → 账本对账 | 双向误差 = 0(G9);M3 回执按 frag_id+seq 去重 |
| TC-S2-08 | 断网 72 h 连续巡检后回连 | 现场新增记录全部保留;无丢失;对账一致 |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-S3-01 | 灌入 3 个碎片共 12,000 条 | 成功且库可打开(G1 目标值);占用 ≈9.0 MB |
| TC-S3-02 | 用 P4 的 20 条验收用例自检(frag.verify) | ≥18/20 通过 |
| TC-S3-03 | 用别名提问(术语表未覆盖的同义表述) | 命中标准词条目;不因表述差异漏检 |
| TC-S3-04 | 提问红线内容 | 必须拒答;话术符合 P1(≤40 字,承认不知道) |
| TC-S3-05 | 提问库中故意没有的知识(2 条用例) | 返回「不知道」,不编造 |
| TC-S3-06 | 提问已过期知识(ttl_h 已过) | 提示已过期 + 「联网后可更新」;走 P5 第三类模板 |
| TC-S3-07 | 满库状态下再灌入 500 条 | 触发容量压力策略:按 prio+last_hit_ms 淘汰至 75%;PINNED 条目不被淘汰 |
| TC-S3-08 | 满库下 mem.query × 1,000 次 | P50 <10 ms,P99 <30 ms,P99/P50 <4(G2) |
| 级别 | 机制 | 进程真死 | 提供者 | 定位 |
|---|---|---|---|---|
| L1 | 进程内注入仿真:IO 置失效后重新 open 模拟上电 | 否 | 固件侧 tests/unit/ | 开发期回归与精确定位(能指出断在事务哪一步)。不出对外数字 |
| L2 | 真进程中止:子进程写到第 N 个字节后 abort(),父进程 reopen 验收 | 是 | QA tests/accept/ | PC 侧对外口径。字节粒度,可精确复现 |
| L3 | 硬件掉电:程控继电器 / 程控电源随机切断供电并记录时刻 | 是 | 板端台架 TS-2 | 板端对外口径。含真实 flash 时序与电源跌落行为 |
★ 判据缺陷登记(2026-10-28,TS-2 台架设计时发现):「随机掉电 100 次」的抽样方式本身会让 G7 被误杀。
G7 原文只写「随机掉电 100 次」,未规定断电时刻的抽样分布。但一次 em.put 的提交耗时
远小于两次 put 之间的间隔 ⇒ 纯随机时刻落在提交窗口内的概率很低 ⇒
越"真随机",saw_visible(防空通过计数)越容易掉到下限 10 以下,
于是 G7 会因为抽样方式、而不是固件缺陷被判失败。L3 的时刻抖动比 L2 大得多,这个偏差只会更明显。
裁定:L3 的 100 次必须分层抽样,不许纯随机。三组各约 1/3:
saw_visible 的主要来源★ 判据缺陷登记 · 增补(2026-10-28 晚,零采购裁定之后):上述「分层抽样」在人工拔插方案下有 2/3 层做不到,必须说明用什么替代。
用户裁定「先别买硬件,用别的办法顶」后,L3 的执行机构临时改为人工拔插 USB-C(真实拔掉 VBUS,属真实断电)。
结论是「部分接受」,论证全文见 07-实测手册/TS-2掉电台架设计_v0.3_20261028.md §7。分层抽样的三层在这一方案下的处境:
| 层 | 人工方案下能否做到 | 替代办法 |
|---|---|---|
| 钉在 put 之后(after_put) | 做不到。人的延迟 200–500 ms,而该窗口是毫秒级,差一个数量级以上,练不出来 | 并入「写入占空比」方案,事后归因 |
| 钉在 put 之间(in_put) | 做不到(同上) | 并入「写入占空比」方案,事后归因 |
| 纯随机 idle | 做得到。脚本保证窗口内无写操作 ⇒ 人延迟几百毫秒仍在窗口内 | 无需替代,可继续执行 |
替代办法(两条补丁,缺一不成立):
① 写入占空比:让 DUT 背靠背持续灌库,人何时拔都大概率落在写里 —— 这使 saw_visible 天然高位,
恰好规避了本红框担心的「因抽样方式被误杀」,且断点更多落在写里 ⇒ 通过更难 ⇒ 判据偏严,不是偏松。
② 事后归因:host 侧记录每条 put 的发送/ack 时间戳,在检测到端口消失的瞬间打快照,
把每轮事后归类为 in_put/after_put/idle。配额不可保证,但「实际命中分布」因此成为实测数字而非推断。
🔴 由此新增的判据红线:若 100 轮事后归因中 in_put 类为 0,
则本批不得宣称覆盖了提交中断,只能宣称「多次真实断电后可开」。不加这条,占空比补偿就是循环论证。
表述纪律(违反即假绿):本方案的结果只能写作「人工时刻掉电 100 次」,
不得写成「随机掉电 100 次」—— 时刻是人选的,既非 PRNG 也非均匀分布,且与被测系统可见行为存在相关性。
同时必须随结论发布效力边界:① 覆盖范围只能事后报告、不能事前保证;② 不得与 L2 的 100/100 合并成一个数字;
③ pass + fail + not_verified == rounds 必须恒等,NOT-VERIFIED 轮次不得计入通过、也不得挑着补跑。
完整表述模板见 TS-2 v0.3 §7.5,六条假绿风险自查见 TS-2 v0.3 §7.8。
在按此口径重跑之前,任何「L3 随机掉电 N 次」的数字都不得与 L2 的 100/100 混为一谈,
也不得用它去推翻或支撑 G7 结论。另:TS-2 设计阶段还查出 nonmono 与 tx2 两项判据
在 L3 结构上不可判定(详见 07-实测手册/TS-2掉电台架设计_v0.1_20261028.md §5),
其板端口径分别退化为「前缀完整性」与「上界约束 visible ≤ acked + in_flight」,与 L2 同名判据不等价。
[G7 真数字] 100 次随机硬掉电(真实进程 abort): open_fail=0 half=0 tx2=0 nonmono=0 lost=0 mismatch=0 corrupt=0 noreject=0 notfired=0 saw_visible=98 首见字节=722 [PASS] TC-N-08 IMPL 随机掉电 100 次,库 100% 可开 43427.6 ms [PASS] TC-N-11 IMPL 断电扫描 96 点:全部中断点可无损重启 46935.1 ms
| 放行标准 | 实测 | 结论 |
|---|---|---|
open_fail = 0 | 0 | [OK] |
partial = 0(half / tx2 / nonmono 均 0) | 0 | [OK] |
lost = 0 | 0 | [OK] |
saw_visible ≥ 10(防空通过) | 98 / 100 | [OK] 远超下限,证明断点确实落在提交之后 |
open_inval = 0(第 5 条,后加) | 0 | [OK] 配置类 open 失败不计入 G7,但须单独断言为 0 |
open_inval 从 open_fail 里分出来:二者原本共用一个计数器,一个配置 bug 就能把 G7 的失败计数顶爆——这是判据被无关因素污染的典型。G7 测的是「掉电后库开不开」,不该被配置错误干扰。现在 open_fail 只统计 IO / CORRUPT / 超时(计入 G7);open_inval(EM_E_INVAL)不计入,但单独断言必须为 0,否则说明测试环境本身有配置错。
三个前提同时成立(缺一则该数字不成立):① emstub_impl.c 已删,13 个引擎 .c + em_blk_reg.c 原样入链,后端自报 emlite 且 em_open 真跑通;② 断电是真进程 abort,父进程靠「异常终止 + POWERCUT marker + 无 DONE」三重判定;③ 非空通过,98/100 断点落在提交之后。
EM_PCUT_BIT_AT 第一版是坏的——em_flash_write 按 EM_FLASH_CHUNK=256 整块推进,触发条件 done == bit_at 而 done 只取 0/256/512…,bit_idx=7 被整块跨过,注入静默退化成"什么都没发生"。mark 判据确实完备),修复后两条独立证据逐位对上(纯枚举 128/127、真实介质 128/127),只是依据现在才补齐。powered==false 下返回 EM_E_POWER,需直接读仿真介质文件;否则读到的是前滚补完的行,测不到撕裂态)。
WAL 增量×2 → COMMIT → 数据 8 B → mark 4 B → 超级块擦/体/魔法。COMMIT 先于数据页落盘 → 「数据页写一半」这类撕裂在下次开库时被幂等前滚修好、不残留(实测:撕裂后重开有效样本=4,均值=20.00)。mark 是纵深防御——它兜的是"前滚本身再被断电打断"的中间态,不是兜住每一次半写。两个极端都不要写:既不要写成"判据兜住每一次半写",也不要反过来据此说"判据用不上"。
| ID | 判据 | 步骤 | 预期 |
|---|---|---|---|
| TC-N-01 | G1 | 向 Dev-B 持续灌入直到拒绝为止,记录条数 | ≥12,000 条(可行性门槛 8,000);Dev-A ≥2,500 条;库可正常打开并检索 |
| TC-N-02 | G2 | 12,000 条库,mem.query × 1,000 次,记录板侧耗时 | P50<10 ms,P99<30 ms,P99/P50<4 |
| TC-N-03 | G3 | 满库稳态下读水位 | PSRAM ≤5 MB,DRAM ≤180 KB |
| TC-N-04 | G3 | 包装 malloc/calloc/realloc,进入 RUNNING 后计数 | 计数 = 0(全预分配池) |
| TC-N-05 | G5 | 12,000 条 .emf 经 HTTP 灌入,计时 | ≤ 60 s |
| TC-N-06 | G5 | 同一包分别经 USB bulk / 串口 921600 / MSC 灌入 | USB ≤90 s;串口 ≤240 s;MSC ≤60 s。四通道分别计,不合并 |
| TC-N-07 | G6 | 拔网线 / 关 Wi-Fi,重跑 TC-C / TC-F / TC-S3 各核心用例 | 全部通过;本地灌库、检索、回写、接力均可用;联网后复测全过 |
| TC-N-08 | G7 | TS-2 台架:随机掉电 100 次(覆盖:空闲 / 灌库中 / 提交中 / compact 中 / 接力中 五种状态各 20 次) | 100% 库可打开且索引与数据一致 —— 一票否决。任一次失败即判定 MVP 失败,回退评估 |
| TC-N-09 | G8 | 解析 .map,统计 libedgehippom.a 的 .text | ≤ 60 KB |
| TC-N-10 | G8 | 1,000 次「begin → put×N → abort」,记录耗时 | abort P99 ≤ 2 × P50 |
| TC-N-11 | G8 | PC 仿真(TS-3):在写入第 N 字节后精确中断,遍历 N | 所有中断点恢复后数据一致;无半成品记录 |
| TC-N-12 | 长稳 | 7×24 h 连续运行(采集 + 入库 + 查询并发) | 无自发重启;无内存泄漏;heap 水位无单调下降。若重启先查栈溢出(抓 Rebooting 前 30 行) |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-M-01 | 两板上电,观察 link.scan | 30 s 内互相可见;能力通告含 frags 摘要与 bearers |
| TC-M-02 | 关闭一台设备,等待 | 120 s 后从邻居表消失(TTL 生效) |
| TC-M-03 | M1 完整六原语时序:query→bid→request→result×N→award | 跑通;碎片入库;账本双方各记一条 |
| TC-M-04 | 大碎片分块传输(≥100 块) | 每块 CRC32 校验通过;无错位 |
| TC-M-05 | 传输到第 50 块时中断 → 重连 → 续传 | 从第 50 块继续,不从头;最终完整 |
| TC-M-06 | M2:源设备离线,Hub 代持其碎片 | 第三方可从 Hub 取得;Hub 账本记双份(给 owner + 给 Hub) |
| TC-M-07 | M2 下 owner 重新上线 | 三方账本对账一致;无重复记账 |
| TC-M-08 | M3:USB MSC 拷入 .emf + .emr | ≤60 s;可用;回执字段完整 |
| TC-M-09 | M3 后联网对账 | 账本并集去重,误差 = 0 |
| TC-M-10 | mesh.ledger 双方导出比对 | 双向条目一致,误差 = 0(G9) |
| TC-M-11 | 接力中途失败(断链 / CRC 错 ×3 / 配额不足) | abort 且已有库完好如初;返回明确错误码 |
| TC-M-12 | 配额耗尽后继续请求 | 返回 ERR_QUOTA_EXCEEDED;不得降级为「先给数据后补账」 |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-W-01 | 页面(http://localhost:8080)fetch 板子 /api/status | 成功(CORS + OPTIONS 预检生效)。这是地基,不通则后面全不成立 |
| TC-W-02 | https 页面请求 http 板子 | 复现 mixed content 拦截 → 文档与启动脚本须明确禁止 |
| TC-W-03 | WebUSB 连接 Dev-B | 枚举成功;设备卡片显示 ID / 形态(form)/ 容量 / 固件版本(不出现角色字段,ADR-018) |
| TC-W-04 | WebUSB 不可用 → 自动降级 Web Serial | 降级提示清晰;用户可手动选端口 |
| TC-W-05 | Wi-Fi 通道连接同网段板子 | 成功;/api/store/map 数据正确渲染 |
| TC-W-06 | 连接中拔掉 USB / 断开 Wi-Fi | 进入 LOST;明确区分「设备掉线」与「灌库失败」 |
| TC-W-07 | 恢复连接 | 自动或一键重连成功;状态回到 READY |
| TC-W-08 | 设备变砖 → esptool-js 救砖 | 可进入 ROM bootloader 并刷回。救砖通道必须可用 |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-W-09 | 五步向导逐步填写 | 状态机正确;不可跳步;六项产出收集齐才可进第 5 步 |
| TC-W-10 | 任一必填项留空 → 下一步 | 被拦截并给出明确提示 |
| TC-W-11 | P0 变量替换({{cap_kb}} 等) | 全部替换;无残留 {{ }} |
| TC-W-12 | P0 输出 JSON 解析 | 六个键齐全;容量约束被遵守 |
| TC-W-13 | P2 生成条目的 text 字节数 | 全部 ≤150 字节;超长条目被重新生成而非截断 |
| TC-W-14 | P3 去重判据 | 余弦 >0.95 → MERGE;<0.85 → KEEP_BOTH;中间档给出理由 |
| TC-W-15 | API Key:留空提交 / 输入新值 / 输入 __clear__ | 分别:保留旧值 / 更新 / 清除;全程不回显明文 |
| TC-W-16 | P5 断网话术生成 | 三类模板齐全;中文 ≤40 字;承认不知道 |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-W-17 | 打包 1,000 条 → 检查 32 B 头 | magic="EMKBIMG1";version / vec_dim / rec_count / payload_len 正确 |
| TC-W-18 | 校验 payload_crc32 | 与独立计算一致 |
| TC-W-19 | 向量是否在记录末尾 | 解析记录:text→meta→vec;vec 必须是最后一段(ADR-010) |
| TC-W-20 | P4 的 20 条验收用例是否入包 | 存在特殊 frag_id=0xFFFFFFFF 元数据块;frag.verify 可读取 |
| TC-W-21 | M3 回执 .emr 生成 | 字段完整(from/frag_id/bytes/quota/crc32) |
| TC-W-22 | embedding 调用是否经过我方服务器 | 抓包验证:直连厂商 API,无任何我方域名(ADR-008) |
| ID | 步骤 | 预期 |
|---|---|---|
| TC-W-23 | HTTP 烧录 12,000 条 | ≤60 s(G5);进度条连续 |
| TC-W-24 | USB bulk 烧录同一包 | ≤90 s |
| TC-W-25 | 串口 921600 烧录同一包 | ≤240 s;进度条必须清晰(这是串口通路被保留的前提) |
| TC-W-26 | 烧录到 50% 时拔线 → 重连 → 续传 | 从断点继续;最终完整;已有库在失败期间完好 |
| TC-W-27 | 灌入错误包 | 被拒绝;已有库完好如初;UI 明确提示「已自动回滚,您的记忆不会丢」 |
| TC-W-28 | 固件 OTA 后检查知识库 | OTA 只写 app,已灌记忆完好;版本号 sys.info 已更新 |
| 层次 | 范围 | 触发 | 说明 |
|---|---|---|---|
| L1 PC 单测 | 引擎层全部(em_flash_io 文件仿真) | 每次 commit | 最快反馈。含 TC-N-11 精确断电遍历 |
| L2 构建门禁 | 两板构建 + 槽位硬门槛(W0-06)+ .text 体积检查 | 每次 commit | 占用 >90% 构建失败 |
| L3 板级冒烟 | TC-C-01…08 + TC-F-01/04 | 每日 | 需 TS-1 台架在线 |
| L4 全量回归 | 96 条中可自动化的部分(约 70%) | 每周 + 里程碑前 | 掉电/长稳/断网需人工台架 |
| L5 人工 | TC-N-08 掉电、TC-N-12 长稳、TC-W 主观体验 | 里程碑 | — |
不可自动化的 22 条:TC-N-08(需物理台架)、TC-N-12(7×24 h)、TC-S2-*(断网操作)、TC-W 主观体验部分。
| 级别 | 定义 | 响应 | 放行 |
|---|---|---|---|
| S1 致命 | 库损坏 / 掉电不可恢复 / 数据静默丢失 / 合规越线 | 立即停线 | 0 容忍 |
| S2 严重 | 判据未达标(G1–G6、G8、G9)/ 主要功能不可用 / 接力失败破坏已有库 | 24 h 内修复 | 可放行但必须记录并给出时间表 |
| S3 一般 | 次要功能异常、性能略低于目标但不影响可用性 | 排入迭代 | 可放行 |
| S4 提示 | 文案、样式、体验建议 | 择机 | 可放行 |
EdgeMemory-MVP 验收报告 [里程碑 M_] 一、结论 □ Go —— 进入下一阶段 □ No-Go —— 回退评估(说明触发的判据) □ 有条件 Go —— 列出挂起项与时间表 二、判据达成情况 判据 目标值 实测值 用例 结论 G1 ≥12,000 条 _______ TC-N-01 □达标 □未达 G2 P50<10/P99<30 _______ TC-N-02 □达标 □未达 G3 ≤5MB/≤180KB _______ TC-N-03/04 □达标 □未达 G4 闭环可命中 _______ TC-S1-07 □达标 □未达 G5 四通道耗时 _______ TC-N-05/06 □达标 □未达 G6 断网全通过 _______ TC-N-07 □达标 □未达 G7 掉电 100 次 _______/100 TC-N-08 □达标 □未达 ← 一票否决 G8 emlite 三项 _______ TC-N-09/10 □达标 □未达 G9 账本误差 0 _______ TC-M-10 □达标 □未达 三、用例统计 总数 92|通过 __|失败 __|阻塞 __|未执行 __ S1 缺陷 __(必须为 0)|S2 __|S3 __|S4 __ 四、实测 vs 推算对照(用于更新文档) 项目 推算值 实测值 是否需修订文档 单条有效成本 930 B ______ □是 □否 Dev-B 容量 12,900 ______ □是 □否 ... 五、已知限制(不得进入对外材料) 1. … 2. … 六、签字 PM ____ FW-A ____ FW-B ____ TOOL ____ WEB ____ QA ____
| 编号 | 关联判据 | 被测改动 | 平台 | 状态 |
|---|---|---|---|---|
| TC-R-01 | G3 内存 | app_main.c 新增 emlite_init_task(栈 8192 B)+ 双模 BLE + telem_start | Dev-A 优先,Dev-B 同测 | 待跑 |
| TC-R-02 | 启动时序 | 同上;Dev-A 冷启动改走 BLE autoconnect + 15 s 遥测 | Dev-A 优先,Dev-B 同测 | 待跑 |
| TC-R-03 | kb 数据契约 | link_mgr.c 落盘 tags src= 由写死 edge 改为 emgw_form_str() | Dev-A + Dev-B 互联 | 待跑 |
| 项 | 内容 |
|---|---|
| 目的 | 确认 W0-05 后新增的 emlite 开库任务与遥测任务,未把峰值内存推过 G3 门槛 |
| 改动来源 | app_main.c:xTaskCreate(emlite_init_task, "emlite_init", 8192, NULL, 5, NULL);link_mgr 双模 BLE;telem_start()(周期 15 s) |
| 步骤 | ① 刷入当前 xiao(gamma-card)固件,整片擦除后冷启动;② 等日志出现「emlite 引擎就绪」;③ 读取 sys.info / store.map,记录 PSRAM 占用与 DRAM 峰值;④ 重复 3 次取最大值 |
| 期望 | PSRAM ≤ 5 MB;内部 DRAM 峰值 ≤ 180 KB;运行期 malloc = 0 |
| 关联 | G3;07-实测手册 §6 硬指标 |
| 状态 | 待跑 —— 未执行,无任何证据 |
| 项 | 内容 |
|---|---|
| 目的 | 确认 Dev-A 新增的 BLE 自动重连与 15 s 遥测上报,未拖垮冷启动成功率;且引擎开库不阻塞其它模块 |
| ★ precondition (必须显式记录) | 刷了新固件的板,NVS 键由 "role" 改为 "form",旧值不再被读取
⇒ 形态一定取编译期默认值(EMGW_FORM_DEFAULT_STR)。若需覆盖,必须显式执行 sys.set_form。
据此,本用例执行前必须先确认被测板的 sys.form 实际返回值,否则后续结论不成立。 |
| 步骤 | ① 记录当前 sys.form;② 连续冷启动 3 次;③ 每次记录 NVS / transport / store / wifi / cli / ble / link / telem / emlite 各模块是否全部成功;④ 记录从复位到「emlite 引擎就绪」的耗时 |
| 期望 | 冷启动成功率 3/3;emlite 首次开库(含整片擦除)不阻塞日志/网络/互联起来(这是把它独立成任务的初衷) |
| 状态 | 待跑 —— 未执行,无任何证据 |
| 项 | 内容 |
|---|---|
| 目的 | 确认落盘 tags 的 src= 字段与全仓断言一致,避免静默失配 → 假绿 |
| 改动来源 | link_mgr.c L773-777:em_kb_add(rec_id, "tier=dynamic;src=edge;type=telemetry", ...)
→ snprintf(src_tag, "tier=dynamic;src=%s;type=telemetry", emgw_form_str()) |
| ⚠ 风险说明 | 查 src=edge 的断言在改成 src=gamma-card / src=usb-dongle 之后会变成「查不到」,
而「查不到」在不少判据里被当作「拒答正确」→ 假绿。这比直接报错危险得多,因此单独立用例。 |
| 步骤 | ① Dev-A 与 Dev-B 配对并互联;② 触发一次遥测上报并落库;③ 执行 em.kb.list;④ 检查返回的 tags 中 src= 取值 |
| 期望 | Dev-A 落盘记录 tags 含 src=gamma-card;Dev-B 落盘记录 tags 含 src=usb-dongle;不再出现 src=edge |
| 状态 | 待跑 —— 未执行,无任何证据 |
s。s=44 与 s=644 相差 14.6 倍,脱离 s 的条数是无效数字。C = rec_pages × 4080 B/页;
Dev-B(16MB / 3,040 页)rec_pages = 2,683 → C = 10,946,640 B,s=644 稳态约 14,448 条;
Dev-A(8MB / 992 页)rec_pages = 635 → C = 2,590,800 B,s=644 稳态约 3,419 条。partitions_emgw.csv;分区表一换,C 必须重算。