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 工具一起做
35 lines
1.0 KiB
JSON
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
|
|
}
|