@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
@@ -88,6 +88,7 @@ PATHSETS = (("lexical",), ("lexical", "bucket"),
88
88
 
89
89
  # ------------------------------------------------------------------ 写入侧加工
90
90
 
91
+ # 生效条件:c 含 'zh_fields' 且其中 identity/time/summary/terms/condition 均存在时,返回按身份、时间、摘要、词、条件及 c['text'] 拼成的正文,缺任一键则抛 KeyError;
91
92
  def body_of(c):
92
93
  """正文:与 bench_zh_mad.build_arm 的 a0 臂**逐字一致**(无意图行/无承接行)。"""
93
94
  f = c["zh_fields"]
@@ -102,6 +103,7 @@ def body_of(c):
102
103
  ])
103
104
 
104
105
 
106
+ # 生效条件:c 含 'zh_fields',terms 可迭代且 summary 经 str() 后参与空白切分时,将 terms 与切分词合并后交 routing.big_domain_classify 返回域判定结果;
105
107
  def write_domain(c):
106
108
  """写入侧域判定:只读 turn 自身的 zh_fields(盲于查询集)。"""
107
109
  f = c["zh_fields"]
@@ -109,11 +111,13 @@ def write_domain(c):
109
111
  return routing.big_domain_classify(terms)
110
112
 
111
113
 
114
+ # 生效条件:q 含 question 字段时,返回 mg.expand_query_terms(q["question"]) 的词列表经 routing.big_domain_classify 得到的域分类。
112
115
  def query_domain(q):
113
116
  """查询侧域判定:与写入侧共用同一份 routing 词表(两侧同构)。"""
114
117
  return routing.big_domain_classify(list(mg.expand_query_terms(q["question"])))
115
118
 
116
119
 
120
+ # 生效条件:mode 为 'base' 时返回 [];mode 为 'bare' 时返回 bz.normalize_terms(c, df) 的列表;其余 mode 下取 doms.get(c['id']) 得 d,d 为真值时返回 ['domain:'+d],否则返回 [];
117
121
  def arm_tags(c, mode, df, doms):
118
122
  if mode == "base":
119
123
  return []
@@ -124,6 +128,7 @@ def arm_tags(c, mode, df, doms):
124
128
  return [f"domain:{d}"] if d else []
125
129
 
126
130
 
131
+ # 生效条件:传入 corpus/name/mode/df 时先清空 HERE+ARM_PREFIX+name 同名目录再建 MdCGOS 并返回 (cg, doms);mode 为 'shuf' 时把有域节点的域随机重排,verbose 为假值时跳过桶健康输出;
127
132
  def build_domain_arm(corpus, name, mode, df, verbose=True):
128
133
  """按臂建库。四臂唯一差异是 tags 内容(layer/正文/edges 全同)。"""
129
134
  import shutil
@@ -158,6 +163,7 @@ def build_domain_arm(corpus, name, mode, df, verbose=True):
158
163
 
159
164
  # ------------------------------------------------------------------ 主流程
160
165
 
166
+ # 生效条件:不适用(无必需形参与模块级常量)
161
167
  def main():
162
168
  corpus = list(ec.iter_jsonl(CORPUS567))
163
169
  questions = list(ec.iter_jsonl(QUESTIONS500))
@@ -175,6 +181,7 @@ def main():
175
181
  n_ctx = sum(1 for v in qctx.values() if v)
176
182
  print(f"查询侧落域 {n_ctx}/{len(questions)} = {n_ctx / len(questions):.1%}")
177
183
 
184
+ # 生效条件:q 含 'qid' 键时返回查询上下文映射中该 qid 对应的值,映射缺该键时 .get 返回 None(q 缺 'qid' 则抛 KeyError);
178
185
  def context_of(q):
179
186
  return qctx.get(q["qid"])
180
187
 
@@ -218,6 +225,7 @@ def main():
218
225
  ec.save_result("axis_domain_locomo_zh.json", out)
219
226
 
220
227
  # ---- 裁决摘要 ----
228
+ # 生效条件:a 与 p 以 '|' 拼成键后,在结果字典的 cells 映射中取该键,含键时返回其值,缺键时 .get 返回 {};
221
229
  def cell(a, p):
222
230
  return out["cells"].get(f"{a}|{p}", {})
223
231
 
@@ -247,4 +255,4 @@ def main():
247
255
 
248
256
 
249
257
  if __name__ == "__main__":
250
- main()
258
+ main()
@@ -122,10 +122,12 @@ D_TPL = [
122
122
  DISTRACT_POOL = ["马", "鱼", "狗", "鸟", "羊", "猪", "鸭", "肉", "奶", "蛋", "油", "米"]
123
123
 
124
124
 
125
+ # 生效条件:s 为字符串时返回其全部相邻二元组集合;当 len(s) 小于 2 时返回空集合。
125
126
  def _bigrams(s):
126
127
  return {s[i:i + 2] for i in range(len(s) - 1)}
127
128
 
128
129
 
130
+ # 生效条件:无参调用且 ATOMS_PATH 载入 atoms 后,逐条确认 UNSEEN 各组合词不在其中文集合、其相邻字符对均为原子,并确认 UNSEEN 无重复、set(COMP_EN)==set(UNSEEN)、set(COMP_L3)<=set(UNSEEN),全部成立才静默通过,任一断言不成立即 AssertionError。
129
131
  def assert_material():
130
132
  """盲测纪律的机器化:素材在/不在 atoms + 组合词互相不冲突。"""
131
133
  atoms = json.load(open(ATOMS_PATH, encoding="utf-8"))["atoms"]
@@ -139,6 +141,7 @@ def assert_material():
139
141
  assert set(COMP_EN) == set(UNSEEN) and set(COMP_L3) <= set(UNSEEN)
140
142
 
141
143
 
144
+ # 生效条件:以 SEED 初始化 random.Random 后对 UNSEEN 每词按 G_TPL 取模板生成含 gold 的篇目,再对 j=0..21 用 DISTRACT_POOL 随机取两个不同词按 D_TPL 造文,50 次重试内首次出现不含 UNSEEN 任何组合词的文本即 break 并 append,22 篇齐备后返回 corpus,50 次全冲突则 raise AssertionError。
142
145
  def gen_corpus():
143
146
  """33 篇受控语料:11 gold + 22 干扰。确定性,断言内嵌。"""
144
147
  rng = random.Random(SEED)
@@ -160,6 +163,7 @@ def gen_corpus():
160
163
  return corpus
161
164
 
162
165
 
166
+ # 生效条件:对 UNSEEN 中每个 c 生成 L1 与 L2 题;当 c 属于 L3_SET 时,用 assert 强制其 COMP_L3 问句与 g_c 的 gold 文本 bigram 零交集,失败抛 AssertionError,通过后追加 L3 题。
163
167
  def gen_questions():
164
168
  """33 题。L3 生成时校验 query×gold bigram 零交集(纪律4)。"""
165
169
  questions = []
@@ -184,6 +188,7 @@ def gen_questions():
184
188
  CORPUS = None # gen_questions 需引用语料正文(L3 校验),main 内先建语料
185
189
 
186
190
 
191
+ # 生效条件:以 cg/questions/tag/en_atoms 与默认 semantic=False 调用时,en_atoms 为真则设 os.environ["MDCG_EN_ATOMS"]="1"、为假则 pop,semantic 为真则设 MDCG_SEMANTIC="1" 且仅当 semantic=="norm" 时把带真值 q_atoms 的题替换为 q_atoms 文本、semantic=="raw" 保持原句、semantic 为假则 pop,随后在 lexical 路径以 k=5 评测并返回 (按 ALL/L1_surface/L2_crosslingual/L3_semantic 分型的 by_type, 仅 en_atoms 为真时按 L2_crosslingual 题收集中文语素的 probe)。
187
192
  def run_arm(cg, questions, tag, en_atoms, semantic=False):
188
193
  """单臂评测:臂差异只在查询侧环境开关展开。返回 (summary_by_type, l2_probe)。
189
194
 
@@ -223,6 +228,7 @@ def run_arm(cg, questions, tag, en_atoms, semantic=False):
223
228
  return by_type, probe
224
229
 
225
230
 
231
+ # 生效条件:无参调用时先 assert_material 再经 gen_corpus/gen_questions 得到语料与题,os.path.isdir(ARM_ROOT) 为真则删除该目录,以 ARM_ROOT 建 cg 并写入 CORPUS 全部篇目,os.path.isdir(ARM_ROOT+"_b2") 为真则删除该目录、以该路径建 cg2 并仅对 gold 为真值的篇目附加 semantic=" ".join(gold) 后写入,再依次以 (cg,b0_legacy,False,False)/(cg,b1_enatoms,True,False)/(cg2,b2_comp,False,"norm")/(cg2,b3_unified,False,"raw") 四臂调 run_arm 汇总指标与 b1 的 L2 探针,最后 ec.save_result 写出 blind_comp_baseline.json 并在 out 中记录 seed/n_corpus/n_q/arms/l2_probe/elapsed_s/boundaries。
226
232
  def main():
227
233
  global CORPUS
228
234
  t0 = time.time()
@@ -300,4 +306,4 @@ def main():
300
306
 
301
307
 
302
308
  if __name__ == "__main__":
303
- main()
309
+ main()
@@ -68,6 +68,7 @@ NOISE_ZH = "天气 音乐 旅行"
68
68
  WRONG_POOLS = ["经济 历史 音乐", "天体 地理 化学", "科技 法律 医学"]
69
69
 
70
70
 
71
+ # 生效条件:text 非空且 mode 为 drop20/noise3/wrong20 时按 idx 错位扰动并返回新串;text 为空返回 text or "",mode 不在三者之内时原样返回 text。
71
72
  def perturb_kw(text, mode, idx):
72
73
  """②路 query 关键词扰动(确定性规则,验证归一噪声灵敏度)。
73
74
 
@@ -89,6 +90,7 @@ def perturb_kw(text, mode, idx):
89
90
  return text
90
91
 
91
92
 
93
+ # 生效条件:CHAR_ATOMS 可读时按 data.get("lexicon") or {} 取词库,lexicon 缺失或为假值即返回空字典,否则逐键返回 {ch: str(v.get("en") or "")}(v 缺 "en" 或 "en" 为假值时该键值为空串)。
92
94
  def load_char_atoms():
93
95
  """字级英文原子库:{中文字: 英文短语}。"""
94
96
  with io.open(CHAR_ATOMS, encoding="utf-8") as f:
@@ -97,6 +99,7 @@ def load_char_atoms():
97
99
  return {ch: str(v.get("en") or "") for ch, v in lex.items()}
98
100
 
99
101
 
102
+ # 生效条件:以 text or "" 逐字符、char_atoms 为字级映射表——字符落在 ZH_RANGE 内时取 char_atoms.get(ch, "")(缺键回落空串),其余字符原样保留,返回 normalize_en(" ".join(parts));text 为假值(None/空串)时按空串返回 normalize_en("")。
100
103
  def zh_map_en(text, char_atoms):
101
104
  """中文逐字→英文短语映射串;英文/数字原样保留(交 normalize_en 归一)。"""
102
105
  lo, hi = ZH_RANGE
@@ -109,6 +112,7 @@ def zh_map_en(text, char_atoms):
109
112
  return normalize_en(" ".join(parts))
110
113
 
111
114
 
115
+ # 生效条件:以 normalize_en(str(c.get("text") or "")).split() 为基词集,body_only 为真时只返回该集合的 frozenset;body_only 为假(默认 False)时再并入 zh_map_en(str(c.get("zh") or ""), char_atoms) 拆出的词,返回合并后的 frozenset。
112
116
  def node_atom_set(c, char_atoms, body_only=False):
113
117
  """doc 侧节点原子集:中文五槽字级映射 ∪ 英文正文归一词(双语双路 doc 侧)。
114
118
 
@@ -121,6 +125,7 @@ def node_atom_set(c, char_atoms, body_only=False):
121
125
  return frozenset(toks)
122
126
 
123
127
 
128
+ # 生效条件:a 或 b 为假值(None/空集)时返回 0.0,否则交集非空返回 len(a & b)/len(a | b)、交集为空亦返回 0.0。
124
129
  def jaccard(a, b):
125
130
  if not a or not b:
126
131
  return 0.0
@@ -128,10 +133,12 @@ def jaccard(a, b):
128
133
  return inter / len(a | b) if inter else 0.0
129
134
 
130
135
 
136
+ # 生效条件:对 st.items() 每个值取 round(v, 1) 组成同键字典,st 为空字典时返回空字典。
131
137
  def round_dict(st):
132
138
  return {k: round(v, 1) for k, v in st.items()}
133
139
 
134
140
 
141
+ # 生效条件:遍历 questions 逐问评测——qatoms_of(q) 为假值时仅累加 st["n"] 不计命中,否则按 jaccard 对 docs 降序(同分按 nid 升序)排序、以首个 nid 落在 q.get("evidence_turns") or [] 中的 rank 累加 hit@1/5/10 与 1/rank 的 MRR,打印后返回 {k: v/max(st["n"],1)(rr 项)或 v*100.0/max(st["n"],1)}。
135
142
  def run_arm(questions, docs, qatoms_of, label):
136
143
  """单臂评测:全池 Jaccard 排序,hit@1/5/10 + MRR。"""
137
144
  st = {"h1": 0, "h5": 0, "h10": 0, "rr": 0.0, "n": 0}
@@ -160,6 +167,7 @@ def run_arm(questions, docs, qatoms_of, label):
160
167
  return {k: (v / n if k == "rr" else v * 100.0 / n) for k, v in st.items()}
161
168
 
162
169
 
170
+ # 生效条件:CORPUS、QUESTIONS、CHAR_ATOMS 与 b6.EN_QUESTIONS 均可读(en_rows 由 ec.iter_jsonl 读取 b6.EN_QUESTIONS 构建)时,载入语料与题、构建 docs 与 docs_body、逐臂 run_arm 并打印锚点,返回 0。
163
171
  def main():
164
172
  t0 = time.time()
165
173
  with io.open(CORPUS, encoding="utf-8") as f:
@@ -190,6 +198,7 @@ def main():
190
198
  # 臂④ 机械归一端到端下界:英文问句 → 词表直译为中文词(CEDICT 28294 键
191
199
  # ∪ EN_ZH 手工层,无 AI)→ ②同链路。与②唯一差异 = query 归一来源:
192
200
  # ②=AI 理解式归一的输出形态(标注关键词),④=机械查表归一。
201
+ # 生效条件:以 en_rows.get(q.get("qid"), "")(qid 缺键回落空串)取英文题面,经 normalize_en_query 取出的 terms 拼接后由 zh_map_en 映射,返回 frozenset(zh_map_en(" ".join(terms), char_atoms).split());terms 为空时返回空 frozenset。
193
202
  def e4(q):
194
203
  terms, _ = normalize_en_query(en_rows.get(q.get("qid"), ""))
195
204
  return frozenset(zh_map_en(" ".join(terms), char_atoms).split())
@@ -0,0 +1,348 @@
1
+ # -*- coding: utf-8 -*-
2
+ """治理四指标只读评估器(阶段三 §5.1/§5.2 基线测量,纯合成确定性语料,不改任何行为面)。
3
+
4
+ 四指标(对照值来自 docs/灵枢自我改进工作计划_外部研究系列吸收 §5):
5
+ g1 修正传播率 — 上游信任态降级后,依赖下游一跳同步失效比例
6
+ (承载=trust.set_state+mark_dependents;对照 MAGE 91.2%)
7
+ g2 矛盾处理率 — 矛盾/否定证据被正确裁决比例
8
+ (承载=judge_qualification 负条件 REJECT + judge_ranking 终排剔除;
9
+ 对照 MAGE 88.5%)
10
+ g3 过期取回率 — 检索 top-k 返回已过期节点比例(越低越好)
11
+ (口径唯一真源=trust.is_expired / scrub._EXPIRY_KEYS;
12
+ 主口径=validity 防线残留率,副口径=默认面暴露率;对照 MAGE 3.1%)
13
+ g4 拒答 F1 — 不可答问题拒答的精确率/召回率/F1
14
+ (拒答判据=空结果 或 top1 资格态∈{BLINDSPOT, DEFER};
15
+ 对照 REMem 64.0)
16
+
17
+ 设计约束:
18
+ - 纯合成语料、无随机源,重复运行结果逐位一致(第 5 条可回放);
19
+ - tempfile 库,不触碰真实认知图库(评估器只读);
20
+ - 语料守卫断言(语料本身不合法立即 fail,防指标虚高——对齐 bench_blind_comp
21
+ assert_material 纪律)。
22
+ 运行:python -X utf8 -m md_cg.bench_governance [--out <json>]
23
+ """
24
+ import argparse
25
+ import json
26
+ import os
27
+ import shutil
28
+ import subprocess
29
+ import sys
30
+ import tempfile
31
+ import time
32
+
33
+ from .mdcg import MdCG
34
+ from .mdcos import MdCGOS
35
+ from . import trust
36
+
37
+ BASELINE_REF = {
38
+ "g1_correction_propagation": {"ours": None, "mage": 0.912},
39
+ "g2_contradiction_handling": {"ours": None, "mage": 0.885},
40
+ "g3_expired_recall": {"ours": None, "mage": 0.031, "note": "越低越好"},
41
+ "g4_refusal_f1": {"ours": None, "remem_f1": 64.0, "note": "REMem 为其自报口径,仅作量级对照"},
42
+ }
43
+
44
+ # ---------------------------------------------------------------- 语料 ----
45
+
46
+ NOW = None # main 内注入,保证同一次运行内时间一致
47
+
48
+
49
+ def _doc(title, fact, cond="无条件", neg=None):
50
+ """CCG 六要素正文(与 test_sem_noise._doc 同构:负条件双写中的正文行)。"""
51
+ lines = [
52
+ "# 功能名:" + title,
53
+ "# 生效条件:" + cond,
54
+ "# 子功能:" + title + "事实卡",
55
+ "# 执行:检索面事实提供",
56
+ "# 验证方式:test",
57
+ "# 不适用条件:" + (neg or "无"),
58
+ "",
59
+ fact,
60
+ ]
61
+ return "\n".join(lines)
62
+
63
+
64
+ # 可答事实:条件词面刻意出现在对应 query 里(正条件确认可命中 → ACCEPT)
65
+ FACTS = [
66
+ # (nid, 事实句, 正条件行, query)
67
+ ("g_f1", "灵枢检索缓存默认保留 128 条。", "载体:缓存配置", "缓存配置里默认缓存多大"),
68
+ ("g_f2", "蜂巢心跳间隔为 30 秒。", "载体:蜂巢参数", "蜂巢参数中心跳间隔是多少"),
69
+ ("g_f3", "评测器统一经 eval_common 汇总指标。", "载体:评测约定", "评测约定的汇总入口在哪"),
70
+ ("g_f4", "python 命令统一走 argv 列表加显式 UTF-8。", "无条件", "python 命令执行要用什么编码约定"),
71
+ ("g_f5", "语义摘要路默认关闭、显式 opt-in 才启用。", "无条件", "语义摘要路默认开还是关"),
72
+ ("g_f6", "分支节点不出库、不进主支检索。", "无条件", "分支节点会不会进主支检索"),
73
+ ]
74
+
75
+ # 否定反事实:负条件双写(kwarg + 正文行),否定情境 query=「你刚才在干什么」
76
+ NEG_QUERY = "你刚才在干什么"
77
+ NEG_COND = "刚才在干什么"
78
+ NEGATIVES = [
79
+ ("g_n1", "我没有在喝水。"),
80
+ ("g_n2", "我没有在写代码。"),
81
+ ("g_n3", "我没有在开会。"),
82
+ ("g_n4", "我没有在跑步。"),
83
+ ]
84
+
85
+ # 过期节点:与可答事实同题竞争(旧版本数值已失效),effective_until 已过
86
+ STALE = [
87
+ ("g_e1", "蜂巢心跳间隔曾为 10 秒(旧版)。", "g_f2"),
88
+ ("g_e2", "评测器旧口径按 k=3 汇总(已废弃)。", "g_f3"),
89
+ ("g_e3", "检索缓存默认曾为 64 条(旧版)。", "g_f1"),
90
+ ]
91
+
92
+ # 修正传播链:地基 U + 一跳依赖 D1..D4
93
+ U_GOV = "g_u_gov"
94
+ DEPENDENTS = ["g_d1", "g_d2", "g_d3", "g_d4"]
95
+
96
+ # 无关背景(干扰;CCG 完整可 ACCEPT——拒答 F1 的诚实下界来自它)
97
+ BACKDROP = [
98
+ ("g_b1", "工作区在约定中默认使用简体中文交流。"),
99
+ ("g_b2", "认知图只给知识与建议能力名,不执行操作。"),
100
+ ("g_b3", "留痕粒度按任务合并,不逐命令逐行。"),
101
+ ]
102
+
103
+ # 不可答问题(与语料词面零重叠;期望系统拒答)
104
+ UNANSWERABLE = [
105
+ "用户 2026 年春节在哪过的",
106
+ "项目预算总共批了多少万",
107
+ "作者最喜欢的菜是什么",
108
+ "下个版本计划支持日语吗",
109
+ "服务器部署在哪个机房",
110
+ "团队现在有多少人",
111
+ "竞品报价单是多少",
112
+ "昨天的会议纪要说了什么",
113
+ ]
114
+
115
+
116
+ def _assert_material(now):
117
+ """语料守卫:素材纪律机器断言(违者 fail,防指标虚高)。"""
118
+ fact_ids = {nid for nid, *_ in FACTS}
119
+ stale_ids = {nid for nid, *_ in STALE}
120
+ neg_ids = {nid for nid, *_ in NEGATIVES}
121
+ assert not (fact_ids & stale_ids | fact_ids & neg_ids | stale_ids & neg_ids), "语料 id 重叠"
122
+ assert len(UNANSWERABLE) >= 5 and len(FACTS) >= 5, "探针集过小"
123
+ # 不可答题与语料词面零重叠(粗粒度:语料特征词不出现于不可答题面)
124
+ lex = "".join(f for _, f, *_ in FACTS) + "".join(f for _, f in NEGATIVES) \
125
+ + "".join(f for _, f, _ in STALE) + "".join(f for _, f in BACKDROP)
126
+ for q in UNANSWERABLE:
127
+ overlap = [w for w in ("缓存", "蜂巢", "心跳", "评测", "python", "语义摘要", "分支") if w in q]
128
+ assert not overlap, f"不可答题词面泄漏:{q} 命中 {overlap}"
129
+ assert "无条件" not in lex or True # 语料自洽由 judge 实测兜底
130
+ for _, _, base in STALE:
131
+ assert base in fact_ids, "过期节点必须与某可答事实同题竞争"
132
+
133
+
134
+ def build_corpus(cg, now):
135
+ """建确定性语料。返回节点数。"""
136
+ n = 0
137
+ # 可答事实(F1-F3 带条件、F4-F6 无条件豁免)
138
+ for nid, fact, cond, _q in FACTS:
139
+ cg.add(nid, _doc(nid, fact, cond=cond), layer="knowledge",
140
+ verification_basis="test")
141
+ n += 1
142
+ # 否定反事实(负条件双写)
143
+ for nid, sent in NEGATIVES:
144
+ cg.add(nid, _doc(nid, sent, cond="时间:即时情境", neg=NEG_COND), layer="knowledge",
145
+ verification_basis="test", non_applicable_conditions=[NEG_COND])
146
+ n += 1
147
+ # 过期节点(effective_until 已过;expired_at 冗余由 add 派生)
148
+ for nid, fact, _base in STALE:
149
+ cg.add(nid, _doc(nid, fact, cond="无条件"), layer="knowledge",
150
+ verification_basis="test",
151
+ effective_from=now - 7200.0, effective_until=now - 3600.0)
152
+ n += 1
153
+ # 无关背景
154
+ for nid, fact in BACKDROP:
155
+ cg.add(nid, _doc(nid, fact), layer="knowledge", verification_basis="test")
156
+ n += 1
157
+ # 修正传播链:地基 + 一跳依赖(depends_on=依赖图语义,trust.dependents_index 消费;
158
+ # derived_from=血缘溯源,语义不同不混用)
159
+ cg.add(U_GOV, _doc(U_GOV, "地基结论:核心算法口径以文档 A 为准。", cond="无条件"),
160
+ layer="knowledge", verification_basis="test")
161
+ n += 1
162
+ for did in DEPENDENTS:
163
+ cg.add(did, _doc(did, f"{did} 结论:沿用地基口径实现细节。", cond="无条件"),
164
+ layer="knowledge", verification_basis="test", depends_on=[U_GOV])
165
+ n += 1
166
+ return n
167
+
168
+
169
+ # ---------------------------------------------------------------- 指标 ----
170
+
171
+ def m1_correction_propagation(cg):
172
+ """g1:上游降级 doubted → mark_dependents 一跳同步传播率。"""
173
+ r0 = trust.set_state(cg, U_GOV, "doubted", reason="基线评测:地基被修正")
174
+ assert isinstance(r0, dict) and r0.get("ok"), f"上游降级失败:{r0}"
175
+ r = trust.mark_dependents(cg, U_GOV, reason="基线评测:上游修正传播", apply=True)
176
+ deps, upd = r.get("dependents") or [], r.get("updated") or []
177
+ assert sorted(deps) == sorted(DEPENDENTS), f"依赖索引不符预期:{deps}"
178
+ rate = (len(upd) / len(deps)) if deps else None
179
+ return {"metric": "correction_propagation", "value": rate,
180
+ "detail": {"dependents": len(deps), "updated": len(upd),
181
+ "skipped": r.get("skipped"), "reference_mage": 0.912}}
182
+
183
+
184
+ def _is_refusal(results):
185
+ """拒答判据:空结果 或 top1 资格态 ∈ {BLINDSPOT, DEFER}。"""
186
+ if not results:
187
+ return True, "empty"
188
+ entry = results[0]
189
+ qual = entry[2] if len(entry) > 2 else None # 条目=(node, score, qual, prov)
190
+ st = (qual or {}).get("state") if isinstance(qual, dict) else None
191
+ return st in ("BLINDSPOT", "DEFER"), st
192
+
193
+
194
+ def m2_contradiction_handling(cg):
195
+ """g2:否定证据正确裁决率 = 定点裁决 + 检索防线(skip 项不入分母)。"""
196
+ correct = wrong = skipped = 0
197
+ detail = {"judged": [], "retrieval": []}
198
+ # (a) 定点裁决:否定节点在否定情境下应 REJECT(judge_qualification 直调)
199
+ for nid, _sent in NEGATIVES:
200
+ node = cg.get(nid)
201
+ qual = MdCG.judge_qualification(
202
+ {"frontmatter": node.get("frontmatter") or {}, "content": node.get("content") or ""},
203
+ NEG_QUERY, None)
204
+ st = qual.get("state")
205
+ detail["judged"].append({"nid": nid, "state": st})
206
+ if st == "REJECT":
207
+ correct += 1
208
+ elif st is None:
209
+ skipped += 1
210
+ else:
211
+ wrong += 1
212
+ # (b) 检索防线:judge_ranking 终排后 top-k 无否定节点冒充
213
+ res, meta = cg.search_rrf(NEG_QUERY, k=10, judge=True, judge_ranking=True,
214
+ record=False)
215
+ ids = [r[0]["id"] for r in res]
216
+ leaked = [i for i in ids if i in {n for n, _ in NEGATIVES}]
217
+ detail["retrieval"] = {"top_ids": ids[:5], "leaked_negatives": leaked,
218
+ "judge_filtered": (meta or {}).get("judge_filtered")}
219
+ if leaked:
220
+ wrong += 1
221
+ else:
222
+ correct += 1
223
+ total = correct + wrong
224
+ return {"metric": "contradiction_handling", "value": (correct / total) if total else None,
225
+ "detail": dict(detail, correct=correct, wrong=wrong, skipped=skipped,
226
+ reference_mage=0.885)}
227
+
228
+
229
+ def m3_expired_recall(cg, now):
230
+ """g3:过期取回率。主口径=validity 防线残留率;副口径=默认面暴露率。"""
231
+ stale_ids = {nid for nid, *_ in STALE}
232
+ probe = "蜂巢参数中心跳间隔是多少" # 与过期节点 g_e1 同题竞争
233
+ out = {}
234
+ for tag, kw in (("raw", {}), ("guard", {"validity": True}),
235
+ ("judge_ranking", {"judge_ranking": True})):
236
+ res, _meta = cg.search_rrf(probe, k=10, judge=True, record=False, **kw)
237
+ ids = [r[0]["id"] for r in res]
238
+ hits = [i for i in ids if i in stale_ids]
239
+ out[tag] = {"top_ids": ids[:5], "stale_hits": hits,
240
+ "rate": (len(hits) / len(ids)) if ids else None}
241
+ return {"metric": "expired_recall",
242
+ "value": out["guard"]["rate"], # 主口径:防线后残留(越低越好)
243
+ "detail": dict(out, probe=probe, stale_total=len(stale_ids),
244
+ reference_mage=0.031, note="raw=默认面暴露;guard=validity 防线")}
245
+
246
+
247
+ def m4_refusal_f1(cg):
248
+ """g4:拒答精确率/召回率/F1(正类=不可答)。"""
249
+ tp = fn = fp = tn = 0
250
+ detail = {"unanswerable": [], "answerable": []}
251
+ for q in UNANSWERABLE:
252
+ res, _m = cg.search_rrf(q, k=3, judge=True, judge_ranking=True, record=False)
253
+ refused, st = _is_refusal(res)
254
+ detail["unanswerable"].append({"q": q, "refused": refused, "top_state": st})
255
+ if refused:
256
+ tp += 1
257
+ else:
258
+ fn += 1
259
+ for _nid, _fact, _cond, q in FACTS:
260
+ res, _m = cg.search_rrf(q, k=3, judge=True, judge_ranking=True, record=False)
261
+ refused, st = _is_refusal(res)
262
+ detail["answerable"].append({"q": q, "refused": refused, "top_state": st})
263
+ if refused:
264
+ fp += 1
265
+ else:
266
+ tn += 1
267
+ p = tp / (tp + fp) if (tp + fp) else None
268
+ r = tp / (tp + fn) if (tp + fn) else None
269
+ if p is not None and r is not None and p + r:
270
+ f1 = 2 * p * r / (p + r)
271
+ else:
272
+ # tp+fp=0:系统从未拒答(无 query 侧拒答信号)——保守编码 F1=0.0 并如实注明
273
+ f1 = 0.0
274
+ return {"metric": "refusal_f1",
275
+ "value": f1,
276
+ "detail": {"precision": p, "recall": r, "tp": tp, "fn": fn, "fp": fp, "tn": tn,
277
+ "refusal_rule": "empty or top1 state in {BLINDSPOT, DEFER}",
278
+ "note": ("no refusal signal: judge 资格态只判节点可用性,"
279
+ "不判答案存在性;不可答题被无关 ACCEPT 节点冒充全部未拒"
280
+ if (tp + fp) == 0 else ""),
281
+ "reference_remem_f1": 64.0}}
282
+
283
+
284
+ # ---------------------------------------------------------------- 主流程 ----
285
+
286
+ def run(root=None, keep=False):
287
+ """跑四指标,返回 (report_dict, root)。root 供测试复检。"""
288
+ now = time.time()
289
+ _assert_material(now)
290
+ root = root or tempfile.mkdtemp(prefix="mdcg_governance_")
291
+ try:
292
+ cg = MdCGOS(root, actor="bench_governance", autoflush=200)
293
+ n_nodes = build_corpus(cg, now)
294
+ cg.flush()
295
+ report = {
296
+ "meta": {
297
+ "bench": "bench_governance",
298
+ "date": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(now)),
299
+ "corpus_nodes": n_nodes,
300
+ "head": _git_head(),
301
+ "determinism": "synthetic corpus, no RNG",
302
+ "scopes": "阶段三 §5.1 治理三件套 + §5.2 拒答量化(基线测量,不改行为)",
303
+ },
304
+ "g1_correction_propagation": m1_correction_propagation(cg),
305
+ "g2_contradiction_handling": m2_contradiction_handling(cg),
306
+ "g3_expired_recall": m3_expired_recall(cg, now),
307
+ "g4_refusal_f1": m4_refusal_f1(cg),
308
+ "baseline_reference": BASELINE_REF,
309
+ }
310
+ return report, root
311
+ finally:
312
+ if not keep:
313
+ shutil.rmtree(root, ignore_errors=True)
314
+
315
+
316
+ def _git_head():
317
+ try:
318
+ out = subprocess.run(["git", "rev-parse", "--short", "HEAD"],
319
+ capture_output=True, text=True, encoding="utf-8",
320
+ errors="replace", shell=False, timeout=10)
321
+ return (out.stdout or "").strip() or "unknown"
322
+ except Exception: # noqa: BLE001
323
+ return "unknown"
324
+
325
+
326
+ def main(argv=None):
327
+ ap = argparse.ArgumentParser(description="治理四指标只读评估器")
328
+ ap.add_argument("--out", default=os.path.join("data", "external", "eval_results",
329
+ "governance_baseline.json"))
330
+ ap.add_argument("--keep", action="store_true", help="保留临时库目录(调试用)")
331
+ args = ap.parse_args(argv)
332
+ report, root = run(keep=args.keep)
333
+ out = os.path.abspath(args.out)
334
+ os.makedirs(os.path.dirname(out), exist_ok=True)
335
+ with open(out, "w", encoding="utf-8") as f:
336
+ json.dump(report, f, ensure_ascii=False, indent=2)
337
+ print(json.dumps({k: v.get("value") for k, v in report.items()
338
+ if isinstance(v, dict) and "value" in v},
339
+ ensure_ascii=False, indent=2))
340
+ print("baseline ->", out, "| temp root:", root)
341
+ vals = [report[g]["value"] for g in ("g1_correction_propagation",
342
+ "g2_contradiction_handling",
343
+ "g3_expired_recall", "g4_refusal_f1")]
344
+ return 0 if all(v is not None for v in vals) else 1
345
+
346
+
347
+ if __name__ == "__main__":
348
+ raise SystemExit(main())
@@ -75,6 +75,7 @@ ZH_Q_PROMPT = """从下面英文问题里抽出中文关键词:只输出名词
75
75
 
76
76
 
77
77
  # ------------------------------------------------------------------ LLM
78
+ # 生效条件:环境变量 DEEPSEEK_API_KEY 为真值(缺省或空串即抛 RuntimeError「需要 DEEPSEEK_API_KEY」)且 range(retries) 至少迭代一次(retries≥1)时,用 messages、max_tokens 调 llm_chat 并返回 (content, usage);全部重试失败或 retries=0(last 保持 None)时抛 RuntimeError「LLM 调用失败:…」。
78
79
  def _llm(messages, max_tokens=400, retries=3):
79
80
  from md_cg.bench_task_ab_llm import llm_chat
80
81
  key = os.environ.get("DEEPSEEK_API_KEY")
@@ -100,6 +101,7 @@ _DEFAULT_COND = {"observation_position": "会话陈述", "observation_tool": "
100
101
  "existence_constraint": "公开"}
101
102
 
102
103
 
104
+ # 生效条件:p 经 os.path.isfile(p) 判定为普通文件时按 utf-8 打开并返回 json.load(f);os.path.isfile(p) 为假(含目录、不存在路径、空串)时返回 {}。
103
105
  def _load_json(p):
104
106
  if os.path.isfile(p):
105
107
  with open(p, encoding="utf-8") as f:
@@ -107,6 +109,7 @@ def _load_json(p):
107
109
  return {}
108
110
 
109
111
 
112
+ # 生效条件:无参调用即返回 (_load_json(MAN_ZH), _load_json(MAN_Q)),每个元素在模块级常量 MAN_ZH / MAN_Q 指向普通文件时为解析出的 JSON、否则为 {}。
110
113
  def _load_manual():
111
114
  """读入会话模型直接产出的中文层 / 中文查询词(零 API 依赖)。
112
115
 
@@ -119,6 +122,7 @@ def _load_manual():
119
122
  return _load_json(MAN_ZH), _load_json(MAN_Q)
120
123
 
121
124
 
125
+ # 生效条件:z 为真值且 re.search(r"条件=([^;;]+)") 命中,并按 [||] 切分后至少有一段以 ":" / ":" 分为两段且首段 strip 后在模块级常量 _COND_KEYS 中时,返回非空映射 dict;z 为假值、正则未命中或映射为空时返回 None。
122
126
  def _cond_of(z):
123
127
  """从中文层的「条件=观测位置:…|观测工具:…|…」抽条件空间 dict。"""
124
128
  m = re.search(r"条件=([^;;]+)", z or "")
@@ -132,6 +136,7 @@ def _cond_of(z):
132
136
  return out or None
133
137
 
134
138
 
139
+ # 生效条件:模块级常量 CACHE 经 os.path.isfile(CACHE) 判定为普通文件时按 utf-8 打开并返回 json.load(f);否则返回 {}。
135
140
  def _load_cache():
136
141
  if os.path.isfile(CACHE):
137
142
  with open(CACHE, encoding="utf-8") as f:
@@ -139,12 +144,14 @@ def _load_cache():
139
144
  return {}
140
145
 
141
146
 
147
+ # 生效条件:以 c 为输入即 os.makedirs(DIR, exist_ok=True) 后按 utf-8 把 c 以 ensure_ascii=False、indent=1 写入模块级常量 CACHE,无前置校验、无返回值。
142
148
  def _save_cache(c):
143
149
  os.makedirs(DIR, exist_ok=True)
144
150
  with open(CACHE, "w", encoding="utf-8") as f:
145
151
  json.dump(c, f, ensure_ascii=False, indent=1)
146
152
 
147
153
 
154
+ # 生效条件:cache 命中 "L2:"+turn["id"] 时直接返回该缓存值;否则用 ZH_PROMPT 拼 json.dumps({"date": turn.get("date"), "text": turn.get("text")})(键缺失回落 null)调 _llm,依次取 max_tokens=1200、2600,对 content or "" 去代码块与标签后 strip(" ,,、|"),首个非空即 break,把结果写回 cache 并返回(两次皆空则缓存并返回 "")。
148
155
  def zh_layer(turn, cache):
149
156
  """一条 turn → 中文词袋。缓存 key 带版本号:prompt 改版必须失效旧缓存。
150
157
 
@@ -171,6 +178,7 @@ def zh_layer(turn, cache):
171
178
  return s
172
179
 
173
180
 
181
+ # 生效条件:cache 命中 "Q2:"+q["qid"] 时直接返回该缓存值;否则以 ZH_Q_PROMPT+q["question"] 调 _llm(max_tokens=1200),去代码块后 strip(" ,,、") 写入 cache[key],结果为空串时抛 RuntimeError「查询侧关键词为空…」,非空时返回 cache[key]。
174
182
  def zh_question(q, cache):
175
183
  """英文问题 → 中文关键词(与写入侧同源;额度须 ≥1200,否则推理烧空 content)。"""
176
184
  key = "Q2:" + q["qid"]
@@ -186,6 +194,7 @@ def zh_question(q, cache):
186
194
 
187
195
 
188
196
  # ------------------------------------------------------------------ 池
197
+ # 生效条件:模块级常量 POOL 为普通文件时直接返回其中非空行的 json.loads 列表(此时不读 n_q、n_distract、seed);否则以 random.Random(seed)、每组 max(1, n_q//len(GROUPS)) 条(取 q["evidence_turns"][0] 为 gold)采样后追加 rng.sample(rest, min(n_distract, len(rest))) 干扰项,写出 POOL 与 questions.json 并返回 pool。
189
198
  def build_pool(n_q, n_distract, seed=7):
190
199
  """采样:n_q 题(分组覆盖)各取 evidence_turns[0] 为 gold,再取干扰。"""
191
200
  if os.path.isfile(POOL):
@@ -222,12 +231,14 @@ def build_pool(n_q, n_distract, seed=7):
222
231
  return pool
223
232
 
224
233
 
234
+ # 生效条件:DIR 目录下的 questions.json 是 UTF-8 合法 JSON 时,返回 json.load 得到的对象。
225
235
  def load_questions_zh():
226
236
  with open(os.path.join(DIR, "questions.json"), encoding="utf-8") as f:
227
237
  return json.load(f)
228
238
 
229
239
 
230
240
  # ------------------------------------------------------------------ 建库 / 评测
241
+ # 生效条件:以 ec.build_eval_cg(None, root, corpus or POOL, ec.lm_turn_text, "lmezh", calib_of=calib if zh_of 为真值 else None, rebuild=rebuild) 执行并返回其结果(形参 pool 在该调用中未被使用,实际用 corpus or POOL;zh_only 只在内层 calib 中生效,不传给 build_eval_cg)。
231
242
  def build(root, pool, zh_of=None, rebuild=False, zh_only=False, corpus=None):
232
243
  """zh_of: turn_id → 中文层;None = 裸文本库。
233
244
 
@@ -237,6 +248,7 @@ def build(root, pool, zh_of=None, rebuild=False, zh_only=False, corpus=None):
237
248
  上界而非全译库真值。故另设 F 臂(池只含 20 条 gold、正文全中文)隔离该假象,
238
249
  单测中文层自身的可区分性。
239
250
  """
251
+ # 生效条件:作为 build 的内层函数闭包使用 zh_of/zh_only,ctx 未被使用;zh_of 为真值且 zh_of.get(r["id"]) 为真值时 cs = _cond_of(z) or cs,否则 cs = dict(_DEFAULT_COND);zh_only 为真值时返回 (z or ec.lm_turn_text(r), [], cs),否则返回 (ec.lm_turn_text(r) 在 z 为真值时再拼 "\n"+z, [], cs)。
240
252
  def calib(r, ctx=None):
241
253
  z = zh_of.get(r["id"]) if zh_of else None
242
254
  cs = dict(_DEFAULT_COND)
@@ -252,6 +264,7 @@ def build(root, pool, zh_of=None, rebuild=False, zh_only=False, corpus=None):
252
264
  calib_of=calib if zh_of else None, rebuild=rebuild)
253
265
 
254
266
 
267
+ # 生效条件:给定 cg、questions 与 qtext_of 时,对每题用 qtext_of(q) 替换 question 后经 ec.evaluate_group 评测,并按 k 汇总为结果。
255
268
  def eval_arm(cg, questions, qtext_of, k=5):
256
269
  rows = []
257
270
  for q in questions:
@@ -261,6 +274,7 @@ def eval_arm(cg, questions, qtext_of, k=5):
261
274
  return ec.summarize(rows, k=k)
262
275
 
263
276
 
277
+ # 生效条件:argv 由 argparse 解析(--n-q/--n-distract/--k/--build/--rebuild/--workers 等);--build 只产池即返回,否则需外部数据在指定路径就位、缺失即抛异常不静默降级;
264
278
  def main():
265
279
  ap = argparse.ArgumentParser()
266
280
  ap.add_argument("--n-q", type=int, default=20)
@@ -287,6 +301,7 @@ def main():
287
301
  print(f"中文层:本地 {len(man_zh)} 条(查询词本地 {len(man_q)} 条),"
288
302
  f"缓存合计 {len(cache)} 条,模型 {MODEL}(本轮不调用)")
289
303
 
304
+ # 生效条件:对 r 调 zh_layer(r, cache)(cache 为闭包变量)成功时返回 (r["id"], 中文层, None);zh_layer 抛任何异常时返回 (r["id"], "", f"{type(exc).__name__}: {exc}")。
290
305
  def work(r):
291
306
  try:
292
307
  return r["id"], zh_layer(r, cache), None
@@ -393,4 +408,4 @@ def main():
393
408
 
394
409
 
395
410
  if __name__ == "__main__":
396
- sys.exit(main())
411
+ sys.exit(main())