@furongjun1999/dsh-memory 0.4.11 → 0.5.1

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 (580) hide show
  1. package/README.md +552 -465
  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 +143 -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/bench_lingshu_self/bench_self.py +140 -0
  15. package/docs/eval/bench_lingshu_self/self_bench_result.json +404 -0
  16. package/docs/eval/bench_lingshu_self//347/201/265/346/236/242/350/207/252/345/272/223/347/253/257/345/210/260/347/253/257/346/243/200/347/264/242/345/256/236/346/265/213_v1.0.md +38 -0
  17. package/docs/eval//344/270/215/345/217/257/351/235/240/346/200/247/350/220/275/345/234/260_P0_v1.0.md +185 -0
  18. 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
  19. package/docs/eval//346/225/205/351/232/234/346/263/250/345/205/245/345/256/236/346/265/213_v1.0.md +422 -0
  20. 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
  21. package/docs/eval//347/253/257/345/210/260/347/253/257LoCoMoQA/345/220/214/345/217/243/345/276/204/345/257/271/347/205/247_v1.0.md +100 -0
  22. package/docs/eval//347/253/257/345/210/260/347/253/257/345/271/262/346/211/260/346/261/240/350/257/204/346/265/213_/347/241/256/345/256/232/346/200/247/350/243/201/345/206/263vsLLM_judge_v1.1.md +197 -0
  23. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v1.md +156 -0
  24. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v10.md +210 -0
  25. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v11.md +227 -0
  26. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v12.md +203 -0
  27. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v13.md +233 -0
  28. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v14.md +191 -0
  29. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v15.md +213 -0
  30. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v16.md +214 -0
  31. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v17.md +199 -0
  32. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v2.md +156 -0
  33. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v3.md +152 -0
  34. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v4.md +128 -0
  35. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v5.md +114 -0
  36. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v6.md +192 -0
  37. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v7.md +187 -0
  38. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v8.md +207 -0
  39. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v9.md +203 -0
  40. 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
  41. 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
  42. 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
  43. package/docs/hive//345/256/211/345/205/250/345/256/241/350/256/241/345/256/236/351/224/232_v0.1.md +202 -0
  44. 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
  45. 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
  46. 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
  47. 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
  48. 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 +519 -503
  49. 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
  50. 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
  51. 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
  52. package/docs/images/lingshu-moonlight-covenant-poster-preview.jpg +0 -0
  53. package/docs/images/lingshu-moonlight-covenant-poster.png +0 -0
  54. 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
  55. package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +646 -646
  56. package/docs/mdcg/lingshu_tutorial.html +14449 -14449
  57. package/docs/mdcg/release_v0.4.11.md +49 -0
  58. package/docs/mdcg/release_v0.4.5.md +55 -55
  59. package/docs/mdcg/tool_table_v0.3.0.md +117 -117
  60. 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
  61. 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
  62. 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
  63. package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +54 -0
  64. 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
  65. 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
  66. 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
  67. package/docs/mdcg//347/274/272/345/217/243/345/215/225_P0/346/224/266/345/217/243_v0.1.md +270 -270
  68. 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
  69. 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
  70. 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
  71. 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
  72. 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
  73. package/docs/swarm//350/234/202/347/276/244/344/272/222/350/201/224_v0.1.md +704 -704
  74. 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
  75. package/docs/theory//344/270/215/345/217/257/351/235/240/345/256/232/347/220/206/344/270/216/345/244/261/346/225/210/344/274/230/345/205/210/346/241/206/346/236/266_v0.3.md +365 -0
  76. 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
  77. 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
  78. package/docs/theory//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
  79. 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
  80. 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
  81. 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
  82. 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
  83. 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
  84. package/docs//344/270/215/345/217/257/351/235/240/346/200/247/347/220/206/350/256/272_v0.1.md +343 -0
  85. 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
  86. 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
  87. package/dsh/README.md +82 -82
  88. package/dsh/cordis.yml.example +139 -139
  89. package/dsh/update-lingshu.bat +11 -11
  90. package/lib/bridge.d.ts +9 -0
  91. package/lib/bridge.js +35 -0
  92. package/lib/hooks.js +36 -2
  93. package/lib/index.js +7 -1
  94. package/lib/lib/roleplay_web.js +116 -29
  95. package/lib/lib/token_store.d.ts +7 -1
  96. package/lib/lib/token_store.js +12 -3
  97. package/md_cg/__init__.py +7 -7
  98. package/md_cg/audit.py +379 -368
  99. package/md_cg/autonomy.py +287 -287
  100. package/md_cg/backfill.py +1328 -1327
  101. package/md_cg/backfill_bigdomain.py +34 -34
  102. package/md_cg/backfill_bucket_zh.py +35 -0
  103. package/md_cg/bench6_arms.py +410 -410
  104. package/md_cg/bench6_common.py +230 -230
  105. package/md_cg/bench6_competitors.py +212 -212
  106. package/md_cg/bench_axis_domain.py +257 -257
  107. package/md_cg/bench_blind_comp.py +308 -308
  108. package/md_cg/bench_e2e_judge.py +532 -0
  109. package/md_cg/bench_e2e_locomo_qa.py +368 -0
  110. package/md_cg/bench_e2e_qa.py +256 -0
  111. package/md_cg/bench_en_atoms_public.py +230 -230
  112. package/md_cg/bench_governance.py +348 -348
  113. package/md_cg/bench_lme_zh.py +410 -410
  114. package/md_cg/bench_locomo.py +121 -121
  115. package/md_cg/bench_locomo_zh.py +450 -450
  116. package/md_cg/bench_locomo_zh_public.py +147 -147
  117. package/md_cg/bench_longmem.py +112 -112
  118. package/md_cg/bench_membench.py +632 -632
  119. package/md_cg/bench_p0.py +149 -149
  120. package/md_cg/bench_progressive.py +287 -287
  121. package/md_cg/bench_role_views.py +238 -238
  122. package/md_cg/bench_task_ab.py +243 -243
  123. package/md_cg/bench_task_ab_llm.py +408 -408
  124. package/md_cg/bench_unified_en.py +204 -204
  125. package/md_cg/bench_zh_mad.py +601 -601
  126. package/md_cg/blindspot_tickets.py +123 -123
  127. package/md_cg/branches.py +301 -285
  128. package/md_cg/build_postings.py +73 -73
  129. package/md_cg/ccgc.py +1006 -948
  130. package/md_cg/census.py +132 -132
  131. package/md_cg/chain.py +315 -300
  132. package/md_cg/codeindex.py +531 -531
  133. package/md_cg/coldverify.py +292 -292
  134. package/md_cg/comment_gate.py +337 -337
  135. package/md_cg/cond_compose.py +190 -190
  136. package/md_cg/cond_facts.py +154 -154
  137. package/md_cg/cond_template.json +106 -106
  138. package/md_cg/condition_anchor.py +142 -142
  139. package/md_cg/conformance.py +726 -726
  140. package/md_cg/consistency.py +717 -717
  141. package/md_cg/consolidate.py +1537 -1439
  142. package/md_cg/corpus.py +110 -110
  143. package/md_cg/crosscheck.py +1098 -1097
  144. package/md_cg/crypto.py +3 -1
  145. package/md_cg/d_meta.py +310 -310
  146. package/md_cg/datapath.py +78 -18
  147. package/md_cg/docindex.py +473 -473
  148. package/md_cg/eval_common.py +575 -575
  149. package/md_cg/evidence.py +4 -2
  150. package/md_cg/evolution.py +477 -477
  151. package/md_cg/export.py +222 -220
  152. package/md_cg/forgetting.py +581 -581
  153. package/md_cg/fsutil.py +377 -329
  154. package/md_cg/hotcache.py +48 -7
  155. package/md_cg/hyperedge.py +251 -251
  156. package/md_cg/identity.py +390 -390
  157. package/md_cg/insight.py +500 -500
  158. package/md_cg/interop.py +338 -0
  159. package/md_cg/judgment_manifest.py +177 -0
  160. package/md_cg/lexicon/build_cedict_en_zh.py +329 -329
  161. package/md_cg/lexicon/build_standard_en.py +171 -171
  162. package/md_cg/lexicon/expand_en_zh.py +211 -211
  163. package/md_cg/lifecycle.py +272 -272
  164. package/md_cg/linkref.py +280 -280
  165. package/md_cg/links.py +140 -107
  166. package/md_cg/mcp_server.py +403 -55
  167. package/md_cg/md_whitebox.py +345 -345
  168. package/md_cg/mdcg.py +783 -233
  169. package/md_cg/mdcos.py +500 -70
  170. package/md_cg/metacognition.py +591 -591
  171. package/md_cg/migrate.py +119 -119
  172. package/md_cg/migrate_aeis.py +221 -221
  173. package/md_cg/migrate_roleplay.py +293 -293
  174. package/md_cg/migrate_wisdom_graph.py +360 -360
  175. package/md_cg/mreview/__init__.py +25 -25
  176. package/md_cg/mreview/__main__.py +110 -110
  177. package/md_cg/mreview/bundle.py +178 -178
  178. package/md_cg/mreview/candidates.py +262 -262
  179. package/md_cg/mreview/govern.py +694 -693
  180. package/md_cg/mreview/locate.py +939 -939
  181. package/md_cg/mreview/pipeline.py +728 -728
  182. package/md_cg/mreview/rules/duplication.json +21 -21
  183. package/md_cg/mreview/rules/field_coverage.json +54 -54
  184. package/md_cg/mreview/rules/source_license.json +21 -21
  185. package/md_cg/mreview/rules/template_flow.json +21 -21
  186. package/md_cg/mreview/ruleset.py +252 -252
  187. package/md_cg/nodefile.py +575 -575
  188. package/md_cg/pooling.py +484 -472
  189. package/md_cg/postings.py +300 -298
  190. package/md_cg/predict.py +1100 -1100
  191. package/md_cg/progressive.py +123 -123
  192. package/md_cg/protect.py +272 -272
  193. package/md_cg/protocol/md_cg_gate.proto +33 -33
  194. package/md_cg/protocol.py +372 -372
  195. package/md_cg/provenance.py +582 -582
  196. package/md_cg/reach.py +453 -453
  197. package/md_cg/readcache.py +143 -0
  198. package/md_cg/reconcile.py +228 -0
  199. package/md_cg/refindex.py +833 -833
  200. package/md_cg/refine.py +604 -604
  201. package/md_cg/review_cli.py +170 -0
  202. package/md_cg/roleviews.py +89 -89
  203. package/md_cg/routing.py +393 -365
  204. package/md_cg/run_tests.py +211 -0
  205. package/md_cg/scrub.py +13 -3
  206. package/md_cg/security.py +128 -18
  207. package/md_cg/self_state.py +1029 -1029
  208. package/md_cg/selfreport.py +152 -151
  209. package/md_cg/semantic/__init__.py +10 -10
  210. package/md_cg/semantic/canonical.py +122 -122
  211. package/md_cg/semantic/en_normalizer.py +364 -364
  212. package/md_cg/semantic/en_zh_map.json +28694 -0
  213. package/md_cg/semantic/export_en_zh_map.py +64 -0
  214. package/md_cg/semantic/unify.py +45 -0
  215. package/md_cg/semantic/zh_en_atoms.py +139 -139
  216. package/md_cg/signer.py +7 -4
  217. package/md_cg/sources.py +816 -582
  218. package/md_cg/statushdr.py +179 -179
  219. package/md_cg/stg.py +54 -37
  220. package/md_cg/subgraph.py +729 -729
  221. package/md_cg/sustain.py +35 -5
  222. package/md_cg/tasks.py +470 -470
  223. package/md_cg/test_access_hints.py +147 -0
  224. package/md_cg/test_action_derive.py +203 -203
  225. package/md_cg/test_audit_rotate.py +270 -270
  226. package/md_cg/test_autonomy.py +143 -143
  227. package/md_cg/test_bench_governance.py +102 -102
  228. package/md_cg/test_blindspot_tickets.py +166 -166
  229. package/md_cg/test_branch_discard_tombstone.py +136 -0
  230. package/md_cg/test_branches.py +13 -3
  231. package/md_cg/test_ccg_perturb.py +184 -184
  232. package/md_cg/test_ccgc.py +433 -433
  233. package/md_cg/test_census_prune.py +81 -81
  234. package/md_cg/test_chain_read_isolate.py +168 -0
  235. package/md_cg/test_cond_compose_anchors.py +76 -76
  236. package/md_cg/test_cond_match.py +165 -165
  237. package/md_cg/test_condition_anchor.py +81 -81
  238. package/md_cg/test_d_meta.py +412 -412
  239. package/md_cg/test_datapath_device_name.py +203 -0
  240. package/md_cg/test_datapath_root.py +199 -199
  241. package/md_cg/test_emit_negtail_cache.py +156 -0
  242. package/md_cg/test_en_pipeline.py +22 -2
  243. package/md_cg/test_gain_gate.py +212 -212
  244. package/md_cg/test_govern_directread.py +421 -0
  245. package/md_cg/test_health_scale.py +173 -173
  246. package/md_cg/test_hive_ingest.py +285 -0
  247. package/md_cg/test_hot_cold.py +215 -215
  248. package/md_cg/test_hyperedge.py +245 -245
  249. package/md_cg/test_i26_empty_first_write.py +116 -0
  250. package/md_cg/test_i27_e041_identity.py +128 -0
  251. package/md_cg/test_i28_hotcache_prodpath.py +122 -0
  252. package/md_cg/test_i32_hotcache_env_key.py +218 -0
  253. package/md_cg/test_identity_attribution.py +96 -15
  254. package/md_cg/test_index_durability.py +17 -3
  255. package/md_cg/test_interop.py +95 -0
  256. package/md_cg/test_interop_judgment.py +228 -0
  257. package/md_cg/test_issue39_utf8_stdio.py +273 -0
  258. package/md_cg/test_lifecycle.py +309 -309
  259. package/md_cg/test_linkref.py +306 -306
  260. package/md_cg/test_links_concurrent_write.py +188 -0
  261. package/md_cg/test_lock.py +43 -43
  262. package/md_cg/test_md_access_parity.py +255 -255
  263. package/md_cg/test_md_writepath.py +345 -345
  264. package/md_cg/test_mdstore_search_parity.py +160 -0
  265. package/md_cg/test_merge_upsert.py +168 -0
  266. package/md_cg/test_mr_m2.py +587 -587
  267. package/md_cg/test_mr_m3.py +710 -710
  268. package/md_cg/test_mr_m4.py +485 -485
  269. package/md_cg/test_n123_derive_expiry_chain.py +205 -0
  270. package/md_cg/test_n130_verify_falsified_protect.py +185 -0
  271. package/md_cg/test_n131_merge_gate.py +205 -0
  272. package/md_cg/test_p0.py +250 -250
  273. package/md_cg/test_p1.py +316 -316
  274. package/md_cg/test_p10_identity.py +173 -173
  275. package/md_cg/test_p11_consistency.py +233 -233
  276. package/md_cg/test_p12_metacognition.py +212 -212
  277. package/md_cg/test_p13_encryption.py +241 -241
  278. package/md_cg/test_p14_sustain.py +249 -249
  279. package/md_cg/test_p15_scrub.py +280 -280
  280. package/md_cg/test_p16_self_state.py +301 -301
  281. package/md_cg/test_p17_predict.py +354 -354
  282. package/md_cg/test_p18_whitebox.py +171 -171
  283. package/md_cg/test_p19_migrate_roleplay.py +149 -149
  284. package/md_cg/test_p1x_ref_root.py +160 -0
  285. package/md_cg/test_p20_evolution.py +315 -315
  286. package/md_cg/test_p21_tokens.py +293 -270
  287. package/md_cg/test_p22_theory.py +175 -175
  288. package/md_cg/test_p23_links.py +311 -311
  289. package/md_cg/test_p24_evidence.py +227 -227
  290. package/md_cg/test_p25_weights.py +156 -156
  291. package/md_cg/test_p26_refindex.py +416 -416
  292. package/md_cg/test_p27_docindex.py +16 -7
  293. package/md_cg/test_p28_refcheck.py +305 -305
  294. package/md_cg/test_p29_session_ingest_export.py +354 -333
  295. package/md_cg/test_p2_mcp.py +3 -0
  296. package/md_cg/test_p3.py +11 -2
  297. package/md_cg/test_p30_maintain.py +330 -330
  298. package/md_cg/test_p31_insight.py +534 -534
  299. package/md_cg/test_p32_backfill.py +7 -1
  300. package/md_cg/test_p33_ccg_wiring.py +293 -293
  301. package/md_cg/test_p34_crosscheck.py +331 -331
  302. package/md_cg/test_p35_conditioned_claim.py +252 -252
  303. package/md_cg/test_p36_kp_align.py +230 -230
  304. package/md_cg/test_p37_condition_space.py +248 -248
  305. package/md_cg/test_p38_concurrent_flush.py +102 -0
  306. package/md_cg/test_p38_contextualize.py +273 -273
  307. package/md_cg/test_p39_verify_flow.py +153 -0
  308. package/md_cg/test_p39_vision_evidence.py +369 -369
  309. package/md_cg/test_p40_refine_worklist.py +241 -241
  310. package/md_cg/test_p41_evolve_patrol.py +224 -224
  311. package/md_cg/test_p42_provenance.py +269 -269
  312. package/md_cg/test_p43_pooling.py +412 -398
  313. package/md_cg/test_p44_md_whitebox.py +231 -231
  314. package/md_cg/test_p45_session_identity.py +219 -219
  315. package/md_cg/test_p46_unit_scope.py +272 -272
  316. package/md_cg/test_p47_session_view.py +316 -0
  317. package/md_cg/test_p4_fuzzy.py +223 -223
  318. package/md_cg/test_p5_semantic.py +226 -226
  319. package/md_cg/test_p6_consolidate.py +440 -387
  320. package/md_cg/test_p7_goals_recent.py +202 -202
  321. package/md_cg/test_p8_subgraph_chain.py +200 -200
  322. package/md_cg/test_p9_forget_protect.py +231 -231
  323. package/md_cg/test_predict_beta.py +135 -135
  324. package/md_cg/test_preflight_failclosed.py +100 -100
  325. package/md_cg/test_progressive.py +146 -146
  326. package/md_cg/test_propose_tail_index.py +157 -0
  327. package/md_cg/test_protocol.py +243 -243
  328. package/md_cg/test_reach.py +378 -378
  329. package/md_cg/test_reach_keys.py +201 -201
  330. package/md_cg/test_read_clip.py +141 -141
  331. package/md_cg/test_read_scope_b27.py +277 -0
  332. package/md_cg/test_readcache_default_on.py +168 -0
  333. package/md_cg/test_readcache_precise_inval.py +270 -0
  334. package/md_cg/test_readcache_prodpath.py +203 -0
  335. package/md_cg/test_reconcile_v0.py +294 -0
  336. package/md_cg/test_retr_gates_prodpath.py +140 -0
  337. package/md_cg/test_retr_s1.py +344 -340
  338. package/md_cg/test_retr_s1b.py +276 -209
  339. package/md_cg/test_retr_s3.py +194 -194
  340. package/md_cg/test_retr_s4.py +163 -163
  341. package/md_cg/test_retr_s5.py +200 -200
  342. package/md_cg/test_retr_s6.py +157 -157
  343. package/md_cg/test_retr_s7.py +392 -384
  344. package/md_cg/test_retr_s8_time.py +369 -316
  345. package/md_cg/test_retr_s9_edges.py +286 -286
  346. package/md_cg/test_retr_s9_entity_ctx.py +9 -3
  347. package/md_cg/test_retr_score_once.py +208 -0
  348. package/md_cg/test_review_conformance.py +367 -367
  349. package/md_cg/test_review_onepass.py +170 -0
  350. package/md_cg/test_role_views.py +354 -354
  351. package/md_cg/test_rrf_graph_seed_cache.py +154 -0
  352. package/md_cg/test_security_audit.py +155 -0
  353. package/md_cg/test_security_audit_b26.py +161 -0
  354. package/md_cg/test_security_audit_v21.py +250 -0
  355. package/md_cg/test_sem_noise.py +242 -242
  356. package/md_cg/test_semantic_canonical.py +16 -2
  357. package/md_cg/test_session_isolation.py +168 -0
  358. package/md_cg/test_snapshot_autoclose.py +187 -0
  359. package/md_cg/test_subproc_encoding.py +192 -192
  360. package/md_cg/test_sustain_mutual.py +153 -153
  361. package/md_cg/test_tail_watermark_race.py +208 -0
  362. package/md_cg/test_tasks.py +409 -409
  363. package/md_cg/test_tenant_env_override_warn.py +139 -0
  364. package/md_cg/test_tenant_registry_corrupt_warn.py +151 -0
  365. package/md_cg/test_tool_face.py +189 -189
  366. package/md_cg/test_transfer.py +180 -180
  367. package/md_cg/test_trust.py +361 -361
  368. package/md_cg/test_twophase.py +286 -286
  369. package/md_cg/test_v14_fixes.py +38 -20
  370. package/md_cg/test_validity_filter.py +280 -280
  371. package/md_cg/test_verify_answer.py +138 -138
  372. package/md_cg/test_verify_dirty_reconcile.py +157 -0
  373. package/md_cg/test_wisdom_md_store.py +292 -292
  374. package/md_cg/test_writelimit.py +197 -197
  375. package/md_cg/test_writepipe.py +214 -214
  376. package/md_cg/theory.py +6 -3
  377. package/md_cg/tokens.py +85 -14
  378. package/md_cg/tool_face.py +260 -260
  379. package/md_cg/trust.py +986 -950
  380. package/md_cg/twophase.py +231 -231
  381. package/md_cg/units.py +668 -667
  382. package/md_cg/vision_evidence.py +667 -666
  383. package/md_cg/weights.py +624 -624
  384. package/md_cg/whitebox.py +527 -527
  385. package/md_cg/whitebox_kb/__init__.py +37 -37
  386. package/md_cg/whitebox_kb/aeis_core/__init__.py +42 -42
  387. package/md_cg/whitebox_kb/aeis_core/semantic.py +280 -280
  388. package/md_cg/whitebox_kb/aeis_core/textutil.py +13 -13
  389. package/md_cg/whitebox_kb/engine.py +310 -310
  390. package/md_cg/whitebox_kb/seed_knowledge//346/231/272/350/203/275/350/256/2723.4.md +5260 -5260
  391. package/md_cg/whitebox_kb/wisdom/browser_units.py +2631 -2631
  392. package/md_cg/whitebox_kb/wisdom/causal_discover.py +432 -432
  393. package/md_cg/whitebox_kb/wisdom/chat_engine.py +1506 -1506
  394. package/md_cg/whitebox_kb/wisdom/compiler_code_units.py +3033 -3033
  395. package/md_cg/whitebox_kb/wisdom/condition_algebra.py +112 -112
  396. package/md_cg/whitebox_kb/wisdom/condition_frame.py +315 -315
  397. package/md_cg/whitebox_kb/wisdom/condition_kb.py +108 -108
  398. package/md_cg/whitebox_kb/wisdom/conflict_map.json +4445 -4445
  399. package/md_cg/whitebox_kb/wisdom/core/lexer.py +512 -512
  400. package/md_cg/whitebox_kb/wisdom/core/name_checker.py +1023 -1023
  401. package/md_cg/whitebox_kb/wisdom/cspmn.py +258 -258
  402. package/md_cg/whitebox_kb/wisdom/csre.py +264 -264
  403. package/md_cg/whitebox_kb/wisdom/danmaku_audit.py +252 -252
  404. package/md_cg/whitebox_kb/wisdom/distilled_condition_units.json +6417 -6417
  405. package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902b.json +1950 -1950
  406. package/md_cg/whitebox_kb/wisdom/docs/WB-EVAL-20260902c.json +1296 -1296
  407. package/md_cg/whitebox_kb/wisdom/docs/whitebox_capability_graph_demo.json +59 -59
  408. package/md_cg/whitebox_kb/wisdom/graph_db_units.py +3089 -3089
  409. package/md_cg/whitebox_kb/wisdom/knowledge_points.py +318 -318
  410. package/md_cg/whitebox_kb/wisdom/md_access.py +470 -470
  411. package/md_cg/whitebox_kb/wisdom/md_store.py +276 -251
  412. package/md_cg/whitebox_kb/wisdom/migrate_wisdom.py +476 -476
  413. package/md_cg/whitebox_kb/wisdom/multilang_ir.py +128 -124
  414. package/md_cg/whitebox_kb/wisdom/navigate.py +248 -248
  415. package/md_cg/whitebox_kb/wisdom/neural_retrieve.py +224 -224
  416. package/md_cg/whitebox_kb/wisdom/os_units.py +2735 -2735
  417. package/md_cg/whitebox_kb/wisdom/pattern_separation.py +376 -376
  418. package/md_cg/whitebox_kb/wisdom/prereq_map.json +364 -364
  419. package/md_cg/whitebox_kb/wisdom/python_code_units.py +2766 -2766
  420. package/md_cg/whitebox_kb/wisdom/role_solidified.json +7 -7
  421. package/md_cg/whitebox_kb/wisdom/route_memory.py +244 -244
  422. package/md_cg/whitebox_kb/wisdom/scene_reconstruction.py +148 -148
  423. package/md_cg/whitebox_kb/wisdom/snr_report.json +40 -40
  424. package/md_cg/whitebox_kb/wisdom/test_code_compose_domains.py +7541 -7541
  425. package/md_cg/whitebox_kb/wisdom/test_compiler_self_bootstrap.py +354 -354
  426. package/md_cg/whitebox_kb/wisdom/test_ecosystem_assembly.py +158 -158
  427. package/md_cg/whitebox_kb/wisdom/test_ecosystem_demos.py +193 -193
  428. package/md_cg/whitebox_kb/wisdom/test_graph_db.py +292 -292
  429. package/md_cg/whitebox_kb/wisdom/test_python_self_bootstrap.py +160 -160
  430. package/md_cg/whitebox_kb/wisdom/trigger_words_index.json +4366 -4366
  431. package/md_cg/whitebox_kb/wisdom/verifier.py +1297 -1297
  432. package/md_cg/writelimit.py +356 -356
  433. package/md_cg/writepipe.py +20 -8
  434. package/package.json +101 -96
  435. package/skills/plugin.json +54 -54
  436. package/skills/skills/designer-perspective/SKILL.md +158 -158
  437. package/skills/skills/designer-perspective/references/01-observation-position.md +66 -66
  438. package/skills/skills/designer-perspective/references/02-structure-recognition.md +62 -62
  439. package/skills/skills/designer-perspective/references/03-direction-judgment.md +55 -55
  440. package/skills/skills/designer-perspective/references/04-qualification-verdict.md +72 -72
  441. package/skills/skills/designer-perspective/references/05-condition-attribution.md +74 -74
  442. package/skills/skills/designer-perspective/scripts/designer.py +545 -545
  443. package/skills/skills/designer-perspective/tests/cases.jsonl +17 -17
  444. package/skills/skills/designer-perspective/tests/selftest.py +61 -61
  445. package/skills/skills/lingshu-browser/SKILL.md +60 -60
  446. package/skills/skills/lingshu-compiler/SKILL.md +56 -56
  447. package/skills/skills/lingshu-compiler/units/analyze-type-infer/SKILL.md +45 -45
  448. package/skills/skills/lingshu-compiler/units/check-name-real/SKILL.md +45 -45
  449. package/skills/skills/lingshu-compiler/units/compile-assign/SKILL.md +45 -45
  450. package/skills/skills/lingshu-compiler/units/compile-expr-tree/SKILL.md +45 -45
  451. package/skills/skills/lingshu-compiler/units/compile-full-pipeline/SKILL.md +45 -45
  452. package/skills/skills/lingshu-compiler/units/compile-func-def/SKILL.md +45 -45
  453. package/skills/skills/lingshu-compiler/units/compile-if-then/SKILL.md +45 -45
  454. package/skills/skills/lingshu-compiler/units/compile-logic-expr/SKILL.md +45 -45
  455. package/skills/skills/lingshu-compiler/units/compile-recursive/SKILL.md +45 -45
  456. package/skills/skills/lingshu-compiler/units/compile-scope/SKILL.md +45 -45
  457. package/skills/skills/lingshu-compiler/units/compile-type-check/SKILL.md +45 -45
  458. package/skills/skills/lingshu-compiler/units/compile-while/SKILL.md +45 -45
  459. package/skills/skills/lingshu-compiler/units/compiler-0010c4bf/SKILL.md +45 -45
  460. package/skills/skills/lingshu-compiler/units/compiler-0355bffb/SKILL.md +45 -45
  461. package/skills/skills/lingshu-compiler/units/compiler-0361708a/SKILL.md +45 -45
  462. package/skills/skills/lingshu-compiler/units/compiler-054a0414/SKILL.md +45 -45
  463. package/skills/skills/lingshu-compiler/units/compiler-05a1691a/SKILL.md +45 -45
  464. package/skills/skills/lingshu-compiler/units/compiler-05eeed1e/SKILL.md +45 -45
  465. package/skills/skills/lingshu-compiler/units/compiler-0622a1f6/SKILL.md +45 -45
  466. package/skills/skills/lingshu-compiler/units/compiler-08b54217/SKILL.md +45 -45
  467. package/skills/skills/lingshu-compiler/units/compiler-0a62b70c/SKILL.md +45 -45
  468. package/skills/skills/lingshu-compiler/units/compiler-0ab24d00/SKILL.md +45 -45
  469. package/skills/skills/lingshu-compiler/units/compiler-0e093688/SKILL.md +45 -45
  470. package/skills/skills/lingshu-compiler/units/compiler-0e82b966/SKILL.md +45 -45
  471. package/skills/skills/lingshu-compiler/units/compiler-0ee9b9b9/SKILL.md +45 -45
  472. package/skills/skills/lingshu-compiler/units/compiler-0f3787e6/SKILL.md +45 -45
  473. package/skills/skills/lingshu-compiler/units/compiler-1028685f/SKILL.md +45 -45
  474. package/skills/skills/lingshu-compiler/units/compiler-11897630/SKILL.md +45 -45
  475. package/skills/skills/lingshu-compiler/units/compiler-16661b9b/SKILL.md +45 -45
  476. package/skills/skills/lingshu-compiler/units/compiler-1f722303/SKILL.md +45 -45
  477. package/skills/skills/lingshu-compiler/units/compiler-25be1262/SKILL.md +45 -45
  478. package/skills/skills/lingshu-compiler/units/compiler-2a76ba07/SKILL.md +45 -45
  479. package/skills/skills/lingshu-compiler/units/compiler-2dbea54a/SKILL.md +45 -45
  480. package/skills/skills/lingshu-compiler/units/compiler-2df52f16/SKILL.md +45 -45
  481. package/skills/skills/lingshu-compiler/units/compiler-2ec2c9d2/SKILL.md +45 -45
  482. package/skills/skills/lingshu-compiler/units/compiler-2f8c8f39/SKILL.md +45 -45
  483. package/skills/skills/lingshu-compiler/units/compiler-38378ac7/SKILL.md +45 -45
  484. package/skills/skills/lingshu-compiler/units/compiler-39457d2e/SKILL.md +45 -45
  485. package/skills/skills/lingshu-compiler/units/compiler-39fb5926/SKILL.md +45 -45
  486. package/skills/skills/lingshu-compiler/units/compiler-47f4fbfa/SKILL.md +45 -45
  487. package/skills/skills/lingshu-compiler/units/compiler-4a8cd1f1/SKILL.md +45 -45
  488. package/skills/skills/lingshu-compiler/units/compiler-4b230b6b/SKILL.md +45 -45
  489. package/skills/skills/lingshu-compiler/units/compiler-4cbbda95/SKILL.md +45 -45
  490. package/skills/skills/lingshu-compiler/units/compiler-4d5a68ff/SKILL.md +45 -45
  491. package/skills/skills/lingshu-compiler/units/compiler-56dc9bdd/SKILL.md +45 -45
  492. package/skills/skills/lingshu-compiler/units/compiler-57e76ebe/SKILL.md +45 -45
  493. package/skills/skills/lingshu-compiler/units/compiler-61ff016b/SKILL.md +45 -45
  494. package/skills/skills/lingshu-compiler/units/compiler-63eae588/SKILL.md +45 -45
  495. package/skills/skills/lingshu-compiler/units/compiler-64c4224b/SKILL.md +45 -45
  496. package/skills/skills/lingshu-compiler/units/compiler-66377955/SKILL.md +45 -45
  497. package/skills/skills/lingshu-compiler/units/compiler-674ab4f6/SKILL.md +45 -45
  498. package/skills/skills/lingshu-compiler/units/compiler-6af76fd6/SKILL.md +45 -45
  499. package/skills/skills/lingshu-compiler/units/compiler-6d979db2/SKILL.md +45 -45
  500. package/skills/skills/lingshu-compiler/units/compiler-6de326c0/SKILL.md +45 -45
  501. package/skills/skills/lingshu-compiler/units/compiler-6f1c0eea/SKILL.md +45 -45
  502. package/skills/skills/lingshu-compiler/units/compiler-724d6c9b/SKILL.md +45 -45
  503. package/skills/skills/lingshu-compiler/units/compiler-7690177f/SKILL.md +45 -45
  504. package/skills/skills/lingshu-compiler/units/compiler-7b229a7d/SKILL.md +45 -45
  505. package/skills/skills/lingshu-compiler/units/compiler-7f471b3a/SKILL.md +45 -45
  506. package/skills/skills/lingshu-compiler/units/compiler-815cad08/SKILL.md +45 -45
  507. package/skills/skills/lingshu-compiler/units/compiler-83c61634/SKILL.md +45 -45
  508. package/skills/skills/lingshu-compiler/units/compiler-8c798c81/SKILL.md +45 -45
  509. package/skills/skills/lingshu-compiler/units/compiler-8dd747ac/SKILL.md +45 -45
  510. package/skills/skills/lingshu-compiler/units/compiler-90324d0a/SKILL.md +45 -45
  511. package/skills/skills/lingshu-compiler/units/compiler-94b8d72d/SKILL.md +45 -45
  512. package/skills/skills/lingshu-compiler/units/compiler-94f12231/SKILL.md +45 -45
  513. package/skills/skills/lingshu-compiler/units/compiler-95937c16/SKILL.md +45 -45
  514. package/skills/skills/lingshu-compiler/units/compiler-98a5625b/SKILL.md +45 -45
  515. package/skills/skills/lingshu-compiler/units/compiler-98b4c42f/SKILL.md +45 -45
  516. package/skills/skills/lingshu-compiler/units/compiler-98e3894a/SKILL.md +45 -45
  517. package/skills/skills/lingshu-compiler/units/compiler-9bdfe4b8/SKILL.md +45 -45
  518. package/skills/skills/lingshu-compiler/units/compiler-9d9b4e83/SKILL.md +45 -45
  519. package/skills/skills/lingshu-compiler/units/compiler-9f7be5ad/SKILL.md +45 -45
  520. package/skills/skills/lingshu-compiler/units/compiler-a6daf076/SKILL.md +45 -45
  521. package/skills/skills/lingshu-compiler/units/compiler-a7995a0c/SKILL.md +45 -45
  522. package/skills/skills/lingshu-compiler/units/compiler-a8399248/SKILL.md +45 -45
  523. package/skills/skills/lingshu-compiler/units/compiler-aabbd099/SKILL.md +45 -45
  524. package/skills/skills/lingshu-compiler/units/compiler-afe169d8/SKILL.md +45 -45
  525. package/skills/skills/lingshu-compiler/units/compiler-b0678bda/SKILL.md +45 -45
  526. package/skills/skills/lingshu-compiler/units/compiler-b09bd196/SKILL.md +45 -45
  527. package/skills/skills/lingshu-compiler/units/compiler-b1396e23/SKILL.md +45 -45
  528. package/skills/skills/lingshu-compiler/units/compiler-b9b31ce0/SKILL.md +45 -45
  529. package/skills/skills/lingshu-compiler/units/compiler-c10264a7/SKILL.md +45 -45
  530. package/skills/skills/lingshu-compiler/units/compiler-cb1e8e4b/SKILL.md +45 -45
  531. package/skills/skills/lingshu-compiler/units/compiler-ccafd438/SKILL.md +45 -45
  532. package/skills/skills/lingshu-compiler/units/compiler-cda9c262/SKILL.md +45 -45
  533. package/skills/skills/lingshu-compiler/units/compiler-ce648068/SKILL.md +45 -45
  534. package/skills/skills/lingshu-compiler/units/compiler-cf5776a4/SKILL.md +45 -45
  535. package/skills/skills/lingshu-compiler/units/compiler-d974e5d3/SKILL.md +45 -45
  536. package/skills/skills/lingshu-compiler/units/compiler-e3979fd3/SKILL.md +45 -45
  537. package/skills/skills/lingshu-compiler/units/compiler-eb1cf2b5/SKILL.md +45 -45
  538. package/skills/skills/lingshu-compiler/units/compiler-ecb30d5b/SKILL.md +45 -45
  539. package/skills/skills/lingshu-compiler/units/compiler-f8c8b24b/SKILL.md +45 -45
  540. package/skills/skills/lingshu-compiler/units/compiler-f99fedbe/SKILL.md +45 -45
  541. package/skills/skills/lingshu-compiler/units/compiler-fa8ff5f7/SKILL.md +45 -45
  542. package/skills/skills/lingshu-compiler/units/compiler-fe1b058d/SKILL.md +45 -45
  543. package/skills/skills/lingshu-compiler/units/lex-chinese-program/SKILL.md +45 -45
  544. package/skills/skills/lingshu-compiler/units/lex-dao-de-jing/SKILL.md +45 -45
  545. package/skills/skills/lingshu-compiler/units/lex-nine-chapters/SKILL.md +45 -45
  546. package/skills/skills/lingshu-compiler/units/vm-arithmetic/SKILL.md +45 -45
  547. package/skills/skills/lingshu-compiler/units/vm-array-ops/SKILL.md +45 -45
  548. package/skills/skills/lingshu-compiler/units/vm-closure-call/SKILL.md +45 -45
  549. package/skills/skills/lingshu-compiler/units/vm-closure-create/SKILL.md +45 -45
  550. package/skills/skills/lingshu-compiler/units/vm-compare/SKILL.md +45 -45
  551. package/skills/skills/lingshu-compiler/units/vm-cond-jump/SKILL.md +45 -45
  552. package/skills/skills/lingshu-compiler/units/vm-cond-space/SKILL.md +45 -45
  553. package/skills/skills/lingshu-compiler/units/vm-exception/SKILL.md +45 -45
  554. package/skills/skills/lingshu-compiler/units/vm-func-call/SKILL.md +45 -45
  555. package/skills/skills/lingshu-compiler/units/vm-loop-run/SKILL.md +45 -45
  556. package/skills/skills/lingshu-compiler/units/vm-profiling/SKILL.md +45 -45
  557. package/skills/skills/lingshu-compiler/units/vm-refcount/SKILL.md +45 -45
  558. package/skills/skills/lingshu-compiler/units/vm-run-loop/SKILL.md +45 -45
  559. package/skills/skills/lingshu-compiler/units/vm-short-circuit/SKILL.md +45 -45
  560. package/skills/skills/lingshu-compiler/units/vm-stack-guard/SKILL.md +45 -45
  561. package/skills/skills/lingshu-compiler/units/vm-stack-ops/SKILL.md +45 -45
  562. package/skills/skills/lingshu-compiler/units/vm-trust-accum/SKILL.md +45 -45
  563. package/skills/skills/lingshu-graph/SKILL.md +63 -63
  564. package/skills/skills/lingshu-net/SKILL.md +48 -48
  565. package/skills/skills/lingshu-os/SKILL.md +64 -64
  566. package/skills/skills/lingshu-pylang/SKILL.md +71 -71
  567. package/src/bridge.ts +33 -0
  568. package/src/hooks.ts +38 -2
  569. package/src/index.ts +526 -518
  570. package/src/lib/datapath.ts +326 -326
  571. package/src/lib/mdcg_client.ts +413 -413
  572. package/src/lib/mutual.ts +428 -428
  573. package/src/lib/prompt_safety.ts +62 -62
  574. package/src/lib/python_path.ts +71 -71
  575. package/src/lib/roleplay_web.ts +116 -29
  576. package/src/lib/token_store.ts +13 -3
  577. package/src/tools.ts +212 -212
  578. package/zcode/AGENTS.md +11 -3
  579. package/zcode/README.md +41 -41
  580. /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,433 +1,433 @@
1
- # -*- coding: utf-8 -*-
2
- """ccgc 验收:对话记录 → CCG 六要素编译器(V1-V20)。
3
-
4
- 运行:python -m md_cg.test_ccgc
5
-
6
- 三条判据在实现层为何是**机械可判定**的(不依赖自觉):
7
- ① 「LLM 不得自己验证自己」——候选结构里没有签章字段,且 attest 机械比对
8
- `verifier != compiled_by`(E041);link 再挡一次(双闸)。
9
- ② 「幻觉」——名实门 E010/E011:每个写入值必须是源文本字面子串,零灰区。
10
- ③ 「缺参数」——是编译错误(E001-E004)而非 DEFER,`success = (errors == [])`。
11
-
12
- V16-V20 覆盖**跨调用形态**(三次独立 MCP 调用传不动对象,只能落盘):
13
- 候选与签章绑定在 `_ccgc_pending/`(hash 防篡改)+ 复核通道三态 + 蜂巢契约
14
- 端到端(假执行器模拟 serve,无网络无密钥也能确定性验收「通道与签章」)。
15
- """
16
- from __future__ import annotations
17
-
18
- import json
19
- import os
20
- import shutil
21
- import sys
22
- import tempfile
23
- import threading
24
- import time
25
-
26
- from . import audit, backfill, ccgc, nodefile, units
27
- from .mdcos import MdCGOS
28
-
29
- PASS = FAIL = 0
30
- FAILS = []
31
-
32
- DIALOG = ("文件摄取分派:按扩展名把文件路由到对应摄取器"
33
- "。该方法使用扩展名映射表进行路由"
34
- "。此功能在本地文件系统中生效"
35
- "。仅对本地可读文件生效"
36
- "。2026-09-16"
37
- "。通过回放测试验证"
38
- "。二进制文件不适用")
39
-
40
- SLOTS = {
41
- "observation_position": {"value": "此功能在本地文件系统中生效"},
42
- "observation_tool": {"value": "该方法使用扩展名映射表进行路由"},
43
- "time_window": {"value": [0.0, 9999999999.0]},
44
- "existence_constraint": {"value": "仅对本地可读文件生效"},
45
- }
46
-
47
- MARKS = {
48
- "功能名": {"value": "文件摄取分派:按扩展名把文件路由到对应摄取器"},
49
- "子功能": {"value": "按扩展名把文件路由到对应摄取器"},
50
- "执行": {"value": "使用扩展名映射表进行路由"},
51
- "验证方式": {"value": "回放测试", "basis": "test"},
52
- "不适用条件": {"value": "二进制文件不适用"},
53
- }
54
-
55
-
56
- def ok(cond, label):
57
- global PASS, FAIL
58
- if cond:
59
- PASS += 1
60
- else:
61
- FAIL += 1
62
- FAILS.append(label)
63
- print(" FAIL " + label)
64
-
65
-
66
- def _has(errs, code):
67
- return any(str(e).startswith(code) for e in (errs or []))
68
-
69
-
70
- def _seed(root):
71
- cg = MdCGOS(root)
72
- cg.add("tgt", "# 功能名:待编译节点\n\n占位正文。\n", layer="knowledge")
73
- cg.flush()
74
- cg.rebuild_index()
75
- return cg
76
-
77
-
78
- def _fake_serve(jobs, stop, seen):
79
- """假蜂巢执行器:读 spec.json 写 result.json(契约与 hive 的 LLM 委托型一致)。
80
-
81
- 用线程模拟 serve 侧的单元执行,使**复核通道与签章搬运**在无网络无密钥下
82
- 可确定性验收——被测的是通道契约,不是模型质量。seen 记录 spec 形态供断言。
83
- """
84
- while not stop.is_set():
85
- try:
86
- names = sorted(os.listdir(jobs))
87
- except OSError:
88
- names = []
89
- for jid in names:
90
- d = os.path.join(jobs, jid)
91
- sp = os.path.join(d, units.SPEC_FILE)
92
- rp = os.path.join(d, units.RESULT_FILE)
93
- if not jid.startswith("h") or not os.path.isfile(sp) or os.path.exists(rp):
94
- continue
95
- try:
96
- with open(sp, encoding="utf-8") as f:
97
- spec = json.load(f)
98
- except (OSError, ValueError):
99
- continue
100
- prompt = str(spec.get("user_prompt") or spec.get("prompt") or "")
101
- seen.update({"role": spec.get("role"), "model": spec.get("model"),
102
- "prompt_len": len(prompt),
103
- "prompt_has_dialog": "文件摄取分派" in prompt})
104
- payload = {"verdict": seen.get("verdict") or "accept",
105
- "reason": "假单元复核:候选与对话原文一致",
106
- "slot_corrections": {}}
107
- try:
108
- with open(rp, "w", encoding="utf-8") as f:
109
- json.dump({"ok": True, "model": spec.get("model"),
110
- "content": json.dumps(payload, ensure_ascii=False)},
111
- f, ensure_ascii=False)
112
- except OSError:
113
- continue
114
- time.sleep(0.05)
115
-
116
-
117
- def _import_mcp():
118
- """延迟导入工具面(避免测试顶部把 server 依赖一并拉起)。"""
119
- try:
120
- from . import mcp_server
121
- return mcp_server
122
- except Exception: # noqa: BLE001
123
- return None
124
-
125
-
126
- def main():
127
- global PASS, FAIL
128
- tmp = tempfile.mkdtemp(prefix="mdcg_ccgc_")
129
- try:
130
- root = os.path.join(tmp, "root")
131
- os.makedirs(root, exist_ok=True)
132
- cg = _seed(root)
133
-
134
- # ---------- V1 缺参即编译错误(裁定 B) ----------
135
- r = ccgc.compile_dialog("", "tgt", "agent:a1")
136
- ok((not r.success) and _has(r.errors, "E001"), "V1a 缺 dialog → E001")
137
- r = ccgc.compile_dialog(DIALOG, "", "agent:a1")
138
- ok((not r.success) and _has(r.errors, "E002"), "V1b 缺 node_id → E002")
139
- r = ccgc.compile_dialog(DIALOG, "tgt", "")
140
- ok((not r.success) and _has(r.errors, "E003"), "V1c 缺 actor → E003")
141
- r = ccgc.compile_dialog(DIALOG, "nope", "agent:a1", cg=cg)
142
- ok((not r.success) and _has(r.errors, "E002"), "V1d 节点不存在 → E002")
143
- ok(bool(r.verdict) and r.verdict.get("authority") == "VERIFICATION_UNIT",
144
- "V1e 终裁 authority=VERIFICATION_UNIT")
145
-
146
- # ---------- V2 名实门:幻觉在编译期被机械检出 ----------
147
- bad_slots = dict(SLOTS)
148
- bad_slots["observation_tool"] = {"value": "该方法使用神经网络进行路由",
149
- "span": "该方法使用神经网络进行路由"}
150
- r_bad = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
151
- slots=bad_slots, marks=MARKS, cg=cg)
152
- ok((not r_bad.success) and _has(r_bad.errors, "E011"), "V2a 捏造值 → E011")
153
- ok(len(r_bad.ungrounded) >= 1, "V2b 未过门项进入 ungrounded 台账")
154
-
155
- bad2 = dict(SLOTS)
156
- bad2["observation_position"] = {"value": "此功能在本地文件系统中生效",
157
- "span": "不存在的引用文本"}
158
- r2 = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
159
- slots=bad2, marks=MARKS, cg=cg)
160
- ok((not r2.success) and _has(r2.errors, "E010"), "V2c 引用定位失败 → E010")
161
-
162
- class EvilParser(object):
163
- """冒充 LLM 通道:给出看起来合理但源文本里没有的值。"""
164
-
165
- def candidates(self, dialog, ctx):
166
- return {"marks": dict(MARKS), "slots": dict(bad_slots)}
167
-
168
- r3 = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
169
- parser=EvilParser(), cg=cg)
170
- ok((not r3.success) and _has(r3.errors, "E011"),
171
- "V2d 外部 parser 幻觉同样被 E011 拦截(结构级阻断)")
172
-
173
- # ---------- V3 四槽强制 ----------
174
- r4 = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
175
- slots={"observation_position": SLOTS["observation_position"]},
176
- marks=MARKS, cg=cg)
177
- ok((not r4.success) and _has(r4.errors, "E020"), "V3a 四槽不全 → E020")
178
-
179
- # ---------- V4/V5 唯一合成入口 + 六要素齐备 ----------
180
- plain_slots = {k: v.get("value") for k, v in SLOTS.items()}
181
- r = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
182
- slots=SLOTS, marks=MARKS, cg=cg)
183
- ok(r.success, "V4a 完整入参编译成功")
184
- ok(r.lines.get("生效条件") == nodefile.condition_space_text(plain_slots),
185
- "V4b 生效条件 == nodefile.condition_space_text(唯一入口)")
186
- ok(set(r.lines) == set(nodefile.CCG_MARKS), "V5a 六要素齐备")
187
- ok(r.sources.get("verification_basis") == "test", "V5b 验证基底 test")
188
-
189
- # ---------- V7 自证拒绝(裁定 A 核心) ----------
190
- a_self = ccgc.attest("tgt", ccgc.ACCEPT, "agent:a1", "agent:a1", cg=cg)
191
- ok((not a_self.ok) and "E041" in a_self.error, "V7a 验证方==编译方 → E041")
192
- a_defer = ccgc.attest("tgt", ccgc.DEFER, "designer", "agent:a1", cg=cg)
193
- ok((not a_defer.ok) and "E042" in a_defer.error, "V7b DEFER 不构成签章")
194
- a_ok = ccgc.attest("tgt", ccgc.ACCEPT, "designer", "agent:a1",
195
- evidence="设计者核对原文一致", cg=cg)
196
- ok(a_ok.ok and bool(a_ok.token), "V7c 编外验证方 ACCEPT → 有效签章")
197
-
198
- # ---------- V8 无章不写 ----------
199
- l0 = ccgc.link(r, None, cg=cg, apply=True)
200
- ok((not l0.ok) and any("E040" in e for e in l0.errors), "V8a 无签章 → E040 拒绝")
201
- l1 = ccgc.link(r, a_self, cg=cg, apply=True)
202
- ok(not l1.ok, "V8b 自证签章 → link 拒绝")
203
- l2 = ccgc.link(r, a_ok, cg=cg, apply=False)
204
- ok(l2.ok and l2.dry_run and l2.written == 0, "V8c dry-run 不写入")
205
- _fm_b, c_before = cg._read(cg.index["nodes"]["tgt"])
206
- ok(not nodefile.ccg_completeness(c_before)["complete"], "V5c link 前六要素不全")
207
-
208
- # ---------- link 落库 ----------
209
- l3 = ccgc.link(r, a_ok, cg=cg, apply=True)
210
- ok(l3.ok and l3.written == 6, "V8d 签章通过 → 写入六行")
211
- fm_after, c_after = cg._read(cg.index["nodes"]["tgt"])
212
- ok(nodefile.ccg_completeness(c_after)["complete"],
213
- "V5d link 后六要素齐备(可判定性提升)")
214
- ok(fm_after.get("condition_space") == plain_slots, "V4c condition_space 落 frontmatter")
215
- ok(fm_after.get("verification_basis") == "test", "V5e verification_basis 落盘")
216
-
217
- # ---------- V6 未制造条件污染 ----------
218
- rep = backfill.verify_conditions(cg)
219
- ok(rep.get("legacy_position") == 0, "V6a 弱等价残留 legacy_position == 0")
220
- ok(rep.get("from_synthesis", 0) >= 1, "V6b 生效条件来源=合成")
221
-
222
- # ---------- V9 缺验证器恒 DEFER(能力外置) ----------
223
- v = audit.audit("ccg_marks", {"node": "tgt"}, {})
224
- ok(v.get("state") == "DEFER", "V9a 未注入验证器 → DEFER(不假装通过)")
225
- ok(audit.kinds()["ccg_marks"]["basis"] == "test", "V9b ccg_marks 基底建议=test")
226
-
227
- # ---------- V11 用后续验证修正生效条件 ----------
228
- rc = ccgc.recalibrate("tgt", {"existence_constraint": "仅对本地可读文件生效"},
229
- "agent:a1", "agent:a1", cg=cg, apply=False)
230
- ok(any("E041" in e for e in rc.errors), "V11a 修正方==编译方 → E041")
231
- rc = ccgc.recalibrate("tgt", {"生效条件": "手写条件"}, "designer", "agent:a1",
232
- cg=cg, apply=False)
233
- ok(any("E043" in e for e in rc.errors), "V11b 非四槽键 → E043(无第二通路)")
234
- rc = ccgc.recalibrate("tgt", {"observation_tool": "该方法使用扩展名映射表进行路由"},
235
- "designer", "agent:a1", evidence="实测复核:方法槽无误",
236
- cg=cg, apply=True)
237
- ok(rc.ok, "V11c 编外验证方修正获准")
238
- _fm_r, c_r = cg._read(cg.index["nodes"]["tgt"])
239
- ok(nodefile.ccg_completeness(c_r)["complete"], "V11d 修正后仍齐备")
240
- logs = ccgc._read_jsonl(ccgc._log_path(cg))
241
- ok(any(x.get("action") == "ccgc_recalibrate" and x.get("slots_before") is not None
242
- and x.get("slots_after") is not None for x in logs),
243
- "V11e 修正留痕含 before/after(可溯源)")
244
- ok(any(x.get("action") == "ccgc_attest" for x in logs), "V11f 签章留痕可查")
245
-
246
- # ---------- V13 内生规则解析器:诚实下界 ----------
247
- r_rule = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1", cg=cg)
248
- ok(any("下界能力" in w for w in r_rule.warnings), "V13a 未注入解析器时如实声明下界")
249
- bad_spans = [s for arr in r_rule.spans.values() for s in arr
250
- if s and s not in DIALOG]
251
- ok(not bad_spans, "V13b 内生解析器引用全部 grounded")
252
-
253
- # ---------- V14 产物无占位残留 ----------
254
- ok(not any(nodefile.is_placeholder_text(x) for x in r.lines.values()),
255
- "V14 产物无占位残留")
256
-
257
- # ---------- V15 裁定 B 术语落地:单一真源 + 六要素一一对应 ----------
258
- ok(ccgc.CONTRACT_ROLES is nodefile.CCG_CONTRACT_ROLES,
259
- "V15a 术语真源唯一(ccgc 引用 nodefile,不另定义一份)")
260
- ok(tuple(nodefile.CCG_CONTRACT_ROLES) == tuple(nodefile.CCG_MARKS),
261
- "V15b 契约角色与六要素一一对应(顺序一致)")
262
- ok(nodefile.CCG_CONTRACT_ROLES["生效条件"] == "前置条件 precondition",
263
- "V15c 生效条件角色 = precondition(裁定 B)")
264
-
265
- # ---------- V16 pending:候选与签章绑定(跨 MCP 三次独立调用形态) ----------
266
- p_path = ccgc.pending_path(cg, "tgt")
267
- ok(bool(p_path) and ccgc.PENDING_DIR in p_path, "V16a pending 落 LAYERS 之外的冷区")
268
- sv = ccgc.save_pending(cg, r)
269
- ok(bool(sv.get("ok")) and os.path.isfile(sv["path"]) and bool(sv.get("hash")),
270
- "V16b 候选落盘并留内容摘要")
271
- got = ccgc.load_pending(cg, "tgt")
272
- ok(bool(got.get("ok")) and bool(got.get("hash_ok")), "V16c 读回摘要一致(原件未被改写)")
273
- ok(got["compiled"].lines == r.lines, "V16d 读回六行 == 编译产物(无损搬运)")
274
- with open(sv["path"], encoding="utf-8") as f:
275
- rec = json.load(f)
276
- rec["compiled"]["lines"]["功能名"] = "被篡改的功能名"
277
- with open(sv["path"], "w", encoding="utf-8") as f:
278
- json.dump(rec, f, ensure_ascii=False)
279
- lx = ccgc.link_pending(cg, "tgt", apply=True)
280
- ok((not lx.ok) and any("hash" in e for e in lx.errors),
281
- "V16e 候选被改写 → hash 不符,拒绝写入(签章只忠于原件)")
282
- sv = ccgc.save_pending(cg, r, a_ok)
283
- lz = ccgc.link_pending(cg, "tgt", apply=True, actor="agent:a1")
284
- ok(lz.ok and lz.written == 6, "V16f 读回原件+签章 → 落库成功")
285
- ok(not os.path.isfile(sv["path"]), "V16g 落库成功即清 pending(暂存非存档)")
286
- ok(not any(ccgc.PENDING_DIR in str(k) for k in (cg.index.get("nodes") or {})),
287
- "V16h pending 不进索引(冷区对检索隐身)")
288
-
289
- # ---------- V17 闸门:只认编外裁决,绝不假装通过 ----------
290
- v = audit.audit("ccg_marks", {"node_id": "tgt", "unit_verdict": "ACCEPT",
291
- "verifier": "hive:reflect:h1",
292
- "evidence": "假单元复核:与原文一致"}, {})
293
- ok(v.get("state") == "ACCEPT", "V17a 编外裁决+依据 → ACCEPT")
294
- v = audit.audit("ccg_marks", {"node_id": "tgt", "unit_verdict": "ACCEPT",
295
- "verifier": "hive:reflect:h1"}, {})
296
- ok(v.get("state") == "DEFER", "V17b ACCEPT 但无依据 → DEFER(无依据不通过)")
297
- v = audit.audit("ccg_marks", {"node_id": "tgt", "unit_verdict": "ACCEPT",
298
- "verifier": "agent:a1", "evidence": "我自己验的"},
299
- {"compiled_by": "agent:a1"})
300
- ok(v.get("state") == "REJECT", "V17c 自证 → REJECT(E041 在闸门层再挡一次)")
301
- v = audit.audit("ccg_marks", {"node_id": "tgt", "unit_verdict": "ACCEPT",
302
- "evidence": "无验证方"}, {})
303
- ok(v.get("state") == "DEFER", "V17d 有裁决缺验证方标识 → DEFER")
304
- v = audit.audit("ccg_marks", {"node_id": "tgt"}, {})
305
- d = v.get("detail") or {}
306
- ok(v.get("state") == "DEFER" and bool(d.get("next")) and d.get("channel_state") in units.STATES,
307
- "V17e 无裁决 → DEFER 且给出下一步通道(不阻塞写路径)")
308
- v = audit.audit("ccg_marks", {}, {})
309
- ok(v.get("state") == "DEFER", "V17f 缺 node_id → DEFER")
310
-
311
- # ---------- V18 复核通道:三态如实 + 来源标识结构上非编译者 ----------
312
- ok(units.transport_name(units.HIVE, units.REFLECT, "h1") == "hive:reflect:h1",
313
- "V18a 蜂巢来源标识 = hive:<role>:<job>")
314
- ok(units.transport_name(units.HIVE, units.REFLECT, "h1") != "agent:a1",
315
- "V18b 来源标识结构上不可能等于编译者(裁定 A 不被误伤)")
316
- u = units.verdict_of('前置说明\n```json\n{"verdict":"accept","reason":"一致"}\n```')
317
- ok(u["verdict"] == units.ACCEPT and bool(u["parsed"]), "V18c 围栏 JSON 可解析 → ACCEPT")
318
- u = units.verdict_of("我无法判断这件事")
319
- ok(u["verdict"] == units.DEFER and not u["parsed"], "V18d 解析不出 → DEFER(不猜测)")
320
- u = units.verdict_of({"verdict": "drop", "reason": "与原文不符",
321
- "slot_corrections": {"observation_tool": "x"}})
322
- ok(u["verdict"] == units.REJECT and bool(u["slot_corrections"]),
323
- "V18e drop → REJECT(四槽修正随裁决带回)")
324
- aa = units.to_attest_args({"verdict": units.ACCEPT, "reason": "一致"}, state=units.HIVE,
325
- role=units.REFLECT, job_id="h1",
326
- compiled_by=units.transport_name(units.HIVE, units.REFLECT, "h1"))
327
- ok(aa.get("self_verify") is True, "V18f 万一自证 → 显式标记(供上层拒绝)")
328
- aa = units.to_attest_args({"verdict": units.ACCEPT, "reason": "一致"}, state=units.HIVE,
329
- role=units.REFLECT, job_id="h1", compiled_by="agent:a1")
330
- ok(not aa.get("self_verify") and aa["verifier"].startswith("hive:reflect:"),
331
- "V18g 非自证:verifier 取蜂巢来源标识(不设自证标记)")
332
- pr = units.probe(jobs=os.path.join(tmp, "nojobs"))
333
- ok(pr["state"] == units.CONFIGURE and units.ENV_MODEL in pr["hint"],
334
- "V18h 蜂巢不可用 → 返回配置指引(不自动拉起、不假装可用)")
335
- pr = units.probe(jobs=os.path.join(tmp, "nojobs"), allow_degrade=True)
336
- ok(pr["state"] == units.SUBAGENT, "V18i 显式 allow_degrade → 子代理降级(不冒充 hive)")
337
-
338
- # ---------- V19/V20 端到端:假蜂巢 → 编外裁决 → 签章 → 落库 ----------
339
- jobs = os.path.join(tmp, "jobs")
340
- os.makedirs(jobs, exist_ok=True)
341
- # 假 serve 是**本进程内的线程**,故「该 pid 是本程序」如实为真——把本程序
342
- # 口径指向本进程映像名即可(v14 缺陷 E 修复后 units 判活含**身份层**:
343
- # 旧写法心跳 pid=本进程却让 EXE 口径指向 hive.exe,身份层判假 → 通道不可用,
344
- # 那不是被测缺陷而是测试自身要与新口径对齐)。
345
- _old_exe = os.environ.get(units.ENV_EXE)
346
- os.environ[units.ENV_EXE] = sys.executable
347
- with open(os.path.join(jobs, units.SERVE_FILE), "w", encoding="utf-8") as f:
348
- json.dump({"ts": int(time.time() * 1000), "pid": os.getpid()}, f)
349
- seen = {}
350
- stop = threading.Event()
351
- th = threading.Thread(target=_fake_serve, args=(jobs, stop, seen), daemon=True)
352
- th.start()
353
- _old_model = os.environ.get(units.ENV_MODEL)
354
- os.environ[units.ENV_MODEL] = "fake-unit-model"
355
- try:
356
- pr = units.probe(jobs=jobs)
357
- ok(pr["state"] == units.HIVE, "V19a 心跳新鲜+模型已配 → HIVE 可派发")
358
- rv = units.review(digest=r, dialog=DIALOG, role=units.REFLECT, node_id="tgt",
359
- jobs=jobs, blocking=True, wait_s=30, cg=cg, actor="agent:a1")
360
- ok(rv["state"] == units.HIVE and bool(rv.get("unit")), "V19b 派发并取回编外裁决")
361
- ok((rv["unit"] or {}).get("verdict") == units.ACCEPT, "V19c 单元裁决解析为 ACCEPT")
362
- ok(seen.get("role") == units.REFLECT and seen.get("model") == "fake-unit-model"
363
- and seen.get("prompt_has_dialog"),
364
- "V19d spec 形态合蜂巢契约(role/model/复核包正文)")
365
- ok(str((rv.get("attest") or {}).get("verifier") or "").startswith("hive:reflect:"),
366
- "V19e 签章方 = 蜂巢单元标识(结构上非编译者)")
367
- at = ccgc.attest("tgt", rv["attest"]["verdict"], rv["attest"]["verifier"],
368
- "agent:a1", evidence=rv["attest"]["evidence"] or "单元复核",
369
- cg=cg)
370
- ok(at.ok, "V19f 蜂巢裁决可直接签章(E041 不被误伤)")
371
- logs = ccgc._read_jsonl(os.path.join(str(cg.root), units.LOG_NAME))
372
- ok(any(x.get("action") == "review" and x.get("job_id") for x in logs),
373
- "V19g 派发留痕(job_id 可追溯)")
374
-
375
- # --- V20 MCP 工具面:compile → review → attest/link 三段式 ---
376
- mcp = _import_mcp()
377
- ok(mcp is not None, "V20a 工具面可加载")
378
- c1 = mcp._ccg_call(cg, {"ccg": {"action": "catalog"}})
379
- ok(c1["ok"] and "compile" in c1["actions"] and "E041" in c1["errors"],
380
- "V20b catalog 自描述(动作清单 + 错误码)")
381
- c2 = mcp._ccg_call(cg, {"ccg": {"action": "compile", "node_id": "tgt",
382
- "dialog": DIALOG, "marks": MARKS, "slots": SLOTS}})
383
- ok(c2["ok"] and c2["compiled"]["success"] and c2["pending"]["ok"],
384
- "V20c compile 成功并落 pending(不当场写库)")
385
- ok("E041" in c2["hint"], "V20d hint 指向编外复核(裁定 A 对调用方可见)")
386
- c3 = mcp._ccg_call(cg, {"ccg": {"action": "attest", "node_id": "tgt",
387
- "verdict": "ACCEPT", "verifier": c2["compiled_by"],
388
- "compiled_by": c2["compiled_by"],
389
- "evidence": "我自己验的"}})
390
- ok((not c3["ok"]) and "E041" in str(c3["attest"]["error"]),
391
- "V20e MCP 面自证 → E041(机械拒绝,不靠自觉)")
392
- c4 = mcp._ccg_call(cg, {"ccg": {"action": "link", "node_id": "tgt", "apply": True}})
393
- ok(not c4["ok"], "V20f 自证章不构成准入 → link 拒绝")
394
- c5 = mcp._ccg_call(cg, {"ccg": {"action": "review", "node_id": "tgt",
395
- "jobs": jobs, "blocking": True, "wait_s": 30}})
396
- ok(c5["state"] == units.HIVE and c5["verdict"] == "ACCEPT" and c5["passed"] is True,
397
- "V20g review 取回裁决:ok/verdict/passed 三者分离")
398
- ok(bool((c5.get("attest") or {}).get("ok")), "V20h 拿到裁决即自动签章")
399
- c7 = mcp._ccg_call(cg, {"ccg": {"action": "review", "node_id": "tgt",
400
- "jobs": jobs, "blocking": False}})
401
- ok(c7["state"] == units.HIVE and c7["verdict"] is None and c7["passed"] is False,
402
- "V20j 非阻塞:派发成功但裁决未回(verdict=None,不冒充通过)")
403
- c6 = mcp._ccg_call(cg, {"ccg": {"action": "link", "node_id": "tgt", "apply": True}})
404
- ok(c6["ok"] and c6["link"]["written"] == 6, "V20i link 落库(三段式闭环)")
405
- c10 = mcp._ccg_call(cg, {"ccg": {"action": "link", "node_id": "tgt", "apply": True}})
406
- ok(not c10["ok"], "V20m 落库后 pending 已清 → 再 link 明确报错(暂存非存档)")
407
- c8 = mcp._ccg_call(cg, {"ccg": {"action": "units", "jobs": jobs, "doctor": True}})
408
- ok(c8["ok"] and c8["action"] == "units", "V20k units/doctor 走三级链体检")
409
- c9 = mcp._ccg_call(cg, {"ccg": {"action": "nope"}})
410
- ok(not c9["ok"], "V20l 未知 action → 明确报错(不静默降级)")
411
- finally:
412
- stop.set()
413
- th.join(timeout=3)
414
- if _old_model is None:
415
- os.environ.pop(units.ENV_MODEL, None)
416
- else:
417
- os.environ[units.ENV_MODEL] = _old_model
418
- if _old_exe is None:
419
- os.environ.pop(units.ENV_EXE, None)
420
- else:
421
- os.environ[units.ENV_EXE] = _old_exe
422
-
423
- finally:
424
- print()
425
- print("ccgc: PASS=%d FAIL=%d" % (PASS, FAIL))
426
- if FAILS:
427
- print("FAILS: " + "; ".join(FAILS))
428
- shutil.rmtree(tmp, ignore_errors=True)
429
- return 1 if FAIL else 0
430
-
431
-
432
- if __name__ == "__main__":
433
- sys.exit(main())
1
+ # -*- coding: utf-8 -*-
2
+ """ccgc 验收:对话记录 → CCG 六要素编译器(V1-V20)。
3
+
4
+ 运行:python -m md_cg.test_ccgc
5
+
6
+ 三条判据在实现层为何是**机械可判定**的(不依赖自觉):
7
+ ① 「LLM 不得自己验证自己」——候选结构里没有签章字段,且 attest 机械比对
8
+ `verifier != compiled_by`(E041);link 再挡一次(双闸)。
9
+ ② 「幻觉」——名实门 E010/E011:每个写入值必须是源文本字面子串,零灰区。
10
+ ③ 「缺参数」——是编译错误(E001-E004)而非 DEFER,`success = (errors == [])`。
11
+
12
+ V16-V20 覆盖**跨调用形态**(三次独立 MCP 调用传不动对象,只能落盘):
13
+ 候选与签章绑定在 `_ccgc_pending/`(hash 防篡改)+ 复核通道三态 + 蜂巢契约
14
+ 端到端(假执行器模拟 serve,无网络无密钥也能确定性验收「通道与签章」)。
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import json
19
+ import os
20
+ import shutil
21
+ import sys
22
+ import tempfile
23
+ import threading
24
+ import time
25
+
26
+ from . import audit, backfill, ccgc, nodefile, units
27
+ from .mdcos import MdCGOS
28
+
29
+ PASS = FAIL = 0
30
+ FAILS = []
31
+
32
+ DIALOG = ("文件摄取分派:按扩展名把文件路由到对应摄取器"
33
+ "。该方法使用扩展名映射表进行路由"
34
+ "。此功能在本地文件系统中生效"
35
+ "。仅对本地可读文件生效"
36
+ "。2026-09-16"
37
+ "。通过回放测试验证"
38
+ "。二进制文件不适用")
39
+
40
+ SLOTS = {
41
+ "observation_position": {"value": "此功能在本地文件系统中生效"},
42
+ "observation_tool": {"value": "该方法使用扩展名映射表进行路由"},
43
+ "time_window": {"value": [0.0, 9999999999.0]},
44
+ "existence_constraint": {"value": "仅对本地可读文件生效"},
45
+ }
46
+
47
+ MARKS = {
48
+ "功能名": {"value": "文件摄取分派:按扩展名把文件路由到对应摄取器"},
49
+ "子功能": {"value": "按扩展名把文件路由到对应摄取器"},
50
+ "执行": {"value": "使用扩展名映射表进行路由"},
51
+ "验证方式": {"value": "回放测试", "basis": "test"},
52
+ "不适用条件": {"value": "二进制文件不适用"},
53
+ }
54
+
55
+
56
+ def ok(cond, label):
57
+ global PASS, FAIL
58
+ if cond:
59
+ PASS += 1
60
+ else:
61
+ FAIL += 1
62
+ FAILS.append(label)
63
+ print(" FAIL " + label)
64
+
65
+
66
+ def _has(errs, code):
67
+ return any(str(e).startswith(code) for e in (errs or []))
68
+
69
+
70
+ def _seed(root):
71
+ cg = MdCGOS(root)
72
+ cg.add("tgt", "# 功能名:待编译节点\n\n占位正文。\n", layer="knowledge")
73
+ cg.flush()
74
+ cg.rebuild_index()
75
+ return cg
76
+
77
+
78
+ def _fake_serve(jobs, stop, seen):
79
+ """假蜂巢执行器:读 spec.json 写 result.json(契约与 hive 的 LLM 委托型一致)。
80
+
81
+ 用线程模拟 serve 侧的单元执行,使**复核通道与签章搬运**在无网络无密钥下
82
+ 可确定性验收——被测的是通道契约,不是模型质量。seen 记录 spec 形态供断言。
83
+ """
84
+ while not stop.is_set():
85
+ try:
86
+ names = sorted(os.listdir(jobs))
87
+ except OSError:
88
+ names = []
89
+ for jid in names:
90
+ d = os.path.join(jobs, jid)
91
+ sp = os.path.join(d, units.SPEC_FILE)
92
+ rp = os.path.join(d, units.RESULT_FILE)
93
+ if not jid.startswith("h") or not os.path.isfile(sp) or os.path.exists(rp):
94
+ continue
95
+ try:
96
+ with open(sp, encoding="utf-8") as f:
97
+ spec = json.load(f)
98
+ except (OSError, ValueError):
99
+ continue
100
+ prompt = str(spec.get("user_prompt") or spec.get("prompt") or "")
101
+ seen.update({"role": spec.get("role"), "model": spec.get("model"),
102
+ "prompt_len": len(prompt),
103
+ "prompt_has_dialog": "文件摄取分派" in prompt})
104
+ payload = {"verdict": seen.get("verdict") or "accept",
105
+ "reason": "假单元复核:候选与对话原文一致",
106
+ "slot_corrections": {}}
107
+ try:
108
+ with open(rp, "w", encoding="utf-8") as f:
109
+ json.dump({"ok": True, "model": spec.get("model"),
110
+ "content": json.dumps(payload, ensure_ascii=False)},
111
+ f, ensure_ascii=False)
112
+ except OSError:
113
+ continue
114
+ time.sleep(0.05)
115
+
116
+
117
+ def _import_mcp():
118
+ """延迟导入工具面(避免测试顶部把 server 依赖一并拉起)。"""
119
+ try:
120
+ from . import mcp_server
121
+ return mcp_server
122
+ except Exception: # noqa: BLE001
123
+ return None
124
+
125
+
126
+ def main():
127
+ global PASS, FAIL
128
+ tmp = tempfile.mkdtemp(prefix="mdcg_ccgc_")
129
+ try:
130
+ root = os.path.join(tmp, "root")
131
+ os.makedirs(root, exist_ok=True)
132
+ cg = _seed(root)
133
+
134
+ # ---------- V1 缺参即编译错误(裁定 B) ----------
135
+ r = ccgc.compile_dialog("", "tgt", "agent:a1")
136
+ ok((not r.success) and _has(r.errors, "E001"), "V1a 缺 dialog → E001")
137
+ r = ccgc.compile_dialog(DIALOG, "", "agent:a1")
138
+ ok((not r.success) and _has(r.errors, "E002"), "V1b 缺 node_id → E002")
139
+ r = ccgc.compile_dialog(DIALOG, "tgt", "")
140
+ ok((not r.success) and _has(r.errors, "E003"), "V1c 缺 actor → E003")
141
+ r = ccgc.compile_dialog(DIALOG, "nope", "agent:a1", cg=cg)
142
+ ok((not r.success) and _has(r.errors, "E002"), "V1d 节点不存在 → E002")
143
+ ok(bool(r.verdict) and r.verdict.get("authority") == "VERIFICATION_UNIT",
144
+ "V1e 终裁 authority=VERIFICATION_UNIT")
145
+
146
+ # ---------- V2 名实门:幻觉在编译期被机械检出 ----------
147
+ bad_slots = dict(SLOTS)
148
+ bad_slots["observation_tool"] = {"value": "该方法使用神经网络进行路由",
149
+ "span": "该方法使用神经网络进行路由"}
150
+ r_bad = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
151
+ slots=bad_slots, marks=MARKS, cg=cg)
152
+ ok((not r_bad.success) and _has(r_bad.errors, "E011"), "V2a 捏造值 → E011")
153
+ ok(len(r_bad.ungrounded) >= 1, "V2b 未过门项进入 ungrounded 台账")
154
+
155
+ bad2 = dict(SLOTS)
156
+ bad2["observation_position"] = {"value": "此功能在本地文件系统中生效",
157
+ "span": "不存在的引用文本"}
158
+ r2 = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
159
+ slots=bad2, marks=MARKS, cg=cg)
160
+ ok((not r2.success) and _has(r2.errors, "E010"), "V2c 引用定位失败 → E010")
161
+
162
+ class EvilParser(object):
163
+ """冒充 LLM 通道:给出看起来合理但源文本里没有的值。"""
164
+
165
+ def candidates(self, dialog, ctx):
166
+ return {"marks": dict(MARKS), "slots": dict(bad_slots)}
167
+
168
+ r3 = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
169
+ parser=EvilParser(), cg=cg)
170
+ ok((not r3.success) and _has(r3.errors, "E011"),
171
+ "V2d 外部 parser 幻觉同样被 E011 拦截(结构级阻断)")
172
+
173
+ # ---------- V3 四槽强制 ----------
174
+ r4 = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
175
+ slots={"observation_position": SLOTS["observation_position"]},
176
+ marks=MARKS, cg=cg)
177
+ ok((not r4.success) and _has(r4.errors, "E020"), "V3a 四槽不全 → E020")
178
+
179
+ # ---------- V4/V5 唯一合成入口 + 六要素齐备 ----------
180
+ plain_slots = {k: v.get("value") for k, v in SLOTS.items()}
181
+ r = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1",
182
+ slots=SLOTS, marks=MARKS, cg=cg)
183
+ ok(r.success, "V4a 完整入参编译成功")
184
+ ok(r.lines.get("生效条件") == nodefile.condition_space_text(plain_slots),
185
+ "V4b 生效条件 == nodefile.condition_space_text(唯一入口)")
186
+ ok(set(r.lines) == set(nodefile.CCG_MARKS), "V5a 六要素齐备")
187
+ ok(r.sources.get("verification_basis") == "test", "V5b 验证基底 test")
188
+
189
+ # ---------- V7 自证拒绝(裁定 A 核心) ----------
190
+ a_self = ccgc.attest("tgt", ccgc.ACCEPT, "agent:a1", "agent:a1", cg=cg)
191
+ ok((not a_self.ok) and "E041" in a_self.error, "V7a 验证方==编译方 → E041")
192
+ a_defer = ccgc.attest("tgt", ccgc.DEFER, "designer", "agent:a1", cg=cg)
193
+ ok((not a_defer.ok) and "E042" in a_defer.error, "V7b DEFER 不构成签章")
194
+ a_ok = ccgc.attest("tgt", ccgc.ACCEPT, "designer", "agent:a1",
195
+ evidence="设计者核对原文一致", cg=cg)
196
+ ok(a_ok.ok and bool(a_ok.token), "V7c 编外验证方 ACCEPT → 有效签章")
197
+
198
+ # ---------- V8 无章不写 ----------
199
+ l0 = ccgc.link(r, None, cg=cg, apply=True)
200
+ ok((not l0.ok) and any("E040" in e for e in l0.errors), "V8a 无签章 → E040 拒绝")
201
+ l1 = ccgc.link(r, a_self, cg=cg, apply=True)
202
+ ok(not l1.ok, "V8b 自证签章 → link 拒绝")
203
+ l2 = ccgc.link(r, a_ok, cg=cg, apply=False)
204
+ ok(l2.ok and l2.dry_run and l2.written == 0, "V8c dry-run 不写入")
205
+ _fm_b, c_before = cg._read(cg.index["nodes"]["tgt"])
206
+ ok(not nodefile.ccg_completeness(c_before)["complete"], "V5c link 前六要素不全")
207
+
208
+ # ---------- link 落库 ----------
209
+ l3 = ccgc.link(r, a_ok, cg=cg, apply=True)
210
+ ok(l3.ok and l3.written == 6, "V8d 签章通过 → 写入六行")
211
+ fm_after, c_after = cg._read(cg.index["nodes"]["tgt"])
212
+ ok(nodefile.ccg_completeness(c_after)["complete"],
213
+ "V5d link 后六要素齐备(可判定性提升)")
214
+ ok(fm_after.get("condition_space") == plain_slots, "V4c condition_space 落 frontmatter")
215
+ ok(fm_after.get("verification_basis") == "test", "V5e verification_basis 落盘")
216
+
217
+ # ---------- V6 未制造条件污染 ----------
218
+ rep = backfill.verify_conditions(cg)
219
+ ok(rep.get("legacy_position") == 0, "V6a 弱等价残留 legacy_position == 0")
220
+ ok(rep.get("from_synthesis", 0) >= 1, "V6b 生效条件来源=合成")
221
+
222
+ # ---------- V9 缺验证器恒 DEFER(能力外置) ----------
223
+ v = audit.audit("ccg_marks", {"node": "tgt"}, {})
224
+ ok(v.get("state") == "DEFER", "V9a 未注入验证器 → DEFER(不假装通过)")
225
+ ok(audit.kinds()["ccg_marks"]["basis"] == "test", "V9b ccg_marks 基底建议=test")
226
+
227
+ # ---------- V11 用后续验证修正生效条件 ----------
228
+ rc = ccgc.recalibrate("tgt", {"existence_constraint": "仅对本地可读文件生效"},
229
+ "agent:a1", "agent:a1", cg=cg, apply=False)
230
+ ok(any("E041" in e for e in rc.errors), "V11a 修正方==编译方 → E041")
231
+ rc = ccgc.recalibrate("tgt", {"生效条件": "手写条件"}, "designer", "agent:a1",
232
+ cg=cg, apply=False)
233
+ ok(any("E043" in e for e in rc.errors), "V11b 非四槽键 → E043(无第二通路)")
234
+ rc = ccgc.recalibrate("tgt", {"observation_tool": "该方法使用扩展名映射表进行路由"},
235
+ "designer", "agent:a1", evidence="实测复核:方法槽无误",
236
+ cg=cg, apply=True)
237
+ ok(rc.ok, "V11c 编外验证方修正获准")
238
+ _fm_r, c_r = cg._read(cg.index["nodes"]["tgt"])
239
+ ok(nodefile.ccg_completeness(c_r)["complete"], "V11d 修正后仍齐备")
240
+ logs = ccgc._read_jsonl(ccgc._log_path(cg))
241
+ ok(any(x.get("action") == "ccgc_recalibrate" and x.get("slots_before") is not None
242
+ and x.get("slots_after") is not None for x in logs),
243
+ "V11e 修正留痕含 before/after(可溯源)")
244
+ ok(any(x.get("action") == "ccgc_attest" for x in logs), "V11f 签章留痕可查")
245
+
246
+ # ---------- V13 内生规则解析器:诚实下界 ----------
247
+ r_rule = ccgc.compile_dialog(DIALOG, "tgt", "agent:a1", cg=cg)
248
+ ok(any("下界能力" in w for w in r_rule.warnings), "V13a 未注入解析器时如实声明下界")
249
+ bad_spans = [s for arr in r_rule.spans.values() for s in arr
250
+ if s and s not in DIALOG]
251
+ ok(not bad_spans, "V13b 内生解析器引用全部 grounded")
252
+
253
+ # ---------- V14 产物无占位残留 ----------
254
+ ok(not any(nodefile.is_placeholder_text(x) for x in r.lines.values()),
255
+ "V14 产物无占位残留")
256
+
257
+ # ---------- V15 裁定 B 术语落地:单一真源 + 六要素一一对应 ----------
258
+ ok(ccgc.CONTRACT_ROLES is nodefile.CCG_CONTRACT_ROLES,
259
+ "V15a 术语真源唯一(ccgc 引用 nodefile,不另定义一份)")
260
+ ok(tuple(nodefile.CCG_CONTRACT_ROLES) == tuple(nodefile.CCG_MARKS),
261
+ "V15b 契约角色与六要素一一对应(顺序一致)")
262
+ ok(nodefile.CCG_CONTRACT_ROLES["生效条件"] == "前置条件 precondition",
263
+ "V15c 生效条件角色 = precondition(裁定 B)")
264
+
265
+ # ---------- V16 pending:候选与签章绑定(跨 MCP 三次独立调用形态) ----------
266
+ p_path = ccgc.pending_path(cg, "tgt")
267
+ ok(bool(p_path) and ccgc.PENDING_DIR in p_path, "V16a pending 落 LAYERS 之外的冷区")
268
+ sv = ccgc.save_pending(cg, r)
269
+ ok(bool(sv.get("ok")) and os.path.isfile(sv["path"]) and bool(sv.get("hash")),
270
+ "V16b 候选落盘并留内容摘要")
271
+ got = ccgc.load_pending(cg, "tgt")
272
+ ok(bool(got.get("ok")) and bool(got.get("hash_ok")), "V16c 读回摘要一致(原件未被改写)")
273
+ ok(got["compiled"].lines == r.lines, "V16d 读回六行 == 编译产物(无损搬运)")
274
+ with open(sv["path"], encoding="utf-8") as f:
275
+ rec = json.load(f)
276
+ rec["compiled"]["lines"]["功能名"] = "被篡改的功能名"
277
+ with open(sv["path"], "w", encoding="utf-8") as f:
278
+ json.dump(rec, f, ensure_ascii=False)
279
+ lx = ccgc.link_pending(cg, "tgt", apply=True)
280
+ ok((not lx.ok) and any("hash" in e for e in lx.errors),
281
+ "V16e 候选被改写 → hash 不符,拒绝写入(签章只忠于原件)")
282
+ sv = ccgc.save_pending(cg, r, a_ok)
283
+ lz = ccgc.link_pending(cg, "tgt", apply=True, actor="agent:a1")
284
+ ok(lz.ok and lz.written == 6, "V16f 读回原件+签章 → 落库成功")
285
+ ok(not os.path.isfile(sv["path"]), "V16g 落库成功即清 pending(暂存非存档)")
286
+ ok(not any(ccgc.PENDING_DIR in str(k) for k in (cg.index.get("nodes") or {})),
287
+ "V16h pending 不进索引(冷区对检索隐身)")
288
+
289
+ # ---------- V17 闸门:只认编外裁决,绝不假装通过 ----------
290
+ v = audit.audit("ccg_marks", {"node_id": "tgt", "unit_verdict": "ACCEPT",
291
+ "verifier": "hive:reflect:h1",
292
+ "evidence": "假单元复核:与原文一致"}, {})
293
+ ok(v.get("state") == "ACCEPT", "V17a 编外裁决+依据 → ACCEPT")
294
+ v = audit.audit("ccg_marks", {"node_id": "tgt", "unit_verdict": "ACCEPT",
295
+ "verifier": "hive:reflect:h1"}, {})
296
+ ok(v.get("state") == "DEFER", "V17b ACCEPT 但无依据 → DEFER(无依据不通过)")
297
+ v = audit.audit("ccg_marks", {"node_id": "tgt", "unit_verdict": "ACCEPT",
298
+ "verifier": "agent:a1", "evidence": "我自己验的"},
299
+ {"compiled_by": "agent:a1"})
300
+ ok(v.get("state") == "REJECT", "V17c 自证 → REJECT(E041 在闸门层再挡一次)")
301
+ v = audit.audit("ccg_marks", {"node_id": "tgt", "unit_verdict": "ACCEPT",
302
+ "evidence": "无验证方"}, {})
303
+ ok(v.get("state") == "DEFER", "V17d 有裁决缺验证方标识 → DEFER")
304
+ v = audit.audit("ccg_marks", {"node_id": "tgt"}, {})
305
+ d = v.get("detail") or {}
306
+ ok(v.get("state") == "DEFER" and bool(d.get("next")) and d.get("channel_state") in units.STATES,
307
+ "V17e 无裁决 → DEFER 且给出下一步通道(不阻塞写路径)")
308
+ v = audit.audit("ccg_marks", {}, {})
309
+ ok(v.get("state") == "DEFER", "V17f 缺 node_id → DEFER")
310
+
311
+ # ---------- V18 复核通道:三态如实 + 来源标识结构上非编译者 ----------
312
+ ok(units.transport_name(units.HIVE, units.REFLECT, "h1") == "hive:reflect:h1",
313
+ "V18a 蜂巢来源标识 = hive:<role>:<job>")
314
+ ok(units.transport_name(units.HIVE, units.REFLECT, "h1") != "agent:a1",
315
+ "V18b 来源标识结构上不可能等于编译者(裁定 A 不被误伤)")
316
+ u = units.verdict_of('前置说明\n```json\n{"verdict":"accept","reason":"一致"}\n```')
317
+ ok(u["verdict"] == units.ACCEPT and bool(u["parsed"]), "V18c 围栏 JSON 可解析 → ACCEPT")
318
+ u = units.verdict_of("我无法判断这件事")
319
+ ok(u["verdict"] == units.DEFER and not u["parsed"], "V18d 解析不出 → DEFER(不猜测)")
320
+ u = units.verdict_of({"verdict": "drop", "reason": "与原文不符",
321
+ "slot_corrections": {"observation_tool": "x"}})
322
+ ok(u["verdict"] == units.REJECT and bool(u["slot_corrections"]),
323
+ "V18e drop → REJECT(四槽修正随裁决带回)")
324
+ aa = units.to_attest_args({"verdict": units.ACCEPT, "reason": "一致"}, state=units.HIVE,
325
+ role=units.REFLECT, job_id="h1",
326
+ compiled_by=units.transport_name(units.HIVE, units.REFLECT, "h1"))
327
+ ok(aa.get("self_verify") is True, "V18f 万一自证 → 显式标记(供上层拒绝)")
328
+ aa = units.to_attest_args({"verdict": units.ACCEPT, "reason": "一致"}, state=units.HIVE,
329
+ role=units.REFLECT, job_id="h1", compiled_by="agent:a1")
330
+ ok(not aa.get("self_verify") and aa["verifier"].startswith("hive:reflect:"),
331
+ "V18g 非自证:verifier 取蜂巢来源标识(不设自证标记)")
332
+ pr = units.probe(jobs=os.path.join(tmp, "nojobs"))
333
+ ok(pr["state"] == units.CONFIGURE and units.ENV_MODEL in pr["hint"],
334
+ "V18h 蜂巢不可用 → 返回配置指引(不自动拉起、不假装可用)")
335
+ pr = units.probe(jobs=os.path.join(tmp, "nojobs"), allow_degrade=True)
336
+ ok(pr["state"] == units.SUBAGENT, "V18i 显式 allow_degrade → 子代理降级(不冒充 hive)")
337
+
338
+ # ---------- V19/V20 端到端:假蜂巢 → 编外裁决 → 签章 → 落库 ----------
339
+ jobs = os.path.join(tmp, "jobs")
340
+ os.makedirs(jobs, exist_ok=True)
341
+ # 假 serve 是**本进程内的线程**,故「该 pid 是本程序」如实为真——把本程序
342
+ # 口径指向本进程映像名即可(v14 缺陷 E 修复后 units 判活含**身份层**:
343
+ # 旧写法心跳 pid=本进程却让 EXE 口径指向 hive.exe,身份层判假 → 通道不可用,
344
+ # 那不是被测缺陷而是测试自身要与新口径对齐)。
345
+ _old_exe = os.environ.get(units.ENV_EXE)
346
+ os.environ[units.ENV_EXE] = sys.executable
347
+ with open(os.path.join(jobs, units.SERVE_FILE), "w", encoding="utf-8") as f:
348
+ json.dump({"ts": int(time.time() * 1000), "pid": os.getpid()}, f)
349
+ seen = {}
350
+ stop = threading.Event()
351
+ th = threading.Thread(target=_fake_serve, args=(jobs, stop, seen), daemon=True)
352
+ th.start()
353
+ _old_model = os.environ.get(units.ENV_MODEL)
354
+ os.environ[units.ENV_MODEL] = "fake-unit-model"
355
+ try:
356
+ pr = units.probe(jobs=jobs)
357
+ ok(pr["state"] == units.HIVE, "V19a 心跳新鲜+模型已配 → HIVE 可派发")
358
+ rv = units.review(digest=r, dialog=DIALOG, role=units.REFLECT, node_id="tgt",
359
+ jobs=jobs, blocking=True, wait_s=30, cg=cg, actor="agent:a1")
360
+ ok(rv["state"] == units.HIVE and bool(rv.get("unit")), "V19b 派发并取回编外裁决")
361
+ ok((rv["unit"] or {}).get("verdict") == units.ACCEPT, "V19c 单元裁决解析为 ACCEPT")
362
+ ok(seen.get("role") == units.REFLECT and seen.get("model") == "fake-unit-model"
363
+ and seen.get("prompt_has_dialog"),
364
+ "V19d spec 形态合蜂巢契约(role/model/复核包正文)")
365
+ ok(str((rv.get("attest") or {}).get("verifier") or "").startswith("hive:reflect:"),
366
+ "V19e 签章方 = 蜂巢单元标识(结构上非编译者)")
367
+ at = ccgc.attest("tgt", rv["attest"]["verdict"], rv["attest"]["verifier"],
368
+ "agent:a1", evidence=rv["attest"]["evidence"] or "单元复核",
369
+ cg=cg)
370
+ ok(at.ok, "V19f 蜂巢裁决可直接签章(E041 不被误伤)")
371
+ logs = ccgc._read_jsonl(os.path.join(str(cg.root), units.LOG_NAME))
372
+ ok(any(x.get("action") == "review" and x.get("job_id") for x in logs),
373
+ "V19g 派发留痕(job_id 可追溯)")
374
+
375
+ # --- V20 MCP 工具面:compile → review → attest/link 三段式 ---
376
+ mcp = _import_mcp()
377
+ ok(mcp is not None, "V20a 工具面可加载")
378
+ c1 = mcp._ccg_call(cg, {"ccg": {"action": "catalog"}})
379
+ ok(c1["ok"] and "compile" in c1["actions"] and "E041" in c1["errors"],
380
+ "V20b catalog 自描述(动作清单 + 错误码)")
381
+ c2 = mcp._ccg_call(cg, {"ccg": {"action": "compile", "node_id": "tgt",
382
+ "dialog": DIALOG, "marks": MARKS, "slots": SLOTS}})
383
+ ok(c2["ok"] and c2["compiled"]["success"] and c2["pending"]["ok"],
384
+ "V20c compile 成功并落 pending(不当场写库)")
385
+ ok("E041" in c2["hint"], "V20d hint 指向编外复核(裁定 A 对调用方可见)")
386
+ c3 = mcp._ccg_call(cg, {"ccg": {"action": "attest", "node_id": "tgt",
387
+ "verdict": "ACCEPT", "verifier": c2["compiled_by"],
388
+ "compiled_by": c2["compiled_by"],
389
+ "evidence": "我自己验的"}})
390
+ ok((not c3["ok"]) and "E041" in str(c3["attest"]["error"]),
391
+ "V20e MCP 面自证 → E041(机械拒绝,不靠自觉)")
392
+ c4 = mcp._ccg_call(cg, {"ccg": {"action": "link", "node_id": "tgt", "apply": True}})
393
+ ok(not c4["ok"], "V20f 自证章不构成准入 → link 拒绝")
394
+ c5 = mcp._ccg_call(cg, {"ccg": {"action": "review", "node_id": "tgt",
395
+ "jobs": jobs, "blocking": True, "wait_s": 30}})
396
+ ok(c5["state"] == units.HIVE and c5["verdict"] == "ACCEPT" and c5["passed"] is True,
397
+ "V20g review 取回裁决:ok/verdict/passed 三者分离")
398
+ ok(bool((c5.get("attest") or {}).get("ok")), "V20h 拿到裁决即自动签章")
399
+ c7 = mcp._ccg_call(cg, {"ccg": {"action": "review", "node_id": "tgt",
400
+ "jobs": jobs, "blocking": False}})
401
+ ok(c7["state"] == units.HIVE and c7["verdict"] is None and c7["passed"] is False,
402
+ "V20j 非阻塞:派发成功但裁决未回(verdict=None,不冒充通过)")
403
+ c6 = mcp._ccg_call(cg, {"ccg": {"action": "link", "node_id": "tgt", "apply": True}})
404
+ ok(c6["ok"] and c6["link"]["written"] == 6, "V20i link 落库(三段式闭环)")
405
+ c10 = mcp._ccg_call(cg, {"ccg": {"action": "link", "node_id": "tgt", "apply": True}})
406
+ ok(not c10["ok"], "V20m 落库后 pending 已清 → 再 link 明确报错(暂存非存档)")
407
+ c8 = mcp._ccg_call(cg, {"ccg": {"action": "units", "jobs": jobs, "doctor": True}})
408
+ ok(c8["ok"] and c8["action"] == "units", "V20k units/doctor 走三级链体检")
409
+ c9 = mcp._ccg_call(cg, {"ccg": {"action": "nope"}})
410
+ ok(not c9["ok"], "V20l 未知 action → 明确报错(不静默降级)")
411
+ finally:
412
+ stop.set()
413
+ th.join(timeout=3)
414
+ if _old_model is None:
415
+ os.environ.pop(units.ENV_MODEL, None)
416
+ else:
417
+ os.environ[units.ENV_MODEL] = _old_model
418
+ if _old_exe is None:
419
+ os.environ.pop(units.ENV_EXE, None)
420
+ else:
421
+ os.environ[units.ENV_EXE] = _old_exe
422
+
423
+ finally:
424
+ print()
425
+ print("ccgc: PASS=%d FAIL=%d" % (PASS, FAIL))
426
+ if FAILS:
427
+ print("FAILS: " + "; ".join(FAILS))
428
+ shutil.rmtree(tmp, ignore_errors=True)
429
+ return 1 if FAIL else 0
430
+
431
+
432
+ if __name__ == "__main__":
433
+ sys.exit(main())