Files
HologramAgent-DSH-Memory-Port/package.json
jianf 00a4a5f6ee feat(memory-b): G2† 编成 test + H 组完成(http adapter + 两表指纹一致)
G2† 补成自动化(你坚持的那条,我认)
你指出 G 组只有三条变异是自动化断言,G2† 只活在我的 commit message 里 ——
手工记录的变异不会随时间复现。已编成 test,并扩到覆盖**每一条**降级路径:

  DEGRADATION_PATHS 数据表(6 条,新增第五条时未覆盖则测试即红)
    embedder is null / undefined / 无 embedText
    ★ 无 info()                      ← 你点名的那条
    ★ info() 的 fingerprint 为空串
    ★ info() 的 fingerprint 非字符串
  + 每条都断言 degraded=no_embedder、仍能召回、且零 fetch
  + 额外一条「指纹检查在 embedText 之前」(钉顺序,不只钉结果)

变异实测打红
  把 embedText 调用挪到指纹检查之前
    not ok 8 - G2†: the fingerprint check runs BEFORE embedText is called
  让无指纹分支发一次 fetch
    not ok 5 - G2†: "embedder with no info()" ... zero network calls

H 组实现(lib/embed/http.js,单文件,G5 守卫)
- 协议与 HA 逐字段一致:model / modality / side / text;响应两种形状都收
- 指纹 http:<model>:<dim>:<sha256(规范化 endpoint)[:8]>
  规范化(hash 之前):去空白 / scheme+host 小写 / 去尾斜杠 / 去默认端口
  不做 query 重排与 .. 解析(那些差异通常是真实的)
  ★ 构造时算一次并复用 —— 因为同一个串必须同时进两张表
- 失败在 adapter 层是硬错误(非 2xx / 无 embedding / 维度不符 / 超限 / 超时),
  在召回层被 catch 成 degraded='embed_error',退回 FTS5
- 维度不符绝不截断不填充(block_recall.go:135-138)

票② 两表指纹一致 —— 落在 H 组 schema,未拖到 F
- memory_blocks 加 vector / fingerprint 两列(phase A 的表已发布,
  这里用 CREATE TABLE IF NOT EXISTS 的新列,旧库需 ALTER;已记入待办)
- graph_centroid 列名对齐 HA(vector_count / vector / stats / built_at),
  并把 is_anomalous 提成独立列(票③口径),不塞进 stats JSON
- putBlock 拒绝「有向量但无指纹」——无标签的向量永远不可安全比较
- putBlock 重提交不带向量时不清空已有向量(与 PutMemoryBlocks 的空值不覆盖同构)
- 新增 saveCentroid / loadCentroid / blockFingerprints

票② 判据
  ok - ticket②: block fingerprint and centroid fingerprint are byte-identical
  ok - ticket② mutation: a re-derived centroid fingerprint misses the lookup
       (加一个尾随空格即查不到,且不抛错 —— 正是必须用断言钉住的原因)
  ok - ticket②: a vector without a fingerprint is refused at write time
  ok - ticket②: re-committing without a vector must not erase the stored one

H 组变异(8 条,全部实跑打红)
  HM1 side 写死 document        → not ok 1 - H1
  HM2 指纹去掉 endpoint hash     → not ok 10/12/13 - F-fp1/fp3/fp4(三条一起红)
  HM3 维度不符改为截断           → not ok 5 - H3b
  HM4 去掉响应体积上限           → not ok 9 - H6
  HM5 保留尾斜杠                 → not ok 11 - F-fp2
  HM6 非 2xx 当成功              → not ok 4 - H3
  HM7 忽略 timeout signal        → not ok 8 - H4
  HM8 指纹每次 info() 重算       → not ok 15 - F-fp6

一处设计确认:lib/index.js 现在 import './embed/http.js',
G5 仍绿 —— 因为该文件没有 fetch/Authorization 等 transport 标识符。
「可以 import adapter,不可以知道 transport」正是 G5 的设计意图。

验证
- npm test 76/76(56 + H 组 20)
- npm run check 9/9
- 提交前连跑 3 次 test + 3 次 check,6 次全绿

待办(不催,记着)
- 票③ D7 fail-closed(中心表空但有向量行 ⇒ dim 报 null 不报 0)跟 F 组
- phase A 旧库升级需 ALTER TABLE 加两列,随 D 组的 stats 工具一起做
2026-10-30 10:17:18 +08:00

35 lines
1.0 KiB
JSON

{
"name": "dsh-memory",
"version": "0.1.0",
"description": "HologramAgent-style block memory (stablemem) for dsh: sqlite + FTS5 recall, no embedding.",
"type": "module",
"main": "lib/index.js",
"exports": {
".": "./lib/index.js"
},
"files": [
"lib/*.js",
"lib/types/*.d.ts"
],
"engines": {
"node": ">=22.5.0"
},
"scripts": {
"test": "node --test test/store.test.js test/plugin.test.js test/loader.test.js test/phase-b-a.test.js test/phase-b-g.test.js test/phase-b-g-static.test.js test/phase-b-h.test.js",
"check": "node scripts/checkpoints.js"
},
"peerDependencies": {
"@deepseek-ai/cordis": "^4.0.5",
"@deepseek-ai/dsh-llm": "0.2.1-rc.2",
"@deepseek-ai/dsh-system-prompt": "0.2.1-rc.2",
"@deepseek-ai/dsh-tools": "0.2.1-rc.2"
},
"peerDependenciesMeta": {
"@deepseek-ai/dsh-system-prompt": { "optional": true },
"@deepseek-ai/dsh-tools": { "optional": true },
"@deepseek-ai/dsh-llm": { "optional": true }
},
"license": "MIT",
"private": true
}