@furongjun1999/dsh-memory 0.4.11 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (504) hide show
  1. package/README.md +16 -16
  2. package/codebuddy/CODEBUDDY.md +11 -3
  3. package/codebuddy/README.md +92 -90
  4. package/codebuddy/mcp.json +27 -27
  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 -169
  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 -144
  7. package/docs/README.md +142 -111
  8. package/docs/discipline/harnesses.yaml +244 -226
  9. package/docs/discipline/templates/full.md.tmpl +61 -61
  10. package/docs/discipline/templates/rules.mdc.tmpl +68 -0
  11. package/docs/discipline/templates/skill.md.tmpl +23 -23
  12. package/docs/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 +299 -299
  13. package/docs/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 +239 -239
  14. 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 +174 -174
  15. 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 +223 -223
  16. package/docs/{mdcg → hive}//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 +165 -160
  17. package/docs/hive//344/273/244/347/211/214/350/257/255/344/271/211/344/277/256/346/255/243_/344/273/262/350/243/201/344/275/215_v0.1.md +76 -0
  18. package/docs/{mdcg → hive}//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 -236
  19. 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 -43
  20. package/docs/hive//346/243/200/347/264/242/347/256/227/346/263/225/345/217/243/345/276/204/345/257/271/347/205/247_v0.1.md +85 -0
  21. 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 -102
  22. package/docs/hive//350/234/202/345/267/242M6_ingest/345/256/236/346/226/275/350/256/241/345/210/222_v0.1.md +47 -0
  23. 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 -503
  24. 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 +85 -85
  25. package/docs/hive//350/234/202/345/267/242/350/256/276/350/256/241_/347/220/206/350/256/272/345/257/271/351/275/220_v0.1.md +191 -0
  26. package/docs/hive//350/234/202/345/267/242/350/277/255/344/273/243_/345/256/217/350/247/202/344/270/216/347/276/244/344/275/223/350/260/203/345/272/246_v0.1.md +90 -0
  27. package/docs/mdcg/D_meta_/345/267/245/347/250/213/345/214/226/346/226/271/346/241/210_v0.2.md +216 -216
  28. package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +646 -646
  29. package/docs/mdcg/lingshu_tutorial.html +14449 -14449
  30. package/docs/mdcg/release_v0.4.11.md +49 -0
  31. package/docs/mdcg/release_v0.4.5.md +55 -55
  32. package/docs/mdcg/tool_table_v0.3.0.md +117 -117
  33. 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 -600
  34. package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +40 -40
  35. 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 +275 -275
  36. package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +54 -0
  37. 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 +130 -130
  38. 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 +278 -278
  39. 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 -172
  40. package/docs/mdcg//347/274/272/345/217/243/345/215/225_P0/346/224/266/345/217/243_v0.1.md +270 -270
  41. 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 +491 -491
  42. 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 +340 -340
  43. 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 +588 -588
  44. 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 -176
  45. 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 +81 -81
  46. package/docs/swarm//350/234/202/347/276/244/344/272/222/350/201/224_v0.1.md +704 -704
  47. 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 -242
  48. 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 -129
  49. 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 -134
  50. package/docs/theory//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
  51. 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 -145
  52. 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 +144 -144
  53. 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 +198 -198
  54. 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 -221
  55. 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 -237
  56. package/docs//345/217/221/345/270/203/344/273/266/345/233/236/346/272/257/350/257/264/346/230/216_v0.1.md +82 -82
  57. 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 +28 -2
  58. package/dsh/README.md +82 -82
  59. package/dsh/cordis.yml.example +139 -139
  60. package/dsh/update-lingshu.bat +11 -11
  61. package/lib/hooks.js +36 -2
  62. package/lib/lib/roleplay_web.js +427 -427
  63. package/md_cg/__init__.py +7 -7
  64. package/md_cg/audit.py +368 -368
  65. package/md_cg/autonomy.py +287 -287
  66. package/md_cg/backfill.py +1327 -1327
  67. package/md_cg/backfill_bigdomain.py +34 -34
  68. package/md_cg/bench6_arms.py +410 -410
  69. package/md_cg/bench6_common.py +230 -230
  70. package/md_cg/bench6_competitors.py +212 -212
  71. package/md_cg/bench_axis_domain.py +257 -257
  72. package/md_cg/bench_blind_comp.py +308 -308
  73. package/md_cg/bench_en_atoms_public.py +230 -230
  74. package/md_cg/bench_governance.py +348 -348
  75. package/md_cg/bench_lme_zh.py +410 -410
  76. package/md_cg/bench_locomo.py +121 -121
  77. package/md_cg/bench_locomo_zh.py +450 -450
  78. package/md_cg/bench_locomo_zh_public.py +147 -147
  79. package/md_cg/bench_longmem.py +112 -112
  80. package/md_cg/bench_membench.py +632 -632
  81. package/md_cg/bench_p0.py +149 -149
  82. package/md_cg/bench_progressive.py +287 -287
  83. package/md_cg/bench_role_views.py +238 -238
  84. package/md_cg/bench_task_ab.py +243 -243
  85. package/md_cg/bench_task_ab_llm.py +408 -408
  86. package/md_cg/bench_unified_en.py +204 -204
  87. package/md_cg/bench_zh_mad.py +601 -601
  88. package/md_cg/blindspot_tickets.py +123 -123
  89. package/md_cg/branches.py +285 -285
  90. package/md_cg/build_postings.py +73 -73
  91. package/md_cg/ccgc.py +1005 -948
  92. package/md_cg/census.py +132 -132
  93. package/md_cg/chain.py +300 -300
  94. package/md_cg/codeindex.py +531 -531
  95. package/md_cg/coldverify.py +292 -292
  96. package/md_cg/comment_gate.py +337 -337
  97. package/md_cg/cond_compose.py +190 -190
  98. package/md_cg/cond_facts.py +154 -154
  99. package/md_cg/cond_template.json +106 -106
  100. package/md_cg/condition_anchor.py +142 -142
  101. package/md_cg/conformance.py +726 -726
  102. package/md_cg/consistency.py +717 -717
  103. package/md_cg/consolidate.py +1536 -1439
  104. package/md_cg/corpus.py +110 -110
  105. package/md_cg/crosscheck.py +1097 -1097
  106. package/md_cg/crypto.py +437 -437
  107. package/md_cg/d_meta.py +310 -310
  108. package/md_cg/datapath.py +334 -334
  109. package/md_cg/docindex.py +473 -473
  110. package/md_cg/eval_common.py +575 -575
  111. package/md_cg/evidence.py +580 -580
  112. package/md_cg/evolution.py +477 -477
  113. package/md_cg/export.py +220 -220
  114. package/md_cg/forgetting.py +581 -581
  115. package/md_cg/fsutil.py +329 -329
  116. package/md_cg/hotcache.py +238 -214
  117. package/md_cg/hyperedge.py +251 -251
  118. package/md_cg/identity.py +390 -390
  119. package/md_cg/insight.py +500 -500
  120. package/md_cg/interop.py +199 -0
  121. package/md_cg/lexicon/build_cedict_en_zh.py +329 -329
  122. package/md_cg/lexicon/build_standard_en.py +171 -171
  123. package/md_cg/lexicon/expand_en_zh.py +211 -211
  124. package/md_cg/lifecycle.py +272 -272
  125. package/md_cg/linkref.py +280 -280
  126. package/md_cg/links.py +622 -622
  127. package/md_cg/mcp_server.py +129 -32
  128. package/md_cg/md_whitebox.py +345 -345
  129. package/md_cg/mdcg.py +176 -117
  130. package/md_cg/mdcos.py +79 -13
  131. package/md_cg/metacognition.py +591 -591
  132. package/md_cg/migrate.py +119 -119
  133. package/md_cg/migrate_aeis.py +221 -221
  134. package/md_cg/migrate_roleplay.py +293 -293
  135. package/md_cg/migrate_wisdom_graph.py +360 -360
  136. package/md_cg/mreview/__init__.py +25 -25
  137. package/md_cg/mreview/__main__.py +110 -110
  138. package/md_cg/mreview/bundle.py +178 -178
  139. package/md_cg/mreview/candidates.py +262 -262
  140. package/md_cg/mreview/govern.py +693 -693
  141. package/md_cg/mreview/locate.py +939 -939
  142. package/md_cg/mreview/pipeline.py +728 -728
  143. package/md_cg/mreview/rules/duplication.json +21 -21
  144. package/md_cg/mreview/rules/field_coverage.json +54 -54
  145. package/md_cg/mreview/rules/source_license.json +21 -21
  146. package/md_cg/mreview/rules/template_flow.json +21 -21
  147. package/md_cg/mreview/ruleset.py +252 -252
  148. package/md_cg/nodefile.py +575 -575
  149. package/md_cg/pooling.py +484 -472
  150. package/md_cg/postings.py +298 -298
  151. package/md_cg/predict.py +1100 -1100
  152. package/md_cg/progressive.py +123 -123
  153. package/md_cg/protect.py +272 -272
  154. package/md_cg/protocol/md_cg_gate.proto +33 -33
  155. package/md_cg/protocol.py +372 -372
  156. package/md_cg/provenance.py +582 -582
  157. package/md_cg/reach.py +453 -453
  158. package/md_cg/readcache.py +85 -0
  159. package/md_cg/refindex.py +833 -833
  160. package/md_cg/refine.py +604 -604
  161. package/md_cg/roleviews.py +89 -89
  162. package/md_cg/routing.py +365 -365
  163. package/md_cg/scrub.py +852 -852
  164. package/md_cg/security.py +274 -274
  165. package/md_cg/self_state.py +1029 -1029
  166. package/md_cg/selfreport.py +151 -151
  167. package/md_cg/semantic/__init__.py +10 -10
  168. package/md_cg/semantic/canonical.py +122 -122
  169. package/md_cg/semantic/en_normalizer.py +364 -364
  170. package/md_cg/semantic/en_zh_map.json +28694 -0
  171. package/md_cg/semantic/export_en_zh_map.py +64 -0
  172. package/md_cg/semantic/unify.py +45 -0
  173. package/md_cg/semantic/zh_en_atoms.py +139 -139
  174. package/md_cg/signer.py +562 -562
  175. package/md_cg/sources.py +815 -582
  176. package/md_cg/statushdr.py +179 -179
  177. package/md_cg/stg.py +48 -37
  178. package/md_cg/subgraph.py +729 -729
  179. package/md_cg/sustain.py +1138 -1138
  180. package/md_cg/tasks.py +470 -470
  181. package/md_cg/test_action_derive.py +203 -203
  182. package/md_cg/test_audit_rotate.py +270 -270
  183. package/md_cg/test_autonomy.py +143 -143
  184. package/md_cg/test_bench_governance.py +102 -102
  185. package/md_cg/test_blindspot_tickets.py +166 -166
  186. package/md_cg/test_branches.py +249 -249
  187. package/md_cg/test_ccg_perturb.py +184 -184
  188. package/md_cg/test_ccgc.py +433 -433
  189. package/md_cg/test_census_prune.py +81 -81
  190. package/md_cg/test_cond_compose_anchors.py +76 -76
  191. package/md_cg/test_cond_match.py +165 -165
  192. package/md_cg/test_condition_anchor.py +81 -81
  193. package/md_cg/test_d_meta.py +412 -412
  194. package/md_cg/test_datapath_root.py +199 -199
  195. package/md_cg/test_en_pipeline.py +166 -166
  196. package/md_cg/test_gain_gate.py +212 -212
  197. package/md_cg/test_health_scale.py +173 -173
  198. package/md_cg/test_hive_ingest.py +285 -0
  199. package/md_cg/test_hot_cold.py +215 -215
  200. package/md_cg/test_hyperedge.py +245 -245
  201. package/md_cg/test_i26_empty_first_write.py +116 -0
  202. package/md_cg/test_i27_e041_identity.py +128 -0
  203. package/md_cg/test_i28_hotcache_prodpath.py +122 -0
  204. package/md_cg/test_identity_attribution.py +147 -147
  205. package/md_cg/test_index_durability.py +224 -224
  206. package/md_cg/test_interop.py +93 -0
  207. package/md_cg/test_lifecycle.py +309 -309
  208. package/md_cg/test_linkref.py +306 -306
  209. package/md_cg/test_lock.py +43 -43
  210. package/md_cg/test_md_access_parity.py +255 -255
  211. package/md_cg/test_md_writepath.py +345 -345
  212. package/md_cg/test_mdstore_search_parity.py +160 -0
  213. package/md_cg/test_mr_m2.py +587 -587
  214. package/md_cg/test_mr_m3.py +710 -710
  215. package/md_cg/test_mr_m4.py +485 -485
  216. package/md_cg/test_p0.py +250 -250
  217. package/md_cg/test_p1.py +316 -316
  218. package/md_cg/test_p10_identity.py +173 -173
  219. package/md_cg/test_p11_consistency.py +233 -233
  220. package/md_cg/test_p12_metacognition.py +212 -212
  221. package/md_cg/test_p13_encryption.py +241 -241
  222. package/md_cg/test_p14_sustain.py +249 -249
  223. package/md_cg/test_p15_scrub.py +280 -280
  224. package/md_cg/test_p16_self_state.py +301 -301
  225. package/md_cg/test_p17_predict.py +354 -354
  226. package/md_cg/test_p18_whitebox.py +171 -171
  227. package/md_cg/test_p19_migrate_roleplay.py +149 -149
  228. package/md_cg/test_p20_evolution.py +315 -315
  229. package/md_cg/test_p21_tokens.py +293 -270
  230. package/md_cg/test_p22_theory.py +175 -175
  231. package/md_cg/test_p23_links.py +311 -311
  232. package/md_cg/test_p24_evidence.py +227 -227
  233. package/md_cg/test_p25_weights.py +156 -156
  234. package/md_cg/test_p26_refindex.py +416 -416
  235. package/md_cg/test_p27_docindex.py +765 -765
  236. package/md_cg/test_p28_refcheck.py +305 -305
  237. package/md_cg/test_p29_session_ingest_export.py +354 -333
  238. package/md_cg/test_p3.py +11 -2
  239. package/md_cg/test_p30_maintain.py +330 -330
  240. package/md_cg/test_p31_insight.py +534 -534
  241. package/md_cg/test_p32_backfill.py +298 -298
  242. package/md_cg/test_p33_ccg_wiring.py +293 -293
  243. package/md_cg/test_p34_crosscheck.py +331 -331
  244. package/md_cg/test_p35_conditioned_claim.py +252 -252
  245. package/md_cg/test_p36_kp_align.py +230 -230
  246. package/md_cg/test_p37_condition_space.py +248 -248
  247. package/md_cg/test_p38_concurrent_flush.py +102 -0
  248. package/md_cg/test_p38_contextualize.py +273 -273
  249. package/md_cg/test_p39_verify_flow.py +113 -0
  250. package/md_cg/test_p39_vision_evidence.py +369 -369
  251. package/md_cg/test_p40_refine_worklist.py +241 -241
  252. package/md_cg/test_p41_evolve_patrol.py +224 -224
  253. package/md_cg/test_p42_provenance.py +269 -269
  254. package/md_cg/test_p43_pooling.py +412 -398
  255. package/md_cg/test_p44_md_whitebox.py +231 -231
  256. package/md_cg/test_p45_session_identity.py +219 -219
  257. package/md_cg/test_p46_unit_scope.py +272 -272
  258. package/md_cg/test_p47_session_view.py +281 -0
  259. package/md_cg/test_p4_fuzzy.py +223 -223
  260. package/md_cg/test_p5_semantic.py +226 -226
  261. package/md_cg/test_p6_consolidate.py +440 -387
  262. package/md_cg/test_p7_goals_recent.py +202 -202
  263. package/md_cg/test_p8_subgraph_chain.py +200 -200
  264. package/md_cg/test_p9_forget_protect.py +231 -231
  265. package/md_cg/test_predict_beta.py +135 -135
  266. package/md_cg/test_preflight_failclosed.py +100 -100
  267. package/md_cg/test_progressive.py +146 -146
  268. package/md_cg/test_protocol.py +243 -243
  269. package/md_cg/test_reach.py +378 -378
  270. package/md_cg/test_reach_keys.py +201 -201
  271. package/md_cg/test_read_clip.py +141 -141
  272. package/md_cg/test_readcache_prodpath.py +155 -0
  273. package/md_cg/test_retr_gates_prodpath.py +140 -0
  274. package/md_cg/test_retr_s1.py +340 -340
  275. package/md_cg/test_retr_s1b.py +209 -209
  276. package/md_cg/test_retr_s3.py +194 -194
  277. package/md_cg/test_retr_s4.py +163 -163
  278. package/md_cg/test_retr_s5.py +200 -200
  279. package/md_cg/test_retr_s6.py +157 -157
  280. package/md_cg/test_retr_s7.py +384 -384
  281. package/md_cg/test_retr_s8_time.py +369 -316
  282. package/md_cg/test_retr_s9_edges.py +286 -286
  283. package/md_cg/test_retr_s9_entity_ctx.py +175 -175
  284. package/md_cg/test_review_conformance.py +367 -367
  285. package/md_cg/test_role_views.py +354 -354
  286. package/md_cg/test_sem_noise.py +242 -242
  287. package/md_cg/test_semantic_canonical.py +241 -241
  288. package/md_cg/test_subproc_encoding.py +192 -192
  289. package/md_cg/test_sustain_mutual.py +153 -153
  290. package/md_cg/test_tasks.py +409 -409
  291. package/md_cg/test_tool_face.py +189 -189
  292. package/md_cg/test_transfer.py +180 -180
  293. package/md_cg/test_trust.py +361 -361
  294. package/md_cg/test_twophase.py +286 -286
  295. package/md_cg/test_v14_fixes.py +397 -397
  296. package/md_cg/test_validity_filter.py +280 -280
  297. package/md_cg/test_verify_answer.py +138 -138
  298. package/md_cg/test_wisdom_md_store.py +292 -292
  299. package/md_cg/test_writelimit.py +197 -197
  300. package/md_cg/test_writepipe.py +214 -214
  301. package/md_cg/theory.py +273 -273
  302. package/md_cg/tokens.py +677 -663
  303. package/md_cg/tool_face.py +260 -260
  304. package/md_cg/trust.py +986 -950
  305. package/md_cg/twophase.py +231 -231
  306. package/md_cg/units.py +667 -667
  307. package/md_cg/vision_evidence.py +666 -666
  308. package/md_cg/weights.py +624 -624
  309. package/md_cg/whitebox.py +527 -527
  310. package/md_cg/whitebox_kb/__init__.py +37 -37
  311. package/md_cg/whitebox_kb/aeis_core/__init__.py +42 -42
  312. package/md_cg/whitebox_kb/aeis_core/semantic.py +280 -280
  313. package/md_cg/whitebox_kb/aeis_core/textutil.py +13 -13
  314. package/md_cg/whitebox_kb/engine.py +310 -310
  315. package/md_cg/whitebox_kb/seed_knowledge//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
  316. package/md_cg/whitebox_kb/wisdom/browser_units.py +2631 -2631
  317. package/md_cg/whitebox_kb/wisdom/causal_discover.py +432 -432
  318. package/md_cg/whitebox_kb/wisdom/chat_engine.py +1506 -1506
  319. package/md_cg/whitebox_kb/wisdom/code_solidified.json +6195 -6195
  320. package/md_cg/whitebox_kb/wisdom/compiler_code_units.py +3033 -3033
  321. package/md_cg/whitebox_kb/wisdom/condition_algebra.py +112 -112
  322. package/md_cg/whitebox_kb/wisdom/condition_frame.py +315 -315
  323. package/md_cg/whitebox_kb/wisdom/condition_kb.py +108 -108
  324. package/md_cg/whitebox_kb/wisdom/conflict_map.json +4445 -4445
  325. package/md_cg/whitebox_kb/wisdom/core/lexer.py +512 -512
  326. package/md_cg/whitebox_kb/wisdom/core/name_checker.py +1023 -1023
  327. package/md_cg/whitebox_kb/wisdom/cspmn.py +258 -258
  328. package/md_cg/whitebox_kb/wisdom/csre.py +264 -264
  329. package/md_cg/whitebox_kb/wisdom/danmaku_audit.py +252 -252
  330. package/md_cg/whitebox_kb/wisdom/distilled_condition_units.json +6417 -6417
  331. package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902b.json +1950 -1950
  332. package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902c.json +1296 -1296
  333. package/md_cg/whitebox_kb/wisdom/docs/whitebox_capability_graph_demo.json +59 -59
  334. package/md_cg/whitebox_kb/wisdom/graph_db_units.py +3089 -3089
  335. package/md_cg/whitebox_kb/wisdom/knowledge_points.py +318 -318
  336. package/md_cg/whitebox_kb/wisdom/md_access.py +470 -470
  337. package/md_cg/whitebox_kb/wisdom/md_store.py +276 -251
  338. package/md_cg/whitebox_kb/wisdom/migrate_wisdom.py +476 -476
  339. package/md_cg/whitebox_kb/wisdom/navigate.py +248 -248
  340. package/md_cg/whitebox_kb/wisdom/neural_retrieve.py +224 -224
  341. package/md_cg/whitebox_kb/wisdom/os_units.py +2735 -2735
  342. package/md_cg/whitebox_kb/wisdom/pattern_separation.py +376 -376
  343. package/md_cg/whitebox_kb/wisdom/prereq_map.json +364 -364
  344. package/md_cg/whitebox_kb/wisdom/python_code_units.py +2766 -2766
  345. package/md_cg/whitebox_kb/wisdom/role_solidified.json +7 -7
  346. package/md_cg/whitebox_kb/wisdom/route_memory.py +244 -244
  347. package/md_cg/whitebox_kb/wisdom/scene_reconstruction.py +148 -148
  348. package/md_cg/whitebox_kb/wisdom/snr_report.json +40 -40
  349. package/md_cg/whitebox_kb/wisdom/test_code_compose_domains.py +7541 -7541
  350. package/md_cg/whitebox_kb/wisdom/test_compiler_self_bootstrap.py +354 -354
  351. package/md_cg/whitebox_kb/wisdom/test_ecosystem_assembly.py +158 -158
  352. package/md_cg/whitebox_kb/wisdom/test_ecosystem_demos.py +193 -193
  353. package/md_cg/whitebox_kb/wisdom/test_graph_db.py +292 -292
  354. package/md_cg/whitebox_kb/wisdom/test_python_self_bootstrap.py +160 -160
  355. package/md_cg/whitebox_kb/wisdom/trigger_words_index.json +4366 -4366
  356. package/md_cg/whitebox_kb/wisdom/verifier.py +1297 -1297
  357. package/md_cg/writelimit.py +356 -356
  358. package/md_cg/writepipe.py +550 -542
  359. package/package.json +97 -96
  360. package/skills/plugin.json +54 -54
  361. package/skills/skills/designer-perspective/SKILL.md +158 -158
  362. package/skills/skills/designer-perspective/references/01-observation-position.md +66 -66
  363. package/skills/skills/designer-perspective/references/02-structure-recognition.md +62 -62
  364. package/skills/skills/designer-perspective/references/03-direction-judgment.md +55 -55
  365. package/skills/skills/designer-perspective/references/04-qualification-verdict.md +72 -72
  366. package/skills/skills/designer-perspective/references/05-condition-attribution.md +74 -74
  367. package/skills/skills/designer-perspective/scripts/designer.py +545 -545
  368. package/skills/skills/designer-perspective/tests/cases.jsonl +17 -17
  369. package/skills/skills/designer-perspective/tests/selftest.py +61 -61
  370. package/skills/skills/lingshu-browser/SKILL.md +60 -60
  371. package/skills/skills/lingshu-compiler/SKILL.md +56 -56
  372. package/skills/skills/lingshu-compiler/units/analyze-type-infer/SKILL.md +45 -45
  373. package/skills/skills/lingshu-compiler/units/check-name-real/SKILL.md +45 -45
  374. package/skills/skills/lingshu-compiler/units/compile-assign/SKILL.md +45 -45
  375. package/skills/skills/lingshu-compiler/units/compile-expr-tree/SKILL.md +45 -45
  376. package/skills/skills/lingshu-compiler/units/compile-full-pipeline/SKILL.md +45 -45
  377. package/skills/skills/lingshu-compiler/units/compile-func-def/SKILL.md +45 -45
  378. package/skills/skills/lingshu-compiler/units/compile-if-then/SKILL.md +45 -45
  379. package/skills/skills/lingshu-compiler/units/compile-logic-expr/SKILL.md +45 -45
  380. package/skills/skills/lingshu-compiler/units/compile-recursive/SKILL.md +45 -45
  381. package/skills/skills/lingshu-compiler/units/compile-scope/SKILL.md +45 -45
  382. package/skills/skills/lingshu-compiler/units/compile-type-check/SKILL.md +45 -45
  383. package/skills/skills/lingshu-compiler/units/compile-while/SKILL.md +45 -45
  384. package/skills/skills/lingshu-compiler/units/compiler-0010c4bf/SKILL.md +45 -45
  385. package/skills/skills/lingshu-compiler/units/compiler-0355bffb/SKILL.md +45 -45
  386. package/skills/skills/lingshu-compiler/units/compiler-0361708a/SKILL.md +45 -45
  387. package/skills/skills/lingshu-compiler/units/compiler-054a0414/SKILL.md +45 -45
  388. package/skills/skills/lingshu-compiler/units/compiler-05a1691a/SKILL.md +45 -45
  389. package/skills/skills/lingshu-compiler/units/compiler-05eeed1e/SKILL.md +45 -45
  390. package/skills/skills/lingshu-compiler/units/compiler-0622a1f6/SKILL.md +45 -45
  391. package/skills/skills/lingshu-compiler/units/compiler-08b54217/SKILL.md +45 -45
  392. package/skills/skills/lingshu-compiler/units/compiler-0a62b70c/SKILL.md +45 -45
  393. package/skills/skills/lingshu-compiler/units/compiler-0ab24d00/SKILL.md +45 -45
  394. package/skills/skills/lingshu-compiler/units/compiler-0e093688/SKILL.md +45 -45
  395. package/skills/skills/lingshu-compiler/units/compiler-0e82b966/SKILL.md +45 -45
  396. package/skills/skills/lingshu-compiler/units/compiler-0ee9b9b9/SKILL.md +45 -45
  397. package/skills/skills/lingshu-compiler/units/compiler-0f3787e6/SKILL.md +45 -45
  398. package/skills/skills/lingshu-compiler/units/compiler-1028685f/SKILL.md +45 -45
  399. package/skills/skills/lingshu-compiler/units/compiler-11897630/SKILL.md +45 -45
  400. package/skills/skills/lingshu-compiler/units/compiler-16661b9b/SKILL.md +45 -45
  401. package/skills/skills/lingshu-compiler/units/compiler-1f722303/SKILL.md +45 -45
  402. package/skills/skills/lingshu-compiler/units/compiler-25be1262/SKILL.md +45 -45
  403. package/skills/skills/lingshu-compiler/units/compiler-2a76ba07/SKILL.md +45 -45
  404. package/skills/skills/lingshu-compiler/units/compiler-2dbea54a/SKILL.md +45 -45
  405. package/skills/skills/lingshu-compiler/units/compiler-2df52f16/SKILL.md +45 -45
  406. package/skills/skills/lingshu-compiler/units/compiler-2ec2c9d2/SKILL.md +45 -45
  407. package/skills/skills/lingshu-compiler/units/compiler-2f8c8f39/SKILL.md +45 -45
  408. package/skills/skills/lingshu-compiler/units/compiler-38378ac7/SKILL.md +45 -45
  409. package/skills/skills/lingshu-compiler/units/compiler-39457d2e/SKILL.md +45 -45
  410. package/skills/skills/lingshu-compiler/units/compiler-39fb5926/SKILL.md +45 -45
  411. package/skills/skills/lingshu-compiler/units/compiler-47f4fbfa/SKILL.md +45 -45
  412. package/skills/skills/lingshu-compiler/units/compiler-4a8cd1f1/SKILL.md +45 -45
  413. package/skills/skills/lingshu-compiler/units/compiler-4b230b6b/SKILL.md +45 -45
  414. package/skills/skills/lingshu-compiler/units/compiler-4cbbda95/SKILL.md +45 -45
  415. package/skills/skills/lingshu-compiler/units/compiler-4d5a68ff/SKILL.md +45 -45
  416. package/skills/skills/lingshu-compiler/units/compiler-56dc9bdd/SKILL.md +45 -45
  417. package/skills/skills/lingshu-compiler/units/compiler-57e76ebe/SKILL.md +45 -45
  418. package/skills/skills/lingshu-compiler/units/compiler-61ff016b/SKILL.md +45 -45
  419. package/skills/skills/lingshu-compiler/units/compiler-63eae588/SKILL.md +45 -45
  420. package/skills/skills/lingshu-compiler/units/compiler-64c4224b/SKILL.md +45 -45
  421. package/skills/skills/lingshu-compiler/units/compiler-66377955/SKILL.md +45 -45
  422. package/skills/skills/lingshu-compiler/units/compiler-674ab4f6/SKILL.md +45 -45
  423. package/skills/skills/lingshu-compiler/units/compiler-6af76fd6/SKILL.md +45 -45
  424. package/skills/skills/lingshu-compiler/units/compiler-6d979db2/SKILL.md +45 -45
  425. package/skills/skills/lingshu-compiler/units/compiler-6de326c0/SKILL.md +45 -45
  426. package/skills/skills/lingshu-compiler/units/compiler-6f1c0eea/SKILL.md +45 -45
  427. package/skills/skills/lingshu-compiler/units/compiler-724d6c9b/SKILL.md +45 -45
  428. package/skills/skills/lingshu-compiler/units/compiler-7690177f/SKILL.md +45 -45
  429. package/skills/skills/lingshu-compiler/units/compiler-7b229a7d/SKILL.md +45 -45
  430. package/skills/skills/lingshu-compiler/units/compiler-7f471b3a/SKILL.md +45 -45
  431. package/skills/skills/lingshu-compiler/units/compiler-815cad08/SKILL.md +45 -45
  432. package/skills/skills/lingshu-compiler/units/compiler-83c61634/SKILL.md +45 -45
  433. package/skills/skills/lingshu-compiler/units/compiler-8c798c81/SKILL.md +45 -45
  434. package/skills/skills/lingshu-compiler/units/compiler-8dd747ac/SKILL.md +45 -45
  435. package/skills/skills/lingshu-compiler/units/compiler-90324d0a/SKILL.md +45 -45
  436. package/skills/skills/lingshu-compiler/units/compiler-94b8d72d/SKILL.md +45 -45
  437. package/skills/skills/lingshu-compiler/units/compiler-94f12231/SKILL.md +45 -45
  438. package/skills/skills/lingshu-compiler/units/compiler-95937c16/SKILL.md +45 -45
  439. package/skills/skills/lingshu-compiler/units/compiler-98a5625b/SKILL.md +45 -45
  440. package/skills/skills/lingshu-compiler/units/compiler-98b4c42f/SKILL.md +45 -45
  441. package/skills/skills/lingshu-compiler/units/compiler-98e3894a/SKILL.md +45 -45
  442. package/skills/skills/lingshu-compiler/units/compiler-9bdfe4b8/SKILL.md +45 -45
  443. package/skills/skills/lingshu-compiler/units/compiler-9d9b4e83/SKILL.md +45 -45
  444. package/skills/skills/lingshu-compiler/units/compiler-9f7be5ad/SKILL.md +45 -45
  445. package/skills/skills/lingshu-compiler/units/compiler-a6daf076/SKILL.md +45 -45
  446. package/skills/skills/lingshu-compiler/units/compiler-a7995a0c/SKILL.md +45 -45
  447. package/skills/skills/lingshu-compiler/units/compiler-a8399248/SKILL.md +45 -45
  448. package/skills/skills/lingshu-compiler/units/compiler-aabbd099/SKILL.md +45 -45
  449. package/skills/skills/lingshu-compiler/units/compiler-afe169d8/SKILL.md +45 -45
  450. package/skills/skills/lingshu-compiler/units/compiler-b0678bda/SKILL.md +45 -45
  451. package/skills/skills/lingshu-compiler/units/compiler-b09bd196/SKILL.md +45 -45
  452. package/skills/skills/lingshu-compiler/units/compiler-b1396e23/SKILL.md +45 -45
  453. package/skills/skills/lingshu-compiler/units/compiler-b9b31ce0/SKILL.md +45 -45
  454. package/skills/skills/lingshu-compiler/units/compiler-c10264a7/SKILL.md +45 -45
  455. package/skills/skills/lingshu-compiler/units/compiler-cb1e8e4b/SKILL.md +45 -45
  456. package/skills/skills/lingshu-compiler/units/compiler-ccafd438/SKILL.md +45 -45
  457. package/skills/skills/lingshu-compiler/units/compiler-cda9c262/SKILL.md +45 -45
  458. package/skills/skills/lingshu-compiler/units/compiler-ce648068/SKILL.md +45 -45
  459. package/skills/skills/lingshu-compiler/units/compiler-cf5776a4/SKILL.md +45 -45
  460. package/skills/skills/lingshu-compiler/units/compiler-d974e5d3/SKILL.md +45 -45
  461. package/skills/skills/lingshu-compiler/units/compiler-e3979fd3/SKILL.md +45 -45
  462. package/skills/skills/lingshu-compiler/units/compiler-eb1cf2b5/SKILL.md +45 -45
  463. package/skills/skills/lingshu-compiler/units/compiler-ecb30d5b/SKILL.md +45 -45
  464. package/skills/skills/lingshu-compiler/units/compiler-f8c8b24b/SKILL.md +45 -45
  465. package/skills/skills/lingshu-compiler/units/compiler-f99fedbe/SKILL.md +45 -45
  466. package/skills/skills/lingshu-compiler/units/compiler-fa8ff5f7/SKILL.md +45 -45
  467. package/skills/skills/lingshu-compiler/units/compiler-fe1b058d/SKILL.md +45 -45
  468. package/skills/skills/lingshu-compiler/units/lex-chinese-program/SKILL.md +45 -45
  469. package/skills/skills/lingshu-compiler/units/lex-dao-de-jing/SKILL.md +45 -45
  470. package/skills/skills/lingshu-compiler/units/lex-nine-chapters/SKILL.md +45 -45
  471. package/skills/skills/lingshu-compiler/units/vm-arithmetic/SKILL.md +45 -45
  472. package/skills/skills/lingshu-compiler/units/vm-array-ops/SKILL.md +45 -45
  473. package/skills/skills/lingshu-compiler/units/vm-closure-call/SKILL.md +45 -45
  474. package/skills/skills/lingshu-compiler/units/vm-closure-create/SKILL.md +45 -45
  475. package/skills/skills/lingshu-compiler/units/vm-compare/SKILL.md +45 -45
  476. package/skills/skills/lingshu-compiler/units/vm-cond-jump/SKILL.md +45 -45
  477. package/skills/skills/lingshu-compiler/units/vm-cond-space/SKILL.md +45 -45
  478. package/skills/skills/lingshu-compiler/units/vm-exception/SKILL.md +45 -45
  479. package/skills/skills/lingshu-compiler/units/vm-func-call/SKILL.md +45 -45
  480. package/skills/skills/lingshu-compiler/units/vm-loop-run/SKILL.md +45 -45
  481. package/skills/skills/lingshu-compiler/units/vm-profiling/SKILL.md +45 -45
  482. package/skills/skills/lingshu-compiler/units/vm-refcount/SKILL.md +45 -45
  483. package/skills/skills/lingshu-compiler/units/vm-run-loop/SKILL.md +45 -45
  484. package/skills/skills/lingshu-compiler/units/vm-short-circuit/SKILL.md +45 -45
  485. package/skills/skills/lingshu-compiler/units/vm-stack-guard/SKILL.md +45 -45
  486. package/skills/skills/lingshu-compiler/units/vm-stack-ops/SKILL.md +45 -45
  487. package/skills/skills/lingshu-compiler/units/vm-trust-accum/SKILL.md +45 -45
  488. package/skills/skills/lingshu-graph/SKILL.md +63 -63
  489. package/skills/skills/lingshu-net/SKILL.md +48 -48
  490. package/skills/skills/lingshu-os/SKILL.md +64 -64
  491. package/skills/skills/lingshu-pylang/SKILL.md +71 -71
  492. package/src/bridge.ts +401 -401
  493. package/src/hooks.ts +38 -2
  494. package/src/lib/datapath.ts +326 -326
  495. package/src/lib/mdcg_client.ts +413 -413
  496. package/src/lib/mutual.ts +428 -428
  497. package/src/lib/prompt_safety.ts +62 -62
  498. package/src/lib/python_path.ts +71 -71
  499. package/src/lib/roleplay_web.ts +932 -932
  500. package/src/lib/token_store.ts +192 -192
  501. package/src/tools.ts +212 -212
  502. package/zcode/AGENTS.md +11 -3
  503. package/zcode/README.md +41 -41
  504. /package/docs/{mdcg → hive}//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" +0 -0
@@ -1,361 +1,361 @@
1
- # -*- coding: utf-8 -*-
2
- """md_cg · 白箱知识图 → md 原生图导出(对照实验)
3
-
4
- 目的:回答「图查询是否必须依赖 db?md 文档 + frontmatter 引用能否承载?」
5
- 白箱 `whitebox_kb/wisdom/wisdom-book-cloud.db`:nodes 4355 / edges 2948
6
- (hierarchical 2832 · similar 71 · causal 45)。本模块把这张图原样导出为
7
- md 认知图,再做**确定性**等价校验(不调 LLM、不依赖概率指标)。
8
-
9
- 映射(两个既有方向缺陷都在此绕开)
10
- ----------------------------------
11
- 1) 白箱 `hierarchical` 实测是 source(父) → target(子)(2832/2832 与
12
- `nodes.state_attributes.parent_card` 对齐),而 md_cg `subgraph.declared()`
13
- 把 hierarchical 当 `part_of`(本节点是子)——口径相反,直接导会树倒置。
14
- 2) `subgraph.parents_index` 对 `part_of` 的处理与 `children_index` 相反
15
- (前者把 part_of 与 contains 并进同一分支),用 part_of 边会让
16
- `parent_of` / `roots()` / 溯源全算错(实测 PARENT_OF_C2=None)。
17
-
18
- 故本导出器**只用「父节点声明 subgraph.nodes」表达层级**——该分支在
19
- children_index 与 parents_index 中解释一致且可逆。非层级边原样落到
20
- `frontmatter.edges`,键名用 `relation_type`(subgraph/chain 只认
21
- relation_type/relation,写 `type` 会静默丢边,`migrate_aeis` 即踩此坑)。
22
-
23
- 用法
24
- ----
25
- python -m md_cg.migrate_wisdom_graph --db <sqlite> --root <md_root> [选项]
26
- --limit N | --dry-run | --verify-only
27
- """
28
- from __future__ import annotations
29
-
30
- import collections
31
- import json
32
- import os
33
- import sqlite3
34
- import sys
35
- import time
36
-
37
- from .mdcos import MdCGOS
38
-
39
- LEVEL_REL = "hierarchical" # 白箱层级关系(source=父,target=子)
40
- EXPORT_LAYER = "knowledge" # 白箱 nodes.layer 实测全为 knowledge
41
- _HERE = os.path.dirname(os.path.abspath(__file__))
42
- DEFAULT_DB = os.path.join(_HERE, "whitebox_kb", "wisdom", "wisdom-book-cloud.db")
43
- DEFAULT_ROOT = os.path.join(os.path.dirname(_HERE), "_md_cg_wisdom_graph")
44
-
45
-
46
- # 生效条件:s 为假值(None/""/0 等)时返回 s or ""(None→""、0→""),否则返回把 "\r\n"、"\r" 依次替换为 "\n" 的字符串。
47
- def _norm_text(s):
48
- """统一换行:md 按 LF 存,源库常含 CRLF,不规范化会造成假失败。"""
49
- if not s:
50
- return s or ""
51
- return s.replace("\r\n", "\n").replace("\r", "\n")
52
-
53
-
54
- # 生效条件:v 为 None 或等于 "" 时返回 default;v 是 dict 或 list 时原样返回 v;否则 json.loads(v),遇 ValueError/TypeError 时返回 default。
55
- def _j(v, default):
56
- if v is None or v == "":
57
- return default
58
- if isinstance(v, (dict, list)):
59
- return v
60
- try:
61
- return json.loads(v)
62
- except (ValueError, TypeError):
63
- return default
64
-
65
-
66
- # 生效条件:float(v) 成功时返回该浮点值(含 v="" 之外的数值串),抛 TypeError/ValueError 时返回 default,default 缺省为 0.0。
67
- def _f(v, default=0.0):
68
- try:
69
- return float(v)
70
- except (TypeError, ValueError):
71
- return default
72
-
73
-
74
- # 生效条件:任何传入的 db 都拼成 f"file:{db}?mode=ro" 并 uri=True 返回 sqlite3.connect 的连接(源码未对 db 做存在性或类型校验)。
75
- def _connect(db):
76
- return sqlite3.connect(f"file:{db}?mode=ro", uri=True)
77
-
78
-
79
- # 生效条件:db 经 _connect 只读打开,limit 为真值(非 None/0/"")时 SQL 追加 f" LIMIT {int(limit)}",limit 为假值时无 LIMIT、返回按 created_at 排序的全部 nodes 字典列表。
80
- def load_nodes(db, limit=None):
81
- con = _connect(db)
82
- con.row_factory = sqlite3.Row
83
- sql = "SELECT * FROM nodes ORDER BY created_at"
84
- if limit:
85
- sql += f" LIMIT {int(limit)}"
86
- rows = [dict(r) for r in con.execute(sql)]
87
- con.close()
88
- return rows
89
-
90
-
91
- # 生效条件:db 只读打开后逐条 edges 按 rel=(relation_type or "").strip() 分派——等于 LEVEL_REL 的记入 children[source_id],其余记入 relations[source_id] 的边字典(target、relation_type、confidence=_f(conf,0.7)、verified=int(ver or 0),且仅当 _j(cs,None) 为真值时加 condition_space、仅当 weight 不为 None 时加 weight=_f(weight,1.0)),返回 (children, relations)。
92
- def load_graph(db):
93
- """返回 (children_of, relations_of)。
94
-
95
- children_of: {父 id: [子 id...]} —— hierarchical(source=父)
96
- relations_of: {源 id: [边字典...]} —— similar / causal 等非层级边
97
- """
98
- con = _connect(db)
99
- children, relations = collections.defaultdict(list), collections.defaultdict(list)
100
- for src, tgt, rel, cs, conf, weight, ver in con.execute(
101
- "SELECT source_id, target_id, relation_type, condition_space, "
102
- "confidence, weight, verified FROM edges"):
103
- src, tgt = str(src), str(tgt)
104
- rel = (rel or "").strip()
105
- if rel == LEVEL_REL:
106
- children[src].append(tgt)
107
- continue
108
- e = {"target": tgt, "relation_type": rel,
109
- "confidence": _f(conf, 0.7), "verified": int(ver or 0)}
110
- cs_j = _j(cs, None)
111
- if cs_j:
112
- e["condition_space"] = cs_j
113
- if weight is not None:
114
- e["weight"] = _f(weight, 1.0)
115
- relations[src].append(e)
116
- con.close()
117
- return children, relations
118
-
119
-
120
- # --------------------------------------------------------------------------
121
- # 写:sqlite → md
122
- # --------------------------------------------------------------------------
123
-
124
- # 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传);dry_run 为真值时不做写入,rep 只有统计字段而无 verify/ok;dry_run 为假值时以 MdCGOS(root) 把 load_nodes(db, limit)(limit 真值才加 LIMIT)的节点按 id 覆盖写入,并令 rep["verify"]=verify(db, root, verbose=verbose)、rep["ok"]=bool(rep["verify"]["ok"]);verbose 为真值时打印 rep。
125
- def export(db=DEFAULT_DB, root=DEFAULT_ROOT, limit=None, dry_run=False,
126
- verbose=True):
127
- rows = load_nodes(db, limit)
128
- children, relations = load_graph(db)
129
- ids = {r["id"] for r in rows}
130
- name = os.path.basename(db)
131
- # 只保留两端都存在的边:悬空子会让 validate 报 dangling_child。
132
- # 预先算好(dry-run 也要如实统计),循环内直接取用。
133
- kids_map = {nid: [c for c in children.get(nid, []) if c in ids] for nid in ids}
134
- rels_map = {nid: [e for e in relations.get(nid, []) if e["target"] in ids]
135
- for nid in ids}
136
- n_edges_kept = sum(len(v) for v in kids_map.values())
137
- n_dangling = sum(len(children.get(nid, [])) for nid in ids) - n_edges_kept
138
-
139
- if not dry_run:
140
- cg = MdCGOS(root, actor="migrate-wisdom", autoflush=500)
141
- t0 = time.time()
142
- for i, r in enumerate(rows, 1):
143
- nid = r["id"]
144
- kids, rels = kids_map[nid], rels_map[nid]
145
- kw = {"subgraph": {"nodes": kids}} if kids else {}
146
- cg.add(
147
- nid, _norm_text(r.get("content") or ""),
148
- layer=EXPORT_LAYER,
149
- override=True, # 整库受控写入:按 id 幂等覆盖
150
- tags=_j(r.get("tags"), []),
151
- condition_space=_j(r.get("condition_space"), {}),
152
- importance=_f(r.get("importance"), 0.5),
153
- confidence=_f(r.get("confidence"), 0.6),
154
- edges=rels,
155
- created_at=_f(r.get("created_at"), 0),
156
- modality=r.get("modality") or "text",
157
- semantic_coordinates=_j(r.get("semantic_coordinates"), {}),
158
- state_attributes=_j(r.get("state_attributes"), {}),
159
- entity_id=r.get("entity_id"),
160
- access_count=int(r.get("access_count") or 0),
161
- last_access=_f(r.get("last_access"), 0),
162
- verification_basis="data",
163
- # legacy 标记:白箱正文非 CCG 五要素形态,资格判定据此判 DEFER
164
- # (可检索、待补条件)而非 BLINDSPOT。
165
- ccg_exempt=True,
166
- migrated_from=name,
167
- **kw)
168
- if verbose and i % 1000 == 0:
169
- print(f" …已写入 {i}/{len(rows)}({time.time()-t0:.0f}s)", flush=True)
170
- cg.flush()
171
- cg.rebuild_index() # 落 subgraph/edges 进索引快照,供图遍历免读盘
172
- cg.close()
173
-
174
- rep = {"db": db, "root": root, "dry_run": dry_run,
175
- "sqlite_nodes": len(rows), "hier_edges_kept": n_edges_kept,
176
- "dangling_children": n_dangling,
177
- "rel_edges_kept": sum(len(v) for v in rels_map.values())}
178
- if not dry_run:
179
- rep["verify"] = verify(db, root, verbose=verbose)
180
- rep["ok"] = bool(rep["verify"]["ok"])
181
- if verbose:
182
- print(json.dumps(rep, ensure_ascii=False, indent=2), flush=True)
183
- return rep
184
-
185
-
186
- # --------------------------------------------------------------------------
187
- # 校验:md 侧 vs sqlite 侧(逐节点全量,不抽样)
188
- # --------------------------------------------------------------------------
189
-
190
- # 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传),在 md_ids 与 load_nodes(db) 的交集上做 L1 子/父集合比对、L2 非层级边 target 集合比对、L3 字段比对(condition_space 经 _cs_same 剔除 time_window)后,out["ok"] 仅当无缺失节点、无 child_bad/parent_bad/rel_bad/field_bad、roots_equal 为真且 sg.validate(cg, limit=5) 的 issues==0;verbose 为真值时打印去掉 tree_validate 键的 out。
191
- def verify(db=DEFAULT_DB, root=DEFAULT_ROOT, verbose=True):
192
- from . import subgraph as sg
193
-
194
- cg = MdCGOS(root)
195
- md_ids = set(cg.index["nodes"])
196
- children_db, relations_db = load_graph(db)
197
- nodes_db = {r["id"]: r for r in load_nodes(db)}
198
- ids = md_ids & set(nodes_db)
199
-
200
- # ---- L1 结构等价:子集合 / 父节点 / 树根 ----
201
- child_bad, parent_bad = [], []
202
- md_children, md_parents = {}, {}
203
- for nid in ids:
204
- want_ch = {c for c in children_db.get(nid, []) if c in md_ids}
205
- got_ch = set(sg.children(cg, nid))
206
- md_children[nid] = got_ch
207
- if want_ch != got_ch:
208
- child_bad.append({"id": nid, "db": sorted(want_ch), "md": sorted(got_ch)})
209
- # 反查父:db 侧由 hierarchical 边推出(白箱父边唯一)
210
- want_p = {p for p, cs in children_db.items() if nid in cs and p in md_ids}
211
- got_p = set(sg.parents_index(cg).get(nid) or [])
212
- md_parents[nid] = got_p
213
- if want_p != got_p:
214
- parent_bad.append({"id": nid, "db": sorted(want_p), "md": sorted(got_p)})
215
-
216
- roots_db = sorted(nid for nid in ids if not (md_parents[nid] or []))
217
- roots_md = sorted(set(sg.roots(cg)) & ids)
218
-
219
- # ---- L2 关系等价:非层级边 target 集合 ----
220
- rel_bad = []
221
- for nid in ids:
222
- want = sorted({e["target"] for e in relations_db.get(nid, []) if e["target"] in md_ids})
223
- fm = cg.get(nid)["frontmatter"]
224
- got = sorted({str(e.get("target")) for e in (fm.get("edges") or [])
225
- if isinstance(e, dict) and e.get("target")})
226
- if want != got:
227
- rel_bad.append({"id": nid, "db": want, "md": got})
228
-
229
- # ---- L3 字段等价 ----
230
- # 生效条件:a、b 各自经 _j(a, {}) or {} 转成字典(None/"" 得空 dict)后 pop("time_window"),仅当剔除该槽后的两字典相等才返回 True,否则 False。
231
- def _cs_same(a, b):
232
- """md 写入侧按条件论纪律自动补 time_window(`mdcg.add` 的观测时间窗),
233
- 比对时剔除该槽——它是有意增强,不是迁移失真。"""
234
- a, b = dict(_j(a, {}) or {}), dict(_j(b, {}) or {})
235
- a.pop("time_window", None)
236
- b.pop("time_window", None)
237
- return a == b
238
-
239
- field_bad, tw_added = [], 0
240
- for nid in ids:
241
- fm = cg.get(nid)["frontmatter"]
242
- r = nodes_db[nid]
243
- if "time_window" not in _j(r.get("condition_space"), {}):
244
- tw_added += 1
245
- checks = (
246
- ("condition_space", not _cs_same(fm.get("condition_space"), r.get("condition_space"))),
247
- ("tags", _j(fm.get("tags"), []) != _j(r.get("tags"), [])),
248
- ("importance", abs(_f(fm.get("importance")) - _f(r.get("importance"))) > 1e-9),
249
- ("confidence", abs(_f(fm.get("confidence")) - _f(r.get("confidence"))) > 1e-9),
250
- ("modality", (fm.get("modality") or "text") != (r.get("modality") or "text")),
251
- )
252
- for name, bad in checks:
253
- if bad:
254
- field_bad.append({"id": nid, "field": name})
255
- break
256
-
257
- out = {
258
- "db": db, "root": root,
259
- "nodes": {"db": len(nodes_db), "md": len(md_ids),
260
- "missing": sorted(set(nodes_db) - md_ids)[:5],
261
- "n_missing": len(set(nodes_db) - md_ids)},
262
- "L1_hierarchy": {
263
- "md_edges": sum(len(v) for v in md_children.values()),
264
- "child_mismatch": len(child_bad), "parent_mismatch": len(parent_bad),
265
- "samples": (child_bad[:3] + parent_bad[:3]),
266
- "roots_db": len(roots_db), "roots_md": len(roots_md),
267
- "roots_equal": roots_db == roots_md,
268
- },
269
- "L2_relations": {"mismatch": len(rel_bad), "samples": rel_bad[:3]},
270
- "L3_fields": {"mismatch": len(field_bad), "samples": field_bad[:3],
271
- "time_window_added_by_discipline": tw_added},
272
- "tree_validate": sg.validate(cg, limit=5),
273
- }
274
- out["ok"] = (not out["nodes"]["n_missing"] and not child_bad and not parent_bad
275
- and not rel_bad and not field_bad and out["L1_hierarchy"]["roots_equal"]
276
- and out["tree_validate"]["issues"] == 0)
277
- cg.close()
278
- if verbose:
279
- print(json.dumps({k: v for k, v in out.items() if k != "tree_validate"},
280
- ensure_ascii=False, indent=2), flush=True)
281
- return out
282
-
283
-
284
- REC_SUBTREE_SQL = (
285
- "WITH RECURSIVE sub(id) AS (SELECT ? "
286
- "UNION SELECT e.target_id FROM edges e JOIN sub s ON e.source_id = s.id "
287
- "WHERE e.relation_type = ?) SELECT id FROM sub")
288
-
289
-
290
- # 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传),仅遍历 sg.roots(cg)∩md_ids 的前 n_roots 个根(n_roots 为 0 时切片为空、不做子树比对),每根比对 db 递归 CTE 子树与 sg.flatten(cg, nid, max_nodes=10**9) 的 nodes,out["ok"] 仅当该样本无失配且 forest_partition_ok(n_db==n_md==len(md_ids))成立;verbose 为真值时打印 out。
291
- def bench_graph(db=DEFAULT_DB, root=DEFAULT_ROOT, n_roots=30, verbose=True):
292
- """L4 子树展开等价 + 森林完整性(回答「图**查询**能否由 md 承担」)。
293
-
294
- L1 已证逐节点邻接等价,递归展开原则上同构;此处**实测**以覆盖
295
- `subgraph.flatten` 自身的 max_depth / max_nodes 截断与环处理。
296
- db 侧递归 CTE,md 侧 flatten,两侧都在同一份 md 节点集上取交集比对。
297
-
298
- 森林完整性是一条强校验:白箱父边唯一 ⇒ 各根子树互不相交且并集 = 全图。
299
- 有环 / 漏边 / 多父,都会让两侧节点和立刻不一致。
300
- """
301
- from . import subgraph as sg
302
-
303
- cg = MdCGOS(root)
304
- md_ids = set(cg.index["nodes"])
305
- con = _connect(db)
306
- roots_md = sorted(set(sg.roots(cg)) & md_ids)
307
-
308
- # 生效条件:用外层闭包的 con 执行 REC_SUBTREE_SQL、参数为 (nid, LEVEL_REL),返回结果各行第 0 列构成的集合。
309
- def _db_subtree(nid):
310
- return {r[0] for r in con.execute(REC_SUBTREE_SQL, (nid, LEVEL_REL)).fetchall()}
311
-
312
- bad = []
313
- for nid in roots_md[:n_roots]:
314
- want = _db_subtree(nid) & md_ids
315
- got = set(sg.flatten(cg, nid, max_nodes=10 ** 9)["nodes"])
316
- if want != got:
317
- bad.append({"root": nid, "db_n": len(want), "md_n": len(got),
318
- "only_db": sorted(want - got)[:3],
319
- "only_md": sorted(got - want)[:3]})
320
-
321
- n_db = sum(len(_db_subtree(nid) & md_ids) for nid in roots_md)
322
- n_md = sum(sg.flatten(cg, nid, max_nodes=10 ** 9)["n_nodes"] for nid in roots_md)
323
- con.close()
324
- cg.close()
325
-
326
- out = {"roots": len(roots_md), "roots_sampled": min(n_roots, len(roots_md)),
327
- "subtree_mismatch": len(bad), "samples": bad[:3],
328
- "forest_nodes_db": n_db, "forest_nodes_md": n_md,
329
- "total_nodes": len(md_ids),
330
- "forest_partition_ok": n_db == n_md == len(md_ids)}
331
- out["ok"] = (not bad) and out["forest_partition_ok"]
332
- if verbose:
333
- print(json.dumps(out, ensure_ascii=False, indent=2), flush=True)
334
- return out
335
-
336
-
337
- # 生效条件:argv 含 "--verify-only" 时返回 0/1 取决于 verify(db, root)["ok"],含 "--bench-graph" 时返回 0/1 取决于 bench_graph(db, root)["ok"],否则以 opt 取的 --db/--root/--limit 调 export(opt("--limit") 缺失或为空串时 limit=None,否则 int(lim);dry_run="--dry-run" in argv),rep.get("dry_run") 为真时直接返回 0,否则按 rep.get("ok") 真→0、假→1。
338
- def main(argv):
339
- if hasattr(sys.stdout, "reconfigure"):
340
- sys.stdout.reconfigure(encoding="utf-8")
341
-
342
- # 生效条件:name 出现在外层 argv 中时返回 argv[argv.index(name) + 1](即首次出现位置的后一个元素),name 不在 argv 中时返回 default,default 缺省为 None。
343
- def opt(name, default=None):
344
- return argv[argv.index(name) + 1] if name in argv else default
345
-
346
- db = opt("--db", DEFAULT_DB)
347
- root = opt("--root", DEFAULT_ROOT)
348
- if "--verify-only" in argv:
349
- return 0 if verify(db, root)["ok"] else 1
350
- if "--bench-graph" in argv:
351
- return 0 if bench_graph(db, root)["ok"] else 1
352
- lim = opt("--limit")
353
- rep = export(db=db, root=root, limit=int(lim) if lim else None,
354
- dry_run="--dry-run" in argv)
355
- if rep.get("dry_run"):
356
- return 0
357
- return 0 if rep.get("ok") else 1
358
-
359
-
360
- if __name__ == "__main__":
1
+ # -*- coding: utf-8 -*-
2
+ """md_cg · 白箱知识图 → md 原生图导出(对照实验)
3
+
4
+ 目的:回答「图查询是否必须依赖 db?md 文档 + frontmatter 引用能否承载?」
5
+ 白箱 `whitebox_kb/wisdom/wisdom-book-cloud.db`:nodes 4355 / edges 2948
6
+ (hierarchical 2832 · similar 71 · causal 45)。本模块把这张图原样导出为
7
+ md 认知图,再做**确定性**等价校验(不调 LLM、不依赖概率指标)。
8
+
9
+ 映射(两个既有方向缺陷都在此绕开)
10
+ ----------------------------------
11
+ 1) 白箱 `hierarchical` 实测是 source(父) → target(子)(2832/2832 与
12
+ `nodes.state_attributes.parent_card` 对齐),而 md_cg `subgraph.declared()`
13
+ 把 hierarchical 当 `part_of`(本节点是子)——口径相反,直接导会树倒置。
14
+ 2) `subgraph.parents_index` 对 `part_of` 的处理与 `children_index` 相反
15
+ (前者把 part_of 与 contains 并进同一分支),用 part_of 边会让
16
+ `parent_of` / `roots()` / 溯源全算错(实测 PARENT_OF_C2=None)。
17
+
18
+ 故本导出器**只用「父节点声明 subgraph.nodes」表达层级**——该分支在
19
+ children_index 与 parents_index 中解释一致且可逆。非层级边原样落到
20
+ `frontmatter.edges`,键名用 `relation_type`(subgraph/chain 只认
21
+ relation_type/relation,写 `type` 会静默丢边,`migrate_aeis` 即踩此坑)。
22
+
23
+ 用法
24
+ ----
25
+ python -m md_cg.migrate_wisdom_graph --db <sqlite> --root <md_root> [选项]
26
+ --limit N | --dry-run | --verify-only
27
+ """
28
+ from __future__ import annotations
29
+
30
+ import collections
31
+ import json
32
+ import os
33
+ import sqlite3
34
+ import sys
35
+ import time
36
+
37
+ from .mdcos import MdCGOS
38
+
39
+ LEVEL_REL = "hierarchical" # 白箱层级关系(source=父,target=子)
40
+ EXPORT_LAYER = "knowledge" # 白箱 nodes.layer 实测全为 knowledge
41
+ _HERE = os.path.dirname(os.path.abspath(__file__))
42
+ DEFAULT_DB = os.path.join(_HERE, "whitebox_kb", "wisdom", "wisdom-book-cloud.db")
43
+ DEFAULT_ROOT = os.path.join(os.path.dirname(_HERE), "_md_cg_wisdom_graph")
44
+
45
+
46
+ # 生效条件:s 为假值(None/""/0 等)时返回 s or ""(None→""、0→""),否则返回把 "\r\n"、"\r" 依次替换为 "\n" 的字符串。
47
+ def _norm_text(s):
48
+ """统一换行:md 按 LF 存,源库常含 CRLF,不规范化会造成假失败。"""
49
+ if not s:
50
+ return s or ""
51
+ return s.replace("\r\n", "\n").replace("\r", "\n")
52
+
53
+
54
+ # 生效条件:v 为 None 或等于 "" 时返回 default;v 是 dict 或 list 时原样返回 v;否则 json.loads(v),遇 ValueError/TypeError 时返回 default。
55
+ def _j(v, default):
56
+ if v is None or v == "":
57
+ return default
58
+ if isinstance(v, (dict, list)):
59
+ return v
60
+ try:
61
+ return json.loads(v)
62
+ except (ValueError, TypeError):
63
+ return default
64
+
65
+
66
+ # 生效条件:float(v) 成功时返回该浮点值(含 v="" 之外的数值串),抛 TypeError/ValueError 时返回 default,default 缺省为 0.0。
67
+ def _f(v, default=0.0):
68
+ try:
69
+ return float(v)
70
+ except (TypeError, ValueError):
71
+ return default
72
+
73
+
74
+ # 生效条件:任何传入的 db 都拼成 f"file:{db}?mode=ro" 并 uri=True 返回 sqlite3.connect 的连接(源码未对 db 做存在性或类型校验)。
75
+ def _connect(db):
76
+ return sqlite3.connect(f"file:{db}?mode=ro", uri=True)
77
+
78
+
79
+ # 生效条件:db 经 _connect 只读打开,limit 为真值(非 None/0/"")时 SQL 追加 f" LIMIT {int(limit)}",limit 为假值时无 LIMIT、返回按 created_at 排序的全部 nodes 字典列表。
80
+ def load_nodes(db, limit=None):
81
+ con = _connect(db)
82
+ con.row_factory = sqlite3.Row
83
+ sql = "SELECT * FROM nodes ORDER BY created_at"
84
+ if limit:
85
+ sql += f" LIMIT {int(limit)}"
86
+ rows = [dict(r) for r in con.execute(sql)]
87
+ con.close()
88
+ return rows
89
+
90
+
91
+ # 生效条件:db 只读打开后逐条 edges 按 rel=(relation_type or "").strip() 分派——等于 LEVEL_REL 的记入 children[source_id],其余记入 relations[source_id] 的边字典(target、relation_type、confidence=_f(conf,0.7)、verified=int(ver or 0),且仅当 _j(cs,None) 为真值时加 condition_space、仅当 weight 不为 None 时加 weight=_f(weight,1.0)),返回 (children, relations)。
92
+ def load_graph(db):
93
+ """返回 (children_of, relations_of)。
94
+
95
+ children_of: {父 id: [子 id...]} —— hierarchical(source=父)
96
+ relations_of: {源 id: [边字典...]} —— similar / causal 等非层级边
97
+ """
98
+ con = _connect(db)
99
+ children, relations = collections.defaultdict(list), collections.defaultdict(list)
100
+ for src, tgt, rel, cs, conf, weight, ver in con.execute(
101
+ "SELECT source_id, target_id, relation_type, condition_space, "
102
+ "confidence, weight, verified FROM edges"):
103
+ src, tgt = str(src), str(tgt)
104
+ rel = (rel or "").strip()
105
+ if rel == LEVEL_REL:
106
+ children[src].append(tgt)
107
+ continue
108
+ e = {"target": tgt, "relation_type": rel,
109
+ "confidence": _f(conf, 0.7), "verified": int(ver or 0)}
110
+ cs_j = _j(cs, None)
111
+ if cs_j:
112
+ e["condition_space"] = cs_j
113
+ if weight is not None:
114
+ e["weight"] = _f(weight, 1.0)
115
+ relations[src].append(e)
116
+ con.close()
117
+ return children, relations
118
+
119
+
120
+ # --------------------------------------------------------------------------
121
+ # 写:sqlite → md
122
+ # --------------------------------------------------------------------------
123
+
124
+ # 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传);dry_run 为真值时不做写入,rep 只有统计字段而无 verify/ok;dry_run 为假值时以 MdCGOS(root) 把 load_nodes(db, limit)(limit 真值才加 LIMIT)的节点按 id 覆盖写入,并令 rep["verify"]=verify(db, root, verbose=verbose)、rep["ok"]=bool(rep["verify"]["ok"]);verbose 为真值时打印 rep。
125
+ def export(db=DEFAULT_DB, root=DEFAULT_ROOT, limit=None, dry_run=False,
126
+ verbose=True):
127
+ rows = load_nodes(db, limit)
128
+ children, relations = load_graph(db)
129
+ ids = {r["id"] for r in rows}
130
+ name = os.path.basename(db)
131
+ # 只保留两端都存在的边:悬空子会让 validate 报 dangling_child。
132
+ # 预先算好(dry-run 也要如实统计),循环内直接取用。
133
+ kids_map = {nid: [c for c in children.get(nid, []) if c in ids] for nid in ids}
134
+ rels_map = {nid: [e for e in relations.get(nid, []) if e["target"] in ids]
135
+ for nid in ids}
136
+ n_edges_kept = sum(len(v) for v in kids_map.values())
137
+ n_dangling = sum(len(children.get(nid, [])) for nid in ids) - n_edges_kept
138
+
139
+ if not dry_run:
140
+ cg = MdCGOS(root, actor="migrate-wisdom", autoflush=500)
141
+ t0 = time.time()
142
+ for i, r in enumerate(rows, 1):
143
+ nid = r["id"]
144
+ kids, rels = kids_map[nid], rels_map[nid]
145
+ kw = {"subgraph": {"nodes": kids}} if kids else {}
146
+ cg.add(
147
+ nid, _norm_text(r.get("content") or ""),
148
+ layer=EXPORT_LAYER,
149
+ override=True, # 整库受控写入:按 id 幂等覆盖
150
+ tags=_j(r.get("tags"), []),
151
+ condition_space=_j(r.get("condition_space"), {}),
152
+ importance=_f(r.get("importance"), 0.5),
153
+ confidence=_f(r.get("confidence"), 0.6),
154
+ edges=rels,
155
+ created_at=_f(r.get("created_at"), 0),
156
+ modality=r.get("modality") or "text",
157
+ semantic_coordinates=_j(r.get("semantic_coordinates"), {}),
158
+ state_attributes=_j(r.get("state_attributes"), {}),
159
+ entity_id=r.get("entity_id"),
160
+ access_count=int(r.get("access_count") or 0),
161
+ last_access=_f(r.get("last_access"), 0),
162
+ verification_basis="data",
163
+ # legacy 标记:白箱正文非 CCG 五要素形态,资格判定据此判 DEFER
164
+ # (可检索、待补条件)而非 BLINDSPOT。
165
+ ccg_exempt=True,
166
+ migrated_from=name,
167
+ **kw)
168
+ if verbose and i % 1000 == 0:
169
+ print(f" …已写入 {i}/{len(rows)}({time.time()-t0:.0f}s)", flush=True)
170
+ cg.flush()
171
+ cg.rebuild_index() # 落 subgraph/edges 进索引快照,供图遍历免读盘
172
+ cg.close()
173
+
174
+ rep = {"db": db, "root": root, "dry_run": dry_run,
175
+ "sqlite_nodes": len(rows), "hier_edges_kept": n_edges_kept,
176
+ "dangling_children": n_dangling,
177
+ "rel_edges_kept": sum(len(v) for v in rels_map.values())}
178
+ if not dry_run:
179
+ rep["verify"] = verify(db, root, verbose=verbose)
180
+ rep["ok"] = bool(rep["verify"]["ok"])
181
+ if verbose:
182
+ print(json.dumps(rep, ensure_ascii=False, indent=2), flush=True)
183
+ return rep
184
+
185
+
186
+ # --------------------------------------------------------------------------
187
+ # 校验:md 侧 vs sqlite 侧(逐节点全量,不抽样)
188
+ # --------------------------------------------------------------------------
189
+
190
+ # 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传),在 md_ids 与 load_nodes(db) 的交集上做 L1 子/父集合比对、L2 非层级边 target 集合比对、L3 字段比对(condition_space 经 _cs_same 剔除 time_window)后,out["ok"] 仅当无缺失节点、无 child_bad/parent_bad/rel_bad/field_bad、roots_equal 为真且 sg.validate(cg, limit=5) 的 issues==0;verbose 为真值时打印去掉 tree_validate 键的 out。
191
+ def verify(db=DEFAULT_DB, root=DEFAULT_ROOT, verbose=True):
192
+ from . import subgraph as sg
193
+
194
+ cg = MdCGOS(root)
195
+ md_ids = set(cg.index["nodes"])
196
+ children_db, relations_db = load_graph(db)
197
+ nodes_db = {r["id"]: r for r in load_nodes(db)}
198
+ ids = md_ids & set(nodes_db)
199
+
200
+ # ---- L1 结构等价:子集合 / 父节点 / 树根 ----
201
+ child_bad, parent_bad = [], []
202
+ md_children, md_parents = {}, {}
203
+ for nid in ids:
204
+ want_ch = {c for c in children_db.get(nid, []) if c in md_ids}
205
+ got_ch = set(sg.children(cg, nid))
206
+ md_children[nid] = got_ch
207
+ if want_ch != got_ch:
208
+ child_bad.append({"id": nid, "db": sorted(want_ch), "md": sorted(got_ch)})
209
+ # 反查父:db 侧由 hierarchical 边推出(白箱父边唯一)
210
+ want_p = {p for p, cs in children_db.items() if nid in cs and p in md_ids}
211
+ got_p = set(sg.parents_index(cg).get(nid) or [])
212
+ md_parents[nid] = got_p
213
+ if want_p != got_p:
214
+ parent_bad.append({"id": nid, "db": sorted(want_p), "md": sorted(got_p)})
215
+
216
+ roots_db = sorted(nid for nid in ids if not (md_parents[nid] or []))
217
+ roots_md = sorted(set(sg.roots(cg)) & ids)
218
+
219
+ # ---- L2 关系等价:非层级边 target 集合 ----
220
+ rel_bad = []
221
+ for nid in ids:
222
+ want = sorted({e["target"] for e in relations_db.get(nid, []) if e["target"] in md_ids})
223
+ fm = cg.get(nid)["frontmatter"]
224
+ got = sorted({str(e.get("target")) for e in (fm.get("edges") or [])
225
+ if isinstance(e, dict) and e.get("target")})
226
+ if want != got:
227
+ rel_bad.append({"id": nid, "db": want, "md": got})
228
+
229
+ # ---- L3 字段等价 ----
230
+ # 生效条件:a、b 各自经 _j(a, {}) or {} 转成字典(None/"" 得空 dict)后 pop("time_window"),仅当剔除该槽后的两字典相等才返回 True,否则 False。
231
+ def _cs_same(a, b):
232
+ """md 写入侧按条件论纪律自动补 time_window(`mdcg.add` 的观测时间窗),
233
+ 比对时剔除该槽——它是有意增强,不是迁移失真。"""
234
+ a, b = dict(_j(a, {}) or {}), dict(_j(b, {}) or {})
235
+ a.pop("time_window", None)
236
+ b.pop("time_window", None)
237
+ return a == b
238
+
239
+ field_bad, tw_added = [], 0
240
+ for nid in ids:
241
+ fm = cg.get(nid)["frontmatter"]
242
+ r = nodes_db[nid]
243
+ if "time_window" not in _j(r.get("condition_space"), {}):
244
+ tw_added += 1
245
+ checks = (
246
+ ("condition_space", not _cs_same(fm.get("condition_space"), r.get("condition_space"))),
247
+ ("tags", _j(fm.get("tags"), []) != _j(r.get("tags"), [])),
248
+ ("importance", abs(_f(fm.get("importance")) - _f(r.get("importance"))) > 1e-9),
249
+ ("confidence", abs(_f(fm.get("confidence")) - _f(r.get("confidence"))) > 1e-9),
250
+ ("modality", (fm.get("modality") or "text") != (r.get("modality") or "text")),
251
+ )
252
+ for name, bad in checks:
253
+ if bad:
254
+ field_bad.append({"id": nid, "field": name})
255
+ break
256
+
257
+ out = {
258
+ "db": db, "root": root,
259
+ "nodes": {"db": len(nodes_db), "md": len(md_ids),
260
+ "missing": sorted(set(nodes_db) - md_ids)[:5],
261
+ "n_missing": len(set(nodes_db) - md_ids)},
262
+ "L1_hierarchy": {
263
+ "md_edges": sum(len(v) for v in md_children.values()),
264
+ "child_mismatch": len(child_bad), "parent_mismatch": len(parent_bad),
265
+ "samples": (child_bad[:3] + parent_bad[:3]),
266
+ "roots_db": len(roots_db), "roots_md": len(roots_md),
267
+ "roots_equal": roots_db == roots_md,
268
+ },
269
+ "L2_relations": {"mismatch": len(rel_bad), "samples": rel_bad[:3]},
270
+ "L3_fields": {"mismatch": len(field_bad), "samples": field_bad[:3],
271
+ "time_window_added_by_discipline": tw_added},
272
+ "tree_validate": sg.validate(cg, limit=5),
273
+ }
274
+ out["ok"] = (not out["nodes"]["n_missing"] and not child_bad and not parent_bad
275
+ and not rel_bad and not field_bad and out["L1_hierarchy"]["roots_equal"]
276
+ and out["tree_validate"]["issues"] == 0)
277
+ cg.close()
278
+ if verbose:
279
+ print(json.dumps({k: v for k, v in out.items() if k != "tree_validate"},
280
+ ensure_ascii=False, indent=2), flush=True)
281
+ return out
282
+
283
+
284
+ REC_SUBTREE_SQL = (
285
+ "WITH RECURSIVE sub(id) AS (SELECT ? "
286
+ "UNION SELECT e.target_id FROM edges e JOIN sub s ON e.source_id = s.id "
287
+ "WHERE e.relation_type = ?) SELECT id FROM sub")
288
+
289
+
290
+ # 生效条件:db/root 取默认 DEFAULT_DB/DEFAULT_ROOT(或调用方所传),仅遍历 sg.roots(cg)∩md_ids 的前 n_roots 个根(n_roots 为 0 时切片为空、不做子树比对),每根比对 db 递归 CTE 子树与 sg.flatten(cg, nid, max_nodes=10**9) 的 nodes,out["ok"] 仅当该样本无失配且 forest_partition_ok(n_db==n_md==len(md_ids))成立;verbose 为真值时打印 out。
291
+ def bench_graph(db=DEFAULT_DB, root=DEFAULT_ROOT, n_roots=30, verbose=True):
292
+ """L4 子树展开等价 + 森林完整性(回答「图**查询**能否由 md 承担」)。
293
+
294
+ L1 已证逐节点邻接等价,递归展开原则上同构;此处**实测**以覆盖
295
+ `subgraph.flatten` 自身的 max_depth / max_nodes 截断与环处理。
296
+ db 侧递归 CTE,md 侧 flatten,两侧都在同一份 md 节点集上取交集比对。
297
+
298
+ 森林完整性是一条强校验:白箱父边唯一 ⇒ 各根子树互不相交且并集 = 全图。
299
+ 有环 / 漏边 / 多父,都会让两侧节点和立刻不一致。
300
+ """
301
+ from . import subgraph as sg
302
+
303
+ cg = MdCGOS(root)
304
+ md_ids = set(cg.index["nodes"])
305
+ con = _connect(db)
306
+ roots_md = sorted(set(sg.roots(cg)) & md_ids)
307
+
308
+ # 生效条件:用外层闭包的 con 执行 REC_SUBTREE_SQL、参数为 (nid, LEVEL_REL),返回结果各行第 0 列构成的集合。
309
+ def _db_subtree(nid):
310
+ return {r[0] for r in con.execute(REC_SUBTREE_SQL, (nid, LEVEL_REL)).fetchall()}
311
+
312
+ bad = []
313
+ for nid in roots_md[:n_roots]:
314
+ want = _db_subtree(nid) & md_ids
315
+ got = set(sg.flatten(cg, nid, max_nodes=10 ** 9)["nodes"])
316
+ if want != got:
317
+ bad.append({"root": nid, "db_n": len(want), "md_n": len(got),
318
+ "only_db": sorted(want - got)[:3],
319
+ "only_md": sorted(got - want)[:3]})
320
+
321
+ n_db = sum(len(_db_subtree(nid) & md_ids) for nid in roots_md)
322
+ n_md = sum(sg.flatten(cg, nid, max_nodes=10 ** 9)["n_nodes"] for nid in roots_md)
323
+ con.close()
324
+ cg.close()
325
+
326
+ out = {"roots": len(roots_md), "roots_sampled": min(n_roots, len(roots_md)),
327
+ "subtree_mismatch": len(bad), "samples": bad[:3],
328
+ "forest_nodes_db": n_db, "forest_nodes_md": n_md,
329
+ "total_nodes": len(md_ids),
330
+ "forest_partition_ok": n_db == n_md == len(md_ids)}
331
+ out["ok"] = (not bad) and out["forest_partition_ok"]
332
+ if verbose:
333
+ print(json.dumps(out, ensure_ascii=False, indent=2), flush=True)
334
+ return out
335
+
336
+
337
+ # 生效条件:argv 含 "--verify-only" 时返回 0/1 取决于 verify(db, root)["ok"],含 "--bench-graph" 时返回 0/1 取决于 bench_graph(db, root)["ok"],否则以 opt 取的 --db/--root/--limit 调 export(opt("--limit") 缺失或为空串时 limit=None,否则 int(lim);dry_run="--dry-run" in argv),rep.get("dry_run") 为真时直接返回 0,否则按 rep.get("ok") 真→0、假→1。
338
+ def main(argv):
339
+ if hasattr(sys.stdout, "reconfigure"):
340
+ sys.stdout.reconfigure(encoding="utf-8")
341
+
342
+ # 生效条件:name 出现在外层 argv 中时返回 argv[argv.index(name) + 1](即首次出现位置的后一个元素),name 不在 argv 中时返回 default,default 缺省为 None。
343
+ def opt(name, default=None):
344
+ return argv[argv.index(name) + 1] if name in argv else default
345
+
346
+ db = opt("--db", DEFAULT_DB)
347
+ root = opt("--root", DEFAULT_ROOT)
348
+ if "--verify-only" in argv:
349
+ return 0 if verify(db, root)["ok"] else 1
350
+ if "--bench-graph" in argv:
351
+ return 0 if bench_graph(db, root)["ok"] else 1
352
+ lim = opt("--limit")
353
+ rep = export(db=db, root=root, limit=int(lim) if lim else None,
354
+ dry_run="--dry-run" in argv)
355
+ if rep.get("dry_run"):
356
+ return 0
357
+ return 0 if rep.get("ok") else 1
358
+
359
+
360
+ if __name__ == "__main__":
361
361
  sys.exit(main(sys.argv))