@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,338 +1,338 @@
1
- # -*- coding: utf-8 -*-
2
- """comment_gate · 代码符号「条件化注释」抽样闸门(计划四环之环二入口)。
3
-
4
- **换对象不换机制**:复用 refine.py 的闸门范式(分层抽样 → 只读工单 → 人工裁决留痕 →
5
- 通过率放行),把处理对象从「node_ 前缀的记忆节点 CCG 字段缺口」换成
6
- 「code_ 前缀的代码符号注释缺口」。
7
-
8
- 候选判据(唯一、机械、不做语义猜测):**代码节点且正文缺『生效条件』**。
9
- 依 Phase 0 契约,代码节点的生效条件只能来自源码人工声明——缺它即 BLINDSPOT
10
- (缺证据),正是本闸门要治理的对象。落点按使用者裁决 q-0:写进源码、定义行紧邻的
11
- 井号注释(**两个窗口**,见 docs/mdcg/代码评审与条件化注释_契约_v0.1.md §三.2)。
12
-
13
- 本模块只做**候选池 / 工单 / 留痕 / 闸门**:不生成注释、不改任何节点。
14
- 生成与评审方式按 q-2(LLM 生成 + 人工抽检,复用 0.90 闸门)。
15
-
16
- 诚实边界(honest_limits 已随 SPEC 一并输出):
17
- · 分层抽样的**分配**沿用 refine.sample_ids 对 code_ 节点的口径(家族=大域),
18
- 而非对候选池重新分配——故 sample_adequacy 会如实报出样本里的候选产出率;
19
- 若产出率不足,应先扩大 n 或改用候选池重分配(已知待办,不在本片)。
20
- """
21
- from __future__ import annotations
22
-
23
- import json
24
- import os
25
- import time
26
-
27
- from . import codeindex, nodefile, refine
28
-
29
- #: 放行阈值**唯一真源在 refine**(不在此处再定义一份,防口径漂移)
30
- GATE_MIN_PASS_RATE = refine.GATE_MIN_PASS_RATE
31
- SAMPLE_N = refine.SAMPLE_N
32
- #: 本闸门自己的抽样种子(与 refine 的 g6-sample-v1 分离,样本可各自复算)
33
- SAMPLE_SEED = "comment-gate-v1"
34
- #: 代码节点 id 前缀(见 codeindex.node_id = code_ + sha1 前 12 位)
35
- PREFIX = "code_"
36
- LOG_NAME = "_comment_gate.jsonl"
37
-
38
- #: 人工核对清单(与工单逐项对应;对照 refine.SPEC.review_items 的同构位置)
39
- REVIEW_ITEMS = (
40
- "生效条件是否为**功能前置条件**(何种输入/状态下正确),而非索引元条件",
41
- "条件可否被机械复核(有输入/状态判据;不是「常用条件默认省略」)",
42
- "落点是否为源码定义行紧邻的井号注释(两窗口之一),且不覆盖既有实现说明",
43
- "公开仓合规:过第 14 条「内容政策 + 隐私」双清单(补写内容随源码公开)",
44
- )
45
-
46
- SPEC = {
47
- "goal": "为代码符号补写功能级生效条件注释,使其在检索侧可判(不再因缺证据恒 BLINDSPOT)",
48
- "target": "code_ 前缀节点中正文缺『生效条件』者",
49
- "landing": "源码定义行紧邻的井号注释(leading/body 两窗口,物理序合并)",
50
- "review_items": list(REVIEW_ITEMS),
51
- "gate": {"min_pass_rate": GATE_MIN_PASS_RATE, "basis": "人工核对忠实比例",
52
- "rule": "低于阈值不得扩批"},
53
- "honest_limits": [
54
- "本闸门只覆盖已索引的代码节点;未索引的源码不在面内(先跑 index_code)",
55
- "分层分配沿用 code_ 节点口径而非候选池,样本候选产出率由 sample_adequacy 如实上报",
56
- "不生成注释、不改节点:生成与评审属另一环节(LLM 生成 + 人工抽检)",
57
- ],
58
- }
59
-
60
-
61
- # 生效条件:cg 传入后返回 os.path.join(cg.root, LOG_NAME),即以 cg.root 与模块级常量 LOG_NAME 拼接的日志路径(cg 缺 root 属性时抛 AttributeError)。
62
- def _log_path(cg) -> str:
63
- return os.path.join(cg.root, LOG_NAME)
64
-
65
-
66
- # 生效条件:cg 与 nid 传入后,先看 str(nid) 是否以模块级常量 PREFIX 开头(不以则返回 False);以 PREFIX 开头时取 cg.get(nid)(缺节点按空字典)的 content(假值按空串)经 nodefile.ccg_completeness 判断,若 "生效条件" 不在其 required_present 中则返回 True,否则 False。
67
- def is_candidate(cg, nid) -> bool:
68
- """候选判据:代码节点且正文缺『生效条件』(机械判据,唯一)。"""
69
- if not str(nid).startswith(PREFIX):
70
- return False
71
- node = cg.get(nid) or {}
72
- comp = nodefile.ccg_completeness(node.get("content") or "")
73
- return "生效条件" not in comp["required_present"]
74
-
75
-
76
- # 生效条件:cg 与 nid 传入后,从 cg.get(nid)(缺节点按空字典)的 frontmatter(假值按空字典)的 code_ref(假值按空字典)中按 path/name/kind/lineno/end/lang/precise 各键取 ref.get(k)(缺键为 None),返回含 code_ref 与固定 landing_rule、landing_note 字段的落点字典。
77
- def _landing(cg, nid) -> dict:
78
- """工单条目 → 源码落点(坐标 + 落点规则),供补写者直接定位。"""
79
- node = cg.get(nid) or {}
80
- fm = node.get("frontmatter") or {}
81
- ref = fm.get("code_ref") or {}
82
- return {
83
- "code_ref": {k: ref.get(k) for k in
84
- ("path", "name", "kind", "lineno", "end", "lang", "precise")},
85
- "landing_rule": "定义行紧邻上方连续井号注释(leading)或定义行紧邻下方、体首语句之前(body)",
86
- "landing_note": "两窗口按源码物理行序合并;靠前者胜出(契约 §三.2)",
87
- }
88
-
89
-
90
- # 生效条件:cg 与 nid 传入后,取 cg.get(nid)(缺节点按空字典)的 content(假值按空串)算长度与 refine._sha(content)[:16] 作为 source_sha,并结合 refine._entry(cg, nid) 的 layer/tags(tags 假值按空列表)与 nodefile.CCG_MARKS 得出 ccg_missing,最后合并 _landing(cg, nid) 的返回构成工单条目字典。
91
- def _item(cg, nid) -> dict:
92
- node = cg.get(nid) or {}
93
- content = node.get("content") or ""
94
- comp = nodefile.ccg_completeness(content)
95
- e = refine._entry(cg, nid)
96
- it = {
97
- "id": nid, "family": refine._family(cg, nid),
98
- "layer": e.get("layer"), "tags": list(e.get("tags") or []),
99
- "ccg_present": comp["present"],
100
- "ccg_missing": [m for m in nodefile.CCG_MARKS if m not in comp["present"]],
101
- "body_len": len(content),
102
- "source_sha": refine._sha(content)[:16],
103
- }
104
- it.update(_landing(cg, nid))
105
- return it
106
-
107
-
108
- # 生效条件:ids 非空时返回经 is_candidate(cg, i) 过滤后的显式候选与 meta.source='explicit_ids';ids 为空时经 refine._pool(cg, PREFIX) 扫描返回候选与 meta.source='scan'(含 skipped_protected)。
109
- def candidates(cg, ids=None):
110
- """候选池(只读)→ (ids, meta)。"""
111
- if ids:
112
- pool = sorted({str(i) for i in ids if is_candidate(cg, i)})
113
- return pool, {"source": "explicit_ids", "pool": len(pool),
114
- "requested": len(pool), "candidates": len(pool)}
115
- all_ids, protected = refine._pool(cg, PREFIX)
116
- cands = sorted(i for i in all_ids if is_candidate(cg, i))
117
- return cands, {"source": "scan", "prefix": PREFIX, "pool": len(all_ids),
118
- "skipped_protected": protected, "candidates": len(cands)}
119
-
120
-
121
- # 生效条件:seed 为假值(None/空串)时回落模块常量 SAMPLE_SEED,n 仅当为 None 时取 SAMPLE_N、否则 int(n)(n=0 保留 0);ids 为真值时样本取全部候选,为假值(含空列表)时经 refine.sample_ids 抽样后按 is_candidate 过滤。
122
- def plan(x, ids=None, n=None, seed=None) -> dict:
123
- """抽检工单(只读):确定性样本 + 源码落点 + 口径声明 + 样本充分性。"""
124
- cg = refine._as_cg(x)
125
- seed = seed or SAMPLE_SEED
126
- n = SAMPLE_N if n is None else int(n)
127
- cands, cmeta = candidates(cg, ids=ids)
128
- if ids:
129
- sample = sorted(cands)
130
- smeta = {"pool": len(cands), "sampled": len(cands), "families": 0, "strata": {}}
131
- else:
132
- picked, smeta = refine.sample_ids(cg, n=n, seed=seed, prefix=PREFIX)
133
- sample = sorted(i for i in picked if is_candidate(cg, i))
134
- items = [_item(cg, nid) for nid in sample]
135
- strata = {}
136
- for it in items:
137
- s = strata.setdefault(it["family"], {"picked": 0, "missing_fields": {}})
138
- s["picked"] += 1
139
- for m in it["ccg_missing"]:
140
- s["missing_fields"][m] = s["missing_fields"].get(m, 0) + 1
141
- adequacy = {
142
- "sample_of_code_nodes": smeta.get("sampled", len(sample)),
143
- "candidates_in_sample": len(sample),
144
- "candidate_yield": round(len(sample) / float(smeta.get("sampled") or 1), 4),
145
- "note": "分配沿用 code_ 节点口径;产出率不足时应扩大 n 或改候选池重分配",
146
- }
147
- return {
148
- "root": cg.root, "dry_run": True, "readonly": True,
149
- "action": "comment_gate", "op": "maintain",
150
- "prefix": PREFIX, "seed": seed, "requested": n,
151
- "pool": cmeta, "sampled": len(items), "families": len(strata),
152
- "sample": sample, "sample_sha": refine._sha(*sample)[:16] if sample else "",
153
- "strata": strata, "items": items, "worklist": items,
154
- "spec": SPEC, "gate_rule": SPEC["gate"], "sample_adequacy": adequacy,
155
- "note": ("代码注释补写工单(只读):供人工核对补写口径;"
156
- "核对通过率未达阈值前不得扩批。本动作不改任何节点。"),
157
- }
158
-
159
-
160
- # 生效条件:verdicts(None 按 [])中可哈希且属于 okv 字面集合(True/"1"/"true"/"True"/"pass"/"PASS"/"faithful"/"忠实"/"accept"/"ACCEPT")的项计 passed,dict 项在 `v in okv` 处不可哈希先抛 TypeError,故源码里 v.get("verdict") 的计数分支不可达;reviewed 为 0 时 rate=0.0、expand_allowed=False、reason="no_review",否则按 rate 与模块常量 GATE_MIN_PASS_RATE 比较给出 expand_allowed 与 reason。
161
- def _stats(verdicts) -> dict:
162
- """通过率(只认忠实/pass/True),阈值取 refine 唯一真源。"""
163
- vs = list(verdicts or [])
164
- okv = {True, "1", "true", "True", "pass", "PASS", "faithful", "忠实",
165
- "accept", "ACCEPT"}
166
- passed = 0
167
- for v in vs:
168
- if v in okv:
169
- passed += 1
170
- elif isinstance(v, dict) and v.get("verdict") in okv:
171
- passed += 1
172
- reviewed = len(vs)
173
- rate = (passed / float(reviewed)) if reviewed else 0.0
174
- allowed = reviewed > 0 and rate >= GATE_MIN_PASS_RATE
175
- return {"reviewed": reviewed, "passed": passed, "pass_rate": round(rate, 4),
176
- "min_pass_rate": GATE_MIN_PASS_RATE, "expand_allowed": allowed,
177
- "reason": ("" if allowed else
178
- ("no_review" if reviewed == 0 else
179
- "rate %.4f < %.2f" % (rate, GATE_MIN_PASS_RATE)))}
180
-
181
-
182
- # 生效条件:x 传入后经 refine._as_cg 得到 cg,若 cg.principal 非 None 则调用其 require_admin("maintain_comment_gate");随后调用 plan(cg, ids=ids, n=n, seed=seed) 取工单、调用 _stats(verdicts) 取闸门统计,batch 假值回落 time.strftime("%Y%m%d-%H%M%S"),os.makedirs(cg.root, exist_ok=True) 后把含 batch/actor/seed/pool/sample/verdicts/gate 等字段的记录以追加方式写入 _log_path(cg),并返回 ok=True 的留痕结果。
183
- def apply(x, ids=None, n=None, seed=None, verdicts=None, actor=None, note=None,
184
- batch=None) -> dict:
185
- """落抽检批次 + 人工裁决到 _comment_gate.jsonl。**不改写任何节点**。
186
-
187
- 权限**自持在模块内**(与 refine 同档):apply 虽只落留痕,但它决定后续是否放行
188
- **扩批**,故按管理面处理。放在此处而非分发层,是为避免「分发面漏挂一道闸」
189
- 这类易失同步的权限缺口。
190
- """
191
- cg = refine._as_cg(x)
192
- _principal = getattr(cg, "principal", None)
193
- if _principal is not None:
194
- _principal.require_admin("maintain_comment_gate")
195
- p = plan(cg, ids=ids, n=n, seed=seed)
196
- batch = batch or time.strftime("%Y%m%d-%H%M%S")
197
- stats = _stats(verdicts)
198
- rec = {"t": time.time(), "action": "comment_gate", "batch": batch, "actor": actor,
199
- "seed": p["seed"], "requested": p["requested"], "pool": p["pool"],
200
- "sampled": p["sampled"], "sample": p["sample"], "sample_sha": p["sample_sha"],
201
- "sample_adequacy": p["sample_adequacy"], "verdicts": list(verdicts or []),
202
- "gate": stats, "note": note}
203
- os.makedirs(cg.root, exist_ok=True)
204
- with open(_log_path(cg), "a", encoding="utf-8") as f:
205
- f.write(json.dumps(rec, ensure_ascii=False) + chr(10))
206
- return {"ok": True, "action": "comment_gate", "op": "maintain", "batch": batch,
207
- "root": cg.root, "sampled": p["sampled"], "gate": stats, "log": LOG_NAME,
208
- "note": ("抽检留痕已落盘(未改任何节点);" +
209
- ("闸门放行扩批" if stats["expand_allowed"] else
210
- "闸门未放行:" + stats["reason"]))}
211
-
212
-
213
- # 生效条件:x 传入后经 refine._as_cg 得到 cg,读取 _log_path(cg) 且仅当 os.path.exists 为真时逐行解析(空行跳过、json.loads 抛 ValueError 的行跳过),batch 为真时仅保留 batch 字段匹配的记录;recs 为空时返回 expand_allowed=False、reason="no_batch",否则取 recs[-1] 的 verdicts 经 _stats 复算并返回。
214
- def gate(x, batch=None) -> dict:
215
- """扩批闸门:读留痕复算通过率(不写盘)。"""
216
- cg = refine._as_cg(x)
217
- recs = []
218
- path = _log_path(cg)
219
- if os.path.exists(path):
220
- with open(path, encoding="utf-8", errors="replace") as f:
221
- for line in f:
222
- line = line.strip()
223
- if not line:
224
- continue
225
- try:
226
- recs.append(json.loads(line))
227
- except ValueError:
228
- continue
229
- if batch:
230
- recs = [r for r in recs if r.get("batch") == batch]
231
- if not recs:
232
- return {"ok": True, "action": "comment_gate_gate", "op": "maintain",
233
- "root": cg.root, "batch": batch, "batches": 0,
234
- "expand_allowed": False, "reason": "no_batch"}
235
- rec = recs[-1]
236
- stats = _stats(rec.get("verdicts"))
237
- return {"ok": True, "action": "comment_gate_gate", "op": "maintain",
238
- "root": cg.root, "batch": rec.get("batch"),
239
- "batches": len({r.get("batch") for r in recs}), **stats}
240
-
241
-
242
- # 生效条件:root 传入后调用 codeindex.index_dir 扫描(max_files 假值回落 500,max_items 假值回落 2000),对返回 items 的每条 comments(假值按空列表)逐条先 str(c).lstrip("#").strip() 再判断是否以 "生效条件" 开头,全部不以该串开头的项进入候选并返回含 items/errors/stats/examined/candidates 的字典。
243
- def candidates_from_sources(root, patterns=None, max_files=None, max_items=None,
244
- skip_dirs=None):
245
- """**源级**候选枚举(不依赖认知图):扫源码树,筛出注释里缺『生效条件』的符号。
246
-
247
- 为什么需要它(2026-09-17 实测):真实库 2934 条 code_ 节点的生效条件 **100% 是旧 render
248
- 的合成值**,故**图内候选池为 0**;而「源码里哪些符号缺条件注释」是**源侧事实**,
249
- 无须先重索引(重索引会让 2934 条同时失去条件、判 BLINDSPOT)。本入口绕开该一次性代价。
250
-
251
- 判据唯一且机械:符号的 **井号注释窗口**(leading + body,见 codeindex)中不存在以
252
- 『生效条件』开头的行;只认井号注释、不认 docstring——落点按 q-0 裁决。
253
- """
254
- items, errors, stats = codeindex.index_dir(
255
- root, patterns=patterns, max_files=int(max_files or 500),
256
- max_items=int(max_items or 2000), skip_dirs=skip_dirs)
257
- cands = []
258
- for it in items:
259
- has = any(str(c).lstrip("#").strip().startswith("生效条件")
260
- for c in (it.get("comments") or []))
261
- if not has:
262
- cands.append(it)
263
- return {"root": root, "items": cands, "errors": errors, "stats": stats,
264
- "examined": len(items), "candidates": len(cands),
265
- "note": ("源级枚举:判据=井号注释窗口内无『生效条件』行;"
266
- "不含图内节点状态,故不受存量渲染影响")}
267
-
268
-
269
- # 生效条件:it 传入后取 it.get("path")(假值按空串)按 "/" 分割首段作为 family(首段为空则 family="."),并返回含 id=codeindex.node_id(it)、name/kind、code_ref(path/lineno/end/lang/precise 各缺省 None)、comments(假值按空列表逐项 str)、以及固定 landing_rule 与 landing_note 的字典。
270
- def _landing_src(it) -> dict:
271
- return {"id": codeindex.node_id(it), "name": it.get("name"),
272
- "kind": it.get("kind"),
273
- "family": (it.get("path") or "").split("/")[0] or ".",
274
- "code_ref": {"path": it.get("path"), "lineno": it.get("lineno"),
275
- "end": it.get("end"), "lang": it.get("lang"),
276
- "precise": it.get("precise")},
277
- "comments": [str(c) for c in (it.get("comments") or [])],
278
- "landing_rule": ("定义行紧邻上方连续井号注释(leading)或定义行紧邻下方、"
279
- "体首语句之前(body)"),
280
- "landing_note": "两窗口按源码物理行序合并;靠前者胜出(契约 §三.2)"}
281
-
282
-
283
- # 生效条件:root 传入后调用 candidates_from_sources(root, patterns=patterns, skip_dirs=skip_dirs, max_files=max_files, max_items=max_items) 得候选,seed 假值回落 SAMPLE_SEED,n 为 None 时取 SAMPLE_N 否则 int(n)(0 保持 0),按 path 首段(空则 ".")分族与 sha(seed, node_id) 排序后做族间确定性轮转取至多 n 项,返回只读源级工单。
284
- def plan_sources(root, n=None, seed=None, patterns=None, skip_dirs=None,
285
- max_files=None, max_items=None) -> dict:
286
- """**源级**工单(只读):确定性抽样 + 源码落点;不依赖认知图、不改任何节点。
287
-
288
- 抽样口径:按大域(顶层目录)**确定性轮转**(族内按 sha(seed,id) 排序)。
289
- 刻意**不复制** refine 的浮点最大余数分配——那是第二份实现,会引入漂移;
290
- 源级候选列表是精确的(无「先抽样再过滤」的口径损失),轮转已给出跨族覆盖。
291
- """
292
- seed = seed or SAMPLE_SEED
293
- n = SAMPLE_N if n is None else int(n)
294
- got = candidates_from_sources(root, patterns=patterns, skip_dirs=skip_dirs,
295
- max_files=max_files, max_items=max_items)
296
- fams = {}
297
- for it in got["items"]:
298
- top = (it.get("path") or "").split("/")[0] or "."
299
- fams.setdefault(top, []).append(it)
300
- pools = {f: len(v) for f, v in fams.items()}
301
- names = sorted(fams)
302
- for f in names:
303
- fams[f].sort(key=lambda it: refine._sha(seed, codeindex.node_id(it)))
304
- picked = []
305
- while len(picked) < n and any(fams[f] for f in names):
306
- for f in names:
307
- if fams[f] and len(picked) < n:
308
- picked.append(fams[f].pop(0))
309
- work = [_landing_src(it) for it in picked]
310
- return {"root": root, "dry_run": True, "readonly": True, "mode": "source_level",
311
- "action": "comment_gate_sources", "op": "maintain",
312
- "seed": seed, "requested": n, "examined": got["examined"],
313
- "candidates": got["candidates"], "sampled": len(work),
314
- "families": len(pools), "strata": pools,
315
- "items": work, "worklist": work, "spec": SPEC,
316
- "scan_errors": list(got["errors"])[:10], "scan_stats": got["stats"],
317
- "gate_rule": SPEC["gate"],
318
- "note": ("源级工单(只读):不依赖认知图、不改任何节点;"
319
- "抽样为按大域的确定性轮转。")}
320
-
321
-
322
- # 生效条件:x 与 action 传入后,action=="comment_gate" 时若 kw.get("apply") 为真则转 apply(x, ids,n,seed,verdicts,actor,note,batch),否则转 plan(x, ids,n,seed);action=="comment_gate_verdict" 时转 gate(x, batch);action 为 "comment_gate_sources" 或 "comment_gate_source_plan" 时以 root=kw.get("root") or getattr(x,"root",None) or str(x) 转 plan_sources(...);其余 action 抛 ValueError。
323
- def run(x, action, **kw) -> dict:
324
- """maintain op 分派入口(与 backfill.run 同形,便于 mcp_server 侧并列分派)。"""
325
- if action == "comment_gate":
326
- if kw.get("apply"):
327
- return apply(x, ids=kw.get("ids"), n=kw.get("n"), seed=kw.get("seed"),
328
- verdicts=kw.get("verdicts"), actor=kw.get("actor"),
329
- note=kw.get("note"), batch=kw.get("batch"))
330
- return plan(x, ids=kw.get("ids"), n=kw.get("n"), seed=kw.get("seed"))
331
- if action == "comment_gate_verdict":
332
- return gate(x, batch=kw.get("batch"))
333
- if action in ("comment_gate_sources", "comment_gate_source_plan"):
334
- root = kw.get("root") or getattr(x, "root", None) or str(x)
335
- return plan_sources(root, n=kw.get("n"), seed=kw.get("seed"),
336
- patterns=kw.get("patterns"), skip_dirs=kw.get("skip_dirs"))
337
- raise ValueError("未知 comment_gate action:%s(允许 comment_gate / "
1
+ # -*- coding: utf-8 -*-
2
+ """comment_gate · 代码符号「条件化注释」抽样闸门(计划四环之环二入口)。
3
+
4
+ **换对象不换机制**:复用 refine.py 的闸门范式(分层抽样 → 只读工单 → 人工裁决留痕 →
5
+ 通过率放行),把处理对象从「node_ 前缀的记忆节点 CCG 字段缺口」换成
6
+ 「code_ 前缀的代码符号注释缺口」。
7
+
8
+ 候选判据(唯一、机械、不做语义猜测):**代码节点且正文缺『生效条件』**。
9
+ 依 Phase 0 契约,代码节点的生效条件只能来自源码人工声明——缺它即 BLINDSPOT
10
+ (缺证据),正是本闸门要治理的对象。落点按使用者裁决 q-0:写进源码、定义行紧邻的
11
+ 井号注释(**两个窗口**,见 docs/mdcg/代码评审与条件化注释_契约_v0.1.md §三.2)。
12
+
13
+ 本模块只做**候选池 / 工单 / 留痕 / 闸门**:不生成注释、不改任何节点。
14
+ 生成与评审方式按 q-2(LLM 生成 + 人工抽检,复用 0.90 闸门)。
15
+
16
+ 诚实边界(honest_limits 已随 SPEC 一并输出):
17
+ · 分层抽样的**分配**沿用 refine.sample_ids 对 code_ 节点的口径(家族=大域),
18
+ 而非对候选池重新分配——故 sample_adequacy 会如实报出样本里的候选产出率;
19
+ 若产出率不足,应先扩大 n 或改用候选池重分配(已知待办,不在本片)。
20
+ """
21
+ from __future__ import annotations
22
+
23
+ import json
24
+ import os
25
+ import time
26
+
27
+ from . import codeindex, nodefile, refine
28
+
29
+ #: 放行阈值**唯一真源在 refine**(不在此处再定义一份,防口径漂移)
30
+ GATE_MIN_PASS_RATE = refine.GATE_MIN_PASS_RATE
31
+ SAMPLE_N = refine.SAMPLE_N
32
+ #: 本闸门自己的抽样种子(与 refine 的 g6-sample-v1 分离,样本可各自复算)
33
+ SAMPLE_SEED = "comment-gate-v1"
34
+ #: 代码节点 id 前缀(见 codeindex.node_id = code_ + sha1 前 12 位)
35
+ PREFIX = "code_"
36
+ LOG_NAME = "_comment_gate.jsonl"
37
+
38
+ #: 人工核对清单(与工单逐项对应;对照 refine.SPEC.review_items 的同构位置)
39
+ REVIEW_ITEMS = (
40
+ "生效条件是否为**功能前置条件**(何种输入/状态下正确),而非索引元条件",
41
+ "条件可否被机械复核(有输入/状态判据;不是「常用条件默认省略」)",
42
+ "落点是否为源码定义行紧邻的井号注释(两窗口之一),且不覆盖既有实现说明",
43
+ "公开仓合规:过第 14 条「内容政策 + 隐私」双清单(补写内容随源码公开)",
44
+ )
45
+
46
+ SPEC = {
47
+ "goal": "为代码符号补写功能级生效条件注释,使其在检索侧可判(不再因缺证据恒 BLINDSPOT)",
48
+ "target": "code_ 前缀节点中正文缺『生效条件』者",
49
+ "landing": "源码定义行紧邻的井号注释(leading/body 两窗口,物理序合并)",
50
+ "review_items": list(REVIEW_ITEMS),
51
+ "gate": {"min_pass_rate": GATE_MIN_PASS_RATE, "basis": "人工核对忠实比例",
52
+ "rule": "低于阈值不得扩批"},
53
+ "honest_limits": [
54
+ "本闸门只覆盖已索引的代码节点;未索引的源码不在面内(先跑 index_code)",
55
+ "分层分配沿用 code_ 节点口径而非候选池,样本候选产出率由 sample_adequacy 如实上报",
56
+ "不生成注释、不改节点:生成与评审属另一环节(LLM 生成 + 人工抽检)",
57
+ ],
58
+ }
59
+
60
+
61
+ # 生效条件:cg 传入后返回 os.path.join(cg.root, LOG_NAME),即以 cg.root 与模块级常量 LOG_NAME 拼接的日志路径(cg 缺 root 属性时抛 AttributeError)。
62
+ def _log_path(cg) -> str:
63
+ return os.path.join(cg.root, LOG_NAME)
64
+
65
+
66
+ # 生效条件:cg 与 nid 传入后,先看 str(nid) 是否以模块级常量 PREFIX 开头(不以则返回 False);以 PREFIX 开头时取 cg.get(nid)(缺节点按空字典)的 content(假值按空串)经 nodefile.ccg_completeness 判断,若 "生效条件" 不在其 required_present 中则返回 True,否则 False。
67
+ def is_candidate(cg, nid) -> bool:
68
+ """候选判据:代码节点且正文缺『生效条件』(机械判据,唯一)。"""
69
+ if not str(nid).startswith(PREFIX):
70
+ return False
71
+ node = cg.get(nid) or {}
72
+ comp = nodefile.ccg_completeness(node.get("content") or "")
73
+ return "生效条件" not in comp["required_present"]
74
+
75
+
76
+ # 生效条件:cg 与 nid 传入后,从 cg.get(nid)(缺节点按空字典)的 frontmatter(假值按空字典)的 code_ref(假值按空字典)中按 path/name/kind/lineno/end/lang/precise 各键取 ref.get(k)(缺键为 None),返回含 code_ref 与固定 landing_rule、landing_note 字段的落点字典。
77
+ def _landing(cg, nid) -> dict:
78
+ """工单条目 → 源码落点(坐标 + 落点规则),供补写者直接定位。"""
79
+ node = cg.get(nid) or {}
80
+ fm = node.get("frontmatter") or {}
81
+ ref = fm.get("code_ref") or {}
82
+ return {
83
+ "code_ref": {k: ref.get(k) for k in
84
+ ("path", "name", "kind", "lineno", "end", "lang", "precise")},
85
+ "landing_rule": "定义行紧邻上方连续井号注释(leading)或定义行紧邻下方、体首语句之前(body)",
86
+ "landing_note": "两窗口按源码物理行序合并;靠前者胜出(契约 §三.2)",
87
+ }
88
+
89
+
90
+ # 生效条件:cg 与 nid 传入后,取 cg.get(nid)(缺节点按空字典)的 content(假值按空串)算长度与 refine._sha(content)[:16] 作为 source_sha,并结合 refine._entry(cg, nid) 的 layer/tags(tags 假值按空列表)与 nodefile.CCG_MARKS 得出 ccg_missing,最后合并 _landing(cg, nid) 的返回构成工单条目字典。
91
+ def _item(cg, nid) -> dict:
92
+ node = cg.get(nid) or {}
93
+ content = node.get("content") or ""
94
+ comp = nodefile.ccg_completeness(content)
95
+ e = refine._entry(cg, nid)
96
+ it = {
97
+ "id": nid, "family": refine._family(cg, nid),
98
+ "layer": e.get("layer"), "tags": list(e.get("tags") or []),
99
+ "ccg_present": comp["present"],
100
+ "ccg_missing": [m for m in nodefile.CCG_MARKS if m not in comp["present"]],
101
+ "body_len": len(content),
102
+ "source_sha": refine._sha(content)[:16],
103
+ }
104
+ it.update(_landing(cg, nid))
105
+ return it
106
+
107
+
108
+ # 生效条件:ids 非空时返回经 is_candidate(cg, i) 过滤后的显式候选与 meta.source='explicit_ids';ids 为空时经 refine._pool(cg, PREFIX) 扫描返回候选与 meta.source='scan'(含 skipped_protected)。
109
+ def candidates(cg, ids=None):
110
+ """候选池(只读)→ (ids, meta)。"""
111
+ if ids:
112
+ pool = sorted({str(i) for i in ids if is_candidate(cg, i)})
113
+ return pool, {"source": "explicit_ids", "pool": len(pool),
114
+ "requested": len(pool), "candidates": len(pool)}
115
+ all_ids, protected = refine._pool(cg, PREFIX)
116
+ cands = sorted(i for i in all_ids if is_candidate(cg, i))
117
+ return cands, {"source": "scan", "prefix": PREFIX, "pool": len(all_ids),
118
+ "skipped_protected": protected, "candidates": len(cands)}
119
+
120
+
121
+ # 生效条件:seed 为假值(None/空串)时回落模块常量 SAMPLE_SEED,n 仅当为 None 时取 SAMPLE_N、否则 int(n)(n=0 保留 0);ids 为真值时样本取全部候选,为假值(含空列表)时经 refine.sample_ids 抽样后按 is_candidate 过滤。
122
+ def plan(x, ids=None, n=None, seed=None) -> dict:
123
+ """抽检工单(只读):确定性样本 + 源码落点 + 口径声明 + 样本充分性。"""
124
+ cg = refine._as_cg(x)
125
+ seed = seed or SAMPLE_SEED
126
+ n = SAMPLE_N if n is None else int(n)
127
+ cands, cmeta = candidates(cg, ids=ids)
128
+ if ids:
129
+ sample = sorted(cands)
130
+ smeta = {"pool": len(cands), "sampled": len(cands), "families": 0, "strata": {}}
131
+ else:
132
+ picked, smeta = refine.sample_ids(cg, n=n, seed=seed, prefix=PREFIX)
133
+ sample = sorted(i for i in picked if is_candidate(cg, i))
134
+ items = [_item(cg, nid) for nid in sample]
135
+ strata = {}
136
+ for it in items:
137
+ s = strata.setdefault(it["family"], {"picked": 0, "missing_fields": {}})
138
+ s["picked"] += 1
139
+ for m in it["ccg_missing"]:
140
+ s["missing_fields"][m] = s["missing_fields"].get(m, 0) + 1
141
+ adequacy = {
142
+ "sample_of_code_nodes": smeta.get("sampled", len(sample)),
143
+ "candidates_in_sample": len(sample),
144
+ "candidate_yield": round(len(sample) / float(smeta.get("sampled") or 1), 4),
145
+ "note": "分配沿用 code_ 节点口径;产出率不足时应扩大 n 或改候选池重分配",
146
+ }
147
+ return {
148
+ "root": cg.root, "dry_run": True, "readonly": True,
149
+ "action": "comment_gate", "op": "maintain",
150
+ "prefix": PREFIX, "seed": seed, "requested": n,
151
+ "pool": cmeta, "sampled": len(items), "families": len(strata),
152
+ "sample": sample, "sample_sha": refine._sha(*sample)[:16] if sample else "",
153
+ "strata": strata, "items": items, "worklist": items,
154
+ "spec": SPEC, "gate_rule": SPEC["gate"], "sample_adequacy": adequacy,
155
+ "note": ("代码注释补写工单(只读):供人工核对补写口径;"
156
+ "核对通过率未达阈值前不得扩批。本动作不改任何节点。"),
157
+ }
158
+
159
+
160
+ # 生效条件:verdicts(None 按 [])中可哈希且属于 okv 字面集合(True/"1"/"true"/"True"/"pass"/"PASS"/"faithful"/"忠实"/"accept"/"ACCEPT")的项计 passed,dict 项在 `v in okv` 处不可哈希先抛 TypeError,故源码里 v.get("verdict") 的计数分支不可达;reviewed 为 0 时 rate=0.0、expand_allowed=False、reason="no_review",否则按 rate 与模块常量 GATE_MIN_PASS_RATE 比较给出 expand_allowed 与 reason。
161
+ def _stats(verdicts) -> dict:
162
+ """通过率(只认忠实/pass/True),阈值取 refine 唯一真源。"""
163
+ vs = list(verdicts or [])
164
+ okv = {True, "1", "true", "True", "pass", "PASS", "faithful", "忠实",
165
+ "accept", "ACCEPT"}
166
+ passed = 0
167
+ for v in vs:
168
+ if v in okv:
169
+ passed += 1
170
+ elif isinstance(v, dict) and v.get("verdict") in okv:
171
+ passed += 1
172
+ reviewed = len(vs)
173
+ rate = (passed / float(reviewed)) if reviewed else 0.0
174
+ allowed = reviewed > 0 and rate >= GATE_MIN_PASS_RATE
175
+ return {"reviewed": reviewed, "passed": passed, "pass_rate": round(rate, 4),
176
+ "min_pass_rate": GATE_MIN_PASS_RATE, "expand_allowed": allowed,
177
+ "reason": ("" if allowed else
178
+ ("no_review" if reviewed == 0 else
179
+ "rate %.4f < %.2f" % (rate, GATE_MIN_PASS_RATE)))}
180
+
181
+
182
+ # 生效条件:x 传入后经 refine._as_cg 得到 cg,若 cg.principal 非 None 则调用其 require_admin("maintain_comment_gate");随后调用 plan(cg, ids=ids, n=n, seed=seed) 取工单、调用 _stats(verdicts) 取闸门统计,batch 假值回落 time.strftime("%Y%m%d-%H%M%S"),os.makedirs(cg.root, exist_ok=True) 后把含 batch/actor/seed/pool/sample/verdicts/gate 等字段的记录以追加方式写入 _log_path(cg),并返回 ok=True 的留痕结果。
183
+ def apply(x, ids=None, n=None, seed=None, verdicts=None, actor=None, note=None,
184
+ batch=None) -> dict:
185
+ """落抽检批次 + 人工裁决到 _comment_gate.jsonl。**不改写任何节点**。
186
+
187
+ 权限**自持在模块内**(与 refine 同档):apply 虽只落留痕,但它决定后续是否放行
188
+ **扩批**,故按管理面处理。放在此处而非分发层,是为避免「分发面漏挂一道闸」
189
+ 这类易失同步的权限缺口。
190
+ """
191
+ cg = refine._as_cg(x)
192
+ _principal = getattr(cg, "principal", None)
193
+ if _principal is not None:
194
+ _principal.require_admin("maintain_comment_gate")
195
+ p = plan(cg, ids=ids, n=n, seed=seed)
196
+ batch = batch or time.strftime("%Y%m%d-%H%M%S")
197
+ stats = _stats(verdicts)
198
+ rec = {"t": time.time(), "action": "comment_gate", "batch": batch, "actor": actor,
199
+ "seed": p["seed"], "requested": p["requested"], "pool": p["pool"],
200
+ "sampled": p["sampled"], "sample": p["sample"], "sample_sha": p["sample_sha"],
201
+ "sample_adequacy": p["sample_adequacy"], "verdicts": list(verdicts or []),
202
+ "gate": stats, "note": note}
203
+ os.makedirs(cg.root, exist_ok=True)
204
+ with open(_log_path(cg), "a", encoding="utf-8") as f:
205
+ f.write(json.dumps(rec, ensure_ascii=False) + chr(10))
206
+ return {"ok": True, "action": "comment_gate", "op": "maintain", "batch": batch,
207
+ "root": cg.root, "sampled": p["sampled"], "gate": stats, "log": LOG_NAME,
208
+ "note": ("抽检留痕已落盘(未改任何节点);" +
209
+ ("闸门放行扩批" if stats["expand_allowed"] else
210
+ "闸门未放行:" + stats["reason"]))}
211
+
212
+
213
+ # 生效条件:x 传入后经 refine._as_cg 得到 cg,读取 _log_path(cg) 且仅当 os.path.exists 为真时逐行解析(空行跳过、json.loads 抛 ValueError 的行跳过),batch 为真时仅保留 batch 字段匹配的记录;recs 为空时返回 expand_allowed=False、reason="no_batch",否则取 recs[-1] 的 verdicts 经 _stats 复算并返回。
214
+ def gate(x, batch=None) -> dict:
215
+ """扩批闸门:读留痕复算通过率(不写盘)。"""
216
+ cg = refine._as_cg(x)
217
+ recs = []
218
+ path = _log_path(cg)
219
+ if os.path.exists(path):
220
+ with open(path, encoding="utf-8", errors="replace") as f:
221
+ for line in f:
222
+ line = line.strip()
223
+ if not line:
224
+ continue
225
+ try:
226
+ recs.append(json.loads(line))
227
+ except ValueError:
228
+ continue
229
+ if batch:
230
+ recs = [r for r in recs if r.get("batch") == batch]
231
+ if not recs:
232
+ return {"ok": True, "action": "comment_gate_gate", "op": "maintain",
233
+ "root": cg.root, "batch": batch, "batches": 0,
234
+ "expand_allowed": False, "reason": "no_batch"}
235
+ rec = recs[-1]
236
+ stats = _stats(rec.get("verdicts"))
237
+ return {"ok": True, "action": "comment_gate_gate", "op": "maintain",
238
+ "root": cg.root, "batch": rec.get("batch"),
239
+ "batches": len({r.get("batch") for r in recs}), **stats}
240
+
241
+
242
+ # 生效条件:root 传入后调用 codeindex.index_dir 扫描(max_files 假值回落 500,max_items 假值回落 2000),对返回 items 的每条 comments(假值按空列表)逐条先 str(c).lstrip("#").strip() 再判断是否以 "生效条件" 开头,全部不以该串开头的项进入候选并返回含 items/errors/stats/examined/candidates 的字典。
243
+ def candidates_from_sources(root, patterns=None, max_files=None, max_items=None,
244
+ skip_dirs=None):
245
+ """**源级**候选枚举(不依赖认知图):扫源码树,筛出注释里缺『生效条件』的符号。
246
+
247
+ 为什么需要它(2026-09-17 实测):真实库 2934 条 code_ 节点的生效条件 **100% 是旧 render
248
+ 的合成值**,故**图内候选池为 0**;而「源码里哪些符号缺条件注释」是**源侧事实**,
249
+ 无须先重索引(重索引会让 2934 条同时失去条件、判 BLINDSPOT)。本入口绕开该一次性代价。
250
+
251
+ 判据唯一且机械:符号的 **井号注释窗口**(leading + body,见 codeindex)中不存在以
252
+ 『生效条件』开头的行;只认井号注释、不认 docstring——落点按 q-0 裁决。
253
+ """
254
+ items, errors, stats = codeindex.index_dir(
255
+ root, patterns=patterns, max_files=int(max_files or 500),
256
+ max_items=int(max_items or 2000), skip_dirs=skip_dirs)
257
+ cands = []
258
+ for it in items:
259
+ has = any(str(c).lstrip("#").strip().startswith("生效条件")
260
+ for c in (it.get("comments") or []))
261
+ if not has:
262
+ cands.append(it)
263
+ return {"root": root, "items": cands, "errors": errors, "stats": stats,
264
+ "examined": len(items), "candidates": len(cands),
265
+ "note": ("源级枚举:判据=井号注释窗口内无『生效条件』行;"
266
+ "不含图内节点状态,故不受存量渲染影响")}
267
+
268
+
269
+ # 生效条件:it 传入后取 it.get("path")(假值按空串)按 "/" 分割首段作为 family(首段为空则 family="."),并返回含 id=codeindex.node_id(it)、name/kind、code_ref(path/lineno/end/lang/precise 各缺省 None)、comments(假值按空列表逐项 str)、以及固定 landing_rule 与 landing_note 的字典。
270
+ def _landing_src(it) -> dict:
271
+ return {"id": codeindex.node_id(it), "name": it.get("name"),
272
+ "kind": it.get("kind"),
273
+ "family": (it.get("path") or "").split("/")[0] or ".",
274
+ "code_ref": {"path": it.get("path"), "lineno": it.get("lineno"),
275
+ "end": it.get("end"), "lang": it.get("lang"),
276
+ "precise": it.get("precise")},
277
+ "comments": [str(c) for c in (it.get("comments") or [])],
278
+ "landing_rule": ("定义行紧邻上方连续井号注释(leading)或定义行紧邻下方、"
279
+ "体首语句之前(body)"),
280
+ "landing_note": "两窗口按源码物理行序合并;靠前者胜出(契约 §三.2)"}
281
+
282
+
283
+ # 生效条件:root 传入后调用 candidates_from_sources(root, patterns=patterns, skip_dirs=skip_dirs, max_files=max_files, max_items=max_items) 得候选,seed 假值回落 SAMPLE_SEED,n 为 None 时取 SAMPLE_N 否则 int(n)(0 保持 0),按 path 首段(空则 ".")分族与 sha(seed, node_id) 排序后做族间确定性轮转取至多 n 项,返回只读源级工单。
284
+ def plan_sources(root, n=None, seed=None, patterns=None, skip_dirs=None,
285
+ max_files=None, max_items=None) -> dict:
286
+ """**源级**工单(只读):确定性抽样 + 源码落点;不依赖认知图、不改任何节点。
287
+
288
+ 抽样口径:按大域(顶层目录)**确定性轮转**(族内按 sha(seed,id) 排序)。
289
+ 刻意**不复制** refine 的浮点最大余数分配——那是第二份实现,会引入漂移;
290
+ 源级候选列表是精确的(无「先抽样再过滤」的口径损失),轮转已给出跨族覆盖。
291
+ """
292
+ seed = seed or SAMPLE_SEED
293
+ n = SAMPLE_N if n is None else int(n)
294
+ got = candidates_from_sources(root, patterns=patterns, skip_dirs=skip_dirs,
295
+ max_files=max_files, max_items=max_items)
296
+ fams = {}
297
+ for it in got["items"]:
298
+ top = (it.get("path") or "").split("/")[0] or "."
299
+ fams.setdefault(top, []).append(it)
300
+ pools = {f: len(v) for f, v in fams.items()}
301
+ names = sorted(fams)
302
+ for f in names:
303
+ fams[f].sort(key=lambda it: refine._sha(seed, codeindex.node_id(it)))
304
+ picked = []
305
+ while len(picked) < n and any(fams[f] for f in names):
306
+ for f in names:
307
+ if fams[f] and len(picked) < n:
308
+ picked.append(fams[f].pop(0))
309
+ work = [_landing_src(it) for it in picked]
310
+ return {"root": root, "dry_run": True, "readonly": True, "mode": "source_level",
311
+ "action": "comment_gate_sources", "op": "maintain",
312
+ "seed": seed, "requested": n, "examined": got["examined"],
313
+ "candidates": got["candidates"], "sampled": len(work),
314
+ "families": len(pools), "strata": pools,
315
+ "items": work, "worklist": work, "spec": SPEC,
316
+ "scan_errors": list(got["errors"])[:10], "scan_stats": got["stats"],
317
+ "gate_rule": SPEC["gate"],
318
+ "note": ("源级工单(只读):不依赖认知图、不改任何节点;"
319
+ "抽样为按大域的确定性轮转。")}
320
+
321
+
322
+ # 生效条件:x 与 action 传入后,action=="comment_gate" 时若 kw.get("apply") 为真则转 apply(x, ids,n,seed,verdicts,actor,note,batch),否则转 plan(x, ids,n,seed);action=="comment_gate_verdict" 时转 gate(x, batch);action 为 "comment_gate_sources" 或 "comment_gate_source_plan" 时以 root=kw.get("root") or getattr(x,"root",None) or str(x) 转 plan_sources(...);其余 action 抛 ValueError。
323
+ def run(x, action, **kw) -> dict:
324
+ """maintain op 分派入口(与 backfill.run 同形,便于 mcp_server 侧并列分派)。"""
325
+ if action == "comment_gate":
326
+ if kw.get("apply"):
327
+ return apply(x, ids=kw.get("ids"), n=kw.get("n"), seed=kw.get("seed"),
328
+ verdicts=kw.get("verdicts"), actor=kw.get("actor"),
329
+ note=kw.get("note"), batch=kw.get("batch"))
330
+ return plan(x, ids=kw.get("ids"), n=kw.get("n"), seed=kw.get("seed"))
331
+ if action == "comment_gate_verdict":
332
+ return gate(x, batch=kw.get("batch"))
333
+ if action in ("comment_gate_sources", "comment_gate_source_plan"):
334
+ root = kw.get("root") or getattr(x, "root", None) or str(x)
335
+ return plan_sources(root, n=kw.get("n"), seed=kw.get("seed"),
336
+ patterns=kw.get("patterns"), skip_dirs=kw.get("skip_dirs"))
337
+ raise ValueError("未知 comment_gate action:%s(允许 comment_gate / "
338
338
  "comment_gate_verdict)" % action)