@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
@@ -3,13 +3,18 @@
3
3
  #
4
4
  # 说明:
5
5
  # - !!js process.env.X 语法在加载期求值,密钥不入库
6
- # - 记忆写入路径(下面 mdcg.root)默认锚定**插件仓自身** data/,与进程 cwd
7
- # 解耦——历史事故:cwd 落在别的仓时,相对路径会把记忆真源写偏。目录不存在
8
- # 会自动创建。想换位置有三种方式(优先级由高到低):
6
+ # - 记忆写入路径(下面 mdcg.root)默认落在**用户级状态根**(~/.dsh/.dsh-memory/data),
7
+ # 与进程 cwd、**插件包目录**都解耦——历史事故①:cwd 落在别的仓时相对路径会把
8
+ # 记忆真源写偏;事故②:默认曾锚定插件包内 data/,而 pnpm 更新包会整目录替换,
9
+ # 包内数据每次更新成功即被删掉(详见 src/lib/datapath.ts 头注)。目录不存在会
10
+ # 自动创建。想换位置有三种方式(优先级由高到低):
9
11
  # ① 环境变量 MDCG_DATA_ROOT(数据根)/ MDCG_ROOT(认知图根)
10
- # ② 编辑 <插件仓>/data/paths.json 的 "data_root" / "root"
12
+ # ② 编辑 <用户级状态根>/paths.json 的 "data_root" / "root"
13
+ # (旧版包内 data/paths.json 仍兼容读,但会被下次 pnpm 更新删除)
11
14
  # ③ 本文件的 mdcg.root(填绝对路径或相对插件仓的路径)
12
15
  # 查当前解析结果:python md_cg/datapath.py
16
+ # 旧版数据迁移:包内 data/ 仍有内容时,插件首启会**复制**(不删除)到用户级根;
17
+ # 也可手动执行 python md_cg/datapath.py --migrate-legacy
13
18
 
14
19
  - id: lingshu-memory
15
20
  name: '@furongjun1999/dsh-memory'
@@ -108,9 +113,10 @@
108
113
  mdcg:
109
114
  enabled: true
110
115
  # root = 记忆写入路径(用户可改)。留空 '' = 走解析优先级,默认落在
111
- # **插件仓自身** data/mdcg(与 cwd 解耦):
112
- # env MDCG_ROOT > data/paths.json 的 "root" > 本项 > 默认 <插件仓>/data/mdcg
113
- # 想换位置:填绝对路径(如 'D:/lingshu/mdcg'),或改 data/paths.json。
116
+ # **用户级状态根** data/mdcg(与 cwd、插件包目录都解耦):
117
+ # env MDCG_ROOT > <用户级状态根>/paths.json 的 "root" > 本项
118
+ # > 默认 ~/.dsh/.dsh-memory/data/mdcg
119
+ # 想换位置:填绝对路径(如 'D:/lingshu/mdcg'),或改 paths.json。
114
120
  root: ''
115
121
  actor: 'dsh-memory' # MDCG_ACTOR:私有内容按 (tenant, actor) 派生 DEK
116
122
  tenant: 'default' # MDCG_TENANT:须与迁移脚本 --tenant 一致
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * hive-mcp-probe.mjs —— 用 DSH 自带的 @modelcontextprotocol/sdk 直接连一次蜂巢 MCP server。
4
+ *
5
+ * 目的:在不动 DSH 进程的前提下,验证「DSH 的 mcp-client 会看到什么」。
6
+ * - 用与 dsh-mcp-client 同一个 SDK(版本一致)走 stdio 握手
7
+ * - tools/list → 工具名与入参 schema
8
+ * - tools/call hive_doctor → serve 存活与任务统计
9
+ * - (可选)tools/call hive_spawn → 真提交一个任务,证明写路径通
10
+ *
11
+ * 用法:node dsh/hive-mcp-probe.mjs [--spawn]
12
+ * 依赖环境变量(可覆盖):DSH_ROOT、HIVE_REPO、HIVE_LIB、MDCG_ROOT
13
+ * DSH_ROOT = DSH 安装目录(其下含 node_modules/@modelcontextprotocol/sdk)
14
+ * HIVE_REPO = dsh-memory 仓绝对路径
15
+ * HIVE_LIB = 认知图库仓绝对路径(追加进 PYTHONPATH)
16
+ * MDCG_ROOT = 认知图根
17
+ * 四个值未设置且脚本内仍为占位符时直接报错退出——本仓是公开仓,不硬编码本机路径。
18
+ */
19
+ const DSH_ROOT = (process.env.DSH_ROOT || '<REPLACE_WITH_DSH_INSTALL_DIR>').replace(/\\/g, '/')
20
+ const REPO = process.env.HIVE_REPO || '<REPLACE_WITH_ABSOLUTE_PATH_TO_dsh-memory>'
21
+ const LIB = process.env.HIVE_LIB || '<REPLACE_WITH_ABSOLUTE_PATH_TO_mdcg_lib>'
22
+ const MDCG_ROOT = process.env.MDCG_ROOT || '<REPLACE_WITH_ABSOLUTE_PATH_TO_MDCG_ROOT>'
23
+
24
+ const PH = { DSH_ROOT, HIVE_REPO: REPO, HIVE_LIB: LIB, MDCG_ROOT }
25
+ const missing = Object.entries(PH).filter(([, v]) => v.includes('REPLACE_WITH'))
26
+ if (missing.length) {
27
+ console.error('[ABORT] 以下参数仍是占位符,请用同名环境变量覆盖后重跑:' + missing.map(([k]) => k).join(', '))
28
+ process.exit(1)
29
+ }
30
+
31
+ const SDK = 'file:///' + DSH_ROOT + '/node_modules/@modelcontextprotocol/sdk/dist/esm'
32
+ const { Client } = await import(SDK + '/client/index.js')
33
+ const { StdioClientTransport } = await import(SDK + '/client/stdio.js')
34
+
35
+ const doSpawn = process.argv.includes('--spawn')
36
+
37
+ const transport = new StdioClientTransport({
38
+ command: 'python',
39
+ args: ['-m', 'hive.hive_mcp.mcp_server'],
40
+ cwd: REPO,
41
+ env: {
42
+ ...process.env,
43
+ PYTHONPATH: REPO + ';' + LIB,
44
+ PYTHONUTF8: '1',
45
+ PYTHONIOENCODING: 'utf-8',
46
+ MDCG_ROOT,
47
+ },
48
+ })
49
+
50
+ const client = new Client({ name: 'dsh-hive-probe', version: '1.0.0' })
51
+ await client.connect(transport)
52
+ console.log('[OK] MCP 握手成功(stdio)')
53
+ console.log('serverInfo =', JSON.stringify(client.getServerVersion?.() ?? {}))
54
+
55
+ const listed = await client.listTools()
56
+ console.log('[OK] tools/list 返回 ' + listed.tools.length + ' 个工具:')
57
+ for (const t of listed.tools) {
58
+ console.log(' - ' + t.name + ' 参数:' + Object.keys(t.inputSchema?.properties ?? {}).join(', '))
59
+ }
60
+
61
+ const doc = await client.callTool({ name: 'hive_doctor', arguments: {} })
62
+ const docText = (doc.content ?? []).map((c) => c.text ?? '').join('')
63
+ console.log('[OK] hive_doctor →')
64
+ console.log(' ' + docText.slice(0, 900).replace(/\n/g, '\n '))
65
+
66
+ if (doSpawn) {
67
+ const tag = 'HIVE_MCP_OK_' + Date.now()
68
+ const sp = await client.callTool({ name: 'hive_spawn', arguments: {
69
+ model: 'deepseek-flash',
70
+ user_prompt: 'Reply with exactly this token and nothing else: ' + tag,
71
+ max_tokens: 2000,
72
+ } })
73
+ const spText = (sp.content ?? []).map((c) => c.text ?? '').join('')
74
+ console.log('[OK] hive_spawn → ' + spText.slice(0, 400))
75
+ const jobId = (spText.match(/h\d+_[0-9a-f]+/) || [])[0]
76
+ if (jobId) {
77
+ let last = ''
78
+ for (let i = 0; i < 60; i++) {
79
+ await new Promise((r) => setTimeout(r, 3000))
80
+ const pl = await client.callTool({ name: 'hive_poll', arguments: { job_id: jobId } })
81
+ const txt = (pl.content ?? []).map((c) => c.text ?? '').join('')
82
+ const st = (txt.match(/"state"\s*:\s*"([a-z]+)"/) || [])[1]
83
+ if (st !== last) { console.log(' poll ' + jobId + ' state=' + st); last = st }
84
+ if (['done', 'error', 'timeout', 'killed'].includes(st)) {
85
+ console.log('[RESULT] ' + txt.slice(0, 1200))
86
+ console.log('[CHECK] 令牌往返 ' + (txt.includes(tag) ? '通过(content 含 ' + tag + ')' : '未在片段中看到令牌,读全文确认'))
87
+ break
88
+ }
89
+ }
90
+ }
91
+ }
92
+
93
+ await client.close()
94
+ console.log('[DONE] 探针结束')
@@ -0,0 +1,62 @@
1
+ # ─────────────────────────────────────────────────────────────────────────────
2
+ # 蜂巢(hive)MCP 接入 · DSH 端配置样例(本机实测通过 2026-09-17)
3
+ #
4
+ # 作用:把 hive 的 4 个工具变成 DSH 原生工具,交给模型直接调用:
5
+ # mcp__hive__hive_spawn 提交 LLM 任务(毫秒返回 job_id,蜂巢后台并发执行)
6
+ # mcp__hive__hive_poll 查状态 / 读结果(含 handoff_ready 交回信号)
7
+ # mcp__hive__hive_kill 写 kill 标志强杀(worker ≤1s 生效)
8
+ # mcp__hive__hive_doctor 体检:serve 存活 / 任务统计 / env 资格列
9
+ #
10
+ # 放置位置:$DSH_HOME/profiles/<profile>/cordis.patch.yml(用户 patch 层,追加即可)
11
+ #
12
+ # ⚠️ 必须包在 `- insert:` 里。用户 patch 层的裸条目 `- id: xxx` 语义是「覆盖已
13
+ # 有行的 config」;对不存在的 id **不生效,而且不报错**。实测:裸写 mcp-hive
14
+ # 后 `dsh --profile web --dump-config` 里查无此行、stderr 也为空;改成
15
+ # `- insert: [...]` 后立刻出现在 dump 里。
16
+ #
17
+ # 前置依赖(一次性):
18
+ # 1) profile 需能解析 @deepseek-ai/dsh-mcp-client(DSH 自带此包,用 link: 指过去):
19
+ # {"@deepseek-ai/dsh-mcp-client": "link:<你的 DSH 安装目录>/node_modules/@deepseek-ai/dsh-mcp-client"}
20
+ # 再用 pnpm install --lockfile-only 同步 lockfile(只写 lockfile,不动 node_modules)。
21
+ # node_modules 下的目录实体与其它 link: 依赖同形(Windows Junction),可手工补齐:
22
+ # New-Item -ItemType Junction -Path <profile>\\node_modules\\@deepseek-ai\\dsh-mcp-client -Target <上面的路径>
23
+ # (DSH 运行中跑 pnpm install 会被 <profile>\\node_modules\\@furongjun1999\\dsh-memory
24
+ # 的目录锁挡住报 EPERM;用 Junction 可绕开,因为不重命名任何目录。)
25
+ # 2) 生效时机:profile 的 patchReload 默认 "startup" → 改完要**重启 DSH**才加载。
26
+ #
27
+ # 实测要点(2026-09-17 本机,全部有回显证据):
28
+ # · mcp-client 会清洗宿主环境变量:只继承 APPDATA / HOMEDRIVE / HOMEPATH /
29
+ # LOCALAPPDATA / PATH / PROCESSOR_ARCHITECTURE / SYSTEMDRIVE / SYSTEMROOT /
30
+ # TEMP / USERNAME / USERPROFILE / PROGRAMFILES 这 12 个
31
+ # (@modelcontextprotocol/sdk 的 stdio.js::DEFAULT_INHERITED_ENV_VARS)。
32
+ # → PYTHONPATH / PYTHONUTF8 必须在这里显式声明,否则
33
+ # `python -m hive.hive_mcp.mcp_server` 直接 ModuleNotFoundError。
34
+ # · hive/ 是 python 包;`-m hive.hive_mcp.mcp_server` 要求 PYTHONPATH 指向仓根。
35
+ # · serve 未存活时 hive_spawn 会自动拉起(复用 serve_start.start())。该路径的
36
+ # env = MCP 进程 env + hive/config.local.json;而 config.local.json 里
37
+ # HIVE_API_KEY 的来源写作 {"env": "DEEPSEEK_API_KEY"} → 必须把
38
+ # DEEPSEEK_API_KEY 传下来,否则自动拉起的是「没钥匙的 serve」,任务必失败。
39
+ # · 验收(端到端):mcp__hive__hive_spawn 提交 → mcp__hive__hive_poll 轮询到
40
+ # done。实测 job h1789598763792_32c0aa:claimed→running→done 5.77s,
41
+ # content 与提示词约定的令牌逐字相同,且 serve 由本次 spawn 自动拉起。
42
+ # · 可用 `node dsh/hive-mcp-probe.mjs` 在不动 DSH 的前提下单独验证 server 侧。
43
+ # · 本文件是公开仓模板:下面 4 个 <REPLACE_WITH_...> 占位符须换成你自己的
44
+ # 绝对路径(正斜杠写法),否则客户端会以错误 cwd/PYTHONPATH 启动 server。
45
+ # ─────────────────────────────────────────────────────────────────────────────
46
+ - insert:
47
+ - id: mcp-hive
48
+ name: '@deepseek-ai/dsh-mcp-client'
49
+ config:
50
+ serverName: hive
51
+ transport: stdio
52
+ command: python
53
+ args: ['-m', 'hive.hive_mcp.mcp_server']
54
+ cwd: '<REPLACE_WITH_ABSOLUTE_PATH_TO_dsh-memory>'
55
+ env:
56
+ PYTHONPATH: '<REPLACE_WITH_ABSOLUTE_PATH_TO_dsh-memory>;<REPLACE_WITH_ABSOLUTE_PATH_TO_mdcg_lib>'
57
+ PYTHONUTF8: '1'
58
+ PYTHONIOENCODING: 'utf-8'
59
+ MDCG_ROOT: '<REPLACE_WITH_ABSOLUTE_PATH_TO_MDCG_ROOT>'
60
+ DEEPSEEK_API_KEY: !!js process.env.DEEPSEEK_API_KEY
61
+ toolCallTimeoutMs: 60000
62
+ failOnStartupError: false
@@ -0,0 +1,11 @@
1
+ @echo off
2
+ rem ============================================================
3
+ rem update-lingshu.bat - 灵枢插件一键更新(占位:逻辑在 update-lingshu.ps1)
4
+ rem ============================================================
5
+ setlocal
6
+ powershell -NoProfile -ExecutionPolicy Bypass -File "%~dp0update-lingshu.ps1" %*
7
+ set RC=%ERRORLEVEL%
8
+ echo.
9
+ if "%RC%"=="0" (echo [OK] update finished.) else (echo [FAILED] exit %RC% - see %TEMP%\update-lingshu.log)
10
+ pause
11
+ endlocal
@@ -0,0 +1,337 @@
1
+ #Requires -Version 5.1
2
+ <#
3
+ update-lingshu.ps1 —— 灵枢大脑(@furongjun1999/dsh-memory)一键更新
4
+
5
+ 为什么需要它(2026-09-16 实测得到的三条教训):
6
+ 1) 目录锁:pnpm 装新版本的最后一步是把 dsh-memory_tmp_NNN 重命名成 dsh-memory。
7
+ 只要 DSH 主进程还活着(工作目录锚在这个包内),Windows 就拒绝重命名,
8
+ 报 EPERM ... rename ... dsh-memory_tmp_NNN。所以更新前必须先停 DSH。
9
+ 2) 发布龄闸门:pnpm 有供应链 minimumReleaseAge 策略,刚发布的版本默认解析不进来,
10
+ 必须在 pnpm-workspace.yaml 的 minimumReleaseAgeExclude 里显式放行,
11
+ 否则 pnpm 会安静地"更新成功",版本号却一动不动。
12
+ 3) 慢网:本机到 registry.npmjs.org 可能只有几十 KB/s,27MB 的包会撞上 pnpm 默认
13
+ 60s 下载超时。本脚本改用 curl 断点续传 + sha512 校验,再按文件覆盖安装
14
+ (不重命名目录),最后逐文件哈希核对与发布包是否一致。
15
+
16
+ 用法:
17
+ update-lingshu.bat 双击:更新到 npm 最新版并重启 DSH
18
+ powershell -File update-lingshu.ps1 -DryRun 只看要做什么,不落任何修改
19
+ powershell -File update-lingshu.ps1 -NoRestart
20
+ powershell -File update-lingshu.ps1 -UsePnpm 走 pnpm 官方安装路线(慢网可能超时)
21
+ powershell -File update-lingshu.ps1 -Tarball C:\path\dsh-memory-0.4.9.tgz
22
+ powershell -File update-lingshu.ps1 -Force 已是最新也重装一遍
23
+
24
+ 日志:%TEMP%\update-lingshu.log
25
+ #>
26
+ [CmdletBinding()]
27
+ param(
28
+ [string]$Profile = 'web',
29
+ [switch]$NoRestart,
30
+ [switch]$DryRun,
31
+ [switch]$Force,
32
+ [switch]$UsePnpm,
33
+ [string]$Tarball = ''
34
+ )
35
+
36
+ $ErrorActionPreference = 'Stop'
37
+
38
+ $Pkg = '@furongjun1999/dsh-memory'
39
+ $ProfileDir = Join-Path $env:USERPROFILE ('.dsh\profiles\' + $Profile)
40
+ $PluginDir = Join-Path $ProfileDir 'node_modules\@furongjun1999\dsh-memory'
41
+ $WsFile = Join-Path $ProfileDir 'pnpm-workspace.yaml'
42
+ $PkgJson = Join-Path $ProfileDir 'package.json'
43
+ $LogFile = Join-Path $env:TEMP 'update-lingshu.log'
44
+ $Stamp = Get-Date -Format 'yyyyMMdd-HHmmss'
45
+ $script:TargetVersion = ''
46
+ $script:Stopped = $false
47
+
48
+ function Log {
49
+ param([string]$m, [string]$c = 'Gray')
50
+ $line = '[' + (Get-Date -Format 'HH:mm:ss') + '] ' + $m
51
+ Write-Host $line -ForegroundColor $c
52
+ try { Add-Content -Path $LogFile -Value $line -Encoding UTF8 } catch { }
53
+ }
54
+
55
+ function Get-InstalledVersion {
56
+ $p = Join-Path $PluginDir 'package.json'
57
+ if (-not (Test-Path $p)) { return '' }
58
+ $m = [regex]::Match((Get-Content $p -Raw -Encoding UTF8), '"version"\s*:\s*"([^"]+)"')
59
+ if ($m.Success) { return $m.Groups[1].Value }
60
+ return ''
61
+ }
62
+
63
+ function Get-LatestVersion {
64
+ $v = (& npm view $Pkg version 2>$null | Out-String).Trim()
65
+ if ($v -notmatch '^\d+\.\d+\.\d+') { throw ('无法从 npm 取到最新版本(返回: ' + $v + ')') }
66
+ return $v
67
+ }
68
+
69
+ function Get-NpmIntegrity {
70
+ param([string]$Version)
71
+ $v = (& npm view ($Pkg + '@' + $Version) dist.integrity 2>$null | Out-String).Trim()
72
+ if ($v -notmatch '^sha512-') { throw ('无法取到 ' + $Version + ' 的 dist.integrity,拒绝在无法校验的情况下覆盖安装') }
73
+ return $v
74
+ }
75
+
76
+ function Get-FileSha512 {
77
+ param([string]$Path)
78
+ $hex = (Get-FileHash $Path -Algorithm SHA512).Hash
79
+ $bytes = New-Object byte[] ($hex.Length / 2)
80
+ for ($i = 0; $i -lt $hex.Length; $i += 2) { $bytes[$i / 2] = [Convert]::ToByte($hex.Substring($i, 2), 16) }
81
+ return 'sha512-' + [Convert]::ToBase64String($bytes)
82
+ }
83
+
84
+ function Set-ReleaseGate {
85
+ param([string]$Version)
86
+ $text = Get-Content $WsFile -Raw -Encoding UTF8
87
+ $pattern = "(?m)^(\s*-\s*'?)" + [regex]::Escape($Pkg) + "@([^'\r\n]*)('?)\s*$"
88
+ $m = [regex]::Match($text, $pattern)
89
+ if ($m.Success) {
90
+ $list = $m.Groups[2].Value
91
+ $has = $false
92
+ foreach ($v in ($list -split '\|\|')) { if ($v.Trim() -eq $Version) { $has = $true } }
93
+ if ($has) {
94
+ Log ('发布龄闸门已放行 ' + $Version)
95
+ } elseif ($DryRun) {
96
+ Log ('[dry-run] 将把 ' + $Version + ' 追加进 minimumReleaseAgeExclude')
97
+ } else {
98
+ $new = $m.Groups[1].Value + $Pkg + '@' + $list.Trim() + ' || ' + $Version + $m.Groups[3].Value
99
+ $text = $text.Replace($m.Value, $new)
100
+ Log ('已放行发布龄闸门: ' + $Pkg + '@' + $Version)
101
+ }
102
+ } else {
103
+ if ($text -match '(?m)^minimumReleaseAgeExclude:') {
104
+ throw 'pnpm-workspace.yaml 的 minimumReleaseAgeExclude 不是单行列表,请手动把最新版本加进去'
105
+ }
106
+ if ($DryRun) {
107
+ Log '[dry-run] 将新增 minimumReleaseAgeExclude 段落'
108
+ } else {
109
+ $text = $text.TrimEnd() + [Environment]::NewLine + 'minimumReleaseAgeExclude:' + [Environment]::NewLine + " - '" + $Pkg + '@' + $Version + "'" + [Environment]::NewLine
110
+ Log '已新增 minimumReleaseAgeExclude 放行条目'
111
+ }
112
+ }
113
+ if ($text -notmatch '(?m)^fetchTimeout:') {
114
+ if ($DryRun) {
115
+ Log '[dry-run] 将把 pnpm 下载超时放宽到 900s(慢网必需)'
116
+ } else {
117
+ $text = $text.TrimEnd() + [Environment]::NewLine + 'fetchTimeout: 900000' + [Environment]::NewLine
118
+ Log '已把 pnpm 下载超时放宽到 900s(慢网必需)'
119
+ }
120
+ }
121
+ if (-not $DryRun) { [System.IO.File]::WriteAllText($WsFile, $text, (New-Object System.Text.UTF8Encoding($false))) }
122
+ }
123
+
124
+ function Set-ProfileRange {
125
+ param([string]$Version)
126
+ $text = Get-Content $PkgJson -Raw -Encoding UTF8
127
+ $pattern = '("' + [regex]::Escape($Pkg) + '"\s*:\s*")(?<v>[^"]*)(")'
128
+ $m = [regex]::Match($text, $pattern)
129
+ if (-not $m.Success) { throw ('profile package.json 里没有 ' + $Pkg + ',请先用 dsh plugin --profile ' + $Profile + ' add 安装') }
130
+ $old = $m.Groups['v'].Value
131
+ $newRange = '^' + $Version
132
+ if ($old -eq $newRange) {
133
+ Log ('依赖区间已是 ' + $newRange)
134
+ return
135
+ }
136
+ if ($DryRun) {
137
+ Log ('[dry-run] 将把依赖区间 ' + $old + ' 改成 ' + $newRange)
138
+ return
139
+ }
140
+ $text = $text.Replace($m.Value, $m.Groups[1].Value + $newRange + $m.Groups[3].Value)
141
+ [System.IO.File]::WriteAllText($PkgJson, $text, (New-Object System.Text.UTF8Encoding($false)))
142
+ Log ('依赖区间 ' + $old + ' → ' + $newRange)
143
+ }
144
+
145
+ function Sync-Lockfile {
146
+ if ($DryRun) { Log '[dry-run] 将执行 pnpm install --lockfile-only'; return }
147
+ Push-Location $ProfileDir
148
+ try {
149
+ $o = (& pnpm install --lockfile-only 2>&1 | Out-String)
150
+ if ($LASTEXITCODE -eq 0) {
151
+ Log 'lockfile 已同步到目标版本'
152
+ } else {
153
+ Log 'lockfile 同步失败(不致命,稍后由安装步骤兜底)' 'Yellow'
154
+ }
155
+ } catch {
156
+ Log ('lockfile 同步异常: ' + $_.Exception.Message) 'Yellow'
157
+ } finally { Pop-Location }
158
+ }
159
+
160
+ function Get-Tarball {
161
+ param([string]$Version, [string]$Hint, [string]$Integrity)
162
+ if ($Hint -ne '') {
163
+ if (-not (Test-Path $Hint)) { throw ('指定的 tarball 不存在: ' + $Hint) }
164
+ $full = (Get-Item $Hint).FullName
165
+ if ((Get-FileSha512 $full) -ne $Integrity) { throw ('本地 tarball 的 sha512 与 registry 不一致: ' + $full) }
166
+ Log ('使用本地 tarball: ' + $full + '(sha512 校验通过)')
167
+ return $full
168
+ }
169
+ $out = Join-Path $env:TEMP ('lingshu-' + $Version + '.tgz')
170
+ if (Test-Path $out) {
171
+ if ((Get-FileSha512 $out) -eq $Integrity) { Log ('复用已缓存且校验通过的 tarball: ' + $out); return $out }
172
+ Remove-Item $out -Force
173
+ }
174
+ $short = $Pkg.Substring($Pkg.IndexOf('/') + 1)
175
+ $url = 'https://registry.npmjs.org/' + $Pkg + '/-/' + $short + '-' + $Version + '.tgz'
176
+ if ($DryRun) {
177
+ Log ('[dry-run] 将断点续传下载 ' + $url + ' 并校验 sha512')
178
+ return $out
179
+ }
180
+ for ($i = 1; $i -le 15; $i++) {
181
+ & curl.exe -sS -L -C - -o $out --retry 3 --retry-delay 3 --max-time 900 --connect-timeout 30 $url 2>$null
182
+ $sz = 0
183
+ if (Test-Path $out) { $sz = (Get-Item $out).Length }
184
+ if ((Test-Path $out) -and ((Get-FileSha512 $out) -eq $Integrity)) {
185
+ Log ('tarball 下载完成并校验通过: ' + [math]::Round($sz / 1MB, 2) + ' MB')
186
+ return $out
187
+ }
188
+ Log (' 第 ' + $i + ' 次下载未完(' + [math]::Round($sz / 1MB, 2) + ' MB),继续断点续传…')
189
+ Start-Sleep -Seconds 3
190
+ }
191
+ throw '下载 tarball 失败(网络过慢)。可手动下载后用 -Tarball 指定本地文件'
192
+ }
193
+
194
+ function Stop-Holders {
195
+ param([bool]$IncludeDsh)
196
+ $n = 0
197
+ $procs = Get-CimInstance Win32_Process -Filter "name='node.exe' or name='python.exe' or name='pythonw.exe'" -ErrorAction SilentlyContinue
198
+ foreach ($p in $procs) {
199
+ $cl = [string]$p.CommandLine
200
+ if ($cl -eq '') { continue }
201
+ $kill = $false
202
+ if ($cl -match 'md_cg') { $kill = $true }
203
+ if ($IncludeDsh -and ($cl -match '@deepseek-ai[\\/]dsh')) { $kill = $true }
204
+ if ($kill) {
205
+ try {
206
+ Stop-Process -Id $p.ProcessId -Force -ErrorAction Stop
207
+ Log (' 已结束 pid=' + $p.ProcessId)
208
+ $n++
209
+ } catch {
210
+ Log (' pid=' + $p.ProcessId + ' 结束失败(可能已退出)')
211
+ }
212
+ }
213
+ }
214
+ return $n
215
+ }
216
+
217
+ function Install-Overlay {
218
+ param([string]$Tgz, [string]$Version)
219
+ $stage = Join-Path $env:TEMP ('lingshu-stage-' + $Version)
220
+ if (Test-Path $stage) { Remove-Item $stage -Recurse -Force }
221
+ New-Item -ItemType Directory -Path $stage -Force | Out-Null
222
+ Log ' 解包发布包…'
223
+ & tar.exe -xzf $Tgz -C $stage
224
+ $src = Join-Path $stage 'package'
225
+ if (-not (Test-Path (Join-Path $src 'package.json'))) { throw '解包结果缺少 package/package.json' }
226
+ $m = [regex]::Match((Get-Content (Join-Path $src 'package.json') -Raw -Encoding UTF8), '"version"\s*:\s*"([^"]+)"')
227
+ if (-not $m.Success -or $m.Groups[1].Value -ne $Version) { throw ('发布包内版本不是 ' + $Version) }
228
+ $suspect = Get-ChildItem $src -Recurse -File -Force | Where-Object { $_.Name -in @('_keys.json', '_audit.jsonl', '_index.json', '_refindex.json') }
229
+ if ($suspect) { throw ('发布包内出现不应发布的运行时文件: ' + $suspect[0].FullName) }
230
+ Log ' 覆盖写入插件目录(不重命名目录,DSH 开着也能装)…'
231
+ & robocopy $src $PluginDir /E /NFL /NDL /NJH /NJS /NP /R:2 /W:1 | Out-Null
232
+ Log ' 逐文件哈希核对…'
233
+ $bad = New-Object System.Collections.ArrayList
234
+ $all = Get-ChildItem $src -Recurse -File -Force
235
+ foreach ($f in $all) {
236
+ $rel = $f.FullName.Substring($src.Length + 1)
237
+ $dst = Join-Path $PluginDir $rel
238
+ if (-not (Test-Path $dst)) { [void]$bad.Add('缺失 ' + $rel); continue }
239
+ if ((Get-Item $dst).Length -ne $f.Length) { [void]$bad.Add('大小不符 ' + $rel); continue }
240
+ if ((Get-FileHash $dst -Algorithm SHA256).Hash -ne (Get-FileHash $f.FullName -Algorithm SHA256).Hash) { [void]$bad.Add('内容不符 ' + $rel) }
241
+ }
242
+ if ($bad.Count -gt 0) { throw ('覆盖后核对失败 ' + $bad.Count + ' 个文件,例如: ' + $bad[0]) }
243
+ Log (' 核对通过: ' + $all.Count + ' 个文件与发布包逐字节一致')
244
+ }
245
+
246
+ function Install-WithPnpm {
247
+ Push-Location $ProfileDir
248
+ try {
249
+ for ($i = 1; $i -le 6; $i++) {
250
+ Log (' pnpm update(第 ' + $i + ' 次)…')
251
+ $o = (& pnpm update 2>&1 | Out-String)
252
+ $v = Get-InstalledVersion
253
+ if ($v -eq $script:TargetVersion) { return $true }
254
+ Log (' 本轮结果仍为 ' + $v + ',重试前再清一次占锁子进程…')
255
+ [void](Stop-Holders -IncludeDsh:$false)
256
+ Start-Sleep -Seconds 3
257
+ }
258
+ return $false
259
+ } finally { Pop-Location }
260
+ }
261
+
262
+ function Start-Dsh {
263
+ $bat = Join-Path $PluginDir 'dsh\dsh-web-start.bat'
264
+ if (-not (Test-Path $bat)) { Log ('找不到启动脚本: ' + $bat) 'Yellow'; return }
265
+ Log '启动 DSH…'
266
+ Start-Process -FilePath $bat -WorkingDirectory (Split-Path $bat) | Out-Null
267
+ Log 'DSH 已在新窗口启动;浏览器访问 http://127.0.0.1:3080'
268
+ }
269
+
270
+ # ============================ 主流程 ============================
271
+ Log '===== 灵枢一键更新 ====='
272
+ Log ('profile 目录: ' + $ProfileDir)
273
+ if ($DryRun) { Log '运行模式: DryRun(不落任何修改)' 'Yellow' }
274
+
275
+ try {
276
+ if (-not (Test-Path $PluginDir)) { throw ('找不到插件目录: ' + $PluginDir) }
277
+ $cur = Get-InstalledVersion
278
+ $script:TargetVersion = Get-LatestVersion
279
+ Log ('当前版本 ' + $cur + ' → npm 最新 ' + $script:TargetVersion)
280
+
281
+ if ($cur -eq $script:TargetVersion -and -not $Force -and $Tarball -eq '') {
282
+ Log '已经是最新版本,未做任何修改。' 'Green'
283
+ exit 0
284
+ }
285
+
286
+ if (-not $DryRun) {
287
+ Copy-Item $WsFile ($WsFile + '.pre-update-' + $Stamp) -Force
288
+ Copy-Item $PkgJson ($PkgJson + '.pre-update-' + $Stamp) -Force
289
+ Log ('已备份 profile 配置(后缀 pre-update-' + $Stamp + ')')
290
+ }
291
+
292
+ Log '--- 1/5 放行发布龄闸门 + 声明目标版本 ---'
293
+ Set-ReleaseGate -Version $script:TargetVersion
294
+ Set-ProfileRange -Version $script:TargetVersion
295
+
296
+ Log '--- 2/5 同步 lockfile(只写 lockfile,不动目录)---'
297
+ Sync-Lockfile
298
+
299
+ Log '--- 3/5 准备发布包(sha512 校验)---'
300
+ $integrity = Get-NpmIntegrity $script:TargetVersion
301
+ $tgz = Get-Tarball -Version $script:TargetVersion -Hint $Tarball -Integrity $integrity
302
+ if ($DryRun) {
303
+ Log '--- DryRun 结束:以上动作均未执行 ---' 'Yellow'
304
+ Log ('完整日志: ' + $LogFile)
305
+ exit 0
306
+ }
307
+
308
+ Log '--- 4/5 停 DSH 与 md_cg 子进程(释放目录锁)---'
309
+ $killed = Stop-Holders -IncludeDsh:$true
310
+ $script:Stopped = $killed -gt 0
311
+ Log ('共结束 ' + $killed + ' 个进程;等待文件句柄释放…')
312
+ Start-Sleep -Seconds 3
313
+
314
+ Log '--- 5/5 安装 ---'
315
+ $ok = $false
316
+ if ($UsePnpm) {
317
+ $ok = Install-WithPnpm
318
+ if (-not $ok) { Log 'pnpm 路线未成功,改用发布包覆盖安装…' 'Yellow' }
319
+ }
320
+ if (-not $ok) { Install-Overlay -Tgz $tgz -Version $script:TargetVersion }
321
+ $final = Get-InstalledVersion
322
+ if ($final -ne $script:TargetVersion) { throw ('安装后版本仍为 ' + $final + ',预期 ' + $script:TargetVersion) }
323
+ Log ('安装完成: ' + $cur + ' → ' + $final) 'Green'
324
+
325
+ if ($NoRestart) {
326
+ Log '按 -NoRestart 未重启 DSH,请手动运行 dsh\dsh-web-start.bat' 'Yellow'
327
+ } else {
328
+ Start-Dsh
329
+ }
330
+ Log ('完整日志: ' + $LogFile)
331
+ exit 0
332
+ } catch {
333
+ Log ('[失败] ' + $_.Exception.Message) 'Red'
334
+ Log ('完整日志: ' + $LogFile) 'Red'
335
+ if ($script:Stopped -and -not $NoRestart) { Log '尝试把 DSH 重新拉起来…' 'Yellow'; Start-Dsh }
336
+ exit 1
337
+ }
package/lib/hooks.d.ts CHANGED
@@ -21,6 +21,14 @@
21
21
  * 模型请求组装 system prompt 时自动注入灵枢最近记忆
22
22
  * (`stg(op=timeline)`,最近记忆节点时间线),让记忆"自动可用"而不只依赖
23
23
  * Agent 主动调用 recall/think 工具。失败静默(不影响请求)。
24
+ * ⚠️ 该注入块的**稳定性**决定宿主是否新追加快照:内容没变时也必须照旧 push
25
+ * (宿主按渲染后的整段文本去重);跳过 push 反而会各追加一份「有块/无块」的快照
26
+ * —— 详见 installMemoryHooks 里的长注释。
27
+ *
28
+ * ⚠️ 注入文本**必经** escapePromptBraces(src/lib/prompt_safety.ts,issue #16):
29
+ * 宿主对 context 文本做严格 `{{variable}}` 插值,裸 `{{` 会让每轮 assemble 抛错
30
+ * → 会话永久不可用(记忆永久在库,非偶发)。记忆真源不动,只在**注入副本**上
31
+ * 打断 `{{`——新增任何 push context/section 的代码,同样必须过这道转义。
24
32
  */
25
33
  import '@deepseek-ai/dsh-session';
26
34
  import '@deepseek-ai/dsh-system-prompt';
package/lib/hooks.js CHANGED
@@ -21,9 +21,18 @@
21
21
  * 模型请求组装 system prompt 时自动注入灵枢最近记忆
22
22
  * (`stg(op=timeline)`,最近记忆节点时间线),让记忆"自动可用"而不只依赖
23
23
  * Agent 主动调用 recall/think 工具。失败静默(不影响请求)。
24
+ * ⚠️ 该注入块的**稳定性**决定宿主是否新追加快照:内容没变时也必须照旧 push
25
+ * (宿主按渲染后的整段文本去重);跳过 push 反而会各追加一份「有块/无块」的快照
26
+ * —— 详见 installMemoryHooks 里的长注释。
27
+ *
28
+ * ⚠️ 注入文本**必经** escapePromptBraces(src/lib/prompt_safety.ts,issue #16):
29
+ * 宿主对 context 文本做严格 `{{variable}}` 插值,裸 `{{` 会让每轮 assemble 抛错
30
+ * → 会话永久不可用(记忆永久在库,非偶发)。记忆真源不动,只在**注入副本**上
31
+ * 打断 `{{`——新增任何 push context/section 的代码,同样必须过这道转义。
24
32
  */
25
33
  import '@deepseek-ai/dsh-session';
26
34
  import '@deepseek-ai/dsh-system-prompt';
35
+ import { escapePromptBraces } from './lib/prompt_safety.js';
27
36
  /** 从 ContentBlock[] 提取纯文本。 */
28
37
  function extractText(blocks) {
29
38
  const parts = [];
@@ -94,8 +103,6 @@ const RECALL_MIN_CHARS = 24;
94
103
  const RECALL_MAX_CHARS = 1400;
95
104
  /** 永久层不自动注入(按需用 mdcg_recall / lingshu_stg 取)。 */
96
105
  const RECALL_SKIP_LAYERS = new Set(['anchor', 'self']);
97
- /** 连续跳过多少步后强制补一次(内容未变也刷新,防止压缩归档后块消失)。 */
98
- const RECALL_REPUSH_EVERY = 8;
99
106
  /** 分级递减渲染:按距当前的次序逐档收窄,早期条目信息量更大。
100
107
  *
101
108
  * 动机:注入块总长受限,而"最近 N 条"里越靠前的越可能被用到;线性等宽分配
@@ -125,18 +132,6 @@ function formatTimelineDecayed(payload) {
125
132
  }
126
133
  return out.join('\n').slice(0, RECALL_MAX_CHARS);
127
134
  }
128
- /** 去重:内容与上次相同就不再 push 新副本。
129
- *
130
- * 背景:本钩子挂在 `system-prompt/assemble` 上,每个 step 都会 push 一份,而每份
131
- * 都会留成独立的 surface 节点 → 同一块累积 N 份(实测 11 份 ≈2700 tok/请求),
132
- * 随步数线性增长。去重后同一块只占 1 份,外加每 RECALL_REPUSH_EVERY 步一次自愈刷新。 */
133
- function shouldPushRecall(text, lastText, skippedSincePush) {
134
- if (!text)
135
- return false;
136
- if (text !== lastText)
137
- return true;
138
- return skippedSincePush >= RECALL_REPUSH_EVERY;
139
- }
140
135
  /** 安装自动记忆钩子(effect 作用域内,随插件卸载自动移除)。
141
136
  *
142
137
  * mdcg 为 null(config.mdcg.enabled=false)时自动记忆整体停用:记忆真源是
@@ -164,27 +159,35 @@ export function installMemoryHooks(ctx, mdcg, opts) {
164
159
  };
165
160
  // P1 完善(自动 recall 注入):每次模型请求组装 system prompt 时,注入灵枢最近记忆。
166
161
  // 用 system-prompt/assemble 事件(waterfall)而非 llm/stream——后者请求 deep-frozen 不可改写。
162
+ //
163
+ // ⚠️ 必须**每步都 push**,哪怕内容与上一步逐字节相同。原因在宿主侧(dsh-agent-loop 的
164
+ // RuntimeContextProjection):assembly.contexts 会被渲染成一段「运行时上下文快照」,
165
+ // 每个 step 拿渲染后的**整段文本**与上一份已提交的快照比对,**只有不同才**在会话里
166
+ // append 一条新的 user/message(append 语义,旧的不会被替换或移除)。于是:
167
+ // · 内容不变 + 照旧 push → 渲染文本不变 → 宿主不追加任何东西(零开销、零增长);
168
+ // · 内容不变 + 跳过 push → 渲染文本**变了**(少了本块)→ 宿主追加一份「没有本块」的
169
+ // 快照;下一步再 push 又把本块加回来 → **再**追加一份。跳过一次反而多花两份快照
170
+ // (实测每份 ~250 tok),这正是 v0.4.8「每 8 步强制补一次」的自愈刷新会把长会话的
171
+ // inject 推到 30k+ tok 的原因。
172
+ // 因此本实现把「要不要补」交还给宿主:压缩归档后宿主会把 retained 置空并重新投影快照
173
+ // (RuntimeContextProjection 的 retained === null 分支),本块自然跟着回来——
174
+ // 不需要插件自己数步数做自愈。
167
175
  if (opts.autoRecall) {
168
176
  const recallLimit = Math.max(1, Math.min(10, opts.autoRecallLimit || 4));
169
- // 去重状态:同一块内容只保留一份 surface 节点,避免随步数线性增长。
170
- let lastRecallText = '';
171
- let skippedSincePush = 0;
172
177
  ctx.on('system-prompt/assemble', async (assembly, _ctx, next) => {
173
178
  try {
174
179
  // 异步取最近记忆节点(失败静默——不阻塞模型请求)
175
180
  if (graph.isReady()) {
176
181
  const text = formatTimelineDecayed(await graph.timeline(recallLimit));
177
- if (shouldPushRecall(text, lastRecallText, skippedSincePush)) {
178
- lastRecallText = text;
179
- skippedSincePush = 0;
182
+ if (text) {
183
+ // 注入边界转义(issue #16):宿主 system-prompt 对 context 文本做严格
184
+ // `{{variable}}` 插值,裸 `{{` 会 throw → 该轮请求整体失败。记忆原文
185
+ // (含用户命令里的 `{{.X}}`)必须保真落库,故只在注入副本上打断 `{{`。
180
186
  assembly.contexts.push({
181
187
  name: 'lingshu:auto-recall',
182
- text: `【灵枢最近记忆】\n${text.slice(0, RECALL_MAX_CHARS)}`,
188
+ text: escapePromptBraces(`【灵枢最近记忆】\n${text.slice(0, RECALL_MAX_CHARS)}`),
183
189
  });
184
190
  }
185
- else {
186
- skippedSincePush += 1;
187
- }
188
191
  }
189
192
  }
190
193
  catch { /* 静默:召回失败不影响请求 */ }