Files
HologramAgent-DSH-Memory-Port/docs
jianf 160b5b5139 fix(memory-b): 三项验收整改 —— 去写死数字 / F8 硬报错 / blockStates 去 JSON.parse
一、skipped 断言不再写死数字
原 assert.equal(hits.skipped, 2) 属于「手抄数字」——与刚删掉的 README 计数同类:
fixture 一改就悄悄不再描述事实。
改为从构造库现算:expectedSkipped = counts.unknownSpace + counts.spaceMismatch,
并先断言 expectedSkipped > 0(防止变成「0 == 0」的假通过)。

二、F8 从「事后统计」改成「写侧硬报错」
原状:写侧维度校验只降级成「不嵌入」,坏向量仍能落库,靠 blockStates
的 dimensionMismatch 事后兜住 —— 那是 accounting,不是 validation,
与 criteria:165 的「硬报错」不符。

实现:putBlock 新增可选 expectedDimension,声明了宽度且不符 ⇒ 抛错不落库。
commit 在「调用方显式传 vector」时传 expectedDimension。

★ 两个入口必须分清,否则会与 W4 打架:
  - 调用方 bug(显式传了宽度不对的向量)⇒ **必须抛**,否则它以
    「块在、召回不了」的形式沉默很久
  - provider 异常(embedding 返回宽度不对)⇒ 按 W4 降级为不嵌入,块仍写入
    (把上游抖动抛给用户 = 让一次 provider 故障变成写入失败)
判据含三例:显式传错宽度抛;显式传对宽度通过;provider 返回错宽度降级不抛。
F8† 变异:把宽度检查改成恒不触发 ⇒ 坏向量落库 ⇒ 判据红。

三、blockStates 不再解析向量(性能账)
实测 2000 块 × 2048 维:
  改前 354ms/次(其中 255ms 是纯 JSON.parse)
  改后 4ms/次(约 90×)
而 renderIndex 每轮都调它 —— 这是挂在 pre-step 热路径上的固定成本。

做法:memory_blocks 新增 vector_dim 列(维度是行事实,不是负载内容),
  - putBlock 写入时一并写
  - 迁移时为存量行回填一次(只此一次,不在读路径)
  - 加两个触发器保证 vector 与 vector_dim 永不脱节:
      ★ 理由:既然这一列的存在就是为了「不解析负载」,那每个写入者都背上了
        保持一致的义务。漏一个写入者(修复脚本、测试 fixture、未来迁移)
        就产生一行「维度是谎话」的数据 —— accounting 报它 active,
        而召回静默跳过它。用触发器让这个状态**不可表示**,而不是只劝阻。
  - 静态判据:blockStates 函数体内不得出现 JSON.parse(防以后「顺手简化」改回去)

四、embedFailure 记账
不进四态(它是单次调用事件,不是库状态),criteria 已补说明:
四态是库状态、从行派生;embedFailure 属于 recallBlocksHybrid 的 degraded,
由 W 组覆盖。塞进库状态会让「同一时刻读两次得到不同数字」,正是 D4 要避免的。

顺带修:F4† 的变异锚点因 blockStates 改写而失效(withMutatedCopy 显式报
「anchor not found」——这条守卫按设计响亮失败,没有静默变绿)。

验证
- npm test 148/148(143 + F8 四条 + 性能守卫一条)
- npm run check 10/10
- 性能实测见上
- 干净副本实数见后续消息
2026-10-30 16:29:05 +08:00
..