@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/sustain.py CHANGED
@@ -80,16 +80,19 @@ _POLL = 0.2 # 循环轮询步长(常驻进程 CPU 可忽
80
80
  # 心跳
81
81
  # --------------------------------------------------------------------------
82
82
 
83
+ # 生效条件:d 为真值时返回 d,d 为 None/空串时回落 MDCG_SUSTAIN_DIR,该环境变量也未设或为空串时返回 os.path.join(os.path.expanduser("~"), ".mdcg", "sustain");
83
84
  def net_dir(d: str = None) -> str:
84
85
  """心跳戳目录:显式 → MDCG_SUSTAIN_DIR → ~/.mdcg/sustain(仓库外)。"""
85
86
  return (d or os.environ.get("MDCG_SUSTAIN_DIR")
86
87
  or os.path.join(os.path.expanduser("~"), ".mdcg", "sustain"))
87
88
 
88
89
 
90
+ # 生效条件:给定必填 name,返回 net_dir(d) 下 heartbeat.<name>.stamp 的拼接路径。
89
91
  def stamp_path(name: str, d: str = None) -> str:
90
92
  return os.path.join(net_dir(d), f"heartbeat.{name}.stamp")
91
93
 
92
94
 
95
+ # 生效条件:name 必填,组装含模块常量 STAMP_VERSION 与 task_running 的戳记录、原子写入 stamp_path(name,d) 后返回该 rec。
93
96
  def write_stamp(name: str, d: str = None, **extra) -> dict:
94
97
  """写一次心跳(原子替换)。extra 会并入戳内容(None 值丢弃)。"""
95
98
  rec = {"v": STAMP_VERSION, "name": name, "ts": time.time(),
@@ -104,6 +107,7 @@ def write_stamp(name: str, d: str = None, **extra) -> dict:
104
107
  return rec
105
108
 
106
109
 
110
+ # 生效条件:stamp_path(name, d) 所得路径上 os.path.exists 为真且 json.load 结果为 dict 时,返回该 rec 并附加 age=max(0.0, time.time() - float(rec.get("ts") or 0));该路径不可读、json.load 抛 ValueError/OSError 或 rec 非 dict 时返回 None;
107
111
  def read_stamp(name: str, d: str = None):
108
112
  """读心跳戳并附 age(秒);不存在 / 损坏 → None。"""
109
113
  p = stamp_path(name, d)
@@ -120,6 +124,7 @@ def read_stamp(name: str, d: str = None):
120
124
  return rec
121
125
 
122
126
 
127
+ # 生效条件:对 stamp_path(name,d) 执行 os.remove,OSError 被静默忽略,无返回值。
123
128
  def clear_stamp(name: str, d: str = None):
124
129
  try:
125
130
  os.remove(stamp_path(name, d))
@@ -127,6 +132,7 @@ def clear_stamp(name: str, d: str = None):
127
132
  pass
128
133
 
129
134
 
135
+ # 生效条件:age 为 None 返回 'absent';否则以 factor=working if task_running else 1.0 比较 age 与 interval*warn*factor、interval*dead*factor,分别返回 'ok'/'warning'/'dead'。
130
136
  def judge(age, *, interval: float = DEFAULT_BEAT_INTERVAL,
131
137
  task_running: bool = False, warn: float = DEFAULT_WARN_FACTOR,
132
138
  dead: float = DEFAULT_DEAD_FACTOR,
@@ -146,6 +152,7 @@ def judge(age, *, interval: float = DEFAULT_BEAT_INTERVAL,
146
152
  return "dead"
147
153
 
148
154
 
155
+ # 生效条件:net_dir(d) 可列为目录时遍历 heartbeat.*.stamp 并返回含 age 与 state 的记录列表,否则返回 []。
149
156
  def peers(d: str = None):
150
157
  """列出本机所有心跳戳(含状态)。"""
151
158
  base = net_dir(d)
@@ -171,6 +178,7 @@ DEFAULT_RESTART_COOLDOWN = 300.0 # 同一对端两次拉起的最小间隔(
171
178
  DEFAULT_FRESH_TIMEOUT = 60.0 # 拉起后等待对端戳变新鲜的窗口
172
179
 
173
180
 
181
+ # 生效条件:pid 可转 int 且 >0 时按探活(os.name=='nt' 用 OpenProcess+WaitForSingleObject,否则 os.kill(pid,0))返回 True,转 int 失败或 pid<=0 或探活失败返回 False。
174
182
  def pid_alive(pid) -> bool:
175
183
  """进程探活(零第三方依赖):Windows=OpenProcess+WaitForSingleObject;
176
184
  posix=os.kill(pid,0)。pid 无效 / 已退出 / 权限外 → False(诚实)。"""
@@ -199,6 +207,7 @@ def pid_alive(pid) -> bool:
199
207
  return False
200
208
 
201
209
 
210
+ # 生效条件:cmd 为 argv 列表时以 stdout/stderr=DEVNULL、不经 shell 的 subprocess.Popen 拉起(nt 附加 DETACHED|NEW_GROUP creationflags),返回该 Popen 对象。
202
211
  def _default_spawner(cmd):
203
212
  """分离式拉起:argv 列表、不经 shell、输出弃置(Windows 完全脱离父控制台)。"""
204
213
  import subprocess
@@ -209,6 +218,7 @@ def _default_spawner(cmd):
209
218
  stderr=subprocess.DEVNULL, **kw)
210
219
 
211
220
 
221
+ # 生效条件:root 与 peer 必填,扫描 root/SUSTAIN_LOG(模块常量)返回 op='mutual'、action='restart' 且 detail 以 peer 开头的记录中最大 t,无匹配返回 0.0。
212
222
  def _last_mutual_restart(root: str, peer: str) -> float:
213
223
  """_sustain.jsonl 里该对端最近一次互维拉起时间(无 → 0.0,审计即状态)。"""
214
224
  last = 0.0
@@ -227,6 +237,7 @@ def _last_mutual_restart(root: str, peer: str) -> float:
227
237
  return last
228
238
 
229
239
 
240
+ # 生效条件:cg 与 peer 必填,读对端戳判状态:ok/warning 直接返回 action='none';dead/absent 时依次按 pid_alive、restart_cooldown、restart_cmd 有无走 alive_but_stale/restart_cooldown/dead_unhandled/拉起并验戳,返回 out。
230
241
  def mutual_watch(cg, peer: str, *, restart_cmd=None, d: str = None,
231
242
  interval: float = DEFAULT_BEAT_INTERVAL,
232
243
  restart_cooldown: float = DEFAULT_RESTART_COOLDOWN,
@@ -294,6 +305,7 @@ def mutual_watch(cg, peer: str, *, restart_cmd=None, d: str = None,
294
305
  return out
295
306
 
296
307
 
308
+ # 生效条件:cg 与 peer 必填,分别按 name 与 peer 读戳判状态,仅当自身与对端状态均属 ('dead','absent') 时返回 ok=False、both_dead=True。
297
309
  def mutual_status(cg, peer: str, *, d: str = None, name: str = "md_cg",
298
310
  interval: float = DEFAULT_BEAT_INTERVAL) -> dict:
299
311
  """互维状态 + 双亡检测:自己也失联时互维不可信 → 显式外部告警语义。"""
@@ -316,6 +328,7 @@ def mutual_status(cg, peer: str, *, d: str = None, name: str = "md_cg",
316
328
  # 诊断(只读)
317
329
  # --------------------------------------------------------------------------
318
330
 
331
+ # 生效条件:root 必填,对模块常量 LAYERS 各层 os.walk 统计以 .md 结尾的文件名个数并返回 n(不解析正文)。
319
332
  def _count_node_files(root: str) -> int:
320
333
  """轻量统计磁盘节点数(只数文件名,不解析正文)。"""
321
334
  n = 0
@@ -325,6 +338,7 @@ def _count_node_files(root: str) -> int:
325
338
  return n
326
339
 
327
340
 
341
+ # 生效条件:root 与 older_than 必填,返回 root 及其 LAYERS 各层下以 '.' 开头、名含 '.tmp-' 且 mtime 早于 now-older_than 的路径列表。
328
342
  def _list_stale_temps(root: str, older_than: float):
329
343
  now, out = time.time(), []
330
344
  bases = [root] + [os.path.join(root, l) for l in LAYERS]
@@ -343,6 +357,7 @@ def _list_stale_temps(root: str, older_than: float):
343
357
  return out
344
358
 
345
359
 
360
+ # 生效条件:root 必填,返回 root 顶层以 .jsonl/.log 结尾且 ends_mid_line 为真的路径列表;root 非目录返回 []。
346
361
  def _half_line_logs(root: str):
347
362
  """顶层行式日志里末尾不是换行的(写者被杀留下的半截记录)。"""
348
363
  out = []
@@ -357,6 +372,7 @@ def _half_line_logs(root: str):
357
372
  return out
358
373
 
359
374
 
375
+ # 生效条件:root/_index_log 可列为目录时返回其中 .log 结尾的文件名列表,否则返回 []。
360
376
  def _index_log_shards(root: str):
361
377
  d = os.path.join(root, "_index_log")
362
378
  if not os.path.isdir(d):
@@ -364,6 +380,7 @@ def _index_log_shards(root: str):
364
380
  return [f for f in os.listdir(d) if f.endswith(".log")]
365
381
 
366
382
 
383
+ # 生效条件:cg 具备 crypto_status 且其返回 unlocked 为假时,返回 cg.index['nodes'] 中 sensitivity 属 crypto.ENCRYPTED_LEVELS 的条目数;属性缺失、调用异常或已解锁时返回 0。
367
384
  def _locked_nodes(cg) -> int:
368
385
  """加密引擎在「未解锁」状态下被隔离的私有节点数(缺密钥 = 权限事实)。"""
369
386
  if not hasattr(cg, "crypto_status"):
@@ -388,6 +405,7 @@ EVOLVE_FIXES = {"ccg_backlog": "consolidate_run",
388
405
  "importance_drift": "importance"}
389
406
 
390
407
 
408
+ # 生效条件:nodes 与 top 必填,遍历索引条目统计缺 verification_basis 或 has_neg_conditions 的候补数 n、no_basis、no_neg 并取最多 top 个 sample,返回含 proxy=True 与 EVOLVE_FIXES['ccg_backlog'] 的字典。
391
409
  def _ccg_backlog(nodes: dict, top: int) -> dict:
392
410
  """固化候补量(**索引代理指标**:零读节点文件、确定性、O(N))。
393
411
 
@@ -412,6 +430,7 @@ def _ccg_backlog(nodes: dict, top: int) -> dict:
412
430
  "proxy": True, "fix": EVOLVE_FIXES["ccg_backlog"]}
413
431
 
414
432
 
433
+ # 生效条件:cg 必填,取 cg.index['nodes'](layer 非空时按 layer 过滤),经 weights.recalc(apply=False) 与 _ccg_backlog 汇总,返回 ok=True、readonly=True、dry_run=True 的候选盘点字典。
415
434
  def evolution_candidates(cg, *, layer: str = None, top: int = 8,
416
435
  min_delta: float = None) -> dict:
417
436
  """演化候选盘点(G7):**只读、零读节点文件、确定性、不写盘**。
@@ -446,6 +465,7 @@ def evolution_candidates(cg, *, layer: str = None, top: int = 8,
446
465
  "重要性重算为确定性动作(有 rollback)")}
447
466
 
448
467
 
468
+ # 生效条件:给定 cg 后只读汇总(nodes 取自 cg.index、disk 计数、refindex.check_refs),stale_temp_age 传入 _list_stale_temps;check_heartbeat / check_evolution(evolve_top) / check_provenance(provenance_top) 为真时分别追加对应 issue,返回 ok = 无 severity=="warning" 的 issue 连同 stats。
449
469
  def diagnose(cg, *, name: str = "md_cg", stale_temp_age: float = STALE_TEMP_AGE,
450
470
  check_heartbeat: bool = True, check_evolution: bool = True,
451
471
  evolve_top: int = 5, check_provenance: bool = True,
@@ -575,17 +595,20 @@ def diagnose(cg, *, name: str = "md_cg", stale_temp_age: float = STALE_TEMP_AGE,
575
595
  # 自愈
576
596
  # --------------------------------------------------------------------------
577
597
 
598
+ # 生效条件:path 必填,以 'ab' 模式向该路径追加写入单个换行 b'\n',无返回值。
578
599
  def _seal_half_line(path: str):
579
600
  with open(path, "ab") as f:
580
601
  f.write(b"\n")
581
602
 
582
603
 
604
+ # 生效条件:root/op/action 必填,向 root/SUSTAIN_LOG(模块常量)追加一行含 t/op/action/detail(截断 200)/pid 的 JSONL,无返回值。
583
605
  def _audit(root: str, op: str, action: str, detail: str = ""):
584
606
  append_jsonl(os.path.join(root, SUSTAIN_LOG),
585
607
  {"t": time.time(), "op": op, "action": action,
586
608
  "detail": str(detail)[:200], "pid": os.getpid()})
587
609
 
588
610
 
611
+ # 生效条件:按 diagnose(cg, name=name, stale_temp_age=stale_temp_age) 的 issues code 集合分派——命中 index_drift/index_orphan 重建索引、ref_stale/ref_dangling 按 ref 重建源索引、index_log_backlog 合并索引分片、stale_temps 清理陈旧临时文件、half_line_logs 修补半截日志;ccg_backlog 仅 allow_evolve=True 且 reflect_fn 非 None 时才 consolidate(否则记 needs_llm),importance_drift 仅 allow_evolve=True 时才重算重要性(否则记 evolve_disabled);dry_run=True 时各动作只记入 actions 不落盘,返回含 after["ok"]、dry_run、actions、before/after 的 stats 与 t 的 dict;
589
612
  def heal(cg, *, name: str = "md_cg", dry_run: bool = False,
590
613
  stale_temp_age: float = STALE_TEMP_AGE,
591
614
  allow_evolve: bool = False, reflect_fn=None, verify_fn=None) -> dict:
@@ -599,6 +622,7 @@ def heal(cg, *, name: str = "md_cg", dry_run: bool = False,
599
622
  root = cg.root
600
623
  actions = []
601
624
 
625
+ # 生效条件:闭包 dry_run 为真时向 actions 追加 {"code": code, "detail": detail, "applied": False} 并返回;否则调用 fn(),成功追加 applied=True/ok=True,抛异常时追加 applied=True/ok=False 与 error,最后执行 _audit(root, "heal", code, detail);
602
626
  def act(code: str, detail: str, fn):
603
627
  if dry_run:
604
628
  actions.append({"code": code, "detail": detail, "applied": False})
@@ -624,6 +648,7 @@ def heal(cg, *, name: str = "md_cg", dry_run: bool = False,
624
648
  if "stale_temps" in codes:
625
649
  paths = _list_stale_temps(root, stale_temp_age)
626
650
 
651
+ # 生效条件:对闭包变量 paths 中每个路径尝试 os.remove(p),单个路径的 OSError 被吞掉后继续处理后续路径;
627
652
  def _sweep():
628
653
  for p in paths:
629
654
  try:
@@ -643,6 +668,7 @@ def heal(cg, *, name: str = "md_cg", dry_run: bool = False,
643
668
  if allow_evolve and reflect_fn is not None:
644
669
  from . import consolidate as _cd
645
670
 
671
+ # 生效条件:调用时返回 _cd.consolidate(cg.root, apply=True, reflect_fn=reflect_fn, verify_fn=verify_fn);
646
672
  def _consolidate():
647
673
  return _cd.consolidate(cg.root, apply=True,
648
674
  reflect_fn=reflect_fn,
@@ -655,6 +681,7 @@ def heal(cg, *, name: str = "md_cg", dry_run: bool = False,
655
681
  if allow_evolve:
656
682
  from . import weights
657
683
 
684
+ # 生效条件:调用时返回 weights.recalc(cg, apply=True, actor="sustain_evolve");
658
685
  def _importance():
659
686
  return weights.recalc(cg, apply=True, actor="sustain_evolve")
660
687
  act("importance", "重算结构重要性(确定性;可 rollback)", _importance)
@@ -674,6 +701,7 @@ def heal(cg, *, name: str = "md_cg", dry_run: bool = False,
674
701
  # 会话水位(重启续接)
675
702
  # --------------------------------------------------------------------------
676
703
 
704
+ # 生效条件:以 root 实例化后账本固定指向 os.path.join(root, LEDGER_FILE),其 _load/_save/note/resume_point/sessions/summary 均以该路径为唯一读写对象;
677
705
  class SessionLedger:
678
706
  """会话水位账本:<root>/_sessions.json。
679
707
 
@@ -681,10 +709,12 @@ class SessionLedger:
681
709
  这里记「某个会话发生过什么」——重启后按会话给出续接点。
682
710
  """
683
711
 
712
+ # 生效条件:传入 root 时置 self.root=root 且 self.path=os.path.join(root, LEDGER_FILE),不做其他校验;
684
713
  def __init__(self, root: str):
685
714
  self.root = root
686
715
  self.path = os.path.join(root, LEDGER_FILE)
687
716
 
717
+ # 生效条件:self.path(root/LEDGER_FILE)可读且 json 结果为 dict、且 d.get("sessions") 也是 dict 时返回该 d;self.path 不可读、json.load 抛 ValueError/OSError、或 d 非 dict / sessions 非 dict 时返回 {"schema": 1, "sessions": {}};
688
718
  def _load(self):
689
719
  if os.path.exists(self.path):
690
720
  try:
@@ -696,9 +726,11 @@ class SessionLedger:
696
726
  pass
697
727
  return {"schema": 1, "sessions": {}}
698
728
 
729
+ # 生效条件:传入 d 时执行 atomic_write(self.path, json.dumps(d, ensure_ascii=False, indent=1)),自身无返回值;
699
730
  def _save(self, d):
700
731
  atomic_write(self.path, json.dumps(d, ensure_ascii=False, indent=1))
701
732
 
733
+ # 生效条件:以 session 为键 setdefault 会话记录后写 events=int(s.get("events") or 0)+int(n)(n 默认 1,n=0 时计数不变),t 非 None 时写 last_t 且 first_t 为空时一并写入,seq 非 None 时写 last_seq,actor 为真值时写 actor,最后写 updated_at 并 _save,返回 dict(s, session=session);
702
734
  def note(self, session: str, *, t=None, seq=None, n: int = 1,
703
735
  actor: str = None) -> dict:
704
736
  """记一笔会话活动(事件计数 + 最后 (t, seq) 水位)。"""
@@ -718,6 +750,7 @@ class SessionLedger:
718
750
  self._save(d)
719
751
  return dict(s, session=session)
720
752
 
753
+ # 生效条件:_load()["sessions"].get(session) 为假值(键缺失或值为空 dict)时返回 {"session": session, "resume": None, "events": 0};否则返回 {"session": session, "events": s.get("events", 0), "resume": {"t": s.get("last_t"), "seq": s.get("last_seq")}, "last_t": s.get("last_t"), "actor": s.get("actor")};
721
754
  def resume_point(self, session: str) -> dict:
722
755
  """重启续接点:(t, seq) 之后的事件才是新的。"""
723
756
  s = self._load()["sessions"].get(session)
@@ -727,9 +760,11 @@ class SessionLedger:
727
760
  "resume": {"t": s.get("last_t"), "seq": s.get("last_seq")},
728
761
  "last_t": s.get("last_t"), "actor": s.get("actor")}
729
762
 
763
+ # 生效条件:无参调用时返回 dict(self._load()["sessions"]) 的浅拷贝,账本缺失/损坏时 _load 回落默认值故此处为 {};
730
764
  def sessions(self) -> dict:
731
765
  return dict(self._load()["sessions"])
732
766
 
767
+ # 生效条件:取 d=_load()["sessions"] 后返回 {"sessions": len(d), "events": sum(int(v.get("events") or 0)), "latest": max(v.get("last_t") or 0) if d else None},d 为空时 latest 为 None;
733
768
  def summary(self) -> dict:
734
769
  d = self._load()["sessions"]
735
770
  return {"sessions": len(d),
@@ -738,6 +773,7 @@ class SessionLedger:
738
773
  if d else None}
739
774
 
740
775
 
776
+ # 生效条件:os.path.exists(os.path.join(cg.root, "_sources.json")) 为真且 json.load 成功时返回 dict((d or {}).get("sources") or {})(d 或 sources 为假值即回落 {});该路径不可读或 json.load 抛 ValueError/OSError 时返回 {};
741
777
  def watermarks(cg) -> dict:
742
778
  """源视角水位快照(读 sources.Ingestor 的 _sources.json)。"""
743
779
  p = os.path.join(cg.root, "_sources.json")
@@ -755,6 +791,7 @@ def watermarks(cg) -> dict:
755
791
  # 常驻循环
756
792
  # --------------------------------------------------------------------------
757
793
 
794
+ # 生效条件:传入 cg 即构造实例并把 self.cg 指向它,name/beat_interval/heal_interval/auto_heal/scrub_interval/auto_scrub/evolve_interval/auto_evolve/tidy_interval/auto_tidy 用各默认值(DEFAULT_* 与 False/True)经 float()/bool() 落为 self 属性,ledger 为假值(默认 None)时回落 SessionLedger(cg.root),d 经 net_dir(d) 赋值,其余运行态字段初始化为 False/None/空列表/空 Event/Lock
758
795
  class SustainLoop:
759
796
  """常驻自维持循环:后台线程周期心跳 + 周期巡检 + 必要时自愈。
760
797
 
@@ -762,6 +799,7 @@ class SustainLoop:
762
799
  让对端立刻看到「正常下线」而不是「失联」。
763
800
  """
764
801
 
802
+ # 生效条件:传入 cg 时按 name 与各 DEFAULT_* 默认值初始化——self.d=net_dir(d)(d 假值时回落 MDCG_SUSTAIN_DIR/~/ .mdcg/sustain)、self.ledger=ledger or SessionLedger(cg.root)(ledger 假值时新建),beat/heal/scrub/evolve/tidy 间隔 float() 化、auto_heal/auto_scrub/auto_evolve/auto_tidy bool() 化后存为实例属性;
765
803
  def __init__(self, cg, name: str = "md_cg", *,
766
804
  beat_interval: float = DEFAULT_BEAT_INTERVAL,
767
805
  heal_interval: float = DEFAULT_HEAL_INTERVAL,
@@ -797,6 +835,8 @@ class SustainLoop:
797
835
  self.evolves = []
798
836
  self.last_tidy = None
799
837
  self.tidys = []
838
+ # 数据健康不变量断言集结论(Pi⑤):与 tidy 同节奏,只取结论不落盘
839
+ self.last_conformance = None
800
840
  self._started_at = None
801
841
  self._th = None
802
842
  self._stop = threading.Event()
@@ -804,6 +844,7 @@ class SustainLoop:
804
844
 
805
845
  # ---- 心跳 ----
806
846
 
847
+ # 生效条件:task_running 非 None 时先置 self.task_running=bool(task_running),再 write_stamp(self.name, self.d, task_running=self.task_running, root=self.cg.root, uptime=... if self._started_at else 0.0),beats 自增并记 last_beat=rec["ts"],返回该 rec;
807
848
  def beat(self, task_running: bool = None) -> dict:
808
849
  if task_running is not None:
809
850
  self.task_running = bool(task_running)
@@ -817,6 +858,7 @@ class SustainLoop:
817
858
 
818
859
  # ---- 生命周期 ----
819
860
 
861
+ # 生效条件:不适用(无必需形参与模块级常量)
820
862
  def start(self):
821
863
  if self._th is not None and self._th.is_alive():
822
864
  return self
@@ -828,6 +870,7 @@ class SustainLoop:
828
870
  self._th.start()
829
871
  return self
830
872
 
873
+ # 生效条件:调用时置 _stop 事件,self._th 非 None 时 join(timeout)(默认 3.0)后置为 None,随后 clear_stamp(self.name, self.d),返回 self;
831
874
  def stop(self, timeout: float = 3.0):
832
875
  self._stop.set()
833
876
  if self._th is not None:
@@ -836,6 +879,7 @@ class SustainLoop:
836
879
  clear_stamp(self.name, self.d)
837
880
  return self
838
881
 
882
+ # 生效条件:self._stop 未置位期间轮询,按 beat_interval/heal_interval/scrub_interval/evolve_interval/tidy_interval 到期分别执行 beat 与 _tick_heal/_tick_scrub/_tick_evolve/_tick_tidy,各 tick 抛出的异常被吞掉不中断循环,末尾以 _stop.wait(_POLL) 休眠;
839
883
  def _run(self):
840
884
  next_beat = time.time() + self.beat_interval
841
885
  next_heal = time.time() + self.heal_interval
@@ -876,6 +920,7 @@ class SustainLoop:
876
920
  next_tidy = now + self.tidy_interval
877
921
  self._stop.wait(_POLL)
878
922
 
923
+ # 生效条件:以 apply=self.auto_tidy 调 writelimit.tidy_contextual(self.cg, actor="sustain_tidy"),把 t/scanned/groups/members/applied_count/auto_tidy 记入 self.last_tidy 与 tidys(仅保留最近 20 条),随后调 _tick_conformance();auto_tidy=False(默认)时只盘点不落盘;
879
924
  def _tick_tidy(self):
880
925
  """整理巡检(contextual 流水治理·读侧):同构组聚合 + 成员降权。
881
926
 
@@ -894,7 +939,24 @@ class SustainLoop:
894
939
  with self._lock:
895
940
  self.tidys.append(rec)
896
941
  self.tidys = self.tidys[-20:]
942
+ self._tick_conformance()
897
943
 
944
+ # 生效条件:把 conformance.report_summary(self.cg) 的结论写入 self.last_conformance;该调用抛异常时写入 {"ok": False, "verdict": "BLINDSPOT", "error": "<类型名>: <消息>"};
945
+ def _tick_conformance(self):
946
+ """数据健康不变量断言集(Pi⑤)——与 tidy 同节奏,**只取结论**。
947
+
948
+ 复用 tidy 的 6h 节奏而不新开周期:两者都是「存量数据体检」,且都是
949
+ 只读巡检。纪律:本断言集**只告警不改数据**,故 `auto_*` 在此无意义;
950
+ `check_paths=False` 跳过 1.1 万次 stat,`_audit.jsonl` 只读尾窗。
951
+ """
952
+ from . import conformance
953
+ try:
954
+ self.last_conformance = conformance.report_summary(self.cg)
955
+ except Exception as e: # noqa: BLE001
956
+ self.last_conformance = {"ok": False, "verdict": "BLINDSPOT",
957
+ "error": f"{type(e).__name__}: {e}"}
958
+
959
+ # 生效条件:恒以 evolution_candidates(self.cg) 只读盘点并记入 last_evolve 与 evolves(保留最近 20 条);仅当 self.auto_evolve 为真且 ev["importance_drift"]["n"] 为真时才额外执行 weights.recalc(self.cg, apply=True, actor="sustain_evolve"),其异常写入 rec["applied"];
898
960
  def _tick_evolve(self):
899
961
  """演化巡检(G7):盘点固化/重要性候选 —— 让「有能力」变成「有驱动」。
900
962
 
@@ -921,6 +983,7 @@ class SustainLoop:
921
983
  self.evolves.append(rec)
922
984
  self.evolves = self.evolves[-20:]
923
985
 
986
+ # 生效条件:以 dry_run=not self.auto_scrub 调 scrub.sweep(self.cg),把 t/ok/n_issues/n_high_medium/applied/dry_run 记入 last_scrub 与 scrubs(保留最近 20 条);auto_scrub=False(默认)时 dry_run=True 只读巡检;
924
987
  def _tick_scrub(self):
925
988
  """记忆自净:抽查 → 联想 → 去污染 → 校准偏差。
926
989
 
@@ -939,6 +1002,7 @@ class SustainLoop:
939
1002
  self.scrubs.append(rec)
940
1003
  self.scrubs = self.scrubs[-20:]
941
1004
 
1005
+ # 生效条件:先 diagnose(self.cg, name=self.name) 并将 ok 与 issues code 记入 last_diagnose;仅当 self.auto_heal 为真且 rep["ok"] 为假时才调 heal(self.cg, name=self.name),其 actions 非空时把各 action 的 code 记入 heals(保留最近 20 条);
942
1006
  def _tick_heal(self):
943
1007
  rep = diagnose(self.cg, name=self.name)
944
1008
  self.last_diagnose = {"t": time.time(), "ok": rep["ok"],
@@ -954,6 +1018,7 @@ class SustainLoop:
954
1018
 
955
1019
  # ---- 状态 ----
956
1020
 
1021
+ # 生效条件:以 read_stamp(self.name, self.d) 判定 state(有戳走 judge(age, interval=self.beat_interval, task_running=...),无戳为 "stopped"),返回含 name/running/pid/uptime(无 _started_at 时为 0.0)/beats/last_beat/各 interval 与 auto_* 开关/heals[-5:]/evolves[-5:]/tidys[-5:]/peers(self.d)/ledger.summary() 的 dict;
957
1022
  def status(self) -> dict:
958
1023
  st = read_stamp(self.name, self.d)
959
1024
  state = (judge(st["age"], interval=self.beat_interval,
@@ -980,6 +1045,7 @@ class SustainLoop:
980
1045
  "evolves": self.evolves[-5:],
981
1046
  "last_tidy": self.last_tidy,
982
1047
  "tidys": self.tidys[-5:],
1048
+ "last_conformance": self.last_conformance,
983
1049
  "peers": peers(self.d),
984
1050
  "sessions": self.ledger.summary()}
985
1051
 
@@ -988,6 +1054,7 @@ _LOOPS = {}
988
1054
  _LOOPS_LOCK = threading.Lock()
989
1055
 
990
1056
 
1057
+ # 生效条件:cg 必填,以 (os.path.abspath(cg.root), name) 为键在模块级 _LOOPS 中复用已有实例或新建 SustainLoop 并返回该实例。
991
1058
  def ensure_loop(cg, name: str = "md_cg", **kw) -> SustainLoop:
992
1059
  """按 (root, name) 复用同一个常驻循环(避免重复线程 / 重复戳)。"""
993
1060
  key = (os.path.abspath(cg.root), name)
@@ -999,10 +1066,12 @@ def ensure_loop(cg, name: str = "md_cg", **kw) -> SustainLoop:
999
1066
  return lp
1000
1067
 
1001
1068
 
1069
+ # 生效条件:cg 必填,返回 _LOOPS[(os.path.abspath(cg.root), name)],该键未登记时返回 None。
1002
1070
  def get_loop(cg, name: str = "md_cg"):
1003
1071
  return _LOOPS.get((os.path.abspath(cg.root), name))
1004
1072
 
1005
1073
 
1074
+ # 生效条件:模块级 _LOOPS 非空时清空该表并对每个循环调用 stop()(异常被吞),无返回值。
1006
1075
  def stop_all():
1007
1076
  """测试 / 进程退出用:停掉本进程创建的所有常驻循环。"""
1008
1077
  with _LOOPS_LOCK:
@@ -1015,6 +1084,7 @@ def stop_all():
1015
1084
  pass
1016
1085
 
1017
1086
 
1087
+ # 生效条件:以 read_stamp(name) 有戳时返回 heartbeat={'age': round(st["age"],1), 'state': judge(...), 'pid', 'task_running'}、无戳时 {'state':'absent'},loop 取 get_loop(cg, name) 有值时给 running/beats/state、无值时 {'running': False},并附带 SessionLedger(cg.root).summary()、scrub_summary(cg)、evolve_summary(cg)、provenance_summary(cg);
1018
1088
  def summary(cg, name: str = "md_cg") -> dict:
1019
1089
  """并入 health_os 的轻量摘要(只读戳与计数,不做巡检)。"""
1020
1090
  st = read_stamp(name)
@@ -1036,6 +1106,7 @@ def summary(cg, name: str = "md_cg") -> dict:
1036
1106
  }
1037
1107
 
1038
1108
 
1109
+ # 生效条件:cg 必填,可导入 provenance 且其 summary(cg) 调用成功时返回该摘要,异常时返回 {}。
1039
1110
  def provenance_summary(cg) -> dict:
1040
1111
  """派生溯源摘要(G8,只读;失败不抛,避免拖垮 health_os)。"""
1041
1112
  try:
@@ -1045,6 +1116,7 @@ def provenance_summary(cg) -> dict:
1045
1116
  return {}
1046
1117
 
1047
1118
 
1119
+ # 生效条件:cg 必填,evolution_candidates(cg, top=3) 成功时返回 candidates/ccg_backlog/importance_drift 计数摘要,异常时返回 {}。
1048
1120
  def evolve_summary(cg) -> dict:
1049
1121
  """演化巡检摘要(只读;失败不抛,避免拖垮 health_os)。"""
1050
1122
  try:
@@ -1057,10 +1129,11 @@ def evolve_summary(cg) -> dict:
1057
1129
  return {}
1058
1130
 
1059
1131
 
1132
+ # 生效条件:cg 必填,可导入 scrub 且其 summary(cg) 调用成功时返回该摘要,异常时返回 {}。
1060
1133
  def scrub_summary(cg) -> dict:
1061
1134
  """记忆自净摘要(惰性导入,避免模块加载顺序耦合)。"""
1062
1135
  try:
1063
1136
  from . import scrub
1064
1137
  return scrub.summary(cg)
1065
1138
  except Exception: # noqa: BLE001
1066
- return {}
1139
+ return {}