@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
package/md_cg/weights.py CHANGED
@@ -1,625 +1,625 @@
1
- # -*- coding: utf-8 -*-
2
- """位置权重矩阵(序标定)——「不同身份,参数偏好不同」。
3
-
4
- 理论出处(本仓原文,非外部知识)
5
- --------------------------------
6
- `docs/theory/智能的公理化基石.md` §4.3:信任合成是
7
- P_trust = f(一致性, 位置可预测性, 版本对齐度)
8
- 其中 `版本对齐度` 已由 `theory` + `links.version_alignment` 提供,
9
- `位置可预测性` 见 `predict`,`一致性` 见 `consistency`。本模块只补一件
10
- 此前缺失的东西:**三个分量在不同位置下的偏好序**。
11
-
12
- 六个位置分为**两类**(由功能身份决定,非人为指定):
13
-
14
- · 认知视角(viewpoint):设计者 / 反思 / 验证
15
- ——「思考的不同视角」,**三分量都涉及**,只标定主导,**不设零**。
16
- · 功能单元(functional):记录 / 输出 / 维生
17
- ——功能需求决定,**身份即排除**:主导 + 明确排除一项(≈0)。
18
-
19
- 排除项可**推导**(派生律:功能身份 → 缺失分量),不是选出来的:
20
-
21
- · 记录单元**不猜** → 不做预测 → 排除 位置可预测性
22
- · 输出单元**不记** → 不复现对账 → 排除 一致性
23
- · 维生系统**不对外** → 无外部协议 → 排除 版本对齐度
24
-
25
- 设计者定位(本轮裁决):
26
- · **不参与日常评估**——它是元视角,思考总体规律;细节由反思/验证承担,
27
- 否则要做全局细节整理,耗时极长。
28
-
29
- 可推导不变量(`invariants()` 逐条自检)
30
- --------------------------------------
31
- 1. **排除唯一**——每个分量恰被 **1** 个位置排除;因视角「3 项都涉及」,
32
- 故每个分量的参与度 = **5/6**(不是 3/6);
33
- 2. **排除项只属功能单元**,且 A/B/C 各被排除一次;
34
- 3. **视角主导 ↔ 功能单元排除**一一配对:
35
- 设计者(A)↔维生、反思(B)↔记录、验证(C)↔输出。
36
-
37
- 诚实边界
38
- --------
39
- · 本模块只声明**序**(谁能压过谁),**不宣称数值**——与 `links.py` 的
40
- `UP_STEP`/`DECAY_DAYS` 同一纪律(文档 §4.3:「v0.1 只声明结构」)。
41
- · `blend()` 里的权重是**占位值**(用序秩当量级),仅供仿真,标定属 v0.3。
42
-
43
- 零第三方依赖。
44
- """
45
- from __future__ import annotations
46
-
47
- import math
48
- import os
49
- import time
50
-
51
- from .fsutil import append_jsonl, read_jsonl
52
-
53
- # --------------------------------------------------------------------------
54
- # 常量
55
- # --------------------------------------------------------------------------
56
-
57
- #: 三个分量(顺序即 A/B/C,稳定,供外部按位引用)
58
- COMPONENTS = ("version_alignment", "predictability", "consistency")
59
-
60
- #: 分量中文名(日志/自描述用)
61
- COMPONENT_LABELS = {
62
- "version_alignment": "版本对齐度",
63
- "predictability": "位置可预测性",
64
- "consistency": "一致性",
65
- }
66
-
67
- #: 位置类别
68
- VIEWPOINT = "viewpoint" # 认知视角:3 项都涉及,只标主导,不设零
69
- FUNCTIONAL = "functional" # 功能单元:主导 + 明确排除一项
70
-
71
- #: 位置 → 权重序规格
72
- #: primary 主导分量(权重最高)
73
- #: secondary 次主导分量(功能单元的第二个偏好;视角为 None=另两项并列)
74
- #: excluded 被排除分量(≈0;仅功能单元有;视角为 None=不设零)
75
- SPEC = {
76
- # ---- 认知视角(不参与日常评估者仅 designer)----
77
- "designer": {"class": VIEWPOINT, "primary": "version_alignment",
78
- "secondary": None, "excluded": None},
79
- "reflect": {"class": VIEWPOINT, "primary": "predictability",
80
- "secondary": None, "excluded": None},
81
- "verify": {"class": VIEWPOINT, "primary": "consistency",
82
- "secondary": None, "excluded": None},
83
- # ---- 功能单元(身份即排除)----
84
- "record": {"class": FUNCTIONAL, "primary": "consistency",
85
- "secondary": "version_alignment", "excluded": "predictability"},
86
- "output": {"class": FUNCTIONAL, "primary": "predictability",
87
- "secondary": "version_alignment", "excluded": "consistency"},
88
- "sustain": {"class": FUNCTIONAL, "primary": "consistency",
89
- "secondary": "predictability", "excluded": "version_alignment"},
90
- }
91
-
92
- POSITION_ORDER = ("designer", "record", "reflect", "verify", "output", "sustain")
93
-
94
- #: 参与**日常评估**的位置(设计者是元参照系,不入日常)
95
- DAILY = ("record", "reflect", "verify", "output", "sustain")
96
-
97
- #: 序秩(占位量级,仅仿真用):主导 2 / 次主导 1 / 排除 0;视角另两项 = 1
98
- RANK_PRIMARY = 2.0
99
- RANK_SECONDARY = 1.0
100
- RANK_EXCLUDED = 0.0
101
-
102
-
103
- class WeightError(Exception):
104
- """未知位置 / 未知分量。"""
105
-
106
-
107
- # --------------------------------------------------------------------------
108
- # 基础查询
109
- # --------------------------------------------------------------------------
110
-
111
- # 生效条件:position 经 str(position or "").strip() 作为 SPEC 的键,命中时返回对应 spec dict,未命中(含 position 为 None/空串/未知)抛 WeightError;
112
- def _spec(position: str) -> dict:
113
- s = SPEC.get(str(position or "").strip())
114
- if s is None:
115
- raise WeightError(f"未知位置:{position!r}(允许:{POSITION_ORDER})")
116
- return s
117
-
118
-
119
- # 生效条件:component 经 str(component or "").strip() 后若结果在 COMPONENTS 中返回该规范分量字符串,否则抛 WeightError;
120
- def _comp(component: str) -> str:
121
- c = str(component or "").strip()
122
- if c not in COMPONENTS:
123
- raise WeightError(f"未知分量:{component!r}(允许:{COMPONENTS})")
124
- return c
125
-
126
-
127
- # 生效条件:position 可被 _spec 解析且其结果 "class" 等于 VIEWPOINT 时返回 True,非 VIEWPOINT 返回 False,未知 position 抛 WeightError;
128
- def is_viewpoint(position: str) -> bool:
129
- """是否认知视角(3 项都涉及,不设零)。"""
130
- return _spec(position)["class"] == VIEWPOINT
131
-
132
-
133
- # 生效条件:position 可被 _spec 解析且其结果 "class" 等于 FUNCTIONAL 时返回 True,非 FUNCTIONAL 返回 False,未知 position 抛 WeightError;
134
- def is_functional(position: str) -> bool:
135
- """是否功能单元(身份即排除)。"""
136
- return _spec(position)["class"] == FUNCTIONAL
137
-
138
-
139
- # 生效条件:position 经 _spec(position) 验证可解析后,返回原始 position 是否在模块级 DAILY 中;带首尾空白等未 strip 的值会因不在 DAILY 返回 False,未知 position 抛 WeightError;
140
- def in_daily_eval(position: str) -> bool:
141
- """是否参与日常评估(设计者=False,元参照系)。"""
142
- _spec(position)
143
- return position in DAILY
144
-
145
-
146
- # 生效条件:position 可被 _spec 解析且其 spec 含 "primary" 键时返回该值,未知 position 抛 WeightError;
147
- def dominant(position: str) -> str:
148
- """主导分量(权重最高者)。"""
149
- return _spec(position)["primary"]
150
-
151
-
152
- # 生效条件:position 可被 _spec 解析且其 spec 含 "secondary" 键时返回该值(视角可为 None),未知 position 抛 WeightError;
153
- def secondary(position: str):
154
- """次主导分量;视角返回 None(另两项并列、均 >0)。"""
155
- return _spec(position)["secondary"]
156
-
157
-
158
- # 生效条件:position 可被 _spec 解析且其 spec 含 "excluded" 键时返回该值(视角可为 None),未知 position 抛 WeightError;
159
- def excluded(position: str):
160
- """被排除分量(≈0);视角返回 None(不设零)。"""
161
- return _spec(position)["excluded"]
162
-
163
-
164
- # --------------------------------------------------------------------------
165
- # 序比较(本模块的权威结论:只有序,没有数值)
166
- # --------------------------------------------------------------------------
167
-
168
- # 生效条件:position 与 component 分别经 _spec 与 _comp 验证后,若 component 等于该位置 spec["excluded"] 返回 RANK_EXCLUDED,否则若等于 spec["primary"] 返回 RANK_PRIMARY,否则返回 RANK_SECONDARY;
169
- def rank(position: str, component: str) -> float:
170
- """分量在该位置的序秩(占位量级):2 主导 / 1 参与 / 0 排除。"""
171
- s = _spec(position)
172
- c = _comp(component)
173
- if s["excluded"] == c:
174
- return RANK_EXCLUDED
175
- if s["primary"] == c:
176
- return RANK_PRIMARY
177
- return RANK_SECONDARY
178
-
179
-
180
- # 生效条件:position、a、b 经 rank 可得序秩,若 rank(position,a)==rank(position,b) 返回 None,否则返回 ra>rb 的 bool;任一参数未知则抛 WeightError;
181
- def prefers(position: str, a: str, b: str):
182
- """该位置是否**严格**偏好 a 胜过 b。
183
-
184
- 返回 True / False / None(None = 二者并列,无严格序)。
185
- """
186
- ra, rb = rank(position, a), rank(position, b)
187
- if ra == rb:
188
- return None
189
- return ra > rb
190
-
191
-
192
- # 生效条件:position 经 _spec 验证且 COMPONENTS 可用时,按 -rank(position,c) 与 COMPONENTS.index(c) 排序,返回 {"preferred":[rank>0], "excluded":[rank==0], "primary":dominant(position), "secondary":secondary(position)}(无 dominant 键);
193
- def order(position: str):
194
- """从高到低排列的分量(并列者按 COMPONENTS 稳定序);排除项单独列出。"""
195
- _spec(position)
196
- ranked = sorted(COMPONENTS, key=lambda c: (-rank(position, c), COMPONENTS.index(c)))
197
- kept = [c for c in ranked if rank(position, c) > 0]
198
- exc = [c for c in ranked if rank(position, c) == 0]
199
- return {"preferred": kept, "excluded": exc,
200
- "primary": dominant(position), "secondary": secondary(position)}
201
-
202
-
203
- # 生效条件:position 经 _spec 验证且 COMPONENTS 可用时,将各分量 rank 归一化到 4 位小数返回;若 total 为 0 则按 total=1.0 计算;
204
- def weights(position: str) -> dict:
205
- """占位数值权重(序秩归一化);**未标定**,仅供仿真。"""
206
- _spec(position)
207
- raw = {c: rank(position, c) for c in COMPONENTS}
208
- total = sum(raw.values()) or 1.0
209
- return {c: round(raw[c] / total, 4) for c in COMPONENTS}
210
-
211
-
212
- # --------------------------------------------------------------------------
213
- # 合成(占位:f(一致性, 位置可预测性, 版本对齐度))
214
- # --------------------------------------------------------------------------
215
-
216
- # 生效条件:position 经 _spec 可解析且 COMPONENTS 可用时,components 对每个分量经 .get(c,0.0) 取值并截到 [0,1];若 components 无 .get 或该值不能 float 则该分量值记 0.0,仍按 weights(position) 加权求和返回含 score/values/weights/dominant 的 dict;
217
- def blend(position: str, components: dict) -> dict:
218
- """按位置的权重合成单一信任标量。
219
-
220
- `components` 形如 {"version_alignment": 1.0, "predictability": 0.8,
221
- "consistency": 0.6};缺省按 0 计。
222
-
223
- **数值未标定**:这里用序秩当量级,只保证「主导分量对结果影响最大」这
224
- 一方向性事实。标定属路线图 v0.3。
225
- """
226
- s = _spec(position)
227
- w = weights(position)
228
- vals = {}
229
- for c in COMPONENTS:
230
- try:
231
- vals[c] = max(0.0, min(1.0, float(components.get(c, 0.0))))
232
- except (AttributeError, TypeError, ValueError):
233
- vals[c] = 0.0
234
- score = sum(w[c] * vals[c] for c in COMPONENTS)
235
- return {"position": position, "class": s["class"],
236
- "weights": w, "values": vals, "score": round(score, 4),
237
- "dominant": s["primary"],
238
- "note": "权重为占位序秩(未标定);仅方向性结论可信"}
239
-
240
-
241
- # --------------------------------------------------------------------------
242
- # 不变量自检(把上轮的三条结构约束落成可执行断言)
243
- # --------------------------------------------------------------------------
244
-
245
- # 生效条件:模块级 POSITION_ORDER、COMPONENTS、SPEC、VIEWPOINT、FUNCTIONAL 等常量齐备时,invariants() 逐条自检并返回 {"ok": all(checks[*].ok), "checks": ...};
246
- def invariants() -> dict:
247
- """逐条自检结构约束,返回 {ok, checks{name: {ok, detail}}}。"""
248
- checks = {}
249
-
250
- # ① 排除唯一:每分量恰被 1 个位置排除 ⇒ 参与度 = 5/6
251
- part = {c: [p for p in POSITION_ORDER if rank(p, c) > 0] for c in COMPONENTS}
252
- exc_of = {c: [p for p in POSITION_ORDER if rank(p, c) == 0] for c in COMPONENTS}
253
- checks["excluded_exactly_once"] = {
254
- "ok": all(len(exc_of[c]) == 1 for c in COMPONENTS)
255
- and all(len(part[c]) == len(POSITION_ORDER) - 1 for c in COMPONENTS),
256
- "detail": {c: {"participants": len(part[c]), "excluded_by": exc_of[c]}
257
- for c in COMPONENTS}}
258
-
259
- # ② 排除项只属功能单元,且每分量各被排除一次
260
- excs = {}
261
- for p in POSITION_ORDER:
262
- e = excluded(p)
263
- if e is None:
264
- continue
265
- excs.setdefault(e, []).append(p)
266
- only_functional = all(is_functional(p)
267
- for vs in excs.values() for p in vs)
268
- both = all(len(excs.get(c) or []) == 1 for c in COMPONENTS)
269
- checks["exclusion_functional_only_once_each"] = {
270
- "ok": bool(excs) and only_functional and both,
271
- "detail": {c: excs.get(c, []) for c in COMPONENTS}}
272
-
273
- # ③ 视角主导 ↔ 功能单元排除 一一配对
274
- dom_pairs = {} # 分量 → 视角
275
- for p in POSITION_ORDER:
276
- if is_viewpoint(p):
277
- dom_pairs.setdefault(dominant(p), []).append(p)
278
- pairing = {}
279
- for p in POSITION_ORDER:
280
- if not is_functional(p):
281
- continue
282
- e = excluded(p)
283
- if e and len(dom_pairs.get(e) or []) == 1:
284
- pairing[dom_pairs[e][0]] = p
285
- checks["viewpoint_dominant_pairs_unit_exclusion"] = {
286
- "ok": len(pairing) == 3,
287
- "detail": pairing}
288
-
289
- # ④ 功能单元恰有一个排除项;视角一个都没有
290
- checks["functional_excludes_exactly_one"] = {
291
- "ok": all(excluded(p) is not None for p in POSITION_ORDER
292
- if is_functional(p))
293
- and all(excluded(p) is None for p in POSITION_ORDER
294
- if is_viewpoint(p)),
295
- "detail": {p: excluded(p) for p in POSITION_ORDER}}
296
-
297
- # ⑤ 排除项序秩严格最低
298
- checks["excluded_is_lowest"] = {
299
- "ok": all(rank(p, excluded(p)) < rank(p, c)
300
- for p in POSITION_ORDER if excluded(p)
301
- for c in COMPONENTS if c != excluded(p)),
302
- "detail": "排除分量序秩 0,严格低于其余分量"}
303
-
304
- return {"ok": all(c["ok"] for c in checks.values()), "checks": checks}
305
-
306
-
307
- # --------------------------------------------------------------------------
308
- # 自描述
309
- # --------------------------------------------------------------------------
310
-
311
- # 生效条件:模块级 COMPONENTS、COMPONENT_LABELS、VIEWPOINT、FUNCTIONAL、SPEC、POSITION_ORDER、DAILY 齐备时,返回位置权重矩阵自描述 dict,其中 components 按 COMPONENT_LABELS、positions 按 SPEC、daily_eval 按 DAILY 展开;
312
- def catalog() -> dict:
313
- """位置权重矩阵自描述(供 MCP / 文档对照验证)。"""
314
- return {
315
- "question": "不同身份,参数偏好不同",
316
- "components": {c: COMPONENT_LABELS[c] for c in COMPONENTS},
317
- "classes": {
318
- VIEWPOINT: "认知视角:3 项都涉及,只标主导,不设零",
319
- FUNCTIONAL: "功能单元:身份即排除(不猜/不记/不对外)",
320
- },
321
- "positions": {p: dict(SPEC[p]) for p in POSITION_ORDER},
322
- "daily_eval": list(DAILY),
323
- "meta_reference": [p for p in POSITION_ORDER if p not in DAILY],
324
- "derivation": {"record": "不猜 → 排除 位置可预测性",
325
- "output": "不记 → 排除 一致性",
326
- "sustain": "不对外 → 排除 版本对齐度"},
327
- "formula": "P_trust = f(一致性, 位置可预测性, 版本对齐度)",
328
- "honest_boundary": "只声明序,不宣称数值;blend() 权重为占位序秩",
329
- }
330
-
331
-
332
- # ==========================================================================
333
- # 结构重要性重算(maintain.importance)
334
- # ==========================================================================
335
- #
336
- # 与上面的「位置权重矩阵」是**两件事**,不要混:
337
- # · 上面回答「不同身份偏好哪些信任分量」(序标定,作用于位置);
338
- # · 下面回答「一个节点在认知图结构里该有多大重要性」(重算,作用于节点)。
339
- #
340
- # 三个**可测**分量(对齐计划:按覆盖度、冗余度、验证基底重排):
341
- # coverage 覆盖度 —— 有多少节点指向/包含它(入度,结构中枢性)
342
- # redundancy 冗余度 —— 与同层节点内容哈希撞车的比例(越冗余越该降权)
343
- # basis 验证基底 —— 外部验证档位(formal_proof/compiler > test > measurement > data > other)
344
- #
345
- # 纪律:只改 `frontmatter.importance` 与索引快照,**不动正文**(减小 diff 与重写成本);
346
- # 全流程可预演(apply=False)、可留痕(`_maintain.jsonl`)、可回滚(rollback)。
347
- # 性能:dry-run 不读任何节点文件(只用索引快照);apply 只写「变动超阈值」的节点。
348
-
349
- MAINTAIN_LOG = "_maintain.jsonl"
350
-
351
- #: 验证基底 → 可信权重(枚举来自 nodefile.VERIFICATION_BASIS)
352
- #: 文科来源一致性档(textbook/public_kb)低于可复现档、高于 other:
353
- #: 教材/公开知识库是权威二手来源,但不是可复算证据。
354
- BASIS_TRUST = {
355
- "formal_proof": 1.00,
356
- "compiler": 0.90,
357
- "test": 0.80,
358
- "measurement": 0.65,
359
- "textbook": 0.60,
360
- "data": 0.45,
361
- "public_kb": 0.40,
362
- "other": 0.25,
363
- }
364
- BASIS_TRUST_MISSING = 0.25
365
-
366
- #: 三分量合成权重(占位量级,沿用「只声明序」纪律;分量序主导→次要)
367
- IMPORTANCE_MIX = {"basis": 0.40, "coverage": 0.35, "redundancy": 0.25}
368
- COV_SAT = 12.0 # 入度饱和点:约 12 条入边即视为覆盖满
369
- IMPORTANCE_FLOOR = 0.10
370
- IMPORTANCE_CEIL = 1.00
371
- IMPORTANCE_PROTECT = 0.70 # ≥ 此值:保护下限(已保护/高危节点不被降破)
372
- APPLY_DELTA = 0.05 # 变动小于此值不写盘(防 IO 放大)
373
-
374
-
375
- # 生效条件:e 为可 .get 的映射时,遍历 e.get("edges")(假值视为空)逐项按 dict 的 to/target/node/id 或标量转 str 追加非假值,再取 e.get("subgraph"),若为 dict 取其 "nodes" 否则取 subgraph 本身,且当其为 list/tuple 时追加其中 dict 的 id 或标量转 str 的非假值,返回 out;
376
- def _targets(e: dict):
377
- """索引快照里的「出边目标」:edges ∪ subgraph.nodes(兼容 dict/str)。"""
378
- out = []
379
- for x in (e.get("edges") or []):
380
- if isinstance(x, dict):
381
- t = x.get("to") or x.get("target") or x.get("node") or x.get("id")
382
- else:
383
- t = x
384
- if t:
385
- out.append(str(t))
386
- sg = e.get("subgraph")
387
- raw = sg.get("nodes") if isinstance(sg, dict) else sg
388
- if isinstance(raw, (list, tuple)):
389
- for n in raw:
390
- nid = n.get("id") if isinstance(n, dict) else n
391
- if nid:
392
- out.append(str(nid))
393
- return out
394
-
395
-
396
- # 生效条件:basis 为 None 时返回 BASIS_TRUST_MISSING;否则把 str(basis).strip().lower() 作为 BASIS_TRUST 的键,命中返回对应权重,未命中(含空串)返回 BASIS_TRUST_MISSING;
397
- def basis_trust(basis):
398
- """验证基底 → 可信权重;缺失/未知一律给最低档(不假装可信)。"""
399
- if basis is None:
400
- return BASIS_TRUST_MISSING
401
- return BASIS_TRUST.get(str(basis).strip().lower(), BASIS_TRUST_MISSING)
402
-
403
-
404
- # 生效条件:cg 的 index(getattr(cg,"index",None) or {})与其 "nodes" 同为真值时,返回以这些节点 id 为键的入度表,仅当 _targets(e) 给出的目标 t 也在 nodes 且 t != nid 时计数 +1;index 或 "nodes" 为假值(None/{})时 nodes 回落 {},直接返回空 dict。
405
- def coverage_index(cg) -> dict:
406
- """入度表:nid → 被多少节点指向(覆盖度,O(N) 免读文件)。"""
407
- nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
408
- indeg = {nid: 0 for nid in nodes}
409
- for nid, e in nodes.items():
410
- for t in _targets(e):
411
- if t in indeg and t != nid:
412
- indeg[t] += 1
413
- return indeg
414
-
415
-
416
- # 生效条件:cg.index 的 "nodes" 为 dict 时,layer 真值仅处理 e.get("layer")==layer 的节点,layer 假值不过滤;content_hash 为假值(None/空串/0 等)的节点输出 0.0,同 (e.get("layer"), content_hash) 第二次撞车时当前与首次节点均输出 1.0,否则输出 0.0;
417
- def redundancy_map(cg, layer=None) -> dict:
418
- """同层内容哈希撞车 → 冗余度 1.0,否则 0.0(精确冗余,O(N) 免读文件)。
419
-
420
- 诚实边界:这是**精确冗余**(同一层出现完全相同的正文),不是语义近似冗余。
421
- 语义近似由 `forgetting.redundancy`(bigram 覆盖)在写入侧单独负责。
422
- """
423
- nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
424
- seen, out = {}, {}
425
- for nid, e in nodes.items():
426
- if layer and e.get("layer") != layer:
427
- continue
428
- h = e.get("content_hash") or ""
429
- if not h:
430
- out[nid] = 0.0
431
- continue
432
- key = (e.get("layer"), h)
433
- if key in seen:
434
- out[nid] = 1.0
435
- out[seen[key]] = 1.0
436
- else:
437
- seen[key] = nid
438
- out.setdefault(nid, 0.0)
439
- return out
440
-
441
-
442
- # 生效条件:cg.index 的 nodes 为 dict 且 entry 非 None 或 nodes.get(nid) 命中时,e 按 entry 优先否则 nodes.get(nid);indeg/red 分别仅在为 None 时回落 coverage_index(cg)/redundancy_map(cg, layer=e.get("layer"))(空容器不回落);按 IMPORTANCE_MIX、COV_SAT 及 e.get("verification_basis") 的 basis_trust 计算 coverage/redundancy/basis 分量,按 bool(e.get("protected")) 选择 IMPORTANCE_PROTECT 或 IMPORTANCE_FLOOR 作下限、IMPORTANCE_CEIL 作上限,返回含 before(e.get("importance",0.5) or 0.5)、after、components、protected 的 dict;entry 与 nodes.get(nid) 均为 None 返回 None;
443
- def node_importance(cg, nid, indeg=None, red=None, entry=None):
444
- """单节点结构重要性分解(可审计:给出分量而非只给分)。"""
445
- nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
446
- e = entry if entry is not None else nodes.get(nid)
447
- if e is None:
448
- return None
449
- indeg = indeg if indeg is not None else coverage_index(cg)
450
- red = red if red is not None else redundancy_map(cg, layer=e.get("layer"))
451
- d = int(indeg.get(nid, 0) or 0)
452
- cov = min(1.0, math.log1p(d) / math.log1p(COV_SAT))
453
- rr = max(0.0, min(1.0, float(red.get(nid, 0.0) or 0.0)))
454
- bt = basis_trust(e.get("verification_basis"))
455
- score = (IMPORTANCE_MIX["basis"] * bt
456
- + IMPORTANCE_MIX["coverage"] * cov
457
- + IMPORTANCE_MIX["redundancy"] * (1.0 - rr))
458
- protected = bool(e.get("protected"))
459
- floor = IMPORTANCE_PROTECT if protected else IMPORTANCE_FLOOR
460
- score = max(floor, min(IMPORTANCE_CEIL, score))
461
- return {"node_id": nid,
462
- "before": float(e.get("importance", 0.5) or 0.5),
463
- "after": round(score, 4),
464
- "components": {"coverage": round(cov, 4), "redundancy": round(rr, 4),
465
- "basis_trust": round(bt, 4), "in_degree": d,
466
- "verification_basis": e.get("verification_basis")},
467
- "protected": protected,
468
- "protected_floor": protected}
469
-
470
-
471
- # 生效条件:给定 cg 且 nodes = cg.index["nodes"] 时按 layer 过滤、limit 为真值才 ids = ids[:int(limit)] 逐节点重算,abs(after-before) < float(min_delta) 记 unchanged;仅 apply=True 才把 frontmatter.importance/importance_source/importance_components 写回(after >= IMPORTANCE_PROTECT 且未 protected 时补写 protected/protection_reason),并向 cg.root 下 append_jsonl(..., MAINTAIN_LOG) 记 batch 后 rebuild_index。
472
- def recalc(cg, layer=None, limit=None, apply=False, min_delta=APPLY_DELTA,
473
- actor="maintain", dry_run_samples=10):
474
- """结构重要性重算:覆盖度 + 冗余度 + 验证基底 → 重排节点重要性。
475
-
476
- apply=False(默认)只出报表,不写盘(对应计划「可预演」)。
477
- apply=True 逐节点改写 `frontmatter.importance`,每批写一条 `_maintain.jsonl`
478
- (before/after/分量/actor),并提供 rollback 反向应用。
479
- """
480
- nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
481
- indeg = coverage_index(cg)
482
- red = redundancy_map(cg, layer=layer)
483
- ids = [nid for nid, e in nodes.items()
484
- if not layer or e.get("layer") == layer]
485
- ids.sort()
486
- if limit:
487
- ids = ids[:int(limit)]
488
- t0 = time.time()
489
- planned, changed, unchanged, skipped = [], 0, 0, 0
490
- before_sum = after_sum = 0.0
491
- by_layer = {}
492
- batch = time.strftime("%Y%m%d-%H%M%S")
493
- samples = []
494
- for nid in ids:
495
- info = node_importance(cg, nid, indeg=indeg, red=red)
496
- if info is None:
497
- skipped += 1
498
- continue
499
- before, after = info["before"], info["after"]
500
- before_sum += before
501
- after_sum += after
502
- lay = (nodes.get(nid) or {}).get("layer") or "?"
503
- bl = by_layer.setdefault(lay, {"nodes": 0, "changed": 0,
504
- "avg_before": 0.0, "avg_after": 0.0})
505
- bl["nodes"] += 1
506
- if abs(after - before) < float(min_delta):
507
- unchanged += 1
508
- continue
509
- changed += 1
510
- bl["changed"] += 1
511
- plan = dict(info)
512
- plan["batch"] = batch
513
- plan["delta"] = round(after - before, 4)
514
- planned.append(plan)
515
- if len(samples) < int(dry_run_samples):
516
- samples.append(plan)
517
- for lay, bl in list(by_layer.items()):
518
- bl["avg_before"] = 0.0
519
- bl["avg_after"] = 0.0
520
- written = 0
521
- if apply:
522
- for plan in planned:
523
- nid = plan["node_id"]
524
- node = cg.get(nid)
525
- if not node:
526
- continue
527
- fm = node.get("frontmatter") or {}
528
- fm["importance"] = plan["after"]
529
- fm["importance_source"] = "recalc"
530
- fm["importance_components"] = plan["components"]
531
- if plan["after"] >= IMPORTANCE_PROTECT and not fm.get("protected"):
532
- fm["protected"] = True
533
- fm["protection_reason"] = (f"recalc importance={plan['after']:.2f}"
534
- f"≥{IMPORTANCE_PROTECT}")
535
- path = os.path.join(cg.root, (nodes.get(nid) or {}).get("path")
536
- or node.get("path") or f"{nid}.md")
537
- cg._write_node(nid, path, fm, node.get("content") or "")
538
- e = nodes.get(nid)
539
- if e is not None:
540
- e["importance"] = plan["after"]
541
- if fm.get("protected"):
542
- e["protected"] = True
543
- e["protection_reason"] = fm["protection_reason"]
544
- rec = {"t": time.time(), "action": "importance", "batch": batch,
545
- "id": nid, "layer": (e or {}).get("layer"),
546
- "before": plan["before"], "after": plan["after"],
547
- "delta": plan["delta"], "components": plan["components"],
548
- "actor": actor}
549
- append_jsonl(os.path.join(cg.root, MAINTAIN_LOG), rec)
550
- written += 1
551
- if written and hasattr(cg, "rebuild_index"):
552
- cg.rebuild_index() # 索引与盘面重新对齐,防内存/磁盘分叉
553
- n = max(1, len(ids))
554
- return {
555
- "ok": True, "action": "importance", "dry_run": not apply,
556
- "batch": batch, "nodes_scanned": len(ids), "changed": changed,
557
- "unchanged": unchanged, "skipped": skipped, "written": written,
558
- "min_delta": float(min_delta),
559
- "avg_before": round(before_sum / n, 4),
560
- "avg_after": round(after_sum / n, 4),
561
- "by_layer": {k: {"nodes": v["nodes"], "changed": v["changed"]}
562
- for k, v in by_layer.items()},
563
- "samples": samples, "elapsed_ms": int((time.time() - t0) * 1000),
564
- "log": MAINTAIN_LOG,
565
- "note": ("dry-run:未写盘;apply=True 才改写 importance"
566
- if not apply else
567
- f"已改写 {written} 个节点;回滚见 rollback(batch={batch})"),
568
- }
569
-
570
-
571
- # 生效条件:cg.root/MAINTAIN_LOG 可读出 action=="importance" 记录后,entry_ids 为真值时按记录 id 是否在 {str(x) for x in entry_ids} 过滤;否则 batch 为真值时按 r.get("batch")==batch 过滤;否则取最后一条记录的 batch 再按其过滤;无 importance 记录返回 {"ok":False,"error":"no_records","reverted":0},过滤后无记录返回 {"ok":False,"error":"batch_not_found",...};对命中且 cg.get(nid) 为真的记录写回 rec.get("before") 并计数,若 reverted 且 cg 有 rebuild_index 则调用,最后 append_jsonl 写 actor 并返回 {"ok":True,"batch":batch,"reverted":reverted,"ids":ids};
572
- def rollback(cg, batch=None, entry_ids=None, actor="maintain"):
573
- """把重要性重算反向应用(bulk 改写的可回滚兑现)。
574
-
575
- batch 为空则回滚**最近一批**。返回 {ok, reverted, batch, ids}。
576
- """
577
- log_path = os.path.join(cg.root, MAINTAIN_LOG)
578
- records = [r for r in read_jsonl(log_path)
579
- if r.get("action") == "importance"]
580
- if not records:
581
- return {"ok": False, "error": "no_records", "reverted": 0}
582
- if entry_ids:
583
- want = {str(x) for x in entry_ids}
584
- records = [r for r in records if str(r.get("id")) in want]
585
- elif batch:
586
- records = [r for r in records if r.get("batch") == batch]
587
- else:
588
- batch = records[-1].get("batch")
589
- records = [r for r in records if r.get("batch") == batch]
590
- if not records:
591
- return {"ok": False, "error": "batch_not_found", "batch": batch,
592
- "reverted": 0}
593
- nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
594
- reverted, ids = 0, []
595
- # 同一节点多条记录时以最早一条的 before 为准
596
- for rec in records:
597
- nid = rec.get("id")
598
- node = cg.get(nid)
599
- if not node:
600
- continue
601
- fm = node.get("frontmatter") or {}
602
- fm["importance"] = rec.get("before")
603
- fm["importance_source"] = "recalc_rollback"
604
- path = os.path.join(cg.root, (nodes.get(nid) or {}).get("path")
605
- or node.get("path") or f"{nid}.md")
606
- cg._write_node(nid, path, fm, node.get("content") or "")
607
- e = nodes.get(nid)
608
- if e is not None:
609
- e["importance"] = rec.get("before")
610
- reverted += 1
611
- ids.append(nid)
612
- if reverted and hasattr(cg, "rebuild_index"):
613
- cg.rebuild_index()
614
- append_jsonl(log_path, {"t": time.time(), "action": "importance_rollback",
615
- "batch": batch, "reverted": reverted, "actor": actor})
616
- return {"ok": True, "batch": batch, "reverted": reverted, "ids": ids}
617
-
618
-
619
- # 生效条件:cg.root/MAINTAIN_LOG 可读出 JSONL 记录后,action 为真值时按 r.get("action")==action 过滤,假值不过滤;返回 recs[-int(limit):],其中 limit=0 时 int(0)=0 使切片为 recs[0:] 返回全部而非空;
620
- def history(cg, limit=100, action=None):
621
- """维护留痕(最近 limit 条),可按 action 过滤。"""
622
- recs = list(read_jsonl(os.path.join(cg.root, MAINTAIN_LOG)))
623
- if action:
624
- recs = [r for r in recs if r.get("action") == action]
1
+ # -*- coding: utf-8 -*-
2
+ """位置权重矩阵(序标定)——「不同身份,参数偏好不同」。
3
+
4
+ 理论出处(本仓原文,非外部知识)
5
+ --------------------------------
6
+ `docs/theory/智能的公理化基石.md` §4.3:信任合成是
7
+ P_trust = f(一致性, 位置可预测性, 版本对齐度)
8
+ 其中 `版本对齐度` 已由 `theory` + `links.version_alignment` 提供,
9
+ `位置可预测性` 见 `predict`,`一致性` 见 `consistency`。本模块只补一件
10
+ 此前缺失的东西:**三个分量在不同位置下的偏好序**。
11
+
12
+ 六个位置分为**两类**(由功能身份决定,非人为指定):
13
+
14
+ · 认知视角(viewpoint):设计者 / 反思 / 验证
15
+ ——「思考的不同视角」,**三分量都涉及**,只标定主导,**不设零**。
16
+ · 功能单元(functional):记录 / 输出 / 维生
17
+ ——功能需求决定,**身份即排除**:主导 + 明确排除一项(≈0)。
18
+
19
+ 排除项可**推导**(派生律:功能身份 → 缺失分量),不是选出来的:
20
+
21
+ · 记录单元**不猜** → 不做预测 → 排除 位置可预测性
22
+ · 输出单元**不记** → 不复现对账 → 排除 一致性
23
+ · 维生系统**不对外** → 无外部协议 → 排除 版本对齐度
24
+
25
+ 设计者定位(本轮裁决):
26
+ · **不参与日常评估**——它是元视角,思考总体规律;细节由反思/验证承担,
27
+ 否则要做全局细节整理,耗时极长。
28
+
29
+ 可推导不变量(`invariants()` 逐条自检)
30
+ --------------------------------------
31
+ 1. **排除唯一**——每个分量恰被 **1** 个位置排除;因视角「3 项都涉及」,
32
+ 故每个分量的参与度 = **5/6**(不是 3/6);
33
+ 2. **排除项只属功能单元**,且 A/B/C 各被排除一次;
34
+ 3. **视角主导 ↔ 功能单元排除**一一配对:
35
+ 设计者(A)↔维生、反思(B)↔记录、验证(C)↔输出。
36
+
37
+ 诚实边界
38
+ --------
39
+ · 本模块只声明**序**(谁能压过谁),**不宣称数值**——与 `links.py` 的
40
+ `UP_STEP`/`DECAY_DAYS` 同一纪律(文档 §4.3:「v0.1 只声明结构」)。
41
+ · `blend()` 里的权重是**占位值**(用序秩当量级),仅供仿真,标定属 v0.3。
42
+
43
+ 零第三方依赖。
44
+ """
45
+ from __future__ import annotations
46
+
47
+ import math
48
+ import os
49
+ import time
50
+
51
+ from .fsutil import append_jsonl, read_jsonl
52
+
53
+ # --------------------------------------------------------------------------
54
+ # 常量
55
+ # --------------------------------------------------------------------------
56
+
57
+ #: 三个分量(顺序即 A/B/C,稳定,供外部按位引用)
58
+ COMPONENTS = ("version_alignment", "predictability", "consistency")
59
+
60
+ #: 分量中文名(日志/自描述用)
61
+ COMPONENT_LABELS = {
62
+ "version_alignment": "版本对齐度",
63
+ "predictability": "位置可预测性",
64
+ "consistency": "一致性",
65
+ }
66
+
67
+ #: 位置类别
68
+ VIEWPOINT = "viewpoint" # 认知视角:3 项都涉及,只标主导,不设零
69
+ FUNCTIONAL = "functional" # 功能单元:主导 + 明确排除一项
70
+
71
+ #: 位置 → 权重序规格
72
+ #: primary 主导分量(权重最高)
73
+ #: secondary 次主导分量(功能单元的第二个偏好;视角为 None=另两项并列)
74
+ #: excluded 被排除分量(≈0;仅功能单元有;视角为 None=不设零)
75
+ SPEC = {
76
+ # ---- 认知视角(不参与日常评估者仅 designer)----
77
+ "designer": {"class": VIEWPOINT, "primary": "version_alignment",
78
+ "secondary": None, "excluded": None},
79
+ "reflect": {"class": VIEWPOINT, "primary": "predictability",
80
+ "secondary": None, "excluded": None},
81
+ "verify": {"class": VIEWPOINT, "primary": "consistency",
82
+ "secondary": None, "excluded": None},
83
+ # ---- 功能单元(身份即排除)----
84
+ "record": {"class": FUNCTIONAL, "primary": "consistency",
85
+ "secondary": "version_alignment", "excluded": "predictability"},
86
+ "output": {"class": FUNCTIONAL, "primary": "predictability",
87
+ "secondary": "version_alignment", "excluded": "consistency"},
88
+ "sustain": {"class": FUNCTIONAL, "primary": "consistency",
89
+ "secondary": "predictability", "excluded": "version_alignment"},
90
+ }
91
+
92
+ POSITION_ORDER = ("designer", "record", "reflect", "verify", "output", "sustain")
93
+
94
+ #: 参与**日常评估**的位置(设计者是元参照系,不入日常)
95
+ DAILY = ("record", "reflect", "verify", "output", "sustain")
96
+
97
+ #: 序秩(占位量级,仅仿真用):主导 2 / 次主导 1 / 排除 0;视角另两项 = 1
98
+ RANK_PRIMARY = 2.0
99
+ RANK_SECONDARY = 1.0
100
+ RANK_EXCLUDED = 0.0
101
+
102
+
103
+ class WeightError(Exception):
104
+ """未知位置 / 未知分量。"""
105
+
106
+
107
+ # --------------------------------------------------------------------------
108
+ # 基础查询
109
+ # --------------------------------------------------------------------------
110
+
111
+ # 生效条件:position 经 str(position or "").strip() 作为 SPEC 的键,命中时返回对应 spec dict,未命中(含 position 为 None/空串/未知)抛 WeightError;
112
+ def _spec(position: str) -> dict:
113
+ s = SPEC.get(str(position or "").strip())
114
+ if s is None:
115
+ raise WeightError(f"未知位置:{position!r}(允许:{POSITION_ORDER})")
116
+ return s
117
+
118
+
119
+ # 生效条件:component 经 str(component or "").strip() 后若结果在 COMPONENTS 中返回该规范分量字符串,否则抛 WeightError;
120
+ def _comp(component: str) -> str:
121
+ c = str(component or "").strip()
122
+ if c not in COMPONENTS:
123
+ raise WeightError(f"未知分量:{component!r}(允许:{COMPONENTS})")
124
+ return c
125
+
126
+
127
+ # 生效条件:position 可被 _spec 解析且其结果 "class" 等于 VIEWPOINT 时返回 True,非 VIEWPOINT 返回 False,未知 position 抛 WeightError;
128
+ def is_viewpoint(position: str) -> bool:
129
+ """是否认知视角(3 项都涉及,不设零)。"""
130
+ return _spec(position)["class"] == VIEWPOINT
131
+
132
+
133
+ # 生效条件:position 可被 _spec 解析且其结果 "class" 等于 FUNCTIONAL 时返回 True,非 FUNCTIONAL 返回 False,未知 position 抛 WeightError;
134
+ def is_functional(position: str) -> bool:
135
+ """是否功能单元(身份即排除)。"""
136
+ return _spec(position)["class"] == FUNCTIONAL
137
+
138
+
139
+ # 生效条件:position 经 _spec(position) 验证可解析后,返回原始 position 是否在模块级 DAILY 中;带首尾空白等未 strip 的值会因不在 DAILY 返回 False,未知 position 抛 WeightError;
140
+ def in_daily_eval(position: str) -> bool:
141
+ """是否参与日常评估(设计者=False,元参照系)。"""
142
+ _spec(position)
143
+ return position in DAILY
144
+
145
+
146
+ # 生效条件:position 可被 _spec 解析且其 spec 含 "primary" 键时返回该值,未知 position 抛 WeightError;
147
+ def dominant(position: str) -> str:
148
+ """主导分量(权重最高者)。"""
149
+ return _spec(position)["primary"]
150
+
151
+
152
+ # 生效条件:position 可被 _spec 解析且其 spec 含 "secondary" 键时返回该值(视角可为 None),未知 position 抛 WeightError;
153
+ def secondary(position: str):
154
+ """次主导分量;视角返回 None(另两项并列、均 >0)。"""
155
+ return _spec(position)["secondary"]
156
+
157
+
158
+ # 生效条件:position 可被 _spec 解析且其 spec 含 "excluded" 键时返回该值(视角可为 None),未知 position 抛 WeightError;
159
+ def excluded(position: str):
160
+ """被排除分量(≈0);视角返回 None(不设零)。"""
161
+ return _spec(position)["excluded"]
162
+
163
+
164
+ # --------------------------------------------------------------------------
165
+ # 序比较(本模块的权威结论:只有序,没有数值)
166
+ # --------------------------------------------------------------------------
167
+
168
+ # 生效条件:position 与 component 分别经 _spec 与 _comp 验证后,若 component 等于该位置 spec["excluded"] 返回 RANK_EXCLUDED,否则若等于 spec["primary"] 返回 RANK_PRIMARY,否则返回 RANK_SECONDARY;
169
+ def rank(position: str, component: str) -> float:
170
+ """分量在该位置的序秩(占位量级):2 主导 / 1 参与 / 0 排除。"""
171
+ s = _spec(position)
172
+ c = _comp(component)
173
+ if s["excluded"] == c:
174
+ return RANK_EXCLUDED
175
+ if s["primary"] == c:
176
+ return RANK_PRIMARY
177
+ return RANK_SECONDARY
178
+
179
+
180
+ # 生效条件:position、a、b 经 rank 可得序秩,若 rank(position,a)==rank(position,b) 返回 None,否则返回 ra>rb 的 bool;任一参数未知则抛 WeightError;
181
+ def prefers(position: str, a: str, b: str):
182
+ """该位置是否**严格**偏好 a 胜过 b。
183
+
184
+ 返回 True / False / None(None = 二者并列,无严格序)。
185
+ """
186
+ ra, rb = rank(position, a), rank(position, b)
187
+ if ra == rb:
188
+ return None
189
+ return ra > rb
190
+
191
+
192
+ # 生效条件:position 经 _spec 验证且 COMPONENTS 可用时,按 -rank(position,c) 与 COMPONENTS.index(c) 排序,返回 {"preferred":[rank>0], "excluded":[rank==0], "primary":dominant(position), "secondary":secondary(position)}(无 dominant 键);
193
+ def order(position: str):
194
+ """从高到低排列的分量(并列者按 COMPONENTS 稳定序);排除项单独列出。"""
195
+ _spec(position)
196
+ ranked = sorted(COMPONENTS, key=lambda c: (-rank(position, c), COMPONENTS.index(c)))
197
+ kept = [c for c in ranked if rank(position, c) > 0]
198
+ exc = [c for c in ranked if rank(position, c) == 0]
199
+ return {"preferred": kept, "excluded": exc,
200
+ "primary": dominant(position), "secondary": secondary(position)}
201
+
202
+
203
+ # 生效条件:position 经 _spec 验证且 COMPONENTS 可用时,将各分量 rank 归一化到 4 位小数返回;若 total 为 0 则按 total=1.0 计算;
204
+ def weights(position: str) -> dict:
205
+ """占位数值权重(序秩归一化);**未标定**,仅供仿真。"""
206
+ _spec(position)
207
+ raw = {c: rank(position, c) for c in COMPONENTS}
208
+ total = sum(raw.values()) or 1.0
209
+ return {c: round(raw[c] / total, 4) for c in COMPONENTS}
210
+
211
+
212
+ # --------------------------------------------------------------------------
213
+ # 合成(占位:f(一致性, 位置可预测性, 版本对齐度))
214
+ # --------------------------------------------------------------------------
215
+
216
+ # 生效条件:position 经 _spec 可解析且 COMPONENTS 可用时,components 对每个分量经 .get(c,0.0) 取值并截到 [0,1];若 components 无 .get 或该值不能 float 则该分量值记 0.0,仍按 weights(position) 加权求和返回含 score/values/weights/dominant 的 dict;
217
+ def blend(position: str, components: dict) -> dict:
218
+ """按位置的权重合成单一信任标量。
219
+
220
+ `components` 形如 {"version_alignment": 1.0, "predictability": 0.8,
221
+ "consistency": 0.6};缺省按 0 计。
222
+
223
+ **数值未标定**:这里用序秩当量级,只保证「主导分量对结果影响最大」这
224
+ 一方向性事实。标定属路线图 v0.3。
225
+ """
226
+ s = _spec(position)
227
+ w = weights(position)
228
+ vals = {}
229
+ for c in COMPONENTS:
230
+ try:
231
+ vals[c] = max(0.0, min(1.0, float(components.get(c, 0.0))))
232
+ except (AttributeError, TypeError, ValueError):
233
+ vals[c] = 0.0
234
+ score = sum(w[c] * vals[c] for c in COMPONENTS)
235
+ return {"position": position, "class": s["class"],
236
+ "weights": w, "values": vals, "score": round(score, 4),
237
+ "dominant": s["primary"],
238
+ "note": "权重为占位序秩(未标定);仅方向性结论可信"}
239
+
240
+
241
+ # --------------------------------------------------------------------------
242
+ # 不变量自检(把上轮的三条结构约束落成可执行断言)
243
+ # --------------------------------------------------------------------------
244
+
245
+ # 生效条件:模块级 POSITION_ORDER、COMPONENTS、SPEC、VIEWPOINT、FUNCTIONAL 等常量齐备时,invariants() 逐条自检并返回 {"ok": all(checks[*].ok), "checks": ...};
246
+ def invariants() -> dict:
247
+ """逐条自检结构约束,返回 {ok, checks{name: {ok, detail}}}。"""
248
+ checks = {}
249
+
250
+ # ① 排除唯一:每分量恰被 1 个位置排除 ⇒ 参与度 = 5/6
251
+ part = {c: [p for p in POSITION_ORDER if rank(p, c) > 0] for c in COMPONENTS}
252
+ exc_of = {c: [p for p in POSITION_ORDER if rank(p, c) == 0] for c in COMPONENTS}
253
+ checks["excluded_exactly_once"] = {
254
+ "ok": all(len(exc_of[c]) == 1 for c in COMPONENTS)
255
+ and all(len(part[c]) == len(POSITION_ORDER) - 1 for c in COMPONENTS),
256
+ "detail": {c: {"participants": len(part[c]), "excluded_by": exc_of[c]}
257
+ for c in COMPONENTS}}
258
+
259
+ # ② 排除项只属功能单元,且每分量各被排除一次
260
+ excs = {}
261
+ for p in POSITION_ORDER:
262
+ e = excluded(p)
263
+ if e is None:
264
+ continue
265
+ excs.setdefault(e, []).append(p)
266
+ only_functional = all(is_functional(p)
267
+ for vs in excs.values() for p in vs)
268
+ both = all(len(excs.get(c) or []) == 1 for c in COMPONENTS)
269
+ checks["exclusion_functional_only_once_each"] = {
270
+ "ok": bool(excs) and only_functional and both,
271
+ "detail": {c: excs.get(c, []) for c in COMPONENTS}}
272
+
273
+ # ③ 视角主导 ↔ 功能单元排除 一一配对
274
+ dom_pairs = {} # 分量 → 视角
275
+ for p in POSITION_ORDER:
276
+ if is_viewpoint(p):
277
+ dom_pairs.setdefault(dominant(p), []).append(p)
278
+ pairing = {}
279
+ for p in POSITION_ORDER:
280
+ if not is_functional(p):
281
+ continue
282
+ e = excluded(p)
283
+ if e and len(dom_pairs.get(e) or []) == 1:
284
+ pairing[dom_pairs[e][0]] = p
285
+ checks["viewpoint_dominant_pairs_unit_exclusion"] = {
286
+ "ok": len(pairing) == 3,
287
+ "detail": pairing}
288
+
289
+ # ④ 功能单元恰有一个排除项;视角一个都没有
290
+ checks["functional_excludes_exactly_one"] = {
291
+ "ok": all(excluded(p) is not None for p in POSITION_ORDER
292
+ if is_functional(p))
293
+ and all(excluded(p) is None for p in POSITION_ORDER
294
+ if is_viewpoint(p)),
295
+ "detail": {p: excluded(p) for p in POSITION_ORDER}}
296
+
297
+ # ⑤ 排除项序秩严格最低
298
+ checks["excluded_is_lowest"] = {
299
+ "ok": all(rank(p, excluded(p)) < rank(p, c)
300
+ for p in POSITION_ORDER if excluded(p)
301
+ for c in COMPONENTS if c != excluded(p)),
302
+ "detail": "排除分量序秩 0,严格低于其余分量"}
303
+
304
+ return {"ok": all(c["ok"] for c in checks.values()), "checks": checks}
305
+
306
+
307
+ # --------------------------------------------------------------------------
308
+ # 自描述
309
+ # --------------------------------------------------------------------------
310
+
311
+ # 生效条件:模块级 COMPONENTS、COMPONENT_LABELS、VIEWPOINT、FUNCTIONAL、SPEC、POSITION_ORDER、DAILY 齐备时,返回位置权重矩阵自描述 dict,其中 components 按 COMPONENT_LABELS、positions 按 SPEC、daily_eval 按 DAILY 展开;
312
+ def catalog() -> dict:
313
+ """位置权重矩阵自描述(供 MCP / 文档对照验证)。"""
314
+ return {
315
+ "question": "不同身份,参数偏好不同",
316
+ "components": {c: COMPONENT_LABELS[c] for c in COMPONENTS},
317
+ "classes": {
318
+ VIEWPOINT: "认知视角:3 项都涉及,只标主导,不设零",
319
+ FUNCTIONAL: "功能单元:身份即排除(不猜/不记/不对外)",
320
+ },
321
+ "positions": {p: dict(SPEC[p]) for p in POSITION_ORDER},
322
+ "daily_eval": list(DAILY),
323
+ "meta_reference": [p for p in POSITION_ORDER if p not in DAILY],
324
+ "derivation": {"record": "不猜 → 排除 位置可预测性",
325
+ "output": "不记 → 排除 一致性",
326
+ "sustain": "不对外 → 排除 版本对齐度"},
327
+ "formula": "P_trust = f(一致性, 位置可预测性, 版本对齐度)",
328
+ "honest_boundary": "只声明序,不宣称数值;blend() 权重为占位序秩",
329
+ }
330
+
331
+
332
+ # ==========================================================================
333
+ # 结构重要性重算(maintain.importance)
334
+ # ==========================================================================
335
+ #
336
+ # 与上面的「位置权重矩阵」是**两件事**,不要混:
337
+ # · 上面回答「不同身份偏好哪些信任分量」(序标定,作用于位置);
338
+ # · 下面回答「一个节点在认知图结构里该有多大重要性」(重算,作用于节点)。
339
+ #
340
+ # 三个**可测**分量(对齐计划:按覆盖度、冗余度、验证基底重排):
341
+ # coverage 覆盖度 —— 有多少节点指向/包含它(入度,结构中枢性)
342
+ # redundancy 冗余度 —— 与同层节点内容哈希撞车的比例(越冗余越该降权)
343
+ # basis 验证基底 —— 外部验证档位(formal_proof/compiler > test > measurement > data > other)
344
+ #
345
+ # 纪律:只改 `frontmatter.importance` 与索引快照,**不动正文**(减小 diff 与重写成本);
346
+ # 全流程可预演(apply=False)、可留痕(`_maintain.jsonl`)、可回滚(rollback)。
347
+ # 性能:dry-run 不读任何节点文件(只用索引快照);apply 只写「变动超阈值」的节点。
348
+
349
+ MAINTAIN_LOG = "_maintain.jsonl"
350
+
351
+ #: 验证基底 → 可信权重(枚举来自 nodefile.VERIFICATION_BASIS)
352
+ #: 文科来源一致性档(textbook/public_kb)低于可复现档、高于 other:
353
+ #: 教材/公开知识库是权威二手来源,但不是可复算证据。
354
+ BASIS_TRUST = {
355
+ "formal_proof": 1.00,
356
+ "compiler": 0.90,
357
+ "test": 0.80,
358
+ "measurement": 0.65,
359
+ "textbook": 0.60,
360
+ "data": 0.45,
361
+ "public_kb": 0.40,
362
+ "other": 0.25,
363
+ }
364
+ BASIS_TRUST_MISSING = 0.25
365
+
366
+ #: 三分量合成权重(占位量级,沿用「只声明序」纪律;分量序主导→次要)
367
+ IMPORTANCE_MIX = {"basis": 0.40, "coverage": 0.35, "redundancy": 0.25}
368
+ COV_SAT = 12.0 # 入度饱和点:约 12 条入边即视为覆盖满
369
+ IMPORTANCE_FLOOR = 0.10
370
+ IMPORTANCE_CEIL = 1.00
371
+ IMPORTANCE_PROTECT = 0.70 # ≥ 此值:保护下限(已保护/高危节点不被降破)
372
+ APPLY_DELTA = 0.05 # 变动小于此值不写盘(防 IO 放大)
373
+
374
+
375
+ # 生效条件:e 为可 .get 的映射时,遍历 e.get("edges")(假值视为空)逐项按 dict 的 to/target/node/id 或标量转 str 追加非假值,再取 e.get("subgraph"),若为 dict 取其 "nodes" 否则取 subgraph 本身,且当其为 list/tuple 时追加其中 dict 的 id 或标量转 str 的非假值,返回 out;
376
+ def _targets(e: dict):
377
+ """索引快照里的「出边目标」:edges ∪ subgraph.nodes(兼容 dict/str)。"""
378
+ out = []
379
+ for x in (e.get("edges") or []):
380
+ if isinstance(x, dict):
381
+ t = x.get("to") or x.get("target") or x.get("node") or x.get("id")
382
+ else:
383
+ t = x
384
+ if t:
385
+ out.append(str(t))
386
+ sg = e.get("subgraph")
387
+ raw = sg.get("nodes") if isinstance(sg, dict) else sg
388
+ if isinstance(raw, (list, tuple)):
389
+ for n in raw:
390
+ nid = n.get("id") if isinstance(n, dict) else n
391
+ if nid:
392
+ out.append(str(nid))
393
+ return out
394
+
395
+
396
+ # 生效条件:basis 为 None 时返回 BASIS_TRUST_MISSING;否则把 str(basis).strip().lower() 作为 BASIS_TRUST 的键,命中返回对应权重,未命中(含空串)返回 BASIS_TRUST_MISSING;
397
+ def basis_trust(basis):
398
+ """验证基底 → 可信权重;缺失/未知一律给最低档(不假装可信)。"""
399
+ if basis is None:
400
+ return BASIS_TRUST_MISSING
401
+ return BASIS_TRUST.get(str(basis).strip().lower(), BASIS_TRUST_MISSING)
402
+
403
+
404
+ # 生效条件:cg 的 index(getattr(cg,"index",None) or {})与其 "nodes" 同为真值时,返回以这些节点 id 为键的入度表,仅当 _targets(e) 给出的目标 t 也在 nodes 且 t != nid 时计数 +1;index 或 "nodes" 为假值(None/{})时 nodes 回落 {},直接返回空 dict。
405
+ def coverage_index(cg) -> dict:
406
+ """入度表:nid → 被多少节点指向(覆盖度,O(N) 免读文件)。"""
407
+ nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
408
+ indeg = {nid: 0 for nid in nodes}
409
+ for nid, e in nodes.items():
410
+ for t in _targets(e):
411
+ if t in indeg and t != nid:
412
+ indeg[t] += 1
413
+ return indeg
414
+
415
+
416
+ # 生效条件:cg.index 的 "nodes" 为 dict 时,layer 真值仅处理 e.get("layer")==layer 的节点,layer 假值不过滤;content_hash 为假值(None/空串/0 等)的节点输出 0.0,同 (e.get("layer"), content_hash) 第二次撞车时当前与首次节点均输出 1.0,否则输出 0.0;
417
+ def redundancy_map(cg, layer=None) -> dict:
418
+ """同层内容哈希撞车 → 冗余度 1.0,否则 0.0(精确冗余,O(N) 免读文件)。
419
+
420
+ 诚实边界:这是**精确冗余**(同一层出现完全相同的正文),不是语义近似冗余。
421
+ 语义近似由 `forgetting.redundancy`(bigram 覆盖)在写入侧单独负责。
422
+ """
423
+ nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
424
+ seen, out = {}, {}
425
+ for nid, e in nodes.items():
426
+ if layer and e.get("layer") != layer:
427
+ continue
428
+ h = e.get("content_hash") or ""
429
+ if not h:
430
+ out[nid] = 0.0
431
+ continue
432
+ key = (e.get("layer"), h)
433
+ if key in seen:
434
+ out[nid] = 1.0
435
+ out[seen[key]] = 1.0
436
+ else:
437
+ seen[key] = nid
438
+ out.setdefault(nid, 0.0)
439
+ return out
440
+
441
+
442
+ # 生效条件:cg.index 的 nodes 为 dict 且 entry 非 None 或 nodes.get(nid) 命中时,e 按 entry 优先否则 nodes.get(nid);indeg/red 分别仅在为 None 时回落 coverage_index(cg)/redundancy_map(cg, layer=e.get("layer"))(空容器不回落);按 IMPORTANCE_MIX、COV_SAT 及 e.get("verification_basis") 的 basis_trust 计算 coverage/redundancy/basis 分量,按 bool(e.get("protected")) 选择 IMPORTANCE_PROTECT 或 IMPORTANCE_FLOOR 作下限、IMPORTANCE_CEIL 作上限,返回含 before(e.get("importance",0.5) or 0.5)、after、components、protected 的 dict;entry 与 nodes.get(nid) 均为 None 返回 None;
443
+ def node_importance(cg, nid, indeg=None, red=None, entry=None):
444
+ """单节点结构重要性分解(可审计:给出分量而非只给分)。"""
445
+ nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
446
+ e = entry if entry is not None else nodes.get(nid)
447
+ if e is None:
448
+ return None
449
+ indeg = indeg if indeg is not None else coverage_index(cg)
450
+ red = red if red is not None else redundancy_map(cg, layer=e.get("layer"))
451
+ d = int(indeg.get(nid, 0) or 0)
452
+ cov = min(1.0, math.log1p(d) / math.log1p(COV_SAT))
453
+ rr = max(0.0, min(1.0, float(red.get(nid, 0.0) or 0.0)))
454
+ bt = basis_trust(e.get("verification_basis"))
455
+ score = (IMPORTANCE_MIX["basis"] * bt
456
+ + IMPORTANCE_MIX["coverage"] * cov
457
+ + IMPORTANCE_MIX["redundancy"] * (1.0 - rr))
458
+ protected = bool(e.get("protected"))
459
+ floor = IMPORTANCE_PROTECT if protected else IMPORTANCE_FLOOR
460
+ score = max(floor, min(IMPORTANCE_CEIL, score))
461
+ return {"node_id": nid,
462
+ "before": float(e.get("importance", 0.5) or 0.5),
463
+ "after": round(score, 4),
464
+ "components": {"coverage": round(cov, 4), "redundancy": round(rr, 4),
465
+ "basis_trust": round(bt, 4), "in_degree": d,
466
+ "verification_basis": e.get("verification_basis")},
467
+ "protected": protected,
468
+ "protected_floor": protected}
469
+
470
+
471
+ # 生效条件:给定 cg 且 nodes = cg.index["nodes"] 时按 layer 过滤、limit 为真值才 ids = ids[:int(limit)] 逐节点重算,abs(after-before) < float(min_delta) 记 unchanged;仅 apply=True 才把 frontmatter.importance/importance_source/importance_components 写回(after >= IMPORTANCE_PROTECT 且未 protected 时补写 protected/protection_reason),并向 cg.root 下 append_jsonl(..., MAINTAIN_LOG) 记 batch 后 rebuild_index。
472
+ def recalc(cg, layer=None, limit=None, apply=False, min_delta=APPLY_DELTA,
473
+ actor="maintain", dry_run_samples=10):
474
+ """结构重要性重算:覆盖度 + 冗余度 + 验证基底 → 重排节点重要性。
475
+
476
+ apply=False(默认)只出报表,不写盘(对应计划「可预演」)。
477
+ apply=True 逐节点改写 `frontmatter.importance`,每批写一条 `_maintain.jsonl`
478
+ (before/after/分量/actor),并提供 rollback 反向应用。
479
+ """
480
+ nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
481
+ indeg = coverage_index(cg)
482
+ red = redundancy_map(cg, layer=layer)
483
+ ids = [nid for nid, e in nodes.items()
484
+ if not layer or e.get("layer") == layer]
485
+ ids.sort()
486
+ if limit:
487
+ ids = ids[:int(limit)]
488
+ t0 = time.time()
489
+ planned, changed, unchanged, skipped = [], 0, 0, 0
490
+ before_sum = after_sum = 0.0
491
+ by_layer = {}
492
+ batch = time.strftime("%Y%m%d-%H%M%S")
493
+ samples = []
494
+ for nid in ids:
495
+ info = node_importance(cg, nid, indeg=indeg, red=red)
496
+ if info is None:
497
+ skipped += 1
498
+ continue
499
+ before, after = info["before"], info["after"]
500
+ before_sum += before
501
+ after_sum += after
502
+ lay = (nodes.get(nid) or {}).get("layer") or "?"
503
+ bl = by_layer.setdefault(lay, {"nodes": 0, "changed": 0,
504
+ "avg_before": 0.0, "avg_after": 0.0})
505
+ bl["nodes"] += 1
506
+ if abs(after - before) < float(min_delta):
507
+ unchanged += 1
508
+ continue
509
+ changed += 1
510
+ bl["changed"] += 1
511
+ plan = dict(info)
512
+ plan["batch"] = batch
513
+ plan["delta"] = round(after - before, 4)
514
+ planned.append(plan)
515
+ if len(samples) < int(dry_run_samples):
516
+ samples.append(plan)
517
+ for lay, bl in list(by_layer.items()):
518
+ bl["avg_before"] = 0.0
519
+ bl["avg_after"] = 0.0
520
+ written = 0
521
+ if apply:
522
+ for plan in planned:
523
+ nid = plan["node_id"]
524
+ node = cg.get(nid)
525
+ if not node:
526
+ continue
527
+ fm = node.get("frontmatter") or {}
528
+ fm["importance"] = plan["after"]
529
+ fm["importance_source"] = "recalc"
530
+ fm["importance_components"] = plan["components"]
531
+ if plan["after"] >= IMPORTANCE_PROTECT and not fm.get("protected"):
532
+ fm["protected"] = True
533
+ fm["protection_reason"] = (f"recalc importance={plan['after']:.2f}"
534
+ f"≥{IMPORTANCE_PROTECT}")
535
+ path = os.path.join(cg.root, (nodes.get(nid) or {}).get("path")
536
+ or node.get("path") or f"{nid}.md")
537
+ cg._write_node(nid, path, fm, node.get("content") or "")
538
+ e = nodes.get(nid)
539
+ if e is not None:
540
+ e["importance"] = plan["after"]
541
+ if fm.get("protected"):
542
+ e["protected"] = True
543
+ e["protection_reason"] = fm["protection_reason"]
544
+ rec = {"t": time.time(), "action": "importance", "batch": batch,
545
+ "id": nid, "layer": (e or {}).get("layer"),
546
+ "before": plan["before"], "after": plan["after"],
547
+ "delta": plan["delta"], "components": plan["components"],
548
+ "actor": actor}
549
+ append_jsonl(os.path.join(cg.root, MAINTAIN_LOG), rec)
550
+ written += 1
551
+ if written and hasattr(cg, "rebuild_index"):
552
+ cg.rebuild_index() # 索引与盘面重新对齐,防内存/磁盘分叉
553
+ n = max(1, len(ids))
554
+ return {
555
+ "ok": True, "action": "importance", "dry_run": not apply,
556
+ "batch": batch, "nodes_scanned": len(ids), "changed": changed,
557
+ "unchanged": unchanged, "skipped": skipped, "written": written,
558
+ "min_delta": float(min_delta),
559
+ "avg_before": round(before_sum / n, 4),
560
+ "avg_after": round(after_sum / n, 4),
561
+ "by_layer": {k: {"nodes": v["nodes"], "changed": v["changed"]}
562
+ for k, v in by_layer.items()},
563
+ "samples": samples, "elapsed_ms": int((time.time() - t0) * 1000),
564
+ "log": MAINTAIN_LOG,
565
+ "note": ("dry-run:未写盘;apply=True 才改写 importance"
566
+ if not apply else
567
+ f"已改写 {written} 个节点;回滚见 rollback(batch={batch})"),
568
+ }
569
+
570
+
571
+ # 生效条件:cg.root/MAINTAIN_LOG 可读出 action=="importance" 记录后,entry_ids 为真值时按记录 id 是否在 {str(x) for x in entry_ids} 过滤;否则 batch 为真值时按 r.get("batch")==batch 过滤;否则取最后一条记录的 batch 再按其过滤;无 importance 记录返回 {"ok":False,"error":"no_records","reverted":0},过滤后无记录返回 {"ok":False,"error":"batch_not_found",...};对命中且 cg.get(nid) 为真的记录写回 rec.get("before") 并计数,若 reverted 且 cg 有 rebuild_index 则调用,最后 append_jsonl 写 actor 并返回 {"ok":True,"batch":batch,"reverted":reverted,"ids":ids};
572
+ def rollback(cg, batch=None, entry_ids=None, actor="maintain"):
573
+ """把重要性重算反向应用(bulk 改写的可回滚兑现)。
574
+
575
+ batch 为空则回滚**最近一批**。返回 {ok, reverted, batch, ids}。
576
+ """
577
+ log_path = os.path.join(cg.root, MAINTAIN_LOG)
578
+ records = [r for r in read_jsonl(log_path)
579
+ if r.get("action") == "importance"]
580
+ if not records:
581
+ return {"ok": False, "error": "no_records", "reverted": 0}
582
+ if entry_ids:
583
+ want = {str(x) for x in entry_ids}
584
+ records = [r for r in records if str(r.get("id")) in want]
585
+ elif batch:
586
+ records = [r for r in records if r.get("batch") == batch]
587
+ else:
588
+ batch = records[-1].get("batch")
589
+ records = [r for r in records if r.get("batch") == batch]
590
+ if not records:
591
+ return {"ok": False, "error": "batch_not_found", "batch": batch,
592
+ "reverted": 0}
593
+ nodes = (getattr(cg, "index", None) or {}).get("nodes") or {}
594
+ reverted, ids = 0, []
595
+ # 同一节点多条记录时以最早一条的 before 为准
596
+ for rec in records:
597
+ nid = rec.get("id")
598
+ node = cg.get(nid)
599
+ if not node:
600
+ continue
601
+ fm = node.get("frontmatter") or {}
602
+ fm["importance"] = rec.get("before")
603
+ fm["importance_source"] = "recalc_rollback"
604
+ path = os.path.join(cg.root, (nodes.get(nid) or {}).get("path")
605
+ or node.get("path") or f"{nid}.md")
606
+ cg._write_node(nid, path, fm, node.get("content") or "")
607
+ e = nodes.get(nid)
608
+ if e is not None:
609
+ e["importance"] = rec.get("before")
610
+ reverted += 1
611
+ ids.append(nid)
612
+ if reverted and hasattr(cg, "rebuild_index"):
613
+ cg.rebuild_index()
614
+ append_jsonl(log_path, {"t": time.time(), "action": "importance_rollback",
615
+ "batch": batch, "reverted": reverted, "actor": actor})
616
+ return {"ok": True, "batch": batch, "reverted": reverted, "ids": ids}
617
+
618
+
619
+ # 生效条件:cg.root/MAINTAIN_LOG 可读出 JSONL 记录后,action 为真值时按 r.get("action")==action 过滤,假值不过滤;返回 recs[-int(limit):],其中 limit=0 时 int(0)=0 使切片为 recs[0:] 返回全部而非空;
620
+ def history(cg, limit=100, action=None):
621
+ """维护留痕(最近 limit 条),可按 action 过滤。"""
622
+ recs = list(read_jsonl(os.path.join(cg.root, MAINTAIN_LOG)))
623
+ if action:
624
+ recs = [r for r in recs if r.get("action") == action]
625
625
  return recs[-int(limit):]