@furongjun1999/dsh-memory 0.7.2 → 0.7.4
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 +57 -47
- package/codebuddy/CODEBUDDY.md +6 -6
- 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/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/217/221/345/270/20312_/344/270/226/347/225/214/346/250/241/345/236/213/345/212/237/350/203/275/347/253/257_v1.0.md +108 -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/eval//350/257/255/344/271/211/346/227/266/347/251/272/345/233/276/350/241/245/345/205/250_P1_/346/212/275/345/217/226/345/231/250v4_/344/270/211/347/216/207/350/257/273/346/225/260_v1.0.md +231 -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//344/270/226/347/225/214/346/250/241/345/236/213/345/212/237/350/203/275/347/253/257_/344/275/277/347/224/250/344/270/216/350/277/220/347/273/264_v1.0.md +305 -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 +45 -42
- 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 +6 -5
- 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 +134 -50
- 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/lib/lib/session_state.d.ts +56 -0
- package/lib/lib/session_state.js +124 -0
- package/lib/tools.js +12 -1
- package/md_cg/auditview.py +248 -0
- package/md_cg/bench_e2e_judge.py +4 -2
- package/md_cg/branches.py +29 -3
- 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/lifecycle.py +38 -0
- package/md_cg/mcp_server.py +122 -12
- package/md_cg/mdcg.py +4923 -4822
- package/md_cg/mdcos.py +109 -21
- package/md_cg/nodefile.py +77 -13
- package/md_cg/readcache.py +29 -4
- 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/state_slots.py +221 -0
- package/md_cg/stg.py +68 -3
- 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_datapath_device_name.py +62 -3
- package/md_cg/test_generation_guard.py +5 -2
- package/md_cg/test_ghostref.py +182 -0
- package/md_cg/test_interop.py +1 -1
- package/md_cg/test_issue52_scan_condition_first.py +1 -1
- package/md_cg/test_lifecycle_retire_leak.py +408 -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_read_face_semantics.py +6 -3
- 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_event_op.py +514 -0
- package/md_cg/test_state_events.py +178 -0
- package/md_cg/test_state_slots.py +691 -0
- package/md_cg/test_time_core_lint.py +8 -1
- package/md_cg/test_writepipe.py +8 -5
- package/md_cg/tokens.py +18 -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 +599 -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/src/lib/session_state.ts +127 -0
- package/src/tools.ts +12 -1
- package/zcode/AGENTS.md +6 -6
package/md_cg/mdcos.py
CHANGED
|
@@ -37,7 +37,7 @@ from .mdcg import (MdCG, expand_query_terms, bigrams, normalize_en, STATE_ACCEPT
|
|
|
37
37
|
from . import (nodefile, routing, chain, subgraph, forgetting, protect,
|
|
38
38
|
identity, consistency, metacognition, crypto, sustain,
|
|
39
39
|
self_state, predict, evolution, weights, pooling,
|
|
40
|
-
writelimit, reach, trust, roleviews, autonomy_modes)
|
|
40
|
+
writelimit, reach, trust, roleviews, autonomy_modes, lifecycle)
|
|
41
41
|
from .fsutil import (FileLock, atomic_write, append_jsonl, read_jsonl,
|
|
42
42
|
read_jsonl_tail, count_jsonl, publish)
|
|
43
43
|
from .security import (Principal, TenantRegistry, AccessDenied,
|
|
@@ -425,6 +425,26 @@ def _note_visible(cg, e) -> bool:
|
|
|
425
425
|
return _security.visible_to(cg, e)
|
|
426
426
|
|
|
427
427
|
|
|
428
|
+
# 生效条件:cg 索引的 nodes 中该 nid 有条目且 lifecycle.is_archived(该条目) 为真时返回 True;条目缺失时把 None 交给 state_of ⇒ 返回 False(fail-open,与判据单点同语义)。
|
|
429
|
+
def _retired_by_id(cg, nid) -> bool:
|
|
430
|
+
"""退役判据在「**按 id 取**的节点」上的单点包装(会话续接包台账段用)。
|
|
431
|
+
|
|
432
|
+
台账两段(goals / tasks)拿到的是 `_goal_entry` / `tasks._entry` 的**对外条目**
|
|
433
|
+
(只有 id,没有索引条目本身),故此处按 id 回查索引再交判据单点
|
|
434
|
+
`lifecycle.is_archived`——判据仍只此一份,不另立第二套口径。
|
|
435
|
+
"""
|
|
436
|
+
e = ((getattr(cg, "index", None) or {}).get("nodes") or {}).get(nid)
|
|
437
|
+
return lifecycle.is_archived(e)
|
|
438
|
+
|
|
439
|
+
|
|
440
|
+
#: 会话续接包台账段(goals / tasks)的取数窗:取全量再过滤退役再截断
|
|
441
|
+
#: (`list_goals` 本就全表扫;`tasks.session_tasks` 内部本就先建全量列表再切片,
|
|
442
|
+
#: 故不增遍历成本),避免「窗口内的 archived 被剔后不足额」。
|
|
443
|
+
_LEDGER_WINDOW = 10 ** 6
|
|
444
|
+
#: 台账段每段最终回出的条数(与改动前的 limit=5 逐位一致)。
|
|
445
|
+
_PACK_ROWS = 5
|
|
446
|
+
|
|
447
|
+
|
|
428
448
|
# 生效条件:以任意 root 构造时按其拼接 audit_log/hippocampus/trash 等路径并 makedirs 创建 hippocampus 与 trash_dir(exist_ok=True),autoflush 透传父类、actor 存入 self.actor;
|
|
429
449
|
class MdCGOS(MdCG):
|
|
430
450
|
"""MdCG + 记忆 OS 七项能力。"""
|
|
@@ -747,7 +767,7 @@ class MdCGOS(MdCG):
|
|
|
747
767
|
payload_hash=_sig(content))
|
|
748
768
|
return nid
|
|
749
769
|
|
|
750
|
-
# 生效条件:在已用 root 构造的实例上遍历 index["nodes"],恒剔除 layer 为 rejected/unresolved/goals
|
|
770
|
+
# 生效条件:在已用 root 构造的实例上遍历 index["nodes"],恒剔除 layer 为 rejected/unresolved/goals 的节点,恒剔除 lifecycle.is_archived(e) 为真的节点(退役不参与默认检索;缺 lifecycle 键=active 照常,converged/demoted 仍参与),session 为真值而 e["session"] 不等于它时剔除,e["branch_id"] 不在 (None, branch) 时剔除(branch=None 时只留 branch_id 为 None 者),validity 为真值而 trust.is_expired(e) 为真时剔除(**只排已过期,not_yet 保留**),layer 为真值而 layer 不等时剔除,roles 不为 None 时仅留 role 落在 roles 内的节点;view 为真值时 role 维度裁决权移交 roleviews.matches(receipt=工作角色白名单须绕过默认剔除才可达,非法 view ValueError),view 为假值且 include_work 为假时剔除 WORK_ROLES 角色,时间算子启用时按 time_axis 轴过滤(效力轴不可判定 fail-open、观察轴不可判定 fail-closed 并入 self._time_filter_stat),其余收集进 out 返回。
|
|
751
771
|
def _candidates(self, layer=None, roles=None, include_work=False,
|
|
752
772
|
session=None, branch=None, validity=None,
|
|
753
773
|
start_time=None, end_time=None, start_operator=None,
|
|
@@ -782,6 +802,19 @@ class MdCGOS(MdCG):
|
|
|
782
802
|
if e.get("layer") in NEG_ROUTE_LAYERS:
|
|
783
803
|
continue # 负记忆走覆盖标记;目标只做定向,都不进正排
|
|
784
804
|
# (真源 mdcg.NEG_ROUTE_LAYERS,本处直接导入,不留第二份字面量)
|
|
805
|
+
if lifecycle.is_archived(e):
|
|
806
|
+
continue # lifecycle.py:42 标称兑现:archived 不参与默认检索。
|
|
807
|
+
# 本处是 **cg 检索面单点**——`MdCGSecure._candidates`
|
|
808
|
+
# 经 super() 在此之上叠加读可见性,故全部**检索类**
|
|
809
|
+
# cg 读 op(search / search_rrf / recall / route…)经此
|
|
810
|
+
# 一处。cg 的读 op 并非全走候选池:`op=session` 的续接包
|
|
811
|
+
# 自持取数面,另在 `_session_notes` / `session_recall`
|
|
812
|
+
# 接同一判据(见 lifecycle.is_archived 的消费面清单)。
|
|
813
|
+
# 判据单点在 lifecycle.is_archived(fail-open:缺键=
|
|
814
|
+
# active 照常;只剔 archived——converged/demoted 是
|
|
815
|
+
# **降权轴**,仍参与默认检索)。
|
|
816
|
+
# 直读面(cg.get / op=audit / 库层 set_state 恢复路径)**不**
|
|
817
|
+
# 经本函数:退役不删除、可显式恢复。见 lifecycle.is_archived
|
|
785
818
|
# '"*"' = 显式跨会话(读遍所有会话);缺省 None 同义(见 stg.timeline)
|
|
786
819
|
if session and session != "*" and e.get("session") != session:
|
|
787
820
|
continue
|
|
@@ -977,7 +1010,9 @@ class MdCGOS(MdCG):
|
|
|
977
1010
|
# 语义资格(MDCG_SEMANTIC=1):fm.semantic 节点无条件入池
|
|
978
1011
|
hits = [d for d in docs
|
|
979
1012
|
if self._like(d[2], d[1], terms,
|
|
980
|
-
index_key_hits(d[0], terms, q)
|
|
1013
|
+
index_key_hits(d[0], terms, q),
|
|
1014
|
+
entry=d[0],
|
|
1015
|
+
positive_body=self._positive_body)
|
|
981
1016
|
or (semantic_on() and d[1].get("semantic"))]
|
|
982
1017
|
out = try_stage(hits, TIER_BUCKET_LIKE)
|
|
983
1018
|
if out:
|
|
@@ -1004,7 +1039,9 @@ class MdCGOS(MdCG):
|
|
|
1004
1039
|
_dif = set(_rstat.get("reach_diffused_paths") or ())
|
|
1005
1040
|
hits_r = [d for d in docs_r
|
|
1006
1041
|
if self._like(d[2], d[1], terms,
|
|
1007
|
-
index_key_hits(d[0], terms, q)
|
|
1042
|
+
index_key_hits(d[0], terms, q),
|
|
1043
|
+
entry=d[0],
|
|
1044
|
+
positive_body=self._positive_body)
|
|
1008
1045
|
or (semantic_on() and d[1].get("semantic"))
|
|
1009
1046
|
or d[0].get("path") in _dif] # 图扩散补召回:无词面命中也放行进打分
|
|
1010
1047
|
stat["pre_cap"] = len(hits_r) # 与 T2 同序:截断**前**的候选数
|
|
@@ -1038,7 +1075,9 @@ class MdCGOS(MdCG):
|
|
|
1038
1075
|
# 语义资格(MDCG_SEMANTIC=1):fm.semantic 节点无条件入池
|
|
1039
1076
|
hits = [d for d in docs_all
|
|
1040
1077
|
if self._like(d[2], d[1], terms,
|
|
1041
|
-
index_key_hits(d[0], terms, q)
|
|
1078
|
+
index_key_hits(d[0], terms, q),
|
|
1079
|
+
entry=d[0],
|
|
1080
|
+
positive_body=self._positive_body)
|
|
1042
1081
|
or (semantic_on() and d[1].get("semantic"))]
|
|
1043
1082
|
stat["pre_cap"] = len(hits)
|
|
1044
1083
|
stat["cap"] = GLOBAL_CAP
|
|
@@ -1088,7 +1127,9 @@ class MdCGOS(MdCG):
|
|
|
1088
1127
|
# 语义摘要=检索面(设想核心),否则摘要层只在 LIKE 全空时生效
|
|
1089
1128
|
hits = [d for d in docs
|
|
1090
1129
|
if self._like(d[2], d[1], terms,
|
|
1091
|
-
index_key_hits(d[0], terms, query)
|
|
1130
|
+
index_key_hits(d[0], terms, query),
|
|
1131
|
+
entry=d[0],
|
|
1132
|
+
positive_body=self._positive_body)
|
|
1092
1133
|
or (semantic_on() and d[1].get("semantic"))]
|
|
1093
1134
|
if not hits:
|
|
1094
1135
|
# 兜底池(LIKE 全空 = 无相关度信号):截断依据=importance/created_at
|
|
@@ -1346,8 +1387,10 @@ class MdCGOS(MdCG):
|
|
|
1346
1387
|
out = []
|
|
1347
1388
|
for e, fm, c in self._read_many(entries, stat):
|
|
1348
1389
|
tags = " ".join(str(t) for t in (fm.get("tags") or []))
|
|
1349
|
-
# 负条件行不作召回键(反例命中应由 judge 走 REJECT
|
|
1350
|
-
|
|
1390
|
+
# 负条件行不作召回键(反例命中应由 judge 走 REJECT,不该召回节点)。
|
|
1391
|
+
# N273:走 `_positive_body` 钩子(readcache 启用时 path 键控缓存
|
|
1392
|
+
# 版)——与 `_like` 侧同一条派生物缓存口径,不再是第二处直调。
|
|
1393
|
+
cov = _weighted_coverage(tw, f"{self._positive_body(e, c)} {tags}")
|
|
1351
1394
|
if cov <= 0.0:
|
|
1352
1395
|
continue
|
|
1353
1396
|
e_dom = routing.route_key(None, e.get("tags"))
|
|
@@ -3143,11 +3186,18 @@ class MdCGOS(MdCG):
|
|
|
3143
3186
|
return {"ok": True, "id": nid, "session": session, "layer": layer,
|
|
3144
3187
|
"basis": basis, "tokens": est_tokens(content)}
|
|
3145
3188
|
|
|
3146
|
-
# 生效条件:当 session 传入且为真时仅保留 tags 含 f"session:{session}"
|
|
3189
|
+
# 生效条件:当 session 传入且为真时仅保留 tags 含 f"session:{session}" 的项;恒剔除 lifecycle.is_archived(e) 为真的条目(退役不参与默认注入,判据单点在 lifecycle.py);保留 tags 含 SESSION_TAG 或任一以 "session:" 开头的索引节点,且该索引条目经可见性单点 _readable 判为可见,_read 的 content 为 None 则跳过;按 created_at 降序后返回前 max(1, int(limit or 5)) 条,limit 为假值(含 0/None)按 5 处理;
|
|
3147
3190
|
def _session_notes(self, session=None, limit=5):
|
|
3148
3191
|
"""按时间倒序取会话要点(索引过滤 + 可见性闸 + 惰性回读摘要)。只读,不写盘。"""
|
|
3149
3192
|
out = []
|
|
3150
3193
|
for nid, e in list((self.index.get("nodes") or {}).items()):
|
|
3194
|
+
if lifecycle.is_archived(e):
|
|
3195
|
+
continue # 退役剔除(判据单点 lifecycle.is_archived,
|
|
3196
|
+
# 与 cg 检索面 `_candidates`、stg 面
|
|
3197
|
+
# `_scan_one` 同一份):会话续接包是「把节点
|
|
3198
|
+
# **内容摘要**回给调用方」的注入面,archived
|
|
3199
|
+
# 不再参与默认注入(与 §5.2 退役纪律同口径);
|
|
3200
|
+
# fail-open:缺键/非法值=active 照常。
|
|
3151
3201
|
tags = list(e.get("tags") or [])
|
|
3152
3202
|
if self.SESSION_TAG not in tags and not any(
|
|
3153
3203
|
str(t).startswith("session:") for t in tags):
|
|
@@ -3181,7 +3231,7 @@ class MdCGOS(MdCG):
|
|
|
3181
3231
|
out.sort(key=lambda n: (-n["created_at"], str(n.get("id") or "")))
|
|
3182
3232
|
return out[:max(1, int(limit or 5))]
|
|
3183
3233
|
|
|
3184
|
-
# 生效条件:limit 经 max(1,min(int(limit or 5),50))、budget_tokens 经 max(200,int(budget_tokens or 1200)) 归一后逐段取数(include_state 为真才取 self_state
|
|
3234
|
+
# 生效条件:limit 经 max(1,min(int(limit or 5),50))、budget_tokens 经 max(200,int(budget_tokens or 1200)) 归一后逐段取数(include_state 为真才取 self_state;会话要点段、未解问题段与台账两段(goals/tasks)恒剔除 lifecycle.is_archived 条目——退役不参与默认注入;台账段取全量窗过滤后再截断 `_PACK_ROWS` 条,`tasks.active_total/done_total` 取剔除后的全窗计数),每段异常只把段名追加进 degraded,再由 while 循环按预算交替裁 recent/notes 尾部、任务段最后才裁并置 tasks_truncated。
|
|
3185
3235
|
def session_recall(self, session=None, limit=5, recent_limit=10,
|
|
3186
3236
|
budget_tokens=1200, include_state=True):
|
|
3187
3237
|
"""按需恢复:一次调用返回「可续接的上下文包」(替代 hook 自动注入)。
|
|
@@ -3193,6 +3243,15 @@ class MdCGOS(MdCG):
|
|
|
3193
3243
|
任务段(2026-09-16 新增)是「忘记已实现的工程」的直接解药:新会话开机即见
|
|
3194
3244
|
「还在做的」与「刚做完的」,不必先想到去查。任务属结构层、跨会话稳定,
|
|
3195
3245
|
故**不按 session 过滤**——工程台账跟着工程走,不跟着会话走。
|
|
3246
|
+
|
|
3247
|
+
**退役口径(本包统一)**:本 op 是**注入面**(内容直接回给调用方/进上下文),
|
|
3248
|
+
故四个取数段(notes / goals / tasks[active/done 两清单]/ unresolved;合计
|
|
3249
|
+
五个清单)一律剔除
|
|
3250
|
+
`lifecycle_state=archived`(判据单点 `lifecycle.is_archived`)——「退役不参与
|
|
3251
|
+
默认注入」。`recent` 段是**事件窗口**(非节点)、`self_state` 是只读快照卡,
|
|
3252
|
+
两者不含节点条目,不涉及退役。**管理查询面不受限**:`cg(op=goal, action=list)`
|
|
3253
|
+
与 `cg(op=task, action=list)` 直读台账、archived 期间照常可达(两处不冲突:
|
|
3254
|
+
同一份台账,注入面剔除、管理面直读)。
|
|
3196
3255
|
"""
|
|
3197
3256
|
limit = max(1, min(int(limit or 5), 50))
|
|
3198
3257
|
budget = max(200, int(budget_tokens or 1200))
|
|
@@ -3208,26 +3267,41 @@ class MdCGOS(MdCG):
|
|
|
3208
3267
|
except Exception: # noqa: BLE001
|
|
3209
3268
|
pack["degraded"].append("notes")
|
|
3210
3269
|
# ② 活跃目标(检索定向的默认来源)
|
|
3270
|
+
# 退役剔除(判据单点 lifecycle.is_archived,经 `_retired_by_id` 按 id 取):
|
|
3271
|
+
# 续接包是**注入面**,archived 不参与默认注入(同 ① 与 ④)。取数窗取
|
|
3272
|
+
# **全量**(limit=None)再过滤再截断——否则窗口内的 archived 被剔后不足额,
|
|
3273
|
+
# 本该补位的在役目标补不上(`list_goals` 本就是全表扫,无额外成本)。
|
|
3274
|
+
# 管理查询面 `cg(op=goal, action=list)` **不受限**(不经本函数、直读台账)。
|
|
3211
3275
|
try:
|
|
3212
3276
|
pack["goals"] = [{"id": g["id"], "goal": g["goal"],
|
|
3213
3277
|
"priority": g["priority"]}
|
|
3214
|
-
for g in self.active_goals(limit=
|
|
3278
|
+
for g in self.active_goals(limit=None)
|
|
3279
|
+
if not _retired_by_id(self, g.get("id"))
|
|
3280
|
+
][:_PACK_ROWS]
|
|
3215
3281
|
except Exception: # noqa: BLE001
|
|
3216
3282
|
pack["degraded"].append("goals")
|
|
3217
3283
|
# ②.5 任务台账(structural 层)——见 docstring:不按 session 过滤
|
|
3284
|
+
# 退役剔除(同上,台账段是同一注入面的子段):列表剔 archived、`*_total`
|
|
3285
|
+
# 随之取**剔除后**的全窗计数(列表是它的前 `_PACK_ROWS` 条,两者同源自洽);
|
|
3286
|
+
# 管理查询面 `cg(op=task, action=list)` 仍直读台账、**不受限**。
|
|
3218
3287
|
try:
|
|
3219
3288
|
from . import tasks as _tasks
|
|
3220
|
-
ts = _tasks.session_tasks(self, active_limit=
|
|
3289
|
+
ts = _tasks.session_tasks(self, active_limit=_LEDGER_WINDOW,
|
|
3290
|
+
done_limit=_LEDGER_WINDOW)
|
|
3291
|
+
_act = [t for t in ts["active"]
|
|
3292
|
+
if not _retired_by_id(self, t.get("id"))]
|
|
3293
|
+
_done = [t for t in ts["done"]
|
|
3294
|
+
if not _retired_by_id(self, t.get("id"))]
|
|
3221
3295
|
pack["tasks"] = {
|
|
3222
3296
|
"active": [{"id": t["id"], "name": t["name"], "status": t["status"],
|
|
3223
3297
|
"plan": (t.get("plan") or "")[:300],
|
|
3224
3298
|
"updated_at": t.get("updated_at")}
|
|
3225
|
-
for t in
|
|
3299
|
+
for t in _act[:_PACK_ROWS]],
|
|
3226
3300
|
"done": [{"id": t["id"], "name": t["name"], "status": t["status"],
|
|
3227
3301
|
"result": (t.get("result") or "")[:300],
|
|
3228
3302
|
"updated_at": t.get("updated_at")}
|
|
3229
|
-
for t in
|
|
3230
|
-
"active_total":
|
|
3303
|
+
for t in _done[:_PACK_ROWS]],
|
|
3304
|
+
"active_total": len(_act), "done_total": len(_done)}
|
|
3231
3305
|
except Exception: # noqa: BLE001
|
|
3232
3306
|
pack["degraded"].append("tasks")
|
|
3233
3307
|
# ③ 近期事件(原始滚动窗口)
|
|
@@ -3243,6 +3317,11 @@ class MdCGOS(MdCG):
|
|
|
3243
3317
|
for nid, e in list((self.index.get("nodes") or {}).items()):
|
|
3244
3318
|
if e.get("layer") != "unresolved":
|
|
3245
3319
|
continue
|
|
3320
|
+
if lifecycle.is_archived(e):
|
|
3321
|
+
continue # 退役剔除(同 ① 会话要点:本条是续接包里
|
|
3322
|
+
# 「未解问题正文片段回给调用方」的第二处注入
|
|
3323
|
+
# 子面,判据仍是 lifecycle.is_archived 单点;
|
|
3324
|
+
# fail-open 同上)
|
|
3246
3325
|
# N211(2026-09-28,本族第二出口,原树内并号 N209 按 v24 裁定改判):与 ① 会话要点同根——此处也
|
|
3247
3326
|
# 是「只按 layer 过滤 → 回读正文 → 抽出 `# 问题:`」的直读出口,
|
|
3248
3327
|
# 无 _readable。实测:restricted 档未解问题的正文经 session_recall
|
|
@@ -4416,9 +4495,15 @@ class MdCGOS(MdCG):
|
|
|
4416
4495
|
def check_consistency(self, content, layer=None, condition_space=None,
|
|
4417
4496
|
non_applicable_conditions=None, tags=None,
|
|
4418
4497
|
exclude=None, limit=consistency.MAX_SCAN,
|
|
4419
|
-
depth=consistency.MAX_DEPTH, auto_flywheel=False
|
|
4498
|
+
depth=consistency.MAX_DEPTH, auto_flywheel=False,
|
|
4499
|
+
log_write=True):
|
|
4420
4500
|
"""不落盘地预检一条待写内容是否与既有节点/纪律冲突(三级决策)。
|
|
4421
4501
|
|
|
4502
|
+
log_write(路线 C,2026-10-05,透传 consistency.check 同名参数):
|
|
4503
|
+
缺省 True=原行为(落 `_consistency.jsonl` 台账);**只读消费面**
|
|
4504
|
+
(auditview 证据审计)传 False——判定照常返回、台账不写(「不落盘
|
|
4505
|
+
预检」承诺的补全:既有 log 是无条件写,只读面消费会变成隐式写)。
|
|
4506
|
+
|
|
4422
4507
|
对齐《智能的公理化基石》§十一(情绪=信息差二阶变化,独立不参与信任)、
|
|
4423
4508
|
条件论「反题」(预测与事实冲突)、:273(递归受深度/节点/循环/增益门槛约束)。
|
|
4424
4509
|
|
|
@@ -4436,7 +4521,7 @@ class MdCGOS(MdCG):
|
|
|
4436
4521
|
if not _is_null_condition(x)],
|
|
4437
4522
|
tags=tags,
|
|
4438
4523
|
exclude=exclude, limit=limit, depth=depth,
|
|
4439
|
-
auto_flywheel=auto_flywheel)
|
|
4524
|
+
auto_flywheel=auto_flywheel, log_write=log_write)
|
|
4440
4525
|
|
|
4441
4526
|
# 生效条件:当 limit 传入时,以 limit(默认 100)调用 consistency.history 并返回其结果;本函数不改变 limit;
|
|
4442
4527
|
def consistency_history(self, limit=100):
|
|
@@ -5103,8 +5188,8 @@ class MdCGSecure(MdCGOS):
|
|
|
5103
5188
|
def _neg_coverage(self, terms):
|
|
5104
5189
|
return [e for e in super()._neg_coverage(terms) if self._readable(e)]
|
|
5105
5190
|
|
|
5106
|
-
# 生效条件:node_id 在 self.index["nodes"] 中存在且 self._readable(e) 为假时返回 None,否则转 super().get(node_id);索引缺该条目时**先做代际探活重载再判可见性**(N196:索引缺条目 ≡ 本进程陈旧,不得据以跳过读隔离),重载后仍无条目才回落 super().get 的 not_found 语义;super().get 返回真值节点后用**同一次读取所得的 frontmatter**(sensitivity/session)再判一次可见性,为假即返回 None(N213:命中陈旧条目的路径不得以旧快照当判据、以新盘面当正文);
|
|
5107
|
-
def get(self, node_id: str):
|
|
5191
|
+
# 生效条件:probe 为真(缺省,行为与改动前逐位一致)时,索引缺该条目才做代际探活重载(N196)且 super().get 照旧探活;probe=False 时两处探活一并跳过(N276:调用方已在本批读之前探过一次,批量循环内的逐节点读不再各自重探);其余判据与 probe 无关:node_id 在 self.index["nodes"] 中存在且 self._readable(e) 为假时返回 None,否则转 super().get(node_id, probe=probe);索引缺该条目时**先做代际探活重载再判可见性**(N196:索引缺条目 ≡ 本进程陈旧,不得据以跳过读隔离),重载后仍无条目才回落 super().get 的 not_found 语义;super().get 返回真值节点后用**同一次读取所得的 frontmatter**(sensitivity/session)再判一次可见性,为假即返回 None(N213:命中陈旧条目的路径不得以旧快照当判据、以新盘面当正文);
|
|
5192
|
+
def get(self, node_id: str, probe: bool = True):
|
|
5108
5193
|
e = self.index["nodes"].get(node_id)
|
|
5109
5194
|
if e is None:
|
|
5110
5195
|
# N196(2026-09-28):索引缺条目**不**等于「节点不存在」——本进程
|
|
@@ -5114,11 +5199,14 @@ class MdCGSecure(MdCGOS):
|
|
|
5114
5199
|
# 第二次读才归 None,因为那时条目已随重载进入索引)。先探活重载
|
|
5115
5200
|
# 再判可见性;真不存在时 e 仍为 None,super().get 照旧返回 None。
|
|
5116
5201
|
# 成本只在**未命中**路径(一次 stat),命中路径零变化。
|
|
5117
|
-
|
|
5202
|
+
# N276:probe=False(批内单探针)时本探活同跳——语义窗口见
|
|
5203
|
+
# forgetting.redundancy 同注(本批读期间他进程写入不探知)。
|
|
5204
|
+
if probe:
|
|
5205
|
+
self._maybe_reload_index()
|
|
5118
5206
|
e = self.index["nodes"].get(node_id)
|
|
5119
5207
|
if e is not None and not self._readable(e):
|
|
5120
5208
|
return None # 读隔离:不可见即不存在
|
|
5121
|
-
node = super().get(node_id)
|
|
5209
|
+
node = super().get(node_id, probe=probe)
|
|
5122
5210
|
if node is None:
|
|
5123
5211
|
return None
|
|
5124
5212
|
# N213(2026-09-28):命中陈旧条目的路径此前**零探活**——可见性判据取自
|
package/md_cg/nodefile.py
CHANGED
|
@@ -123,6 +123,22 @@ REPRODUCIBLE_BASIS = ("compiler", "test", "measurement", "formal_proof", "data")
|
|
|
123
123
|
#: 来源一致性档:文科断言可用(来源表述一致即可)
|
|
124
124
|
CONSISTENCY_BASIS = ("textbook", "public_kb")
|
|
125
125
|
|
|
126
|
+
# ---- 多主体世界模型对齐(2026-10-05):检验强度字段真源 ----------------------------
|
|
127
|
+
# 「检验强度」分级(过程追踪过程 tracing 方法,见对齐评估 v0.1 §2 L1):一条断言
|
|
128
|
+
# 的**证据能带走多少裁决权重**——hoop(必要证据:不满足即证伪)/ smoking_gun
|
|
129
|
+
# (决定性:单独即可确立)/ doubly_decisive(同时排除竞争假设)。与
|
|
130
|
+
# `verification_basis`(来源**类型**)正交:一个说「凭什么类别的证据」,一个说
|
|
131
|
+
# 「证据的裁决力有多强」。缺省 None=未声明(**不落 fm 键**,存量零迁移、读取侧
|
|
132
|
+
# `.get()` 回落);显式传入时校验闭集(与 VERIFICATION_BASIS 同风格)。
|
|
133
|
+
CHECK_STRENGTHS = ("hoop", "smoking_gun", "doubly_decisive")
|
|
134
|
+
CHECK_STRENGTH_FIELD = "check_strength"
|
|
135
|
+
|
|
136
|
+
#: 幽灵引用标记字段(A2,多主体世界模型对齐 v0.1 §2 L1「转引不得升级」):
|
|
137
|
+
#: 写入链检测到的**无可解析出处**的回指短语清单(短语层),落 fm 供后续
|
|
138
|
+
#: 裁决/检索看见。**正文属性**:每次写入按当次检测重算、不继承(与
|
|
139
|
+
#: check_strength 的声明继承语义相反——正文变了检测就该变)。
|
|
140
|
+
UNCERTAIN_REFS_FIELD = "uncertain_refs"
|
|
141
|
+
|
|
126
142
|
# ---- 裁定 D(2026-09-19):可验证记忆单元的**字段名真源** --------------------------
|
|
127
143
|
# 「子功能」的契约角色是**依赖 dependency**(见 CCG_CONTRACT_ROLES),其落字段即
|
|
128
144
|
# `depends_on`——名字与角色对齐(不叫 sub_features,避免同一概念两种写法)。
|
|
@@ -386,6 +402,48 @@ def ccg_mark_present(content: str, mark: str) -> bool:
|
|
|
386
402
|
return False
|
|
387
403
|
|
|
388
404
|
|
|
405
|
+
# 生效条件:content 为真时逐行扫描——命中 marks 中任一要素的 CCG 标题行(判据单点 _ccg_heading_rest,`^#\s*<要素>` 冒号可有可无)即整段剥除:行内带值(`# 生效条件:v`/前缀式)只剥该行,裸标题连同其后首个非空、非标题行(该字段的值行,取值口径同 ccg_field_value)一并剥除;其余原行原样保留(含缩进)以 "\n" 连接返回;content 假值按空串返回。
|
|
406
|
+
def _strip_ccg_segments(content, marks=CCG_MARKS):
|
|
407
|
+
"""剥除 CCG 声明**整段字段**后的文本——剥除算法单点。
|
|
408
|
+
|
|
409
|
+
单点动因(N238 同族):六要素允许无冒号形态(`# 不适用条件` + 换行 + 值行),
|
|
410
|
+
**值行才是内容本体**;只剥标题行会把该字段的正文留在正文里——同一条内容写成
|
|
411
|
+
带冒号时剥净、写成无冒号时残留,两种写法给出两种结论(该缺陷在
|
|
412
|
+
`consistency._body_text` 已按 N238 收口,本函数把**剥除算法本身**也收成一份,
|
|
413
|
+
防下游再各写一份循环而漂移)。调用方:`positive_body`(只剥不适用条件)与
|
|
414
|
+
`consistency._body_text`(剥全部六要素)。
|
|
415
|
+
|
|
416
|
+
判据一律走单点(`_ccg_heading_rest`,与写入闸门 data/policy.json 同一行语义):
|
|
417
|
+
缩进标题与二级标题不构成「已声明」,与 `ccg_mark_present` 同边界。
|
|
418
|
+
"""
|
|
419
|
+
lines = (content or "").split("\n")
|
|
420
|
+
out = []
|
|
421
|
+
i, n = 0, len(lines)
|
|
422
|
+
while i < n:
|
|
423
|
+
rest = None
|
|
424
|
+
for mark in marks:
|
|
425
|
+
rest = _ccg_heading_rest(lines[i], mark)
|
|
426
|
+
if rest is not None:
|
|
427
|
+
break
|
|
428
|
+
if rest is None:
|
|
429
|
+
out.append(lines[i])
|
|
430
|
+
i += 1
|
|
431
|
+
continue
|
|
432
|
+
i += 1
|
|
433
|
+
if rest.strip():
|
|
434
|
+
continue # 行内已带值(冒号式 `# 字段:v` / 前缀式)→ 只剥该行
|
|
435
|
+
while i < n: # 裸标题:其后首个非空、非标题行是值行,同剥
|
|
436
|
+
t = lines[i].strip()
|
|
437
|
+
if not t:
|
|
438
|
+
i += 1
|
|
439
|
+
continue
|
|
440
|
+
if t.startswith("#"):
|
|
441
|
+
break # 下一个标题 ⇒ 本字段值为空,不消费
|
|
442
|
+
i += 1
|
|
443
|
+
break
|
|
444
|
+
return "\n".join(out)
|
|
445
|
+
|
|
446
|
+
|
|
389
447
|
# 生效条件:content 中出现 "# {mark}:" 或 "# {mark}:"(中/英文冒号)或仅 "# {mark}" 标题行即把该 mark 计入 present 与 required_present;complete 为 required_present 覆盖全部 CCG_REQUIRED、all_present 为 present 覆盖全部 CCG_MARKS,ratio = len(required_present)/len(CCG_REQUIRED),四键连同两个清单一起返回。
|
|
390
448
|
def ccg_completeness(content: str) -> dict:
|
|
391
449
|
"""CCG 要素齐全度——白箱可审计性的量化指标。
|
|
@@ -441,39 +499,45 @@ def is_placeholder_text(value) -> bool:
|
|
|
441
499
|
return any(m in s for m in PLACEHOLDER_MARKERS)
|
|
442
500
|
|
|
443
501
|
|
|
444
|
-
# 生效条件:content
|
|
502
|
+
# 生效条件:content 中存在 NEG_FIELD("不适用条件")的 CCG 标题行(判据单点 ccg_mark_present,`^#\s*不适用条件`,冒号可有可无,与写入闸门同一行语义)时返回 True,否则 False。
|
|
445
503
|
def has_non_applicable(content: str) -> bool:
|
|
446
504
|
"""是否声明了不适用条件——REJECT 路径成立的必要条件。
|
|
447
505
|
|
|
448
506
|
没有不适用条件的节点在白箱下不能 REJECT(无法证明「不适用」),
|
|
449
507
|
只能 ACCEPT 或 BLINDSPOT。这是第 1 篇第 10 章从 28%→88% 的关键。
|
|
508
|
+
|
|
509
|
+
A3(N238 同族残面):判据单点 = `ccg_mark_present`——本函数原先只认
|
|
510
|
+
「`# 不适用条件:`/`# 不适用条件:`」两种**带冒号**的字面量,无冒号形态
|
|
511
|
+
(`# 不适用条件` + 换行 + 值行)被判成「没声明」:同一条正文写不写冒号
|
|
512
|
+
给出两种结论,而「冒号可有可无」已由单点定案(test_ccg_form_parity ①-⑦)。
|
|
513
|
+
消费面:索引条目 `has_neg_conditions`(mdcg `_entry` / rebuild / `_stage`),
|
|
514
|
+
进而 `export`/`insight`/`sustain`/`predict` 的统计与边界读数。
|
|
450
515
|
"""
|
|
451
|
-
return
|
|
516
|
+
return ccg_mark_present(content, NEG_FIELD)
|
|
452
517
|
|
|
453
518
|
|
|
454
519
|
#: 负条件字段名——它是**反例声明**,不是召回键
|
|
455
520
|
NEG_FIELD = "不适用条件"
|
|
456
521
|
|
|
457
522
|
|
|
458
|
-
# 生效条件:content 为 None 时按 ""
|
|
523
|
+
# 生效条件:content 为 None 时按 "" 处理;逐行剥除 NEG_FIELD 的整段 CCG 声明(剥除算法单点 _strip_ccg_segments——行内带值只剥该行,裸标题连同其后首个非空、非标题的值行一并剥除),其余行原样保留(含原缩进),返回保留行的 "\n".join。
|
|
459
524
|
def positive_body(content: str) -> str:
|
|
460
|
-
"""剥离 `#
|
|
525
|
+
"""剥离 `# 不适用条件` 声明段后的正文——负条件不作召回键。
|
|
461
526
|
|
|
462
527
|
不适用条件声明的是「什么时候**不**适用」,其触发词是反例。一旦把它当召回
|
|
463
528
|
键,查询命中反例时节点反而被召回——**恰好在它不该适用的地方被召回**,属实
|
|
464
529
|
质性错误。反例的正确去向是 `judge_qualification` 的 REJECT 路径(读
|
|
465
530
|
`frontmatter.non_applicable_conditions`),而不是召回。
|
|
466
531
|
|
|
467
|
-
只剥离真正的 CCG
|
|
468
|
-
|
|
532
|
+
只剥离真正的 CCG 行(判据单点 `_ccg_heading_rest`:`# <字段>` 标题前缀、
|
|
533
|
+
冒号可有可无),避免误伤正文里恰好以「不适用条件」开头的普通句子。
|
|
534
|
+
|
|
535
|
+
A3(N238 同族残面):剥的必须是**整段字段**——无冒号形态(`# 不适用条件` +
|
|
536
|
+
换行 + 值行)原先只剥标题行,值行(内容本体)残留 ⇒ 反例词面照样进召回键
|
|
537
|
+
(`MdCG._like` 实测命中),与带冒号写法的行为相反。剥除算法收在单点
|
|
538
|
+
`_strip_ccg_segments`(与 `consistency._body_text` 共用一份循环)。
|
|
469
539
|
"""
|
|
470
|
-
|
|
471
|
-
for ln in (content or "").split("\n"):
|
|
472
|
-
s = ln.strip()
|
|
473
|
-
if s.startswith("#") and s.lstrip("#").strip().startswith(NEG_FIELD):
|
|
474
|
-
continue
|
|
475
|
-
keep.append(ln)
|
|
476
|
-
return "\n".join(keep)
|
|
540
|
+
return _strip_ccg_segments(content, (NEG_FIELD,))
|
|
477
541
|
|
|
478
542
|
|
|
479
543
|
# ---- 条件空间 → 生效条件声明 -------------------------------------------------
|
package/md_cg/readcache.py
CHANGED
|
@@ -25,7 +25,9 @@
|
|
|
25
25
|
2. 缓存**解析产物** `(fm, content)`(benchmark 版只缓存原文,parse 仍逐次),
|
|
26
26
|
**并缓存文档侧检索派生物** `_doc_norm_bigrams`(归一化 bigram——批次 21
|
|
27
27
|
实测本机热点 88% 在此而非 I/O:内容不变则派生物不变,随读缓存常驻;
|
|
28
|
-
Rust `load_docs` 预计算 stripped/db_len
|
|
28
|
+
Rust `load_docs` 预计算 stripped/db_len 同款理论)与 `_positive_body`
|
|
29
|
+
(剥除不适用条件后的召回键正文——N273,8000 池实测 ~102ms/查询,
|
|
30
|
+
与 bigram 同一 path 键控 + 脏集失效口径,两者恒同步);
|
|
29
31
|
3. 进程内一致性边界(与 MdStore 相同的诚实边界):跨进程/外部直接改写
|
|
30
32
|
md 文件不保证可见——认知图的多进程形态(每智能体一进程)各持快照。
|
|
31
33
|
4. **读失败不固化(C-3 / FI-M02 / N134,2026-09-29)**:只接纳「成功」与
|
|
@@ -67,7 +69,7 @@ def direct_read(cg, entry):
|
|
|
67
69
|
return fn(entry)
|
|
68
70
|
|
|
69
71
|
|
|
70
|
-
# 生效条件:cg 提供 _read_status(MdCG/MdCGSecure 恒有)时按其**三态标签**包装:第三元素为 None(成功 / 终态真缺)者照脏集精确失效口径入缓存,第三元素非 None(瞬时读失败,fsutil.READ_FAIL_TRANSIENT)者**一律不入缓存**(C-3:不得把可重试的读失败以「新鲜」身份固化);cg 无 _read_status(非 MdCG 载体)时回落包装 cg._read,且空结果一律不接纳(无判别面时的保守侧:宁可重读,不可固化可能是瞬时的缺失);cg._doc_norm_bigrams 存在时同款包装其派生物(_score 热点:文档侧归一化 bigram 只依赖 content
|
|
72
|
+
# 生效条件:cg 提供 _read_status(MdCG/MdCGSecure 恒有)时按其**三态标签**包装:第三元素为 None(成功 / 终态真缺)者照脏集精确失效口径入缓存,第三元素非 None(瞬时读失败,fsutil.READ_FAIL_TRANSIENT)者**一律不入缓存**(C-3:不得把可重试的读失败以「新鲜」身份固化);cg 无 _read_status(非 MdCG 载体)时回落包装 cg._read,且空结果一律不接纳(无判别面时的保守侧:宁可重读,不可固化可能是瞬时的缺失);cg._doc_norm_bigrams 存在时同款包装其派生物(_score 热点:文档侧归一化 bigram 只依赖 content,随读缓存一并常驻);cg._positive_body 存在时同款包装其派生物(_like 热点:剥除不适用条件后的正文只依赖 content,N273 与前者同一 path 键控 + 脏集失效口径);包装后 cg._read 与 cg._doc_norm_bigrams/cg._positive_body 走缓存、cg._read_cache/_norm_bigrams_cache/_positive_body_cache 为缓存字典、cg._read_uncached 为**穿透缓存的原始二态 _read**(direct_read 的真源,返回形状与 install 前逐位一致);返回缓存字典。
|
|
71
73
|
def install(cg):
|
|
72
74
|
"""把 `cg._read`(与派生物钩子)包成**脏集精确失效**的常驻缓存。
|
|
73
75
|
|
|
@@ -189,14 +191,37 @@ def install(cg):
|
|
|
189
191
|
|
|
190
192
|
cg._doc_norm_bigrams = _cached_nb
|
|
191
193
|
cg._norm_bigrams_cache = nb_cache
|
|
194
|
+
|
|
195
|
+
# N273(第 32 轮性能面):`_positive_body` 派生物同款缓存层——同 `entry`
|
|
196
|
+
# path 键、同 `_fresh` 脏集判据、同装载/失效时机(与 `_doc_norm_bigrams`
|
|
197
|
+
# 一字不差的同形结构,故两者命中率与失效行为恒同步)。修前 `_like` 每
|
|
198
|
+
# 查询对每个候选节点直调 `nodefile.positive_body`(逐行扫 CCG 声明段),
|
|
199
|
+
# 8000 池实测每次查询 ~102ms(占热态查询 ~47%)——它却是与 bigram 同
|
|
200
|
+
# 性质的纯函数(只依赖 content),缓存不对称在此收口。
|
|
201
|
+
pb_cache = {}
|
|
202
|
+
if hasattr(cg, "_positive_body"):
|
|
203
|
+
orig_pb = cg._positive_body
|
|
204
|
+
|
|
205
|
+
def _cached_pb(entry, content):
|
|
206
|
+
p = entry["path"]
|
|
207
|
+
gen = getattr(cg._dirty, "write_gen", len(cg._dirty))
|
|
208
|
+
hit = pb_cache.get(p)
|
|
209
|
+
if hit is not None and _fresh(p, hit):
|
|
210
|
+
return hit[1]
|
|
211
|
+
val = orig_pb(entry, content)
|
|
212
|
+
pb_cache[p] = (gen, val)
|
|
213
|
+
return val
|
|
214
|
+
|
|
215
|
+
cg._positive_body = _cached_pb
|
|
216
|
+
cg._positive_body_cache = pb_cache
|
|
192
217
|
return cache
|
|
193
218
|
|
|
194
219
|
|
|
195
|
-
# 生效条件:cg._read_cache 与 cg.
|
|
220
|
+
# 生效条件:cg._read_cache、cg._norm_bigrams_cache 与 cg._positive_body_cache 均清空(写侧显式兜底;哨兵之外的强制手段),返回清空的条目总数;无缓存时返回 0。
|
|
196
221
|
def clear(cg) -> int:
|
|
197
222
|
"""强制清空(外部批量改写文件后可手动调;正常写路径无需——哨兵自动失效)。"""
|
|
198
223
|
n = 0
|
|
199
|
-
for attr in ("_read_cache", "_norm_bigrams_cache"):
|
|
224
|
+
for attr in ("_read_cache", "_norm_bigrams_cache", "_positive_body_cache"):
|
|
200
225
|
c = getattr(cg, attr, None)
|
|
201
226
|
if c:
|
|
202
227
|
n += len(c)
|
package/md_cg/selfreport.py
CHANGED
|
@@ -126,10 +126,19 @@ def read_all() -> dict:
|
|
|
126
126
|
return out
|
|
127
127
|
|
|
128
128
|
|
|
129
|
-
# 生效条件:pids 为可迭代的 pid 集合(通常是「当前进程表中仍在的 md_cg
|
|
130
|
-
def purge(pids) -> int:
|
|
131
|
-
"""清掉不属于「仍在的进程」的自报文件(防目录随重启次数膨胀)。
|
|
129
|
+
# 生效条件:pids 为可迭代的 pid 集合(通常是「当前进程表中仍在的 md_cg 进程」),allow_empty 为破坏性动作的显式开关;keep 非空时删除自报目录中 pid 不在该集合内的 *.json 与遗留 *.tmp 并返回删除条数;keep 为**空集**且 allow_empty=False(默认)时一律不删并返回 0——空集既可能是「在役进程真的全部退出」也可能是「探测失败/未经校验」,两者不可分,故清空须显式开启;目录不存在或删除失败逐项吞掉,不抛。
|
|
130
|
+
def purge(pids, *, allow_empty: bool = False) -> int:
|
|
131
|
+
"""清掉不属于「仍在的进程」的自报文件(防目录随重启次数膨胀)。
|
|
132
|
+
|
|
133
|
+
N255(2026-10-05):keep 为空集时**默认不删任何东西**(fail-closed)——空集既可能来自
|
|
134
|
+
「在役进程确已全部退出」,也可能来自**一次失败/未经校验的探测**。后者在本仓实证过:
|
|
135
|
+
`scripts/mdcg_stale_servers.py` 的 scan() 尾部曾无条件调用 `purge([])`(探测失败 →
|
|
136
|
+
pids 为空),把自报目录下全部 *.json 一次删光(沙盒 3 件预置全灭)。确要清空时,由
|
|
137
|
+
**探测已成功**的调用方显式传 `allow_empty=True`(见该脚本的 purge_reports())。
|
|
138
|
+
"""
|
|
132
139
|
keep = {int(p) for p in (pids or ())}
|
|
140
|
+
if not keep and not allow_empty:
|
|
141
|
+
return 0
|
|
133
142
|
n = 0
|
|
134
143
|
try:
|
|
135
144
|
names = os.listdir(SELF_REPORT_DIR)
|