@furongjun1999/dsh-memory 0.4.7 → 0.4.9

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 (325) hide show
  1. package/README.md +130 -47
  2. package/codebuddy/CODEBUDDY.md +21 -10
  3. package/codebuddy/README.md +13 -1
  4. package/codebuddy/mcp.json +9 -0
  5. package/docs/GBrain/345/217/257/345/200/237/351/211/264/347/202/271_/347/201/265/346/236/242/350/220/275/347/202/271/344/272/244/346/216/245_20260919.md +169 -0
  6. package/docs/Pi/345/217/257/345/255/246/344/271/240/344/274/230/347/202/271_/347/201/265/346/236/242/345/244/247/350/204/221/346/224/271/350/277/233/344/272/244/346/216/245_20260915.md +144 -0
  7. package/docs/README.md +111 -0
  8. package/docs/discipline/harnesses.yaml +226 -152
  9. package/docs/discipline/templates/full.md.tmpl +61 -58
  10. package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_LoCoMo_/347/201/265/346/236/242_.md +127 -0
  11. package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_LoCoMo_/347/201/265/346/236/242_.png +0 -0
  12. package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_/347/201/265/346/236/242_vs_dejavu_/347/273/237/344/270/200/350/257/204/345/210/206_v7.md +202 -0
  13. package/docs/experiments/linkref_backfill/candidates_20260917.json +726 -0
  14. package/docs/experiments/linkref_backfill/candidates_internal_20260917.json +602 -0
  15. package/docs/experiments/linkref_backfill/candidates_internal_v2.json +603 -0
  16. package/docs/experiments/linkref_backfill/candidates_secret_20260917.json +884 -0
  17. package/docs/experiments/linkref_backfill/candidates_secret_v2.json +789 -0
  18. package/docs/experiments/m4-role-probe/census.py +86 -0
  19. package/docs/experiments/m4-role-probe/probe.py +89 -0
  20. package/docs/experiments/mapped_confidence/bench_mapped_conf.py +216 -0
  21. package/docs/experiments/mapped_confidence/post_check.py +75 -0
  22. package/docs/experiments/mapped_confidence/repro_thirdparty_tol.py +83 -0
  23. package/docs/experiments/mapped_confidence/result_mapped_conf.json +215 -0
  24. package/docs/hive//345/244/232/347/253/257harness/351/200/232/344/277/241/345/245/221/347/272/246_v0.1.md +42 -0
  25. package/docs/hive//346/243/200/347/264/242/346/224/266/346/225/233/345/256/236/346/265/213/344/270/216S1b/350/256/276/350/256/241_v0.1.md +43 -0
  26. 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 +102 -0
  27. package/docs/hive//347/234/237/345/256/236/345/272/223/347/253/257/345/210/260/347/253/257/345/256/236/346/265/213_S1b/344/270/216/345/217/254/345/233/236/346/235/203/350/241/241_v0.1.md +57 -0
  28. package/docs/hive//347/234/237/345/256/236/345/272/223/347/253/257/345/210/260/347/253/257/345/256/236/346/265/213_S7/345/200/222/346/216/222/345/200/231/351/200/211/345/261/202_v0.1.md +126 -0
  29. 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 +503 -0
  30. package/docs/{ → hive/}/350/234/202/345/267/242/345/267/245/344/275/234/350/256/260/345/277/206_/351/241/271/347/233/256/350/256/241/345/210/222.md +14 -2
  31. package/docs/mdcg/D_meta_/345/267/245/347/250/213/345/214/226/346/226/271/346/241/210_v0.2.md +216 -0
  32. package/docs/{README → mdcg/README}/350/257/246/347/273/206/347/211/210_v0.4.5.md +631 -625
  33. package/docs/{ → mdcg/}/344/270/273/344/273/243/347/220/206/345/255/220/344/273/243/347/220/206/350/256/260/345/277/206/346/236/266/346/236/204/350/256/276/350/256/241.md +1 -1
  34. package/docs/mdcg//344/273/243/347/240/201/350/257/204/345/256/241/344/270/216/346/235/241/344/273/266/345/214/226/346/263/250/351/207/212_/345/245/221/347/272/246_v0.1.md +82 -0
  35. package/docs/mdcg//345/205/250/345/272/223/344/273/243/347/240/201/350/257/204/345/256/241/344/270/216/346/235/241/344/273/266/345/214/226/346/263/250/351/207/212_/350/256/241/345/210/222_v0.1.md +600 -0
  36. 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 +263 -0
  37. package/docs/{ → mdcg/}/345/215/225/345/205/203/350/207/252/346/210/221/351/224/232/347/202/271_/347/263/273/347/273/237/346/217/220/347/244/272/350/257/215/346/240/207/345/207/206_v0.3.md +1 -1
  38. package/docs/mdcg//345/255/220/344/273/243/347/220/206/351/205/215/347/275/256/346/240/207/345/207/206_v0.5.md +236 -0
  39. package/docs/{ → mdcg/}/346/272/220/347/240/201/347/272/247/346/236/266/346/236/204/345/256/241/350/256/241_GPT/346/211/271/350/257/204/345/257/271/347/205/247_v1.0.md +2 -2
  40. package/docs/{ → mdcg/}/347/201/265/346/236/242/344/270/211/345/261/202/346/213/206/345/210/206/350/247/204/345/210/222_v0.1.md +181 -181
  41. 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 +172 -0
  42. package/docs/mdcg//347/216/257/344/272/214_/347/231/275/347/256/261/345/241/253/345/205/205/346/265/201/346/260/264/347/272/277_v0.1.md +31 -0
  43. package/docs/{ → mdcg/}/347/274/272/345/217/243/345/215/225_P0/346/224/266/345/217/243_v0.1.md +2 -2
  44. package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_G4-G8/347/274/272/345/217/243/350/243/201/345/256/232/345/215/225_v0.1.md +1 -1
  45. 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 +4 -4
  46. package/docs/{ → mdcg/}/350/256/260/345/277/206/346/223/215/344/275/234/347/263/273/347/273/237_MdCGOS/344/270/216MCP/346/216/245/345/205/245_v0.1.md +2 -2
  47. package/docs/mdcg//350/267/250/347/253/257/351/252/214/350/257/201/344/270/216/345/220/214/346/255/245/345/215/217/350/256/256_v0.1.md +93 -0
  48. package/docs/plans/GridWorld/346/234/200/345/260/217/351/227/255/347/216/257/350/247/204/346/240/274_v0.1.md +176 -0
  49. package/docs/{ → swarm/}/350/234/202/347/276/244/344/272/222/350/201/224_v0.1.md +3 -3
  50. package/docs/swarm//350/234/202/347/276/244/345/220/214/351/224/231/346/243/200/346/265/213/345/256/236/351/252/214/345/215/217/350/256/256_v0.1.md +242 -0
  51. package/docs/theory//345/215/225/347/272/277/347/250/213/344/270/216/346/263/250/346/204/217/345/212/233/351/233/206/344/270/255_/346/227/240/344/272/211/350/256/256/347/220/206/350/256/272/346/226/207/346/241/243_v1.0.md +129 -0
  52. package/docs/theory//345/271/266/345/217/221/345/277/205/347/204/266/346/200/247/347/220/206/350/256/272_v0.2.md +134 -0
  53. package/docs/theory//346/246/202/345/277/265/345/210/206/345/261/202/345/257/271/351/275/220/350/241/250_v0.1.md +145 -0
  54. package/docs/{ → theory/}/347/220/206/350/256/272_/346/234/272/345/210/266_/344/273/243/347/240/201_/345/256/236/351/252/214_/347/274/272/345/217/243/347/237/251/351/230/265_v0.1.md +6 -6
  55. package/docs/{ → theory/}/347/220/206/350/256/272/344/273/223/346/213/206/345/210/206/344/270/216/347/231/275/347/256/261/347/237/245/350/257/206/345/272/223/345/206/205/350/277/201_v0.1.md +1 -1
  56. package/docs/theory//350/256/244/347/237/245/344/273/243/347/220/206/344/270/216/346/224/266/346/225/233/347/273/223/346/236/204_/346/235/241/344/273/266/350/256/272/351/207/215/346/236/204_v0.1.md +221 -0
  57. package/docs/world_model//344/270/226/347/225/214/346/250/241/345/236/213_/347/245/236/347/273/217/347/275/221/347/273/234/345/272/225/345/261/202/346/236/266/346/236/204_v1.0.md +237 -0
  58. package/docs//345/255/230/347/256/227/344/270/200/344/275/223/346/236/266/346/236/204/345/255/246/344/271/240_/345/244/226/351/203/250/347/220/206/350/256/272/345/257/271/347/205/247/344/270/216/350/267/257/347/272/277/344/272/244/346/216/245_20260916.md +98 -0
  59. package/docs//345/255/230/347/256/227/344/270/200/344/275/223/347/245/236/347/273/217/347/275/221/347/273/234/346/236/266/346/236/204_/346/200/273/347/272/262/344/270/216/344/272/244/346/216/245_20260916.md +109 -0
  60. 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 +434 -405
  61. package/docs//347/201/265/346/236/242/350/207/252/346/210/221/346/224/271/350/277/233/345/267/245/344/275/234/350/256/241/345/210/222_/345/244/226/351/203/250/347/240/224/347/251/266/347/263/273/345/210/227/345/220/270/346/224/266_v1_20260919.md +286 -0
  62. package/docs//347/231/275/347/256/261/345/214/226/347/272/262/351/242/206_/344/270/211/351/241/271/347/233/256/345/255/246/344/271/240/346/200/273/346/236/266/346/236/204/344/270/216Ghidra/344/272/244/346/216/245_20260916.md +104 -0
  63. package/docs//350/256/260/345/277/206/350/257/204/345/256/241/347/263/273/347/273/237_/347/253/213/351/241/271/350/256/276/350/256/241/344/270/216/346/226/275/345/267/245/344/272/244/346/216/245_20260915.md +183 -0
  64. package/dsh/README.md +34 -1
  65. package/dsh/cordis.yml.example +13 -7
  66. package/dsh/hive-mcp-probe.mjs +94 -0
  67. package/dsh/hive-mcp.example.yml +62 -0
  68. package/dsh/update-lingshu.bat +11 -0
  69. package/dsh/update-lingshu.ps1 +337 -0
  70. package/lib/hooks.d.ts +8 -0
  71. package/lib/hooks.js +27 -24
  72. package/lib/index.d.ts +4 -2
  73. package/lib/index.js +29 -6
  74. package/lib/lib/datapath.d.ts +76 -1
  75. package/lib/lib/datapath.js +199 -13
  76. package/lib/lib/mdcg_client.d.ts +6 -3
  77. package/lib/lib/mdcg_client.js +6 -5
  78. package/lib/lib/mutual.js +4 -4
  79. package/lib/lib/prompt_safety.d.ts +48 -0
  80. package/lib/lib/prompt_safety.js +62 -0
  81. package/lib/lib/token_store.js +4 -5
  82. package/md_cg/audit.py +91 -2
  83. package/md_cg/autonomy.py +86 -15
  84. package/md_cg/backfill.py +36 -1
  85. package/md_cg/backfill_bigdomain.py +34 -0
  86. package/md_cg/bench6_arms.py +28 -1
  87. package/md_cg/bench6_common.py +10 -1
  88. package/md_cg/bench6_competitors.py +6 -1
  89. package/md_cg/bench_axis_domain.py +9 -1
  90. package/md_cg/bench_blind_comp.py +7 -1
  91. package/md_cg/bench_en_atoms_public.py +9 -0
  92. package/md_cg/bench_governance.py +348 -0
  93. package/md_cg/bench_lme_zh.py +16 -1
  94. package/md_cg/bench_locomo.py +2 -1
  95. package/md_cg/bench_locomo_zh.py +16 -1
  96. package/md_cg/bench_locomo_zh_public.py +4 -1
  97. package/md_cg/bench_longmem.py +2 -1
  98. package/md_cg/bench_membench.py +37 -6
  99. package/md_cg/bench_p0.py +4 -1
  100. package/md_cg/bench_progressive.py +61 -10
  101. package/md_cg/bench_role_views.py +238 -0
  102. package/md_cg/bench_task_ab.py +8 -1
  103. package/md_cg/bench_task_ab_llm.py +13 -1
  104. package/md_cg/bench_unified_en.py +6 -1
  105. package/md_cg/bench_zh_mad.py +20 -1
  106. package/md_cg/blindspot_tickets.py +123 -0
  107. package/md_cg/branches.py +286 -0
  108. package/md_cg/build_postings.py +73 -0
  109. package/md_cg/ccgc.py +949 -0
  110. package/md_cg/census.py +5 -1
  111. package/md_cg/chain.py +24 -3
  112. package/md_cg/codeindex.py +134 -17
  113. package/md_cg/coldverify.py +265 -0
  114. package/md_cg/comment_gate.py +338 -0
  115. package/md_cg/cond_compose.py +190 -0
  116. package/md_cg/cond_facts.py +155 -0
  117. package/md_cg/cond_template.json +107 -0
  118. package/md_cg/condition_anchor.py +143 -0
  119. package/md_cg/conformance.py +727 -0
  120. package/md_cg/consistency.py +25 -2
  121. package/md_cg/consolidate.py +53 -2
  122. package/md_cg/corpus.py +5 -1
  123. package/md_cg/crosscheck.py +42 -2
  124. package/md_cg/crypto.py +35 -1
  125. package/md_cg/d_meta.py +310 -0
  126. package/md_cg/datapath.py +201 -26
  127. package/md_cg/docindex.py +122 -1
  128. package/md_cg/eval_common.py +35 -6
  129. package/md_cg/evidence.py +27 -1
  130. package/md_cg/evolution.py +21 -1
  131. package/md_cg/export.py +11 -1
  132. package/md_cg/forgetting.py +34 -4
  133. package/md_cg/fsutil.py +81 -2
  134. package/md_cg/hotcache.py +214 -0
  135. package/md_cg/hyperedge.py +251 -0
  136. package/md_cg/identity.py +20 -3
  137. package/md_cg/insight.py +19 -3
  138. package/md_cg/lexicon/build_cedict_en_zh.py +9 -0
  139. package/md_cg/lexicon/build_standard_en.py +171 -168
  140. package/md_cg/lexicon/expand_en_zh.py +6 -0
  141. package/md_cg/lifecycle.py +273 -0
  142. package/md_cg/linkref.py +281 -0
  143. package/md_cg/links.py +29 -1
  144. package/md_cg/mcp_server.py +894 -168
  145. package/md_cg/md_whitebox.py +53 -1
  146. package/md_cg/mdcg.py +1205 -41
  147. package/md_cg/mdcos.py +1060 -76
  148. package/md_cg/metacognition.py +39 -4
  149. package/md_cg/migrate.py +4 -0
  150. package/md_cg/migrate_aeis.py +221 -213
  151. package/md_cg/migrate_roleplay.py +8 -0
  152. package/md_cg/migrate_wisdom_graph.py +14 -1
  153. package/md_cg/mreview/__init__.py +25 -0
  154. package/md_cg/mreview/__main__.py +110 -0
  155. package/md_cg/mreview/bundle.py +178 -0
  156. package/md_cg/mreview/candidates.py +262 -0
  157. package/md_cg/mreview/govern.py +694 -0
  158. package/md_cg/mreview/locate.py +939 -0
  159. package/md_cg/mreview/pipeline.py +729 -0
  160. package/md_cg/mreview/rules/duplication.json +21 -0
  161. package/md_cg/mreview/rules/field_coverage.json +54 -0
  162. package/md_cg/mreview/rules/source_license.json +21 -0
  163. package/md_cg/mreview/rules/template_flow.json +21 -0
  164. package/md_cg/mreview/ruleset.py +253 -0
  165. package/md_cg/nodefile.py +269 -1
  166. package/md_cg/pooling.py +23 -1
  167. package/md_cg/postings.py +298 -0
  168. package/md_cg/predict.py +113 -15
  169. package/md_cg/progressive.py +3 -0
  170. package/md_cg/protect.py +18 -5
  171. package/md_cg/protocol.py +372 -0
  172. package/md_cg/provenance.py +262 -0
  173. package/md_cg/reach.py +453 -0
  174. package/md_cg/refindex.py +88 -4
  175. package/md_cg/refine.py +20 -1
  176. package/md_cg/roleviews.py +89 -0
  177. package/md_cg/routing.py +76 -0
  178. package/md_cg/scrub.py +68 -3
  179. package/md_cg/security.py +26 -1
  180. package/md_cg/self_state.py +65 -2
  181. package/md_cg/selfreport.py +151 -0
  182. package/md_cg/semantic/canonical.py +5 -0
  183. package/md_cg/semantic/en_normalizer.py +364 -295
  184. package/md_cg/semantic/zh_en_atoms.py +139 -136
  185. package/md_cg/signer.py +41 -1
  186. package/md_cg/sources.py +583 -547
  187. package/md_cg/statushdr.py +179 -0
  188. package/md_cg/stg.py +59 -18
  189. package/md_cg/subgraph.py +23 -0
  190. package/md_cg/sustain.py +74 -1
  191. package/md_cg/tasks.py +471 -0
  192. package/md_cg/test_action_derive.py +203 -0
  193. package/md_cg/test_audit_rotate.py +270 -0
  194. package/md_cg/test_autonomy.py +26 -0
  195. package/md_cg/test_bench_governance.py +102 -0
  196. package/md_cg/test_blindspot_tickets.py +166 -0
  197. package/md_cg/test_branches.py +249 -0
  198. package/md_cg/test_ccg_perturb.py +1 -1
  199. package/md_cg/test_ccgc.py +433 -0
  200. package/md_cg/test_codeindex.py +338 -0
  201. package/md_cg/test_comment_gate.py +187 -0
  202. package/md_cg/test_cond_compose_anchors.py +76 -0
  203. package/md_cg/test_condition_anchor.py +82 -0
  204. package/md_cg/test_conformance.py +343 -0
  205. package/md_cg/test_d_meta.py +412 -0
  206. package/md_cg/test_datapath_root.py +188 -0
  207. package/md_cg/test_en_pipeline.py +24 -0
  208. package/md_cg/test_gain_gate.py +47 -1
  209. package/md_cg/test_health_scale.py +173 -0
  210. package/md_cg/test_hot_cold.py +187 -0
  211. package/md_cg/test_hyperedge.py +245 -0
  212. package/md_cg/test_identity_attribution.py +6 -0
  213. package/md_cg/test_index_durability.py +224 -0
  214. package/md_cg/test_lifecycle.py +309 -0
  215. package/md_cg/test_linkref.py +306 -0
  216. package/md_cg/test_md_access_parity.py +15 -3
  217. package/md_cg/test_mr_m1.py +769 -0
  218. package/md_cg/test_mr_m2.py +587 -0
  219. package/md_cg/test_mr_m3.py +710 -0
  220. package/md_cg/test_mr_m4.py +485 -0
  221. package/md_cg/test_p1.py +1 -1
  222. package/md_cg/test_p11_consistency.py +1 -1
  223. package/md_cg/test_p12_metacognition.py +2 -2
  224. package/md_cg/test_p16_self_state.py +1 -1
  225. package/md_cg/test_p26_refindex.py +50 -21
  226. package/md_cg/test_p27_docindex.py +258 -4
  227. package/md_cg/test_p28_refcheck.py +1 -1
  228. package/md_cg/test_p29_session_ingest_export.py +1 -1
  229. package/md_cg/test_p2_mcp.py +7 -1
  230. package/md_cg/test_p31_insight.py +24 -0
  231. package/md_cg/test_p38_contextualize.py +1 -1
  232. package/md_cg/test_p39_vision_evidence.py +1 -1
  233. package/md_cg/test_p40_refine_worklist.py +1 -1
  234. package/md_cg/test_p41_evolve_patrol.py +1 -1
  235. package/md_cg/test_p42_provenance.py +1 -1
  236. package/md_cg/test_p43_pooling.py +41 -13
  237. package/md_cg/test_p44_md_whitebox.py +14 -1
  238. package/md_cg/test_protocol.py +243 -0
  239. package/md_cg/test_reach.py +378 -0
  240. package/md_cg/test_reach_keys.py +201 -0
  241. package/md_cg/test_reach_meta_exits.py +145 -0
  242. package/md_cg/test_read_clip.py +141 -0
  243. package/md_cg/test_retr_s1.py +340 -0
  244. package/md_cg/test_retr_s1b.py +209 -0
  245. package/md_cg/test_retr_s3.py +194 -0
  246. package/md_cg/test_retr_s4.py +163 -0
  247. package/md_cg/test_retr_s5.py +200 -0
  248. package/md_cg/test_retr_s6.py +157 -0
  249. package/md_cg/test_retr_s7.py +385 -0
  250. package/md_cg/test_retr_s8_time.py +316 -0
  251. package/md_cg/test_retr_s9_edges.py +286 -0
  252. package/md_cg/test_retr_s9_entity_ctx.py +175 -0
  253. package/md_cg/test_review_conformance.py +367 -0
  254. package/md_cg/test_role_views.py +354 -0
  255. package/md_cg/test_tasks.py +409 -0
  256. package/md_cg/test_tool_face.py +189 -0
  257. package/md_cg/test_trust.py +361 -0
  258. package/md_cg/test_twophase.py +286 -0
  259. package/md_cg/test_units_poll.py +71 -0
  260. package/md_cg/test_v14_fixes.py +397 -0
  261. package/md_cg/test_validity_filter.py +280 -0
  262. package/md_cg/test_wisdom_md_store.py +7 -3
  263. package/md_cg/test_writepipe.py +214 -0
  264. package/md_cg/theory.py +17 -2
  265. package/md_cg/tokens.py +134 -12
  266. package/md_cg/tool_face.py +261 -0
  267. package/md_cg/trust.py +943 -0
  268. package/md_cg/twophase.py +232 -0
  269. package/md_cg/units.py +665 -0
  270. package/md_cg/vision_evidence.py +25 -2
  271. package/md_cg/weights.py +25 -2
  272. package/md_cg/whitebox.py +33 -2
  273. package/md_cg/whitebox_kb/data/verify_cache.json +21233 -360
  274. package/md_cg/whitebox_kb/data/verify_savings.jsonl +5124 -0
  275. package/md_cg/whitebox_kb/wisdom/audit_log/chain_heat.json +10 -10
  276. package/md_cg/whitebox_kb/wisdom/code_compose.py +113 -6
  277. package/md_cg/whitebox_kb/wisdom/code_solidified.json +1 -1
  278. package/md_cg/whitebox_kb/wisdom/verifier.py +340 -55
  279. package/md_cg/whitebox_kb/wisdom/wisdom-book-cloud.db +0 -0
  280. package/md_cg/writelimit.py +37 -7
  281. package/md_cg/writepipe.py +543 -0
  282. package/package.json +2 -2
  283. package/skills/skills/designer-perspective/scripts/__pycache__/designer.cpython-310.pyc +0 -0
  284. package/skills/skills/designer-perspective/scripts/designer.py +17 -1
  285. package/skills/skills/designer-perspective/tests/selftest.py +3 -1
  286. package/src/hooks.ts +27 -22
  287. package/src/index.ts +33 -6
  288. package/src/lib/datapath.ts +211 -13
  289. package/src/lib/mdcg_client.ts +12 -8
  290. package/src/lib/mutual.ts +411 -411
  291. package/src/lib/prompt_safety.ts +62 -0
  292. package/src/lib/token_store.ts +4 -5
  293. package/zcode/AGENTS.md +21 -10
  294. package/zcode/README.md +4 -0
  295. package/docs//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +0 -221
  296. /package/docs/{AGI → eval/AGI}/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v1.0.md" +0 -0
  297. /package/docs/{AGI → eval/AGI}/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v2.0.md" +0 -0
  298. /package/docs/{ → eval/}/345/256/236/351/252/214/346/226/271/346/241/210_/345/255/246/344/271/240/351/227/255/347/216/257AB/344/270/216/346/250/252/350/257/204_v1.0.md" +0 -0
  299. /package/docs/{ → eval/}/346/250/252/350/257/204_/345/205/255/345/256/266100/351/242/230/344/270/255/350/213/261/345/217/214/346/237/245_v1.0.md" +0 -0
  300. /package/docs/{guardrail-charter.md → mdcg/guardrail-charter.md} +0 -0
  301. /package/docs/{lingshu_tutorial.html → mdcg/lingshu_tutorial.html} +0 -0
  302. /package/docs/{memory-assessment.html → mdcg/memory-assessment.html} +0 -0
  303. /package/docs/{memory_score.html → mdcg/memory_score.html} +0 -0
  304. /package/docs/{memory_score.png → mdcg/memory_score.png} +0 -0
  305. /package/docs/{release_v0.3.0.md → mdcg/release_v0.3.0.md} +0 -0
  306. /package/docs/{release_v0.4.5.md → mdcg/release_v0.4.5.md} +0 -0
  307. /package/docs/{tool_table_v0.3.0.md → mdcg/tool_table_v0.3.0.md} +0 -0
  308. /package/docs/{ → mdcg/}/344/273/244/347/211/214/344/270/216/350/247/222/350/211/262/346/235/203/350/201/214/345/210/206/347/246/273_v0.1.md" +0 -0
  309. /package/docs/{ → mdcg/}/347/201/265/346/236/24282/345/267/245/345/205/267_/345/212/237/350/203/275/346/225/264/347/220/206/344/270/216/350/277/201/347/247/273/346/230/240/345/260/204_v0.1.md" +0 -0
  310. /package/docs/{ → mdcg/}/347/201/265/346/236/242MCP/345/267/245/345/205/267/346/200/273/350/241/250_v3.4.md" +0 -0
  311. /package/docs/{ → mdcg/}/347/201/265/346/236/242_/350/207/252/346/210/221/345/261/202/345/256/232/344/271/211.md" +0 -0
  312. /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_MD/347/233/256/345/275/225/346/226/271/346/241/210_v0.1.md" +0 -0
  313. /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_/346/235/241/344/273/266/347/251/272/351/227/264/345/220/210/346/210/220/344/270/216/347/224/237/346/225/210/346/235/241/344/273/266/345/217/243/345/276/204_v0.1.md" +0 -0
  314. /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276/344/275/234/344/270/272/350/256/260/345/277/206/346/223/215/344/275/234/347/263/273/347/273/237_/350/257/204/344/274/260/344/270/216/350/267/257/347/272/277_v0.1.md" +0 -0
  315. /package/docs/{ → plans/}/345/221/275/345/220/215/346/262/273/347/220/206_/351/241/271/347/233/256/350/256/241/345/210/222.md" +0 -0
  316. /package/docs/{ → plans/}/347/237/245/350/257/206/345/233/276/350/260/261/351/241/271/347/233/256_/344/272/244/346/216/245/346/226/207/346/241/243_20260914.md" +0 -0
  317. /package/docs/{ → swarm/}/350/234/202/347/276/244/345/244/232/346/231/272/350/203/275/344/275/223_/344/275/277/347/224/250/346/212/245/345/221/212_20260913.md" +0 -0
  318. /package/docs/{ → swarm/}/350/234/202/347/276/244/345/244/232/346/231/272/350/203/275/344/275/223_/345/212/237/350/203/275/350/257/264/346/230/216_v0.6.md" +0 -0
  319. /package/docs/{ → swarm/}/350/234/202/347/276/244/347/233/262/345/214/272/346/240/207/350/256/260_v1.0.md" +0 -0
  320. /package/docs/{ → theory/}/344/277/241/346/201/257/345/267/256/344/270/272/344/273/200/344/271/210/345/277/205/347/204/266/345/255/230/345/234/250/344/270/224/350/207/252/347/204/266/346/211/251/345/244/247.md" +0 -0
  321. /package/docs/{ → theory/}/346/231/272/350/203/275/347/232/204/345/205/254/347/220/206/345/214/226/345/237/272/347/237/263.md" +0 -0
  322. /package/docs/{ → theory/}/346/231/272/350/203/275/347/232/204/350/256/244/347/237/245/350/277/207/347/250/213.md" +0 -0
  323. /package/docs/{ → theory/}/346/231/272/350/203/275/350/256/2723.4.md" +0 -0
  324. /package/docs/{ → theory/}/347/231/275/347/256/261/346/231/272/350/203/275/346/230/257/344/273/200/344/271/210/357/274/237.md" +0 -0
  325. /package/docs/{ → theory/}/347/231/275/347/256/261/346/231/272/350/203/275/347/263/273/345/210/227/302/267/347/254/254/344/272/224/347/257/207/357/274/232/350/256/251AI/347/234/237/346/255/243/350/243/205/344/270/212/350/256/260/345/277/206.md" +0 -0
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """条件文档图端到端测试(P27 · 认知图的文档面)。
3
3
 
4
- R2 改造的验收(对照 docs/认知图_索引与工程规范化_计划_v0.1.md §六 R2、§七):
4
+ R2 改造的验收(对照 docs/mdcg/认知图_索引与工程规范化_计划_v0.1.md §六 R2、§七):
5
5
 
6
6
  ① 切块纪律:只切 level<=3;直接正文 <200 字且无子节的小节**合并进父节**
7
7
  (不单独建节点,其文字进父节摘要)。既不过细,也不丢内容。
@@ -20,20 +20,31 @@ R2 改造的验收(对照 docs/认知图_索引与工程规范化_计划_v0.1.
20
20
  ⑦ 不静默:truncated / skipped_suffixes / skipped_dirs 显式上报;排除为**追加**
21
21
  (只增不减,内置 .git/.venv/node_modules 不可被关闭);只读契约(源 mtime 不变);
22
22
  幂等(重跑节点数不变);`index_doc` 进 ALL_OPS 且与工具 schema 一致。
23
+ ⑧ fence 往返列六件套的形状与边界:BINDING_FIELDS / binding_of / binding_key
24
+ (**不含行位**)/ binding_slug / validate_binding / binding_drift / locate。
25
+ 为什么必须钉死:列形状漂移会让对账器把坏列当好消息(漏报);键若悄悄带上
26
+ 行位,真源上方插一行就会让整库失配——两者都是静默退化,只有断言看得见。
27
+ ⑨ 逐字节回放回归:对**真实索引出的卡**断言 `render(条目) + "\n" == 卡片正文`。
28
+ ⑧ 只证「列可定位」;只有逐字节相等才证明卡片是真源条目的**派生物**而非另一份
29
+ 副本(渲染漂移或人工改写时列全然不变,对账器看不出来)。外部历史库另段抽样
30
+ (设 MDCG_ROOT 则跑,未设如实 SKIP 不虚报通过)。
23
31
 
24
32
  运行:python -m md_cg.test_p27_docindex
33
+ 设 MDCG_ROOT=<认知图库根> 追加跑【12b】外部历史库逐字节回放抽样
25
34
  """
26
35
  from __future__ import annotations
27
36
 
28
37
  import os
38
+ import random
29
39
  import shutil
30
40
  import sys
31
41
  import tempfile
32
42
 
33
- from . import codeindex, corpus, docindex, nodefile, routing, tokens
43
+ from . import codeindex, corpus, docindex, nodefile, refindex, routing, tokens
34
44
  from . import mcp_server
35
- from .mdcos import MdCGOS # 生产路径:forget 属 OS 层,基础层 MdCG 无删除原语
45
+ from .mdcos import MdCGOS, MdCGSecure # 生产路径:forget 属 OS 层,基础层 MdCG 无删除原语
36
46
  from .mcp_server import call_tool
47
+ from .security import Principal
37
48
 
38
49
  PASS = FAIL = 0
39
50
  FAILS = []
@@ -41,7 +52,7 @@ FAILS = []
41
52
  _BASE = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
42
53
  ROOT = os.path.join(_BASE, "_md_cg_p27")
43
54
  DOCS = os.path.join(_BASE, "docs")
44
- PLAN_DOC = "认知图_MD目录方案_v0.1.md"
55
+ PLAN_DOC = "mdcg/认知图_MD目录方案_v0.1.md"
45
56
 
46
57
 
47
58
  def check(name, cond, detail=""):
@@ -55,6 +66,79 @@ def check(name, cond, detail=""):
55
66
  print(f" [FAIL] {name} · {detail}")
56
67
 
57
68
 
69
+ def _norm(p):
70
+ """路径归一(大小写 + 分隔符):root 归属比对用,避免同一目录被判成两个。"""
71
+ return os.path.normcase(os.path.normpath(str(p or "")))
72
+
73
+
74
+ # 逐字节回放:把「往返列」从「形状可校验」推进到「内容可无损重建」。
75
+ # 生效条件:cg 已索引完成的库;索引条目 tags 含 "doc" 且 frontmatter 有非空 doc_ref。
76
+ # 判据:真源同键条目 `render(条目)` 补一个换行 == 卡片正文——`nodefile.dumps` 对不以
77
+ # 换行结尾的正文补 '\n',故卡片正文恒比 render 多 1 字节(是常态,不是缺陷;判等
78
+ # 一律按 `render + "\n"`,避免把口径差当回归)。
79
+ # 为什么非此不可:列形状对(validate_binding)只保证「可定位」;只有逐字节相等才
80
+ # 证明卡片是真源条目的**派生物**而非另一份副本。渲染漂移或人工改写卡片正文时,
81
+ # 列全都不变(路径/行位/hash 都是真源侧的值),对账器看不出来——本函数才看得见。
82
+ # 悬空(真源已移出)/ 未解析如实计数:那是数据面事实,不冒充渲染失败。
83
+ def _replay_cards(cg, roots=None, sample=0, seed=7):
84
+ nodes = (getattr(cg, "index", {}) or {}).get("nodes") or {}
85
+ picks = []
86
+ for nid in sorted(nodes):
87
+ if "doc" not in ((nodes.get(nid) or {}).get("tags") or []):
88
+ continue
89
+ kind, ref = refindex.ref_of(cg.get(nid))
90
+ if kind != "doc_ref" or not ref:
91
+ continue
92
+ if roots is not None and _norm(ref.get("root")) not in roots:
93
+ continue
94
+ picks.append((nid, ref))
95
+ if sample and len(picks) > sample:
96
+ picks = sorted(random.Random(seed).sample(picks, sample))
97
+ out = {"sampled": len(picks), "ok": 0, "dangling": 0, "gone": 0,
98
+ "unreadable": 0, "mismatch": []}
99
+ cache = {}
100
+ for nid, ref in picks:
101
+ fp = (str(ref.get("root") or ""), str(ref.get("path") or ""))
102
+ ckey = (_norm(fp[0]), fp[1])
103
+ if ckey not in cache:
104
+ # 把「源文件已移出」(数据面事实,非缺陷)与其它 IO/抽取异常(可能是真
105
+ # 问题:权限、编码、源被改成无标题文档)分开计数——混为一谈会把真实
106
+ # 故障伪装成历史遗留,静默吞掉回归。三态:True 读得 / False 不存在 /
107
+ # None 读不了。
108
+ try:
109
+ with open(os.path.join(fp[0], fp[1]), "r", encoding="utf-8",
110
+ errors="replace") as f:
111
+ cache[ckey] = (True, docindex.extract(f.read(), fp[1]))
112
+ except FileNotFoundError:
113
+ cache[ckey] = (False, None)
114
+ except (OSError, ValueError):
115
+ cache[ckey] = (None, None)
116
+ hit, items = cache[ckey]
117
+ if hit is not True:
118
+ out["gone" if hit is False else "unreadable"] += 1
119
+ continue
120
+ node = cg.get(nid) or {}
121
+ want = docindex.binding_key(docindex.binding_of(node))
122
+ # 键(path#heading_path)在同名标题重复时可能命中多条:先按行位锁定同名代,
123
+ # 行位也漂了才回落首条(此时本来就判「不符」,不掩盖结论)。
124
+ cands = [i for i in items if docindex.binding_key(i) == want]
125
+ if not cands:
126
+ out["dangling"] += 1
127
+ continue
128
+ item = next((i for i in cands if i.get("lineno") == ref.get("lineno")),
129
+ cands[0])
130
+ got = docindex.render(item) + "\n"
131
+ content = node.get("content") or ""
132
+ if got == content:
133
+ out["ok"] += 1
134
+ continue
135
+ k = next((i for i in range(min(len(got), len(content)))
136
+ if got[i] != content[i]), min(len(got), len(content)))
137
+ out["mismatch"].append(
138
+ f"{nid}@{k} 回放={got[k:k + 24]!r} 卡片={content[k:k + 24]!r}")
139
+ return out
140
+
141
+
58
142
  LONG = "这是总览段落," + "用以验证章节切块在长正文下的表现," * 12 + "结束。"
59
143
 
60
144
  GUIDE_LINES = [
@@ -494,6 +578,176 @@ def main():
494
578
  check("清退后悬空归零", not (ck3.get("dangling") or []),
495
579
  str(ck3.get("dangling"))[:130])
496
580
 
581
+ # 跨进程一致性:新实例重放 _index_log 后,已清退节点不得复活成幽灵条目
582
+ # (索引有条目、文件不存在)——只有把「删除」也写进增量日志才成立。
583
+ cg2 = MdCGOS(ROOT)
584
+ revived = sorted(n for n in ids4 if n in (cg2.index.get("nodes") or {}))
585
+ check("清退后重开不复活幽灵条目", not revived, f"复活={revived}")
586
+
587
+ # 存量幽灵(历史「删除只摘内存索引」遗留):索引有条目、节点文件不存在
588
+ # 也必须清得掉,否则 dangling 永远够不着零。
589
+ gid = "doc_ghost_probe0001"
590
+ cg.index["nodes"][gid] = {"path": "knowledge/ghost_probe.md",
591
+ "layer": "knowledge", "tags": ["doc"],
592
+ "bucket": None, "importance": 0.5}
593
+ g1 = call_tool(cg, "cg", {"op": "ref", "action": "prune"})
594
+ check("幽灵条目被清退(索引有、文件无)",
595
+ len(g1.get("ghost_pruned") or []) >= 1
596
+ and gid not in (cg.index.get("nodes") or {}), str(g1)[:130])
597
+ ck4 = call_tool(cg, "cg", {"op": "ref", "action": "check", "max_nodes": 5000})
598
+ check("清幽灵后悬空仍为零", not (ck4.get("dangling") or []),
599
+ str(ck4.get("dangling"))[:130])
600
+
601
+ # ============================================ ⑪ fence 往返列(binding)
602
+ # 缺口:往返列(取列 / 造键 / 校验 / 漂移 / 反查)是「条件卡 ↔ Markdown 真源」
603
+ # 的可校验面,此前零测试。列形状一旦漂移,对账器会把坏列当好消息(漏报);
604
+ # 键若悄悄带上行位,真源上方插一行就会让整库失配——故两者都要钉死。
605
+ print("\n【11】fence 往返列:形状 / 键不含行位 / 校验 / 漂移 / 反查")
606
+ li = docindex.extract(GUIDE, "guide.md")
607
+ s9b = next(i for i in li if i["heading"] == "9. 分阶段实施")
608
+ rendered = docindex.render(s9b)
609
+ gnode = cg.get(g_id) or {}
610
+ g_ref = (gnode.get("frontmatter") or {}).get("doc_ref") or {}
611
+ b0 = docindex.binding_of(gnode)
612
+ check("必需列齐全且无空值",
613
+ isinstance(b0, dict)
614
+ and all(b0.get(k) not in (None, "") for k in docindex.BINDING_FIELDS),
615
+ str(sorted(docindex.BINDING_FIELDS)))
616
+ check("列面 = 必需列 + 附加列(无第二份列口径)",
617
+ set(b0 or {}) == set(docindex.BINDING_FIELDS)
618
+ | set(docindex.BINDING_OPTIONAL),
619
+ str(sorted(set(b0 or {}) ^ (set(docindex.BINDING_FIELDS)
620
+ | set(docindex.BINDING_OPTIONAL)))))
621
+ check("必需列/附加列 ⊆ 写侧 doc_ref 列(读写同一列面)",
622
+ (set(docindex.BINDING_FIELDS) | set(docindex.BINDING_OPTIONAL))
623
+ <= set(g_ref),
624
+ str(sorted(set(docindex.BINDING_FIELDS) - set(g_ref))))
625
+ check("binding_of 与直接读 frontmatter 同源(同一投影)",
626
+ b0 == docindex.binding_of({"frontmatter": {"doc_ref": g_ref}}))
627
+ check("binding_of 对非索引节点返回 None(不猜、不补默认值)",
628
+ docindex.binding_of(None) is None
629
+ and docindex.binding_of([]) is None
630
+ and docindex.binding_of({}) is None
631
+ and docindex.binding_of({"frontmatter": {"tags": ["doc"]}}) is None)
632
+ check("validate_binding:本仓卡片列形状合法(ok + 零 issue)",
633
+ docindex.validate_binding(b0) == {"ok": True, "issues": []},
634
+ str(docindex.validate_binding(b0)))
635
+ check("validate_binding:非 dict 如实报错且不抛",
636
+ docindex.validate_binding(None)
637
+ == {"ok": False, "issues": ["绑定不是字典(该节点无 doc_ref)"]})
638
+ lo0 = b0["lineno"]
639
+ bad_detail = []
640
+ for _nm, _b, _want in (
641
+ ("缺列", {k: v for k, v in b0.items() if k != "anchor"},
642
+ "缺列 anchor"),
643
+ ("类型错 root", {**b0, "root": 123},
644
+ "root 应为字符串,实为 int"),
645
+ ("类型错 lineno", {**b0, "lineno": "十"}, "行位不是整数"),
646
+ ("行位越界", {**b0, "lineno": 0}, "lineno 越界(0 < 1)"),
647
+ ("区间倒置", {**b0, "end": lo0 - 1},
648
+ f"end 早于 lineno({lo0}-{lo0 - 1})")):
649
+ _v = docindex.validate_binding(_b)
650
+ if _v["ok"] or _want not in _v["issues"]:
651
+ bad_detail.append(f"{_nm}→{_v['issues']}")
652
+ check("validate_binding 逐类坏列均被点出(缺列/类型错/越界/区间倒置)",
653
+ not bad_detail, "; ".join(bad_detail)[:170])
654
+ b_shift = docindex.binding_of({"frontmatter": {"doc_ref": {
655
+ **g_ref, "lineno": lo0 + 40, "end": g_ref["end"] + 40}}})
656
+ check("键不含行位:行位位移不改键(重排后仍是同一章节)",
657
+ docindex.binding_key(b0) == docindex.binding_key(b_shift)
658
+ == "guide.md#总览/9. 分阶段实施",
659
+ docindex.binding_key(b0))
660
+ check("漂移按固定列序报出变化项(lineno → end → hash)",
661
+ docindex.binding_drift(b0, b_shift) == ["lineno", "end"]
662
+ and docindex.binding_drift(b0, {**b0, "hash": "zz"}) == ["hash"]
663
+ and docindex.binding_drift(
664
+ b0, {**b0, "hash": "zz", "lineno": lo0 + 1})
665
+ == ["lineno", "hash"],
666
+ str(docindex.binding_drift(b0, b_shift)))
667
+ check("同列零漂移(无变化不报 / 空值不炸)",
668
+ docindex.binding_drift(b0, dict(b0)) == []
669
+ and docindex.binding_drift(None, None) == [])
670
+ check("binding_key 缺 heading_path 回落 path#anchor · 非 dict 返空串",
671
+ docindex.binding_key({"path": "a.md", "anchor": "s1"}) == "a.md#s1"
672
+ and docindex.binding_key({"path": "a.md"}) == "a.md#"
673
+ and docindex.binding_key(None) == "")
674
+ check("binding_slug 与 render 正文「本条目属于」逐字同源",
675
+ docindex.binding_slug(b0) == "guide.md#9-分阶段实施"
676
+ and f"本条目属于 {docindex.binding_slug(b0)}" in rendered,
677
+ docindex.binding_slug(b0))
678
+ check("反查取最内层(父节区间内的子节优先,不回落父节)",
679
+ docindex.locate(li, 12)["heading"] == "9. 分阶段实施"
680
+ and docindex.locate(li, 30)["heading"] == "代码示例",
681
+ str((docindex.locate(li, 12) or {}).get("heading")))
682
+ check("反查区间闭合(标题行与末行都算本节)",
683
+ docindex.locate(li, s9b["lineno"])["heading"] == "9. 分阶段实施"
684
+ and docindex.locate(li, s9b["end"])["heading"] == "9. 分阶段实施")
685
+ check("反查越界/非整数/空表 → None(fail-closed 不猜)",
686
+ docindex.locate(li, 10 ** 6) is None
687
+ and docindex.locate(li, 0) is None
688
+ and docindex.locate(li, "x") is None
689
+ and docindex.locate(li, None) is None
690
+ and docindex.locate([], 10) is None)
691
+
692
+ # ================================ ⑫ 逐字节回放回归(往返列无损)
693
+ # ⑪ 只证「列可校验」;本段把口径推到内容无损:卡片必须是真源条目的派生物
694
+ # (render 补一个换行 == 卡片正文)。root 限定为本次真正索引过的两个真源,
695
+ # 断言只落在本轮写入的卡上——历史残留不参与,避免把脏数据当回归。
696
+ print("\n【12】逐字节回放回归:render(条目) + 换行 == 卡片正文")
697
+ cg.flush()
698
+ rp = _replay_cards(cg, roots={_norm(fx), _norm(DOCS)})
699
+ print(f" 取样 {rp['sampled']} 卡:一致 {rp['ok']} · 键未命中 "
700
+ f"{rp['dangling']} · 源已移出 {rp['gone']} · 读不了 "
701
+ f"{rp['unreadable']}")
702
+ check("回放取样命中卡片(root 限定=本次索引的两个真源)",
703
+ rp["sampled"] > 0, str(rp["sampled"]))
704
+ check("可读卡 100% 逐字节回放一致(写侧 render 与读侧同源)",
705
+ not rp["mismatch"],
706
+ f"一致 {rp['ok']}/{rp['sampled']};" + ";".join(rp["mismatch"][:2]))
707
+ check("零键未命中 / 零源已移出 / 零读不了(源在库则必可重定位并读回)",
708
+ rp["dangling"] == 0 and rp["gone"] == 0
709
+ and rp["unreadable"] == 0,
710
+ f"键未命中={rp['dangling']} 源已移出={rp['gone']} "
711
+ f"读不了={rp['unreadable']}")
712
+ check("回放账目闭合(一致 + 键未命中 + 源已移出 + 读不了 = 取样数)",
713
+ (rp["ok"] + rp["dangling"] + rp["gone"] + rp["unreadable"])
714
+ == rp["sampled"],
715
+ f"{rp['ok']}+{rp['dangling']}+{rp['gone']}+{rp['unreadable']}"
716
+ f" vs {rp['sampled']}")
717
+
718
+ # 历史抽样:真实认知图库(仓外数据面,历史卡最多)。以 MDCG_ROOT 显式声明;
719
+ # 裸 clone / CI 无此数据面 → 如实报 SKIP(不虚报通过、也不 FAIL)。
720
+ ext_root = os.environ.get("MDCG_ROOT") or ""
721
+ if not (ext_root and os.path.isdir(ext_root)):
722
+ print("\n【12b】历史抽样:跳过(未设 MDCG_ROOT 或目录不存在)"
723
+ "—— 本仓语料回放见【12】")
724
+ else:
725
+ print(f"\n【12b】历史抽样:外部认知图库 {ext_root}(只读身份)")
726
+ ext = MdCGSecure(ext_root, principal=Principal(
727
+ actor="p27-replay", clearance="secret", can_write=False,
728
+ can_admin=False, role="designer", auth_mode="local-cli"))
729
+ try:
730
+ hp = _replay_cards(ext, sample=120)
731
+ finally:
732
+ ext.close()
733
+ print(f" 抽样 {hp['sampled']} 卡:一致 {hp['ok']} · 键未命中 "
734
+ f"{hp['dangling']} · 源已移出 {hp['gone']} · 读不了 "
735
+ f"{hp['unreadable']}")
736
+ check("【12b】历史库抽样命中卡片(数据面可达)",
737
+ hp["sampled"] > 0, str(hp["sampled"]))
738
+ check("【12b】可读历史卡零回放不符(未被渲染漂移/人工改写腐化)",
739
+ not hp["mismatch"],
740
+ f"一致 {hp['ok']}/{hp['sampled']};"
741
+ + ";".join(hp["mismatch"][:2]))
742
+ check("【12b】未读回的全部是「源已移出」(非 IO/抽取故障)",
743
+ hp["unreadable"] == 0,
744
+ f"源已移出={hp['gone']} 读不了={hp['unreadable']}")
745
+ check("【12b】抽样账目闭合(无静默丢弃)",
746
+ (hp["ok"] + hp["dangling"] + hp["gone"] + hp["unreadable"])
747
+ == hp["sampled"],
748
+ f"{hp['ok']}+{hp['dangling']}+{hp['gone']}+{hp['unreadable']}"
749
+ f" vs {hp['sampled']}")
750
+
497
751
  finally:
498
752
  shutil.rmtree(tmp, ignore_errors=True)
499
753
 
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """ref 增量索引 + 漂移/悬空巡检(P28 · R3 改造验收)。
3
3
 
4
- 对照 `docs/认知图_索引与工程规范化_计划_v0.1.md` 的 R3:
4
+ 对照 `docs/mdcg/认知图_索引与工程规范化_计划_v0.1.md` 的 R3:
5
5
 
6
6
  ① 统一 ref 协议 + 提取器注册表:调用方只说 `kind`,`refindex` 决定用哪个
7
7
  提取器;无提取器后缀显式报错。
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """会话层 + 摄取分派 + 全库导出(P29 · P0 工程缺口验收)。
3
3
 
4
- 对照 `docs/灵枢82工具_功能整理与迁移映射_v0.1.md` §五:P0 新增三个 op。
4
+ 对照 `docs/mdcg/灵枢82工具_功能整理与迁移映射_v0.1.md` §五:P0 新增三个 op。
5
5
 
6
6
  ① op 三处同步:`tokens.ALL_OPS` == `cg` 工具 op 描述 == `_cg_call` 分支
7
7
  ② session:note 幂等写入;recall 一次返回可续接上下文包;compact 启发式压缩
@@ -262,12 +262,18 @@ def main():
262
262
  kn = [t["name"] for t in kt]
263
263
  check("kernel 只暴露 2 个基元", kn == ["cg", "stg"], str(kn))
264
264
  info = kc.call("cg", {"op": "info"})
265
+ # 注:新增 content_kind(如 ccg_marks)须同步本清单——工具面自描述
266
+ # 与 audit.CONTENT_KINDS 真源逐类对齐,防「真源扩了、自描述没跟」。
265
267
  check("cg info 自描述审核体系",
266
268
  info.get("surface") == "kernel"
267
269
  and set(info.get("audit_kinds", {})) == {
268
270
  "code", "image_desc", "text", "permission",
269
- "work_done", "work_wip"},
271
+ "work_done", "work_wip", "ccg_marks", "hyperedge"},
270
272
  str(list(info.get("audit_kinds", {})))[:120])
273
+ check("cg info 自描述 CCG 契约角色(裁定 B)",
274
+ info.get("ccg_contract", {}).get("生效条件") == "前置条件 precondition"
275
+ and len(info.get("ccg_contract", {})) == 6,
276
+ str(info.get("ccg_contract"))[:120])
271
277
  w = kc.call("cg", {"op": "write", "content_kind": "text",
272
278
  "content": "hello", "node_id": "kw1"})
273
279
  check("未验证的写入进审核队列",
@@ -201,6 +201,30 @@ def main():
201
201
  mfm.get("induced_concept") == cid
202
202
  and cid in {e.get("target") for e in (mfm.get("edges") or [])},
203
203
  str(mfm.get("induced_concept")))
204
+ # ---- 2026-09-19 阶段一:巩固留痕字段一等公民 ----
205
+ check("成员侧记 consolidated_into(规范名·巩固进哪一条)",
206
+ mfm.get("consolidated_into") == cid
207
+ and mfm.get("induced_concept") == cid,
208
+ str(mfm.get("consolidated_into")))
209
+ check("成员侧记 consolidated_at(何时巩固)",
210
+ bool(mfm.get("consolidated_at")), str(mfm.get("consolidated_at")))
211
+ check("概念侧记 consolidated_at(概念形成即巩固时刻)",
212
+ bool(cfm.get("consolidated_at"))
213
+ and cfm.get("induced_at") == cfm.get("consolidated_at"),
214
+ f"{cfm.get('consolidated_at')} / {cfm.get('induced_at')}")
215
+ check("前身可定位:概念侧 induced_from 与成员侧列互查一致",
216
+ set(cfm.get("induced_from") or []) == {"ind_1", "ind_2", "ind_3"}
217
+ and all(((cg.get(m) or {}).get("frontmatter") or {}
218
+ ).get("consolidated_into") == cid
219
+ for m in ("ind_1", "ind_2", "ind_3")))
220
+ # add() 是**全量重建 fm**——覆写后留痕必须仍在(回读节点继承,非索引快照)
221
+ cg.add("ind_1", IND_A, layer="contextual", importance=0.4,
222
+ verification_basis="other", actor="p31")
223
+ mfm2 = (cg.get("ind_1") or {}).get("frontmatter") or {}
224
+ check("覆写后成员侧巩固留痕继承(consolidated_into/at 不丢)",
225
+ mfm2.get("consolidated_into") == cid
226
+ and bool(mfm2.get("consolidated_at")),
227
+ str(mfm2.get("consolidated_into")))
204
228
  check("induce 留痕 _maintain.jsonl",
205
229
  any(r.get("action") == "induce"
206
230
  for r in consolidate._read_maintain(ROOT)))
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """层归位(P38 · G4 设计态验收)。
3
3
 
4
- 对照 `docs/认知图_G4-G8缺口裁定单_v0.1.md` §二:批次流水账(`note_`/`milestone_`/
4
+ 对照 `docs/mdcg/认知图_G4-G8缺口裁定单_v0.1.md` §二:批次流水账(`note_`/`milestone_`/
5
5
  `retest6_`)与感知产物(`imgpart_`/`vpipe_`)混在 knowledge 层,语义上属**情境**,
6
6
  需归位到 `contextual` 且**保留可召回**。
7
7
 
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """视觉证据回填(P39 · G5 设计态验收)。
3
3
 
4
- 对照 `docs/认知图_G4-G8缺口裁定单_v0.1.md` §三:视觉节点证据面恒为 `{}`,
4
+ 对照 `docs/mdcg/认知图_G4-G8缺口裁定单_v0.1.md` §三:视觉节点证据面恒为 `{}`,
5
5
  根因是产出侧只取 `model_evidence`(白箱部件不带该键)——即**证据口径未定义**。
6
6
  本轮以**库外只读归档**(逐部件结构化结果)为证据源,按三档映射回填,脱敏、
7
7
  不读图像、不重跑视觉。
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """G6 · node_ 结构提炼抽检工单与扩批闸门(P40 设计态验收)。
3
3
 
4
- 对照 `docs/认知图_G4-G8缺口裁定单_v0.1.md` §四 G6:`node_*`(P37 派生记忆)
4
+ 对照 `docs/mdcg/认知图_G4-G8缺口裁定单_v0.1.md` §四 G6:`node_*`(P37 派生记忆)
5
5
  自带 `ccg_exempt=true`,只声明「功能名 / 生效条件」,`子功能/执行/不适用条件` 全缺。
6
6
  条件 A 要求**先抽 20 条做提炼预演、人工核对提炼口径,绝不盲跑全量**。
7
7
 
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """G7 · 自主演化巡检(把「有能力」变成「有驱动」)(P41 设计态验收)。
3
3
 
4
- 对照 `docs/认知图_G4-G8缺口裁定单_v0.1.md` §五 G7:固化 / 重要性 / 去污染三类自我
4
+ 对照 `docs/mdcg/认知图_G4-G8缺口裁定单_v0.1.md` §五 G7:固化 / 重要性 / 去污染三类自我
5
5
  演化动作早已具备,但**没有任何驱动源**周期性问「现在有多少该固化 / 该重算的候选」,
6
6
  于是能力被饿死。本项给常驻循环挂上**只读**演化巡检 + **受控**自愈。
7
7
 
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """G8 · 派生溯源(新增即建链 + 失败不阻断 + 悬空可检出)(P42 设计态验收)。
3
3
 
4
- 对照 `docs/认知图_G4-G8缺口裁定单_v0.1.md` §六 G8:节点拆并/派生后**血缘丢失**,
4
+ 对照 `docs/mdcg/认知图_G4-G8缺口裁定单_v0.1.md` §六 G8:节点拆并/派生后**血缘丢失**,
5
5
  库根无 `_link.jsonl`、frontmatter 的派生字段全空,事后无从回答「这个节点从哪来」。
6
6
  本项只对**新增**节点常态化建链(历史不回填),且立三条硬约束。
7
7
 
@@ -1,7 +1,7 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  """§七 · 召回分池与降权(P43 设计态验收)。
3
3
 
4
- 对照 `docs/认知图_G4-G8缺口裁定单_v0.1.md` §七:索引/产物类节点(`code_`/`doc_`)
4
+ 对照 `docs/mdcg/认知图_G4-G8缺口裁定单_v0.1.md` §七:索引/产物类节点(`code_`/`doc_`)
5
5
  词面更易命中,在 `GLOBAL_CAP` 单条截断点**先把知识节点挤掉**。本项把截断额度
6
6
  **显式分池**(不是抬高额度),并立四条纪律。
7
7
 
@@ -41,7 +41,11 @@ PASS = FAIL = 0
41
41
  FAILS = []
42
42
 
43
43
  BODY = "召回截断 索引 分池 内容"
44
- QUERY = "召回截断"
44
+ # 多词查询:索引类含全部查询词、知识类缺「分池」→ 相关度有**区分度**。
45
+ # 原语料下 16 条分数全等(覆盖度口径),截断谁入榜只能由传入序决定——而传入序
46
+ # 本身不确定(目录枚举 + 并行 prefetch),断言 `off=6` 实为顺序抽签的产物。
47
+ QUERY = "召回截断 分池"
48
+ KBODY = "召回截断 索引 内容"
45
49
 
46
50
 
47
51
  def ok(cond, label):
@@ -71,7 +75,12 @@ def _snapshot(root):
71
75
 
72
76
 
73
77
  def _mk(root):
74
- """6 个索引类(code_/doc_)+ 10 个知识类,正文同源 → 词面完全等价竞争。"""
78
+ """6 个索引类(code_/doc_)+ 10 个知识类。
79
+
80
+ §七 的真实机制是「索引/产物类节点**词面命中率更高**」(正文短、查询词占比大),
81
+ 故索引类正文短、知识类正文长(含背景说明),使索引类相似度**确实**高于知识类
82
+ ——挤占由相关度驱动,不依赖写入顺序(截断依据已改为相关度,见 `cut_by_relevance`)。
83
+ """
75
84
  cg = MdCGOS(root, actor="test")
76
85
  for i in range(4):
77
86
  cg.add(f"code_{i}", f"# 功能名:索引条目 {i}\n# 生效条件:条件 I\n\n{BODY} {i}\n",
@@ -80,7 +89,10 @@ def _mk(root):
80
89
  cg.add(f"doc_{i}", f"# 功能名:文档索引 {i}\n# 生效条件:条件 D\n\n{BODY} {i}\n",
81
90
  layer="knowledge", tags=["index"])
82
91
  for i in range(10):
83
- cg.add(f"kp_{i}", f"# 功能名:知识 {i}\n# 生效条件:条件 K\n\n{BODY} {i}\n",
92
+ cg.add(f"kp_{i}",
93
+ f"# 功能名:知识 {i}\n# 生效条件:条件 K\n\n{KBODY} {i}\n"
94
+ f"备注:本条为知识类条目,含背景说明、推理链与引用出处,正文较长,"
95
+ f"查询词在全文中的占比因此显著低于索引类条目。\n",
84
96
  layer="knowledge")
85
97
  cg.add("n_rej", f"# 功能名:被否决\n# 生效条件:条件 R\n\n{BODY} 否\n",
86
98
  layer="rejected")
@@ -238,12 +250,27 @@ def main():
238
250
  # 但「乘数可复算」这一被测语义不变。
239
251
  base = {r[0]["id"]: r[1] for r in off}
240
252
  sc = {r[0]["id"]: r[1] for r in on}
241
- ok(abs(sc["code_0"] - base.get("code_0", 0.0) * 0.6) < 1e-9,
242
- f"(8) 索引类命中分 == 基础分 × 0.6(base={base.get('code_0', 0.0):.6f} → "
243
- f"{sc.get('code_0', float('nan')):.6f})")
244
- common = [i for i in range(6) if f"kp_{i}" in base and f"kp_{i}" in sc]
245
- ok(common and all(abs(sc[f"kp_{i}"] - base[f"kp_{i}"]) < 1e-9 for i in common),
246
- f"(8) 知识类命中分不被削(权重 1.0;逐条比对 {len(common)} 条)")
253
+
254
+ def _pick_idx(d):
255
+ """挑一条「关闭态也有基础分」的索引类入榜条目。
256
+
257
+ 截断依据改为相关度后,具体哪条索引入榜由分数序决定(不再是固定的
258
+ `code_0`——那正是按传入序截断时代的产物),故动态取。
259
+ """
260
+ return next((i for i in d if PL.pool_of(i) == "index" and i in base), None)
261
+
262
+ iid = _pick_idx(sc)
263
+ ok(iid is not None, "(8) 分池态含索引类条目(额度保底生效)")
264
+ ok(iid is not None and abs(sc[iid] - base[iid] * 0.6) < 1e-9,
265
+ f"(8) 索引类命中分 == 基础分 × 0.6({iid}: base={base.get(iid, 0.0):.6f} → "
266
+ f"{sc.get(iid, float('nan')):.6f})")
267
+ # 知识类权重 1.0 → 命中分应与关闭态同源分一致。不硬编码编号:关闭态额度
268
+ # 被索引类占满,只余 2 条知识类入榜,与分池态取的 6 条未必有同编号交集
269
+ # (全同分下由稳定序决定),故按「关闭态知识分基准」比对。
270
+ base_kp = [v for k, v in base.items() if k.startswith("kp_")]
271
+ sc_kp = [v for k, v in sc.items() if k.startswith("kp_")]
272
+ ok(base_kp and sc_kp and all(abs(v - base_kp[0]) < 1e-9 for v in sc_kp),
273
+ f"(8) 知识类命中分不被削(权重 1.0;base={base_kp[:1]} → on={sc_kp[:2]})")
247
274
  ok(PL.weight_of("code_x", {}, True) == PL.WEIGHTS["index"]["weight"],
248
275
  "(8) weight_of 与表内系数一致")
249
276
  alt = {"knowledge": {"cap_ratio": 0.5, "weight": 1.0},
@@ -251,9 +278,10 @@ def main():
251
278
  "negative": {"cap_ratio": 0.1, "weight": 0.5}}
252
279
  on2, _m2 = cg.search(QUERY, k=20, record=False, pools=alt)
253
280
  sc2 = {r[0]["id"]: r[1] for r in on2}
254
- ok(abs(sc2["code_0"] - base.get("code_0", 0.0) * 0.3) < 1e-9,
255
- f"(8) 换表即换行为(base×0.3={base.get('code_0', 0.0) * 0.3:.6f} → "
256
- f"{sc2.get('code_0', float('nan')):.6f})")
281
+ iid2 = _pick_idx(sc2)
282
+ ok(iid2 is not None and abs(sc2[iid2] - base[iid2] * 0.3) < 1e-9,
283
+ f"(8) 换表即换行为({iid2}: base×0.3={base.get(iid2, 0.0) * 0.3:.6f} → "
284
+ f"{sc2.get(iid2, float('nan')):.6f})")
257
285
  ok(PL.caps(10, PL.resolve(alt)) == {"knowledge": 4, "index": 4, "negative": 2},
258
286
  f"(8) 换表额度同步可复算(实得 {PL.caps(10, PL.resolve(alt))})")
259
287
 
@@ -28,7 +28,7 @@ import tempfile
28
28
 
29
29
  _HERE = os.path.dirname(os.path.abspath(__file__))
30
30
 
31
- from .md_whitebox import build_db_from_md # noqa: E402
31
+ from .md_whitebox import build_db_from_md, corpus_gap # noqa: E402
32
32
 
33
33
  SOURCE_DB = os.path.join(_HERE, "whitebox_kb", "wisdom", "wisdom-book-cloud.db")
34
34
 
@@ -129,6 +129,19 @@ def _report(rows):
129
129
  def main():
130
130
  ok = True
131
131
 
132
+ # 依赖自辩(2026-09-20 v14 缺陷 F):源库与 md 语料均为 gitignored 本地
133
+ # 数据面——缺失时本模块自己打 SKIP 返回 0。旧形态下缺库会以未捕获的
134
+ # `sqlite3.OperationalError: unable to open database file` traceback 示人,
135
+ # 与兄弟目标「自建库后断言失败」构成同一根因的第三副面孔。
136
+ if not os.path.exists(SOURCE_DB):
137
+ print("SKIP test_p44_md_whitebox:依赖源库 %s(.gitignore 忽略,"
138
+ "需本地生成)" % SOURCE_DB)
139
+ return 0
140
+ _gap = corpus_gap()
141
+ if _gap:
142
+ print("SKIP test_p44_md_whitebox:%s" % _gap)
143
+ return 0
144
+
132
145
  # ---- 1) 结构等价 ----
133
146
  # force:从 md 语料**重新**还原,保证 access_count 等可变字段与源库快照
134
147
  # 同起点(复用旧库会带上此前问答累积的 access,造成假差异)。