@furongjun1999/dsh-memory 0.7.1 → 0.7.3
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.
- package/README.md +58 -48
- package/codebuddy/CODEBUDDY.md +9 -9
- package/docs/README.md +148 -144
- package/docs/discipline/harnesses.yaml +16 -8
- package/docs/discipline/templates/zcode-user.md.tmpl +49 -0
- package/docs/eval/AGI/344/270/203/347/273/264/350/257/204/345/210/206/346/212/245/345/221/212_/345/205/255/345/256/266/350/256/260/345/277/206/347/263/273/347/273/237/345/220/214/345/260/272/345/256/236/346/265/213_v3.1.md +340 -0
- package/docs/eval/N225_/347/264/242/345/274/225/346/227/245/345/277/227/351/235/236/345/257/271/350/261/241/350/243/205/350/275/275/351/235/242/347/261/273/345/236/213/351/227/270_v1.0.md +2 -2
- package/docs/eval/cons200_/345/206/262/347/252/201/346/243/200/346/265/213/351/200/211/351/235/242_/345/256/236/346/226/275/350/256/260/345/275/225_v1.0.md +1 -1
- package/docs/eval/cons200_/345/206/262/347/252/201/346/243/200/346/265/213/351/200/211/351/235/242_/345/256/236/346/226/275/350/256/260/345/275/225_v1.1.md +1 -1
- package/docs/eval/issue43_/351/273/230/350/256/244/347/255/226/347/225/245/344/270/216/351/224/256/347/261/273/345/236/213/351/227/270_v1.1.md +1 -1
- package/docs/eval/issue43_/351/273/230/350/256/244/347/255/226/347/225/245/345/212/240/350/275/275/344/270/216/345/207/255/346/215/256/346/230/216/346/226/207/351/230/237/345/210/227_v1.0.md +2 -2
- package/docs/eval/issue50_/345/205/203/346/225/260/346/215/256/351/200/217/344/274/240/344/270/216/345/205/234/345/272/225_/344/277/256/345/244/215/350/256/260/345/275/225_v1.0.md +5 -5
- package/docs/eval/issue50_/345/215/212/351/207/215/345/244/215/345/276/205/345/256/232/345/244/215/346/240/270_/344/277/256/345/244/215/350/256/260/345/275/225_v1.0.md +9 -9
- package/docs/eval/issue50_/345/276/205/345/256/232/345/244/215/346/240/270/345/205/245/351/230/237_/344/277/256/345/244/215/350/256/260/345/275/225_v1.0.md +4 -4
- package/docs/eval/issue50_/351/207/215/350/246/201/345/272/246/345/220/214/346/272/220/344/270/216/344/277/235/346/212/244/350/257/255/344/271/211_/344/277/256/345/244/215/350/256/260/345/275/225_v1.0.md +1 -1
- package/docs/eval/issue51_/344/270/200/351/224/256/345/256/211/350/243/205/345/244/261/350/264/245_/345/275/222/345/261/236/345/210/244/345/256/232_v1.0.md +1 -1
- package/docs/eval/issue52_/346/235/241/344/273/266/345/205/210/350/241/214/344/270/216/346/210/252/346/226/255/345/217/257/350/247/202/346/265/213_/344/277/256/345/244/215/350/256/260/345/275/225_v1.0.md +3 -3
- package/docs/eval//344/270/211/346/241/243/350/207/252/346/262/273_/346/255/245/351/252/244/342/221/242/345/217/230/346/233/264/345/215/225/344/270/216/345/233/236/346/273/232/345/216/237/350/257/255_/350/220/275/347/240/201/350/256/260/345/275/225_v1.0.md +3 -3
- package/docs/eval//344/270/211/346/241/243/350/207/252/346/262/273_/346/255/245/351/252/244/342/221/243/345/207/206/345/205/245/350/257/273/346/225/260_/350/220/275/347/240/201/350/256/260/345/275/225_v1.0.md +7 -7
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/270/200/346/211/271_/346/216/245/347/272/277/344/270/216/347/255/211/344/273/267/345/217/230/346/215/242_v1.0.md +2 -2
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/270/211/346/211/271_/351/227/250/347/246/201/350/275/254/346/255/243/344/270/216/350/260/203/345/272/246/346/255/242/350/241/200/344/270/216/351/227/250/346/216/247/346/224/266/345/217/243_v1.0.md +1 -1
- package/docs/eval//344/274/230/345/214/226/347/254/254/344/272/214/346/211/271_/344/276/235/350/265/226/351/200/217/344/274/240/344/270/216/345/257/271/346/213/215/345/217/243/345/276/204/344/270/216/350/264/237/347/274/223/345/255/230_v1.0.md +7 -7
- package/docs/eval//345/207/272/350/264/247/351/235/242/345/206/222/347/203/237_/350/277/233/350/264/247/351/227/250/347/246/201_v1.0.md +10 -10
- package/docs/eval//345/217/221/345/270/20307_/345/244/226/351/203/250/346/212/245/345/221/212/345/233/233/346/211/271/344/277/256/345/244/215/344/270/216/346/217/222/344/273/266/351/235/242/345/212/240/345/233/272_v1.0.md +4 -0
- package/docs/eval//345/217/221/345/270/20308_/350/207/252/350/277/255/344/273/243/344/270/216/347/235/241/347/234/240_/345/233/276/346/243/200/347/264/242/350/267/257/344/270/216/346/235/203/351/207/215_v1.0.md +1 -1
- package/docs/eval//345/217/221/345/270/20309_/346/243/200/347/264/242/351/235/242/344/270/211/346/211/271/346/224/266/345/217/243_v1.0.md +1 -1
- package/docs/eval//345/217/221/345/270/20310_/350/257/273/351/235/242/346/215/237/345/235/217UTF8/345/256/266/346/227/217/346/224/266/345/217/243_v1.0.md +71 -0
- package/docs/eval//345/217/221/345/270/20311_/345/244/226/346/212/245/345/205/255/350/277/236/344/277/256/344/270/216/344/270/226/347/225/214/346/250/241/345/236/213/345/272/225/345/272/247_v1.0.md +91 -0
- package/docs/eval//345/275/222/344/270/200/345/261/202/347/274/272/347/234/201/347/277/273/345/205/263_/344/277/256/345/244/215/350/256/260/345/275/225_v1.0.md +2 -2
- package/docs/eval//347/224/250/346/210/267/350/243/201/345/206/263/345/244/204/347/275/256_/347/254/254/344/270/200/346/211/271_v1.0.md +195 -0
- package/docs/eval//347/224/250/346/210/267/350/243/201/345/206/263/345/244/204/347/275/256_/347/254/254/344/272/214/346/211/271B6_/346/234/254/346/234/272/350/267/257/345/276/204/347/233/270/345/257/271/345/214/226_v1.0.md +78 -0
- 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 +1 -1
- 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 +3 -3
- package/docs/eval//347/254/2543/345/261/202stg/347/273/223/346/236/204/347/264/242/345/274/225_/345/256/236/346/226/275/350/256/260/345/275/225_v1.0.md +1 -1
- package/docs/eval//347/274/226/347/240/201/351/235/242/345/211/215/347/275/256_/345/205/245/345/217/243/350/207/252/344/277/235/350/257/201UTF8/344/270/216/346/226/207/346/234/254open/345/256/210/345/215/253_v1.0.md +1 -1
- 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_v26.md +196 -0
- 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_v27.md +259 -0
- 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_v28.md +217 -0
- 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_v29.md +270 -0
- 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_v30.md +231 -0
- 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_v31.md +281 -0
- package/docs/hive//345/256/211/345/205/250/345/256/241/350/256/241/345/256/236/351/224/232_v0.1.md +1 -1
- package/docs/hive//350/234/202/345/267/242M6_ingest/345/256/236/346/226/275/350/256/241/345/210/222_v0.1.md +1 -1
- 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 +1 -1
- package/docs/hive//350/234/202/345/267/242/350/256/276/350/256/241_/347/220/206/350/256/272/345/257/271/351/275/220_v0.1.md +17 -17
- package/docs/hive//350/234/202/345/267/242/350/277/255/344/273/243_/345/256/217/350/247/202/344/270/216/347/276/244/344/275/223/350/260/203/345/272/246_v0.1.md +1 -1
- package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +2 -2
- 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 +42 -41
- package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +29 -8
- package/docs/mdcg//347/235/241/347/234/240/345/221/250/346/234/237_/350/277/220/347/273/264/345/211/215/346/217/220/344/270/216/347/273/264/346/212/244/346/214/207/345/215/227_v1.0.md +71 -1
- package/docs/plans//345/205/250/344/270/255/346/226/207/347/274/226/347/240/201/344/270/216/350/234/202/345/267/242/344/273/273/345/212/241/346/240/207/350/257/206/345/245/221/347/272/246_v2.0.md +1 -1
- package/docs/plans//345/244/232/344/270/273/344/275/223/344/270/226/347/225/214/346/250/241/345/236/213_/345/257/271/351/275/220/350/257/204/344/274/260/344/270/216/350/220/275/345/234/260/350/256/276/350/256/241_v0.1.md +141 -0
- package/docs/plans//347/235/241/347/234/240/344/270/216/350/207/252/350/277/255/344/273/243_/345/212/237/350/203/275/344/274/230/345/214/226/350/256/276/350/256/241_v0.4.md +2 -2
- package/docs/plans//350/257/255/344/271/211/346/227/266/347/251/272/345/233/276/350/241/245/345/205/250_/344/270/226/347/225/214/346/250/241/345/236/213/345/212/237/350/203/275/347/253/257_/350/256/276/350/256/241_v0.1.md +107 -0
- 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 +9 -8
- package/docs//347/247/244_/350/256/260/345/277/206/347/263/273/347/273/237/350/257/204/346/265/213/350/247/204/350/214/203_v2.1.md +225 -0
- package/dsh/cordis-patch-profile-web.example.yml +2 -2
- package/lib/bridge.js +9 -0
- package/lib/hooks.d.ts +8 -1
- package/lib/hooks.js +94 -32
- package/lib/lib/hook_audit.d.ts +55 -0
- package/lib/lib/hook_audit.js +208 -0
- package/lib/lib/mutual.js +5 -1
- package/lib/lib/roleplay_web.js +17 -2
- package/md_cg/auditview.py +248 -0
- package/md_cg/bench6_arms.py +10 -6
- package/md_cg/bench_e2e_judge.py +4 -2
- package/md_cg/branches.py +29 -3
- package/md_cg/census.py +2 -1
- package/md_cg/consistency.py +38 -13
- package/md_cg/datapath.py +38 -11
- package/md_cg/forgetting.py +15 -2
- package/md_cg/freshness.py +32 -11
- package/md_cg/ghostref.py +130 -0
- package/md_cg/judgment_manifest.py +7 -0
- package/md_cg/mcp_server.py +58 -1
- package/md_cg/mdcg.py +4923 -4764
- package/md_cg/mdcos.py +40 -15
- package/md_cg/mreview/locate.py +1 -1
- package/md_cg/nodefile.py +77 -13
- package/md_cg/readcache.py +29 -4
- package/md_cg/rollback.py +12 -3
- package/md_cg/routing.py +10 -1
- package/md_cg/selfreport.py +12 -3
- package/md_cg/sleep.py +129 -13
- package/md_cg/sources.py +1 -1
- package/md_cg/state_events.py +131 -0
- package/md_cg/sustain.py +1436 -1436
- package/md_cg/test_auditview.py +277 -0
- package/md_cg/test_autonomy_modes.py +2 -1
- package/md_cg/test_boot_openblas_guard.py +197 -0
- package/md_cg/test_ccg_form_parity.py +95 -4
- package/md_cg/test_cons200_scan_selection.py +4 -2
- package/md_cg/test_corrupt_utf8_read_surfaces.py +451 -0
- package/md_cg/test_datapath_device_name.py +62 -3
- package/md_cg/test_generation_guard.py +20 -11
- package/md_cg/test_ghostref.py +182 -0
- package/md_cg/test_health_corrupt_utf8.py +37 -0
- package/md_cg/test_index_crossprocess_reload.py +39 -24
- package/md_cg/test_interop.py +1 -1
- package/md_cg/test_issue52_scan_condition_first.py +1 -1
- package/md_cg/test_issue53_cipher_health_hash.py +385 -0
- package/md_cg/test_lock.py +16 -7
- package/md_cg/test_m3_h9_semantic_guard.py +1 -1
- package/md_cg/test_n230_dirty_replay.py +375 -375
- package/md_cg/test_n238_body_text_parity.py +156 -0
- package/md_cg/test_n276_probe_hoist.py +199 -0
- package/md_cg/test_p4_freshness.py +95 -1
- package/md_cg/test_policy_required_ccg.py +3 -1
- package/md_cg/test_readcache_prodpath.py +66 -0
- package/md_cg/test_sleep.py +58 -1
- package/md_cg/test_sleep_p1.py +218 -2
- package/md_cg/test_state_events.py +178 -0
- package/md_cg/test_time_core_lint.py +8 -1
- package/md_cg/test_writepipe.py +8 -5
- package/md_cg/tokens.py +11 -2
- package/md_cg/writepipe.py +76 -0
- package/package.json +2 -2
- package/skills/plugin.json +1 -1
- package/src/bridge.ts +9 -0
- package/src/hooks.ts +576 -517
- package/src/lib/hook_audit.ts +243 -0
- package/src/lib/mutual.ts +5 -1
- package/src/lib/roleplay_web.ts +17 -2
- package/zcode/AGENTS.md +9 -9
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""test_ghostref · 幽灵引用检查器(A2):短语层标记 + id 层降级告警(不拒收)。
|
|
3
|
+
|
|
4
|
+
多主体世界模型对齐 v0.1 §2 L1「转引不得升级」的行为守卫。
|
|
5
|
+
运行:python -m md_cg.test_ghostref
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import os
|
|
10
|
+
import tempfile
|
|
11
|
+
import time
|
|
12
|
+
|
|
13
|
+
from . import branches, ghostref, nodefile
|
|
14
|
+
from .mdcos import MdCGOS
|
|
15
|
+
from .writepipe import default_pipeline
|
|
16
|
+
|
|
17
|
+
_ok = 0
|
|
18
|
+
_fail = []
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def check(name, cond, detail=""):
|
|
22
|
+
global _ok
|
|
23
|
+
if cond:
|
|
24
|
+
_ok += 1
|
|
25
|
+
print("[ok] " + name)
|
|
26
|
+
else:
|
|
27
|
+
_fail.append(name)
|
|
28
|
+
print("[FAIL] %s · %s" % (name, str(detail)[:240]))
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
H = ("# 功能名:幽灵引用守卫\n# 生效条件:测试环境\n# 子功能:无\n"
|
|
32
|
+
"# 执行:无\n# 验证方式:test\n# 不适用条件:无\n")
|
|
33
|
+
URF = nodefile.UNCERTAIN_REFS_FIELD
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def main():
|
|
37
|
+
tmp = tempfile.mkdtemp(prefix="mdcg_ghost_test_")
|
|
38
|
+
cg = MdCGOS(os.path.join(tmp, "root"))
|
|
39
|
+
pipe = default_pipeline()
|
|
40
|
+
|
|
41
|
+
def W(nid, body, **kw):
|
|
42
|
+
a = {"op": "write", "node_id": nid, "content": H + body + "\n",
|
|
43
|
+
"layer": "knowledge", "content_kind": "text",
|
|
44
|
+
"verification_basis": "test"}
|
|
45
|
+
a.update(kw)
|
|
46
|
+
return pipe.execute(cg, a)
|
|
47
|
+
|
|
48
|
+
def FM(nid):
|
|
49
|
+
return ((cg.get(nid) or {}).get("frontmatter")) or {}
|
|
50
|
+
|
|
51
|
+
# ---- 1. 短语层:无可解析出处 ⇒ 标记;**不拒收** ----
|
|
52
|
+
out1 = W("ghp_one", "可以允许你在帐篷里点那根你上次买的香薰蜡烛。")
|
|
53
|
+
check("T1a 幽灵回指仍落盘(不拒收)", out1.get("committed") is True,
|
|
54
|
+
{k: out1.get(k) for k in ("ok", "committed", "moved_to")})
|
|
55
|
+
_refs1 = FM("ghp_one").get(URF) or []
|
|
56
|
+
check("T1b 短语标记落 fm(上次买)", "上次买" in _refs1, _refs1)
|
|
57
|
+
check("T1c 出口带 ghost_refs 告警",
|
|
58
|
+
bool(out1.get("ghost_refs")) and "上次买" in out1["ghost_refs"],
|
|
59
|
+
out1.get("ghost_refs"))
|
|
60
|
+
|
|
61
|
+
# ---- 2. 有出处(句内含库内 id)⇒ 不标记 ----
|
|
62
|
+
W("base_node", "集市采购的凭证记录。")
|
|
63
|
+
out2 = W("ghp_two", "上次说的那件事,见 base_node 的记载。")
|
|
64
|
+
check("T2a 有出处的回指不落标记",
|
|
65
|
+
URF not in FM("ghp_two"), FM("ghp_two").get(URF))
|
|
66
|
+
check("T2b 有出处的回指建 reference 边",
|
|
67
|
+
any(e.get("target") == "base_node" for e in (FM("ghp_two").get("edges") or [])),
|
|
68
|
+
FM("ghp_two").get("edges"))
|
|
69
|
+
check("T2c 出口无 ghost_refs", not out2.get("ghost_refs"), out2.get("ghost_refs"))
|
|
70
|
+
|
|
71
|
+
# ---- 3. 无回指短语 ⇒ 不标记(对照)----
|
|
72
|
+
out3 = W("ghp_three", "集市购物,周末进行。")
|
|
73
|
+
check("T3a 无短语不落标记", URF not in FM("ghp_three"), FM("ghp_three").get(URF))
|
|
74
|
+
# 2026-10-05 复核实证:T3 在「写入被拒」时会假通过(无标记≠已落盘)——
|
|
75
|
+
# 补 committed 断言把「对照场景确实落盘」钉住。
|
|
76
|
+
check("T3b 对照场景确实落盘", out3.get("committed") is True,
|
|
77
|
+
out3.get("committed"))
|
|
78
|
+
|
|
79
|
+
# ---- 4. 幽灵 id(句内 id 形态但不在库)⇒ 无出处 ⇒ 标记 ----
|
|
80
|
+
W("ghp_four", "参照 ghost_absent 那条记载,明明讲过。")
|
|
81
|
+
_refs4 = FM("ghp_four").get(URF) or []
|
|
82
|
+
check("T4a 幽灵 id 句仍标记(明明讲过)", "明明讲过" in _refs4, _refs4)
|
|
83
|
+
check("T4b 幽灵 id 不建边", not (FM("ghp_four").get("edges") or []),
|
|
84
|
+
FM("ghp_four").get("edges"))
|
|
85
|
+
|
|
86
|
+
# ---- 5. id 层:目标晚于自身 ⇒ 降级告警(不拒收)----
|
|
87
|
+
W("late_target", "晚出现的凭证节点。")
|
|
88
|
+
out5 = W("late_src", "依据见 late_target 记载。",
|
|
89
|
+
valid_from=time.time() - 100000)
|
|
90
|
+
check("T5a 目标晚于自身仍落盘(不拒收)", out5.get("committed") is True,
|
|
91
|
+
out5.get("committed"))
|
|
92
|
+
_lr = out5.get("late_refs") or []
|
|
93
|
+
check("T5b 降级告警点名目标",
|
|
94
|
+
len(_lr) == 1 and _lr[0].get("target") == "late_target", _lr)
|
|
95
|
+
|
|
96
|
+
# ---- 6. 正常时序 ⇒ 无告警(对照)----
|
|
97
|
+
out6 = W("ok_src", "依据见 late_target 记载。",
|
|
98
|
+
valid_from=time.time() + 100)
|
|
99
|
+
check("T6a 正常时序无告警", not out6.get("late_refs"), out6.get("late_refs"))
|
|
100
|
+
check("T6b 对照场景确实落盘", out6.get("committed") is True,
|
|
101
|
+
out6.get("committed"))
|
|
102
|
+
|
|
103
|
+
# ---- 7. opt-out(ghostref=False)⇒ 不标记 ----
|
|
104
|
+
out7 = W("ghp_opt", "上次说的事。", ghostref=False)
|
|
105
|
+
check("T7a opt-out 仍落盘", out7.get("committed") is True, out7.get("committed"))
|
|
106
|
+
check("T7b opt-out 不落标记", URF not in FM("ghp_opt"),
|
|
107
|
+
FM("ghp_opt").get(URF))
|
|
108
|
+
|
|
109
|
+
# ---- 8. add 层:显式落键 / 覆写不继承 / 非法拒(直调,不经写链)----
|
|
110
|
+
cg.add("ghp_eight", H + "上次说的那件事。\n", layer="knowledge",
|
|
111
|
+
verification_basis="test", uncertain_refs=["上次说", "之前说"])
|
|
112
|
+
check("T8a 显式落键", FM("ghp_eight").get(URF) == ["上次说", "之前说"],
|
|
113
|
+
FM("ghp_eight").get(URF))
|
|
114
|
+
cg.add("ghp_eight", H + "改写后的干净正文。\n", layer="knowledge",
|
|
115
|
+
verification_basis="test")
|
|
116
|
+
check("T8b 覆写不继承(正文属性重算)", URF not in FM("ghp_eight"),
|
|
117
|
+
FM("ghp_eight").get(URF))
|
|
118
|
+
try:
|
|
119
|
+
cg.add("ghp_bad", H + "正文。\n", layer="knowledge",
|
|
120
|
+
verification_basis="test", uncertain_refs="上次的")
|
|
121
|
+
check("T8c 非法类型拒绝", False, "未抛 ValueError")
|
|
122
|
+
except ValueError:
|
|
123
|
+
check("T8c 非法类型拒绝", True)
|
|
124
|
+
|
|
125
|
+
# ---- 9. fork 副本携带标记 ----
|
|
126
|
+
r9 = branches.fork(cg, ["ghp_one"], branch_id="br_ghost")
|
|
127
|
+
_bid = (r9.get("forked") or [{}])[0].get("to")
|
|
128
|
+
check("T9a fork 成功", bool(r9.get("ok")) and bool(_bid), r9)
|
|
129
|
+
check("T9b 副本携带标记", (_bid and FM(_bid).get(URF) == FM("ghp_one").get(URF)),
|
|
130
|
+
(_bid, FM(_bid).get(URF) if _bid else None))
|
|
131
|
+
|
|
132
|
+
# ---- 11. rewrite 按新正文重算标记(复核 yellow-1 修)----
|
|
133
|
+
# 副本 ghp_one@br_ghost 有标记 ["上次买"](T1/ fork 携带):
|
|
134
|
+
# 改成干净正文 → 标记消失;改回幽灵正文 → 标记出现(双向,非「清空」)。
|
|
135
|
+
rr1 = branches.rewrite(cg, _bid, H + "改写为干净正文。\n")
|
|
136
|
+
check("T11a rewrite 成功", rr1.get("ok") is True, rr1)
|
|
137
|
+
check("T11b rewrite 干净正文 → 标记重算消失", URF not in FM(_bid),
|
|
138
|
+
FM(_bid).get(URF))
|
|
139
|
+
rr2 = branches.rewrite(cg, _bid, H + "之前说的那件事。\n")
|
|
140
|
+
check("T11c rewrite 幽灵正文 → 标记重算出现",
|
|
141
|
+
"之前说" in (FM(_bid).get(URF) or []), FM(_bid).get(URF))
|
|
142
|
+
|
|
143
|
+
# ---- 12. merge 回主支按分支正文重算(复核 yellow-2① 修)----
|
|
144
|
+
# 主支幽灵正文 → fork → rewrite 分支为干净 → merge 回主支 → 主支标记消失。
|
|
145
|
+
W("ghp_merge", "明明讲过的那件事。")
|
|
146
|
+
check("T12a 主支初始有标记", "明明讲过" in (FM("ghp_merge").get(URF) or []),
|
|
147
|
+
FM("ghp_merge").get(URF))
|
|
148
|
+
r12 = branches.fork(cg, ["ghp_merge"], branch_id="br_mg")
|
|
149
|
+
_bid12 = (r12.get("forked") or [{}])[0].get("to")
|
|
150
|
+
branches.rewrite(cg, _bid12, H + "干净正文(无回指)。\n")
|
|
151
|
+
rm = branches.merge(cg, "br_mg")
|
|
152
|
+
check("T12b merge 成功", rm.get("ok") is True, rm)
|
|
153
|
+
check("T12c 主支标记按分支正文重算(消失)", URF not in FM("ghp_merge"),
|
|
154
|
+
FM("ghp_merge").get(URF))
|
|
155
|
+
# 反方向(2026-10-05 自证补):干净主支 → 分支改幽灵 → merge 回写 ⇒ 主支
|
|
156
|
+
# 标记应**出现**——「消失」方向抓「携带旧值」,「出现」方向抓「置空不重算」。
|
|
157
|
+
W("ghp_merge2", "干净正文示例。")
|
|
158
|
+
r13 = branches.fork(cg, ["ghp_merge2"], branch_id="br_mg2")
|
|
159
|
+
_bid13 = (r13.get("forked") or [{}])[0].get("to")
|
|
160
|
+
branches.rewrite(cg, _bid13, H + "上次说的那件事。\n")
|
|
161
|
+
branches.merge(cg, "br_mg2")
|
|
162
|
+
check("T12d 主支标记按分支正文重算(出现)",
|
|
163
|
+
"上次说" in (FM("ghp_merge2").get(URF) or []),
|
|
164
|
+
FM("ghp_merge2").get(URF))
|
|
165
|
+
|
|
166
|
+
# ---- 10. 纯函数级:短语去重保序 + late_targets 边界 ----
|
|
167
|
+
# 「上次说的那件」只命中「上次说」——「上次的」要求连续子串(说/的 之间
|
|
168
|
+
# 不跳字);命中去重后跨句保序。
|
|
169
|
+
_pf = ghostref.find_ghost_phrases("上次说的事;上次说的那件;之前说的那批。")
|
|
170
|
+
check("T10a 短语去重保序", _pf == ["上次说", "之前说"], _pf)
|
|
171
|
+
check("T10b late_targets 无 own_from 直接空",
|
|
172
|
+
ghostref.late_targets(cg, ["late_target"], None) == [])
|
|
173
|
+
check("T10c late_targets 非数 own_from 空",
|
|
174
|
+
ghostref.late_targets(cg, ["late_target"], "昨天") == [])
|
|
175
|
+
|
|
176
|
+
print("\ntest_ghostref: %d 通过 / %d 失败" % (_ok, len(_fail)))
|
|
177
|
+
if _fail:
|
|
178
|
+
raise SystemExit(1)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
if __name__ == "__main__":
|
|
182
|
+
main()
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
"""health() skips a damaged UTF-8 node instead of crashing the health endpoint."""
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import shutil
|
|
7
|
+
import tempfile
|
|
8
|
+
|
|
9
|
+
from md_cg.mdcos import MdCGOS
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def main() -> None:
|
|
13
|
+
root = tempfile.mkdtemp(prefix="health_utf8_guard_")
|
|
14
|
+
cg = MdCGOS(root, autoflush=0)
|
|
15
|
+
try:
|
|
16
|
+
cg.add("good", "可读的健康检查节点", tags=["domain:health"])
|
|
17
|
+
cg.add("bad", "待损坏节点", tags=["domain:health"])
|
|
18
|
+
cg.flush()
|
|
19
|
+
bad_path = os.path.join(root, cg.index["nodes"]["bad"]["path"].replace("/", os.sep))
|
|
20
|
+
with open(bad_path, "wb") as fh:
|
|
21
|
+
fh.write(bytes((0xff, 0xfe, 0xfd)))
|
|
22
|
+
|
|
23
|
+
assert cg.get("bad") is None
|
|
24
|
+
results, _meta = cg.search("可读", k=5, include_neg=True)
|
|
25
|
+
assert any(item[0]["id"] == "good" for item in results), results
|
|
26
|
+
health = cg.health()
|
|
27
|
+
assert health["total_nodes"] == 2, health
|
|
28
|
+
assert sum(v["total"] for v in health["ccg_by_layer"].values()) == 1, health
|
|
29
|
+
print("PASS health skips invalid UTF-8 node")
|
|
30
|
+
finally:
|
|
31
|
+
cg.close()
|
|
32
|
+
shutil.rmtree(root, ignore_errors=True)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
if __name__ == "__main__":
|
|
36
|
+
main()
|
|
37
|
+
|
|
@@ -262,30 +262,45 @@ def main():
|
|
|
262
262
|
a4.close()
|
|
263
263
|
|
|
264
264
|
# ---------- ⑥ 性能粗测:无跨进程写入时逐读开销 ----------
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
265
|
+
# 并行豁免 + 3 轮中位数(2026-10-03 外部报告核验新增):
|
|
266
|
+
# · 并行全量下 CPU 争抢使本断言假红(报告机器实测 on 242.0µs / off 35.6µs,
|
|
267
|
+
# 单独跑 3 次 41~42µs 全 PASS——接线态是 syscall 密集面,争抢长尾远重于
|
|
268
|
+
# 空转桩态)⇒ 并行时**明示豁免**(run_tests 经 MDCG_RUN_TESTS_PARALLEL
|
|
269
|
+
# 传信号;串行(--jobs 1,含 CI)照测——语义断言不受本豁免影响);
|
|
270
|
+
# · 串行下采样改 3 轮取中位(抗偶发长尾),阈值口径不变(仍防真回归)。
|
|
271
|
+
_parallel = os.environ.get("MDCG_RUN_TESTS_PARALLEL") == "1"
|
|
272
|
+
if _parallel:
|
|
273
|
+
print("\n【⑥】性能粗测(无跨进程写入,接线态 vs 重载桩空转态)")
|
|
274
|
+
print(" [SKIP] 性能上界断言(并行豁免):CPU 争抢下本断言假红(外部报告"
|
|
275
|
+
"实测 on 242.0µs vs off 35.6µs;单跑 41~42µs)——串行(--jobs 1,含 CI)照测")
|
|
276
|
+
else:
|
|
277
|
+
print("\n【⑥】性能粗测(无跨进程写入,接线态 vs 重载桩空转态;3 轮取中位)")
|
|
278
|
+
N = 300
|
|
279
|
+
a2c = MdCGSecure(root3, principal=_principal())
|
|
280
|
+
|
|
281
|
+
def _probe():
|
|
282
|
+
for _ in range(5):
|
|
283
|
+
a2c.get("own_0")
|
|
284
|
+
t0 = time.perf_counter()
|
|
285
|
+
for _ in range(N):
|
|
286
|
+
a2c.get("own_0")
|
|
287
|
+
return (time.perf_counter() - t0) / N * 1e6
|
|
288
|
+
|
|
289
|
+
on_runs = [_probe() for _ in range(3)]
|
|
290
|
+
orig = a2c._maybe_reload_index
|
|
291
|
+
a2c._maybe_reload_index = lambda: False
|
|
292
|
+
off_runs = [_probe() for _ in range(3)]
|
|
293
|
+
a2c._maybe_reload_index = orig
|
|
294
|
+
a2c.close()
|
|
295
|
+
t_on = sorted(on_runs)[1]
|
|
296
|
+
t_off = sorted(off_runs)[1]
|
|
297
|
+
print(" 接线态 %.1f µs/读(3 轮 %s)· 桩空转态 %.1f µs/读(3 轮 %s)· 增幅 %.1f%%"
|
|
298
|
+
% (t_on, "/".join("%.1f" % v for v in on_runs),
|
|
299
|
+
t_off, "/".join("%.1f" % v for v in off_runs),
|
|
300
|
+
(t_on - t_off) / max(t_off, 1e-9) * 100))
|
|
301
|
+
check("性能上界:接线态(3 轮中位)≤ 桩空转态(3 轮中位)×3 + 30µs(中位抗长尾)",
|
|
302
|
+
t_on <= t_off * 3 + 30.0,
|
|
303
|
+
"on=%.1f off=%.1f" % (t_on, t_off))
|
|
289
304
|
finally:
|
|
290
305
|
for r_ in roots:
|
|
291
306
|
shutil.rmtree(r_, ignore_errors=True)
|
package/md_cg/test_interop.py
CHANGED
|
@@ -62,7 +62,7 @@ def main():
|
|
|
62
62
|
check("3a 合规 verdict 通过门禁", isinstance(v, dict) and v["passed"] == 27)
|
|
63
63
|
for name, bad in [
|
|
64
64
|
("3b 绝对路径拦截",
|
|
65
|
-
{**v, "details": [{"log": r"D:\
|
|
65
|
+
{**v, "details": [{"log": r"D:\secret\path.txt"}]}),
|
|
66
66
|
("3c prompt 字段拦截",
|
|
67
67
|
{**v, "prompt": "你是一个…"}),
|
|
68
68
|
("3d API key 拦截",
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
(c) 截断完全静默(返回体无任何标记)——「读不全」与「读不到」不可区分;
|
|
12
12
|
(d) 被排除集合随索引重排漂移(运行期 dict 追加 vs 重建后 sorted 写盘)。
|
|
13
13
|
三接口 timeline/anchors/consistency 共用 `_scan` 同病;MCP 面 `_stg_call` 不透传
|
|
14
|
-
max_scan(永远默认口径);DSH 侧 hooks.ts:
|
|
14
|
+
max_scan(永远默认口径);DSH 侧 hooks.ts:432 auto-recall 直连 timeline 默认口径。
|
|
15
15
|
|
|
16
16
|
本批修法(设计者裁定 2026-10-03,原文):「遇到更多的检索节点,应该要建立索引,
|
|
17
17
|
明确检索条件,和不适用条件,而不是扩大节点数」⇒ 只落「条件先行 + 截断可观测」
|