@furongjun1999/dsh-memory 0.6.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +588 -572
- package/codebuddy/CODEBUDDY.md +10 -10
- package/data/policy.json +27 -0
- package/docs/discipline/harnesses.yaml +31 -0
- package/docs/discipline/templates/full.md.tmpl +1 -1
- package/docs/discipline/templates/rules.mdc.tmpl +1 -1
- package/docs/eval/N225_/347/264/242/345/274/225/346/227/245/345/277/227/351/235/236/345/257/271/350/261/241/350/243/205/350/275/275/351/235/242/347/261/273/345/236/213/351/227/270_v1.0.md +418 -0
- package/docs/eval/issue43_/351/273/230/350/256/244/347/255/226/347/225/245/344/270/216/351/224/256/347/261/273/345/236/213/351/227/270_v1.1.md +441 -0
- package/docs/eval/issue43_/351/273/230/350/256/244/347/255/226/347/225/245/345/212/240/350/275/275/344/270/216/345/207/255/346/215/256/346/230/216/346/226/207/351/230/237/345/210/227_v1.0.md +398 -0
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/270/200/346/211/271_/346/216/245/347/272/277/344/270/216/347/255/211/344/273/267/345/217/230/346/215/242_v1.0.md +498 -0
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/270/211/346/211/271_/351/227/250/347/246/201/350/275/254/346/255/243/344/270/216/350/260/203/345/272/246/346/255/242/350/241/200/344/270/216/351/227/250/346/216/247/346/224/266/345/217/243_v1.0.md +669 -0
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/272/214/346/211/271_/344/276/235/350/265/226/351/200/217/344/274/240/344/270/216/345/257/271/346/213/215/345/217/243/345/276/204/344/270/216/350/264/237/347/274/223/345/255/230_v1.0.md +683 -0
- package/docs/eval//345/217/221/345/270/20307_/345/244/226/351/203/250/346/212/245/345/221/212/345/233/233/346/211/271/344/277/256/345/244/215/344/270/216/346/217/222/344/273/266/351/235/242/345/212/240/345/233/272_v1.0.md +205 -0
- package/docs/eval//346/200/247/350/203/275/344/270/223/351/241/271_/345/206/267/346/237/245/350/257/242/344/270/216/345/206/205/345/255/230_v1.0.md +218 -0
- package/docs/eval//346/225/205/351/232/234/346/263/250/345/205/245/345/256/236/346/265/213_v1.0.md +10 -0
- package/docs/eval//347/274/226/347/240/201/351/235/242/345/211/215/347/275/256_/345/205/245/345/217/243/350/207/252/344/277/235/350/257/201UTF8/344/270/216/346/226/207/346/234/254open/345/256/210/345/215/253_v1.0.md +646 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v20.md +283 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v21.md +224 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v22.md +223 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v23.md +293 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v24.md +303 -0
- package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v25.md +230 -0
- package/docs/hive//346/243/200/347/264/242/350/267/257/345/276/204/344/270/216/350/256/244/347/237/245/347/273/223/346/236/204/345/245/221/347/272/246_v0.1.md +20 -0
- package/docs/hive//350/234/202/345/267/242M6_ingest/345/256/236/346/226/275/350/256/241/345/210/222_v0.1.md +1 -1
- package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +12 -0
- package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +40 -40
- package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +21 -9
- package/docs/mdcg//347/201/265/346/236/242/350/256/260/345/277/206/345/212/250/350/257/215/345/215/217/350/256/256_v1.0-draft.md +7 -2
- package/docs/mdcg//350/256/244/347/237/245/345/233/276_/347/264/242/345/274/225/344/270/216/345/267/245/347/250/213/350/247/204/350/214/203/345/214/226_/350/256/241/345/210/222_v0.1.md +39 -3
- package/docs/plans//345/205/250/344/270/255/346/226/207/347/274/226/347/240/201/344/270/216/350/234/202/345/267/242/344/273/273/345/212/241/346/240/207/350/257/206/345/245/221/347/272/246_v2.0.md +220 -0
- package/docs/plans//347/234/237/346/272/220/347/264/242/345/274/225_/351/200/232/347/224/250/346/234/272/345/210/266_v0.3.md +227 -0
- package/docs/plans//350/234/202/345/267/242/346/250/241/345/236/213/345/257/206/351/222/245/351/205/215/347/275/256/351/235/242_v1.0.md +385 -0
- package/docs//345/267/245/344/275/234/347/272/252/345/276/213_/350/256/244/347/237/245/345/233/276/346/235/241/347/233/256_v1.1.json +460 -460
- package/lib/bridge.js +24 -2
- package/lib/hooks.d.ts +31 -2
- package/lib/hooks.js +219 -16
- package/lib/init.js +16 -1
- package/lib/lib/prompt_safety.d.ts +52 -1
- package/lib/lib/prompt_safety.js +76 -1
- package/md_cg/audit.py +652 -379
- package/md_cg/bench6_arms.py +1 -1
- package/md_cg/bench_p0.py +1 -1
- package/md_cg/branches.py +2 -2
- package/md_cg/ccgc.py +1071 -1006
- package/md_cg/chain.py +1 -1
- package/md_cg/consistency.py +97 -9
- package/md_cg/consolidate.py +34 -9
- package/md_cg/crypto.py +59 -26
- package/md_cg/docindex.py +16 -1
- package/md_cg/evolution.py +17 -1
- package/md_cg/export.py +1 -1
- package/md_cg/forgetting.py +309 -13
- package/md_cg/fsutil.py +454 -8
- package/md_cg/identity.py +3 -3
- package/md_cg/insight.py +24 -3
- package/md_cg/linkref.py +1 -1
- package/md_cg/logref.py +327 -0
- package/md_cg/mcp_server.py +4152 -3818
- package/md_cg/mdcg.py +4208 -3547
- package/md_cg/mdcos.py +4491 -4159
- package/md_cg/mreview/pipeline.py +15 -1
- package/md_cg/nodefile.py +639 -575
- package/md_cg/protect.py +158 -11
- package/md_cg/protocol.py +41 -2
- package/md_cg/provenance.py +22 -4
- package/md_cg/reach.py +4 -4
- package/md_cg/readcache.py +76 -15
- package/md_cg/reconcile.py +1 -1
- package/md_cg/refindex.py +246 -37
- package/md_cg/refine.py +1 -1
- package/md_cg/routing.py +32 -5
- package/md_cg/run_tests.py +17 -0
- package/md_cg/scrub.py +30 -3
- package/md_cg/security.py +47 -1
- package/md_cg/self_state.py +5 -5
- package/md_cg/sources.py +23 -6
- package/md_cg/srcindex.py +352 -0
- package/md_cg/stg.py +47 -3
- package/md_cg/subgraph.py +2 -2
- package/md_cg/sustain.py +1299 -1168
- package/md_cg/tasks.py +469 -470
- package/md_cg/test_b1_auto_id_multiproc.py +277 -0
- package/md_cg/test_b1b2_write_face.py +417 -0
- package/md_cg/test_b2_sensitivity_landing.py +223 -0
- package/md_cg/test_b3_merge_keeps_content.py +576 -0
- package/md_cg/test_b4_shard_dir_selfheal.py +843 -0
- package/md_cg/test_b4_shard_dir_selfheal_guard.py +238 -0
- package/md_cg/test_c3_transient_read_negative.py +793 -0
- package/md_cg/test_c8_search_rrf_gates.py +502 -0
- package/md_cg/test_ccg_form_parity.py +188 -0
- package/md_cg/test_ccgc.py +28 -3
- package/md_cg/test_govern_directread.py +17 -4
- package/md_cg/test_h2_session_view_norm.py +233 -0
- package/md_cg/test_h4_sustain_snapshot.py +1377 -0
- package/md_cg/test_hive_ingest.py +285 -285
- package/md_cg/test_issue39_utf8_stdio.py +307 -16
- package/md_cg/test_issue43_default_policy.py +865 -0
- package/md_cg/test_legacy_p3_node_id_type.py +375 -0
- package/md_cg/test_linkref.py +10 -3
- package/md_cg/test_lock.py +2 -2
- package/md_cg/test_logref.py +1109 -0
- package/md_cg/test_m3_h9_bucket_health_protect_mark.py +301 -0
- package/md_cg/test_m3_h9_semantic_guard.py +525 -0
- package/md_cg/test_mr_m2.py +15 -3
- package/md_cg/test_n130_verify_falsified_protect.py +1 -1
- package/md_cg/test_n139_dek_provision_failclosed.py +185 -0
- package/md_cg/test_n176_link_trust.py +221 -0
- package/md_cg/test_n178_units_jobid_gate.py +212 -0
- package/md_cg/test_n184_keys_concurrent_provision.py +307 -0
- package/md_cg/test_n195_writepath_reload.py +283 -0
- package/md_cg/test_n196_stale_gate_skip.py +169 -0
- package/md_cg/test_n197_n208_write_face_gates.py +471 -0
- package/md_cg/test_n198_tokens_corrupt_failclosed.py +225 -0
- package/md_cg/test_n199_tokens_concurrent_write.py +378 -0
- package/md_cg/test_n201_proposal_visibility.py +382 -0
- package/md_cg/test_n202_session_notes_visibility.py +461 -0
- package/md_cg/test_n204_n205_n226_n227_n228_n229_exit_gates.py +542 -0
- package/md_cg/test_n206_stdio_jsonrpc_type.py +403 -0
- package/md_cg/test_n209_verify_write_face_gates.py +461 -0
- package/md_cg/test_n212_n213_n224_generation_gates.py +513 -0
- package/md_cg/test_n214_n215_n221_n222_write_face_gates.py +563 -0
- package/md_cg/test_n225_nonobject_load.py +1110 -0
- package/md_cg/test_n62_tenant_bind_failclosed.py +200 -0
- package/md_cg/test_neg_condition_hits.py +333 -0
- package/md_cg/test_neg_tail_honesty.py +663 -0
- package/md_cg/test_none_id_write_guard.py +4 -3
- package/md_cg/test_opt_batch1_md_cg.py +451 -0
- package/md_cg/test_p1.py +5 -5
- package/md_cg/test_p11_consistency.py +161 -12
- package/md_cg/test_p26_refindex.py +2 -2
- package/md_cg/test_p27_docindex.py +777 -774
- package/md_cg/test_p28_refcheck.py +740 -13
- package/md_cg/test_p29_session_ingest_export.py +2 -2
- package/md_cg/test_p2_mcp.py +12 -1
- package/md_cg/test_p30_maintain.py +33 -2
- package/md_cg/test_p31_insight.py +1 -0
- package/md_cg/test_p9c_dedup_hints.py +276 -0
- package/md_cg/test_policy_required_ccg.py +426 -0
- package/md_cg/test_protocol.py +22 -0
- package/md_cg/test_rank_parity_score_mode.py +516 -0
- package/md_cg/test_read_face_input_gates.py +363 -0
- package/md_cg/test_read_face_semantics.py +489 -0
- package/md_cg/test_recall_face_guards.py +812 -0
- package/md_cg/test_rejected_credential_forms.py +188 -0
- package/md_cg/test_rejected_redact.py +146 -0
- package/md_cg/test_retr_s1b.py +2 -2
- package/md_cg/test_retr_s5.py +20 -7
- package/md_cg/test_review_conformance.py +21 -3
- package/md_cg/test_security_audit_v21.py +2 -2
- package/md_cg/test_server_version.py +67 -0
- package/md_cg/test_srcindex.py +171 -0
- package/md_cg/test_tenant_env_override_warn.py +63 -50
- package/md_cg/test_token_lowercase_form.py +315 -0
- package/md_cg/test_v21r1_package_version.py +310 -0
- package/md_cg/test_writepipe.py +10 -4
- package/md_cg/tokens.py +225 -95
- package/md_cg/tool_face.py +4 -4
- package/md_cg/trust.py +49 -5
- package/md_cg/units.py +204 -6
- package/md_cg/weights.py +4 -4
- package/md_cg/whitebox_kb/wisdom/knowledge_points.py +1 -1
- package/md_cg/writelimit.py +42 -8
- package/md_cg/writepipe.py +651 -554
- package/package.json +3 -2
- package/skills/plugin.json +1 -1
- package/src/bridge.ts +25 -2
- package/src/hooks.ts +229 -16
- package/src/init.ts +15 -1
- package/src/lib/prompt_safety.ts +88 -1
- package/zcode/AGENTS.md +10 -10
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
# 0.6.1 发布报告 v1.0 —— 外部测试报告核验 · 四批修复 · Linux 双栈验证
|
|
2
|
+
|
|
3
|
+
> 批次:0.6.1 发布 | 报告:v1.0 | 环境:win32(Windows 10.0.19045)+ Docker Desktop(ServerVersion 28.4.0)
|
|
4
|
+
> 仓库 `dsh-memory-main`,发版前 HEAD `956807a1`,本版基线 `06db0f74`
|
|
5
|
+
> 编号说明:上一件为 [`发布06_一键配置与DSH0172_v1.0.md`](发布06_一键配置与DSH0172_v1.0.md)(0.6.0),本件续其序号为 07。
|
|
6
|
+
> 本报告所引全部检查为本会话**实跑复验**的结果;未跑项在第六节如实声明。**代理自报不作为判据**——每批均由编排侧独立复跑守卫、套件与门禁。
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 一、总览
|
|
11
|
+
|
|
12
|
+
本版修的是**外部 DSH 插件测试报告**中经核验「在 HEAD 上仍生效」的缺陷。一个前提必须先说清楚:
|
|
13
|
+
|
|
14
|
+
> 那份报告测的是**已发布的 npm 0.6.0 制品**,其代码早于本仓 HEAD;而 HEAD 的版本串当时**也是 0.6.0**
|
|
15
|
+
> ⇒ 一切「已修/未修」的判断只能**按代码**,不能按版本号。因此本轮先用九项探针把报告断言逐条落到 HEAD 的代码行为上,再动手。
|
|
16
|
+
|
|
17
|
+
| 阶段 | 内容 | 结果 |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| 第 0 步 | 九项探针(P-1…P-9b),只读、沙箱 root、绝不碰在役库 | 推翻我三处预判;额外挖出报告未含的缺陷 |
|
|
20
|
+
| 第 1 包 | 写面静默失败族(B1 自动 id 撞毫秒 / B2 密级静默降级 / B4 索引分片目录不自愈) | `778f8ede`,12 文件 +2344/−22 |
|
|
21
|
+
| 第 2 包 | 合并吞正文与冲突误判(B3 / H8 / H3)+ 补强 | `69e8719b`,8 文件 +1094/−41 |
|
|
22
|
+
| 第 3 包 | 召回面诚实性(H7/H10/H11/M1/M2/M3/M4/H9)+ 补强 | `2e7d7230`(18 文件 +3636/−140)、`f706b799`(9 文件 +243/−66) |
|
|
23
|
+
| 第 4 包 | 插件面(M5 / H5 / H6 / H1 / H2) | `956807a1`,14 文件 +1777/−36 |
|
|
24
|
+
| 收口 | 版本号 8 处 → 0.6.1 · README 版本表 · 门禁链文档订正 · **自查抓到并修掉一条自有回归** | 见第四、七节 |
|
|
25
|
+
|
|
26
|
+
四批合计(`06db0f74..956807a1`):**43 文件,+9036 / −247**。执行模型沿用第 17 条——每个工作包派发一轮 zcode 动态工作流(契约:先探针读数 → 再改码 → 守卫 → 定点变异自证 → 报告逐条读数),编排侧独立复核并分批提交。
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 二、九项探针:三处预判被推翻
|
|
31
|
+
|
|
32
|
+
探针全部独立 `tempfile` 沙箱 root(独立 `MDCG_ROOT`/`MDCG_AUX_ROOT`/`MDCG_MASTER_KEY`)、argv 列表 + `shell=False` + 显式 UTF-8,**不写入在役库**。三条结论与我事前的判断相反:
|
|
33
|
+
|
|
34
|
+
1. **P-4(分片目录删除后能否自愈)**——我原以为「新进程也看不到节点」,**被证伪**:全新短命进程本就会重建目录,故不自愈的必要条件是「本进程已持有 `ShardLog` 实例」(长驻 MCP serve 形态)。B4 的修法与反证据此写成。
|
|
35
|
+
2. **P-9a(H4 统一归一层默认开影响英文检索)**——**直接证伪报告结论**:默认态下英文查询命中 gold top1,且仓内本就有两条测试断言这一点。报告该条**不成立**。按使用者裁定「不动默认,补探针与文档」,本版**不翻全局默认**。
|
|
36
|
+
3. **P-3(MERGE 还是熵 DROP 吞正文)**——我原以为只有一条分支有问题,**实测是两条都吞**:`0.85` 的 MERGE 与 `0.60` 的熵 DROP 都丢新正文。第 2 包据此两分支一起修。
|
|
37
|
+
|
|
38
|
+
九探针另额外挖出**报告里没有**的三条缺陷:
|
|
39
|
+
|
|
40
|
+
- **①** CCG 哨兵 `不适用条件:无` 会无条件触发 `condition_clash`(假冲突)⇒ 第 2 包 H8-⑤ 收口(`_is_null_condition` + 输入剥空值)。
|
|
41
|
+
- **②** 基类 `MdCG.search` 的负记忆提示段会把同一节点**重复出条** ⇒ 随 H10 负尾单点化一并收口。**诚实边界**:收口后「重复出条」这一具体形态**我未单独立断言复验**,只由 `test_neg_tail_honesty.py`(44 断言)与 `test_read_face_semantics.py`(123 断言)间接覆盖 ⇒ **记为待复验项**。
|
|
42
|
+
- **③** `scripts/linkref_backfill.py` 仍在铸造裸毫秒 id(存量现场遗漏)⇒ 第 1 包 B1 把它改为委托 `mint_auto_id`,守卫断言「`def mint_auto_id(` 全仓仅 1 处」。
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 三、四批修复逐条
|
|
47
|
+
|
|
48
|
+
### 3.1 第 1 包 `778f8ede` —— 写面静默失败族
|
|
49
|
+
|
|
50
|
+
| 项 | 缺陷 | 修法(单点) | 守卫 |
|
|
51
|
+
|---|---|---|---|
|
|
52
|
+
| **B1** | 同毫秒自动 id 相撞**静默顶替**(并发写入丢条目) | 唯一铸造点 `mdcg.mint_auto_id`:形态 `mem_<毫秒>_<6位hex>`,撞既有 id 换随机段**有界重生成**(5 次),撞满 fail-closed 抛错;`writepipe` / `mcp_server` / `linkref_backfill` 三处现场全部委托 | `test_b1_auto_id_multiproc.py`(11)、`test_b1b2_write_face.py`(33) |
|
|
53
|
+
| **B2** | 声明 `private` 却落 `internal`,**密级静默降级** | 四处落盘实参表补 `sensitivity` 透传 + 单点 fail-closed 闸 `_check_sensitivity_landing` 接在全库唯一写盘口 `MdCG._write_node`(12 处调用点一次覆盖);**声明值与落盘值经 `declared_sensitivity` 分离**,否则 `or DEFAULT` 会把两者归一、闸永远看不见差异 | `test_b2_sensitivity_landing.py`(14) |
|
|
54
|
+
| **B4** | 长驻进程删掉 `_index_log/` 后**永不自愈** | 单点 `fsutil.ensure_shard_dir`(缺失即建 / 失败抛结构化 `ShardDirError` 带 code+hint / 成功记账 + stderr 告警——**容忍不等于静默**) | `test_b4_shard_dir_selfheal.py`(29)、`_guard.py`(21) |
|
|
55
|
+
|
|
56
|
+
**语义未动**:显式传 `node_id` 的「同 id 即改写」既有 upsert 契约原样保留(有断言钉住不被误伤);`read_all` 缺目录返回 `[]` 的既有语义未动。
|
|
57
|
+
|
|
58
|
+
### 3.2 第 2 包 `69e8719b` —— 合并吞正文与冲突误判
|
|
59
|
+
|
|
60
|
+
- **B3(真凶已定位)**:`forgetting.reinforce` 写回的是 `node.get("content")`(**既有**正文),且签名根本没有 content 参数。修法=加 `content=None` 槽(缺省不变 ⇒ 既有调用零破坏)+ 抽出共享聚合行 `forgetting.aggregate_line`(`reinforce` 与 `writelimit.converge_into` 同源),**MERGE 与熵 DROP 两条分支都写「新正文去向」**,且聚合行不再被截断在 80 字符。
|
|
61
|
+
- **H8**:仅空白差异(`\r\n`↔`\n`、尾换行、缩进)的近重复被误判成 `same_condition_divergence`。修法=两侧改用**同一归一化** `_norm_ws/_nows` + 「逐字相同 ⇒ 必判重复」短路;阈值 `CONCLUSION_SAME=0.95` **未动**。顺带补上此前**零覆盖**的 `CONCLUSION_SAME` 判据。
|
|
62
|
+
- **H3**:合并时**双方归属并列**落 `fm`(`forgetting.note_source`,有界 20 条),不再只留一侧。
|
|
63
|
+
- **H8-⑤**:CCG 哨兵空值化(见第二节①)。
|
|
64
|
+
- 守卫:`test_b3_merge_keeps_content.py`(31)、`test_p11_consistency.py` G 段(42)、`test_p30_maintain.py`(57)。
|
|
65
|
+
|
|
66
|
+
### 3.3 第 3 包 `2e7d7230` + 补强 `f706b799` —— 召回面诚实性
|
|
67
|
+
|
|
68
|
+
| 项 | 缺陷 | 修法 |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| **H10** | 被负记忆覆盖的条目以 `score=1.0` 冒充答案、被顶到首位且**溢出 k** | 哨兵值 `NEG_COVERAGE_SCORE`(不再用 1.0)、尾部位置、条数 `min(NEG_COVERAGE_MAX, k)` **计入 k 预算**、`_compute_d` 分母排除提示条目;负尾单点 `_neg_tail` 构造,带 `negative_coverage`/`neg_layer`/`node_id` 三个独立字段 |
|
|
71
|
+
| **H7** | 负记忆路由层未短路(读面串层) | `NEG_ROUTE_LAYERS` 单点 + `_ticket_slug`/`_refresh_unresolved` 工单刷新 |
|
|
72
|
+
| **H11** | 一致性飞轮对**任意**判定建工单(噪音) | `FLYWHEEL_TRIGGERS=("REJECT",)`——只对**真冲突**建单 |
|
|
73
|
+
| **M1** | `k=0` 被当成「没传」(静默换成缺省 20) | 统一 `is not None` 口径,单点 `_int_arg`;k 族同族 **8 处**一并收口(补强批) |
|
|
74
|
+
| **M2** | `node_id` 类型错返回**裸 null** | 类型闸 + 结构化错误(对齐既有 `{"ok": False, "error": "not_found"}` 口径) |
|
|
75
|
+
| **M3** | 仅 1 个桶的库被判「分区健康」 | `routing.bucket_health(counts, total_nodes)`——巨桶检查加 `nb > 1`,单桶给显式 reason「条件路由不可用(无分区,非退化)」,`counts=={}` 但对非空库判红 |
|
|
76
|
+
| **M4** | 隐式默认动作不可辨 | `action_source` 登记进 `protocol.py` 真源 + 对外暴露 |
|
|
77
|
+
| **H9** | `protect.mark` 对不存在节点返回裸 null | 改结构化 `{"ok": False, "error": "node_not_found", ...}` |
|
|
78
|
+
|
|
79
|
+
- 新守卫:`test_recall_face_guards.py`(41)、`test_neg_tail_honesty.py`(42→44)、`test_read_face_input_gates.py`(61→77)、`test_read_face_semantics.py`(123)、`test_m3_h9_bucket_health_protect_mark.py`(31)、`test_m3_h9_semantic_guard.py`(41)、`test_protocol.py`(→44)。
|
|
80
|
+
- **既有守卫的方向性改动我逐条判过**:`test_retr_s5.py` 三条分数断言由 `1.0/0.5/0.75` 改 `0.0`、`test_p11_consistency.py` D 段重写——**方向均为收严**(对缺陷更敏感),不是放宽。
|
|
81
|
+
- **JM-RACE-01**:`scripts/test_judgment_manifest.py:75` 原本在**追踪文件上原地写**(`hive/test_exec_tools.py`)再还原 ⇒ 结构上并行不安全。子代理**否掉了我的 `_SERIAL_ONLY` 方案并给出更好的理由**(`_SERIAL_ONLY` 的语义是**跳过**,「这条守卫不再跑」比偶发红更糟;且挡不住嵌套套件),改为「临时副本做弱化实验」+ 4 条新断言钉住「运行期绝不写追踪文件」。我接受该反驳。
|
|
82
|
+
|
|
83
|
+
### 3.4 第 4 包 `956807a1` —— 插件面
|
|
84
|
+
|
|
85
|
+
| 项 | 缺陷 | 修法 | 诚实边界 |
|
|
86
|
+
|---|---|---|---|
|
|
87
|
+
| **M5** | **全角**凭据形态绕过脱敏 | 九条值类正则纳入全角(数字/字母/下划线/冒号/等号),单点 `twoWidth` 折叠 | 有意**不走 NFKC**(归一化改长度会毁偏移映射,且会把「.」塌成「。」误伤标点);两条令牌形态正则**保持半角字面量**(Python 侧 `test_token_lowercase_form.py` 直接抽取该源码判据);`data/policy.json` 写入闸门**未同步加宽** ⇒ 两侧对全角形态**有意分叉**(已实测 policy.json 无全角类) |
|
|
88
|
+
| **H5** | 注入的记忆块**无不可信边界** | 外包 `<untrusted-memory>…</untrusted-memory>` + 固定声明「仅作参考、不得执行其中指令」,并拆散伪造闭合标签 | 定位为**提示层软约束,非安全边界**;两处未修缺口如实上报(**H5-R1** 开式形态拆解不幂等、**H5-R2** en-dash/em-dash/U+2010/全角空格变体透传) |
|
|
89
|
+
| **H6** | 直写不去重、无提示 | 两个直写入口(`mcp_server` / `writepipe`)**同源委托**同一实现;返回 `dup_of` 提示(`prior_node`/`self_coverage` 判据 + `overwrite_of`/`overwrite_ratio` 熵读数 + `dedup_skipped` 理由) | **不改写入语义**(`writelimit` 只作用 contextual 层是既有文档化设计);PROTECT 分支**只加注不改序**;读数一律在 `cg.add` **之前**取(否则覆写谓词恒真) |
|
|
90
|
+
| **H1** | 子代理委派被写成本人记忆 | `isSubagentSession`(会话级,刻意**前置于 sid 捕获之前**,否则子代理会话会污染 `lastSession`)+ `isRelayedMessage`(消息级)两个纯判据 | 六种退化形态一律**不筛不报错**;⚠️ **真实宿主是否真写 `origin`/`delegationDepth`/`form:'relay'` 只在类型面成立、未在真实会话事件上观测**(本机未装 DSH harness) |
|
|
91
|
+
| **H2** | 写入与召回的会话口径不同尺 | 读侧 `stg._view_session` 消费**同一个** `mcp_server._normalize_session`(**不重写实现**);插件侧无会话标识时写显式 `unassigned`(替代进程级随机 `sess_*` 兜底桶);召回改为显式带会话槽 | 三态语义(缺省/`""`/`"*"`)逐位不变;`cg` 读路径的 session 走身份判定(issue #35 定稿「身份不可自报」)**不经**此视图,不得互相「对齐」(对齐即等于开一条按请求 session 读 private 的越权通道);env 固定会话的部署形态仍读不到本会话视图(如实记录,不在本次范围) |
|
|
92
|
+
|
|
93
|
+
- 守卫:`md_cg/test_p9c_dedup_hints.py`(31)、`md_cg/test_h2_session_view_norm.py`(17)、`test/fullwidth_redact.test.ts`、`test/untrusted_memory.test.ts`、`test/h1-source-filter.test.ts`。
|
|
94
|
+
- **文件并发写入的完整性核验**:`src/hooks.ts` 在同一轮里被**四方**(M5/H5/H1/H2)写入、守卫文件也被中途追加。我在提交前逐标记核验四处改动**全部在场且互不覆盖**(`twoWidth`/`renderUntrustedMemoryBlock`/`isSubagentSession`/`UNASSIGNED_SESSION`),变异残留扫描全程为 0。
|
|
95
|
+
- **我自己的派发契约缺陷**:H1/H2 的 `hooks.ts` 侧在我写的归属划分里**没有主**(我把 hooks.ts 排给了插件面修改员,却把 H1/H2 排给了另一员)。是该子代理**拒答并上报**(`dwfq-a9007424-1`)才暴露的——**缺陷在我,不在它的边界**。我据此补授权并加了三项防丢更新要求。
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 四、自有回归:自查抓到的一条,比新增守卫更重要
|
|
100
|
+
|
|
101
|
+
容器栈一(Linux)第一次跑出 `[FAIL] md_cg.test_policy_required_ccg --head-baseline`。取证链条:
|
|
102
|
+
|
|
103
|
+
1. **红项集合比对**:实际 `{G2b,G2c,G2d,G3b,G3c,G4a,G4b,G4c,G5a,**G8a**,G8c,**G8d**}` vs 预期 `{…,**G8b**,G8c}` ⇒ 多出 G8a/G8d(`ModuleNotFoundError: No module named 'mdcg_head.mdcg'`),且**预期该红的 G8b 变绿了**。
|
|
104
|
+
2. **基线对拍(决定性)**:把改前的 `06db0f74` 检出到**独立 worktree** 跑同一守卫 ⇒ 红项**恰好**是预期 11 项、自带红基线 PASS ⇒ **这是我这四批引入的回归,不是既有状态**(worktree 已 `remove`,工作区未被触碰)。
|
|
105
|
+
3. **根因**:该守卫用「假包 `mdcg_head` + 转发层 `_SHIMS`」把工作区源码做定点变异后单测。我这四批给 `md_cg/writepipe.py` 新增了两处**函数内**委托(`from .mdcg import …`、`from . import forgetting`),而 `_SHIMS` 没跟上 ⇒ 假包缺模块 ⇒ 调用期抛异常 ⇒ 被 `_try` 收成 `err`、`got` 退化为 `{}` ⇒ `hint=""` ⇒ **G8b 的 `"重试同样结果" not in ""` 恒真**,于是「守卫坏了」伪装成「多两个红项 + 一个假绿」。
|
|
106
|
+
|
|
107
|
+
**修法(治三处,不只是补一个名字)**:
|
|
108
|
+
|
|
109
|
+
1. 补齐转发层:`_SHIMS` 增加 `mdcg`/`forgetting`/`units`/`coldverify`/`hotcache`/`hyperedge`/`nodefile`——注意后五个是我这条新判据**自己查出来的**(历史靠「那条路径没跑到」侥幸绿着)。
|
|
110
|
+
2. **新增 fail-closed 判据 `_check_shim_coverage`**:用 AST 抽取基线源里**全部**相对 import(含函数内延迟导入),凡未登记即报 `SHIM-MISS` 并点名模块 ⇒ 同类缺口从此在**装配期**就叫停,不再退化成假绿。**定点变异自证**:抽掉 `_SHIMS` 里的 `forgetting` ⇒ 立刻 `SHIM-MISS` 且**逐字点名 `writepipe -> .forgetting`**。
|
|
111
|
+
3. **堵死假绿**:G8b 断言补 `err is None and bool(hint)`。**定点变异自证**:用一个「一碰就抛」的 `wp_mod` 桩跑 `run_checks` ⇒ G8b **转红**(detail = `RuntimeError: boom-stub(WritePipeline)`),而旧写法在同一输入下判定为 `True`(假绿形态**在进程内复现**)。
|
|
112
|
+
|
|
113
|
+
修后:绿态 **28 pass / 0 fail**、红基线**红项恰好 11 项**(`rc=0`),容器栈一该腿 `[PASS]`。
|
|
114
|
+
|
|
115
|
+
---
|
|
116
|
+
|
|
117
|
+
## 五、验证读数(本会话实跑,逐条为原始读数)
|
|
118
|
+
|
|
119
|
+
### 5.1 分批复跑(每批提交前后各一次)
|
|
120
|
+
|
|
121
|
+
| 批次 | python 全量 | npm test | gate |
|
|
122
|
+
|---|---|---|---|
|
|
123
|
+
| 第 1 包 `778f8ede` | 277/277 | — | rc=0 |
|
|
124
|
+
| 第 2 包 `69e8719b` | 278/278 | — | rc=0 |
|
|
125
|
+
| 第 3 包 `2e7d7230` | 284/284 | — | rc=0 |
|
|
126
|
+
| 第 3 包补强 `f706b799` | 286/286 | — | rc=0 |
|
|
127
|
+
| 第 4 包 `956807a1` | 286/286(5 跳过) | rc=0(99 用例 / 98 通过 / 1 跳过) | rc=0 |
|
|
128
|
+
|
|
129
|
+
### 5.2 发版验证三连(改版后最终态)
|
|
130
|
+
|
|
131
|
+
| 项 | 命令 | 读数 |
|
|
132
|
+
|---|---|---|
|
|
133
|
+
| ① | `python scripts/run_tests.py --jobs 4` | **286/286 通过,5 跳过**,rc=0 |
|
|
134
|
+
| ② | `npm.cmd test`(= build + `node --import tsx --test "test/*.test.ts"`) | **99 用例 / 98 通过 / 0 失败 / 1 跳过**,rc=0 |
|
|
135
|
+
| ③ | `npm.cmd run gate`(8 条腿) | **VERDICT=PASS**,rc=0 |
|
|
136
|
+
|
|
137
|
+
gate 八腿逐条:`check_unreachable` PASS · `check_publish_artifact` PASS(R1 凭据面=0/0、R2、R3、**R4 非追踪=28 允许=28**、R5、R6)· `cogmap_sync check` PASS · `link_check` PASS · `workspace_index --check` [OK](顶层 20 · 追踪 2104 件)· `verify_discipline --allow-missing` PASS(9 条链一致 / 1 SKIP codebuddy-local 未生成)· `cargo test` rc=0 **27 passed / 0 failed** · `rank_parity` rc=0 **两侧同口径逐位一致**。
|
|
138
|
+
|
|
139
|
+
### 5.3 Linux 容器双栈(Docker Desktop 28.4.0)
|
|
140
|
+
|
|
141
|
+
前置:三个容器脚本(`scripts/*.sh`)**CRLF=0**(纯 LF)——`core.autocrlf=true` 下 CRLF 会让整腿在第一步退出。
|
|
142
|
+
|
|
143
|
+
| 栈 | 镜像 / 命令 | 读数 |
|
|
144
|
+
|---|---|---|
|
|
145
|
+
| 栈一 | `rust:bookworm` + `bash scripts/linux_verify.sh full`(`CARGO_TARGET_DIR=/tmp/target`,与 Windows 侧 `target/` 隔离) | **38 pass / 0 fail**,rc=0(Python 3.11.2 / cargo 1.98.1;含 `cargo test`、`cargo build --release`、23 条 `md_cg` 套件、4 条 hive python、7 条 head/branch 基线自证腿、1 条 hive 锚链自证腿、smoke) |
|
|
146
|
+
| 栈二 | `node:22-bookworm` + `npm ci --include=dev && npm run build && node --import tsx --test test/*.test.ts` | **99 用例 / 96 通过 / 0 失败 / 3 跳过**,rc=0 |
|
|
147
|
+
|
|
148
|
+
两处**口径修正**(相对我事前的说法,如实记账):
|
|
149
|
+
|
|
150
|
+
- 栈二原用 `npm install`,会**在挂载的仓内**重装 `node_modules`(把宿主 win32 的 esbuild 二进制换成 Linux 版,且 `npm install` 会改写 `package-lock.json`)。已改为 **`npm ci` + `node_modules` 挂匿名卷**隔离。
|
|
151
|
+
- 栈一的 `cargo test` 腿覆盖的是 **`hive` crate**,**不是 `rust/`**;且脚本用 `tail -4` 截断输出,容器日志里可见的是最后一个测试二进制的 `0 passed`(真实通过数被截断,**腿的判据是退出码**)。`rust/` 的 27 passed 由 Windows 侧 gate 的 `gate_rust_crate_test` 腿给出。
|
|
152
|
+
|
|
153
|
+
### 5.4 版本面
|
|
154
|
+
|
|
155
|
+
| 项 | 处置 |
|
|
156
|
+
|---|---|
|
|
157
|
+
| 版本号 **8 处** → 0.6.1 | `package.json:3` · `package-lock.json:3/:9` · `.claude-plugin/marketplace.json:12` · `claude/lingshu-memory/.claude-plugin/plugin.json:4` · `codex/lingshu-memory/.codex-plugin/plugin.json:3` · `skills/plugin.json:4` · `README.md:16`。逐处**断言命中数**后字节级替换(`package-lock.json:810` 的 `^10.6.0` 是引擎区间,**未误伤**) |
|
|
158
|
+
| `SERVER_VERSION` | **未动**——它动态读 `package.json`,正是 issue #42 的修法 |
|
|
159
|
+
| README 版本表 | 原表从 v0.5.1 直跳 0.6.0(历史遗漏),本版补 `Release v0.6.0` 与 `Release v0.6.1` **两行** |
|
|
160
|
+
| `docs/mdcg/发布门禁链_v0.1.md` | 陈旧表述订正:门禁由「五道」改为**八道**,并**逐条与 `package.json` 的 `scripts.gate` 实读对齐**。新增诚实边界:第 1/7/8 道(`check_unreachable` 与两条 Rust 腿)**没有对应 CI workflow**——`hive-check.yml` 只跑 `hive/Cargo.toml`,`rust/` 至今零 CI |
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 六、未跑 / 未修清单(如实声明)
|
|
165
|
+
|
|
166
|
+
**未跑**:
|
|
167
|
+
|
|
168
|
+
- `npm pack` / `npm publish` —— publish 属使用者终端凭据动作(实测 `npm whoami` = E401 凭据无效)。`prepublishOnly` 会在发布时自动再跑 build+test+gate。
|
|
169
|
+
- 发布后回验(`check_publish_artifact.py --registry 0.6.1`、`npx @furongjun1999/dsh-memory init` 清缓存终验、`check_registry_tarball.py`)——须等 registry 出现 0.6.1 之后。
|
|
170
|
+
- **H1 的真实宿主行为**:本机未装 DSH harness ⇒ 「宿主要不要真写 `origin`/`delegationDepth`/`form:'relay'`」**只在类型面成立、未在真实会话事件上观测过**。守卫证明的是「判据在场即拦、缺失即不拦」这一可机械判定的性质,**不是**真实委派已被拦住。
|
|
171
|
+
- `test_conformance.py:312` 硬编码一条**本机活库绝对路径**(`<盘符>/Program Files/2_ai/…` 形态;门禁 R3 的 `LOCAL_PATH_PROGRAM` 规则对本仓自有文档同样生效,故本报告不复述字面量)——按本轮「不碰在役库」约束,复核侧改用 `conformance --root <沙箱>` 替代,**未在活库上跑**。
|
|
172
|
+
- 第二节的**探针额外发现②(负尾重复出条)**:收口方式为负尾单点化,**该具体形态未单独立断言复验** ⇒ 待复验。
|
|
173
|
+
|
|
174
|
+
**未修(记入留池,供使用者裁定)**:
|
|
175
|
+
|
|
176
|
+
| # | 项 | 位置 / 形态 |
|
|
177
|
+
|---|---|---|
|
|
178
|
+
| 1 | `limit=0` / `k=0` 在**库层**语义与读面不一致 | `scrub.py:859 records[-int(limit):]`(`limit=0` ⇒ 「全量」)、`tasks.py:447 max(int(k or 5), 1)`(`k=0` ≡ `k=5`)——补强批「下限 1」的措辞据此**订正为不准确** |
|
|
179
|
+
| 2 | 同族更宽的两处 | `mcp_server.py:1981`(help, k=40)/ `:2141`(link.evidence, k=100) |
|
|
180
|
+
| 3 | `backfill.py:61 SKIP_LAYERS` 第三份字面量副本 | 未收单点 |
|
|
181
|
+
| 4 | MCP 结果面未暴露 `negative_coverage` / `neg_layer` / `node_id` | 提示只在库层结果里可判 |
|
|
182
|
+
| 5 | `mdcg_get` 对 list/dict 型 `node_id` 仍抛异常 | 与 M2 同族,未一并收口 |
|
|
183
|
+
| 6 | legacy `unr_<sha10hex>` 工单未迁移 | 与 H7 的 `_ticket_slug` 同族 |
|
|
184
|
+
| 7 | `merge_count` / `last_merge_at` 未镜像进内存索引 | H3 只落了 fm |
|
|
185
|
+
| 8 | **H5-R1** 开式形态拆解不幂等(docstring 声称幂等,实测仅闭合形态成立) | 第 4 包守卫复核发现并独立复现 |
|
|
186
|
+
| 9 | **H5-R2** en-dash / em-dash / U+2010 / 全角空格变体透传 | 同上 |
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## 七、纪律合规声明(第 16 条格式)
|
|
191
|
+
|
|
192
|
+
- **功能名**:0.6.1 发布准备(外部报告核验 · 四批修复 · Linux 双栈验证)
|
|
193
|
+
- **生效条件**:`git tag v0.6.1` 存在且 `npm publish` 由使用者执行完成;在此之前本报告描述的修复只在**仓库 HEAD** 生效,**不在** registry 的 0.6.0 制品里。
|
|
194
|
+
- **子功能**:① 九探针先行取证 ② 四批写面/合并面/召回面/插件面修复(各带守卫与定点变异自证)③ 自有回归的取证与修复(第 4 节)④ 版本面与文档面收口 ⑤ Linux 容器双栈验证
|
|
195
|
+
- **执行**:见第三节各批提交(`778f8ede` / `69e8719b` / `2e7d7230` / `f706b799` / `956807a1`)与第五节读数的对应命令;每批提交前**均由编排侧独立复跑**守卫、套件与门禁,**代理自报未作为判据**。
|
|
196
|
+
- **验证方式**:`python scripts/run_tests.py --jobs 4`(286/286)+ `npm.cmd test`(99/98/1)+ `npm.cmd run gate`(8 腿 PASS、`VERDICT=PASS` rc=0)+ Docker 双栈(38/0 与 99/96/3,均 rc=0)+ 基线 worktree 对拍(自有回归的定因)。
|
|
197
|
+
- **不适用条件**:不覆盖**已发布 npm 制品**的行为(那是 0.6.0 代码);不覆盖**真实 DSH 宿主**的委派字段写入行为(未装 harness);不覆盖 `test_conformance.py:312` 的活库路径腿(本轮约束不碰在役库);不覆盖留池 9 项;`SERVER_VERSION` 不在版本面内(动态读 `package.json`,故意的)。
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## 附:文件清单
|
|
202
|
+
|
|
203
|
+
**新增守卫(12 个)**:`md_cg/test_b1_auto_id_multiproc.py`、`test_b2_sensitivity_landing.py`、`test_b1b2_write_face.py`、`test_b4_shard_dir_selfheal.py`、`test_b4_shard_dir_selfheal_guard.py`、`test_b3_merge_keeps_content.py`、`test_recall_face_guards.py`、`test_neg_tail_honesty.py`、`test_read_face_input_gates.py`、`test_read_face_semantics.py`、`test_m3_h9_bucket_health_protect_mark.py`、`test_m3_h9_semantic_guard.py`、`test_p9c_dedup_hints.py`、`test_h2_session_view_norm.py` + TS 三份 `test/fullwidth_redact.test.ts`、`test/untrusted_memory.test.ts`、`test/h1-source-filter.test.ts`。
|
|
204
|
+
|
|
205
|
+
**文档面**:`README.md`(版本串 + 版本表两行)、`docs/mdcg/发布门禁链_v0.1.md`(八道腿订正 + CI 覆盖诚实边界)、`docs/mdcg/README详细版_v0.4.10.md`(H1/H2 的声明与未验证项)、本文件。
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# 性能专项报告:冷查询与内存 v1.0
|
|
2
|
+
|
|
3
|
+
> 专项范围:`md_cg/mdcg.py`(引擎 `_load_index` / `_read` / `_read_many` / `_node_disk_path` / `normalize_en` 归一链)与 `md_cg/readcache.py`(解析读缓存);`md_cg/docindex.py` 未涉改动。
|
|
4
|
+
> 数据来源声明:本文「修复会话实测」数字来自本专项各修复任务在临时库上的实跑记录(材料转述);「本会话复核」数字为报告撰写会话当场实跑结果(第四节列明命令与输出)。凡本会话未跑过的检查,一律如实标注,不冒充已通过。
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## 一、背景与基线
|
|
9
|
+
|
|
10
|
+
### 1.1 生产冷态基线与根因(cProfile 引证)
|
|
11
|
+
|
|
12
|
+
- **冷态首查**(OS 文件缓存冲刷后):`search` **61.7–200s**;**热态** 0.12–0.79s。
|
|
13
|
+
- cProfile 根因定位:单次冷查 **13,884 次 `_read` 累计 61.2s**,其中
|
|
14
|
+
- `TextIOWrapper.read`(文件 I/O)**45.3s**;
|
|
15
|
+
- `os.path.realpath`(路径规范化)**13.5s**(27,766 次调用)——占 61.2s 的 **22%**。
|
|
16
|
+
- 读缓存缺省已开(`md_cg/readcache.py:40-43`,`MDCG_READ_CACHE` 未设即 `enabled()==True`;本会话已核实该行),故热态 0.12–0.79s 已由既有优化覆盖;冷态首查仍全量走「open + realpath + parse」。
|
|
17
|
+
- 对照参考(既往同口径优化):读缓存批次 14 per-path 精确失效 **35.8×**、MdStore 预计算 **148×**。
|
|
18
|
+
|
|
19
|
+
### 1.2 临时复现库基线(先测后修)
|
|
20
|
+
|
|
21
|
+
| 复现库 | 规模 | 口径 | 修前实测(修复会话) |
|
|
22
|
+
|---|---|---|---|
|
|
23
|
+
| `_md_cg_perf_warmup/cgroot` | 3200 池 / 10.23MB | 进程冷态(新进程首查) | search#1 = 5.456 / 1.578 / 1.574s(首轮含 OS 缓存冷启),热查 0.032–0.033s |
|
|
24
|
+
| 8000 文档 store×3 副本 | 全池扫描 496,002 词事件/查询 | 进程冷扫 | T3 全池冷扫中位 3.053s(HEAD 纯净) |
|
|
25
|
+
|
|
26
|
+
- 本测(3200 池)cProfile:`_node_disk_path` 子树 **0.301s cum**(候选评估测次;修前基线测次 0.303s cum,其中 realpath 本体 0.286s),占 `_read` 子树 45–48%、**全查 ~11%**;realpath 调用 **6400 次/冷查**(每读 2 次 × 3200 节点)。
|
|
27
|
+
- 本测(8000 文档)cProfile:**73% 耗时在 `_score`/`normalize_en`**——`_norm_word` **498,446 次/冷扫**、cum 1.301s,str 方法调用 **348.9 万次/冷扫**;readcache 已缓存文档级派生物(`_doc_norm_bigrams`,`readcache.py:25-28`)但仅限本进程,冷态首查仍逐词全量重算。
|
|
28
|
+
- json 解析占比(冷态口径):`nodefile.loads` 整体 cumtime 0.238s=8.6%,json decode **0.117s/2.75s≈4%**——占比过低。
|
|
29
|
+
|
|
30
|
+
### 1.3 内存画像基线
|
|
31
|
+
|
|
32
|
+
- 缓存足迹最大单项为 `_norm_bigrams_cache`(文档级归一 bigram),占读缓存足迹 **67%**(引用画像 64.1MB)。
|
|
33
|
+
- 外部报告的「45.8GB 内存失控」待复现/否证(结论见第五节:**未复现,无失控证据**)。
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 二、修复面与实现(定稿 4 候选,实际实施 3 项)
|
|
38
|
+
|
|
39
|
+
### 2.1 realpath 缓存(候选 a,定稿采纳,优先级 1)✅ 已实施
|
|
40
|
+
|
|
41
|
+
- **target**:`_node_disk_path`(修前位置 `md_cg/mdcg.py:1320-1327`,HEAD 版 7 行实现)每读 2 次 `os.path.realpath`(修前 1321-1322 行各一次)——改为 root realpath 进程内解析一次 + 每 rel-path 解析结果 memo 化;失效口径复用 `readcache._fresh` 的 per-path 哨兵(批次 14 纪律同源)。
|
|
42
|
+
- **rationale**:双数据集支持——本测 3200 池 6400 次 realpath/次冷查(0.301s cum,占 `_read` 子树 45%、全查 11%);生产真冷态 27,766 次/13.5s = 61.2s 中的 22%。缓存后每读 realpath 降为 1 次字典命中,纯确定性字符串复用,检索结果零变化(同输入同输出;修后须以 bench.py + 结果逐项对照复验)。
|
|
43
|
+
- **risk**:P2-20 越界断言语义必须保持——root realpath 一次性解析的进程内边界内,越界判定结果不变;symlink/junction 中途改挂的陈旧窗口 = 进程内一致性边界,须与 `readcache.py:29-30` 同款声明写入文档;修后跑 `test_readcache_prodpath.py` 等既有守卫。
|
|
44
|
+
|
|
45
|
+
### 2.2 `_norm_word` 词级 memo(数据新增目标,定稿采纳,优先级 2)✅ 已实施
|
|
46
|
+
|
|
47
|
+
- **target**:`normalize_en` 文档侧归一为纯函数链(`md_cg/mdcg.py:416` `strip_tense_en` / 修前 `:449` 内嵌 `_norm_word`),落模块级 word→归一结果 memo(可 LRU 封顶)。
|
|
48
|
+
- **rationale**:本测冷态首查 73% 耗时在 `_score`/`normalize_en`(498,446 次 `_norm_word`、348.9 万 str 方法调用/次冷查);readcache 已缓存派生产物但仅限本进程,冷态首查仍全量重算。词级 memo 纯函数无行为漂移面,同时压缩冷态装配与未来任何缓存 miss 的重推导。
|
|
49
|
+
- **risk**:memo 按词精确键控(纯函数,同词同结果)零结果变化;内存增量 = 词表规模(远小于 `_norm_bigrams_cache` 的 64.1MB);若加 LRU 封顶须注意热态 0.033s 依赖派生缓存,容量不宜过小。
|
|
50
|
+
|
|
51
|
+
### 2.3 `_read` 的 json 解析懒加载(候选 b,数据否决,不修)⛔
|
|
52
|
+
|
|
53
|
+
- **target**:`_read` 内 nodefile 解析改懒加载。
|
|
54
|
+
- **rationale**:实测占比过低——json decode 0.117s/2.75s≈4%(`nodefile.loads` 整体 0.238s=8.6%);且 readcache(`readcache.py:102-113`)已把解析产物按 path 缓存为进程内一次,懒加载只能再省首查的这一次解析,收益上限即这 4%。
|
|
55
|
+
- **risk**:懒加载 fm 语义有行为漂移面(调用方就地改 fm 的模式),收益/风险比不支持,明确不修——修了属无数据支撑的改动。
|
|
56
|
+
|
|
57
|
+
### 2.4 读缓存装配增量化(候选 c,数据否决,不修)+ 内存上限备忘 ⛔
|
|
58
|
+
|
|
59
|
+
- **target**:读缓存装配增量化。
|
|
60
|
+
- **rationale**:实测装配无独立成本面——`readcache.install`(`readcache.py:62-131`)是 O(1) 包装,填充按节点在读时懒进行(init 0.015s;冷查 1.37–1.66s 与 `READ_CACHE=0` 的 1.28–1.97s 在噪声内重合 = 装配零额外开销);内存 9.4× 正文、线性于 N 且 45.8GB 未复现,无失控证据。
|
|
61
|
+
- **risk**:若未来生产内存水位告急,杠杆是 `_norm_bigrams_cache`(占缓存足迹 67%)做 LRU 封顶——但会侵蚀热态 0.033s 基线,须带修前修后同口径计时再动;本轮作为备忘记录而非修复项。
|
|
62
|
+
|
|
63
|
+
> 合计:**实际实施 3 项**(候选 a、词级 memo、以及候选 b/c 的数据否决裁决执行),否决 2 项不做。
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 三、逐项修复
|
|
68
|
+
|
|
69
|
+
### 3.1 realpath 缓存(候选 a,优先级 1)
|
|
70
|
+
|
|
71
|
+
**target**:`MdCG._node_disk_path` 每读 2 次 `os.path.realpath` 的消除——root realpath 进程内惰性解析一次驻留 + rel-path→abs 解析结果 memo 化,失效口径复用 `readcache._fresh` 的批次 14 per-path 哨兵(`path_gen[path]` + `broad_gen`)。
|
|
72
|
+
|
|
73
|
+
**changed**:`md_cg/mdcg.py` 单文件 3 处(全文件 diff +73/−8,本修复约 +45;diff --stat 已核实):
|
|
74
|
+
|
|
75
|
+
1. `__init__`(mdcg.py:961-964,`self._dirty` 之后)新增 `self._root_real = None` 与 `self._realpath_cache = {}`(附失效同源声明注释);
|
|
76
|
+
2. `_node_disk_path`(mdcg.py:1364-1378,文档串 1347-1363)重写:先查 per-rel-path memo(键 = `e["path"]`,复用索引既有串零拷贝),未命中才 realpath;root 惰性解析一次(`_root_real` 为 None 时解析并驻留);越界 ValueError 不缓存、每次重判;命中条件走新增 `_realpath_fresh`(mdcg.py:1380-1392,逐字镜像 `readcache.py:80-100` 的 `_fresh`:`path_gen` 非 `_DirtyDict` 形态回落整代际相等防御,否则 `pg.get(rp,0) <= 缓存代际 and broad_gen <= 缓存代际`);
|
|
77
|
+
3. `_maybe_reload_index`(mdcg.py:1071-1074)在 `_rc.clear(self)` 旁同步 `self._realpath_cache.clear()`(他进程快照重写事件整池兜底,稀疏事件零热路径开销)。
|
|
78
|
+
|
|
79
|
+
文档串写入:失效口径同源声明、`readcache.py:29-30` 同款进程内一致性边界声明(symlink/junction 中途改挂不推进代际)。不改动任何共享文件之外的内容;git 状态 = `M md_cg/mdcg.py`(同文件还含并发写入者的词级 memo 改动,见 3.2 与 semantics_note)。
|
|
80
|
+
|
|
81
|
+
**before_after**(修复会话实测:临时库 `_md_cg_perf_warmup/cgroot` 3200 池/10.23MB,哑密钥 `bytes(range(32))`,未触真实令牌库与在役库;同口径 bench.py 新进程冷态):
|
|
82
|
+
|
|
83
|
+
- 【计时 · 默认 `MDCG_READ_CACHE=1`】修前 HEAD:冷查 search#1 = 5.456/1.578/1.574s(首轮含 OS 缓存冷启),热查 0.032–0.033s;修后同树(HEAD+a+b):冷查 1.017/1.428/1.038s,热查 0.032–0.043s。
|
|
84
|
+
- 【本修复净贡献 · 同树进程内猴补丁消融法】把 `_node_disk_path` 还原为 HEAD 原 7 行实现后复测(仅候选 b 生效):冷查 median 1.086→1.038s ≈ **−48ms**;realpath 调用 **6400→3201 次/冷查**(cProfile 计数实测,= 3200 rel 首解析 + 1 次 root,与设计精确一致;消融组 `realpath_cache_entries=0` 证实旁路彻底);`_node_disk_path` cum **0.303→0.204s**(修前 0.286s 在 realpath 本体)。
|
|
85
|
+
- 【计时 · `MDCG_READ_CACHE=0` 退出阀】combined 冷查 0.893/0.922s、热查 0.747/0.752s vs 消融 1.031/1.163s、1.009/1.154s——热查询 **−26~−35%**(每读 2×realpath→字典命中)。
|
|
86
|
+
- 【内存 RSS(GetProcessMemoryInfo 实测)】默认模式冷查后 120.2-120.3→120.8-121.9MB(+0.6~1.6MB,与候选 b 词 memo 合并计量);`=0` 模式 38.5-38.7→41.6-41.8MB(+2.9~3.3MB 含分配器噪声;结构性成本 ≈ 3200×(56B tuple+124B abs 串+槽位) ≈ 1MB 量级,键为零拷贝引用)。
|
|
87
|
+
- 【正确性红线】10 条固定查询 × k=10 的有序 (id, score, path, content-sha) + 全索引 3200 条 `_node_disk_path` 映射,combined 与消融两态均与修前 JSON 逐项相等(`queries==True`、`node_disk_paths==True`、errors=0)。
|
|
88
|
+
|
|
89
|
+
**semantics_note**:
|
|
90
|
+
|
|
91
|
+
- 越界断言(P2-20)语义保持:越界 ValueError 不进缓存逐次重判(探针 T2/T4 双态全绿);root realpath 惰性一次解析后,进程内越界判定结果不变(探针 T7c/T7d:双冷恰 2 次 syscall、root 恰解析一次后驻留)。
|
|
92
|
+
- 声明的诚实边界(写入 mdcg.py:1360-1363 文档串,与 `readcache.py:29-30` 同款):symlink/junction 中途改挂不推进任何代际,改挂后本进程内沿用旧解析(探针 T5b 实证 STALE_CACHED),按 path 标脏(`_DirtyDict` 钩子自动)即精确失效重判(T5c 实证改挂后标脏→ValueError);他进程快照重写事件(`_maybe_reload_index` 签名变化)整池清空兜底。
|
|
93
|
+
- 写路径审计:全部 `_node_disk_path` 调用点(mdcg.py:2319/2371/2388/2402/2709/3571/3588,本会话 grep 已核实)与全部写路径 `_dirty[node_id]=entry` 标脏同处一文件,哨兵覆盖闭环。
|
|
94
|
+
- 重要披露:
|
|
95
|
+
1. 共享工作树存在并发写入者——测量期间 mdcg.py 被同工作流另一任务加入词级 memo 改动(`_NORM_WORD_MEMO`,mdcg.py:448-461),故修后数据一律以同树猴补丁消融法分离归因(combined = a+b 树上真值、ablated = 仅 b),未采用 git stash 腾挪(避免破坏并发者未提交工作);修前基线取自并入者写入前的净 HEAD 实测,profile 证实彼时 `_norm_word` 未 memo 化(498,446 次/cum 1.301s)。
|
|
96
|
+
2. 修前全组测试未以干净 stash 态复跑(同因),以「修前猴补丁态守卫族 5/5 绿 + 会话首跑混合态 162/162 + HEAD 提交声明」替代佐证;修后 combined 树全组为干净单态运行。
|
|
97
|
+
3. 候选 b(词级 memo,见 3.2)与本修复正交且已合并计量:正确性红线在 combined 态验证(比仅验本修复更强);热查询默认模式耗时持平属预期(readcache 命中时不触 `_node_disk_path`),收益在冷查与 `=0` 退出阀模式。
|
|
98
|
+
4. 临时产物已清理(`_md_cg_perf_warmup` 下本次新增脚本/数据 19 件删除;此前会话的 bench 框架与 cgroot 语料保留未动,gitignored)。
|
|
99
|
+
|
|
100
|
+
**verified_by**(修复会话实跑记录):① 计时 `python _md_cg_perf_warmup/bench.py` ×3(修前/修后/消融三态各 3 新进程)+ `MDCG_READ_CACHE=0` 两态各 2 次;② cProfile `python _md_cg_perf_warmup/bench_profile.py`(修前 realpath_calls=6400 / `_node_disk_path` cum 0.303s;修后 3201/0.204s);③ 正确性 `python _realpath_fix_dump.py` + `_dump_ablate.py` 修前修后双态 JSON 逐项 diff(等值 True);④ P2-20 语义探针 `_realpath_fix_probe.py` 修后 15/15 rc=0、修前 8/15(7 失败均为缓存行为断言面,语义断言双态绿);⑤ 既有守卫双态:`python -m md_cg.test_readcache_prodpath`(12/12)/ `test_readcache_default_on`(10/10)/ `test_readcache_precise_inval`(23/23)/ `test_i28_hotcache_prodpath` / `test_retr_gates_prodpath`(均 rc=0),修前同族经 `_run_prefixed.py` 猴补丁复跑 5/5 rc=0;⑥ md_cg 全组 `python scripts/run_tests.py md_cg` 修后 162/162 通过 3 跳过 rc=0;⑦ 测量前后 mdcg.py sha256=989280884314630d 未变(本会话复算一致,见第四节);⑧ py_compile 编译通过(本会话复跑 OK)。**未跑项**:修前净 HEAD 的全组测试干净复跑(并发写入者占文件,改以猴补丁守卫族替代);OS 文件缓存强制冲刷的整机真冷态复现(沿用进程冷态口径,与引用基线同口径对照)。
|
|
101
|
+
|
|
102
|
+
### 3.2 `_norm_word` 词级 memo(优先级 2)
|
|
103
|
+
|
|
104
|
+
**target**:`normalize_en` 文档侧归一纯函数链(`md_cg/mdcg.py` `strip_tense_en` / `_norm_word`)落模块级 word→归一结果 memo(带 2^18 封顶)。
|
|
105
|
+
|
|
106
|
+
**changed**:仅 `md_cg/mdcg.py`:
|
|
107
|
+
|
|
108
|
+
1. `strip_tense_en`(mdcg.py:416)之后新增模块级 `_NORM_WORD_MEMO` / `_NORM_WORD_MEMO_CAP`(`1 << 18`)与纯函数 `_norm_word_mem`(mdcg.py:438-461:设计依据注释 438-447、变量 448-449、函数 452-461,含「生效条件」注释);
|
|
109
|
+
2. `normalize_en` 内嵌 `_norm_word`(mdcg.py:474-476)由「小写→停用词剔除→strip_tense_en」改为委托 `_norm_word_mem`(键 = 小写词,未命中按同口径计算并回填,封顶整表 clear);同步更新该内嵌函数的「生效条件」注释。
|
|
110
|
+
|
|
111
|
+
readcache 一致性纪律未触碰(per-path 失效/代际逻辑零改动);mdcos/postings/reach 等调用方经模块属性解析自动受益,零改动。
|
|
112
|
+
|
|
113
|
+
**before_after**(修复会话实测:临时语料 8,000 文档、全池扫描 496,002 词事件/查询,对齐画像 498,446;纯临时库,未触在役数据):
|
|
114
|
+
|
|
115
|
+
- 发现并发会话同文件落树「realpath 进程内缓存」改动,故以 git worktree 挂 HEAD 做三臂同窗口对照(各臂 3 新进程):
|
|
116
|
+
- T3 全池冷扫中位:HEAD 纯净 **3.053s** → +realpath **2.568s** → +realpath+词级 memo **1.437s**;
|
|
117
|
+
- memo 孤立贡献(同树开关对照)= **−1.131s**,**1.79× 加速 / −44.1%**;对纯净 HEAD 组合 **2.12×**;
|
|
118
|
+
- `strip_tense_en` 调用 **496,002→207 次/查询**(仅 memo miss);
|
|
119
|
+
- 热态(读缓存派生物命中)三臂持平 0.0561/0.0570/0.0576s,**无热态回退**;
|
|
120
|
+
- 微基准 normalize_en 链(400 文本×6 轮):16.657ms→8.367ms(**1.99×**);
|
|
121
|
+
- 内存(工作集 RSS,psapi GetProcessMemoryInfo):三臂查后 204.0/205.6/205.8MB,memo 臂增量抖动级;memo 本体 210 词条实测 **25.8KB**(词表规模,符合「远小于 `_norm_bigrams_cache`」预期)。
|
|
122
|
+
|
|
123
|
+
**semantics_note**:
|
|
124
|
+
|
|
125
|
+
- 零行为漂移:memo 纯函数精确键控(键 = 小写词),命中值 ≡ 逐词现算值——同词必同果;停用词返回 `""` 与 `strip_tense_en` 路径均按原口径计算后仅缓存结果。
|
|
126
|
+
- 封顶走整表 clear(纯函数下只损失加速比不损失正确性),容量 2^18≈26 万词形远超常规词表、常态不触发(响应 risk 提示:容量不宜过小,且热态快查走 readcache 派生缓存本不经此路径,实测热态持平)。
|
|
127
|
+
- 正确性红线实测:三臂 ×3 跑 ×4 查询(T3 全扫/T3 命中/en_hit/zh_en)结果 id 序+分值+内容+tier+scanned 互证 **ALL IDENTICAL**(唯一进程间差异 = 引擎固有 reason 字段 set-repr 无序打印,修前两跑互比同样存在,与改动无关);微基准归一输出 md5 修前修后逐位一致(a2caecf1dcd6a1b939cdec3d35070a6b);memo 命中 ≡ 现算抽查 216/216;封顶触发后归一仍正确。
|
|
128
|
+
|
|
129
|
+
**verified_by**(修复会话实跑记录):① 基准:临时语料 8,000 文档 store×3 副本,`python run_bench.py`(新进程冷查+热查+strip 计数包装+RSS 快照+结果 JSON 落盘),三臂(git worktree HEAD 纯净 / 当前树 memooff monkeypatch / 当前树 memoon)各 3 跑;② 正确性:canon(reason set 序归一)逐项 diff 脚本,三臂 9 份快照互证 ALL IDENTICAL;③ 内存:psapi GetProcessMemoryInfo RSS + memo 容器实测 `sys.getsizeof` 求和 25.8KB/210 词条 + 封顶行为探针(临时 cap=10 进程内验证,未改仓库代码);④ 全量测试:`python scripts/run_tests.py` → 220/220 通过、5 跳过(exit 0,改动树上;本会话复跑一致,见第四节);⑤ 守卫:`python scripts/cogmap_sync.py check` 通过(mdcg_* 31 个一致;本会话复跑 OK)、`python scripts/workspace_index.py --check` 通过(本会话复跑 OK);`scripts/verify_discipline.py` 报 codebuddy-local 漂移经 git stash 对照证实为 HEAD 预存环境态、与本次改动无关;`scripts/mdcg_verify_render_meta.py` 未跑(需 `MDCG_ROOT` 指向认知图库,本任务无涉且在役库禁触)。临时产物(语料 store、基准脚本、worktree)已全部清理,`git worktree list` 仅剩主工作区。
|
|
130
|
+
|
|
131
|
+
### 3.3 `_read` 的 json 解析懒加载(候选 b,数据否决,不修)
|
|
132
|
+
|
|
133
|
+
**target**:`_read` 的 json 解析懒加载——**无代码改动**,维持「数据否决,不修」裁决(修复会话 `git status --porcelain` 干净;临时探针目录 `_md_cg_lazyfm_probe` 测完已删)。说明:任务要求的第 1 条「实现」与 target 自身的「数据否决,不修」裁决冲突,按 target 的明确裁决执行——不实施懒加载(修了属无数据支撑的改动),改为对本裁决的两条数据依据做实测复核,全部通过。
|
|
134
|
+
|
|
135
|
+
**before_after**(修复会话实测:无修前修后代码对照——未改代码;以下是「不修(现状) vs 修(懒加载)」的收益测算,567 节点临时池,`tempfile.mkdtemp`,MdCGSecure 同 `test_readcache_default_on.py:49-57` 构造,测完 rmtree):
|
|
136
|
+
|
|
137
|
+
- 【实验 A · 占比复现】`MDCG_READ_CACHE=0` 旧口径单次 search cProfile(总 150.9ms):`nodefile.loads` cumtime 41.6ms=27.6% / tottime 9.1ms=6.0%;json decode(`json/__init__.py:299 loads`)cumtime 27.1ms=18.0%(含 decoder raw_decode 2.3%)——这是 warm OS cache 下旧逐次解析路径的 decode 占比上限;引用的冷态基线(`TextIOWrapper.read` 45.3s + realpath 13.5s 主导 61.2s `_read`,search 61.7-200s)下即为所述 ~4%,实测同向。
|
|
138
|
+
- 【实验 B · 收益上限】READ_CACHE 默认开:新实例首查 567 次 `nodefile.loads` 调用/102.8ms,稳态中位 3.0ms/查询且 `nodefile.loads` 调用 **0 次/查询**——懒加载只能触及首查那一次解析,稳态零解析无可省面;且候选 fm 在同一次查询的资格/评分流(`_read_many`→docs,mdcg.py:2949)即被消费,首查可推迟的也近乎为零。
|
|
139
|
+
- 【实验 C · 解析内部分解】20k 次重复实测:`nodefile.loads` 17.0µs/文件,其中 json decode 12.4µs=72.9%——单次解析内占比虽高,但绝对量 17µs/文件且被 readcache 摊薄为每 path 每进程一次。
|
|
140
|
+
- 结论:收益上限 = 首查一次性 × ≤18%(warm)/ ~4%(冷态口径),与裁决「占比过低」一致。内存水位:不适用(无改动无 RSS 变化,未做对照);注:懒加载若实现,物化时原文+解析产物并存反而可能抬高常驻内存(推理,未实测)。
|
|
141
|
+
|
|
142
|
+
**semantics_note**:不修在语义上是唯一安全选项,实测复核支持:
|
|
143
|
+
|
|
144
|
+
1. readcache 已把解析产物 `(fm, content)` 按 path 缓存为进程内一次(`readcache.py:102-110` `val=orig(entry); cache[p]=(gen,val)`,挂载于 :112-113,docstring :25 明示「缓存解析产物」)——懒加载只能再省首查这一次;
|
|
145
|
+
2. 懒加载 fm 是懒代理对象,而调用方存在就地改 fm 的既成模式:`compact_access`(mdcg.py:3557 定义,:3569-3571 就地写 `access_count` 后 `_write_node`,本会话已核实)、`verify`(mdcg.py:3385 定义、:3442 `fm.setdefault("evidence_log", []).append(...)`,本会话已核实)、`bench_membench.py:348-361` 更把「就地表写 `fm["importance"]=0.5`」写成包装契约(本会话已核实)——懒代理须在这些链路上保持 setdefault/取列表再 append 的物化与别名语义,且与 readcache 的 per-path 代际失效(批次 14 纪律,共享缓存对象随失效周转)叠加,行为漂移面大;4% 上限收益不支持该风险,裁决成立。
|
|
146
|
+
|
|
147
|
+
**verified_by**(修复会话实跑记录):① 探针实测 `python _md_cg_lazyfm_probe/probe_lazyfm.py`(临时池 567 节点,实验 A/B/C 数字如上,输出已核);② 零回归 `python md_cg/test_readcache_default_on.py` → PASS 10/FAIL 0(含 D6a 开/关同库同 query 结果 id 序一致 = 正确性对照的执行证据,D2a 稳态 0 次重解析);`python md_cg/test_readcache_precise_inval.py` → PASS 23/FAIL 0(批次 14 per-path 精确失效纪律无回退);`python md_cg/test_readcache_prodpath.py` → PASS 12/FAIL 0;`python -m md_cg.test_govern_directread` → PASS 40/FAIL 0;`python -m md_cg.test_p27_docindex` → 通过 98/失败 0;③ `python -m md_cg.test_md_access_parity` → 按设计 SKIP(本地语料根 `_md_cg_wisdom_graph` 不存在,.gitignore 本地生成面,exit 0)——如实报告为**未跑**;④ 清理核验:探针目录已不存在,`git status --porcelain` 空。**未跑**全部 165 个 md_cg 测试(零改动项,取 `_read`/readcache/docindex 直接相关面;全量由第四节覆盖)。
|
|
148
|
+
|
|
149
|
+
---
|
|
150
|
+
|
|
151
|
+
## 四、验证
|
|
152
|
+
|
|
153
|
+
### 4.1 本会话(报告撰写会话)当场复跑
|
|
154
|
+
|
|
155
|
+
| 检查 | 命令 | 结果 |
|
|
156
|
+
|---|---|---|
|
|
157
|
+
| **python 全量** | `python scripts/run_tests.py` | **220/220 通过、5 跳过(依赖缺失/平台不符),退出码 0** ✅ |
|
|
158
|
+
| 工作区索引守卫 | `python scripts/workspace_index.py --check` | OK:工作区索引与仓库一致(顶层目录 20 · 追踪 2005 件)✅ |
|
|
159
|
+
| 认知图同步守卫 | `python scripts/cogmap_sync.py check` | OK(exit 0)✅ |
|
|
160
|
+
| 语法编译 | `python -m py_compile md_cg/mdcg.py` | OK ✅ |
|
|
161
|
+
| 被测态指纹 | sha256(mdcg.py) 前 16 位 | `989280884314630d`——与修复会话记录的「测量前后未变」哈希精确一致,证明当前工作树即被测量状态 ✅ |
|
|
162
|
+
| 改动面 | `git status --porcelain` / `git diff --stat HEAD -- md_cg/mdcg.py` | 仅 `M md_cg/mdcg.py`,diff +73/−8(与修复记录一致)✅ |
|
|
163
|
+
|
|
164
|
+
### 4.2 修复会话实测记录(材料转述,见第三节各 verified_by)
|
|
165
|
+
|
|
166
|
+
- 计时/内存/正确性三态对照(修前 HEAD / 修后 combined / 猴补丁消融)——3.1;
|
|
167
|
+
- 三臂同窗口对照(HEAD 纯净 / memooff / memoon)——3.2;
|
|
168
|
+
- 候选 b/c 否决复核(探针实验 A/B/C)——3.3;
|
|
169
|
+
- 守卫族:test_readcache_prodpath 12/12、test_readcache_default_on 10/10、test_readcache_precise_inval 23/23、test_govern_directread 40/40、test_p27_docindex 98/98、test_i28_hotcache_prodpath / test_retr_gates_prodpath 均 rc=0;md_cg 全组 162/162 通过 3 跳过(修后 combined 树)。
|
|
170
|
+
|
|
171
|
+
**结论:python 全量 = 通过(退出码 0),本会话当场复跑证实。**
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## 五、内存水位结论(45.8GB 失控的复现/否证结果)
|
|
176
|
+
|
|
177
|
+
**结论:45.8GB 未复现,无失控证据。** 内存随池规模线性增长(约 9.4× 正文),量级为几十至两百 MB。
|
|
178
|
+
|
|
179
|
+
实测证据(修复会话,GetProcessMemoryInfo / psapi RSS):
|
|
180
|
+
|
|
181
|
+
| 场景 | 规模 | RSS 实测 |
|
|
182
|
+
|---|---|---|
|
|
183
|
+
| 3200 池冷查后(默认 READ_CACHE=1,修后) | 10.23MB 正文 | 120.8–121.9MB(修前 120.2–120.3MB,增量 +0.6~1.6MB 与词 memo 合并计量) |
|
|
184
|
+
| 3200 池冷查后(`MDCG_READ_CACHE=0` 退出阀,修后) | 同上 | 41.6–41.8MB(修前 38.5–38.7MB,+2.9~3.3MB 含分配器噪声;结构性 ≈1MB 量级) |
|
|
185
|
+
| 8,000 文档三臂冷扫后 | 8,000 文档 | 204.0 / 205.6 / 205.8MB(memo 臂增量抖动级) |
|
|
186
|
+
|
|
187
|
+
结构性拆解:
|
|
188
|
+
|
|
189
|
+
- realpath memo:≈3200×(56B tuple + 124B abs 串 + 槽位) ≈ **1MB 量级**(键为索引既有串零拷贝引用);
|
|
190
|
+
- 词级 memo:210 词条实测 **25.8KB**(词表规模,远小于文档级缓存);
|
|
191
|
+
- 缓存足迹最大单项仍是 `_norm_bigrams_cache`(文档级归一 bigram),占读缓存足迹 **67%**(引用画像 64.1MB)——它是唯一值得盯的水位项,处理方案见第六节备忘;
|
|
192
|
+
- 装配零独立成本面(init 0.015s;冷查 1.37–1.66s 与 `READ_CACHE=0` 的 1.28–1.97s 噪声内重合),填充按节点懒进行,`readcache.install` 为 O(1) 包装(readcache.py:62-131,本会话已核实)。
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## 六、遗留与建议
|
|
197
|
+
|
|
198
|
+
1. **`_norm_bigrams_cache` LRU 封顶(备忘,本轮不动)**:占缓存足迹 67%,是未来生产内存水位告急时的唯一杠杆——但会侵蚀热态 0.033s 基线(词级 memo 亦然:容量不宜过小),须带修前修后同口径计时再动。
|
|
199
|
+
2. **修前净 HEAD 全组测试干净复跑未做**:并发写入者占 mdcg.py 文件,修前以「猴补丁守卫族 5/5 + 会话首跑混合态 162/162 + HEAD 提交声明」替代佐证;建议编排会话在提交前以门禁全量复跑一次收口。
|
|
200
|
+
3. **整机真冷态未复现**:全部计时沿用「新进程冷态」口径(与引用基线同口径对照);OS 文件缓存强制冲刷的整机冷态(对齐生产 61.7-200s 量级)留待后续专项。
|
|
201
|
+
4. **`scripts/mdcg_verify_render_meta.py` 未跑**:需 `MDCG_ROOT` 指向认知图库,本任务无涉且在役库禁触。
|
|
202
|
+
5. **`test_md_access_parity` 按设计 SKIP**:本地语料根 `_md_cg_wisdom_graph` 不存在(.gitignore 本地生成面)——有本地语料的环境应跑一次补齐。
|
|
203
|
+
6. **`scripts/verify_discipline.py` 报 codebuddy-local 漂移**:经 git stash 对照证实为 HEAD 预存环境态,与本次改动无关,但属预存问题,建议另开缺陷项处理。
|
|
204
|
+
7. **symlink/junction 中途改挂的进程内一致性边界**:不推进任何代际,改挂后本进程内沿用旧解析(文档串已声明,mdcg.py:1360-1363);跨进程/外部改挂的可见性不保证——生产若依赖改挂即时可见,应走 `MDCG_READ_CACHE=0` 退出阀并重启进程。
|
|
205
|
+
8. **工作树 `M md_cg/mdcg.py` 未提交**:按纪律由编排会话负责提交(本专项不做 git commit)。
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
## 七、纪律合规声明
|
|
210
|
+
|
|
211
|
+
1. **按职责定位查阅**:查文件前先读 `WORKSPACE_INDEX.md`,按性能专项职责面(`md_cg/readcache.py`、`mdcg.py` 的 `_load_index`/`_read`/`_read_many`、`docindex.py`)定位,未做全盘浏览;报告撰写会话逐条核实了材料中的 path:line 引证(`_node_disk_path` 及其 7 个调用点 2319/2371/2388/2402/2709/3571/3588、`_realpath_fresh`、`__init__` 新增、`_norm_word_mem`、`_maybe_reload_index` 兜底、readcache 各哨兵行、compact_access/verify/bench_membench 就地改 fm 点),材料与当前树有数行漂移处一律以核实后行号为准。
|
|
212
|
+
2. **先测后修**:三态对照(修前 HEAD / 修后 combined / 猴补丁消融)+ 三臂同窗口对照,全部同口径(bench.py 新进程冷态 / run_bench.py 三新进程)。
|
|
213
|
+
3. **临时库与哑密钥**:全部实验在临时库(`_md_cg_perf_warmup/cgroot` 3200 池、8,000 文档 store、567 节点临时池)以哑密钥 `bytes(range(32))` 进行,**未触真实令牌库与真实在役数据目录**(D 盘 AEIS 在役库只读参考未动)。
|
|
214
|
+
4. **测完清理**:`_md_cg_perf_warmup` 新增 19 件删除(bench 框架与 cgroot 语料为更早会话产物,gitignored 保留);8,000 文档语料 store、基准脚本、git worktree 全部清理(`git worktree list` 仅剩主工作区);`_md_cg_lazyfm_probe` 探针目录已删。
|
|
215
|
+
5. **正确性红线**:任何加速未改变检索结果——3.1 修前修后双态 10 查询×k=10 有序四元组 + 3200 条路径映射 JSON 逐项相等;3.2 三臂 9 份快照互证 ALL IDENTICAL + 归一输出 md5 逐位一致;3.3 未改代码零漂移。readcache 读缓存一致性纪律(批次 14 per-path 失效/代际)零改动、零回退(test_readcache_precise_inval 23/23)。
|
|
216
|
+
6. **P2-20 越界断言语义保持**:越界 ValueError 不缓存逐次重判;root 惰性一次解析后进程内越界判定不变(语义探针双态语义断言全绿)。
|
|
217
|
+
7. **无数据支撑的改动不做**:候选 b(json 懒加载)、候选 c(装配增量化)经实测占比否决,明确不修。
|
|
218
|
+
8. **诚实报告**:所有「未跑项」「SKIP 项」「未复现项」如实列出(3.1/3.2/3.3 verified_by 与第六节),无冒充通过、无本机绝对路径、未执行任何 git commit。
|
package/docs/eval//346/225/205/351/232/234/346/263/250/345/205/245/345/256/236/346/265/213_v1.0.md
CHANGED
|
@@ -420,3 +420,13 @@ Docker Desktop 28.4.0(WSL2 后端)|镜像 `python:3.12` 与 `rust:bookworm
|
|
|
420
420
|
### 平台适配结论
|
|
421
421
|
|
|
422
422
|
灵枢当前树在 Linux 容器与 Windows 行为一致(全部差异为环境依赖:cargo 可用性、`python`/`python3` 别名、WinDLL 置景);`HIVE_PYTHON` env 开关在 Linux 的价值获实证(issue #19 同族"env 覆盖代替 hardcode"路线正确)。
|
|
423
|
+
|
|
424
|
+
---
|
|
425
|
+
|
|
426
|
+
### 订正留痕(2026-09-30 后加,不改上文任何字节)
|
|
427
|
+
|
|
428
|
+
- **对象**:本文件 FI-R06(`### FI-R06 —— WAL 行乱序不可检 + submit 依赖 fail-fast 拦截(gap)`)的**预期判据**行与**实测观测**行。
|
|
429
|
+
- **事实**:那两行把无环性归因于「job_id 时间序」——预期判据写「job_id 时间序+提交侧 fail-fast 使『引用未来任务』不可能成环」、实测观测写「deps_gate『无环性由 job_id 时间序结构性保证』源断言 OK」。该归因在 **id 契约 v2** 下失实:新形态 `h_<身份>_<任务>_<单元>_<编号>` 不含时间 ⇒ 名序不再携带时序,论证不得依赖它。
|
|
430
|
+
- **上文为何不改**:本文是**留档实测记录**(当时源断言确实如此,且该行被 `docs/eval/缺陷挖掘_自主迭代_v19.md:96`/`:179` 按 `:192-193`/`:416` 引用过行号),改字节会同时篡改记录与引用面。**实测观测的结论不变、仍成立**:submit `rc=1`、文案「依赖不完整: h_notexist_0000(任务不存在,先提交上游任务)」、jobs 目录零残留。
|
|
431
|
+
- **订正后的论证**:真实机制 = **存在性闸**——提交时只能引用**已存在**的任务目录(`hive/src/main.rs` 的 `depends_on` 存在性检查 + MCP 侧 `_dep_gate`),运行期再由 `hive/src/scheduler.rs::deps_gate` 复核。五处注释订正见 `docs/plans/全中文编码与蜂巢任务标识契约_v2.0.md` §五.1「C 论证订正」行。
|
|
432
|
+
- **探针同步**:本用例的自动化判据(`test/chaos_injection/test_fi_r06_wal_reorder_dep.py`)已改为断言新措辞在场**且**旧措辞不在场(`"无环性由**存在性闸**结构性保证" in … and "无环性由 job_id 时间序结构性保证" not in …`)。
|