@furongjun1999/dsh-memory 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +572 -465
  2. package/docs/README.md +1 -0
  3. package/docs/eval/DSH/346/227/245/345/277/227/347/264/242/345/274/225v2_/345/217/202/350/200/203dsh-TUI_v1.0.md +248 -0
  4. package/docs/eval/DSH/346/227/245/345/277/227/347/264/242/345/274/225/346/225/210/346/236/234/351/252/214/350/257/201_v1.0.md +209 -0
  5. package/docs/eval/DSH/347/253/257/347/274/272/351/231/267/344/270/223/351/241/271_v1.0.md +254 -0
  6. package/docs/eval/P1b2_/350/257/273/351/235/242/344/273/243/351/231/205/344/277/256/345/244/215_v1.0.md +124 -0
  7. package/docs/eval/bench_lingshu_self/bench_self.py +140 -0
  8. package/docs/eval/bench_lingshu_self/self_bench_result.json +404 -0
  9. package/docs/eval/bench_lingshu_self//347/201/265/346/236/242/350/207/252/345/272/223/347/253/257/345/210/260/347/253/257/346/243/200/347/264/242/345/256/236/346/265/213_v1.0.md +38 -0
  10. package/docs/eval//344/270/215/345/217/257/351/235/240/346/200/247/350/220/275/345/234/260_P0_v1.0.md +185 -0
  11. package/docs/eval//345/217/221/345/270/20306_/344/270/200/351/224/256/351/205/215/347/275/256/344/270/216DSH0172_v1.0.md +171 -0
  12. package/docs/eval//346/225/205/351/232/234/346/263/250/345/205/245/345/256/236/346/265/213_v1.0.md +422 -0
  13. package/docs/eval//347/253/257/345/210/260/347/253/257LoCoMoQA/345/220/214/345/217/243/345/276/204/345/257/271/347/205/247_v1.0.md +100 -0
  14. package/docs/eval//347/253/257/345/210/260/347/253/257/345/271/262/346/211/260/346/261/240/350/257/204/346/265/213_/347/241/256/345/256/232/346/200/247/350/243/201/345/206/263vsLLM_judge_v1.1.md +197 -0
  15. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v1.md +156 -0
  16. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v10.md +210 -0
  17. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v11.md +227 -0
  18. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v12.md +203 -0
  19. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v13.md +233 -0
  20. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v14.md +191 -0
  21. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v15.md +213 -0
  22. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v16.md +214 -0
  23. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v17.md +199 -0
  24. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v18.md +183 -0
  25. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v19.md +207 -0
  26. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v2.md +156 -0
  27. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v3.md +152 -0
  28. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v4.md +128 -0
  29. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v5.md +114 -0
  30. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v6.md +192 -0
  31. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v7.md +187 -0
  32. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v8.md +207 -0
  33. package/docs/eval//347/274/272/351/231/267/346/214/226/346/216/230_/350/207/252/344/270/273/350/277/255/344/273/243_v9.md +203 -0
  34. package/docs/hive//345/256/211/345/205/250/345/256/241/350/256/241/345/256/236/351/224/232_v0.1.md +202 -0
  35. 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 +19 -3
  36. package/docs/images/lingshu-moonlight-covenant-poster-preview.jpg +0 -0
  37. package/docs/images/lingshu-moonlight-covenant-poster.png +0 -0
  38. package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +40 -40
  39. package/docs/theory//344/270/215/345/217/257/351/235/240/345/256/232/347/220/206/344/270/216/345/244/261/346/225/210/344/274/230/345/205/210/346/241/206/346/236/266_v0.3.md +365 -0
  40. package/docs//344/270/215/345/217/257/351/235/240/346/200/247/347/220/206/350/256/272_v0.1.md +343 -0
  41. package/dsh/cordis-patch-profile-web.example.yml +35 -0
  42. package/lib/bridge.d.ts +9 -0
  43. package/lib/bridge.js +35 -0
  44. package/lib/cli.d.ts +3 -0
  45. package/lib/cli.js +66 -0
  46. package/lib/index.js +7 -1
  47. package/lib/init.d.ts +88 -0
  48. package/lib/init.js +287 -0
  49. package/lib/lib/roleplay_web.js +530 -443
  50. package/lib/lib/token_store.d.ts +7 -1
  51. package/lib/lib/token_store.js +12 -3
  52. package/md_cg/audit.py +12 -1
  53. package/md_cg/backfill.py +16 -15
  54. package/md_cg/backfill_bucket_zh.py +35 -0
  55. package/md_cg/bench_e2e_judge.py +532 -0
  56. package/md_cg/bench_e2e_locomo_qa.py +368 -0
  57. package/md_cg/bench_e2e_qa.py +256 -0
  58. package/md_cg/branches.py +18 -2
  59. package/md_cg/ccgc.py +3 -2
  60. package/md_cg/chain.py +19 -4
  61. package/md_cg/consolidate.py +7 -6
  62. package/md_cg/crosscheck.py +4 -3
  63. package/md_cg/crypto.py +439 -437
  64. package/md_cg/datapath.py +395 -335
  65. package/md_cg/evidence.py +8 -3
  66. package/md_cg/export.py +3 -1
  67. package/md_cg/forgetting.py +2 -2
  68. package/md_cg/fsutil.py +48 -0
  69. package/md_cg/hotcache.py +255 -238
  70. package/md_cg/interop.py +161 -22
  71. package/md_cg/judgment_manifest.py +177 -0
  72. package/md_cg/links.py +655 -622
  73. package/md_cg/mcp_server.py +282 -31
  74. package/md_cg/mdcg.py +702 -126
  75. package/md_cg/mdcos.py +454 -68
  76. package/md_cg/mreview/govern.py +5 -4
  77. package/md_cg/postings.py +4 -2
  78. package/md_cg/readcache.py +76 -18
  79. package/md_cg/reconcile.py +228 -0
  80. package/md_cg/review_cli.py +215 -0
  81. package/md_cg/routing.py +28 -0
  82. package/md_cg/run_tests.py +211 -0
  83. package/md_cg/scrub.py +862 -852
  84. package/md_cg/security.py +385 -275
  85. package/md_cg/selfreport.py +3 -2
  86. package/md_cg/signer.py +565 -562
  87. package/md_cg/sources.py +3 -2
  88. package/md_cg/stg.py +6 -0
  89. package/md_cg/sustain.py +1168 -1138
  90. package/md_cg/test_access_hints.py +147 -0
  91. package/md_cg/test_branch_discard_tombstone.py +136 -0
  92. package/md_cg/test_branches.py +259 -249
  93. package/md_cg/test_chain_read_isolate.py +168 -0
  94. package/md_cg/test_datapath_device_name.py +203 -0
  95. package/md_cg/test_emit_negtail_cache.py +156 -0
  96. package/md_cg/test_en_pipeline.py +186 -166
  97. package/md_cg/test_govern_directread.py +421 -0
  98. package/md_cg/test_i32_hotcache_env_key.py +218 -0
  99. package/md_cg/test_identity_attribution.py +228 -147
  100. package/md_cg/test_index_crossprocess_reload.py +301 -0
  101. package/md_cg/test_index_durability.py +238 -224
  102. package/md_cg/test_interop.py +4 -2
  103. package/md_cg/test_interop_judgment.py +228 -0
  104. package/md_cg/test_issue39_utf8_stdio.py +273 -0
  105. package/md_cg/test_links_concurrent_write.py +188 -0
  106. package/md_cg/test_merge_upsert.py +168 -0
  107. package/md_cg/test_n123_derive_expiry_chain.py +205 -0
  108. package/md_cg/test_n130_verify_falsified_protect.py +185 -0
  109. package/md_cg/test_n131_merge_gate.py +205 -0
  110. package/md_cg/test_none_id_write_guard.py +165 -0
  111. package/md_cg/test_p1x_ref_root.py +160 -0
  112. package/md_cg/test_p27_docindex.py +774 -765
  113. package/md_cg/test_p2_mcp.py +3 -0
  114. package/md_cg/test_p32_backfill.py +304 -298
  115. package/md_cg/test_p39_verify_flow.py +90 -50
  116. package/md_cg/test_p47_session_view.py +60 -25
  117. package/md_cg/test_propose_tail_index.py +157 -0
  118. package/md_cg/test_read_scope_b27.py +277 -0
  119. package/md_cg/test_readcache_default_on.py +168 -0
  120. package/md_cg/test_readcache_precise_inval.py +270 -0
  121. package/md_cg/test_readcache_prodpath.py +55 -7
  122. package/md_cg/test_reconcile_v0.py +294 -0
  123. package/md_cg/test_retr_s1.py +6 -2
  124. package/md_cg/test_retr_s1b.py +67 -0
  125. package/md_cg/test_retr_s7.py +8 -0
  126. package/md_cg/test_retr_s9_entity_ctx.py +181 -175
  127. package/md_cg/test_retr_score_once.py +208 -0
  128. package/md_cg/test_review_cli_attribution.py +177 -0
  129. package/md_cg/test_review_cli_visibility.py +235 -0
  130. package/md_cg/test_review_onepass.py +170 -0
  131. package/md_cg/test_rrf_graph_seed_cache.py +154 -0
  132. package/md_cg/test_security_audit.py +155 -0
  133. package/md_cg/test_security_audit_b26.py +161 -0
  134. package/md_cg/test_security_audit_v21.py +250 -0
  135. package/md_cg/test_semantic_canonical.py +255 -241
  136. package/md_cg/test_session_isolation.py +168 -0
  137. package/md_cg/test_snapshot_autoclose.py +187 -0
  138. package/md_cg/test_tail_watermark_race.py +208 -0
  139. package/md_cg/test_tenant_env_override_warn.py +139 -0
  140. package/md_cg/test_tenant_registry_corrupt_warn.py +151 -0
  141. package/md_cg/test_v14_fixes.py +415 -397
  142. package/md_cg/test_verify_dirty_reconcile.py +157 -0
  143. package/md_cg/theory.py +276 -273
  144. package/md_cg/tokens.py +734 -677
  145. package/md_cg/units.py +3 -2
  146. package/md_cg/vision_evidence.py +4 -3
  147. package/md_cg/whitebox_kb/wisdom/code_solidified.json +6195 -6195
  148. package/md_cg/whitebox_kb/wisdom/multilang_ir.py +128 -124
  149. package/md_cg/writepipe.py +554 -550
  150. package/package.json +11 -2
  151. package/src/bridge.ts +434 -401
  152. package/src/cli.ts +65 -0
  153. package/src/index.ts +526 -518
  154. package/src/init.ts +347 -0
  155. package/src/lib/roleplay_web.ts +1019 -932
  156. package/src/lib/token_store.ts +202 -192
@@ -0,0 +1,160 @@
1
+ # -*- coding: utf-8 -*-
2
+ """test_p1x_ref_root.py · P1-X 回归守卫:op=ref / index_code / index_doc 的根白名单
3
+
4
+ 安全缺陷(两份独立报告合并,severity=high):op=ref 是越权任意文件读原语——
5
+ probe_ref 以调用方自报的 root 与 ref.path 直接 os.path.join 后 open 全文回读
6
+ (refindex.py),无租户根校验、无 check_path_root、无密级闸。三形态全部漏:
7
+
8
+ ① 自报 root 指向记忆根外(victim/secret.txt 全文进模型上下文);
9
+ ② ref.path 绝对路径(os.path.join 遇绝对路径丢弃 root);
10
+ ③ '../' 上跳。
11
+ 同族缺口:index_code / index_doc 的 path 同样不走 check_path_root
12
+ (P1-4 只覆盖 ingest/export/link/mdcg_ingest)。
13
+
14
+ 修复:_ref_call 的 read/get 分支按「最终将打开的完整路径」挂
15
+ check_path_root(MDCG_INGEST_ROOT);index_code/index_doc 对模型可控的显式
16
+ path 挂同闸。语义与 P1-4 先例一致:env 未设置 = 放开(部署开关,默认行为
17
+ 不变);设置了 = realpath 落根内否则拒(fail-closed,上跳与绝对路径在
18
+ realpath 归一后自然涵盖)。
19
+
20
+ 本文件钉死:三形态 + 索引越界必须拒绝;白名单内索引/回读不误伤;
21
+ env 未设保持放开语义;ingest 先例闸与 guest op 闸不回归。
22
+ 运行:python -m md_cg.test_p1x_ref_root
23
+ """
24
+ from __future__ import annotations
25
+
26
+ import os
27
+ import shutil
28
+ import sys
29
+ import tempfile
30
+
31
+ from . import corpus, tokens
32
+ from .mdcg import MdCG
33
+ from .mcp_server import call_tool
34
+ from .security import AccessDenied
35
+
36
+ PASS = FAIL = 0
37
+ FAILS = []
38
+
39
+ SECRET_TEXT = ("AKIAIOSFODNN7EXAMPLE-DUMMY\n" # 哑数据,非真实凭据
40
+ "secret-line-2=dummy\nsecret-line-3=dummy\n")
41
+ ALPHA_TEXT = '""" 供能注释。"""\n\ndef compute(mass):\n return mass\n'
42
+
43
+
44
+ def check(name, cond, detail=""):
45
+ global PASS, FAIL
46
+ if cond:
47
+ PASS += 1
48
+ print(f" [PASS] {name}" + (f" · {detail}" if detail else ""))
49
+ else:
50
+ FAIL += 1
51
+ FAILS.append(name)
52
+ print(f" [FAIL] {name} · {detail}")
53
+
54
+
55
+ def denied(fn):
56
+ """断言 fn 被拒:抛 PermissionError,或返回 ok=False。"""
57
+ try:
58
+ out = fn()
59
+ return out.get("ok") is False, f"returned ok={out.get('ok')}"
60
+ except PermissionError as exc:
61
+ return True, f"PermissionError({str(exc)[:40]}…)"
62
+
63
+
64
+ def main():
65
+ print("=" * 68)
66
+ print("md_cg P1-X 验收 · op=ref/index_code/index_doc 根白名单(三形态防越权读)")
67
+ print("=" * 68)
68
+
69
+ tmp = tempfile.mkdtemp(prefix="mdcg_p1x_")
70
+ memroot = os.path.join(tmp, "memroot") # 认知图根(服务器侧)
71
+ allow = os.path.join(tmp, "allow") # 部署白名单内的代码目录
72
+ victim = os.path.join(tmp, "victim") # 白名单外(宿主敏感区模拟)
73
+ os.makedirs(allow)
74
+ os.makedirs(victim)
75
+ with open(os.path.join(victim, "secret.txt"), "w", encoding="utf-8") as f:
76
+ f.write(SECRET_TEXT)
77
+ with open(os.path.join(allow, "alpha.py"), "w", encoding="utf-8") as f:
78
+ f.write(ALPHA_TEXT)
79
+
80
+ env = "MDCG_INGEST_ROOT"
81
+ old = os.environ.get(env)
82
+ os.environ[env] = allow # 部署声明:只有 allow/ 可读入
83
+
84
+ corpus.reset_root(memroot)
85
+ cg = MdCG(memroot)
86
+ full = {"lineno": 1, "end": 99} # 无 hash → 不做漂移校验直读
87
+
88
+ try:
89
+ print("\n【1】三形态越权读必须被拒(fail-closed)")
90
+ ok, d = denied(lambda: call_tool(cg, "cg", {
91
+ "op": "ref", "ref": dict(path="secret.txt", root=victim, **full)}))
92
+ check("①a 自报 root 越界被拒(secret 不进上下文)", ok, d)
93
+ ok, d = denied(lambda: call_tool(cg, "cg", {
94
+ "op": "ref", "root": allow,
95
+ "ref": dict(path=os.path.join(victim, "secret.txt"), **full)}))
96
+ check("①b ref.path 绝对路径被拒(join 丢弃 root 也拦)", ok, d)
97
+ ok, d = denied(lambda: call_tool(cg, "cg", {
98
+ "op": "ref", "root": allow,
99
+ "ref": dict(path=os.path.join("..", "victim", "secret.txt"),
100
+ **full)}))
101
+ check("①c '../' 上跳被拒", ok, d)
102
+
103
+ print("\n【2】同族:index_code / index_doc 越界 path 必须被拒")
104
+ ok, d = denied(lambda: call_tool(cg, "cg", {"op": "index_code",
105
+ "path": victim}))
106
+ check("②a index_code 越界 path 被拒", ok, d)
107
+ ok, d = denied(lambda: call_tool(cg, "cg", {"op": "index_doc",
108
+ "path": victim}))
109
+ check("②b index_doc 越界 path 被拒", ok, d)
110
+
111
+ print("\n【3】白名单内不误伤")
112
+ out = call_tool(cg, "cg", {"op": "index_code", "path": allow})
113
+ nid = (out.get("ids") or [None])[0]
114
+ rr = call_tool(cg, "cg", {"op": "ref", "node_id": nid}) if nid \
115
+ else {"ok": False, "error": "no ids"}
116
+ check("③a 白名单内索引 + node 回读正常",
117
+ out.get("ok") and out.get("indexed", 0) >= 1
118
+ and rr.get("ok") is True and "compute" in (rr.get("text") or ""),
119
+ f"indexed={out.get('indexed')} ref_ok={rr.get('ok')}")
120
+ rr = call_tool(cg, "cg", {"op": "ref", "root": allow,
121
+ "ref": dict(path="alpha.py", lineno=1, end=2)})
122
+ check("③b 白名单内 inline ref 回读正常", rr.get("ok") is True,
123
+ f"ok={rr.get('ok')} err={rr.get('error')}")
124
+
125
+ print("\n【4】先例与开关语义不回归")
126
+ ok, d = denied(lambda: call_tool(cg, "cg", {
127
+ "op": "ingest", "action": "file",
128
+ "path": os.path.join(victim, "secret.txt")}))
129
+ check("④a ingest 越界仍被 P1-4 拦(先例闸不回归)", ok, d)
130
+ os.environ.pop(env, None)
131
+ rr = call_tool(cg, "cg", {
132
+ "op": "ref", "ref": dict(path="secret.txt", root=victim, **full)})
133
+ check("④b env 未设 = 部署开关放开(默认行为不变)",
134
+ rr.get("ok") is True
135
+ and "AKIAIOSFODNN7EXAMPLE" in (rr.get("text") or ""),
136
+ f"ok={rr.get('ok')}")
137
+ try:
138
+ tokens.Principal(role="guest", ops_allow=("read",), theory_ok=True
139
+ ).require_op("ref")
140
+ ok, d = False, "guest 未被拒"
141
+ except AccessDenied:
142
+ ok, d = True, "AccessDenied"
143
+ check("④c guest 令牌 op=ref 仍被 require_op 拒", ok, d)
144
+ finally:
145
+ if old is None:
146
+ os.environ.pop(env, None)
147
+ else:
148
+ os.environ[env] = old
149
+ corpus.reset_root(memroot) # 收尾:指向本次临时根
150
+ shutil.rmtree(tmp, ignore_errors=True)
151
+
152
+ print("\n" + "=" * 68)
153
+ print(f"P1-X 根白名单守卫: {PASS}/{PASS + FAIL} 通过")
154
+ if FAILS:
155
+ print("未过:" + ";".join(FAILS))
156
+ return 0 if FAIL == 0 else 1
157
+
158
+
159
+ if __name__ == "__main__":
160
+ sys.exit(main())