@furongjun1999/dsh-memory 0.4.8 → 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.
- package/README.md +54 -26
- package/codebuddy/CODEBUDDY.md +196 -195
- package/codebuddy/README.md +13 -1
- package/codebuddy/mcp.json +9 -0
- 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
- package/docs/README.md +1 -1
- package/docs/discipline/harnesses.yaml +18 -7
- package/docs/discipline/templates/full.md.tmpl +4 -3
- package/docs/experiments/linkref_backfill/candidates_20260917.json +726 -0
- package/docs/experiments/linkref_backfill/candidates_internal_20260917.json +602 -0
- package/docs/experiments/linkref_backfill/candidates_internal_v2.json +603 -0
- package/docs/experiments/linkref_backfill/candidates_secret_20260917.json +884 -0
- package/docs/experiments/linkref_backfill/candidates_secret_v2.json +789 -0
- 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
- 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
- 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
- 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
- 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
- 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
- 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
- package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.5.md +631 -625
- 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
- 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
- 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 +47 -45
- 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.4.md → 206_v0.5.md} +92 -4
- 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
- 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
- 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
- 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 +2 -2
- 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 +3 -3
- 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 +2 -2
- 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 -433
- 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
- package/dsh/README.md +33 -0
- package/dsh/cordis.yml.example +13 -7
- package/dsh/hive-mcp-probe.mjs +94 -0
- package/dsh/hive-mcp.example.yml +62 -0
- package/dsh/update-lingshu.bat +11 -0
- package/dsh/update-lingshu.ps1 +337 -0
- package/lib/hooks.d.ts +3 -0
- package/lib/hooks.js +17 -23
- package/lib/index.d.ts +4 -2
- package/lib/index.js +29 -6
- package/lib/lib/datapath.d.ts +76 -1
- package/lib/lib/datapath.js +199 -13
- package/lib/lib/mdcg_client.d.ts +6 -3
- package/lib/lib/mdcg_client.js +6 -5
- package/lib/lib/mutual.js +4 -4
- package/lib/lib/token_store.js +4 -5
- package/md_cg/audit.py +17 -2
- package/md_cg/autonomy.py +86 -15
- package/md_cg/backfill.py +36 -1
- package/md_cg/backfill_bigdomain.py +34 -0
- package/md_cg/bench6_arms.py +28 -1
- package/md_cg/bench6_common.py +10 -1
- package/md_cg/bench6_competitors.py +6 -1
- package/md_cg/bench_axis_domain.py +9 -1
- package/md_cg/bench_blind_comp.py +7 -1
- package/md_cg/bench_en_atoms_public.py +9 -0
- package/md_cg/bench_governance.py +348 -0
- package/md_cg/bench_lme_zh.py +16 -1
- package/md_cg/bench_locomo.py +2 -1
- package/md_cg/bench_locomo_zh.py +16 -1
- package/md_cg/bench_locomo_zh_public.py +4 -1
- package/md_cg/bench_longmem.py +2 -1
- package/md_cg/bench_membench.py +27 -1
- package/md_cg/bench_p0.py +4 -1
- package/md_cg/bench_progressive.py +13 -1
- package/md_cg/bench_role_views.py +238 -0
- package/md_cg/bench_task_ab.py +8 -1
- package/md_cg/bench_task_ab_llm.py +13 -1
- package/md_cg/bench_unified_en.py +6 -1
- package/md_cg/bench_zh_mad.py +20 -1
- package/md_cg/blindspot_tickets.py +123 -0
- package/md_cg/branches.py +12 -1
- package/md_cg/build_postings.py +73 -0
- package/md_cg/ccgc.py +67 -2
- package/md_cg/census.py +5 -1
- package/md_cg/chain.py +24 -3
- package/md_cg/codeindex.py +134 -17
- package/md_cg/coldverify.py +265 -0
- package/md_cg/comment_gate.py +338 -0
- package/md_cg/cond_compose.py +190 -0
- package/md_cg/cond_facts.py +155 -0
- package/md_cg/cond_template.json +107 -0
- package/md_cg/condition_anchor.py +143 -0
- package/md_cg/conformance.py +69 -4
- package/md_cg/consistency.py +24 -1
- package/md_cg/consolidate.py +53 -2
- package/md_cg/corpus.py +4 -0
- package/md_cg/crosscheck.py +42 -2
- package/md_cg/crypto.py +35 -1
- package/md_cg/d_meta.py +310 -0
- package/md_cg/datapath.py +201 -26
- package/md_cg/docindex.py +122 -1
- package/md_cg/eval_common.py +29 -1
- package/md_cg/evidence.py +27 -1
- package/md_cg/evolution.py +21 -1
- package/md_cg/export.py +11 -1
- package/md_cg/forgetting.py +23 -1
- package/md_cg/fsutil.py +18 -1
- package/md_cg/hotcache.py +214 -0
- package/md_cg/hyperedge.py +251 -0
- package/md_cg/identity.py +18 -1
- package/md_cg/insight.py +17 -1
- package/md_cg/lexicon/build_cedict_en_zh.py +9 -0
- package/md_cg/lexicon/build_standard_en.py +171 -168
- package/md_cg/lexicon/expand_en_zh.py +6 -0
- package/md_cg/lifecycle.py +12 -1
- package/md_cg/linkref.py +281 -0
- package/md_cg/links.py +29 -1
- package/md_cg/mcp_server.py +362 -43
- package/md_cg/md_whitebox.py +53 -1
- package/md_cg/mdcg.py +1003 -27
- package/md_cg/mdcos.py +558 -36
- package/md_cg/metacognition.py +37 -2
- package/md_cg/migrate.py +4 -0
- package/md_cg/migrate_aeis.py +221 -213
- package/md_cg/migrate_roleplay.py +8 -0
- package/md_cg/migrate_wisdom_graph.py +14 -1
- package/md_cg/mreview/__main__.py +3 -0
- package/md_cg/mreview/bundle.py +8 -0
- package/md_cg/mreview/candidates.py +9 -0
- package/md_cg/mreview/govern.py +21 -1
- package/md_cg/mreview/locate.py +34 -0
- package/md_cg/mreview/pipeline.py +29 -1
- package/md_cg/mreview/ruleset.py +16 -1
- package/md_cg/nodefile.py +233 -3
- package/md_cg/pooling.py +23 -1
- package/md_cg/postings.py +298 -0
- package/md_cg/predict.py +89 -9
- package/md_cg/progressive.py +3 -0
- package/md_cg/protect.py +14 -1
- package/md_cg/protocol.py +372 -0
- package/md_cg/provenance.py +262 -0
- package/md_cg/reach.py +453 -0
- package/md_cg/refindex.py +47 -2
- package/md_cg/refine.py +20 -1
- package/md_cg/roleviews.py +89 -0
- package/md_cg/routing.py +76 -0
- package/md_cg/scrub.py +63 -2
- package/md_cg/security.py +26 -1
- package/md_cg/self_state.py +64 -1
- package/md_cg/selfreport.py +151 -0
- package/md_cg/semantic/canonical.py +5 -0
- package/md_cg/semantic/en_normalizer.py +364 -355
- package/md_cg/semantic/zh_en_atoms.py +139 -136
- package/md_cg/signer.py +41 -1
- package/md_cg/sources.py +583 -547
- package/md_cg/statushdr.py +179 -0
- package/md_cg/stg.py +59 -18
- package/md_cg/subgraph.py +23 -0
- package/md_cg/sustain.py +56 -1
- package/md_cg/tasks.py +26 -2
- package/md_cg/test_autonomy.py +26 -0
- package/md_cg/test_bench_governance.py +102 -0
- package/md_cg/test_blindspot_tickets.py +166 -0
- package/md_cg/test_ccgc.py +10 -0
- package/md_cg/test_codeindex.py +338 -0
- package/md_cg/test_comment_gate.py +187 -0
- package/md_cg/test_cond_compose_anchors.py +76 -0
- package/md_cg/test_condition_anchor.py +82 -0
- package/md_cg/test_d_meta.py +412 -0
- package/md_cg/test_datapath_root.py +188 -0
- package/md_cg/test_gain_gate.py +47 -1
- package/md_cg/test_hot_cold.py +187 -0
- package/md_cg/test_hyperedge.py +245 -0
- package/md_cg/test_linkref.py +306 -0
- package/md_cg/test_md_access_parity.py +15 -3
- package/md_cg/test_mr_m1.py +108 -18
- package/md_cg/test_mr_m3.py +8 -1
- package/md_cg/test_p26_refindex.py +49 -20
- package/md_cg/test_p27_docindex.py +236 -2
- package/md_cg/test_p2_mcp.py +1 -1
- package/md_cg/test_p31_insight.py +24 -0
- package/md_cg/test_p44_md_whitebox.py +14 -1
- package/md_cg/test_protocol.py +243 -0
- package/md_cg/test_reach.py +378 -0
- package/md_cg/test_reach_keys.py +201 -0
- package/md_cg/test_reach_meta_exits.py +145 -0
- package/md_cg/test_read_clip.py +8 -4
- package/md_cg/test_retr_s1.py +340 -0
- package/md_cg/test_retr_s1b.py +209 -0
- package/md_cg/test_retr_s3.py +194 -0
- package/md_cg/test_retr_s4.py +163 -0
- package/md_cg/test_retr_s5.py +200 -0
- package/md_cg/test_retr_s6.py +157 -0
- package/md_cg/test_retr_s7.py +385 -0
- package/md_cg/test_retr_s8_time.py +316 -0
- package/md_cg/test_retr_s9_edges.py +286 -0
- package/md_cg/test_retr_s9_entity_ctx.py +175 -0
- package/md_cg/test_review_conformance.py +59 -2
- package/md_cg/test_role_views.py +354 -0
- package/md_cg/test_trust.py +361 -0
- package/md_cg/test_units_poll.py +71 -0
- package/md_cg/test_v14_fixes.py +397 -0
- package/md_cg/test_validity_filter.py +280 -0
- package/md_cg/test_wisdom_md_store.py +7 -3
- package/md_cg/test_writepipe.py +5 -1
- package/md_cg/theory.py +16 -1
- package/md_cg/tokens.py +40 -8
- package/md_cg/tool_face.py +13 -2
- package/md_cg/trust.py +943 -0
- package/md_cg/twophase.py +12 -1
- package/md_cg/units.py +129 -10
- package/md_cg/vision_evidence.py +24 -1
- package/md_cg/weights.py +24 -1
- package/md_cg/whitebox.py +32 -1
- package/md_cg/whitebox_kb/data/verify_cache.json +21210 -365
- package/md_cg/whitebox_kb/data/verify_savings.jsonl +5078 -0
- package/md_cg/whitebox_kb/wisdom/audit_log/chain_heat.json +10 -10
- package/md_cg/whitebox_kb/wisdom/code_compose.py +113 -6
- package/md_cg/whitebox_kb/wisdom/code_solidified.json +1 -1
- package/md_cg/whitebox_kb/wisdom/verifier.py +340 -55
- package/md_cg/whitebox_kb/wisdom/wisdom-book-cloud.db +0 -0
- package/md_cg/writelimit.py +18 -4
- package/md_cg/writepipe.py +178 -7
- package/package.json +2 -2
- package/skills/skills/designer-perspective/scripts/__pycache__/designer.cpython-310.pyc +0 -0
- package/skills/skills/designer-perspective/scripts/designer.py +17 -1
- package/skills/skills/designer-perspective/tests/selftest.py +3 -1
- package/src/hooks.ts +17 -21
- package/src/index.ts +33 -6
- package/src/lib/datapath.ts +211 -13
- package/src/lib/mdcg_client.ts +12 -8
- package/src/lib/mutual.ts +411 -411
- package/src/lib/token_store.ts +4 -5
- package/zcode/AGENTS.md +196 -195
- package/zcode/README.md +4 -0
- package/md_cg/whitebox_kb/wisdom/wisdom-book-cloud.db-shm +0 -0
- package/md_cg/whitebox_kb/wisdom/wisdom-book-cloud.db-wal +0 -0
package/md_cg/predict.py
CHANGED
|
@@ -58,9 +58,34 @@ W_BOUNDARY = 0.20
|
|
|
58
58
|
W_VERIFICATION = 0.25
|
|
59
59
|
W_BALANCE = 0.15
|
|
60
60
|
|
|
61
|
+
# D_meta 第五维(opt-in,方案 §2.3):默认 0 = 不参与 composite、不落键、
|
|
62
|
+
# SORT_KEYS 不扩张(默认返回与四维时代逐字节一致,默认零变更纪律)。
|
|
63
|
+
# 显式启用:PREDICTION_META_DIM=<权重>(>0 才生效)
|
|
64
|
+
# PREDICTION_META_PROXY=<代理名>(缺省 unmodeled_growth;**只取单一
|
|
65
|
+
# 代理**——三代理加权合成违反智能论3.4 DEV-002a)
|
|
66
|
+
# 纪律:导入期读一次环境变量,改值须重载模块;catalog().weights 同步扩张。
|
|
67
|
+
try:
|
|
68
|
+
W_META = float(os.environ.get("PREDICTION_META_DIM", "0") or 0.0)
|
|
69
|
+
except ValueError: # 非法值按关闭处理:默认零变更优先,不炸导入
|
|
70
|
+
W_META = 0.0
|
|
71
|
+
W_META = W_META if W_META > 0 else 0.0
|
|
72
|
+
META_PROXY = os.environ.get("PREDICTION_META_PROXY", "unmodeled_growth")
|
|
73
|
+
|
|
61
74
|
SORT_KEYS = ("composite", "trend", "verification", "boundary", "balance")
|
|
75
|
+
if W_META > 0: # 第五维开启时才扩张排序键(默认零变更)
|
|
76
|
+
SORT_KEYS = SORT_KEYS + ("meta_pressure",)
|
|
62
77
|
LOG_FILE = "_prediction.jsonl"
|
|
63
78
|
|
|
79
|
+
|
|
80
|
+
# 生效条件:不适用(无必需形参与分支),恒返回四维权重的自描述 dict;仅当 W_META>0(PREDICTION_META_DIM 显式启用第五维)时追加 meta_pressure 键;
|
|
81
|
+
def _weights():
|
|
82
|
+
"""自描述权重:默认四维逐字节不变,第五维 opt-in 时同步扩张。"""
|
|
83
|
+
w = {"trend": W_TREND, "boundary": W_BOUNDARY,
|
|
84
|
+
"verification": W_VERIFICATION, "balance": W_BALANCE}
|
|
85
|
+
if W_META > 0:
|
|
86
|
+
w["meta_pressure"] = W_META
|
|
87
|
+
return w
|
|
88
|
+
|
|
64
89
|
# 锚点解析纪律(盲区 → 锚点):推断脚手架与负记忆都不得充当锚点。
|
|
65
90
|
# - `gap_hint`(待补线索)与 `scene`(情景重构产物)是「推断得出的引子/回放」,
|
|
66
91
|
# 本身不构成可起推的事实;尤其 gap_hint 会把盲区描述逐字抄进自己的
|
|
@@ -75,14 +100,17 @@ ANCHOR_SKIP_LAYERS = ("unresolved", "rejected")
|
|
|
75
100
|
|
|
76
101
|
# ---------------------------------------------------------------- 基础
|
|
77
102
|
|
|
103
|
+
# 生效条件:传入 cg 具 index 键且其 'nodes' 为非空映射时返回该映射,否则返回空字典 {};
|
|
78
104
|
def _nodes(cg):
|
|
79
105
|
return ((getattr(cg, "index", None) or {}).get("nodes") or {})
|
|
80
106
|
|
|
81
107
|
|
|
108
|
+
# 生效条件:传入 cg 具 root 属性时返回 root 与模块级常量 LOG_FILE 的路径拼接,缺 root 则以 '.' 拼接;
|
|
82
109
|
def log_path(cg):
|
|
83
110
|
return os.path.join(getattr(cg, "root", "."), LOG_FILE)
|
|
84
111
|
|
|
85
112
|
|
|
113
|
+
# 生效条件:传入 cg 与 rec 时向 log_path(cg) 追加一条 JSONL 记录,OSError 被吞掉且无返回值;
|
|
86
114
|
def _append(cg, rec):
|
|
87
115
|
try:
|
|
88
116
|
append_jsonl(log_path(cg), rec)
|
|
@@ -90,6 +118,7 @@ def _append(cg, rec):
|
|
|
90
118
|
pass
|
|
91
119
|
|
|
92
120
|
|
|
121
|
+
# 生效条件:传入 cg 可读出 JSONL 记录时返回记录列表,读取抛 OSError 或 ValueError 时返回 [],limit 为正时仅返回末尾 limit 条;
|
|
93
122
|
def _read_log(cg, limit=0):
|
|
94
123
|
try:
|
|
95
124
|
recs = list(read_jsonl(log_path(cg)))
|
|
@@ -100,18 +129,21 @@ def _read_log(cg, limit=0):
|
|
|
100
129
|
return recs
|
|
101
130
|
|
|
102
131
|
|
|
132
|
+
# 生效条件:传入 cg 的留痕中存在 type=='feedback' 的记录时返回其 hit 布尔序列末尾 limit 条(limit 默认常量 HIT_HISTORY_MAX),无此类记录则返回空列表;
|
|
103
133
|
def _hit_history(cg, limit=HIT_HISTORY_MAX):
|
|
104
134
|
"""D-006 命中历史(持久化 · 差异 2):只取 feedback 记录。"""
|
|
105
135
|
return [bool(r.get("hit")) for r in _read_log(cg)
|
|
106
136
|
if r.get("type") == "feedback"][-int(limit):]
|
|
107
137
|
|
|
108
138
|
|
|
139
|
+
# 生效条件:传入 cg 与 nid 时返回邻接表中 nid 的出边列表 [(目标 id, 边字典)],该键无出边则为 [];
|
|
109
140
|
def _out_edges(cg, nid):
|
|
110
141
|
"""出边(含层级边):[(target_id, edge_dict)],复用 chain 邻接缓存。"""
|
|
111
142
|
from . import chain
|
|
112
143
|
return list((chain.adjacency(cg).get(nid) or []))
|
|
113
144
|
|
|
114
145
|
|
|
146
|
+
# 生效条件:传入 cg 与 nid 时返回邻接表中所有以 nid 为目标的源节点集合,无入边则为空集;
|
|
115
147
|
def _in_sources(cg, nid):
|
|
116
148
|
"""入边来源集合(父节点):用于 D-002「共同父节点」结构模式判定。"""
|
|
117
149
|
from . import chain
|
|
@@ -124,6 +156,7 @@ def _in_sources(cg, nid):
|
|
|
124
156
|
return srcs
|
|
125
157
|
|
|
126
158
|
|
|
159
|
+
# 生效条件:传入 edge 的 'confidence' 可转 float 时返回裁剪到 [0.0,1.0] 的值,取键失败或转换抛 AttributeError/TypeError/ValueError 时返回 1.0;
|
|
127
160
|
def _edge_conf(edge):
|
|
128
161
|
try:
|
|
129
162
|
return max(0.0, min(1.0, float(edge.get("confidence", 1.0))))
|
|
@@ -133,6 +166,7 @@ def _edge_conf(edge):
|
|
|
133
166
|
|
|
134
167
|
# ---------------------------------------------------------------- D-002 过滤门
|
|
135
168
|
|
|
169
|
+
# 生效条件:causal_link 成立条件为 a_id 的出边中存在目标 b_id 且其关系类型属于模块级常量 CAUSAL_BRANCH_TYPES,成立返回 True,否则返回 False;
|
|
136
170
|
def has_causal_link(cg, a_id, b_id):
|
|
137
171
|
"""直接因果/时序边:A → B 已声明(直通,无需过滤)。"""
|
|
138
172
|
from . import chain
|
|
@@ -142,11 +176,13 @@ def has_causal_link(cg, a_id, b_id):
|
|
|
142
176
|
return False
|
|
143
177
|
|
|
144
178
|
|
|
179
|
+
# 生效条件:传入 cg、a_id、b_id 时,a_id 与 b_id 的入边来源集合交集非空返回 True,交集为空返回 False;
|
|
145
180
|
def has_structural_pattern(cg, a_id, b_id):
|
|
146
181
|
"""结构模式:A、B 共享父节点(可解释的间接关联 → 伪因果豁免)。"""
|
|
147
182
|
return bool(_in_sources(cg, a_id) & _in_sources(cg, b_id))
|
|
148
183
|
|
|
149
184
|
|
|
185
|
+
# 生效条件:cg 具 attention_policy 且非 None、且 get_weights() 返回可取值的映射时返回 float(weights.get(node_id, 0.0)),策略缺失、取权重抛异常或转换失败时返回 0.0;
|
|
150
186
|
def preference_weight(cg, node_id):
|
|
151
187
|
"""D-005:AttentionPolicy 适配器(duck-typed `get_weights()`)。
|
|
152
188
|
|
|
@@ -166,6 +202,7 @@ def preference_weight(cg, node_id):
|
|
|
166
202
|
return 0.0
|
|
167
203
|
|
|
168
204
|
|
|
205
|
+
# 生效条件:cg/a_id/b_id 下 has_causal_link 成立返回 (True,'causal_link'),否则 has_structural_pattern 成立返回 (True,'structural_pattern'),否则 preference_weight(cg,b_id) 大于常量 PREFERENCE_THRESHOLD 返回 (True,'preference_weight'),三者皆不成立返回 (False,'rejected_semantic_only');
|
|
169
206
|
def causal_gate(cg, a_id, b_id):
|
|
170
207
|
"""D-002 伪因果过滤门 → (准入?, 理由)。
|
|
171
208
|
|
|
@@ -185,6 +222,7 @@ def causal_gate(cg, a_id, b_id):
|
|
|
185
222
|
|
|
186
223
|
# ---------------------------------------------------------------- 语义邻近
|
|
187
224
|
|
|
225
|
+
# 生效条件:cg.get(node_id) 的 content 去空后非空时以前 200 字符检索,返回相似度不低于常量 SEMANTIC_MIN_SIM 且非自身的至多 k 个 (nid, similarity);content 为空或检索抛异常时返回 [];
|
|
188
226
|
def semantic_neighbors(cg, node_id, k=SEMANTIC_TOP_K):
|
|
189
227
|
"""语义邻近候选:[(node_id, similarity)]。
|
|
190
228
|
|
|
@@ -223,6 +261,7 @@ def semantic_neighbors(cg, node_id, k=SEMANTIC_TOP_K):
|
|
|
223
261
|
|
|
224
262
|
# ---------------------------------------------------------------- D-001 分支
|
|
225
263
|
|
|
264
|
+
# 生效条件:传入 cg 与 node_id 时,其出边中关系类型属于常量 CAUSAL_BRANCH_TYPES 者直通为 causal 候选,semantic 为真时再并入经 causal_gate 放行的语义邻近候选,按 confidence 降序、node_id 升序返回;
|
|
226
265
|
def branch_candidates(cg, node_id, semantic=True):
|
|
227
266
|
"""D-001 局部分支候选:因果/时序边直通 + 语义邻近(经 D-002 门)。"""
|
|
228
267
|
from . import chain
|
|
@@ -254,6 +293,7 @@ def branch_candidates(cg, node_id, semantic=True):
|
|
|
254
293
|
|
|
255
294
|
# ---------------------------------------------------------------- D-003 / D-004
|
|
256
295
|
|
|
296
|
+
# 生效条件:conf 可转 float 时裁剪到 [0,1] 得 c,按 base=1-c 返回 confidence=c 与裁剪到 [0,1] 的 [c-base*0.5, c+base*0.5] 区间,转换失败则按 c=0.0 计算;
|
|
257
297
|
def _uncertainty(conf):
|
|
258
298
|
"""D-001 不确定带:base=1-conf,上下界 = conf ± base*0.5(AEIS 同式)。"""
|
|
259
299
|
try:
|
|
@@ -267,6 +307,7 @@ def _uncertainty(conf):
|
|
|
267
307
|
"method": "linear_local_approx"}
|
|
268
308
|
|
|
269
309
|
|
|
310
|
+
# 生效条件:传入 cg 与 path 且 path 非空时,返回其中 tags 含 'boundary' 或 has_neg_conditions,或 content 匹配「不适用|不确定|边界|盲区」的节点占比;path 为空返回 0.0;
|
|
270
311
|
def _boundary_consistency(cg, path):
|
|
271
312
|
"""boundary 维:路径节点是否声明了适用边界/不确定条件(0-1)。"""
|
|
272
313
|
if not path:
|
|
@@ -284,6 +325,7 @@ def _boundary_consistency(cg, path):
|
|
|
284
325
|
return round(hit / len(path), 4)
|
|
285
326
|
|
|
286
327
|
|
|
328
|
+
# 生效条件:传入 route 时返回其 sources 与 relations 去重并集大小除以 4.0 且上限 1.0 的值,两键皆缺时返回 0.0;
|
|
287
329
|
def _branch_diversity(route):
|
|
288
330
|
"""balance 维:路径覆盖的推理通道维度数 / 4。
|
|
289
331
|
|
|
@@ -295,6 +337,7 @@ def _branch_diversity(route):
|
|
|
295
337
|
return round(min(1.0, len(dims) / 4.0), 4)
|
|
296
338
|
|
|
297
339
|
|
|
340
|
+
# 生效条件:route 的 'confs' 长度不少于 2 时,相邻差绝对值最大值不超过 0.35 返回 'smooth' 否则 'jump';长度不足 2 或无可算步长返回 'unknown';
|
|
298
341
|
def extrapolation_validity(route):
|
|
299
342
|
"""D-003:局部线性外推有效性(smooth / jump / unknown)。"""
|
|
300
343
|
confs = route.get("confs") or []
|
|
@@ -306,6 +349,7 @@ def extrapolation_validity(route):
|
|
|
306
349
|
return "smooth" if max(abs(s) for s in steps) <= 0.35 else "jump"
|
|
307
350
|
|
|
308
351
|
|
|
352
|
+
# 生效条件:传入 cg 且 _hit_history(cg) 非空时返回其命中占比,序列为空时返回模块级常量 BASE_HIT_RATE;
|
|
309
353
|
def hit_rate(cg):
|
|
310
354
|
"""历史命中率(无样本 → 基线 0.40,对齐 D-006)。"""
|
|
311
355
|
h = _hit_history(cg)
|
|
@@ -316,6 +360,7 @@ def hit_rate(cg):
|
|
|
316
360
|
|
|
317
361
|
# ---------------------------------------------------------------- P-T-73/74 通道贝叶斯
|
|
318
362
|
|
|
363
|
+
# 生效条件:传入 hits 序列时以 base*prior_k 与 (1-base)*prior_k 为先验(prior_k 默认常量 PRIOR_STRENGTH、base 默认常量 BASE_HIT_RATE),按命中数 k 与总数 n 返回 alpha/beta/mean/std/ci95/samples/hits;hits 为空即为纯先验,mean 等于 base;
|
|
319
364
|
def beta_posterior(hits, prior_k=PRIOR_STRENGTH, base=BASE_HIT_RATE):
|
|
320
365
|
"""Beta-Bernoulli 后验(纯函数):命中序列 → 后验参数与区间。
|
|
321
366
|
|
|
@@ -346,6 +391,7 @@ def beta_posterior(hits, prior_k=PRIOR_STRENGTH, base=BASE_HIT_RATE):
|
|
|
346
391
|
"samples": n, "hits": k}
|
|
347
392
|
|
|
348
393
|
|
|
394
|
+
# 生效条件:传入 cg 时把 type=='feedback' 的记录按 channel 字段(缺失归 'unlabeled')分组为 {channel: [hit...]},仅取末尾 limit 条(limit 默认常量 HIT_HISTORY_MAX);
|
|
349
395
|
def channel_history(cg, limit=HIT_HISTORY_MAX):
|
|
350
396
|
"""feedback 留痕按通道分组(P-T-74 通道级可信度)→ {channel: [hit...]}。
|
|
351
397
|
|
|
@@ -361,6 +407,7 @@ def channel_history(cg, limit=HIT_HISTORY_MAX):
|
|
|
361
407
|
return out
|
|
362
408
|
|
|
363
409
|
|
|
410
|
+
# 生效条件:channel 非 None 时返回该通道(无记录即先验)的 beta_posterior 并附 channel 键,channel 为 None 时返回 {'all': 全量后验, 'channels': 各通道后验};
|
|
364
411
|
def channel_posterior(cg, channel=None, limit=HIT_HISTORY_MAX):
|
|
365
412
|
"""通道级后验查询:channel=None → 全量+分通道;channel=str → 单通道。"""
|
|
366
413
|
hist = channel_history(cg, limit=limit)
|
|
@@ -375,23 +422,35 @@ def channel_posterior(cg, channel=None, limit=HIT_HISTORY_MAX):
|
|
|
375
422
|
for ch, hits in sorted(hist.items())}}
|
|
376
423
|
|
|
377
424
|
|
|
425
|
+
# 生效条件:传入 cg 与 route 时,trend 取 route 的 confidence、boundary 取 _boundary_consistency(cg, route['path'])、verification 缺省时取 hit_rate(cg)、balance 取 _branch_diversity(route),并按 W_TREND/W_BOUNDARY/W_VERIFICATION/W_BALANCE 加权返回 composite;仅当 W_META>0(PREDICTION_META_DIM 显式启用第五维)时才额外取 d_meta.pressure(d_meta.compute(cg), META_PROXY) 作第五维、落 meta_pressure 键、把 W_META*meta_pressure 计入 composite,关闭时返回键集合与 composite 逐字节不变;
|
|
378
426
|
def score_route(cg, route, verification=None):
|
|
379
|
-
"""D-004 T_pred
|
|
427
|
+
"""D-004 T_pred 四维评分 + **D_meta 第五维(opt-in)**。
|
|
428
|
+
|
|
429
|
+
`verification` 跨路线共享(来自命中率)。第五维 `meta_pressure` 取
|
|
430
|
+
**单一指定代理**(`PREDICTION_META_PROXY`,缺省 `unmodeled_growth`)——
|
|
431
|
+
**不做三代理加权合成**(智能论3.4 §2.7.0 DEV-002a)。默认权重 0:
|
|
432
|
+
不落键、不改 composite、SORT_KEYS 不扩张(默认零变更纪律)。
|
|
433
|
+
"""
|
|
380
434
|
trend = float(route.get("confidence") or 0.0)
|
|
381
435
|
boundary = _boundary_consistency(cg, route.get("path") or [])
|
|
382
436
|
ver = float(verification if verification is not None else hit_rate(cg))
|
|
383
437
|
balance = _branch_diversity(route)
|
|
384
438
|
composite = (W_TREND * trend + W_BOUNDARY * boundary
|
|
385
439
|
+ W_VERIFICATION * ver + W_BALANCE * balance)
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
440
|
+
out = {"trend": round(trend, 4), "boundary": boundary,
|
|
441
|
+
"verification": round(ver, 4), "balance": balance,
|
|
442
|
+
"composite": round(composite, 4), "weights": _weights()}
|
|
443
|
+
if W_META > 0: # 第五维 opt-in:默认不落键
|
|
444
|
+
from . import d_meta # 惰性导入:叶子只读模块,防循环
|
|
445
|
+
mp = d_meta.pressure(d_meta.compute(cg), META_PROXY)
|
|
446
|
+
out["meta_pressure"] = mp
|
|
447
|
+
out["composite"] = round(composite + W_META * mp, 4)
|
|
448
|
+
return out
|
|
391
449
|
|
|
392
450
|
|
|
393
451
|
# ---------------------------------------------------------------- 盲区驱动
|
|
394
452
|
|
|
453
|
+
# 生效条件:blindspot_id 去空后非空且能取到盲区报表时,匹配 unresolved 的 node_id 返回 kind='unresolved',否则匹配 items 的 query 或其 _key 相等返回 kind='blindspot_cluster',均未命中或取报表抛异常返回 None;
|
|
395
454
|
def find_blindspot(cg, blindspot_id):
|
|
396
455
|
"""按 id 定位盲区:unresolved 节点优先,其次盲区邻域(按 query 键)。"""
|
|
397
456
|
from . import metacognition
|
|
@@ -415,6 +474,7 @@ def find_blindspot(cg, blindspot_id):
|
|
|
415
474
|
return None
|
|
416
475
|
|
|
417
476
|
|
|
477
|
+
# 生效条件:blindspot 的 description 中匹配到「可预测性:X」时返回 X 去除空白并小写,未匹配则返回 'predictable';
|
|
418
478
|
def predictability(blindspot):
|
|
419
479
|
"""可预测性:盲区可显式声明 `# 可预测性:unknowable`。
|
|
420
480
|
|
|
@@ -425,6 +485,7 @@ def predictability(blindspot):
|
|
|
425
485
|
return m.group(1).strip().lower() if m else "predictable"
|
|
426
486
|
|
|
427
487
|
|
|
488
|
+
# 生效条件:description 去空后非空时以 cg.search 取常量 ANCHOR_FETCH_K 个候选,跳过 layer 属常量 ANCHOR_SKIP_LAYERS 或 tags 命中常量 ANCHOR_SKIP_TAGS 者,返回首个出边非空的合格节点 id,否则降级返回首个合格候选 id;description 为空、检索抛异常或候选全被过滤返回 None;
|
|
428
489
|
def anchor_from_description(cg, description):
|
|
429
490
|
"""盲区描述 → 锚点节点(检索器打分,与 AEIS 的 LIKE→坐标回退同构)。
|
|
430
491
|
|
|
@@ -483,6 +544,7 @@ def anchor_from_description(cg, description):
|
|
|
483
544
|
|
|
484
545
|
# ---------------------------------------------------------------- 路线生成
|
|
485
546
|
|
|
547
|
+
# 生效条件:cg.get(nid) 的 content 含非空行时返回首行去掉开头 '#' 后的前 60 字符,否则返回 nid;
|
|
486
548
|
def _label(cg, nid):
|
|
487
549
|
node = cg.get(nid) or {}
|
|
488
550
|
for line in (node.get("content") or "").splitlines():
|
|
@@ -492,6 +554,7 @@ def _label(cg, nid):
|
|
|
492
554
|
return nid
|
|
493
555
|
|
|
494
556
|
|
|
557
|
+
# 生效条件:start_id 去空后非空且存在于 _nodes(cg) 时,horizon 裁剪到 [1, HORIZON_HARD]、max_branches 裁剪到 [1, MAX_BRANCHES_HARD] 后 DFS,返回 status='ok' 及带 uncertainty_bound/extrapolation_validity/score/path_labels 的 routes;start_id 为空或不在节点集中返回 status='start_not_found';
|
|
495
558
|
def _generate(cg, start_id, horizon, max_branches, semantic=True):
|
|
496
559
|
"""D-001 局部路径 DFS 生成候选未来(差异 3:增加 path 防环)。"""
|
|
497
560
|
start_id = str(start_id or "").strip()
|
|
@@ -503,6 +566,7 @@ def _generate(cg, start_id, horizon, max_branches, semantic=True):
|
|
|
503
566
|
ver = hit_rate(cg)
|
|
504
567
|
out = []
|
|
505
568
|
|
|
569
|
+
# 生效条件:当 depth < horizon(enclosing 上界)时,对 branch_candidates(cg, cur, semantic=semantic) 取前 max_branches 个候选展开——候选 node_id 已在 path 中则 continue 跳过,否则把 cand["confidence"] 连乘(初始 1.0,结果 round 4)连同 conds/sources/relations 各自追加 cand 对应字段后作为一条路径写入外层 out,并以该 node_id、depth+1 递归;depth >= horizon 时直接返回且不产生任何路径。
|
|
506
570
|
def dfs(cur, path, confs, conds, sources, relations, depth):
|
|
507
571
|
if depth >= horizon:
|
|
508
572
|
return
|
|
@@ -538,6 +602,7 @@ def _generate(cg, start_id, horizon, max_branches, semantic=True):
|
|
|
538
602
|
"generated_at": time.time()}}
|
|
539
603
|
|
|
540
604
|
|
|
605
|
+
# 生效条件:传入 cg、res、sort、limit 时,sort 不属于常量 SORT_KEYS 则退回 'composite',按该键排序并在 limit 为正时截断,追加一条 type 为 log_type(默认 'predict_routes')的留痕后返回 res;
|
|
541
606
|
def _finalize(cg, res, sort, limit, log_type="predict_routes"):
|
|
542
607
|
"""排序 / 限流 / 留痕(预测本身可审计)。"""
|
|
543
608
|
if sort not in SORT_KEYS:
|
|
@@ -556,6 +621,7 @@ def _finalize(cg, res, sort, limit, log_type="predict_routes"):
|
|
|
556
621
|
return res
|
|
557
622
|
|
|
558
623
|
|
|
624
|
+
# 生效条件:blindspot_id 非空时转交 routes_from_blindspot;否则 start_id 为空返回 status='no_start',_generate 返回非 ok 则原样返回,ok 则经 _finalize(cg, res, sort, limit) 返回;
|
|
559
625
|
def routes(cg, start_id=None, blindspot_id=None, horizon=HORIZON_DEFAULT,
|
|
560
626
|
max_branches=MAX_BRANCHES_DEFAULT, sort="composite", limit=0,
|
|
561
627
|
semantic=True):
|
|
@@ -580,6 +646,7 @@ def routes(cg, start_id=None, blindspot_id=None, horizon=HORIZON_DEFAULT,
|
|
|
580
646
|
return _finalize(cg, res, sort, limit)
|
|
581
647
|
|
|
582
648
|
|
|
649
|
+
# 生效条件:find_blindspot 得 None 时返回 status='blindspot_not_found',其 predictability 为 'unknowable' 时返回 status='unpredictable',anchor_from_description 无锚点时返回 status='no_anchor',有锚点则以其 _generate 并在 ok 时经 _finalize(log_type='predict_routes_blindspot')返回;
|
|
583
650
|
def routes_from_blindspot(cg, blindspot_id, horizon=HORIZON_DEFAULT,
|
|
584
651
|
max_branches=MAX_BRANCHES_DEFAULT, sort="composite",
|
|
585
652
|
limit=0, semantic=True):
|
|
@@ -610,10 +677,12 @@ def routes_from_blindspot(cg, blindspot_id, horizon=HORIZON_DEFAULT,
|
|
|
610
677
|
_SAFE_LAYERS = ("knowledge", "contextual", "structural")
|
|
611
678
|
|
|
612
679
|
|
|
680
|
+
# 生效条件:传入 edge 时返回其 'target'、'to'、'dst' 中首个非空值,三者皆空则返回 None;
|
|
613
681
|
def _edge_target(edge):
|
|
614
682
|
return edge.get("target") or edge.get("to") or edge.get("dst")
|
|
615
683
|
|
|
616
684
|
|
|
685
|
+
# 生效条件:传入 cg 与 node_id 时,仅当存在指向 node_id 的因果/时序边且其源节点 frontmatter 的 layer 属于常量 _SAFE_LAYERS,才把该边 confidence 提升 min(1.0, 原值+delta)(delta 默认常量 EDGE_BOOST)并回写,返回被改源节点列表,无满足者返回空列表;
|
|
617
686
|
def _boost_incoming(cg, node_id, delta=EDGE_BOOST, actor="predict"):
|
|
618
687
|
"""命中 → 指向该节点的因果/时序边置信度 +delta。
|
|
619
688
|
|
|
@@ -670,6 +739,7 @@ def _boost_incoming(cg, node_id, delta=EDGE_BOOST, actor="predict"):
|
|
|
670
739
|
return changed
|
|
671
740
|
|
|
672
741
|
|
|
742
|
+
# 生效条件:传入 cg 时若 _hit_history(cg, limit) 样本数少于常量 MIN_SAMPLES,返回 threshold 为常量 BASE_HIT_RATE 且 reflect=False;样本足够则以 max(BASE_HIT_RATE, mean-2σ) 为 threshold,命中均值低于该值时 reflect=True;
|
|
673
743
|
def dynamic_hit_threshold(cg, limit=HIT_HISTORY_MAX):
|
|
674
744
|
"""D-006 命中率动态校准(2.7.2 动态死区)。
|
|
675
745
|
|
|
@@ -693,6 +763,7 @@ def dynamic_hit_threshold(cg, limit=HIT_HISTORY_MAX):
|
|
|
693
763
|
else "命中率正常"}
|
|
694
764
|
|
|
695
765
|
|
|
766
|
+
# 生效条件:cg 与 predicted_node_id 给出即执行——predicted_node_id 为假值(None/0/"")时 pred 取空串,actual_node_id 为假值时 act 回落为 pred,hit 为 None 时按 pred==act 判定;hit 为真时 out["boosted"] 取 _boost_incoming(cg, act, EDGE_BOOST, actor=actor),hit 为假时 out["rejected_id"] 取 cg.add_rejected(...)(该调用抛异常时改记 out["rejected_error"]),随后 out 合并 dynamic_hit_threshold(cg),sync_self 为真时导入 self_state.refresh(cg, actor=actor) 写 out["self_state"](抛异常时写 out["self_state_error"]),返回 out。
|
|
696
767
|
def feedback(cg, predicted_node_id, actual_node_id=None, hit=None, note="",
|
|
697
768
|
actor="predict", sync_self=True, channel=None):
|
|
698
769
|
"""预测反馈(D-006):hit → 边置信度 +0.05;miss → 登记 rejected。
|
|
@@ -743,10 +814,12 @@ LEARN_LOG = "_learn.jsonl"
|
|
|
743
814
|
LEARN_MAX_STEPS = 8
|
|
744
815
|
|
|
745
816
|
|
|
817
|
+
# 生效条件:传入 cg 具 root 属性时返回 root 与模块级常量 LEARN_LOG 的路径拼接,缺 root 则以 '.' 拼接;
|
|
746
818
|
def learn_log_path(cg):
|
|
747
819
|
return os.path.join(getattr(cg, "root", "."), LEARN_LOG)
|
|
748
820
|
|
|
749
821
|
|
|
822
|
+
# 生效条件:传入 cg 与 rec 时向 learn_log_path(cg) 追加一条 JSONL 记录,任何异常被吞掉且无返回值;
|
|
750
823
|
def _learn_append(cg, rec):
|
|
751
824
|
try:
|
|
752
825
|
append_jsonl(learn_log_path(cg), rec)
|
|
@@ -754,6 +827,7 @@ def _learn_append(cg, rec):
|
|
|
754
827
|
pass
|
|
755
828
|
|
|
756
829
|
|
|
830
|
+
# 生效条件:nid 去空后非空、cg.get(nid) 的 frontmatter layer 等于 'knowledge' 且其 content 含常量 consolidate.CCG_REQUIRED 全部要素行时返回 True,否则返回 False;
|
|
757
831
|
def _is_settled(cg, nid):
|
|
758
832
|
"""终点是否已达「可判定」态:知识层 ∧ CCG 五要素齐全。"""
|
|
759
833
|
nid = str(nid or "").strip()
|
|
@@ -775,11 +849,13 @@ def _is_settled(cg, nid):
|
|
|
775
849
|
return False
|
|
776
850
|
|
|
777
851
|
|
|
852
|
+
# 生效条件:传入 route 且其 'path' 非空时返回路径最后一个节点 id,路径为空或 route 为 None 时返回 None;
|
|
778
853
|
def _terminal_node(route):
|
|
779
854
|
path = list((route or {}).get("path") or [])
|
|
780
855
|
return path[-1] if path else None
|
|
781
856
|
|
|
782
857
|
|
|
858
|
+
# 生效条件:传入 cg、bid、step、actor 时,cg 中不存在由 bid 的 sha1 派生的 gap 节点 id 则写入 contextual 的 gap_hint 节点并返回该 id;该 id 已存在或 cg.add 抛异常时返回 None;
|
|
783
859
|
def _write_gap(cg, bid, step, actor):
|
|
784
860
|
"""把待补线索写成 contextual 的 ``gap_hint`` 节点(幂等,非事实断言)。"""
|
|
785
861
|
nid = "gap_%s" % hashlib.sha1(bid.encode("utf-8")).hexdigest()[:10]
|
|
@@ -805,6 +881,7 @@ def _write_gap(cg, bid, step, actor):
|
|
|
805
881
|
return None
|
|
806
882
|
|
|
807
883
|
|
|
884
|
+
# 生效条件:blindspot_id 给出但 find_blindspot 找不到时返回 ok=False 与 status='not_found';否则逐条按 unknowable/no_anchor/unresolved/carried/resolved 判定,apply 为真且 cg 可写时才把 carried/unresolved 落成幂等 gap_hint 节点;
|
|
808
885
|
def learn_blindspots(cg, blindspot_id=None, limit=LEARN_MAX_STEPS,
|
|
809
886
|
horizon=HORIZON_DEFAULT, max_branches=MAX_BRANCHES_DEFAULT,
|
|
810
887
|
apply=False, actor="insight", **extra):
|
|
@@ -903,6 +980,7 @@ def learn_blindspots(cg, blindspot_id=None, limit=LEARN_MAX_STEPS,
|
|
|
903
980
|
"resolved 仅表示已有可判定终点,未改动任何事实层节点")}
|
|
904
981
|
|
|
905
982
|
|
|
983
|
+
# 生效条件:传入 cg 时基于 _read_log(cg) 统计 type 以 'predict_routes' 开头的调用数与 n_routes 合计、feedback 样本与命中率(无样本取常量 BASE_HIT_RATE),并附 channel_posterior 与 dynamic_hit_threshold,recent 取末尾 limit 条(limit 默认 20,为 0 时为空);
|
|
906
984
|
def stats(cg, limit=20):
|
|
907
985
|
"""预测统计:调用数、生成路线数、反馈样本、命中率、动态阈值。"""
|
|
908
986
|
recs = _read_log(cg)
|
|
@@ -921,6 +999,7 @@ def stats(cg, limit=20):
|
|
|
921
999
|
|
|
922
1000
|
# ---------------------------------------------------------------- 因果推理
|
|
923
1001
|
|
|
1002
|
+
# 生效条件:传入 cg 与 path 且 path 长度不少于 2 时,对每对相邻节点返回其在邻接表中且关系类型属于常量 CAUSAL_BRANCH_TYPES 的边条件(无匹配则为空串)逐跳列表,path 更短则返回空列表;
|
|
924
1003
|
def _path_conditions(cg, path):
|
|
925
1004
|
"""路径上每跳的边条件(与节点对一一对应)。"""
|
|
926
1005
|
from . import chain
|
|
@@ -937,6 +1016,7 @@ def _path_conditions(cg, path):
|
|
|
937
1016
|
return conds
|
|
938
1017
|
|
|
939
1018
|
|
|
1019
|
+
# 生效条件:a_id 或 b_id 去空后为空时返回 ok=False 与 error='missing_node';a_id 等于 b_id 返回可达且长度 0;否则仅在常量 CAUSAL_BRANCH_TYPES 边上于 max_depth(下限 1)内 BFS,可达返回路径与逐跳 conditions,不可达返回 reachable=False;
|
|
940
1020
|
def causal_path(cg, a_id, b_id, max_depth=5):
|
|
941
1021
|
"""因果路径推理:A 能否沿因果/时序边到达 B(BFS,最短路径)。
|
|
942
1022
|
|
|
@@ -980,6 +1060,7 @@ def causal_path(cg, a_id, b_id, max_depth=5):
|
|
|
980
1060
|
|
|
981
1061
|
# ---------------------------------------------------------------- 自描述
|
|
982
1062
|
|
|
1063
|
+
# 生效条件:不适用(无必需形参与模块级常量)
|
|
983
1064
|
def catalog():
|
|
984
1065
|
"""决策编号 / 权重 / 校准参数 / 与 AEIS 的差异(供协议对照验证)。"""
|
|
985
1066
|
return {
|
|
@@ -998,8 +1079,7 @@ def catalog():
|
|
|
998
1079
|
"P-T-73/74": "通道贝叶斯后验(Beta-Bernoulli,置信度≠可信度;"
|
|
999
1080
|
"feedback channel 参数 + channel_posterior 查询)",
|
|
1000
1081
|
},
|
|
1001
|
-
"weights":
|
|
1002
|
-
"verification": W_VERIFICATION, "balance": W_BALANCE},
|
|
1082
|
+
"weights": _weights(), # 第五维 opt-in 时同步扩张(防文档漂移)
|
|
1003
1083
|
"calibration": {"min_samples": MIN_SAMPLES,
|
|
1004
1084
|
"base_hit_rate": BASE_HIT_RATE,
|
|
1005
1085
|
"edge_boost": EDGE_BOOST,
|
|
@@ -1018,4 +1098,4 @@ def catalog():
|
|
|
1018
1098
|
],
|
|
1019
1099
|
"actions": ["routes", "routes_from_blindspot", "feedback", "stats",
|
|
1020
1100
|
"causal_path", "causal_gate", "catalog"],
|
|
1021
|
-
}
|
|
1101
|
+
}
|
package/md_cg/progressive.py
CHANGED
|
@@ -44,6 +44,7 @@ from __future__ import annotations
|
|
|
44
44
|
MIN_DISCRIM = 0.1
|
|
45
45
|
|
|
46
46
|
|
|
47
|
+
# 生效条件:atoms 经 `a for a in (atoms or ()) if a` 过滤后为空(atoms 为 None/空容器/元素全为假值)→ 返回 [],否则取过滤后前 n 项,n = max(1, int(len(toks)*ratio)),故 ratio=0 或负值时仍返回 1 项、ratio=1.0 时返回全部。
|
|
47
48
|
def core_subset(atoms, ratio=0.5):
|
|
48
49
|
"""Stage-1 宽检索核心子集:归一序列前 int(len*ratio) 个(保序,确定性)。
|
|
49
50
|
|
|
@@ -57,6 +58,7 @@ def core_subset(atoms, ratio=0.5):
|
|
|
57
58
|
return toks[:n]
|
|
58
59
|
|
|
59
60
|
|
|
61
|
+
# 生效条件:cand_sets 长度 < 2 或 unused 为假值/空序列 → 返回 None;否则对 unused 保序逐项算 cov=命中 cand_sets 的比例、gap=1-|2*cov-1|,返回 gap 严格大于 float(min_gap)(默认模块常量 MIN_DISCRIM)者中 gap 最大者,同 gap 取 unused 原序靠前者;无满足者返回 None。
|
|
60
62
|
def discriminative(unused, cand_sets, min_gap=MIN_DISCRIM):
|
|
61
63
|
"""候选间区分度最大的未用原子(确定性:同 gap 取归一序列原序靠前者)。
|
|
62
64
|
|
|
@@ -76,6 +78,7 @@ def discriminative(unused, cand_sets, min_gap=MIN_DISCRIM):
|
|
|
76
78
|
return best
|
|
77
79
|
|
|
78
80
|
|
|
81
|
+
# 生效条件:atoms 真值过滤后为空 → 返回 {'stages': [], 'added': [], 'converged': False};否则从 used=core_subset(toks, ratio) 起在 range(max_stages) 内循环,每阶段记录 rank_fn(used) 的前 k(默认 10)个 cid 与当前 used,若 stage==max_stages-1 则 break 且 converged 保持 False,非末阶段则用 pool(cond_pool 为真值时取 list(cond_pool),否则回落为 toks 真值过滤后的 atoms)中未用原子对 top 的 cand_atoms.get(cid, frozenset()) 调 discriminative:结果非 None 时并入 used 并追加进 added 继续循环,为 None 时置 converged=True 提前结束。
|
|
79
82
|
def progressive_search(rank_fn, atoms, cand_atoms,
|
|
80
83
|
ratio=0.5, k=10, max_stages=4,
|
|
81
84
|
cond_pool=None, min_gap=MIN_DISCRIM):
|
package/md_cg/protect.py
CHANGED
|
@@ -53,10 +53,12 @@ class ProtectionError(PermissionError):
|
|
|
53
53
|
|
|
54
54
|
# ---------------------------------------------------------------- 判定
|
|
55
55
|
|
|
56
|
+
# 生效条件:对任意 cg、node_id 无条件返回 `(cg.index 或其假值时的 {})["nodes"]`(该键缺失或假值时为 `{}`)中以 node_id 为键的值,索引无此键时返回 None。
|
|
56
57
|
def _entry(cg, node_id):
|
|
57
58
|
return ((getattr(cg, "index", None) or {}).get("nodes") or {}).get(node_id)
|
|
58
59
|
|
|
59
60
|
|
|
61
|
+
# 生效条件:cg 索引中无 node_id 条目时返回 None;有条目时先取 layer/importance(缺 importance 键回落 0.5)/protected/protection_reason/immutable/self_state,仅当条目缺 protected 或 immutable、或(缺 self_state 且条目 layer∈PROTECTED_LAYERS)时再经 cg.get(node_id) 用 frontmatter 覆盖这四个键(cg.get 抛异常或返回假值时保留索引值;layer 取 frontmatter.layer or 索引 layer,importance 缺键时回落索引 importance)。
|
|
60
62
|
def _fm(cg, node_id):
|
|
61
63
|
"""取判定所需的 frontmatter 字段;索引快照缺 protected 时回退读文件。"""
|
|
62
64
|
e = _entry(cg, node_id)
|
|
@@ -91,6 +93,7 @@ def _fm(cg, node_id):
|
|
|
91
93
|
return fm
|
|
92
94
|
|
|
93
95
|
|
|
96
|
+
# 生效条件:cg 索引无 node_id 条目(_fm 直接返回 None,不走回退读文件)时返回 (False, '');有条目时按 layer∈PROTECTED_LAYERS 返回 (True, 层保护);否则 protected is True 时返回 (True, protection_reason 或 '显式保护标记');否则 importance(缺失/假值/float 转换异常一律按 0.0)≥AUTO_PROTECT_IMPORTANCE 时返回 (True, 重要性保护);其余返回 (False, '')。
|
|
94
97
|
def is_protected(cg, node_id):
|
|
95
98
|
"""**不可遗忘**判定 → (是否受保护, 原因)。节点不存在返回 (False, "")。"""
|
|
96
99
|
fm = _fm(cg, node_id)
|
|
@@ -110,6 +113,7 @@ def is_protected(cg, node_id):
|
|
|
110
113
|
return False, ""
|
|
111
114
|
|
|
112
115
|
|
|
116
|
+
# 生效条件:cg 索引无 node_id 条目时返回 (False, '');有条目时若 self_state is True 一律返回 (False, '')(自我状态豁免);否则 layer∈PROTECTED_LAYERS 返回 (True, 层保护);否则 immutable is True 返回 (True, protection_reason 或 '显式不可覆盖标记');其余返回 (False, '')。
|
|
113
117
|
def is_immutable(cg, node_id):
|
|
114
118
|
"""**不可覆盖**判定 → (是否不可篡改, 原因)。比不可遗忘更窄,只认强信号。
|
|
115
119
|
|
|
@@ -133,6 +137,7 @@ def is_immutable(cg, node_id):
|
|
|
133
137
|
|
|
134
138
|
# ---------------------------------------------------------------- 留痕
|
|
135
139
|
|
|
140
|
+
# 生效条件:对任意 cg、action、node_id、reason(actor/snapshot 缺省为 None)都构造含 t/action/node_id/reason/actor/snapshot 的 rec 并返回,同时尝试追加写入 cg.root 下的 AUDIT_FILE,该写入抛出的任何异常被吞掉且不影响返回值。
|
|
136
141
|
def _audit(cg, action, node_id, reason, actor=None, snapshot=None):
|
|
137
142
|
rec = {"t": time.time(), "action": action, "node_id": node_id,
|
|
138
143
|
"reason": reason, "actor": actor, "snapshot": snapshot}
|
|
@@ -143,6 +148,7 @@ def _audit(cg, action, node_id, reason, actor=None, snapshot=None):
|
|
|
143
148
|
return rec
|
|
144
149
|
|
|
145
150
|
|
|
151
|
+
# 生效条件:cg.get(node_id) 抛异常或返回假值时返回 None;否则在 cg.root/HISTORY_DIR/node_id 下以时间戳命名写入当前 frontmatter 与 content,_write_node 抛异常时返回 None,成功则返回相对 cg.root 且以 '/' 分隔的路径。
|
|
146
152
|
def snapshot(cg, node_id):
|
|
147
153
|
"""把节点当前版本快照进 `_protected_history/<id>/<ts>.md`,返回相对路径。"""
|
|
148
154
|
try:
|
|
@@ -163,6 +169,7 @@ def snapshot(cg, node_id):
|
|
|
163
169
|
return os.path.relpath(p, cg.root).replace("\\", "/")
|
|
164
170
|
|
|
165
171
|
|
|
172
|
+
# 生效条件:cg.root/HISTORY_DIR/node_id 不是目录时返回 [];是目录时返回该目录下以 .md 结尾(不递归)的文件按名称排序后的 `HISTORY_DIR/node_id/文件名` 列表,无匹配文件则列表为空。
|
|
166
173
|
def history(cg, node_id):
|
|
167
174
|
"""受保护节点的历史版本列表(按时间升序)。"""
|
|
168
175
|
d = os.path.join(cg.root, HISTORY_DIR, node_id)
|
|
@@ -175,12 +182,14 @@ def history(cg, node_id):
|
|
|
175
182
|
|
|
176
183
|
# ---------------------------------------------------------------- 守卫
|
|
177
184
|
|
|
185
|
+
# 生效条件:对任意 cg、node_id、why、action、override、actor 都无条件返回 {'override': True, 'reason': why, 'snapshot': snapshot(...) 的结果, 'audit': _audit(cg, action, node_id, why, actor, snap) 的结果},override 形参本身不改变返回内容。
|
|
178
186
|
def _allow(cg, node_id, why, action, override, actor):
|
|
179
187
|
snap = snapshot(cg, node_id)
|
|
180
188
|
rec = _audit(cg, action, node_id, why, actor, snap)
|
|
181
189
|
return {"override": True, "reason": why, "snapshot": snap, "audit": rec}
|
|
182
190
|
|
|
183
191
|
|
|
192
|
+
# 生效条件:is_immutable(cg, node_id) 为假(含 self_state is True、layer 不在 PROTECTED_LAYERS 且 immutable 非 True 的情形)时返回 None;为真时 override 取真值则返回 _allow(..., 'override_write', override, actor),否则抛出 ProtectionError;layer 形参不参与该判定。
|
|
184
193
|
def guard_write(cg, node_id, layer=None, override=False, actor=None):
|
|
185
194
|
"""覆盖既有节点前的守卫(只认**不可覆盖**信号)。
|
|
186
195
|
|
|
@@ -196,6 +205,7 @@ def guard_write(cg, node_id, layer=None, override=False, actor=None):
|
|
|
196
205
|
f"节点 {node_id} 受写保护({why});覆盖需显式 override=True")
|
|
197
206
|
|
|
198
207
|
|
|
208
|
+
# 生效条件:is_protected(cg, node_id) 为假时返回 None;为真时 override 取真值则返回 _allow(..., 'override_forget', override, actor),否则抛出 ProtectionError。
|
|
199
209
|
def guard_forget(cg, node_id, override=False, actor=None):
|
|
200
210
|
"""删除前的守卫。受保护节点 = 不可遗忘。"""
|
|
201
211
|
prot, why = is_protected(cg, node_id)
|
|
@@ -207,6 +217,7 @@ def guard_forget(cg, node_id, override=False, actor=None):
|
|
|
207
217
|
f"节点 {node_id} 不可遗忘({why});删除需显式 override=True")
|
|
208
218
|
|
|
209
219
|
|
|
220
|
+
# 生效条件:is_protected(cg, node_id) 为假时返回 None;为真且 to_layer∈PROTECTED_LAYERS(保护层间互搬)时也返回 None;为真且 to_layer 不在 PROTECTED_LAYERS 时,override 取真值则返回 _allow(..., 'override_move', override, actor),否则抛出 ProtectionError。
|
|
210
221
|
def guard_move(cg, node_id, to_layer, override=False, actor=None):
|
|
211
222
|
"""降级/搬迁前的守卫:受保护节点不得被移出保护层。"""
|
|
212
223
|
prot, why = is_protected(cg, node_id)
|
|
@@ -220,6 +231,7 @@ def guard_move(cg, node_id, to_layer, override=False, actor=None):
|
|
|
220
231
|
f"节点 {node_id} 受写保护({why});降级移出保护层需显式 override=True")
|
|
221
232
|
|
|
222
233
|
|
|
234
|
+
# 生效条件:cg.get(node_id) 抛异常或返回假值时返回 None;否则把 protected=True 与 protection_reason=reason 写入 cg.root 下 node["path"](该键缺失即抛 KeyError)对应的 frontmatter 并保持原 content,随后门条目存在时同步其 protected/protection_reason,返回 {'node_id': node_id, 'protected': True, 'reason': reason}。
|
|
223
235
|
def mark(cg, node_id, reason):
|
|
224
236
|
"""给节点打上 `protected=True` 标记(写回 frontmatter,不动 content)。"""
|
|
225
237
|
try:
|
|
@@ -240,6 +252,7 @@ def mark(cg, node_id, reason):
|
|
|
240
252
|
return {"node_id": node_id, "protected": True, "reason": reason}
|
|
241
253
|
|
|
242
254
|
|
|
255
|
+
# 生效条件:遍历 cg.index.nodes(或其假值时的空字典)的每个键,对 is_protected 为真的节点计入 ids 并按 layer(缺失/假值记为 '?')累加 by_layer,其中原因串含 "importance=" 或以 "重要性保护" 开头的计入 auto_by_importance,对 is_immutable 为真的计入 immutable_ids,返回含 protected_count/immutable_count/by_layer/auto_by_importance/ids/immutable_ids 的字典。
|
|
243
256
|
def stats(cg):
|
|
244
257
|
"""保护面盘点:不可遗忘数 / 不可覆盖数 / 分层分布 / 自动保护命中数。"""
|
|
245
258
|
nodes = ((getattr(cg, "index", None) or {}).get("nodes") or {})
|
|
@@ -257,4 +270,4 @@ def stats(cg):
|
|
|
257
270
|
immutable.append(nid)
|
|
258
271
|
return {"protected_count": len(ids), "immutable_count": len(immutable),
|
|
259
272
|
"by_layer": by_layer, "auto_by_importance": auto, "ids": ids,
|
|
260
|
-
"immutable_ids": immutable}
|
|
273
|
+
"immutable_ids": immutable}
|