@furongjun1999/dsh-memory 0.5.0 → 0.6.0

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.
Files changed (156) hide show
  1. package/README.md +572 -465
  2. package/docs/README.md +1 -0
  3. package/docs/eval/DSH/346/227/245/345/277/227/347/264/242/345/274/225v2_/345/217/202/350/200/203dsh-TUI_v1.0.md +248 -0
  4. package/docs/eval/DSH/346/227/245/345/277/227/347/264/242/345/274/225/346/225/210/346/236/234/351/252/214/350/257/201_v1.0.md +209 -0
  5. package/docs/eval/DSH/347/253/257/347/274/272/351/231/267/344/270/223/351/241/271_v1.0.md +254 -0
  6. package/docs/eval/P1b2_/350/257/273/351/235/242/344/273/243/351/231/205/344/277/256/345/244/215_v1.0.md +124 -0
  7. package/docs/eval/bench_lingshu_self/bench_self.py +140 -0
  8. package/docs/eval/bench_lingshu_self/self_bench_result.json +404 -0
  9. package/docs/eval/bench_lingshu_self//347/201/265/346/236/242/350/207/252/345/272/223/347/253/257/345/210/260/347/253/257/346/243/200/347/264/242/345/256/236/346/265/213_v1.0.md +38 -0
  10. package/docs/eval//344/270/215/345/217/257/351/235/240/346/200/247/350/220/275/345/234/260_P0_v1.0.md +185 -0
  11. package/docs/eval//345/217/221/345/270/20306_/344/270/200/351/224/256/351/205/215/347/275/256/344/270/216DSH0172_v1.0.md +171 -0
  12. package/docs/eval//346/225/205/351/232/234/346/263/250/345/205/245/345/256/236/346/265/213_v1.0.md +422 -0
  13. package/docs/eval//347/253/257/345/210/260/347/253/257LoCoMoQA/345/220/214/345/217/243/345/276/204/345/257/271/347/205/247_v1.0.md +100 -0
  14. package/docs/eval//347/253/257/345/210/260/347/253/257/345/271/262/346/211/260/346/261/240/350/257/204/346/265/213_/347/241/256/345/256/232/346/200/247/350/243/201/345/206/263vsLLM_judge_v1.1.md +197 -0
  15. 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_v1.md +156 -0
  16. 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_v10.md +210 -0
  17. 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_v11.md +227 -0
  18. 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_v12.md +203 -0
  19. 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_v13.md +233 -0
  20. 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_v14.md +191 -0
  21. 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_v15.md +213 -0
  22. 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_v16.md +214 -0
  23. 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_v17.md +199 -0
  24. 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_v18.md +183 -0
  25. 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_v19.md +207 -0
  26. 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_v2.md +156 -0
  27. 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_v3.md +152 -0
  28. 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_v4.md +128 -0
  29. 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_v5.md +114 -0
  30. 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_v6.md +192 -0
  31. 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_v7.md +187 -0
  32. 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_v8.md +207 -0
  33. 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_v9.md +203 -0
  34. package/docs/hive//345/256/211/345/205/250/345/256/241/350/256/241/345/256/236/351/224/232_v0.1.md +202 -0
  35. package/docs/hive//350/234/202/345/267/242/345/217/214/345/256/236/344/276/213/344/272/222/351/252/214_/350/256/276/350/256/241/345/256/232/347/250/277.md +19 -3
  36. package/docs/images/lingshu-moonlight-covenant-poster-preview.jpg +0 -0
  37. package/docs/images/lingshu-moonlight-covenant-poster.png +0 -0
  38. 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
  39. package/docs/theory//344/270/215/345/217/257/351/235/240/345/256/232/347/220/206/344/270/216/345/244/261/346/225/210/344/274/230/345/205/210/346/241/206/346/236/266_v0.3.md +365 -0
  40. package/docs//344/270/215/345/217/257/351/235/240/346/200/247/347/220/206/350/256/272_v0.1.md +343 -0
  41. package/dsh/cordis-patch-profile-web.example.yml +35 -0
  42. package/lib/bridge.d.ts +9 -0
  43. package/lib/bridge.js +35 -0
  44. package/lib/cli.d.ts +3 -0
  45. package/lib/cli.js +66 -0
  46. package/lib/index.js +7 -1
  47. package/lib/init.d.ts +88 -0
  48. package/lib/init.js +287 -0
  49. package/lib/lib/roleplay_web.js +530 -443
  50. package/lib/lib/token_store.d.ts +7 -1
  51. package/lib/lib/token_store.js +12 -3
  52. package/md_cg/audit.py +12 -1
  53. package/md_cg/backfill.py +16 -15
  54. package/md_cg/backfill_bucket_zh.py +35 -0
  55. package/md_cg/bench_e2e_judge.py +532 -0
  56. package/md_cg/bench_e2e_locomo_qa.py +368 -0
  57. package/md_cg/bench_e2e_qa.py +256 -0
  58. package/md_cg/branches.py +18 -2
  59. package/md_cg/ccgc.py +3 -2
  60. package/md_cg/chain.py +19 -4
  61. package/md_cg/consolidate.py +7 -6
  62. package/md_cg/crosscheck.py +4 -3
  63. package/md_cg/crypto.py +439 -437
  64. package/md_cg/datapath.py +395 -335
  65. package/md_cg/evidence.py +8 -3
  66. package/md_cg/export.py +3 -1
  67. package/md_cg/forgetting.py +2 -2
  68. package/md_cg/fsutil.py +48 -0
  69. package/md_cg/hotcache.py +255 -238
  70. package/md_cg/interop.py +161 -22
  71. package/md_cg/judgment_manifest.py +177 -0
  72. package/md_cg/links.py +655 -622
  73. package/md_cg/mcp_server.py +282 -31
  74. package/md_cg/mdcg.py +702 -126
  75. package/md_cg/mdcos.py +454 -68
  76. package/md_cg/mreview/govern.py +5 -4
  77. package/md_cg/postings.py +4 -2
  78. package/md_cg/readcache.py +76 -18
  79. package/md_cg/reconcile.py +228 -0
  80. package/md_cg/review_cli.py +215 -0
  81. package/md_cg/routing.py +28 -0
  82. package/md_cg/run_tests.py +211 -0
  83. package/md_cg/scrub.py +862 -852
  84. package/md_cg/security.py +385 -275
  85. package/md_cg/selfreport.py +3 -2
  86. package/md_cg/signer.py +565 -562
  87. package/md_cg/sources.py +3 -2
  88. package/md_cg/stg.py +6 -0
  89. package/md_cg/sustain.py +1168 -1138
  90. package/md_cg/test_access_hints.py +147 -0
  91. package/md_cg/test_branch_discard_tombstone.py +136 -0
  92. package/md_cg/test_branches.py +259 -249
  93. package/md_cg/test_chain_read_isolate.py +168 -0
  94. package/md_cg/test_datapath_device_name.py +203 -0
  95. package/md_cg/test_emit_negtail_cache.py +156 -0
  96. package/md_cg/test_en_pipeline.py +186 -166
  97. package/md_cg/test_govern_directread.py +421 -0
  98. package/md_cg/test_i32_hotcache_env_key.py +218 -0
  99. package/md_cg/test_identity_attribution.py +228 -147
  100. package/md_cg/test_index_crossprocess_reload.py +301 -0
  101. package/md_cg/test_index_durability.py +238 -224
  102. package/md_cg/test_interop.py +4 -2
  103. package/md_cg/test_interop_judgment.py +228 -0
  104. package/md_cg/test_issue39_utf8_stdio.py +273 -0
  105. package/md_cg/test_links_concurrent_write.py +188 -0
  106. package/md_cg/test_merge_upsert.py +168 -0
  107. package/md_cg/test_n123_derive_expiry_chain.py +205 -0
  108. package/md_cg/test_n130_verify_falsified_protect.py +185 -0
  109. package/md_cg/test_n131_merge_gate.py +205 -0
  110. package/md_cg/test_none_id_write_guard.py +165 -0
  111. package/md_cg/test_p1x_ref_root.py +160 -0
  112. package/md_cg/test_p27_docindex.py +774 -765
  113. package/md_cg/test_p2_mcp.py +3 -0
  114. package/md_cg/test_p32_backfill.py +304 -298
  115. package/md_cg/test_p39_verify_flow.py +90 -50
  116. package/md_cg/test_p47_session_view.py +60 -25
  117. package/md_cg/test_propose_tail_index.py +157 -0
  118. package/md_cg/test_read_scope_b27.py +277 -0
  119. package/md_cg/test_readcache_default_on.py +168 -0
  120. package/md_cg/test_readcache_precise_inval.py +270 -0
  121. package/md_cg/test_readcache_prodpath.py +55 -7
  122. package/md_cg/test_reconcile_v0.py +294 -0
  123. package/md_cg/test_retr_s1.py +6 -2
  124. package/md_cg/test_retr_s1b.py +67 -0
  125. package/md_cg/test_retr_s7.py +8 -0
  126. package/md_cg/test_retr_s9_entity_ctx.py +181 -175
  127. package/md_cg/test_retr_score_once.py +208 -0
  128. package/md_cg/test_review_cli_attribution.py +177 -0
  129. package/md_cg/test_review_cli_visibility.py +235 -0
  130. package/md_cg/test_review_onepass.py +170 -0
  131. package/md_cg/test_rrf_graph_seed_cache.py +154 -0
  132. package/md_cg/test_security_audit.py +155 -0
  133. package/md_cg/test_security_audit_b26.py +161 -0
  134. package/md_cg/test_security_audit_v21.py +250 -0
  135. package/md_cg/test_semantic_canonical.py +255 -241
  136. package/md_cg/test_session_isolation.py +168 -0
  137. package/md_cg/test_snapshot_autoclose.py +187 -0
  138. package/md_cg/test_tail_watermark_race.py +208 -0
  139. package/md_cg/test_tenant_env_override_warn.py +139 -0
  140. package/md_cg/test_tenant_registry_corrupt_warn.py +151 -0
  141. package/md_cg/test_v14_fixes.py +415 -397
  142. package/md_cg/test_verify_dirty_reconcile.py +157 -0
  143. package/md_cg/theory.py +276 -273
  144. package/md_cg/tokens.py +734 -677
  145. package/md_cg/units.py +3 -2
  146. package/md_cg/vision_evidence.py +4 -3
  147. package/md_cg/whitebox_kb/wisdom/code_solidified.json +6195 -6195
  148. package/md_cg/whitebox_kb/wisdom/multilang_ir.py +128 -124
  149. package/md_cg/writepipe.py +554 -550
  150. package/package.json +11 -2
  151. package/src/bridge.ts +434 -401
  152. package/src/cli.ts +65 -0
  153. package/src/index.ts +526 -518
  154. package/src/init.ts +347 -0
  155. package/src/lib/roleplay_web.ts +1019 -932
  156. package/src/lib/token_store.ts +202 -192
@@ -0,0 +1,192 @@
1
+ # 缺陷挖掘报告 · 自主迭代 v6
2
+
3
+ - **日期**:2026-09-25
4
+ - **范围**(生效条件):第 6 轮 = 四区复核(scripts-infra / scripts-ops / ts-lib / ts-entry)新发现 21 项确认(候选 21 → 确认 21 → 证伪 0)+ 本轮修复 5 项(high 3 + medium 2)落盘核验与守卫实跑 + 门禁三件(python 全量 / npm test / npm run gate)复现
5
+ - **总量**:新发现确认 **21**(high 3 / medium 6 / low 12)→ 新修 **5**(N31/N32/N33/N42/N44)→ 遗留新增 **16**
6
+ - **回归**:本会话实跑全量 `python scripts/run_tests.py` **SUMMARY 167/167 通过、5 跳过(依赖缺失/平台不符)、退出码 0**(较 v5 的 164 增 3 = 三个新 python 守卫套件入列);`npm test` **49 tests / 48 pass / 0 fail / 1 skipped、退出码 0**(增 2 = 两个新 TS 守卫);`npm run gate` **退出码 0**(报告文件登记 git 追踪后复跑,两遍过程见第四节)
7
+ - **行号口径**:新发现行号为缺陷时点快照行号;两项所在文件本轮被改(src/lib/roleplay_web.ts +56/-13、src/bridge.ts +33),涉及处本会话另注修复后现行行号(N43 → 现行 :542;N44 → scheduleRetry 现行 :295/:328);其余文件本轮零改动,快照行号与现行一致(关键处本会话抽读核实)
8
+ - **代码注释口径**:本轮 python/roleplay 侧修复注释标「V22 修复」、bridge 侧标「V23 修复」(沿用缺陷挖掘内部批次编号);本报告编号 N27-N47 沿历轮报告 N 口径(v5 用至 N26)
9
+ - **结构口径**(CCG 六要素):功能名(标题)/ 生效条件(范围与口径行)/ 子功能(第二~五节)/ 执行与验证方式(第四节:实跑命令与结果)/ 不适用条件(第七节:跳过与未运行项)
10
+
11
+ ---
12
+
13
+ ## 一、执行摘要
14
+
15
+ 本轮对四个区做缺陷复核:scripts-infra(判据面)4 项、scripts-ops(运维面)7 项、ts-lib(令牌/互维护面)4 项、ts-entry(入口/桥/角色扮演面)6 项,合计 21 项全部确认、0 项证伪。本轮修复 5 项、留档 16 项。
16
+
17
+ 修复主题两条:
18
+
19
+ 1. **数据保全与自愈闭环**(scripts-ops):迁移 `--apply` 经 `cg.add` 全量重建 frontmatter 把存量 private 节点的 tags/condition_space/importance/confidence/edges/non_applicable_conditions/created_at/protected 等 8 类字段全部清空重置(N31,high,数据丢失);通道 B verifier 首次失败即 AttributeError 崩溃、队列不回写、条目永久 pending 每轮重试再崩(N32,high,死循环);通道 A 固化误传全量补丁、验证失败者也写进 wisdom 源文件(N33,medium,闸失效)。三项均修复并各配红守卫。
20
+ 2. **入口可用性与进程保真**(ts-entry):角色扮演网页全部编辑操作(创建/保存角色/保存翻译)因前端无携带 x-edit-key 途径开箱即 403,「详情保存」还无条件显示成功——用户被告知已保存但数据从未落盘(N42,high,错误结果+虚假成功);桥在 initialize 握手超时重试时不清理上一个仍存活的子进程,最多累积 8 个僵尸(N44,medium)。两项均修复并各配红守卫(对旧代码实测红:5 fail / 1 fail)。
21
+
22
+ **对输入口径的核验**:输入称「新发现 21 确认(四区)→ 修复 5 → 留档 16」。本会话以 `git status`/`git diff --stat` + 逐处读核 + 守卫实跑核对:改动面恰为 4 文件(scripts/migrate_restricted.py +23、scripts/bootstrap_loop.py +12-3、src/bridge.ts +33、src/lib/roleplay_web.ts +56-13)+ 5 个新守卫文件(scripts/test_migrate_restricted.py、scripts/test_bootstrap_channel_b.py、scripts/test_bootstrap_persist_gate.py、test/roleplay_edit_guard.test.ts、test/bridge_retry_leak.test.ts),与 5 项修复一一对应;新发现 21 − 修复 5 = 留档 16,无多无少。
23
+
24
+ ---
25
+
26
+ ## 二、修复清单(5 项,逐项 where / 问题 / 修复 / 守卫 / 验证)
27
+
28
+ ### F1(N31,high)migrate_restricted --apply 透传旧 frontmatter
29
+
30
+ - **where**:scripts/migrate_restricted.py:61-83(缺陷时点 :62 的 `cg.add` 调用;现行修复段含「V22 修复」注释与排除集注释,本会话读核 :78-83)
31
+ - **问题**:`--apply` 只传 content/layer/sensitivity/override,而 `cg.add` 是全量重建 frontmatter(mdcg.py add docstring 自认;created_at 未传即重置、condition_space 只剩 time_window、importance/confidence/tags/edges/non_applicable_conditions 归默认、protected/protection_reason 清空)——存量 private 节点 8 类字段丢失/重置(数据丢失)。
32
+ - **修复**:旧 frontmatter 全部字段经 `**passthrough` 透传给 `cg.add`;排除集及理由(注释在位):id/layer/sensitivity(显式给值)、state/lifecycle_state/verification_state(add 覆写时默认继承旧值,显式传同值反要走迁移裁决)、bucket/bucket_zh(路由按 tags/condition_space 重算)、writer(语义=最后写入者)。
33
+ - **守卫**:scripts/test_migrate_restricted.py:88-122——先证旧代码红(9 项 FAIL 精确复现 8 类字段丢失主诉),修复后绿。
34
+ - **验证**(材料:上游会话运行)`python -X utf8 scripts/test_migrate_restricted.py` 修复前 exit 1/9 FAIL → 修复后 15 通过 0 失败;`scripts/run_tests.py scripts` 4/4;md_cg 回归五套(test_p19_migrate_roleplay 13/13、test_p9_forget_protect 37/37、test_security_audit 13/13、test_security_audit_b26 17/17、test_security_audit_v21 49/49)无回归。**本会话复跑该守卫:15 通过 / 0 失败**(见第四节)。
35
+
36
+ ### F2(N32,high)通道 B verifier 失败分支 _rej_list 初始化修复
37
+
38
+ - **where**:scripts/bootstrap_loop.py:370(`_rej_list = ""` → `[]`;现行该行带「V22 修复」注释,本会话读核 :367-377)
39
+ - **问题**:cases 物理验证未过分支把 `_rej_list` 初始化为空串,`rejected_log.json` 不存在时首次失败即 `AttributeError: 'str' object has no attribute 'append'`——崩溃点在队列回写与拒绝留痕之前,条目永 pending 每轮重试再崩(通道 B 死循环),run_once 捕获后整轮通道 B 作废。
40
+ - **修复**:初始化改为 `[]`(对照同文件 :319 沙箱拒绝分支的正确写法)。
41
+ - **守卫**:scripts/test_bootstrap_channel_b.py:57-95——cases 未过分支专测(与 V21-4 沙箱拒绝分支守卫互补);先证旧代码红(AttributeError),修复后绿。
42
+ - **验证**(材料:上游会话运行)修复前 exit 1/AttributeError → 修复后 5 通过 0 失败;test_security_audit_v21 49/49 不回归;`run_tests.py scripts` 5/5。**本会话复跑该守卫:5 通过 / 0 失败**(见第四节)。
43
+
44
+ ### F3(N33,medium)通道 A 固化只传验证通过者
45
+
46
+ - **where**:scripts/bootstrap_loop.py:416-421(`persist_triggers(patches)` → `persist_triggers(persisted)`;现行该段带「V22 修复」注释,本会话读核 :415-421;:394 生效条件 docstring 同步)
47
+ - **问题**:run_once 固化时传全量 patches,verify_patch 失败的补丁也被写进 WISDOM 下 6 个 *_units.py 源文件——绕过模块 docstring 声明的「补丁→验证→固化」闸。
48
+ - **修复**:只传只含验证通过者的 `persisted` 列表。
49
+ - **守卫**:scripts/test_bootstrap_persist_gate.py:36-72——monkeypatch 台架与原缺陷复现同款;先证旧代码红(固化入参收到全量 `['gap-unit-x','gap-unit-ok']`),修复后只含 `['gap-unit-ok']`。
50
+ - **验证**(材料:上游会话运行)修复前 exit 1/2 FAIL → 修复后 4 通过 0 失败;test_bootstrap_channel_b 5/5(同文件 F2 不回归);test_security_audit_v21 49/49;`run_tests.py scripts` 6/6。**本会话复跑该守卫:4 通过 / 0 失败**(见第四节)。
51
+
52
+ ### F4(N42,high)roleplay 编辑密钥携带 + 响应检查(虚假成功封死)
53
+
54
+ - **where**:src/lib/roleplay_web.ts:350(saveRoleDetail;缺陷时点 :338,修复后注释锚点现行 :356;改幅 +43/-13 全在内嵌 HTML 字符串内,服务端 handler 与 fail-closed 鉴权语义未动——P1-2 不可回退)
55
+ - **问题**:服务端写操作要求 x-edit-key 头(未配置 ROLEPLAY_EDIT_KEY 时拒绝全部写),但前端页面无任何输入/携带密钥途径——全部编辑操作(创建角色/保存详情/保存翻译)开箱即恒 403 不可用;且 saveRoleDetail 无条件显示「已保存」——用户被告知已保存但服务端 403 在写盘之前 return、数据从未落盘(错误结果 + 虚假成功反馈)。
56
+ - **修复**(五步,全部在内嵌 HTML):① header 新增 🔑 按钮(现行 :104)+ setEditKey(prompt 输入存 localStorage,现行 :203);② apiHeaders 注入 x-edit-key(现行 :211-216);③ saveRoleDetail 的 meta/import 两个 POST 从裸 Content-Type 改走 apiHeaders() 并逐段检查响应 ok(含网络异常 catch),任一失败 alert 服务端原因(403 文案含 ROLEPLAY_EDIT_KEY 指引)并中止,不再无条件显示已保存/关闭面板;④ saveTrans 与 ⑤ createRole 的 POST 改走 apiHeaders(),失败 alert 追加密钥输入引导。
57
+ - **守卫**:test/roleplay_edit_guard.test.ts:148-278(node:test,6 用例:apiHeaders 注入 / setEditKey 持久化 / 403 时不显示已保存+alert+不关面板 / 配密钥后带头且成功 / saveTrans·createRole 带头 / 服务端 403 不落盘回归线)。实现方式:mock 挂载 GET /roleplay 取 HTML,提取 script 在 mock DOM/localStorage/fetch/alert 沙箱求值,直接执行真实前端函数验证。对旧代码实测 **5 红 1 绿**(红在核心断言:服务端 403 未落盘时页面消息却为「角色「…」已保存:… 1 条」的既定成功文案——虚假成功确凿复现)。
58
+ - **验证**(材料:上游会话运行)修复后 6/6 pass;`npm run build` tsc 通过;全量 `node --import tsx --test "test/*.test.ts"` 48 tests/47 pass/0 fail/1 skipped;附加对照 test/verify_web.ts 改动前后均 2/5(②④⑤ 为 HEAD 既有失败,git stash 对照确认非本次引入,无回归)。**本会话经 npm test 全量复现终态:该守卫 6 用例全 ✔(输出见第四节)**。
59
+
60
+ ### F5(N44,medium)桥重试换代前回收旧子进程
61
+
62
+ - **where**:src/bridge.ts:162-189(新增 killStaleProc + spawnAndHandshake 换代前调用;缺陷时点 :284 handshake catch → scheduleRetry → 重 spawn 覆盖引用的泄漏链由此截断;现行 scheduleRetry :295/:328、spawnAndHandshake 内调用点 :189,本会话读核)
63
+ - **问题**:initialize 握手超时重试直接 spawn 新进程覆盖 this.proc 引用,旧进程仍存活(卡死不退出)时既不 kill 也不关 stdin——僵尸进程泄漏,最多 MAX_RETRIES=8 个并存,dispose 也只收尾最后一个(原报告动态复现:8 次重试后存活子进程 = 8,dispose 后仍剩 7)。
64
+ - **修复**(三处最小改动 +33 行):① killStaleProc——先摘 this.proc 引用再对仍存活旧进程 stdin.end + kill,幂等(exitCode/signalCode 非 null 跳过);② spawnAndHandshake 开头换代前统一调用,覆盖握手超时重试、spawn error 重试、exit 重试、冷却恢复全部路径;③ proc.on('exit') 加非当前进程早退守卫——被回收旧进程的 exit 事件只写探针,不再误关新进程 readline/误拒挂起请求/多触发重试。dispose 与 gaveUp 语义未动。
65
+ - **守卫**:test/bridge_retry_leak.test.ts:44-79(node:test):spawn 真实 `node -e 'setInterval(()=>{},1<<30)'`(永不退出、不响应协议)驱动握手超时重试换代,10ms 轮询收集每代 this.proc,达 gaveUp 后断言除最后一代外全部旧进程已退出。旧代码红(AssertionError:7 个旧子进程存活,与原报告吻合);新代码绿(0 存活);finally 兜底 kill 防红跑泄漏。
66
+ - **验证**(材料:上游会话运行)修复前 0 pass/1 fail → 修复后 1/1 pass;`npm run build` 通过;全量 49 tests/48 pass/0 fail/1 skipped(含 bridge.test.ts 真实 python 集成回归——正常握手/调用/dispose 路径未被 exit 守卫破坏)。**本会话经 npm test 全量复现终态:49/48/0/1、退出码 0**。
67
+
68
+ ---
69
+
70
+ ## 三、本轮新发现缺陷明细(确认 21 项 / 证伪 0 项)
71
+
72
+ 四区复核 21 项候选全部确认,**rejected 为空**(四个区的复核结果 rejected 数组均为 0 项)——如实记录:本轮零证伪。以下每项的「证据」均为上游复核会话的读码 + 实跑复现(材料原文,证据中的环境细节已按仓库相对路径口径转录);标注★者本会话另做了关键行抽读核实。
73
+
74
+ ### scripts-infra 区(4 项,全部留档未修)
75
+
76
+ | # | where | 严重度 | 问题摘要 | 证据要点 |
77
+ |---|------|--------|----------|----------|
78
+ | N27★ | scripts/judgment_manifest.py:129 | medium | `--verify` 缺冻结文件参数时不报用法错误:`len(sys.argv) >= 3` 为 False 落入 :142 兜底分支,打印当前盘面全量 manifest 并 return 0——CI/钩子参数拼空时守卫假通过(fail-open) | 实跑 `--verify` 无参 → exit 0、stdout 为全量 manifest 非判决;对照:带空 files 冻结文件 → verdict FAIL、exit 1(判决分支正常,唯缺参 fail-open);docstring :16-17 声明需参数。本会话抽读 :129/:142 在位 |
79
+ | N28★ | scripts/run_tests.py:216 | medium | SUMMARY 输出格式与下游解析契约断裂:hive/verify_runner.py:56-60 的 `_parse_counts` 两个正则(`(\d+) passed` / `通过 X / 失败 Y`)均不命中 `SUMMARY 164/164 通过,N 跳过` 实际形态(失败只打名字无计数)——verdict.json 的 passed/failed 计数恒失真(python 侧恒 0,fail 态靠 `failed + 1` 硬补;verdict 本身因 rc_py 条件仍正确) | importlib 加载后实测 `_parse_counts` 对真实 SUMMARY 形态 → (0,0)、对假设形态才命中;git log --follow -p(483 行 diff)核实「通过 X / 失败 Y」形态从未存在过。本会话抽读 :216-218 与 verify_runner.py:55-62 在位 |
80
+ | N29 | scripts/interop_gate.py:61 | low | PASS 分支直接取 `v['failed']` 但该字段不在 `_REQUIRED`(:26) 也不在 _load 校验——缺 failed 字段的 pass 态 verdict 触发未捕获 KeyError(traceback + exit 1),违反自身「exit 3 = 形状非法」契约 | 实测:构造缺 failed 的 pass 态 JSON → KeyError: 'failed'、exit 1;生产方 verify_runner.py:148 总写该字段,触发面限旧版/手工产物 |
81
+ | N30 | scripts/criteria_fingerprint.py:44 | low | `worktree_of` 用 tempfile.mkdtemp 解包 git archive 后从不删除——每次 `--commit` 调用泄漏一个含完整仓库快照的临时目录,跨运行累积 | 实测:系统临时区 criteria_* 目录基线 0 → 连跑两次 `--commit` 后 2 个(抽样含 27 个顶层条目);附带检查:指纹输出 files=97 与 docstring 声明一致;复现后已清理本轮创建的 2 个目录 |
82
+
83
+ ### scripts-ops 区(7 项,前 3 项已修见第二节,余 4 项留档)
84
+
85
+ | # | where | 严重度 | 问题摘要 | 证据要点 | 状态 |
86
+ |---|------|--------|----------|----------|------|
87
+ | N31 | scripts/migrate_restricted.py:62 | high | --apply 经 cg.add(override=True) 全量重建 frontmatter,存量 private 节点 tags/condition_space/importance/non_applicable_conditions/created_at/protected 等 8 类字段全部清空重置(数据丢失) | 实跑复现(临时库 + importlib 原样调 main):BEFORE tags/importance=0.9/confidence=0.8/cs={env,region,…}/nac/protected/edges 齐备 → AFTER 全部为空/默认/重置(created_at 变更),8 项实证 | **已修**(F1) |
88
+ | N32 | scripts/bootstrap_loop.py:370 | high | 通道 B verifier 失败分支 _rej_list 初始化为空串,rejected_log.json 不存在时首次失败即 AttributeError 崩溃,队列回写不执行 → 条目永 pending 每轮重试再崩(死循环) | 实跑复现:CRASH AttributeError;崩溃后队列 status 仍 None、rejected_log.json 不存在;对照实验:预置空数组再跑 → 不崩(证明崩溃条件=文件不存在) | **已修**(F2) |
89
+ | N33 | scripts/bootstrap_loop.py:416 | medium | run_once 固化传 persist_triggers(patches) 全量而非只含验证通过者的 persisted——verify_patch 失败的补丁也写进 wisdom 源文件,绕过「补丁→验证→固化」闸 | 只读实跑复现(monkeypatch 台架):gaps=2、verified=1/failed=1,但固化入参收到全量 2 个单元(含验证失败者);未实跑真实 persist(避免改写仓库源文件) | **已修**(F3) |
90
+ | N34 | scripts/retr_time_coverage.py:179 | low | --out 传裸文件名时 os.path.dirname 为空串,os.makedirs('') 抛 FileNotFoundError,脚本写结果前崩溃(docstring :14 明示 [--out FILE] 用法) | 实跑:--out bare_out.json → FileNotFoundError 指向 :179;同型实测 retr_baseline_diff.py:444 同款崩溃 | 留档 |
91
+ | N35 | scripts/check_unreachable.py:46 | low | ROOTS 为相对路径按 cwd 解析,非仓库根目录调用时扫描 0 文件仍报「命中 0」exit 0——死代码守卫可空转通过(假绿);grep 全仓无自动调用入口,属手动守卫 | 实跑三种 cwd:仓库根 385 文件/0 命中;在 scripts 子目录与系统临时目录下运行均 0 文件 0 命中 exit 0 | 留档 |
92
+ | N36 | scripts/bootstrap_watchdog.py:82 | low | resolve_python 兜底 glob 模式 `[系统盘]:\Python3*\python.exe` 中 [系统盘] 是单字符字符类,真实盘符(拉丁单字母+冒号)永不命中——「常见安装位置扫描」第二分支是死代码 | 实测:该 glob → 空列表;对照实验证明 [..] 按单字符类匹配(构造盘符形态目录名不在类内即不命中);该分支仅在 sys.executable basename 不含 'python' 的罕见情形可达 | 留档 |
93
+ | N37 | scripts/bootstrap_watchdog.py:289 | low | degraded 分支只在 procs 非空时 kill+restart;进程已死(not_running)且日志新鲜降级时不拉起 return 0——与 docstring :21「进程缺失 → 直接拉起」矛盾,死循环要等日志陈旧(2×interval+120s,interval=600 时约 22 分钟)才被分支③恢复 | 代码证据核实(未实跑——需真实 kill/拉起进程,如实声明);场景可达性由 bootstrap_loop.py:531-533 loop_error 持续写入机制保证 | 留档 |
94
+
95
+ ### ts-lib 区(4 项,全部留档未修)
96
+
97
+ | # | where | 严重度 | 问题摘要 | 证据要点 |
98
+ |---|------|--------|----------|----------|
99
+ | N38★ | src/lib/token_store.ts:76-79 | medium | auxRoot() 用 resolve(env):不做波浪线家目录展开且锚定宿主 cwd,与文件头/token_store.ts:71、index.ts:293 声称「同口径」的 md_cg/datapath.py aux_root()(expanduser+abspath,锚 python 子进程 cwd=runRoot())不一致——MDCG_AUX_ROOT 设为波浪线家目录引用或相对路径时密钥环与令牌记录分居两处,宿主 cwd 变化即触发重复自动签发永不吊销的 designer 令牌 | 探针实测(隔离目录 import 编译产物):MDCG_AUX_ROOT 设波浪线值时 node 得字面波浪线目录(锚 cwd)、python 得真家目录——两侧分居两处;设相对路径时 node 结果随宿主 cwd 变即变;后果链逐行读核(readKeyring 读错处 → issueToken 落另一处 → 全文无 revoke);佐证:同仓 mdcgRoot 已锚 repoRoot 并写明历史教训(src/lib/datapath.ts:122),auxRoot 与既定纪律相悖。本会话抽读 :76-79 在位 |
100
+ | N39 | src/lib/token_store.ts:97-99 | low | writeKeyring 的 mkdirSync/writeFileSync 无 try 包裹(对比 :100-104 chmodSync 有 try),keyring 父路径不可写(被普通文件占用/磁盘满/只读)时 resolveToken 抛裸 fs 错误,index.ts apply()(:246 调用,无 try)激活中断——且令牌已先签发进 _tokens.json,每次重试再泄漏一枚不吊销令牌 | 探针实测(隔离目录 + 父路径放 blocker 文件):输出 EEXIST 裸错误冒出;崩溃前后对照隔离 _tokens.json:新增 1 枚 actor=dsh-memory 且 revoked=None 的令牌记录;探针产物已清理(未触碰本机真实令牌目录) |
101
+ | N40 | src/lib/mutual.ts:33 | low | restartCooldownMs 在接口与 DEFAULTS(60s)声明、头注承诺「幂等:拉起前确认不存在 + 60s 冷却」,但 ensureHarness(129-195 行)无任何冷却逻辑——契约未实现;heartbeatMs 无最小值约束(index.ts:186 可配 1000ms)+ harnessRunning 漏检边界(:96-99 自认)叠加时每拍 spawn 一个 detached guardian 进程累积 | grep 全仓该字段仅声明/赋值/测试填充三处、无冷却行为断言(不构成消费点);调用链逐行读核;缓解:config.mutual.enabled 默认 false + 默认 10min 心跳是事实节流 |
102
+ | N41 | src/lib/mutual.ts:305-310 | low | processTask 用 renameSync 把 task-<id>.json 改名 processing-<id>.json 认领,B 侧进程在认领后、写回 result/done 前崩溃(断电/重启/kill)时无任何 stale processing-* 恢复机制——scanTasks 只认 task- 前缀,任务滞留既不重试也无消费者清理 | grep 全仓 "processing-" 唯一命中构造点、无清理消费者;边界事实如实记录:A 侧 guardian 不在本仓无法核实重发自愈;实测 renameSync 目标已存在时覆盖成功(若 A 侧重发同 id 可覆盖 stale)——但 B 侧自身无恢复机制的事实成立;缓解:mutual.enabled 默认 false + 需恰在 await 窗口死亡 |
103
+
104
+ ### ts-entry 区(6 项,2 项已修见第二节,余 4 项留档)
105
+
106
+ | # | where | 严重度 | 问题摘要 | 证据要点 | 状态 |
107
+ |---|------|--------|----------|----------|------|
108
+ | N42 | src/lib/roleplay_web.ts:338 | high | 角色扮演网页全部编辑操作开箱即 403 不可用(服务端 fail-closed 要求 x-edit-key,前端无携带途径),且「详情保存」无条件显示成功——数据从未落盘(错误结果+虚假成功反馈) | 读码全链:服务端 403 闸四处(/import :700-704、/meta :758-762、/translate :872-876、POST /roles :908-912)、前端 meta/import POST 裸 headers、HTML 无密钥输入路径;saveRoleDetail 的 addMsg 无条件执行、fetch 对 403 不 reject;服务端 403 在写盘(:719-723/:794)之前 return 确证数据未写 | **已修**(F4) |
109
+ | N43 | src/lib/roleplay_web.ts:512(现行 :542) | medium | 角色扮演数据面(转录 :543-548/_roles.json :566/翻译配置 :613)落在相对路径 `<cwd>/data/roleplay_data`,随宿主启动 cwd 漂移分裂成互不可见的多处——本仓 datapath.ts :22-25 把同类问题定性为「数据丢失级历史事故」并为 mdcg.root 专门修过(anchor()),此处未走同一口径 | 实测 join(dirname('data/lingshu.db'),'roleplay_data') → 相对路径;index.ts:157 dbPath 默认相对、:421 原样传 config、全文件无绝对化;capability 桥 spawn cwd undefined 继承宿主 cwd 同样漂移。本会话抽读现行 :542 在位 | 留档 |
110
+ | N44 | src/bridge.ts:284 | medium | initialize 握手超时重试不清理上一个仍存活子进程——旧进程不 kill 不关 stdin,僵尸泄漏最多 8 个并存,dispose 只收尾最后一个 | 动态实跑:timeoutMs=800 + 永不退出的 node 子进程驱动重试,9 秒后存活子进程 = 8,dispose 后仍剩 7,与 MAX_RETRIES=8 上限吻合;复现后残留进程已清理(终查 0) | **已修**(F5) |
111
+ | N45 | src/lib/roleplay_web.ts:715 | low | /import、GET /items、POST /api/roles 三个入口 role_id 未做 validRoleId 白名单校验(P2-23 只修了 /chat 与 /meta)——非法 role 经 node_id 模板被 md_cg 白名单(mdcg.py:1095 `^[A-Za-z0-9_.@-]{1,128}$`)拒绝后落图静默失败、接口仍返回 ok;危险键还会写进 _roles.json 并进角色下拉列表 | grep validRoleId 仅 4 处(:571/:638/:774/:815),三入口不在内;:745-749 fire-and-forget 落图 + :750-754 仍返回 ok 逐行读核;缓解:写路径均在 403 闸之后,需持密钥者手动构造请求才可达 | 留档 |
112
+ | N46 | src/lib/whitebox_llm.ts:195 | low | 白箱输入实现与自述契约不符:注释称「取最后一条用户文本」,实际逆序拼接所有角色(含 assistant)全部文本块后截尾 | node -e 复现:messages=[U1,A1,U2] → lastUserText 为三段混拼(契约应仅 U2);文件头 :2-5 声明已下线、grep installWhiteboxLlm index.ts = 0(无运行时调用方),保留库内真实逻辑错误。本会话抽读 :194-201 在位 | 留档 |
113
+ | N47 | src/hooks.ts:239 | low | 自动召回注入在 system-prompt/assemble waterfall 内同步 await 认知图时间线,桥挂死(进程存活不响应、exit 不触发)时每次模型请求组装阻塞至 toolCallTimeoutMs(默认 60s),与文件头「失败静默(不影响请求)」声明不符 | 读码核实(未动态复现 60s 阻塞——需 mock Cordis waterfall + wedge 子进程,如实声明):await 在 next() 之前阻塞组装链;超时链逐环实读(hooks:239-240 → mdcg_client:317-319 → bridge:340/:344-348,默认 60_000 见 index.ts:174);low 定级:需握手成功后 wedge 的少见场景,后果为 +60s 延迟非功能失败。本会话抽读 :239-241 在位 | 留档 |
114
+
115
+ ---
116
+
117
+ ## 四、验证(本会话实跑门禁结果原文数字)
118
+
119
+ 以下命令均为**本报告写作者本会话实际运行**(仓库根目录,`python -X utf8` / npm):
120
+
121
+ | 命令 | 结果(原文数字) | 退出码 |
122
+ |------|------------------|--------|
123
+ | `python -X utf8 scripts/run_tests.py`(全量) | `===== SUMMARY 167/167 通过,5 跳过(依赖缺失/平台不符) =====`(较 v5 的 164 增 3 = 三个新 python 守卫套件入列) | **0** |
124
+ | `npm test`(= `npm run build` + `node --import tsx --test "test/*.test.ts"`) | `ℹ tests 49 / ℹ pass 48 / ℹ fail 0 / ℹ skipped 1`(skipped 为既有平台跳过项;含两个新 TS 守卫全部用例 ✔,roleplay_edit_guard 六用例与 bridge 集成回归均绿;tsc build 随 npm test 先行通过) | **0** |
125
+ | `npm run gate`(check_unreachable + check_publish_artifact + cogmap_sync check + link_check + workspace_index --check + verify_discipline) | 复跑两遍,如实记录:**第一遍 FAIL**——R4 非追踪件面(非追踪=25,允许=24)点名本报告文件自身(新写入的未跟踪交付件进入 npm pack 清单;lib/ 外非追踪件须 git 登记,check_publish_artifact.py:45/ALLOW_NONTRACKED,历轮报告均追踪在案);按守卫要求将本报告文件 git add 登记后**第二遍通过**:R1-R4 全 PASS、链接全可达、工作区索引 OK(顶层目录 20 · 追踪件随本报告 +1)、纪律注入面 8 条链 0 冲突 | 第二遍 **0**(第一遍 1,原因如左,非修复代码回归) |
126
+ | `python -X utf8 scripts/test_migrate_restricted.py`(新守卫单跑) | `migrate_restricted 守卫: 15 通过 / 0 失败`(含 frontmatter 九字段保全断言) | 0 |
127
+ | `python -X utf8 scripts/test_bootstrap_channel_b.py`(新守卫单跑) | `bootstrap 通道 B 守卫: 5 通过 / 0 失败`(首跑不崩/拒绝留痕/队列回写/死循环消除) | 0 |
128
+ | `python -X utf8 scripts/test_bootstrap_persist_gate.py`(新守卫单跑) | `bootstrap 固化闸守卫: 4 通过 / 0 失败`(固化入参只含验证通过者) | 0 |
129
+
130
+ **上游复核/修复会话已运行、本会话未重跑的验证**(如实区分,材料原文):五项修复的「修复前红态」对照(test_migrate_restricted 9 FAIL、test_bootstrap_channel_b AttributeError、test_bootstrap_persist_gate 2 FAIL、roleplay_edit_guard 5 fail 1 pass、bridge_retry_leak 1 fail 7 存活)经 git stash push/pop 或时序对照完成;md_cg 回归五套(13/13、37/37、13/13、17/17、49/49)单跑通过(其覆盖面已含于本会话全量 167/167);`scripts/run_tests.py scripts` 6/6;test/verify_web.ts 附加对照 2/5(HEAD 既有失败,非本次引入)。21 项新发现的复现实验(探针/实跑/对照)均在四区复核会话完成,证据要点已摘录进第三节各表。
131
+
132
+ **git 工作树核对**(本会话):`git status`/`git diff --stat` —— 改动 4 文件 +105/-19(migrate_restricted +23、bootstrap_loop +12-3、bridge.ts +33、roleplay_web.ts +56-13)+ 未跟踪 5 守卫文件 + 本报告文件(已 git add 登记,见 gate 行说明),与五项修复一一对应,无多余改动面。
133
+
134
+ ---
135
+
136
+ ## 五、遗留清单(deferred 16 项逐项)
137
+
138
+ ### medium(4 项)
139
+
140
+ | # | where | 问题 | 降级理由(材料原文要点) |
141
+ |---|------|------|--------------------------|
142
+ | N27 | scripts/judgment_manifest.py:129 | --verify 缺参 fail-open | 修复廉价但触发面窄(仅 CI/钩子参数拼空时发生),本轮名额让给影响面更大的 medium(N33/N44);建议下轮优先收掉 |
143
+ | N28 | scripts/run_tests.py:216 | SUMMARY 与 _parse_counts 契约断裂,verdict.json 计数系统性失真 | verdict 判决本身仍正确,受损的是留痕计数;修复若动 run_tests 输出格式,其他消费方(verify_linux.sh 等按 SUMMARY 形态 grep)波及面需先盘清 |
144
+ | N38 | src/lib/token_store.ts:76-79 | auxRoot 双口径分裂,令牌重复签发永不吊销 | 触发依赖 MDCG_AUX_ROOT 非常规配置(波浪线家目录引用/相对路径);改令牌/密钥环定位涉及既有部署兼容(现存令牌位置迁移),修复风险中等,宜单独一轮配齐验证 |
145
+ | N43 | src/lib/roleplay_web.ts:512(现行 :542) | roleplay 数据面相对路径随 cwd 漂移分裂 | 根因是 dbPath 本身相对(默认 'data/lingshu.db'),只锚 roleplayData 会令数据面与库文件分裂两处;连贯修法需连 dbPath 一起锚定——涉及既有部署 sqlite 库位置迁移语义,波及面与数据找回风险中等,宜单独一轮处理;本轮 roleplay 名额先给 high 的 N42 |
146
+
147
+ ### low(12 项)
148
+
149
+ | # | where | 问题 | 降级理由/备注 |
150
+ |---|------|------|----------------|
151
+ | N29 | scripts/interop_gate.py:61 | pass 态缺 failed 字段 KeyError 崩溃(应 exit 3) | 触发面限旧版/手工产物(生产方总写该字段) |
152
+ | N30 | scripts/criteria_fingerprint.py:44 | --commit 每调泄漏一个仓库快照临时目录 | 资源泄漏、无正确性影响 |
153
+ | N34 | scripts/retr_time_coverage.py:179(同型 retr_baseline_diff.py:444) | --out 裸文件名即崩 | 用法边缘;同型两文件宜一并修 |
154
+ | N35 | scripts/check_unreachable.py:46 | 错目录运行 0 文件仍 PASS(假绿) | 手动守卫无自动调用入口;修法(ROOTS 锚脚本父目录 + 0 文件判失败)清晰但需连带跑通 gate 六链 |
155
+ | N36 | scripts/bootstrap_watchdog.py:82 | 盘符 glob 死代码 | 永不生效分支,无错误行为 |
156
+ | N37 | scripts/bootstrap_watchdog.py:289 | 进程已死且日志新鲜时不拉起,恢复延迟至日志陈旧 | 验证手段不足(需真实拉起/杀死常驻进程),按纪律不宜本轮修 |
157
+ | N39 | src/lib/token_store.ts:97-99 | writeKeyring 无 try:激活中断 + 每次重试泄漏一枚未吊销令牌 | 触发需 keyring 父路径不可写;与 N38 同文件同域,宜与 N38 一轮配齐验证(含已泄漏令牌清理语义) |
158
+ | N40 | src/lib/mutual.ts:33 | restartCooldownMs 契约未实现,可致 guardian 进程泄漏 | mutual.enabled 默认 false + 默认 10min 心跳事实节流 |
159
+ | N41 | src/lib/mutual.ts:305-310 | stale processing-* 无恢复机制 | 同上默认关闭;且 A 侧重发可覆盖 stale 文件(实测 renameSync 覆盖成功),自愈路径待 A 侧核清 |
160
+ | N45 | src/lib/roleplay_web.ts:715 | 三入口 role_id 未走 validRoleId 白名单 | 写路径在 403 闸后,需持密钥者手动构造请求;与 N43 同文件宜一并处置 |
161
+ | N46 | src/lib/whitebox_llm.ts:195 | 白箱输入混拼 assistant 文本 | 文件已下线、无运行时调用方 |
162
+ | N47 | src/hooks.ts:239 | waterfall 内同步 await,桥挂死时每请求 +60s | 修法(预取缓存/移出 waterfall/加短超时)属设计变更,需 mock Cordis waterfall 验证台架,本轮验证手段不足 |
163
+
164
+ **优先级建议**:N27(修复一个条件判断即除 fail-open,建议下轮首位);N28 需先盘清 SUMMARY 消费方再动格式;N38/N39(令牌面)与 N43/N45(roleplay 面)各自成对、分别一轮配齐验证;N34-N37、N40/N41/N46/N47 可按批次缓收。
165
+
166
+ ---
167
+
168
+ ## 六、纪律合规声明
169
+
170
+ 1. **定位先读索引**:本报告写作前已读 WORKSPACE_INDEX.md(按职责定位 docs/ 为文档归域、scripts/ 为工程管线、src/ 为 TS 源码),未做全盘浏览。
171
+ 2. **结论引证**:所有修复与缺陷均引 path:line(缺陷时点快照行号,漂移处另注现行行号);第三节证据要点摘自任务输入的四区复核材料(上游会话读码 + 实跑,环境细节按仓库口径转录),第四节六项门禁数字为本会话实跑原文输出;未实际运行的检查均标注来源或「未重跑」,无一冒充。
172
+ 3. **修复落盘核验**:五项修复的现行代码本会话逐处读核(migrate_restricted passthrough 段、bootstrap_loop 两处、roleplay_web 🔑/apiHeaders/:356 注释锚点、bridge killStaleProc/:189),git 工作树改动面与五项一一对应。
173
+ 4. **如实记录**:rejected 为 0 如实写明(零证伪);两项证据不完整的缺陷如实标注「未动态复现」(N37 需真实 kill/拉起进程、N47 需 mock waterfall 台架);N33 复现采用只读 monkeypatch 台架、未实跑真实 persist(避免改写仓库源文件),材料已声明;gate 第一遍 FAIL 的原因(本报告文件未登记追踪触发 R4)如实写入第四节,登记后复跑通过——非修复代码回归。
174
+ 5. **隐私脱敏**:全文只写仓库相对路径;本机盘符绝对路径、用户家目录路径(含波浪线引用形态)、系统临时目录路径与探针中的令牌记录 ID 字面量均已去除(以「隔离临时目录」「系统临时区」「波浪线家目录引用」「新增 1 枚未吊销令牌记录」等表述替代);环境变量名(ROLEPLAY_EDIT_KEY/MDCG_AUX_ROOT 等)为源码标识符非凭据值,为证据必需而保留;无任何 key/token 值出现;定稿前经机械扫描复查(盘符路径、家目录路径、系统临时目录、令牌 ID 形态零命中)。
175
+
176
+ ---
177
+
178
+ ## 七、跳过项及原因
179
+
180
+ - **修复跳过**:无「确认后主动跳过」——21 项确认中 5 项本轮修复(3 high 全修 + 2 medium),余 16 项全部列入第五节遗留清单并逐项给降级理由。
181
+ - **未运行项(如实说明)**:
182
+ - 五项修复的「旧代码红态」对照(git stash push/pop、时序对照)未在本会话重做——引用上游修复会话结果(材料原文);本会话以终态绿(守卫单跑 + npm test 全量)覆盖。
183
+ - md_cg 回归五套(test_p19_migrate_roleplay 13/13、test_p9_forget_protect 37/37、test_security_audit 13/13、test_security_audit_b26 17/17、test_security_audit_v21 49/49)未单独重跑——其覆盖面已包含在本会话全量 `run_tests.py` 167/167 之内。
184
+ - `node --import tsx test/verify_web.ts` 附加对照未重跑——该脚本不在 npm test 套内、bridge mock 缺 isReady,材料记载改动前后均 2/5(HEAD 既有失败),不构成门禁。
185
+ - `scripts/verify_linux.sh`(Docker Linux 口径)本轮未跑——本轮 python 侧改动集中于 scripts/(迁移与自愈脚本),Linux 口径确认可后续补跑。
186
+ - N37/N47 的运行时复现未做(需真实进程拉起 / mock Cordis waterfall 台架),以读码 + 机制链证据定级,见第三节各表声明。
187
+ - bench_swarm_parallel / bench_swarm_scale 两套为全量入口既定跳过(负载敏感仅串行),非本轮新增。
188
+ - 本报告文件未做 git 提交(commit 需任务方指令);仅按 R4 守卫要求 git add 登记追踪面,提交由后续流程处置。
189
+
190
+ ---
191
+
192
+ *报告依据:任务输入的第 6 轮材料(四区复核 21 项确认明细及证据、五项修复的 where/守卫/verified_by、留档 16 项及降级理由、门禁结果);本会话的修复落盘读核(migrate_restricted.py/bootstrap_loop.py/roleplay_web.ts/bridge.ts + 5 守卫文件存在性)、关键缺陷行号抽读(judgment_manifest/run_tests/verify_runner/token_store/whitebox_llm/hooks)、git 工作树核对(4 文件 +105/-19 + 5 新守卫)、三门禁实跑(run_tests 167/167·exit 0、npm test 49/48/0/1·exit 0、npm run gate 登记 R4 后复跑·exit 0)、三新 python 守卫单跑(15+5+4=24 通过 0 失败)。*
@@ -0,0 +1,187 @@
1
+ # 缺陷挖掘报告 · 自主迭代 v7(性能专项)
2
+
3
+ - **日期**:2026-09-25
4
+ - **范围**(生效条件):第 7 轮 = 性能专项,三区复核(mdcg-retrieval / mdcg-write / runtime)新发现 12 项确认(候选 12 → 确认 12 → 整项证伪 0;另 6 处外部线索/候选口径部分修正,见第三节)+ 本轮修复 5 项(high 3 + medium 2)落盘读核与守卫实跑 + 门禁复现
5
+ - **总量**:新发现确认 **12**(high 3 / medium 5 / low 4)→ 新修 **5**(N48/N53/N54/N56/N55)→ 遗留新增 **7**
6
+ - **回归**:本会话实跑全量 `python scripts/run_tests.py --jobs 4` **SUMMARY 172/172 通过、5 跳过(依赖缺失/平台不符)、退出码 0**(较 v6 的 167 增 5 = 五个新 python 守卫套件入列,尾部输出与材料一致);`cargo test` **未运行**(Rust 面零改动,本会话 `git status` 证改动面仅 md_cg/README/docs);`npm test` **未运行**(TS 面零改动);`npm run gate` **首跑 FAIL**——R4 非追踪件面命中 5 个新守卫测试文件(本会话独立复现,`check_publish_artifact.py` 非追踪=29、允许=24、退出码 1),按守卫要求 `git add` 登记追踪面后全链复跑**通过**(两遍过程见第四节,非修复代码回归,处置同 v6 先例)
7
+ - **行号口径**:缺陷行号为缺陷时点快照行号;md_cg/mdcos.py 本轮多项修复叠加行号漂移,涉及处本会话另注现行行号(如读缓存挂载缺陷时点/修复时点 :341-347 → 现行 :358-368;merge 分支 :2098-2100 → 现行 :2174-2185;`_read_many` 调用 :841 → 现行 :866;`_neg_coverage` :693-705 → 现行 :718;`try_stage` :775-776 → 现行 :800);未修项所在文件(postings.py / orch.py / swarm.rs)本轮零改动,快照行号与现行一致
8
+ - **编号口径**:本报告 N48-N59 沿历轮 N 口径(v6 用至 N47);代码注释锚 issue #31-#35(#31 读缓存默认开 / #32 propose 尾部增量 / #33 快照自动落盘 / #34 merge 定向 upsert / #35 review 单遍读,本会话逐处读核在位)
9
+ - **结构口径**(CCG 六要素):功能名(标题)/ 生效条件(范围与口径行)/ 子功能(第二~五节)/ 执行与验证方式(第四节:实跑命令与结果)/ 不适用条件(第七节:跳过与未运行项)
10
+
11
+ ---
12
+
13
+ ## 一、执行摘要
14
+
15
+ 本轮为性能专项:三个区复核 12 项候选全部确认、0 项整项证伪(6 处外部线索/候选数字修正单独列于第三节末)。修复 5 项、留档 7 项。
16
+
17
+ 修复主题为「重复装载与默认值断裂」,5 项修复对应三个性能反模式:
18
+
19
+ 1. **机制已有但默认值把生产关在门外**(mdcg-retrieval):检索读缓存机制早已落地(issue #31 批次 21/22——MdStore 装载期预计算与检索读缓存,本轮**不重复报为新建**),但 `MDCG_READ_CACHE` 默认关 → 生产检索入口(mcp_server.py:2113/2159/3127 → MdCGSecure(MdCGOS).search)默认态每查询全池逐节点 open+2×realpath+frontmatter 解析,O(n) 线性。本轮只翻默认值并补穿透直读通道(N48,high):3000 池实测 601.7→21.3 ms/查询(28.3×),万级库 ~2s → ~21ms 量级。
20
+ 2. **append-only 面每调用全量重读**(mdcg-write):propose 每条全量重读 inbox+decisions 对账且全部在 strict 排它锁内(O(M²) 批量、万条存量单条几十 ms;N53,high)与 review 治理面单次调用内把同一 jsonl 解析 2-4 遍(N55,medium)——均改为 stat 尾部增量索引/缓存:propose 单条(2000 存量)4.591→0.243 ms(19×,存量不敏感化);review_stats(M=D=4000)15.97→0.87 ms(18.4×)。
21
+ 3. **O(N) 全库扫描兜底常态化**(mdcg-write):索引快照无任何自动落盘路径——「add→close」的库永远没有快照,每次重开全库逐文件解析(N54,high,close 自动落快照+指纹对账:1500 节点 103.6→9.6 ms,10.8×);merge 裁决只改一个节点却 rebuild_index 全库收尾(N56,medium,定向 upsert 与 accept 同源同级:248.1→3.65 ms,68×)。
22
+
23
+ **对输入口径的核验**:输入称「确认 12 → 修复 5 → 留档 7」。本会话以 `git status`/`git diff --stat` + 逐处读核核对:改动面恰为 9 文件 +480/-143(readcache.py +34、fsutil.py +25、mdcg.py +266、mdcos.py +210、govern.py +9、backfill.py 31 行改写、README.md 2 行、test_index_durability.py +16、test_readcache_prodpath.py +30)+ 5 个新守卫文件(test_readcache_default_on / test_propose_tail_index / test_snapshot_autoclose / test_merge_upsert / test_review_onepass),与 5 项修复一一对应;12 − 5 = 7 留档,无多无少。
24
+
25
+ ---
26
+
27
+ ## 二、修复清单(5 项,逐项 where / 问题 / 修复 / 前后基准对比 / 守卫)
28
+
29
+ ### F1(N48,high,issue #31)生产检索读缓存默认开 + 治理面穿透直读
30
+
31
+ - **where**:`md_cg/mdcos.py:341-347`(材料修复时点构造挂载;现行 :358-368,`if _rc.enabled(): _rc.install(self)`)+ `md_cg/readcache.py:38`(`enabled()` 默认翻转:`os.environ.get("MDCG_READ_CACHE","1")=="1"`)+ `md_cg/readcache.py:42`(新增 `direct_read(cg, entry)`)。缺陷链:`mcp_server.py:2113/2159/3127` → MdCGSecure(mdcos.py:3368 继承 MdCGOS)→ `MdCGOS.search` → `mdcos.py:841`(现行 :866)`docs_all = self._read_many(entries, stat)` 全池逐节点 `_read`(每节点 `_node_disk_path` 2×realpath + open + nodefile.loads,常数 ~245µs/节点)
32
+ - **问题**:生产检索入口默认态 O(n) 全池读盘——3000 池实测 823.7 ms/查询(复核机)/6000 池 1133.6 ms,万级外推 1.9-2.7s;该入口无 S7 倒排段(仅 MdCG.search 有,mdcg.py:2453-2505;grep mdcos.py 对 postings/S7 零命中);读缓存机制已存在但默认关 → 生产恒不装配。
33
+ - **修复**(五点):① `enabled()` 默认开,显式 `MDCG_READ_CACHE=0` 为 opt-out 退出阀(回到逐次读盘旧行为);② 构造挂载改走 `_rc.enabled()`;③ 新增 `direct_read`——经 install 保存的 `cg._read_uncached` 穿透缓存直读盘上真值,治理面写前重查 19 处改走它(mreview/govern.py 4 处 + backfill.py 15 处——预演与执行之间他人/外部进程改盘须见真值,mr_m4 D12 漏判 drift 的根因);④ `set_goal_status` 补 `self._dirty[node_id]` 标脏(直写不推 write_gen 会导致 `_goal_entry` 读旧 goal_status);⑤ README.md:220 开关表同步(本会话读核在位)。
34
+ - **前后基准对比**(临时库 3000 knowledge[CCG 六要素+tags/edges/condition_space]+300 rejected,串行 5query×3rep 取中位、预热 1 次不入统计,测后清理):修复前中位 **601.7 ms**/查询(min 556.8/max 626.5,scanned=3000);修复后首轮 18.9 ms(31.8×)→ 补修两个次生回归后终测 **21.3 ms**(min 14.8/max 29.4,**28.3×**);hits 逐查询与修复前一致(23/23/20/20/20),scanned 审计口径不变(仍如实报 3000,缓存只省磁盘不谎报)。与缺陷证据 823.7ms 同象,绝对差来自测量机与节点正文长短(材料注明)。
35
+ - **守卫**:新增 `md_cg/test_readcache_default_on.py`(计数/复杂度断言,非时间阈值):D1a 默认构造即装、D2a 二次检索 `nodefile.loads` 计数==0、D3b 3 次检索累计装载 ≤ 池节点数、D4/D5/D6 opt-out 退出阀/默认态写后不陈旧/开关结果 id 序一致。修复前实跑红(D1a FAIL、D2a second=12=池大小、D3b total=36=3×池);修复后 10/10 绿。既有守卫 test_readcache_prodpath 同步更新(P1 改「默认开 + =0 opt-out 零变更」断言)12/12 绿。
36
+ - **验证**:① 基准脚本修复前后各跑一次+回归修复后终测一次(临时库,测完清理);② 回归排查——git stash 后干净基线实跑 test_mr_m4 88/0、test_p7_goals_recent 36/0(证明两失败系默认开引入),补修后复跑 88/0、36/0;③ 全量套件(材料时点)168/168 → 本会话终态实跑 **172/172**(见第四节)。
37
+
38
+ ### F2(N53,high,issue #32)propose 尾部增量对账索引(锁内 O(M+D)→O(增量))
39
+
40
+ - **where**:`md_cg/mdcos.py:1636-1641`(缺陷时点:strict FileLock 锁内 `read_jsonl(inbox_log)` 全量逐条 json.loads + payload_hash 缺失时逐条 `_sig` sha1 重算;现行对账段 :1662-1666 走 `_inbox_phash_index()`)+ `:1682-1688`(`_pid_status` 原每调用全量 read_jsonl(decisions),现行 :1711 起增量缓存)+ 配套 `md_cg/fsutil.py:228` 新增 `read_jsonl_tail(path, offset)`
41
+ - **问题**:propose 每条全量重读 inbox+decisions 对账——O(M+D)/条、批量累计 O(M²),且全部 IO 在 strict 排它锁内(OS 级排它锁证并发 propose 完全串行);存量无 payload_hash 记录每次逐条重算 sha1 无缓存;writepipe 校验闸下非 ACCEPT 的 MCP write(除 REJECT 走负记忆外)都转 propose 付此税。
42
+ - **修复**:① `fsutil.read_jsonl_tail` 字节偏移增量读(坏行容错与全量读逐位同);② `__init__` 增 6 个缓存属性(inbox phash 索引 + pid 状态表,各带 size/mtime_ns 扫描水位);③ `_inbox_phash_index()`:phash→[(pid,node_id)] 文件序增量索引,旧格式行现算一次 sha1 后常驻;④ `_pid_status` 改 stat 尾部对账(size/mtime 未变零解析,增长只解析新增字节,回退全量重建兜底);⑤ 锁内对账改查两索引——与原全量扫描同序同义(同 phash 按文件序取、已裁决优先 break、pending 取最后一条),dedup/幂等/info 返回形态零变化;跨进程 append 由 stat 自动并入;诚实边界:外部非 append 形态同 size 重写不在合作写者协议内(docstring 声明);review_list/review_stats 等低频读面未动(最小改动面)。
43
+ - **前后基准对比**(临时库、串行、3rep×20 样本取中位,测后清理):单条 propose inbox 存量 200/1000/2000 → 修复前 0.822/2.634/4.591 ms(10× 存量→5.6× 耗时,线性;与缺陷证据 1.020/3.044/5.615 同象)→ 修复后 **0.238/0.242/0.243 ms**(存量 10× 增长耗时不变,2000 存量 **19×**);inbox=1000+decisions=2000:5.379→0.255 ms(**21×**);旧格式(无 payload_hash)2.993→0.246 ms(**12×**,sha1 摊销到装载期一次);批量 500 条 519.9→222.5 ms 总(每条 0.445 ms 为 append/锁等固定 IO,**O(M²) 解析项已消除**,万条外推 ~4.5s,达成 expected_gain 秒级目标)。
44
+ - **守卫**:新增 `md_cg/test_propose_tail_index.py`:T1a 稳态 propose 全量 read_jsonl==0、T2a 500 条批量全量读==0、T5b 旧格式行不触发每条重算(修复前红:T1a full_reads=2/条、T2a full_reads=1000=2×500、T5b=2);正确性臂 T3 跨进程 append dedup 不漏账、T4 外部裁决后增量可见、T5a 旧格式命中、T6 同内容两次 propose 同 pid 幂等(新旧都必须绿)。修复前 5/3 红→修复后 **8/8 绿**。
45
+ - **验证**:基准修复前后各跑一次;守卫红→绿实跑;全量套件(材料时点)169/169 含 test_review_conformance(propose/decide 语义、pid 互异 20 条)/test_twophase → 本会话终态实跑 **172/172**。
46
+
47
+ ### F3(N54,high,issue #33)索引快照 close 自动落盘 + 指纹对账
48
+
49
+ - **where**:`md_cg/mdcg.py` `close()`(缺陷时点 :973-980 只 flush;现行 :1043 起自动落快照,本会话读核注释与分支在位)+ `_load_index`(缺陷时点 :889-913 无快照走 `_scan_nodes` 全库扫描+无条件重放日志)+ `compact_index`(缺陷时点 :926-949,生产零调用——grep 全仓仅 4 处测试调用)+ 新增 `_dir_fingerprint`(现行 :927)与 `_count_md_files`(现行 :949);生产入口 `mcp_server.py:3712 cg.close()` 与 atexit 兜底(mdcg.py:104-110)同经 close 生效
50
+ - **问题**:索引快照无任何自动落盘路径——flush 只 append 分片日志、compact_index 生产零调用、close/atexit 兜底也只 flush,「add→close」的库永远没有快照,每次进程重开都付 `_scan_nodes` 全库逐文件 open+frontmatter 解析 + 无条件重放全部索引日志(在盘面扫描基底上纯冗余);autoflush=1 逐写涨日志、无上界无阈值 compact,重开税随累计写入线性恶化。
51
+ - **修复**:① close 自动落快照——有快照→compact(增量并入+清日志);无快照且有节点→rebuild(历史节点可能无日志记录必须扫一次盘面);空库不写;OSError/ValueError 静默(失败退回改动前行为不丢数据);② compact 两道新防御:快照损坏/schema 不符→降级 `_scan_nodes` 重建基底;重放后与盘面 `_count_md_files()` 计数对账,不符→scan 基底+重放重入(防写出缺账快照);③ `_dir_fingerprint`(LAYERS 目录树 mtime_ns 映射,只 walk 目录不读文件);④ `_load_index` 快照路径加指纹校验——缺失或不符退回全库扫描(保住改动前「盘面真相兜底」契约:其它存活实例未 flush 的写入可见);⑤ 既有守卫 test_index_durability【④】反证组按新语义更新(可见性由盘面接管、atexit 有效变量改为增量日志零记录)。
52
+ - **前后基准对比**(1500/3000 节点临时库、add→close 后反复重开 MdCGOS(root)、串行 3rep×20 次取中位 n=60,测后清理):1500 节点 103.619→**9.610 ms**(**10.8×**,含指纹校验开销)、3000 节点 478.509→**18.636 ms**(**25.7×**),快照存在=True、节点集全量可见一致;5000 节点外推 ~800→~31 ms。缺陷证据同象(108.2/222.9 ms;其 compact 后 5.8 ms 为复核机 json.load 物理成本下限)。中间实证(缺陷复核阶段):重放日志删除前后节点集逐数一致(断言通过,证重放纯冗余)。
53
+ - **回归两面(如实记录)**:全量首跑 169/170 失败 test_identity_attribution(⑩旧节点兼容 4 断言)——git stash 干净基线 19/0 证系本次引入,根因:close 常态化写快照后快照路径不再扫盘面,其它实例未 flush 写入从索引不可见;指纹校验+计数对账修复后 19/0。二次 169/170 失败 test_index_durability【④】反证组——「无 atexit→不可见」前提被指纹兜底失效(**缺陷被修得更彻底非回归**),按新语义更新反证后 16/0。
54
+ - **守卫**:新增 `md_cg/test_snapshot_autoclose.py`:C1a close 后 `_index.json` 存在、C2a 重开 `_scan_nodes` 调用==0、C3a 零日志重放、C4a 节点集一致、C5 尾部写入不丢、C6a/C6b 快照写坏不产空快照、C7 空库不落、C8 实例 A 写不收尾+实例 B close 后重开仍见 A 节点(双保险)。修复前红(C1a/C2a scans=1/C3a replayed=30);修复后 **10/10 绿**。
55
+ - **验证**:基准修复前/初版/含指纹终版各跑;全量套件(材料时点)170/170 含 test_p0/test_p24_evidence/test_p38_concurrent_flush(compact/并发 flush 语义)→ 本会话终态实跑 **172/172**。
56
+
57
+ ### F4(N56,medium,issue #34)merge 裁决定向 upsert 收尾(O(N)→O(1))
58
+
59
+ - **where**:`md_cg/mdcos.py:2032-2034`(缺陷时点 merge 分支 `_write_node` 直写后 `self.rebuild_index()` 收尾;现行 :2174-2185 定向 upsert,本会话读核在位)+ 对照 accept/edit 分支(:2009-2016 缺陷时点,add+flush 增量收尾)+ 配套 `md_cg/mdcg.py:1070` 新增 `_node_entry`(`_scan_nodes` 条目构造提取为**同源唯一真源**,33 键字段集零漂移由构造保证;`_scan_nodes` 行为零变化)
60
+ - **问题**:merge 裁决只改一个目标节点(content 追加+不适用条件并集)却用 rebuild_index 收尾——`_scan_nodes` 全库逐文件 open+parse(O(N) 文件 IO)+全量快照重写+清日志,而 accept/edit 同场景走 add+flush 增量收尾(O(1))。
61
+ - **修复**:merge 分支改定向 upsert——单文件重读+parse → `_node_entry` 同源条目 → `index["nodes"][target]=e2` + `_dirty[target]=e2` + flush;不走 `_stage`(目标已在索引,会虚增 bucket 计数;merge 不改 tags/目录 bucket 不变);`_dirty` 置数同时推进 readcache 代际(写盘后同实例不陈旧);单文件重读 OSError 静默(极罕见,条目留旧值待下次 rebuild 对账)。
62
+ - **前后基准对比**(每 rep 全新 1500 节点临时库+merge_target、串行 3 rep 取中位,测后清理):accept=3.46 ms(对照)vs merge 修复前 **248.14 ms**(rep 118.24/248.14/261.04,页缓存冷热波动;`rebuild_index` 单独=247.08 ms,merge−rebuild≈1 ms≈accept 全额成本,差值即 rebuild 税;与缺陷证据 3.34/100.85/96.88 同象,本机正文更长绝对值更高)→ 修复后 accept=3.64、merge=**3.65 ms**(**68×,与 accept 同级**,expected_gain 精确达成);rebuild 佐证臂 115.50 ms 未受影响;5000 节点外推 ~330→~5 ms。
63
+ - **守卫**:新增 `md_cg/test_merge_upsert.py`:M1a merge 期间 `_scan_nodes` 调用==0(修复前红 scans=1)、M2a upsert 条目与再 rebuild 的条目**逐位相等**(同源零漂移)、M3a-e merge 语义回归面(ok+node_id/content 追加/不适用条件并集/裁决记录 accepted/级联关闭同内容兄弟提案)、M4a-b accept 对照零扫描、M5a-b merge 后新进程重开可见(增量账本不靠 rebuild 救回)。修复前 10/1 → 修复后 **11/11 绿**。
64
+ - **验证**:基准修复前后各跑;`python -c ast.parse` 语法验证(提取重构 56 行缩进重排);全量套件(材料时点)171/171 含 test_review_conformance(merge 裁决语义/级联)→ 本会话终态实跑 **172/172**。
65
+
66
+ ### F5(N55,medium,issue #35)review 治理面单遍读(全记录增量缓存)
67
+
68
+ - **where**:`md_cg/mdcos.py` 五调用点(缺陷时点)——review_list :1829 / review_stats by_decision :1788 / `_cascade_dedup` :1983 / verify_review_record :2036 / review_decide 找 pid :2070 + 新增 `_inbox_records`(现行 :1768)与 `_decisions_records`(现行 :1793;现行五调用点 :1831/:1854/:1985/:2038/:2080,本会话读核在位)
69
+ - **问题**:review 治理面单次调用内重复全量打开同一 jsonl 并整文件逐行 json.loads——review_stats 把 decisions 解析 4 遍(复核实测计数:打开 4 次读行 200=4×50)+inbox 1 次;review_decide(reject) 把 inbox 读 2 遍+decisions 读 3 遍;verify_review_record 无 pid 索引线性扫全量找单条——浪费倍数固定,解析量随 D/M 线性放大。
70
+ - **修复**:① `__init__` 增两组全记录增量缓存属性(各带 size/mtime_ns 水位);② `_inbox_records`/`_decisions_records` 与 `_pid_status` 同款 stat 尾部对账(未变零解析、增长增量并入、回退全量重建、跨进程 append 自动并入),返回内部缓存列表(调用方只读不得变更);③ 五调用点改内存线性扫。**未扩面(如实说明)**:review_rounds(同形态但缺陷未点名)与 decisions() 公开导出 API 仍走每次全量读——低频/导出面,保持最小改动。
71
+ - **前后基准对比**(每臂独立临时库 M 条 inbox+D 条 decisions 存量、串行 3rep×15 取中位、预热一次后计,测后清理;注:基线已含前序 F2 的 `_pid_status` 增量缓存,故低于缺陷证据 9.53/39.74 ms——decisions 侧重复已被 F2 消掉一部分,剩余如实测):review_stats M=D=1000→4.03 ms / M=D=4000→15.97 ms → 修复后 **0.26/0.87 ms**(**15.5×/18.4×**,存量不敏感);review_decide(reject 纯 pending) 7.15/21.31→**2.12/2.64 ms**(3.4×/8×,剩余为裁决落盘/审计节点写盘固定成本);verify_review_record 10.08/28.92→**3.33/3.86 ms**(3×/7.5×)。
72
+ - **守卫**:新增 `md_cg/test_review_onepass.py`:R1a 预热后 review_stats 全量 read_jsonl==0、R2a 稳态 decide(reject) 零全量读(修复中首测仍 1 次,栈回溯实跑定位为 phash 索引首装+decisions 创建后 pid 状态首装,属预期装载非稳态重复)、R3a verify 链路零全量读、R4 跨进程 append 增量并入、R5 语义对账(records/by_decision/proposals 与独立全量直读口径逐项一致——缓存只改速度不改结果)。修复前 7/3 红 → 修复后 **10/10 绿**。
73
+ - **验证**:基准两规模修复前后各跑;守卫红→绿实跑;全量套件(材料时点)172/172 含 test_review_conformance/test_propose_tail_index/test_merge_upsert → 本会话终态实跑 **172/172**(见第四节)。
74
+
75
+ ---
76
+
77
+ ## 三、发现明细(确认 12 项 / 整项证伪 0 项 / 外部线索核实 6 处)
78
+
79
+ 三区复核 12 项候选全部确认,**rejected 数组均为空**(零整项证伪)——如实记录。以下每项「证据」为上游复核会话的读码+实跑(材料原文,环境细节按仓库口径转录);标注★者本会话另做了关键行抽读核实。
80
+
81
+ ### mdcg-retrieval 区(5 项,1 项已修,4 项留档)
82
+
83
+ | # | where(缺陷时点) | 严重度 | 问题摘要 | 证据要点 | 状态 |
84
+ |---|------|--------|----------|----------|------|
85
+ | N48★ | md_cg/mdcos.py:841(现行 :866) | high | 生产检索入口每查询全池逐节点 open+2×realpath+frontmatter 解析,O(n)、~245µs/节点;无 S7 倒排段(仅 MdCG.search 有);读缓存默认关生产恒不装配 | cProfile 单查询 1.102s 中 `_read_many` cum 0.734s(67%)、`_node_disk_path` 0.378s(realpath 6600 次 0.359s)、nodefile.loads 0.291s;实测 3000 池 823.7ms/查询、6000 池 1133.6ms(scanned=6000,线性成立,万级外推 1.9-2.7s);对照臂 MDCG_READ_CACHE=1→21.5ms(38×)、backfill+S1 门控→90.0ms(9.2×,gates.s1={in:214,dropped:2786}、scanned=214) | **已修**(F1) |
86
+ | N49★ | md_cg/mdcos.py:693-705(现行 :718;调用点 :772;include_neg 默认 True :710);MdCG.search 同型 mdcg.py:2336-2357 | medium | 每查询无条件 open+parse 全部 rejected/unresolved 节点仅做 any 子串词面检查——负记忆随库龄累积每查询固定线性加税;且 scanned 只在 `_read_many` 累加,这部分 IO 对 meta 不可见(审计盲区) | 300 负节点 `_neg_coverage` 44.4ms(148µs/负节点,计数 `_read` 恰 300 次)、600 负节点 85.3ms(2×规模→1.92×耗时线性);端到端 include_neg=True/False 查询差 50.5ms@300/102ms@600,两口径 meta.scanned 完全相同(3000/6000)——审计盲区证实 | 留档 |
87
+ | N50★ | md_cg/mdcos.py:883+932+954/961(现行 :893/:951/:968) | medium | search_rrf 四路召回各自独立读盘:`_lexical` 全池 `_read_many` 后 `_path_entity` 对 tag 命中再 `_read`(实测 600 命中全量重读)、`_path_graph` 种子 get()+邻居 `_read`——同一节点文件单查询最多 open+parse 3 次,重复 IO 随 tag 命中规模线性增长 | 3000 池 3rep 中位 599.3ms:包装计数 `_read` 3604 次、不同 path 3000 → 重复读 604 次(20.1%),get 恰 5 次;cProfile `_path_entity` cum 0.133s / search_rrf 0.901s(15%),`_lexical` 内 `_read_many` 0.638s | 留档 |
88
+ | N51 | md_cg/mdcos.py:847-851+775-776(现行 :800);md_cg/mdcg.py:2553-2557+2371-2375;T3 双跑 mdcos.py:857-862 / mdcg.py:2576-2581 | low | T2 先 `_score(hits)` 供截断、截断后 try_stage 又对 ≤500 条完整重算(normalize_en+bigram set);T3 兜底 `_score(docs_all)+_score(picked)` 双跑;mdcos 侧 try_stage 根本没有 scored 形参,mdcg 侧有参数但 T2 调用未传 | 计数器包装实测:3000 池每查询 `_score` 4 次、`_doc_norm_bigrams` 3500 次(=3000 全量+500 截断后重算,与原报告完全一致);6000 池 6500 次。浪费恒为 GLOBAL_CAP=500 文档重打分 ≈33ms,占查询 ~3% | 留档 |
89
+ | N52 | md_cg/postings.py:122-159 经 md_cg/mdcg.py:2477 每查询调用 | low | 发布表快照指纹校验对全部节点目录逐个 os.stat(随目录数线性,600 目录=601 次 stat/查询),S7 启用者每查询恒付 ~10-30ms 级 stat 税;且 S7 未接生产 MdCGOS.search(grep 证实仅 mdcg.py 有) | 600 节点/600 单例桶目录临时库新鲜态 3rep 中位 9.7ms、每次 601 个 os.stat、16.2µs/目录;真实库 1074 目录外推 ≈17ms(模块 docstring 自认 ≈0.03s 同量级);调用链仅 MdCG.search 且 `_s7` 需 PIPELINE=1+GATE_S7_POSTINGS=1(默认关) | 留档 |
90
+
91
+ ### mdcg-write 区(4 项,全部已修见第二节)
92
+
93
+ | # | where(缺陷时点) | 严重度 | 问题摘要 | 证据要点 | 状态 |
94
+ |---|------|--------|----------|----------|------|
95
+ | N53★ | md_cg/mdcos.py:1636-1641+1682-1688;md_cg/writepipe.py:188-200 | high | propose 每条全量重读 inbox+decisions 对账——O(M+D)/条、批量累计 O(M²),全部 IO 在 strict 排它锁内(并发完全串行);存量无 payload_hash 每条逐次重算 sha1;writepipe 闸下非 ACCEPT 的 MCP write 转 propose 付此税 | 3rep×20 中位:inbox 存量 200/1000/2000 → 单条 1.020/3.044/5.615ms(增量斜率 ~2.6µs/存量条线性);+decisions 2000 → 6.832ms(≈1.9µs/条);旧格式 1000 条 → +0.38ms(重算 1000 次 sha1);万条外推 ~26ms;OS 级排它锁与 writepipe 分支读码核实 | **已修**(F2) |
96
+ | N54★ | md_cg/mdcg.py:902-913+951-971+926-949+103-106;md_cg/mcp_server.py:3614 | high | 索引快照无任何自动落盘路径(flush 只 append、compact_index 生产零调用、close/atexit 只 flush)——「add→close」的库永远没有快照,每次重开 `_scan_nodes` 全库扫描+无条件重放日志;autoflush=1 逐写涨日志无上界,重开税随累计写入线性恶化 | 1500 节点临时库 3rep×20 中位:A 重开 108.217ms / B 删重放日志 97.628ms 且节点集逐数一致(证重放纯冗余净贡献 ~10.6ms)/ C compact 后 5.824ms(18.6×);3000 节点 222.880/195.760/11.850ms 线性放大;grep compact_index 仅 4 处测试调用;rebuild_index(mdcg.py:1070-1079)也写快照但常规 add→close 路径不触发(实测 assert 证实) | **已修**(F3) |
97
+ | N55★ | md_cg/mdcos.py:1713-1730+1942-1946+1955+1850-1851+1902-1904 | medium | review 治理面单次调用内重复全量打开同一 jsonl:review_stats 把 decisions 解析 4 遍;review_decide(reject) inbox 2 遍+decisions 3 遍;verify_review_record 线性扫全量找单条——浪费倍数固定,解析量随 D/M 线性放大 | monkeypatch read_jsonl 计数:review_stats→decisions 打开 4 次(读行 200=4×50)+inbox 1 次;decide(reject 纯 pending pid)→inbox 2 次+decisions 3 次;verify→decisions 1 次全量找 1 条;墙钟 M=D=1000→9.53ms / 4000→39.74ms(≈5.3-5.5× 单遍解析,线性);首测曾误用已裁决 pid 触发早退,换纯 pending pid 后复现完整路径(如实记录) | **已修**(F5) |
98
+ | N56★ | md_cg/mdcos.py:2032-2034(对照 :2009-2016;rebuild 实现 mdcg.py:1070-1079) | medium | merge 裁决只改一个目标节点却 rebuild_index 收尾(`_scan_nodes` 全库 O(N) 文件 IO+全量快照重写+清日志),accept/edit 同场景 add+flush 增量收尾 O(1)——批量运维模块同款模式佐证系统性,本条只报 review_decide.merge | 每 rep 全新 1500 节点库 3 rep 中位:accept=3.34ms vs merge=100.85ms(30×)、rebuild 单独=96.88ms、merge−rebuild≈3.97ms≈accept 全额——差值即 rebuild 税(与原报告逐位吻合);5000 节点外推 ~330ms 与 3000 节点扫描 195.8ms 线性外推一致 | **已修**(F4) |
99
+
100
+ ### runtime 区(3 项,全部留档)
101
+
102
+ | # | where | 严重度 | 问题摘要 | 证据要点 | 状态 |
103
+ |---|------|--------|----------|----------|------|
104
+ | N57 | swarm/rust_runtime/src/swarm.rs:463-532 | medium | WAL 恢复链路重复装载/重复计算且随生命周期线性无界增长:重放对全 WAL 两遍完整「解析+HMAC 验签」,聚合报告再对全部事件(含重放前缀)第三遍验签;好行前缀 ~3× WAL 常驻并在部分恢复时整文件重写;无任何压缩/截断(grep 无 truncate/compact/set_len,每轮至少 1 快照行)——长寿命蜂群每次重启付 O(累计事件数) 税 | 临时目录 release 构建独立形态 + 5 实例 2 条 gossip 路由 fan-out=4(≈14 行/轮),串行单进程各 3 次取中位:R=50/200/800 → WAL 695/2797/11203 行,fresh 69.7/189.7/660.5ms,resume 17.2/52.2/185.6ms;线性拟合 resume_ms = 6.7 + 16.0µs×行数,R²=0.9999;resume 走早退路径已验证(WAL mtime 不变、events 计数幂等) | 留档 |
105
+ | N58 | hive/orch.py:445-460 | low | `_poll` 每次轮询对全部子任务全量重读+重解析 status.json 与完整 result.json 只为渲染 200 字卡片——无读缓存/终态短路;附带 `_card` 线性扫 children + `i not in known` 列表扫 → 每次 poll O(C²) | 合成子任务串行 5 次取中位:C=8 × result 5/50/500KB → 0.71/1.16/10.33ms;C=32 → 2.77/4.86/36.39ms;对照组(无 result.json)C=8/32 → 0.32/1.30ms;单卡计时 ×C 占 poll 92-97%(证 ~97% poll 成本在 result.json 全量解析);C=8→32(500KB)3.52× 线性叠加 | 留档 |
106
+ | N59 | swarm/rust_runtime/src/swarm.rs:1036-1052 | low | WAL 落盘无用户态缓冲:每事件行一次 write_all 直接 syscall(~3.1µs/行);轮末 wal.flush() 对裸 File 是文档化 no-op——B1 纪律注释「事件行先 durable(flush)」与实际语义不符,缓冲化空间被放弃 | syscall 级微基准(rustc -O,800 轮×14 行×200B+轮末 flush+sync_all,3 次):裸 File 336.3/325.9/313.8ms vs BufWriter 300.3/287.6/284.8ms(写阶段 ~10%,两形态输出 cmp 字节级一致);端到端 R=800 fresh 交替串行各 5 次中位:base 689.3 vs buf 664.8ms(3.5%),WAL 行数一致 11203=11203 | 留档 |
107
+
108
+ ### 外部线索与候选口径核实结论(部分修正 6 处,如实记录)
109
+
110
+ 1. **外部线索 3「S1 门控在排序后」的机制描述——证伪成立**:实测 `MDCG_RETRIEVAL_PIPELINE=1` 时 meta `gates.s1={in:214,dropped:2786}`、scanned=214——门控在 `_read_many` **之前**生效(mdcos.py:768→841)、scanned 诚实下降;原线索的 scanned=142 系门控默认关(`MDCG_RETRIEVAL_PIPELINE≠"1"` 时原样返回,mdcg.py:680-681)所致。门控机制本身可用,缺的是默认值/backfill 元数据(已由 F1 路径覆盖读缓存方案)。
111
+ 2. **「edges 零参与」口径**:对生产 `cg.search`(mdcos.py:708-865)默认路径**成立**(无任何 edges 消费;S3 仅 MdCG.search flag 控、reach 默认关——reach.py:109-110);对 search_rrf **不成立**(`_path_graph` 为默认四路之一)——与原报告定性一致。
112
+ 3. **候选「compact 后 0.51ms/200×」不可复现**:复核机实测 compact 后 5.8ms/18.6×(1500 条目快照 json.load 物理成本 ~5ms);机制与结论全部成立(F3 落地后 5000 节点外推 ~20ms 与基准员热点 #5 的 355.3→29.2ms 汇报吻合)。
113
+ 4. **「新鲜或过期都要付 stat 税」不完全准确**(N52):node_count_changed/dirs_changed 等过期形态在 stat 循环前即返回、dir_touched 提前退出——全量 stat 税在**稳态(新鲜)**每查询恒付成立,过期态通常更便宜;不影响主体结论与 low 定级。
114
+ 5. **「所有非 ACCEPT 都转 propose」略不精确**(N53):writepipe `_gate_audit` 中 REJECT 走负记忆 add_rejected,其余(DEFER 等)才转 propose——结论不变。
115
+ 6. **N59 候选估算 5-10% 略偏高**:实测写阶段 ~10%、fresh 全链路 3.5%——方向正确、同量级。
116
+
117
+ 另如实声明:N57 候选证据中「mdcg 索引日志 compact 实测 12×」为背景参照,本轮未独立复核。
118
+
119
+ ---
120
+
121
+ ## 四、验证(门禁结果 + 性能测量条件)
122
+
123
+ 以下「本会话实跑」均为**本报告写作者本会话实际运行**(仓库根目录):
124
+
125
+ | 命令 | 结果(原文数字) | 退出码 |
126
+ |------|------------------|--------|
127
+ | `python scripts/run_tests.py --jobs 4`(全量) | `===== SUMMARY 172/172 通过,5 跳过(依赖缺失/平台不符) =====`(尾部 PASS 项与材料逐行一致:swarm.tests.test_swarm_fault / hive.test_wm_progress / swarm.tests.test_rust_swarm;172 = v6 基线 167 + 5 个新 python 守卫套件,全部含于本次实跑内) | **0** |
128
+ | `python scripts/check_publish_artifact.py`(`npm run gate` 第 2 环,先单独复现失败) | `[FAIL] R4 非追踪件面 命中=5;非追踪=29,允许=24`,命中恰为 5 个新守卫测试文件(test_merge_upsert / test_propose_tail_index / test_readcache_default_on / test_review_onepass / test_snapshot_autoclose);R1 凭据/密钥面、R2 私有数据面、R3 隐私文本均 PASS | **1** |
129
+ | `npm run gate`(check_unreachable + check_publish_artifact + cogmap_sync check + link_check + workspace_index --check + verify_discipline;5 守卫与本报告文件 `git add` 登记追踪面后全链复跑) | 登记后全链复跑**通过**(R1-R4 全 PASS、非追踪=24=允许、链接可达、工作区索引 OK、纪律注入面 0 冲突;与材料首跑 FAIL 同因同置——非修复代码回归,登记动作同 v6 先例,未做任何 commit) | **0** |
130
+ | `cargo test` | **未运行**(材料口径:Rust 面零改动;本会话 `git status` 证实改动面仅 md_cg/ + README.md + docs/——N57/N59 所在 swarm/ 本轮未动,运行无对象变化) | — |
131
+ | `npm test` | **未运行**(材料口径:TS 面零改动;本会话同上证实 src/ 与 test/ 零改动) | — |
132
+
133
+ **性能测量条件统一声明**(第二~三节全部数字适用,材料口径转录):① 同环境**串行**测量(禁止并行测量——本仓 #30 教训:负载敏感基准仅串行),修复前后同脚本同规模同环境对比;② 每项至少 3 次取中位(规模与 rep 数逐项注明:5query×3rep / 3rep×20 / 3rep×15 / 3 rep / 5 次等),部分臂预热 1 次不入统计;③ 数据规模逐项注明(池节点数 / inbox·decisions 存量条数 / WAL 行数 / 子任务数×result 大小);④ 基准脚本与临时库一律建在系统临时区独立目录(各臂互不干扰),**测完即清理**(材料逐项声明「测后已删/测完清理」);⑤ 本会话(报告写作会话)**未重跑性能基准**——基准数字为上游修复会话实测(材料原文),本会话实跑的是测试套件与门禁两项;⑥ 每项基准均带修复前对照臂(红态),守卫断言采用计数/复杂度/存在性形态而非时间阈值(避免机器敏感的脆弱守卫)。
134
+
135
+ **上游会话已运行、本会话未重跑的验证**(如实区分,材料原文):五项守卫的「修复前红态」对照(D1a/D2a/D3b 红、T1a/T2a/T5b 红、C1a/C2a/C3a 红、M1a 红、R1a/R2a/R3a 红);F1 的回归排查两件(git stash 干净基线 test_mr_m4 88/0、test_p7_goals_recent 36/0,证两失败系默认开引入);F3 的中间回归两面(test_identity_attribution 4 断言、test_index_durability【④】反证组语义更新)——其终态覆盖面均含于本会话全量 172/172 之内;12 项发现的复现实验(cProfile/计数器包装/临时库基准)均在三区复核会话完成,证据要点已摘录进第三节各表。
136
+
137
+ **git 工作树核对**(本会话):`git status`/`git diff --stat` —— 改动 9 文件 +480/-143(README.md 2、backfill.py 31、fsutil.py +25、mdcg.py +266、mdcos.py +210、govern.py +9、readcache.py +34、test_index_durability.py +16、test_readcache_prodpath.py +30)+ 5 个新守卫文件(已按 R4 登记)+ 本报告文件(已登记),与五项修复一一对应,无多余改动面。
138
+
139
+ ---
140
+
141
+ ## 五、遗留清单(留档 7 项逐项)
142
+
143
+ ### medium(3 项)
144
+
145
+ | # | where(现行) | 问题 | 留档理由(材料分诊注要点) |
146
+ |---|------|------|--------------------------|
147
+ | N49 | md_cg/mdcos.py:718(调用点与 include_neg 默认值同前) | 负层每查询全量 open+parse,scanned 审计盲区 | 与 F1 同源——负层读亦走 `self._read`,读缓存默认开后**大概率被覆盖**;F1 已于本轮落地,待复测确认后再决定是否独立修(含 scanned 口径修正) |
148
+ | N50 | md_cg/mdcos.py:893+951+968 | search_rrf 四路重复读盘(同节点单查询最多 3 次 open+parse,实测 20.1% 重复率) | 与 F1 同源(重复读均经 `self._read`/get),读缓存默认开后自动受益,待复测确认 |
149
+ | N57 | swarm/rust_runtime/src/swarm.rs:463-532 | WAL 恢复三遍验签/3× 常驻/无截断,重启成本随累计事件数线性无界 | runtime 区**下轮首选候选**——低风险部分收益 ~2×,但涉 HMAC 验签语义的 Rust 共识路径重构,风险高于本轮全部入选项,且本轮 5 席均被更高收益/更低风险的 mdcg 项占据 |
150
+
151
+ ### low(4 项)
152
+
153
+ | # | where | 问题 | 留档理由/备注 |
154
+ |---|------|------|--------------|
155
+ | N51 | md_cg/mdcos.py:800(try_stage 无 scored 形参);mdcg.py:2553-2557 | T2/T3 重打分,每查询恒付 GLOBAL_CAP=500 文档 ≈33ms | low 定级+绝对节省有限;但 F1 落地后总耗时降至 ~21.5ms 量级时该常数占比显著上升,**值得届时复评优先级**(mdcg 侧 reach 分支已是现成传参模板) |
156
+ | N52 | md_cg/postings.py:122-159 | 发布表指纹校验逐目录 os.stat(S7 启用者每查询 ~10-30ms 纯 stat) | S7 默认关且未接生产 MdCGOS.search 入口,受益面窄于本轮入选项;修法(指纹 TTL 化/折叠为索引 mtime 单点校验)+ S7 接生产入口宜一轮配齐 |
157
+ | N58 | hive/orch.py:445-460 | `_poll` 全量重读重解析 result.json 渲染 200 字卡片,O(C²) 附带 | low 定级恰当(默认规模 8×小结果绝对值毫秒级,属重复装载模式而非热点);修法(终态缓存/终态位短路)清晰但本轮名额让给 mdcg 高收益项 |
158
+ | N59 | swarm/rust_runtime/src/swarm.rs:1036-1052 | WAL 落盘无用户态缓冲(~3.1µs/行 syscall),flush 注释语义不符 | 守卫难以脱离 tracing 做 syscall 计数断言,确定性弱于本轮入选项;补丁本身 2 处且 WAL 等价性已在临时副本验证,可与 N57 同轮处置 |
159
+
160
+ **优先级建议**:N49/N50 先做「F1 落地后复测」(读缓存可能已覆盖大半,复测数据决定是否还值得独立修);N57+N59 同轮处置 runtime 区(WAL 恢复重构 + BufWriter,均涉 swarm.rs,守卫方案需一并设计);N51 在检索耗时进入 ~20ms 量级后复评;N52 与「S7 接生产入口」合并一轮;N58 按批次缓收。
161
+
162
+ ---
163
+
164
+ ## 六、纪律合规声明
165
+
166
+ 1. **定位先读索引**:本报告写作前已读 WORKSPACE_INDEX.md(按职责定位 docs/ 为文档归域、md_cg/ 为记忆系统本体、scripts/ 为工程管线),未做全盘浏览。
167
+ 2. **结论引证**:所有修复与缺陷均引 path:line(缺陷时点快照行号,本轮 mdcos.py/mdcg.py 行号漂移处另注现行行号并经本会话 grep/sed 读核);第三节证据要点摘自任务输入的三区复核材料(上游会话读码+实跑,环境细节按仓库口径转录);第四节两项门禁数字为本会话实跑原文输出;未实际运行的检查(cargo test / npm test / 性能基准重跑)均如实标注,无一冒充。
168
+ 3. **修复落盘核验**:五项修复的现行代码本会话逐处读核(readcache.py:38 enabled 默认开 + :42 direct_read、mdcos.py:358-368 挂载段 + :329 #32/:339 #35 缓存属性 + :1662-1666 增量对账 + :1739/:1768/:1793 三索引 + :2174-2185 merge 定向 upsert、mdcg.py:927/:949 指纹与计数 + :1043 close 自动落快照 + :1070 _node_entry、fsutil.py:228 read_jsonl_tail、README.md:220 开关表),git 工作树改动面(9 文件 +480/-143 + 5 新守卫)与五项一一对应。
169
+ 4. **性能测量纪律**:第二~三节全部性能数字的材料口径均为同环境串行、≥3 次取中位、规模逐项注明、临时库/临时目录建在系统临时区且测后清理、修复前后同脚本同条件对照(第四节第五条统一声明);守卫采用计数/复杂度/存在性断言而非时间阈值;本会话未重跑基准(如实声明,未将材料数字冒充为本会话实测)。
170
+ 5. **已修项不重复报**:MdStore.search_content 装载期预计算与检索读缓存为既有成果(issue #31 批次 21/22)——本轮 F1 报告的是**默认值翻转 + 穿透直读通道 + 治理面直读改道**(生产恒不装配的断裂),非缓存机制新建;报告行文已区分。
171
+ 6. **隐私脱敏**:全文只写仓库相对路径;材料的本机绝对路径(临时区路径含用户名)一律转录为「系统临时区/临时库 + 脚本名」;环境变量名(MDCG_READ_CACHE/MDCG_RETRIEVAL_PIPELINE 等)为源码标识符非凭据值,为证据必需而保留;无任何 key/token 值出现(check_publish_artifact R1 凭据面 PASS 佐证包内零凭据);定稿前经机械扫描复查(盘符路径/用户目录路径/token 形态零命中,见下方自查)。
172
+
173
+ ---
174
+
175
+ ## 七、跳过项及原因
176
+
177
+ - **修复跳过**:无「确认后静默丢弃」——12 项确认中 5 项本轮修复(3 high 全修 + mdcg-write 区 2 medium),余 7 项全部列入第五节遗留清单并逐项给分诊注与复测/下轮条件。
178
+ - **cargo test / npm test 未运行**(材料与本会话一致未跑):Rust 面与 TS 面本轮零改动——本会话 `git status` 证实改动面仅 md_cg/ + README.md + docs/,运行无对象变化;如后续 N57/N59 处置 swarm.rs 时须补跑 cargo test。
179
+ - **性能基准本会话未重跑**:基准数字(含修复前后对照)为上游修复会话串行实测(材料原文),本会话以全量测试套件 172/172 + 门禁复现覆盖终态;重跑需重建同规模临时库,不在本报告写作任务面内。
180
+ - **runtime 区三项(N57/N58/N59)确认但全部留档**:N57 属 Rust 共识路径重构(HMAC 验签语义),风险高于本轮全部入选项且本轮 5 席已被更高收益/更低风险项占据(材料分诊注原文);N59 守卫难以脱离 tracing 做 syscall 计数断言;N58 默认规模绝对值毫秒级。
181
+ - **N51/N52 留档**:均 low 定级——N51 待 F1 落地后检索耗时进入 ~20ms 量级时复评占比再定优先级;N52 受益面窄(S7 默认关且未接生产入口),宜与「S7 接生产入口」合并一轮。
182
+ - **`npm run gate` 首跑 FAIL 的处置**:R4 非追踪件面命中 5 个新守卫文件(本会话独立复现,非追踪=29 允许=24)——按守卫自身要求 `git add` 登记追踪面后全链复跑通过(非代码回归;登记非提交,同 v6 先例)。
183
+ - **本报告文件未做 git 提交**(commit 需任务方指令);仅按 R4 守卫要求 git add 登记追踪面(含 5 个新守卫测试文件),提交由后续流程处置。
184
+
185
+ ---
186
+
187
+ *报告依据:任务输入的第 7 轮材料(三区复核 12 项确认明细及证据、五项修复的 where/基准前后对比/守卫/verified_by、留档 7 项及分诊注、门禁结果);本会话的修复落盘读核(readcache/fsutil/mdcg/mdcos/govern/backfill 关键锚点 + README:220)、未修项现行行号核对(mdcos.py:718/:800/:866/:893/:951/:968、postings.py:122、orch.py:445)、git 工作树核对(9 文件 +480/-143 + 5 新守卫)、门禁实跑(run_tests --jobs 4 → 172/172·exit 0;check_publish_artifact 单独复现 R4 FAIL·exit 1 → git add 登记后 npm run gate 全链复跑通过)、报告脱敏机械扫描。*