@furongjun1999/dsh-memory 0.4.7 → 0.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (325) hide show
  1. package/README.md +130 -47
  2. package/codebuddy/CODEBUDDY.md +21 -10
  3. package/codebuddy/README.md +13 -1
  4. package/codebuddy/mcp.json +9 -0
  5. package/docs/GBrain/345/217/257/345/200/237/351/211/264/347/202/271_/347/201/265/346/236/242/350/220/275/347/202/271/344/272/244/346/216/245_20260919.md +169 -0
  6. package/docs/Pi/345/217/257/345/255/246/344/271/240/344/274/230/347/202/271_/347/201/265/346/236/242/345/244/247/350/204/221/346/224/271/350/277/233/344/272/244/346/216/245_20260915.md +144 -0
  7. package/docs/README.md +111 -0
  8. package/docs/discipline/harnesses.yaml +226 -152
  9. package/docs/discipline/templates/full.md.tmpl +61 -58
  10. package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_LoCoMo_/347/201/265/346/236/242_.md +127 -0
  11. package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_LoCoMo_/347/201/265/346/236/242_.png +0 -0
  12. package/docs/eval//347/254/254/344/270/211/346/226/271/351/252/214/350/257/201/346/212/245/345/221/212_/347/201/265/346/236/242_vs_dejavu_/347/273/237/344/270/200/350/257/204/345/210/206_v7.md +202 -0
  13. package/docs/experiments/linkref_backfill/candidates_20260917.json +726 -0
  14. package/docs/experiments/linkref_backfill/candidates_internal_20260917.json +602 -0
  15. package/docs/experiments/linkref_backfill/candidates_internal_v2.json +603 -0
  16. package/docs/experiments/linkref_backfill/candidates_secret_20260917.json +884 -0
  17. package/docs/experiments/linkref_backfill/candidates_secret_v2.json +789 -0
  18. package/docs/experiments/m4-role-probe/census.py +86 -0
  19. package/docs/experiments/m4-role-probe/probe.py +89 -0
  20. package/docs/experiments/mapped_confidence/bench_mapped_conf.py +216 -0
  21. package/docs/experiments/mapped_confidence/post_check.py +75 -0
  22. package/docs/experiments/mapped_confidence/repro_thirdparty_tol.py +83 -0
  23. package/docs/experiments/mapped_confidence/result_mapped_conf.json +215 -0
  24. package/docs/hive//345/244/232/347/253/257harness/351/200/232/344/277/241/345/245/221/347/272/246_v0.1.md +42 -0
  25. package/docs/hive//346/243/200/347/264/242/346/224/266/346/225/233/345/256/236/346/265/213/344/270/216S1b/350/256/276/350/256/241_v0.1.md +43 -0
  26. package/docs/hive//346/243/200/347/264/242/350/267/257/345/276/204/344/270/216/350/256/244/347/237/245/347/273/223/346/236/204/345/245/221/347/272/246_v0.1.md +102 -0
  27. package/docs/hive//347/234/237/345/256/236/345/272/223/347/253/257/345/210/260/347/253/257/345/256/236/346/265/213_S1b/344/270/216/345/217/254/345/233/236/346/235/203/350/241/241_v0.1.md +57 -0
  28. package/docs/hive//347/234/237/345/256/236/345/272/223/347/253/257/345/210/260/347/253/257/345/256/236/346/265/213_S7/345/200/222/346/216/222/345/200/231/351/200/211/345/261/202_v0.1.md +126 -0
  29. package/docs/hive//350/234/202/345/267/242/345/217/214/345/256/236/344/276/213/344/272/222/351/252/214_/350/256/276/350/256/241/345/256/232/347/250/277.md +503 -0
  30. package/docs/{ → hive/}/350/234/202/345/267/242/345/267/245/344/275/234/350/256/260/345/277/206_/351/241/271/347/233/256/350/256/241/345/210/222.md +14 -2
  31. package/docs/mdcg/D_meta_/345/267/245/347/250/213/345/214/226/346/226/271/346/241/210_v0.2.md +216 -0
  32. package/docs/{README → mdcg/README}/350/257/246/347/273/206/347/211/210_v0.4.5.md +631 -625
  33. package/docs/{ → mdcg/}/344/270/273/344/273/243/347/220/206/345/255/220/344/273/243/347/220/206/350/256/260/345/277/206/346/236/266/346/236/204/350/256/276/350/256/241.md +1 -1
  34. package/docs/mdcg//344/273/243/347/240/201/350/257/204/345/256/241/344/270/216/346/235/241/344/273/266/345/214/226/346/263/250/351/207/212_/345/245/221/347/272/246_v0.1.md +82 -0
  35. package/docs/mdcg//345/205/250/345/272/223/344/273/243/347/240/201/350/257/204/345/256/241/344/270/216/346/235/241/344/273/266/345/214/226/346/263/250/351/207/212_/350/256/241/345/210/222_v0.1.md +600 -0
  36. package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +263 -0
  37. package/docs/{ → mdcg/}/345/215/225/345/205/203/350/207/252/346/210/221/351/224/232/347/202/271_/347/263/273/347/273/237/346/217/220/347/244/272/350/257/215/346/240/207/345/207/206_v0.3.md +1 -1
  38. package/docs/mdcg//345/255/220/344/273/243/347/220/206/351/205/215/347/275/256/346/240/207/345/207/206_v0.5.md +236 -0
  39. package/docs/{ → mdcg/}/346/272/220/347/240/201/347/272/247/346/236/266/346/236/204/345/256/241/350/256/241_GPT/346/211/271/350/257/204/345/257/271/347/205/247_v1.0.md +2 -2
  40. package/docs/{ → mdcg/}/347/201/265/346/236/242/344/270/211/345/261/202/346/213/206/345/210/206/350/247/204/345/210/222_v0.1.md +181 -181
  41. package/docs/mdcg//347/201/265/346/236/242/350/256/260/345/277/206/345/212/250/350/257/215/345/215/217/350/256/256_v1.0-draft.md +172 -0
  42. package/docs/mdcg//347/216/257/344/272/214_/347/231/275/347/256/261/345/241/253/345/205/205/346/265/201/346/260/264/347/272/277_v0.1.md +31 -0
  43. package/docs/{ → mdcg/}/347/274/272/345/217/243/345/215/225_P0/346/224/266/345/217/243_v0.1.md +2 -2
  44. package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_G4-G8/347/274/272/345/217/243/350/243/201/345/256/232/345/215/225_v0.1.md +1 -1
  45. package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_/347/264/242/345/274/225/344/270/216/345/267/245/347/250/213/350/247/204/350/214/203/345/214/226_/350/256/241/345/210/222_v0.1.md +4 -4
  46. package/docs/{ → mdcg/}/350/256/260/345/277/206/346/223/215/344/275/234/347/263/273/347/273/237_MdCGOS/344/270/216MCP/346/216/245/345/205/245_v0.1.md +2 -2
  47. package/docs/mdcg//350/267/250/347/253/257/351/252/214/350/257/201/344/270/216/345/220/214/346/255/245/345/215/217/350/256/256_v0.1.md +93 -0
  48. package/docs/plans/GridWorld/346/234/200/345/260/217/351/227/255/347/216/257/350/247/204/346/240/274_v0.1.md +176 -0
  49. package/docs/{ → swarm/}/350/234/202/347/276/244/344/272/222/350/201/224_v0.1.md +3 -3
  50. package/docs/swarm//350/234/202/347/276/244/345/220/214/351/224/231/346/243/200/346/265/213/345/256/236/351/252/214/345/215/217/350/256/256_v0.1.md +242 -0
  51. package/docs/theory//345/215/225/347/272/277/347/250/213/344/270/216/346/263/250/346/204/217/345/212/233/351/233/206/344/270/255_/346/227/240/344/272/211/350/256/256/347/220/206/350/256/272/346/226/207/346/241/243_v1.0.md +129 -0
  52. package/docs/theory//345/271/266/345/217/221/345/277/205/347/204/266/346/200/247/347/220/206/350/256/272_v0.2.md +134 -0
  53. package/docs/theory//346/246/202/345/277/265/345/210/206/345/261/202/345/257/271/351/275/220/350/241/250_v0.1.md +145 -0
  54. package/docs/{ → theory/}/347/220/206/350/256/272_/346/234/272/345/210/266_/344/273/243/347/240/201_/345/256/236/351/252/214_/347/274/272/345/217/243/347/237/251/351/230/265_v0.1.md +6 -6
  55. package/docs/{ → theory/}/347/220/206/350/256/272/344/273/223/346/213/206/345/210/206/344/270/216/347/231/275/347/256/261/347/237/245/350/257/206/345/272/223/345/206/205/350/277/201_v0.1.md +1 -1
  56. package/docs/theory//350/256/244/347/237/245/344/273/243/347/220/206/344/270/216/346/224/266/346/225/233/347/273/223/346/236/204_/346/235/241/344/273/266/350/256/272/351/207/215/346/236/204_v0.1.md +221 -0
  57. package/docs/world_model//344/270/226/347/225/214/346/250/241/345/236/213_/347/245/236/347/273/217/347/275/221/347/273/234/345/272/225/345/261/202/346/236/266/346/236/204_v1.0.md +237 -0
  58. package/docs//345/255/230/347/256/227/344/270/200/344/275/223/346/236/266/346/236/204/345/255/246/344/271/240_/345/244/226/351/203/250/347/220/206/350/256/272/345/257/271/347/205/247/344/270/216/350/267/257/347/272/277/344/272/244/346/216/245_20260916.md +98 -0
  59. package/docs//345/255/230/347/256/227/344/270/200/344/275/223/347/245/236/347/273/217/347/275/221/347/273/234/346/236/266/346/236/204_/346/200/273/347/272/262/344/270/216/344/272/244/346/216/245_20260916.md +109 -0
  60. package/docs//345/267/245/344/275/234/347/272/252/345/276/213_/350/256/244/347/237/245/345/233/276/346/235/241/347/233/256_v1.1.json +434 -405
  61. package/docs//347/201/265/346/236/242/350/207/252/346/210/221/346/224/271/350/277/233/345/267/245/344/275/234/350/256/241/345/210/222_/345/244/226/351/203/250/347/240/224/347/251/266/347/263/273/345/210/227/345/220/270/346/224/266_v1_20260919.md +286 -0
  62. package/docs//347/231/275/347/256/261/345/214/226/347/272/262/351/242/206_/344/270/211/351/241/271/347/233/256/345/255/246/344/271/240/346/200/273/346/236/266/346/236/204/344/270/216Ghidra/344/272/244/346/216/245_20260916.md +104 -0
  63. package/docs//350/256/260/345/277/206/350/257/204/345/256/241/347/263/273/347/273/237_/347/253/213/351/241/271/350/256/276/350/256/241/344/270/216/346/226/275/345/267/245/344/272/244/346/216/245_20260915.md +183 -0
  64. package/dsh/README.md +34 -1
  65. package/dsh/cordis.yml.example +13 -7
  66. package/dsh/hive-mcp-probe.mjs +94 -0
  67. package/dsh/hive-mcp.example.yml +62 -0
  68. package/dsh/update-lingshu.bat +11 -0
  69. package/dsh/update-lingshu.ps1 +337 -0
  70. package/lib/hooks.d.ts +8 -0
  71. package/lib/hooks.js +27 -24
  72. package/lib/index.d.ts +4 -2
  73. package/lib/index.js +29 -6
  74. package/lib/lib/datapath.d.ts +76 -1
  75. package/lib/lib/datapath.js +199 -13
  76. package/lib/lib/mdcg_client.d.ts +6 -3
  77. package/lib/lib/mdcg_client.js +6 -5
  78. package/lib/lib/mutual.js +4 -4
  79. package/lib/lib/prompt_safety.d.ts +48 -0
  80. package/lib/lib/prompt_safety.js +62 -0
  81. package/lib/lib/token_store.js +4 -5
  82. package/md_cg/audit.py +91 -2
  83. package/md_cg/autonomy.py +86 -15
  84. package/md_cg/backfill.py +36 -1
  85. package/md_cg/backfill_bigdomain.py +34 -0
  86. package/md_cg/bench6_arms.py +28 -1
  87. package/md_cg/bench6_common.py +10 -1
  88. package/md_cg/bench6_competitors.py +6 -1
  89. package/md_cg/bench_axis_domain.py +9 -1
  90. package/md_cg/bench_blind_comp.py +7 -1
  91. package/md_cg/bench_en_atoms_public.py +9 -0
  92. package/md_cg/bench_governance.py +348 -0
  93. package/md_cg/bench_lme_zh.py +16 -1
  94. package/md_cg/bench_locomo.py +2 -1
  95. package/md_cg/bench_locomo_zh.py +16 -1
  96. package/md_cg/bench_locomo_zh_public.py +4 -1
  97. package/md_cg/bench_longmem.py +2 -1
  98. package/md_cg/bench_membench.py +37 -6
  99. package/md_cg/bench_p0.py +4 -1
  100. package/md_cg/bench_progressive.py +61 -10
  101. package/md_cg/bench_role_views.py +238 -0
  102. package/md_cg/bench_task_ab.py +8 -1
  103. package/md_cg/bench_task_ab_llm.py +13 -1
  104. package/md_cg/bench_unified_en.py +6 -1
  105. package/md_cg/bench_zh_mad.py +20 -1
  106. package/md_cg/blindspot_tickets.py +123 -0
  107. package/md_cg/branches.py +286 -0
  108. package/md_cg/build_postings.py +73 -0
  109. package/md_cg/ccgc.py +949 -0
  110. package/md_cg/census.py +5 -1
  111. package/md_cg/chain.py +24 -3
  112. package/md_cg/codeindex.py +134 -17
  113. package/md_cg/coldverify.py +265 -0
  114. package/md_cg/comment_gate.py +338 -0
  115. package/md_cg/cond_compose.py +190 -0
  116. package/md_cg/cond_facts.py +155 -0
  117. package/md_cg/cond_template.json +107 -0
  118. package/md_cg/condition_anchor.py +143 -0
  119. package/md_cg/conformance.py +727 -0
  120. package/md_cg/consistency.py +25 -2
  121. package/md_cg/consolidate.py +53 -2
  122. package/md_cg/corpus.py +5 -1
  123. package/md_cg/crosscheck.py +42 -2
  124. package/md_cg/crypto.py +35 -1
  125. package/md_cg/d_meta.py +310 -0
  126. package/md_cg/datapath.py +201 -26
  127. package/md_cg/docindex.py +122 -1
  128. package/md_cg/eval_common.py +35 -6
  129. package/md_cg/evidence.py +27 -1
  130. package/md_cg/evolution.py +21 -1
  131. package/md_cg/export.py +11 -1
  132. package/md_cg/forgetting.py +34 -4
  133. package/md_cg/fsutil.py +81 -2
  134. package/md_cg/hotcache.py +214 -0
  135. package/md_cg/hyperedge.py +251 -0
  136. package/md_cg/identity.py +20 -3
  137. package/md_cg/insight.py +19 -3
  138. package/md_cg/lexicon/build_cedict_en_zh.py +9 -0
  139. package/md_cg/lexicon/build_standard_en.py +171 -168
  140. package/md_cg/lexicon/expand_en_zh.py +6 -0
  141. package/md_cg/lifecycle.py +273 -0
  142. package/md_cg/linkref.py +281 -0
  143. package/md_cg/links.py +29 -1
  144. package/md_cg/mcp_server.py +894 -168
  145. package/md_cg/md_whitebox.py +53 -1
  146. package/md_cg/mdcg.py +1205 -41
  147. package/md_cg/mdcos.py +1060 -76
  148. package/md_cg/metacognition.py +39 -4
  149. package/md_cg/migrate.py +4 -0
  150. package/md_cg/migrate_aeis.py +221 -213
  151. package/md_cg/migrate_roleplay.py +8 -0
  152. package/md_cg/migrate_wisdom_graph.py +14 -1
  153. package/md_cg/mreview/__init__.py +25 -0
  154. package/md_cg/mreview/__main__.py +110 -0
  155. package/md_cg/mreview/bundle.py +178 -0
  156. package/md_cg/mreview/candidates.py +262 -0
  157. package/md_cg/mreview/govern.py +694 -0
  158. package/md_cg/mreview/locate.py +939 -0
  159. package/md_cg/mreview/pipeline.py +729 -0
  160. package/md_cg/mreview/rules/duplication.json +21 -0
  161. package/md_cg/mreview/rules/field_coverage.json +54 -0
  162. package/md_cg/mreview/rules/source_license.json +21 -0
  163. package/md_cg/mreview/rules/template_flow.json +21 -0
  164. package/md_cg/mreview/ruleset.py +253 -0
  165. package/md_cg/nodefile.py +269 -1
  166. package/md_cg/pooling.py +23 -1
  167. package/md_cg/postings.py +298 -0
  168. package/md_cg/predict.py +113 -15
  169. package/md_cg/progressive.py +3 -0
  170. package/md_cg/protect.py +18 -5
  171. package/md_cg/protocol.py +372 -0
  172. package/md_cg/provenance.py +262 -0
  173. package/md_cg/reach.py +453 -0
  174. package/md_cg/refindex.py +88 -4
  175. package/md_cg/refine.py +20 -1
  176. package/md_cg/roleviews.py +89 -0
  177. package/md_cg/routing.py +76 -0
  178. package/md_cg/scrub.py +68 -3
  179. package/md_cg/security.py +26 -1
  180. package/md_cg/self_state.py +65 -2
  181. package/md_cg/selfreport.py +151 -0
  182. package/md_cg/semantic/canonical.py +5 -0
  183. package/md_cg/semantic/en_normalizer.py +364 -295
  184. package/md_cg/semantic/zh_en_atoms.py +139 -136
  185. package/md_cg/signer.py +41 -1
  186. package/md_cg/sources.py +583 -547
  187. package/md_cg/statushdr.py +179 -0
  188. package/md_cg/stg.py +59 -18
  189. package/md_cg/subgraph.py +23 -0
  190. package/md_cg/sustain.py +74 -1
  191. package/md_cg/tasks.py +471 -0
  192. package/md_cg/test_action_derive.py +203 -0
  193. package/md_cg/test_audit_rotate.py +270 -0
  194. package/md_cg/test_autonomy.py +26 -0
  195. package/md_cg/test_bench_governance.py +102 -0
  196. package/md_cg/test_blindspot_tickets.py +166 -0
  197. package/md_cg/test_branches.py +249 -0
  198. package/md_cg/test_ccg_perturb.py +1 -1
  199. package/md_cg/test_ccgc.py +433 -0
  200. package/md_cg/test_codeindex.py +338 -0
  201. package/md_cg/test_comment_gate.py +187 -0
  202. package/md_cg/test_cond_compose_anchors.py +76 -0
  203. package/md_cg/test_condition_anchor.py +82 -0
  204. package/md_cg/test_conformance.py +343 -0
  205. package/md_cg/test_d_meta.py +412 -0
  206. package/md_cg/test_datapath_root.py +188 -0
  207. package/md_cg/test_en_pipeline.py +24 -0
  208. package/md_cg/test_gain_gate.py +47 -1
  209. package/md_cg/test_health_scale.py +173 -0
  210. package/md_cg/test_hot_cold.py +187 -0
  211. package/md_cg/test_hyperedge.py +245 -0
  212. package/md_cg/test_identity_attribution.py +6 -0
  213. package/md_cg/test_index_durability.py +224 -0
  214. package/md_cg/test_lifecycle.py +309 -0
  215. package/md_cg/test_linkref.py +306 -0
  216. package/md_cg/test_md_access_parity.py +15 -3
  217. package/md_cg/test_mr_m1.py +769 -0
  218. package/md_cg/test_mr_m2.py +587 -0
  219. package/md_cg/test_mr_m3.py +710 -0
  220. package/md_cg/test_mr_m4.py +485 -0
  221. package/md_cg/test_p1.py +1 -1
  222. package/md_cg/test_p11_consistency.py +1 -1
  223. package/md_cg/test_p12_metacognition.py +2 -2
  224. package/md_cg/test_p16_self_state.py +1 -1
  225. package/md_cg/test_p26_refindex.py +50 -21
  226. package/md_cg/test_p27_docindex.py +258 -4
  227. package/md_cg/test_p28_refcheck.py +1 -1
  228. package/md_cg/test_p29_session_ingest_export.py +1 -1
  229. package/md_cg/test_p2_mcp.py +7 -1
  230. package/md_cg/test_p31_insight.py +24 -0
  231. package/md_cg/test_p38_contextualize.py +1 -1
  232. package/md_cg/test_p39_vision_evidence.py +1 -1
  233. package/md_cg/test_p40_refine_worklist.py +1 -1
  234. package/md_cg/test_p41_evolve_patrol.py +1 -1
  235. package/md_cg/test_p42_provenance.py +1 -1
  236. package/md_cg/test_p43_pooling.py +41 -13
  237. package/md_cg/test_p44_md_whitebox.py +14 -1
  238. package/md_cg/test_protocol.py +243 -0
  239. package/md_cg/test_reach.py +378 -0
  240. package/md_cg/test_reach_keys.py +201 -0
  241. package/md_cg/test_reach_meta_exits.py +145 -0
  242. package/md_cg/test_read_clip.py +141 -0
  243. package/md_cg/test_retr_s1.py +340 -0
  244. package/md_cg/test_retr_s1b.py +209 -0
  245. package/md_cg/test_retr_s3.py +194 -0
  246. package/md_cg/test_retr_s4.py +163 -0
  247. package/md_cg/test_retr_s5.py +200 -0
  248. package/md_cg/test_retr_s6.py +157 -0
  249. package/md_cg/test_retr_s7.py +385 -0
  250. package/md_cg/test_retr_s8_time.py +316 -0
  251. package/md_cg/test_retr_s9_edges.py +286 -0
  252. package/md_cg/test_retr_s9_entity_ctx.py +175 -0
  253. package/md_cg/test_review_conformance.py +367 -0
  254. package/md_cg/test_role_views.py +354 -0
  255. package/md_cg/test_tasks.py +409 -0
  256. package/md_cg/test_tool_face.py +189 -0
  257. package/md_cg/test_trust.py +361 -0
  258. package/md_cg/test_twophase.py +286 -0
  259. package/md_cg/test_units_poll.py +71 -0
  260. package/md_cg/test_v14_fixes.py +397 -0
  261. package/md_cg/test_validity_filter.py +280 -0
  262. package/md_cg/test_wisdom_md_store.py +7 -3
  263. package/md_cg/test_writepipe.py +214 -0
  264. package/md_cg/theory.py +17 -2
  265. package/md_cg/tokens.py +134 -12
  266. package/md_cg/tool_face.py +261 -0
  267. package/md_cg/trust.py +943 -0
  268. package/md_cg/twophase.py +232 -0
  269. package/md_cg/units.py +665 -0
  270. package/md_cg/vision_evidence.py +25 -2
  271. package/md_cg/weights.py +25 -2
  272. package/md_cg/whitebox.py +33 -2
  273. package/md_cg/whitebox_kb/data/verify_cache.json +21233 -360
  274. package/md_cg/whitebox_kb/data/verify_savings.jsonl +5124 -0
  275. package/md_cg/whitebox_kb/wisdom/audit_log/chain_heat.json +10 -10
  276. package/md_cg/whitebox_kb/wisdom/code_compose.py +113 -6
  277. package/md_cg/whitebox_kb/wisdom/code_solidified.json +1 -1
  278. package/md_cg/whitebox_kb/wisdom/verifier.py +340 -55
  279. package/md_cg/whitebox_kb/wisdom/wisdom-book-cloud.db +0 -0
  280. package/md_cg/writelimit.py +37 -7
  281. package/md_cg/writepipe.py +543 -0
  282. package/package.json +2 -2
  283. package/skills/skills/designer-perspective/scripts/__pycache__/designer.cpython-310.pyc +0 -0
  284. package/skills/skills/designer-perspective/scripts/designer.py +17 -1
  285. package/skills/skills/designer-perspective/tests/selftest.py +3 -1
  286. package/src/hooks.ts +27 -22
  287. package/src/index.ts +33 -6
  288. package/src/lib/datapath.ts +211 -13
  289. package/src/lib/mdcg_client.ts +12 -8
  290. package/src/lib/mutual.ts +411 -411
  291. package/src/lib/prompt_safety.ts +62 -0
  292. package/src/lib/token_store.ts +4 -5
  293. package/zcode/AGENTS.md +21 -10
  294. package/zcode/README.md +4 -0
  295. package/docs//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +0 -221
  296. /package/docs/{AGI → eval/AGI}/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v1.0.md" +0 -0
  297. /package/docs/{AGI → eval/AGI}/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_md_cg_v2.0.md" +0 -0
  298. /package/docs/{ → eval/}/345/256/236/351/252/214/346/226/271/346/241/210_/345/255/246/344/271/240/351/227/255/347/216/257AB/344/270/216/346/250/252/350/257/204_v1.0.md" +0 -0
  299. /package/docs/{ → eval/}/346/250/252/350/257/204_/345/205/255/345/256/266100/351/242/230/344/270/255/350/213/261/345/217/214/346/237/245_v1.0.md" +0 -0
  300. /package/docs/{guardrail-charter.md → mdcg/guardrail-charter.md} +0 -0
  301. /package/docs/{lingshu_tutorial.html → mdcg/lingshu_tutorial.html} +0 -0
  302. /package/docs/{memory-assessment.html → mdcg/memory-assessment.html} +0 -0
  303. /package/docs/{memory_score.html → mdcg/memory_score.html} +0 -0
  304. /package/docs/{memory_score.png → mdcg/memory_score.png} +0 -0
  305. /package/docs/{release_v0.3.0.md → mdcg/release_v0.3.0.md} +0 -0
  306. /package/docs/{release_v0.4.5.md → mdcg/release_v0.4.5.md} +0 -0
  307. /package/docs/{tool_table_v0.3.0.md → mdcg/tool_table_v0.3.0.md} +0 -0
  308. /package/docs/{ → mdcg/}/344/273/244/347/211/214/344/270/216/350/247/222/350/211/262/346/235/203/350/201/214/345/210/206/347/246/273_v0.1.md" +0 -0
  309. /package/docs/{ → mdcg/}/347/201/265/346/236/24282/345/267/245/345/205/267_/345/212/237/350/203/275/346/225/264/347/220/206/344/270/216/350/277/201/347/247/273/346/230/240/345/260/204_v0.1.md" +0 -0
  310. /package/docs/{ → mdcg/}/347/201/265/346/236/242MCP/345/267/245/345/205/267/346/200/273/350/241/250_v3.4.md" +0 -0
  311. /package/docs/{ → mdcg/}/347/201/265/346/236/242_/350/207/252/346/210/221/345/261/202/345/256/232/344/271/211.md" +0 -0
  312. /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_MD/347/233/256/345/275/225/346/226/271/346/241/210_v0.1.md" +0 -0
  313. /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276_/346/235/241/344/273/266/347/251/272/351/227/264/345/220/210/346/210/220/344/270/216/347/224/237/346/225/210/346/235/241/344/273/266/345/217/243/345/276/204_v0.1.md" +0 -0
  314. /package/docs/{ → mdcg/}/350/256/244/347/237/245/345/233/276/344/275/234/344/270/272/350/256/260/345/277/206/346/223/215/344/275/234/347/263/273/347/273/237_/350/257/204/344/274/260/344/270/216/350/267/257/347/272/277_v0.1.md" +0 -0
  315. /package/docs/{ → plans/}/345/221/275/345/220/215/346/262/273/347/220/206_/351/241/271/347/233/256/350/256/241/345/210/222.md" +0 -0
  316. /package/docs/{ → plans/}/347/237/245/350/257/206/345/233/276/350/260/261/351/241/271/347/233/256_/344/272/244/346/216/245/346/226/207/346/241/243_20260914.md" +0 -0
  317. /package/docs/{ → swarm/}/350/234/202/347/276/244/345/244/232/346/231/272/350/203/275/344/275/223_/344/275/277/347/224/250/346/212/245/345/221/212_20260913.md" +0 -0
  318. /package/docs/{ → swarm/}/350/234/202/347/276/244/345/244/232/346/231/272/350/203/275/344/275/223_/345/212/237/350/203/275/350/257/264/346/230/216_v0.6.md" +0 -0
  319. /package/docs/{ → swarm/}/350/234/202/347/276/244/347/233/262/345/214/272/346/240/207/350/256/260_v1.0.md" +0 -0
  320. /package/docs/{ → theory/}/344/277/241/346/201/257/345/267/256/344/270/272/344/273/200/344/271/210/345/277/205/347/204/266/345/255/230/345/234/250/344/270/224/350/207/252/347/204/266/346/211/251/345/244/247.md" +0 -0
  321. /package/docs/{ → theory/}/346/231/272/350/203/275/347/232/204/345/205/254/347/220/206/345/214/226/345/237/272/347/237/263.md" +0 -0
  322. /package/docs/{ → theory/}/346/231/272/350/203/275/347/232/204/350/256/244/347/237/245/350/277/207/347/250/213.md" +0 -0
  323. /package/docs/{ → theory/}/346/231/272/350/203/275/350/256/2723.4.md" +0 -0
  324. /package/docs/{ → theory/}/347/231/275/347/256/261/346/231/272/350/203/275/346/230/257/344/273/200/344/271/210/357/274/237.md" +0 -0
  325. /package/docs/{ → theory/}/347/231/275/347/256/261/346/231/272/350/203/275/347/263/273/345/210/227/302/267/347/254/254/344/272/224/347/257/207/357/274/232/350/256/251AI/347/234/237/346/255/243/350/243/205/344/270/212/350/256/260/345/277/206.md" +0 -0
package/md_cg/backfill.py CHANGED
@@ -127,11 +127,13 @@ CAP_RULES = OrderedDict(
127
127
 
128
128
  # ---- 通用工具 ------------------------------------------------------------
129
129
 
130
+ # 生效条件:x 为 str 时返回 MdCGOS(x),否则原样返回 x。
130
131
  def _as_cg(x):
131
132
  """接受 root 路径或已构造的 cg 实例——保持密级隔离与密钥上下文。"""
132
133
  return MdCGOS(x) if isinstance(x, str) else x
133
134
 
134
135
 
136
+ # 生效条件:v 为 list/tuple 时返回分号连接的非空元素文本;v 为 None 或空串时返回 "";否则返回 str(v).strip()(v 为 0 或 False 走此支返回 "0"/"False")。
135
137
  def _as_text(v) -> str:
136
138
  if isinstance(v, (list, tuple)):
137
139
  return ";".join(str(x).strip() for x in v if str(x).strip())
@@ -140,12 +142,14 @@ def _as_text(v) -> str:
140
142
  return str(v).strip()
141
143
 
142
144
 
145
+ # 生效条件:fm 为假值时按 {} 处理,state_attributes.comment 为 dict 时返回该 dict,否则返回 {}。
143
146
  def _comment(fm: dict) -> dict:
144
147
  st = (fm or {}).get("state_attributes")
145
148
  c = st.get("comment") if isinstance(st, dict) else None
146
149
  return c if isinstance(c, dict) else {}
147
150
 
148
151
 
152
+ # 生效条件:fm 的 state_attributes 为 dict 且其下 comment 为 dict 时原样返回该 comment;否则创建并返回空 comment dict(state_attributes 非 dict 时置 fm["state_attributes"]={},comment 非 dict 时置 st["comment"]={})。
149
153
  def _ensure_comment(fm: dict) -> dict:
150
154
  st = fm.get("state_attributes")
151
155
  if not isinstance(st, dict):
@@ -158,10 +162,12 @@ def _ensure_comment(fm: dict) -> dict:
158
162
  return c
159
163
 
160
164
 
165
+ # 生效条件:e 的 id 为真值时返回 id,否则返回 e 的 path 基名去掉最后 3 个字符(path 为假值时基名为空,结果空串)。
161
166
  def _node_id(e: dict) -> str:
162
167
  return e.get("id") or os.path.basename(e.get("path") or "")[:-3]
163
168
 
164
169
 
170
+ # 生效条件:fm 的 condition_space 四槽齐全时返回 nodefile.condition_space_text 合成文本,否则返回空串。
165
171
  def _condition_text(fm: dict) -> str:
166
172
  """→ 条件空间四槽合成的生效条件声明;四槽不齐 → ""(不冒充)。
167
173
 
@@ -172,14 +178,17 @@ def _condition_text(fm: dict) -> str:
172
178
  return nodefile.condition_space_text((fm or {}).get("condition_space"))
173
179
 
174
180
 
181
+ # 生效条件:s 为真值时返回其 sha1 前 12 位,s 为假值(None/空串等)时对空串取 sha1 前 12 位。
175
182
  def _sha(s: str) -> str:
176
183
  return hashlib.sha1((s or "").encode("utf-8")).hexdigest()[:12]
177
184
 
178
185
 
186
+ # 生效条件:batch 与 nid 经 f-string 拼接后取 sha1 前 12 位;两者为 None 会字符串化为 "None"。
179
187
  def _entry_id(batch: str, nid: str) -> str:
180
188
  return hashlib.sha1(f"{batch}|{nid}".encode("utf-8")).hexdigest()[:12]
181
189
 
182
190
 
191
+ # 生效条件:content 中 strip 后以 # 开头且去掉 # 与空白后、全角或半角冒号前首段等于 field 的整行被删除,其余行保留并 join。
183
192
  def _remove_ccg_line(content: str, field: str) -> str:
184
193
  """删掉 `# <字段>:…` 整行(回滚用)。"""
185
194
  keep = []
@@ -192,12 +201,14 @@ def _remove_ccg_line(content: str, field: str) -> str:
192
201
  return "\n".join(keep)
193
202
 
194
203
 
204
+ # 生效条件:cg.root 与模块级常量 BACKFILL_LOG 拼接为返回路径。
195
205
  def _log_path(cg) -> str:
196
206
  return os.path.join(cg.root, BACKFILL_LOG)
197
207
 
198
208
 
199
209
  # ---- 字段推导(唯一入口:只搬运已声明的证据) -----------------------------
200
210
 
211
+ # 生效条件:fm 与 content 给定时,仅对 content 中尚无对应 CCG 行的字段(功能名/生效条件/子功能/执行/验证方式/不适用条件)从 fm 的已有声明(state_attributes.comment、frontmatter、verification_basis、或形参 basis_text)取值,值非空且非占位文本才写入 out,假值不写、占位文本只把字段名追加进 placeholder_out(未传该形参时用临时列表)。
201
212
  def derive_fields(fm: dict, content: str, basis_text: str = None,
202
213
  placeholder_out: list = None) -> dict:
203
214
  """按**已有声明**推导可回填字段 → `{field: (value, basis)}`。
@@ -213,6 +224,7 @@ def derive_fields(fm: dict, content: str, basis_text: str = None,
213
224
  ph = placeholder_out if placeholder_out is not None else []
214
225
  out = {}
215
226
 
227
+ # 生效条件:field 与 basis 在 value 为真值且 nodefile.is_placeholder_text(value) 为假时写入 out;value 为假值不写入;value 为占位文本时仅把 field 记入 ph。
216
228
  def _put(field, value, basis):
217
229
  """有值且非占位标记才写出;占位值只记名,绝不渲染成事实。"""
218
230
  if not value:
@@ -267,6 +279,7 @@ def derive_fields(fm: dict, content: str, basis_text: str = None,
267
279
 
268
280
  # ---- 节点筛选 ------------------------------------------------------------
269
281
 
282
+ # 生效条件:cg 无 _readable 可调用时返回 True;有可调用时返回 bool(fn(e)),fn(e) 抛异常时返回 False。
270
283
  def _readable_guard(cg, e) -> bool:
271
284
  fn = getattr(cg, "_readable", None)
272
285
  if not callable(fn):
@@ -277,6 +290,7 @@ def _readable_guard(cg, e) -> bool:
277
290
  return False
278
291
 
279
292
 
293
+ # 生效条件:仅当 cg 对 e 读出的 fm 非 None、content 未被 crypto.is_encrypted、e['layer'] 不在 SKIP_LAYERS 且 fm.get('tags') 无命中 SKIP_TAGS、ccg_completeness(content)['complete'] 为假时才继续——derive_fields(受 basis_text 影响)过滤掉 content 已有 CCG 行的可写字段为空时按 placeholder_out 是否非空返回 ('placeholder'/'unfillable', None),非空时返回 ('', item)(item 的 id 取 nid、class 依 undeducible 是否为空取 'backfillable' 或 'partial');上述四个前置不满足时依次返回 ('unreadable'/'locked'/'derived'/'present', None)。
280
294
  def _classify(cg, e, nid, basis_text=None):
281
295
  """→ (skip_reason, item);skip_reason 非空表示不参与回填。"""
282
296
  fm, content = cg._read(e)
@@ -317,6 +331,7 @@ def _classify(cg, e, nid, basis_text=None):
317
331
  }
318
332
 
319
333
 
334
+ # 生效条件:x 经 _as_cg 后遍历 cg.index.nodes,按 ids/layer/prefix 过滤,内部层/不可读/locked/derived/present/unfillable/placeholder/partial 且 include_partial 为 False 分别计数跳过,其余标记 entry_id 并计入 targeted,items 受 limit 限制(limit 为 None 或 len(items) < limit 时追加),返回 dry_run rep。
320
335
  def plan(x, layer=None, limit=None, ids=None, include_partial=False,
321
336
  basis_text=None, prefix=None) -> dict:
322
337
  """预演:产出可回填清单,不写盘。
@@ -381,6 +396,7 @@ def plan(x, layer=None, limit=None, ids=None, include_partial=False,
381
396
 
382
397
  # ---- 回填写入 / 回滚 / 留痕 ----------------------------------------------
383
398
 
399
+ # 生效条件:x 可被 _as_cg 解释为 CG 句柄时,按 layer/ids/prefix/entry_ids 选定条目做回填并返回含 written 等计数的 rep,其中 limit 非 None 时把写入数截断到该值。
384
400
  def apply(x, ids=None, entry_ids=None, layer=None, limit=None,
385
401
  batch=BATCH_DEFAULT, include_partial=False, basis_text=None,
386
402
  actor=None, prefix=None) -> dict:
@@ -458,6 +474,7 @@ def apply(x, ids=None, entry_ids=None, layer=None, limit=None,
458
474
  return rep
459
475
 
460
476
 
477
+ # 生效条件:x 经 _as_cg 定位后读留痕日志,仅对 action=='backfill' 且(batch 为假值则不过滤 batch,否则 rec['batch']==batch)、(entry_ids 为假值则不过滤,否则 rec['entry_id'] 属于该集合)、write_id 未出现在已完成 rollback 集合中、节点命中 cg.index['nodes'] 且 cg._read(e) 的 fm 可读、字段当前 _ccg_field(content, f) 等于留痕 after 的记录执行撤销写回(before 为 None 则删该 comment 键,否则还原原值),无字段可撤销只计 conflict 不写盘,reverted 非空时 rebuild_index,结果汇总进返回的 rep。
461
478
  def rollback(x, batch=None, entry_ids=None, actor=None) -> dict:
462
479
  """按留痕反向应用:撤销本批次回填(当前值 ≠ 写入值时跳过,防覆盖)。"""
463
480
  cg = _as_cg(x)
@@ -528,6 +545,7 @@ def rollback(x, batch=None, entry_ids=None, actor=None) -> dict:
528
545
  return rep
529
546
 
530
547
 
548
+ # 生效条件:x 经 _as_cg,action/batch 为真值时过滤对应日志记录;limit 不为 None 且 >=0 时按 recs[-limit:] 截断(limit=0 时切片为全部记录),limit 为 None 或负数时不截断;返回 total/returned/records。
531
549
  def history(x, limit=100, action=None, batch=None) -> dict:
532
550
  cg = _as_cg(x)
533
551
  recs = []
@@ -555,6 +573,7 @@ def history(x, limit=100, action=None, batch=None) -> dict:
555
573
  _CAP_TEMPLATE_LINES = ("验证方式",)
556
574
 
557
575
 
576
+ # 生效条件:content 中去除 # 与空白后、全角或半角冒号前首段命中 _CAP_TEMPLATE_LINES 的行被剔除,其余行保留并 join。
558
577
  def _cap_body(content: str) -> str:
559
578
  """正文(供关键词匹配)——剔除 CCG 模板行,防模板词污染候选。"""
560
579
  keep = []
@@ -567,6 +586,7 @@ def _cap_body(content: str) -> str:
567
586
  return "\n".join(keep)
568
587
 
569
588
 
589
+ # 生效条件:当 fm 为可 get 的 frontmatter、e 为带 id 的节点条目、content 为正文文本时,返回 title+e.id+功能名/生效条件/子功能字段+正文前 300 字合并后的小写串(不含 fm.tags)。
570
590
  def _cap_text(e, fm, content) -> str:
571
591
  """候选匹配文本:节点标识 + CCG 字段 + 正文(**不含 `fm.tags`**)。"""
572
592
  parts = [_as_text(fm.get("title")), e.get("id") or ""]
@@ -578,6 +598,7 @@ def _cap_text(e, fm, content) -> str:
578
598
  return " ".join(parts).lower()
579
599
 
580
600
 
601
+ # 生效条件:text 包含 CAP_RULES 中某 cap 的至少一个关键词时,该 cap 以匹配关键词与置信度加入返回,按置信度降序、cap 升序排序;无匹配返回空 hits。
581
602
  def cap_matches(text: str) -> list:
582
603
  hits = []
583
604
  for cap, kws in CAP_RULES.items():
@@ -589,6 +610,7 @@ def cap_matches(text: str) -> list:
589
610
  return hits
590
611
 
591
612
 
613
+ # 生效条件:x 经 _as_cg,遍历 nodes 按 ids/layer 过滤,不可读计 denied,读取失败或加密计 locked,扫描后以 _cap_text 匹配并过滤 confidence >= min_conf 且标签未含 cap:,无命中计 present,有命中则 targeted 并受 limit 限制加入 items,返回 dry_run rep。
592
614
  def cap_plan(x, layer=None, limit=None, ids=None, min_conf=0.5) -> dict:
593
615
  """预演:按关键词启发式给出 `cap:<op>` 标签建议(含依据与置信度),不写盘。"""
594
616
  cg = _as_cg(x)
@@ -626,6 +648,7 @@ def cap_plan(x, layer=None, limit=None, ids=None, min_conf=0.5) -> dict:
626
648
  return rep
627
649
 
628
650
 
651
+ # 生效条件:x 经 _as_cg,batch 假值回落 BATCH_DEFAULT;先 cap_plan 得 items,按 entry_ids 过滤;逐个检查节点存在、读取可读、无新增标签分别计 drift/locked/drift,成功写 tags 并记日志,limit 非 None 且 written >= limit 时 break;返回 rep。
629
652
  def cap_apply(x, ids=None, entry_ids=None, layer=None, limit=None,
630
653
  batch=BATCH_DEFAULT, min_conf=0.5, actor=None) -> dict:
631
654
  """注入 `cap:<op>` 标签:只改 frontmatter.tags,不动正文。"""
@@ -676,6 +699,7 @@ def cap_apply(x, ids=None, entry_ids=None, layer=None, limit=None,
676
699
  return rep
677
700
 
678
701
 
702
+ # 生效条件:x 经 _as_cg,读取日志中 action=cap 且未回滚的记录,按 batch/entry_ids 过滤,节点存在且原加入标签仍在 tags 中时移除,否则计 conflict/missing,返回 rep。
679
703
  def cap_rollback(x, batch=None, entry_ids=None, actor=None) -> dict:
680
704
  """撤销 cap 注入:仅移除**仍在 tags 里**的 `cap:` 标签(防覆盖后续修改)。"""
681
705
  cg = _as_cg(x)
@@ -730,6 +754,7 @@ def cap_rollback(x, batch=None, entry_ids=None, actor=None) -> dict:
730
754
  EXEMPT_FLAG = "ccg_exempt"
731
755
 
732
756
 
757
+ # 生效条件:fm 的 verification_basis 合法且 content 的 ccg_completeness 标记 complete 时返回 (True, []),否则把缺失项放入 miss 返回 ready=False。
733
758
  def _exempt_ready(fm: dict, content: str):
734
759
  """摘豁免前置条件 → `(ready, missing)`。
735
760
 
@@ -745,6 +770,7 @@ def _exempt_ready(fm: dict, content: str):
745
770
  return (not miss), miss
746
771
 
747
772
 
773
+ # 生效条件:x 经 _as_cg,遍历 nodes 按 ids/prefix/layer 过滤,内部层/不可读/读取失败或加密分别计数跳过,fm 无 EXEMPT_FLAG 计 not_exempt,require_ready 为真且不 ready 时计 unready 并在 want 为 None 时跳过,否则生成 item 受 limit 限制;sample 为真值时按 id 序等距抽取 sample 个。
748
774
  def exempt_plan(x, layer=None, limit=None, ids=None, require_ready=True,
749
775
  sample=0, prefix=None) -> dict:
750
776
  """预演:列出可摘 `ccg_exempt` 的节点(默认要求证据就绪),不写盘。
@@ -804,6 +830,7 @@ def exempt_plan(x, layer=None, limit=None, ids=None, require_ready=True,
804
830
  return rep
805
831
 
806
832
 
833
+ # 生效条件:x 经 _as_cg,batch 假值回落 BATCH_DEFAULT;先 exempt_plan 得 items,按 entry_ids 过滤;逐个检查节点存在、可读、EXEMPT_FLAG 仍真、require_ready 为真时 _exempt_ready 再次通过;不通过计 skipped_unready 并记 exempt_skip;通过则置 EXEMPT_FLAG=False 写盘记日志;limit 限制 written;返回 rep。
807
834
  def exempt_apply(x, ids=None, entry_ids=None, layer=None, limit=None,
808
835
  batch=BATCH_DEFAULT, require_ready=True, actor=None,
809
836
  prefix=None) -> dict:
@@ -864,6 +891,7 @@ def exempt_apply(x, ids=None, entry_ids=None, layer=None, limit=None,
864
891
  return rep
865
892
 
866
893
 
894
+ # 生效条件:当 x 可解析为 cg 时,日志中 action 为 exempt 的记录若其非空 write_id 已存在于既有 action 为 exempt_rollback 的记录 write_id 集合中,则跳过并计入 skipped_done,否则在通过 batch 与 entry_ids 过滤后,节点存在且可读、EXEMPT_FLAG 当前为假时,该记录才被还原并计入 reverted;。
867
895
  def exempt_rollback(x, batch=None, entry_ids=None, actor=None) -> dict:
868
896
  """反向还原 `ccg_exempt`:仅当当前仍为「已摘」状态时还原,否则计 conflict。"""
869
897
  cg = _as_cg(x)
@@ -920,6 +948,7 @@ def exempt_rollback(x, batch=None, entry_ids=None, actor=None) -> dict:
920
948
  # ③ verify_conditions 只读复算:验收指标 legacy_position == 0
921
949
 
922
950
 
951
+ # 生效条件:x 经 _as_cg,遍历 nodes 按 prefix/layer 过滤,内部层/不可读/读取失败或加密/derived 层或 SKIP_TAGS 分别计数跳过;扫描后,正文已有生效条件计 declared,derive_fields 可推出计 derivable,否则按 condition_space 缺失槽计 pending 并受 limit 限制收集 items;返回 rep。
923
952
  def conditions_pending(x, prefix=None, layer=None, limit=None) -> dict:
924
953
  """只读台账:列出「未声明生效条件、且四槽推不出」的节点及其缺失槽。
925
954
 
@@ -978,6 +1007,7 @@ def conditions_pending(x, prefix=None, layer=None, limit=None) -> dict:
978
1007
  return rep
979
1008
 
980
1009
 
1010
+ # 生效条件:cg 的留痕日志中存在 basis 为 LEGACY_CONDITION_BASIS 且未被回滚的 backfill 生效条件写入时,按 node 记录最后一次的 after/original 返回;无匹配返回空。
981
1011
  def _legacy_condition_records(cg) -> dict:
982
1012
  """→ {node: {after, original, …}}:我们**自己写下的**单槽冒充行(真源 = 留痕)。
983
1013
 
@@ -1005,6 +1035,7 @@ def _legacy_condition_records(cg) -> dict:
1005
1035
  return out
1006
1036
 
1007
1037
 
1038
+ # 生效条件:x 经 _as_cg,从 _legacy_condition_records 取候选,按 prefix 过滤,节点不存在/不可读/读取失败或加密分别计 missing/denied/locked;当前生效条件等于留痕 after 时,四槽合成非空则 rewrite 否则 drop,不等则 conflict;items 受 limit 限制;返回 dry_run rep。
1008
1039
  def fix_conditions_plan(x, prefix=None, limit=None) -> dict:
1009
1040
  """预演:清洗存量单槽冒充行。不写盘。
1010
1041
 
@@ -1054,6 +1085,7 @@ def fix_conditions_plan(x, prefix=None, limit=None) -> dict:
1054
1085
  return rep
1055
1086
 
1056
1087
 
1088
+ # 生效条件:x 经 _as_cg,batch 假值回落 FIX_BATCH_DEFAULT;先 fix_conditions_plan 得 items,按 ids/entry_ids 过滤;逐个再验当前值仍等于 before 且 comment_before 一致,否则 skipped_drift;rewrite 时 upsert 生效条件行并写 comment,drop 时删行并还原 comment;写盘记 condition_fix,drop 另记 condition_pending;limit 限制 rewritten+dropped;返回 rep。
1057
1089
  def fix_conditions_apply(x, ids=None, entry_ids=None, prefix=None, limit=None,
1058
1090
  batch=FIX_BATCH_DEFAULT, actor=None) -> dict:
1059
1091
  """执行清洗:`rewrite` 改写为四槽合成声明;`drop` 删行并登记待补。
@@ -1144,6 +1176,7 @@ def fix_conditions_apply(x, ids=None, entry_ids=None, prefix=None, limit=None,
1144
1176
  return rep
1145
1177
 
1146
1178
 
1179
+ # 生效条件:x 经 _as_cg,读取日志中 action=condition_fix 且未回滚的记录,按 batch/entry_ids 过滤,节点存在且当前生效条件等于 after 时,还原 before(空则删行)并还原 comment_before,否则计 conflict/missing;返回 rep。
1147
1180
  def fix_conditions_rollback(x, batch=None, entry_ids=None, actor=None) -> dict:
1148
1181
  """按留痕反向应用:恢复被改写的旧值 / 重建被删除的冒充行。
1149
1182
 
@@ -1210,6 +1243,7 @@ def fix_conditions_rollback(x, batch=None, entry_ids=None, actor=None) -> dict:
1210
1243
  return rep
1211
1244
 
1212
1245
 
1246
+ # 生效条件:x 经 _as_cg,遍历 nodes 按 prefix 过滤、内部层跳过,读取失败或加密跳过;对每个节点当前生效条件行,缺失计 absent,否则按 is_legacy_position_condition、等于 _condition_text 合成、等于 comment、其他分别计数,legacy_ids 受 limit 限制;返回 rep。
1213
1247
  def verify_conditions(x, prefix=None, limit=None) -> dict:
1214
1248
  """复算核对(只读):生效条件行的来源分布 + 弱等价残留计数。
1215
1249
 
@@ -1264,6 +1298,7 @@ ACTIONS = ("backfill", "backfill_rollback", "backfill_history",
1264
1298
  "exempt", "exempt_rollback", "exempt_history")
1265
1299
 
1266
1300
 
1301
+ # 生效条件:按其 action 分派——action=='backfill' 时 kw['apply'] 为真调 apply(x, 去掉 apply 的 kw)、否则调 plan 同参;action=='cap'/'exempt' 同理在 kw['apply'] 为真时调 cap_apply/exempt_apply、否则调 cap_plan/exempt_plan;action=='backfill_rollback'/'cap_rollback'/'exempt_rollback' 分别调 rollback/cap_rollback/exempt_rollback(x, **kw);action=='backfill_history' 调 history(x, **kw),'cap_history'/'exempt_history' 调 history(x, action='cap'/'exempt', **kw);其余 action 值抛 ValueError。
1267
1302
  def run(x, action, **kw) -> dict:
1268
1303
  """`maintain` op 的分派入口:action ∈ ACTIONS。"""
1269
1304
  if action == "backfill":
@@ -1290,4 +1325,4 @@ def run(x, action, **kw) -> dict:
1290
1325
  return exempt_rollback(x, **kw)
1291
1326
  if action == "exempt_history":
1292
1327
  return history(x, action="exempt", **kw)
1293
- raise ValueError(f"未知 backfill action:{action}(允许:{ACTIONS})")
1328
+ raise ValueError(f"未知 backfill action:{action}(允许:{ACTIONS})")
@@ -0,0 +1,34 @@
1
+ # -*- coding: utf-8 -*-
2
+ """big_domain 域标签回填(S1 大域收敛的前置元数据;幂等、支持 --dry-run)。
3
+
4
+ 用法:
5
+ python -X utf8 -m md_cg.backfill_bigdomain --root <库根> [--dry-run] [--limit N]
6
+
7
+ 为何需要单独的回填入口:域标签是**写入侧**新增的元数据,存量节点没有;
8
+ S1 要按域收敛,就必须先把存量补齐(契约 §8.1)。
9
+ """
10
+ import argparse
11
+ import json
12
+ import sys
13
+
14
+ from .mdcg import MdCG
15
+
16
+
17
+ # 生效条件:无条件解析参数(root 必填,dry_run/limit 可选)、以 MdCG(root) 打开库、调用 backfill_big_domain 并把统计 dict 以 JSON 打印,返回 0。
18
+ def main(argv=None):
19
+ ap = argparse.ArgumentParser()
20
+ ap.add_argument("--root", required=True, help="库根目录")
21
+ ap.add_argument("--dry-run", action="store_true", dest="dry_run",
22
+ help="只统计不改盘")
23
+ ap.add_argument("--limit", type=int, default=None, help="最多补写多少个节点")
24
+ a = ap.parse_args(argv)
25
+ cg = MdCG(a.root)
26
+ st = cg.backfill_big_domain(dry_run=a.dry_run, limit=a.limit)
27
+ print(json.dumps(st, ensure_ascii=False))
28
+ return 0
29
+
30
+
31
+ if __name__ == "__main__":
32
+ if hasattr(sys.stdout, "reconfigure"):
33
+ sys.stdout.reconfigure(encoding="utf-8")
34
+ sys.exit(main())
@@ -54,6 +54,7 @@ QUERY_CONTEXT = {
54
54
  }
55
55
 
56
56
 
57
+ # 生效条件:形参 c 若提供映射接口,则取 c["zh_fields"](缺失或假值回落 {})再取其 "condition"(缺失或假值回落 {}),返回三槽 observation_position/observation_tool/existence_constraint,各自以 cond.get(中文键, "") 取值——中文键缺失时回落空串,键存在而值为 None 时结果即为 None(不回落)。
57
58
  def cond_of(c):
58
59
  """zh_fields.condition(中文三槽)→ mdcos 期望的英文槽名。
59
60
 
@@ -65,6 +66,7 @@ def cond_of(c):
65
66
  "existence_constraint": cond.get("存在约束", "")}
66
67
 
67
68
 
69
+ # 生效条件:形参 c 若提供映射接口,则 f = c["zh_fields"] 为假值(缺失/None/{})时当作 {},返回 [str(f["identity"] 或 "")] + [str(t) for t in (f["terms"] 或 [])]:identity 缺失或假值时首元素为空串(列表恒有 1 项),terms 缺失或假值时只有首元素。
68
70
  def tags_of(c):
69
71
  """喂 entity 路的裸词 tags = identity + terms。
70
72
 
@@ -77,24 +79,30 @@ def tags_of(c):
77
79
  return [str(f.get("identity") or "")] + [str(t) for t in (f.get("terms") or [])]
78
80
 
79
81
 
82
+ # 生效条件:类无 __init__,实例化无需任何形参;其 describe_ingest(nids) 对任意 nids(含空)恒返回 [],而 reset()、add(nid, text)、search(query, k=5) 对任意实参一律抛 NotImplementedError。
80
83
  class Adapter:
81
84
  """统一适配接口。六家一律只回吐 id 列表,指标计算交回 bench6_common。"""
82
85
  name = "adapter"
83
86
 
87
+ # 生效条件:无可选/必需形参,任何调用一律抛 NotImplementedError(基类接口桩)。
84
88
  def reset(self):
85
89
  raise NotImplementedError
86
90
 
91
+ # 生效条件:对任意 nid 与 text 一律抛 NotImplementedError(形参不参与任何判断)。
87
92
  def add(self, nid, text):
88
93
  raise NotImplementedError
89
94
 
95
+ # 生效条件:对任意 query 与任意 k(默认 5)一律抛 NotImplementedError,不返回结果。
90
96
  def search(self, query, k=5):
91
97
  raise NotImplementedError
92
98
 
99
+ # 生效条件:对任意 nids(包括空列表或 None)都直接返回空列表 [],不读取任何存储。
93
100
  def describe_ingest(self, nids):
94
101
  """回读真实存储内容样本,用于取证「入库语言与入库形态」。"""
95
102
  return []
96
103
 
97
104
 
105
+ # 生效条件:必须以 rows、variant、paths 三个必需形参构造(context 默认 None、with_meta 默认 False、rebuild 默认 False 可选),构造后 search(query, k=5) 是否向 search_rrf 传 context 由 context 是否为 None 决定,describe_ingest(nids)/bucket_health() 的取证内容取决于 variant 对应 root 库的索引状态。
98
106
  class LingshuAdapter(Adapter):
99
107
  """灵枢臂:进程内 MdCGOS。
100
108
 
@@ -103,6 +111,7 @@ class LingshuAdapter(Adapter):
103
111
 
104
112
  name = "lingshu"
105
113
 
114
+ # 生效条件:root 固定为 os.path.join(ROOT_BASE, variant);rebuild 为真且 os.path.isdir(root) 为真时先 rmtree,索引中已有节点数 ≥ len(rows) 时直接 return(幂等复用、不写库),否则按 rows 逐条 add(with_meta 为真时同时补 tags=tags_of(c)、condition_space=cond_of(c))后 flush。
106
115
  def __init__(self, rows, variant, paths, context=None, with_meta=False,
107
116
  rebuild=False):
108
117
  from md_cg.bench_locomo_zh_public import body_of
@@ -132,12 +141,14 @@ class LingshuAdapter(Adapter):
132
141
  print(" [lingshu/%s] 建库 %d 节点 %.1fs"
133
142
  % (variant, len(self.cg.index["nodes"]), time.time() - t0))
134
143
 
144
+ # 生效条件:给定 query 与 k(默认 5)即调用 self.cg.search_rrf(k=k、paths=self.paths、judge=False、record=False),仅当 self.context 不为 None 时附加 context 参数,返回每个结果 r 的 r[0]["id"] 组成的列表。
135
145
  def search(self, query, k=5):
136
146
  kw = {"context": self.context} if self.context is not None else {}
137
147
  res, _meta = self.cg.search_rrf(query, k=k, paths=self.paths,
138
148
  judge=False, record=False, **kw)
139
149
  return [r[0]["id"] for r in res]
140
150
 
151
+ # 生效条件:只遍历 nids[:2],节点索引中 .get(nid) 为假值(缺失)的 nid 被跳过,其余按 os.path.join(self.cg.root, e["path"]) 读文件头 300 字符,抛 OSError 时 file_head 保持空串,输出各字段用 e.get(缺键为 None)。
141
152
  def describe_ingest(self, nids):
142
153
  """回读真实落盘内容(索引元数据 + 文件头),取证入库语言与形态。
143
154
 
@@ -161,6 +172,7 @@ class LingshuAdapter(Adapter):
161
172
  "file_head": head})
162
173
  return out
163
174
 
175
+ # 生效条件:无参数,遍历 self.cg.index["nodes"] 各节点的 e.get("bucket"),其缺失或为假值(None/空串等)时归入 "<none>" 计数,再把计数字典交 routing.bucket_health 并返回其结果。
164
176
  def bucket_health(self):
165
177
  """桶健康度自检(routing.bucket_health):取证条件路由是否有区分力。"""
166
178
  from md_cg import routing
@@ -171,6 +183,7 @@ class LingshuAdapter(Adapter):
171
183
  return routing.bucket_health(counts)
172
184
 
173
185
 
186
+ # 生效条件:无必需构造形参,base 为假值(None/空串)时先回落 os.environ["BENCH6_EMBED_BASE"]、再回落 "http://127.0.0.1:1234/v1" 并 rstrip("/"),model 为假值时回落 os.environ["BENCH6_EMBED_MODEL"]、再回落空串 "",timeout 缺省为 30。
174
187
  class VectorRagAdapter(Adapter):
175
188
  """纯向量 RAG 基线(零 LLM):英文原文直嵌入 + 余弦 Top-k。
176
189
 
@@ -180,6 +193,7 @@ class VectorRagAdapter(Adapter):
180
193
 
181
194
  name = "vector_rag"
182
195
 
196
+ # 生效条件:base 依次按 base 形参 → os.environ.get("BENCH6_EMBED_BASE") → "http://127.0.0.1:1234/v1" 取值(每级为空串/None 均继续回落)再去掉尾部 "/",model 依次按 model 形参 → os.environ.get("BENCH6_EMBED_MODEL") → "" 取值(空串也回落),timeout 直接取形参(含 0),ids/vecs 置 []、_dim 置 0。
183
197
  def __init__(self, base=None, model=None, timeout=30):
184
198
  self.base = (base or os.environ.get("BENCH6_EMBED_BASE")
185
199
  or "http://127.0.0.1:1234/v1").rstrip("/")
@@ -189,6 +203,7 @@ class VectorRagAdapter(Adapter):
189
203
  self.vecs = []
190
204
  self._dim = 0
191
205
 
206
+ # 生效条件:以 self.base + path 为 URL、method="POST"、JSON 编码的 payload 为 body、Content-Type: application/json、超时 self.timeout 发出请求,返回响应体按 UTF-8 解码后 json.loads 的对象。
192
207
  def _post(self, path, payload):
193
208
  req = urllib.request.Request(
194
209
  self.base + path, method="POST",
@@ -197,6 +212,7 @@ class VectorRagAdapter(Adapter):
197
212
  with urllib.request.urlopen(req, timeout=self.timeout) as r:
198
213
  return json.loads(r.read().decode("utf-8"))
199
214
 
215
+ # 生效条件:self.model 为真值时直接返回;否则请求 self.base + "/models",从 data.get("data") 筛出 id 非空的模型名列表,该列表为空时抛 RuntimeError,否则优先取名字含 embed/bge/gte/m3 的第一个,无匹配则取 ids[0],写入 self.model 后返回。
200
216
  def resolve_model(self):
201
217
  """未显式指定时,从 /models 取第一个 embedding 模型。"""
202
218
  if self.model:
@@ -216,12 +232,14 @@ class VectorRagAdapter(Adapter):
216
232
  self.model = ids[0]
217
233
  return self.model
218
234
 
235
+ # 生效条件:对任意 text 以 self.model 调 _post("/embeddings", {"model":…, "input": text}),取 d["data"][0]["embedding"],令 self._dim 等于该向量长度并返回该向量。
219
236
  def embed(self, text):
220
237
  d = self._post("/embeddings", {"model": self.model, "input": text})
221
238
  v = d["data"][0]["embedding"]
222
239
  self._dim = len(v)
223
240
  return v
224
241
 
242
+ # 生效条件:按 batch(默认 32)把 texts 切片,每片整批 POST /embeddings 成功时按 x.get("index", 0) 排序后依次收集 r["embedding"],该片抛任何异常时改为对片内每条调 self.embed 回退,self._dim 为 0 且有结果时置为最后一条向量长度,最后返回 out。
225
243
  def embed_many(self, texts, batch=32):
226
244
  """批量嵌入(服务不支持 batch 时逐条回退)。"""
227
245
  out = []
@@ -237,13 +255,16 @@ class VectorRagAdapter(Adapter):
237
255
  self._dim = len(out[-1])
238
256
  return out
239
257
 
258
+ # 生效条件:无前置;把 self.ids 与 self.vecs 同时清空(二者下标耦合,必须成对重置),self._dim 保留原值不动;
240
259
  def reset(self):
241
260
  self.ids, self.vecs = [], []
242
261
 
262
+ # 生效条件:对任意 nid 与 text,把 nid 追加到 self.ids、把 self.embed(text) 的向量追加到 self.vecs,二者按下标一一对应,不查重、不返回。
243
263
  def add(self, nid, text):
244
264
  self.ids.append(nid)
245
265
  self.vecs.append(self.embed(text))
246
266
 
267
+ # 生效条件:self.vecs 为空时直接返回 [];否则嵌入 query 并对每条候选计算余弦相似度(qn 或 vn 为 0 时用 1.0 兜底),按相似度降序、同分按 id 升序排序后返回前 k 个 nid。
247
268
  def search(self, query, k=5):
248
269
  if not self.vecs:
249
270
  return []
@@ -257,6 +278,7 @@ class VectorRagAdapter(Adapter):
257
278
  scored.sort(key=lambda x: (-x[0], x[1]))
258
279
  return [nid for _s, nid in scored[:k]]
259
280
 
281
+ # 生效条件:对任意 nids 都只取前 2 项(nids[:2]),各返回 {"id": nid, "form": "原样英文文本 → embedding", "lang": "en", "dim": self._dim},不读磁盘内容。
260
282
  def describe_ingest(self, nids):
261
283
  return [{"id": nid, "form": "原样英文文本 → embedding",
262
284
  "lang": "en", "dim": self._dim} for nid in nids[:2]]
@@ -264,6 +286,7 @@ class VectorRagAdapter(Adapter):
264
286
 
265
287
  # ------------------------------------------------------------------ 套件与评分
266
288
 
289
+ # 生效条件:lang 等于 "zh" 时逐题取 q["question_zh"],lang 为其它任何值(含 "en")时取 q["question_en"],对 questions 每项调 adapter.search(query, k=k),verbose 为真且序数能被 50 整除时打印进度,返回 {qid: 检索结果列表}。
267
290
  def run_suite(adapter, questions, lang, k=5, verbose=True):
268
291
  """一套查询语言跑一遍 → {qid: [id...]}(顺序即相关性降序)。"""
269
292
  key = "question_zh" if lang == "zh" else "question_en"
@@ -276,6 +299,7 @@ def run_suite(adapter, questions, lang, k=5, verbose=True):
276
299
  return hits
277
300
 
278
301
 
302
+ # 生效条件:对 langs 中每个 lang 依次跑 run_suite(adapter, questions, lang, k=k)、bc.rows_from_hits 与 ec.summarize,结果写入 out["langs"][lang];最后取 questions 前 2 条的 qid 调 adapter.describe_ingest 存入 out["ingest_probe"] 并返回 out。
279
303
  def evaluate(arm, adapter, questions, k=5, langs=("zh", "en")):
280
304
  """一套库 × 两种查询语言 → 指标 + per-question 明细 + 回读取证。"""
281
305
  out = {"arm": arm, "k": k, "langs": {}}
@@ -290,6 +314,7 @@ def evaluate(arm, adapter, questions, k=5, langs=("zh", "en")):
290
314
  return out
291
315
 
292
316
 
317
+ # 生效条件:model 依次按 model 形参 → os.environ.get("BENCH6_EMBED_MODEL") → "text-embedding-bge-m3" 取值(形参为空串/None、环境变量缺失或为空串都会继续回落),随后 resolve_model(),再把 pool 中每条的 t["id"]、t["ingest"] 分别装进 vec.ids 与批量嵌入结果 vec.vecs 后返回 vec。
293
318
  def build_vector_rag(pool, model=None):
294
319
  """向量基线:池内英文原文批量嵌入(零 LLM、无结构化)。"""
295
320
  vec = VectorRagAdapter(model=model or os.environ.get("BENCH6_EMBED_MODEL")
@@ -303,6 +328,7 @@ def build_vector_rag(pool, model=None):
303
328
  return vec
304
329
 
305
330
 
331
+ # 生效条件:argv 为 None 时取 sys.argv[1:],其中出现 "--rebuild" 则各臂以 rebuild=True 建库,非 "-" 开头的项构成 only 白名单,仅当 only 为空或臂名在 only 中时执行对应臂(only 为空时额外执行 2×2 消融块),跑完返回含 manifest/results/elapsed_s 的 payload。
306
332
  def main(argv=None):
307
333
  argv = sys.argv[1:] if argv is None else argv
308
334
  rebuild = "--rebuild" in argv
@@ -322,6 +348,7 @@ def main(argv=None):
322
348
  rows = [corpus_by_id[t["id"]] for t in pool]
323
349
  results, table = {}, {}
324
350
 
351
+ # 生效条件:形参 name 出现在外层 main 的 only 白名单中时返回 True;only 为空(假值)时对任何 name 都返回 True;only 非空且不含 name 时返回 False。
325
352
  def _want(name):
326
353
  return not only or name in only
327
354
 
@@ -381,4 +408,4 @@ def main(argv=None):
381
408
 
382
409
 
383
410
  if __name__ == "__main__":
384
- main()
411
+ main()
@@ -53,6 +53,7 @@ BOUNDARIES = [
53
53
  ]
54
54
 
55
55
 
56
+ # 生效条件:rows 为含 qtype 的行列表、n 取默认 N_QUESTIONS、seed 取默认 SEED 时(rows 为空则分组与配额皆空、out 为空列表;n=0 时各型配额与 out 皆为空/0),按 int(n*组大小/总行数) 定配额并把余数按小数部分降序补足,逐型用 random.Random("%d:%s"%(seed,qt)) 抽 min(配额,组大小) 条,返回按 qid 排序的 (out, quota)
56
57
  def stratified_sample(rows, n=N_QUESTIONS, seed=SEED):
57
58
  """按 qtype 比例分层抽样(最大余额法)。
58
59
 
@@ -78,6 +79,7 @@ def stratified_sample(rows, n=N_QUESTIONS, seed=SEED):
78
79
  return out, quota
79
80
 
80
81
 
82
+ # 生效条件:sample 为含 qid 与 evidence_turns 的题列表、corpus_by_id 为 id→池行的映射时,把不在 corpus_by_id 中的 evidence_turns 逐题记为 {"qid":…,"missing":[…]} 收入 dangling,其余去重后返回 (按 id 排序的 corpus_by_id 行列表, dangling)
81
83
  def build_pool(sample, corpus_by_id):
82
84
  """池 = 抽中题的 gold 引用 turn 去重。返回 (pool, dangling)。
83
85
 
@@ -94,6 +96,7 @@ def build_pool(sample, corpus_by_id):
94
96
  return [corpus_by_id[i] for i in sorted(pool_ids)], dangling
95
97
 
96
98
 
99
+ # 生效条件:c 为含 text 键的映射时取其去空白文本,date 非空则返回 "文本 [date]",date 为空则只返回 text。
97
100
  def ingest_text_en(c):
98
101
  """六家共用的英文写入文本:原始陈述 + 会话时间。
99
102
 
@@ -107,6 +110,7 @@ def ingest_text_en(c):
107
110
  return "%s [%s]" % (text, date) if date else text
108
111
 
109
112
 
113
+ # 生效条件:c 含 "id" 键时返回 {'id': c["id"], 'speaker'/'date'/'text' 为 c.get(键) or ""(键缺失或值为 None/""/0/[] 等假值均落空串), 'ingest': ingest_text_en(c)};缺 "id" 键时 c["id"] 抛 KeyError
110
114
  def turn_rec(c):
111
115
  """池行 → 落盘行(六家共用的英文侧视图)。"""
112
116
  return {"id": c["id"], "speaker": c.get("speaker") or "",
@@ -114,6 +118,7 @@ def turn_rec(c):
114
118
  "ingest": ingest_text_en(c)}
115
119
 
116
120
 
121
+ # 生效条件:sample 每题的 qid 在 en_by_qid 中且中英 evidence_turns 逐字相等时返回按 sample 顺序的 {qid, qtype, question_zh, question_en, evidence_turns} 列表;en_by_qid.get(qid) 为 None 抛 KeyError,两列表不等抛 AssertionError
117
122
  def align_queries(sample, en_by_qid):
118
123
  """中英双查询词面按 qid join,断言 evidence_turns 逐字一致。
119
124
 
@@ -133,6 +138,7 @@ def align_queries(sample, en_by_qid):
133
138
  return out
134
139
 
135
140
 
141
+ # 生效条件:ids 为 id 序列、evidence 为证据 id 集合时,把 ids 包装成 [({"id": x}, 0.0)] 后原样返回 ec.first_evidence_rank 的结果
136
142
  def rank_of(ids, evidence):
137
143
  """首个证据 id 的排名(1-based;未命中 0)。
138
144
 
@@ -143,6 +149,7 @@ def rank_of(ids, evidence):
143
149
  return ec.first_evidence_rank(res, set(evidence))
144
150
 
145
151
 
152
+ # 生效条件:questions 每题含 qid,hits_by_qid 缺该 qid 或其值为假值(含空列表)时按空 id 列表处理,取前 k=K 条后返回每题 {qid, qtype, rank, top1_score(ids 非空为 1.0 否则 0.0), n_res} 的行列表
146
153
  def rows_from_hits(questions, hits_by_qid, k=K):
147
154
  """把任一家的 id 列表统一转成 ec.summarize 的明细行。
148
155
 
@@ -159,6 +166,7 @@ def rows_from_hits(questions, hits_by_qid, k=K):
159
166
  return rows
160
167
 
161
168
 
169
+ # 生效条件:force 为假且 os.path.exists(MANIFEST) 与 os.path.exists(QUESTIONS_JSONL) 均为真时读回 MANIFEST 直接返回(verbose 为真时打印复用信息);否则重建口径、写 POOL_JSONL/QUESTIONS_JSONL/MANIFEST 后返回该 man
162
170
  def prepare(force=False, verbose=True):
163
171
  """固化口径层产物(幂等)。返回 manifest。"""
164
172
  if not force and os.path.exists(MANIFEST) and os.path.exists(QUESTIONS_JSONL):
@@ -211,6 +219,7 @@ def prepare(force=False, verbose=True):
211
219
  return man
212
220
 
213
221
 
222
+ # 生效条件:无参调用时读 MANIFEST 常量并返回 {'questions': QUESTIONS_JSONL 行列表, 'pool': POOL_JSONL 行列表, 'manifest': 该 JSON 对象}
214
223
  def load():
215
224
  """读回已固化的口径层产物。六家适配器只经此取题与池。"""
216
225
  man = json.load(open(MANIFEST, encoding="utf-8"))
@@ -219,4 +228,4 @@ def load():
219
228
 
220
229
 
221
230
  if __name__ == "__main__":
222
- prepare(force="--force" in sys.argv)
231
+ prepare(force="--force" in sys.argv)
@@ -54,11 +54,13 @@ MAIN_ARMS = [
54
54
  LANGS = ("zh", "en")
55
55
 
56
56
 
57
+ # 生效条件:questions、hits、k 三者给定即成立,以 hits 结合 k 经 bc.rows_from_hits 生成 rows,再返回 (ec.summarize(rows, k=k), rows)。
57
58
  def _score_hits(questions, hits, k):
58
59
  rows = bc.rows_from_hits(questions, hits, k=k)
59
60
  return ec.summarize(rows, k=k), rows
60
61
 
61
62
 
63
+ # 生效条件:manifest_note 传入但源码未使用该形参,结果只取决于模块常量 ec.RESULTS 下 bench6_arms_result.json——该路径不存在时打印警告并返回 {},路径可读时返回 json.load 结果 .get('results') or {}(results 键缺失或该值为假值时同样得到 {})。
62
64
  def load_main(manifest_note):
63
65
  """读主进程臂结果(含灵枢 5 口径 + 向量基线)。"""
64
66
  path = os.path.join(ec.RESULTS, "bench6_arms_result.json")
@@ -69,6 +71,7 @@ def load_main(manifest_note):
69
71
  return json.load(f).get("results") or {}
70
72
 
71
73
 
74
+ # 生效条件:由 arm 拼出模块常量 ARM_OUT 下 <arm>.json,该路径不存在时返回 (None, '缺文件 …(该臂未跑或跑失败)');路径可读时用 questions 与 k 对遍历模块常量 LANGS 各语言的 hits 评分(raw['langs']、某语言块、其 hits 缺失或为假值时按 {} 处理,errors 缺失或为假值时按 [] 处理),返回 (out, None)。
72
75
  def load_competitor(arm, questions, k):
73
76
  path = os.path.join(ARM_OUT, "%s.json" % arm)
74
77
  if not os.path.exists(path):
@@ -94,6 +97,7 @@ def load_competitor(arm, questions, k):
94
97
  return out, None
95
98
 
96
99
 
100
+ # 生效条件:遍历 rows 的每个 (label, r),仅当 r['langs'] 对模块常量 LANGS 每个语言都存在真值时,才用 k 读 s['hit@k'] 并打印 hit@1/hit@k/MRR 及未回收率(unmapped_rate 为 None 时显示 n/a);否则只打印 label 加「—」占位行,不打印数值。
97
101
  def print_matrix(rows, k):
98
102
  """六家 × 两语言主表(hit@1 / hit@k / MRR)。"""
99
103
  head = ("系统", "zh hit@1", "zh hit@%d" % k, "zh MRR",
@@ -119,6 +123,7 @@ def print_matrix(rows, k):
119
123
  print(" ".join(c.ljust(wi) for c, wi in zip(cells, w)))
120
124
 
121
125
 
126
+ # 生效条件:argv 为 None 时改读 sys.argv[1:] 解析 --k,随后按 MAIN_ARMS 与 COMPETITOR_ARMS 各自装载结果,返回含 k、arms、missing 的 payload。
122
127
  def main(argv=None):
123
128
  argv = sys.argv[1:] if argv is None else argv
124
129
  k = 5
@@ -205,4 +210,4 @@ def main(argv=None):
205
210
 
206
211
 
207
212
  if __name__ == "__main__":
208
- main()
213
+ main()