@furongjun1999/dsh-memory 0.6.1 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/README.md +49 -18
  2. package/docs/README.md +1 -0
  3. 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 +223 -0
  4. 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 +340 -0
  5. 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 +437 -0
  6. 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 +488 -0
  7. 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 +428 -0
  8. package/docs/eval/issue50_/350/257/273/351/235/242/344/277/235/346/212/244/345/217/252/350/256/244/346/230/276/345/274/217/346/235/245/346/272/220_/344/277/256/345/244/215/350/256/260/345/275/225_v1.0.md +271 -0
  9. 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 +306 -0
  10. 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 +58 -0
  11. 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 +360 -0
  12. package/docs/eval//344/270/211/346/241/243/350/207/252/346/262/273_/346/255/245/351/252/244/342/221/241/346/241/243/344/275/215/345/215/225/344/270/200/345/205/245/345/217/243_/350/220/275/347/240/201/350/256/260/345/275/225_v1.0.md +651 -0
  13. 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 +439 -0
  14. 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 +1337 -0
  15. package/docs/eval//344/270/211/346/241/243/350/207/252/346/262/273_/346/255/245/351/252/244/342/221/244/346/224/266/345/256/230/344/270/216/345/205/250/351/223/276/351/252/214/346/224/266_/350/220/275/347/240/201/350/256/260/345/275/225_v1.0.md +1817 -0
  16. 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 +460 -0
  17. 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 +97 -0
  18. 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 +66 -0
  19. 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 +458 -0
  20. 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 +250 -0
  21. package/docs/hive//346/243/200/347/264/242/347/256/227/346/263/225/345/217/243/345/276/204/345/257/271/347/205/247_v0.1.md +136 -11
  22. 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 +32 -2
  23. package/docs/mdcg/README/350/257/246/347/273/206/347/211/210_v0.4.10.md +88 -0
  24. package/docs/mdcg//345/212/237/350/203/275/350/260/203/347/224/250/346/230/240/345/260/204/350/241/250_v0.1.md +40 -40
  25. package/docs/mdcg//345/217/221/345/270/203/351/227/250/347/246/201/351/223/276_v0.1.md +47 -11
  26. 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 +183 -0
  27. package/docs/plans/stg/346/235/241/344/273/266/345/214/226/344/270/216/347/273/223/346/236/204/347/264/242/345/274/225_/350/256/276/350/256/241_v0.1.md +124 -0
  28. 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 +547 -0
  29. package/docs/plans//350/256/260/345/277/206/350/207/252/345/244/204/347/220/206/344/270/211/346/241/243/350/207/252/346/262/273_/350/256/276/350/256/241_v0.2.md +207 -0
  30. package/md_cg/admission.py +718 -0
  31. package/md_cg/autonomy_modes.py +642 -0
  32. package/md_cg/bench_e2e_locomo_qa.py +11 -4
  33. package/md_cg/chain.py +47 -0
  34. package/md_cg/consistency.py +133 -8
  35. package/md_cg/forgetting.py +38 -6
  36. package/md_cg/freshness.py +527 -0
  37. package/md_cg/generation.py +409 -0
  38. package/md_cg/hotcache.py +4 -1
  39. package/md_cg/lifecycle.py +30 -2
  40. package/md_cg/mcp_server.py +191 -26
  41. package/md_cg/mdcg.py +594 -39
  42. package/md_cg/mdcos.py +869 -38
  43. package/md_cg/nodefile.py +74 -1
  44. package/md_cg/protect.py +79 -4
  45. package/md_cg/provenance.py +1 -1
  46. package/md_cg/review_cli.py +31 -2
  47. package/md_cg/rollback.py +411 -0
  48. package/md_cg/rollback_cli.py +104 -0
  49. package/md_cg/semantic/canonical.py +22 -0
  50. package/md_cg/semantic/unify.py +73 -22
  51. package/md_cg/semantic/unify_fixture.json +25 -0
  52. package/md_cg/sleep.py +1297 -0
  53. package/md_cg/stg.py +400 -50
  54. package/md_cg/stgidx.py +281 -0
  55. package/md_cg/sustain.py +146 -9
  56. package/md_cg/test_auto_defaults.py +424 -0
  57. package/md_cg/test_autonomy_admission.py +1098 -0
  58. package/md_cg/test_autonomy_modes.py +1972 -0
  59. package/md_cg/test_b1_auto_id_multiproc.py +7 -0
  60. package/md_cg/test_b1b2_write_face.py +7 -0
  61. package/md_cg/test_b3_merge_keeps_content.py +7 -0
  62. package/md_cg/test_boundary_hit.py +410 -0
  63. package/md_cg/test_cons200_scan_selection.py +791 -0
  64. package/md_cg/test_en_pipeline.py +22 -13
  65. package/md_cg/test_generation_guard.py +352 -0
  66. package/md_cg/test_h4_sustain_snapshot.py +14 -4
  67. package/md_cg/test_i50a_half_dup_defer.py +408 -0
  68. package/md_cg/test_i50b_defer_to_review_queue.py +545 -0
  69. package/md_cg/test_i50c_meta_passthrough.py +608 -0
  70. package/md_cg/test_i50d_importance_source.py +531 -0
  71. package/md_cg/test_i50e_readside_protection.py +656 -0
  72. package/md_cg/test_issue39_utf8_stdio.py +9 -1
  73. package/md_cg/test_issue52_scan_condition_first.py +677 -0
  74. package/md_cg/test_linkref.py +7 -0
  75. package/md_cg/test_mode_parity.py +1393 -0
  76. package/md_cg/test_mutation_rollback.py +805 -0
  77. package/md_cg/test_n204_n205_n226_n227_n228_n229_exit_gates.py +1 -1
  78. package/md_cg/test_n212_n213_n224_generation_gates.py +14 -8
  79. package/md_cg/test_n214_n215_n221_n222_write_face_gates.py +7 -0
  80. package/md_cg/test_n230_dirty_replay.py +375 -0
  81. package/md_cg/test_p2_mcp.py +8 -0
  82. package/md_cg/test_p2_six_elements.py +463 -0
  83. package/md_cg/test_p3_legacy_closure.py +433 -0
  84. package/md_cg/test_p4_freshness.py +680 -0
  85. package/md_cg/test_p8_subgraph_chain.py +14 -1
  86. package/md_cg/test_p9_forget_protect.py +7 -0
  87. package/md_cg/test_p9c_dedup_hints.py +7 -0
  88. package/md_cg/test_policy_required_ccg.py +5 -1
  89. package/md_cg/test_protocol.py +7 -0
  90. package/md_cg/test_rank_parity_score_mode.py +6 -0
  91. package/md_cg/test_semantic_canonical.py +5 -3
  92. package/md_cg/test_sleep.py +611 -0
  93. package/md_cg/test_sleep_p1.py +784 -0
  94. package/md_cg/test_stgidx_index_parity.py +1020 -0
  95. package/md_cg/test_time_core_lint.py +968 -0
  96. package/md_cg/test_unify_default_off.py +701 -0
  97. package/md_cg/test_unify_scope.py +182 -0
  98. package/md_cg/test_writelimit.py +36 -9
  99. package/md_cg/test_writepipe.py +5 -2
  100. package/md_cg/weights.py +15 -1
  101. package/md_cg/whitebox_kb/aeis_core/time_core.py +8 -0
  102. package/md_cg/writepipe.py +101 -2
  103. package/package.json +3 -2
  104. package/skills/plugin.json +1 -1
  105. package/utf8_boot.py +237 -0
@@ -0,0 +1,207 @@
1
+ # 灵枢记忆自处理三档自治 · 设计 v0.2(已签收 · 冻结)
2
+
3
+ > **状态:已签收(规格冻结)**——五条裁定已于 2026-10-01 由使用者签收(§〇.2)
4
+ > **本稿不改一行代码、不动任何数据**;落码属下一阶段,需另行开工(§十三)
5
+ > **前置**:issue #50 的两项修复(§八)——不落地则「变更确认」档在用户通道上没有输入
6
+ > **相邻**:`docs/plans/睡眠与自迭代_功能优化设计_v0.4.md` 的九步台账是本设计「计划模式」的**现存形态**
7
+
8
+ ## 〇 一句话
9
+
10
+ 把「**灵枢自己怎么处理自己的记忆**」收成三档可选的自治态度(计划 / 变更确认 / 完全访问),
11
+ **把确认覆盖面补齐到删除·改写·合并**(今天恰好缺这三样),
12
+ 并给出**升档的机检准入读数**——先证明判断可信,再放权。
13
+
14
+ ## 〇.1 三档定义(使用者原话,不得改写)
15
+
16
+ | 档 | 定义(原话) |
17
+ |---|---|
18
+ | **计划模式** | 严格自己制定计划,让灵枢按照计划处理记忆。 |
19
+ | **变更确认** | 对记忆进行变更(删除、改写、合并)时进行确认。 |
20
+ | **完全访问** | 完全交给灵枢自己处理,不过问用户。 |
21
+
22
+ **主客关系**(同日裁定,为权重依据):**灵枢本体是那个"学生"**,使用者与编排方是它的**教师与家长**;
23
+ 其他使用者可能取「朋友」(想少写作业)或「老板」(只求产出)的立场——
24
+ **纪律与判据面上判断权在我们,只在易用性与产出面上采纳后两类立场**。
25
+
26
+ ## 〇.2 五条裁定(使用者 2026-10-01 签收,本稿据此冻结)
27
+
28
+ | # | 裁决点 | 裁定 |
29
+ |---|---|---|
30
+ | ① | **默认档位** | **变更确认** |
31
+ | ② | **变更确认的覆盖面** | **改写 · 删除 · 合并**(三类全含) |
32
+ | ③ | **准入读数的时间窗** | **长期记忆 30 天 / 短期记忆 3 天**(映射见 §七) |
33
+ | ④ | **确认队列** | **复用既有审核队列**(不新建第二套) |
34
+ | ⑤ | **升降档** | **升档 = 计划式确认**(必须写计划、由用户确认);**降档 = 自动执行** |
35
+
36
+ > 口径说明(编排侧读法,若有偏差以使用者为准):第⑤条的"升档人工"其**具体形态就是把升档这件事走一遍计划模式**——先写一份计划(它拿更高自治要做什么、在什么范围内、看什么读数),交使用者确认后才升;降档不需要任何人点头,读数跌破门槛即自动回落并告警。
37
+
38
+ ## 一 对象面:记忆变更动作的完整分类(一手证据,非推断)
39
+
40
+ 「确认什么」必须先穷举「能改什么」。按落点普查(只读 grep,非测试文件)分五类:
41
+
42
+ | 类 | 动作 | 落点(仓内相对路径:行) | 可回滚 | 今天有无前置确认 |
43
+ |---|---|---|---|---|
44
+ | **A** | 新增节点 | 门控写入 `ACCEPT` → `MdCG.add`;不入库的出口是提案 | 新增天然可回滚(软删) | 无(入提案队列仅在非 ACCEPT 出口) |
45
+ | **B** | **合并**(新内容并入既有节点) | `forgetting.reinforce`(`md_cg/forgetting.py:456`,写回在 `:524`)+ `writelimit.converge_into` | 部分:前像无快照;聚合行可按标记剥离 | **无**(普通节点);受保护节点要 `override`+快照 |
46
+ | **C** | **改写**(既有节点就地改) | 同 id 覆写(`cg(op=write, node_id=…)`)=改写;`_write_node` 直调点:`backfill`×8、`consolidate:642/848/891`、`ccgc:837/926`、`crosscheck:675/971`、`evolution:407`;**层迁移 + 删旧文件** `consolidate.py:891/893`;CCG 行 upsert | 否(除受保护节点) | **无** |
47
+ | **D** | **删除** | 软删(节点移入 `trash/`+删除清单,可审计,`md_cg/mcp_server.py:324`);**丢弃**(`forgetting.assess` 的丢弃分支 → 只留痕不落节点,`forgetting.py:411` `record_drop`);断面裁剪 `forgetting.py:756 _prune`;去污染实改(缺省关) | 软删是;丢弃否(仅日志留全文);裁剪否 | **无** |
48
+ | **E** | 权重与生命周期 | `freshness.recalc(..., apply=False)`(`md_cg/freshness.py:302`)、`weights`、`lifecycle.stamp`(`md_cg/lifecycle.py:52` 四态单向降级轴) | 是:`freshness.rollback`(`:428`)及各模块 `rollback` | 无(但改的是分数,破坏性最低) |
49
+
50
+ ## 二 现状:确认覆盖面与破坏性强度**倒置**
51
+
52
+ 1. **确认形态只长在批量维护上**:`consolidate`/`crosscheck`/`ccgc`/`trust`/`autonomy` 全是"**先出报表、再落盘**"(落盘参数 `apply` 缺省为假;如 `consolidate.py:970/1130/1411`、`crosscheck.py:738`)。这是设计对的地方。
53
+ 2. **热写入路径上破坏性最强的三个动作没有确认**:合并与改写由 `forgetting.reinforce` **就地把既有节点改写**(改 frontmatter + 追加聚合行),丢弃只留痕不落节点;对**普通节点**全无前置确认,只有 importance ≥ 0.70 的受保护节点要 `override` + 快照(`protect.py:32` → `_protected_history/<id>/<时间戳>.md` + `_protected_audit.jsonl`)。
54
+ 3. **热路径上唯一形似确认的机制是 `DEFER → 审核队列`**(`writepipe.py:260/325` `moved_to="review_queue"`、`mdcos.propose` `mdcos.py:2016/4284`,裁决通道 `scripts/review_cli.py` 的 accept/reject/edit/merge/noop)——但它**只覆盖 A(新增提案),不覆盖对既有记忆的 B/C/D**。
55
+ 4. **缺省档位事实上已经是「完全访问」**:自愈开、自整理开、自演化关、去污染实改关(`md_cg/sustain.py:88-89`);睡眠合并缺省 `auto`、去污染实改缺省关(`md_cg/sleep.py:84` 表)。它已经在跑,而且跑在判断力最弱的那条通道上(§八)。
56
+
57
+ **结论**:**破坏性最强的地方最没有确认,确认形态反而只覆盖批量维护与新增提案。** 本设计的主要工作就是把这个倒置掰回来。
58
+
59
+ ## 三 设计:三档语义 × 动作面(裁决矩阵 · 已冻结)
60
+
61
+ 「允许=自动执行」「确认=先出变更单、经裁定后才落」「禁止=fail-closed 拒并给 hint」。
62
+
63
+ | 动作 | 计划模式 | **变更确认(默认档)** | 完全访问 |
64
+ |---|---|---|---|
65
+ | **A 新增** | 允许(须命中计划中的步骤) | 允许 | 允许 |
66
+ | **B 合并** | 允许(须命中计划步骤) | **需确认** | 允许 |
67
+ | **C 改写** | **需确认** | **需确认** | 允许 |
68
+ | **D 删除** | **需确认** | **需确认** | 允许 |
69
+ | **E 权重/生命周期** | 允许(须命中计划步骤) | 允许(分数类不阻塞) | 允许 |
70
+
71
+ 三条硬约束:
72
+
73
+ - **单一入口**:档位是**一个** env 键(`MDCG_AUTONOMY=plan|confirm|full`,缺省 `confirm`),由**一处**判据函数读取与解释;不得各模块各读一份(沿用 sleep 的 §4.7 "env 表单一真源" 纪律)。
74
+ - **纯加严**:任一档都不得放宽既有判据——档位只在既有裁决**通过之后**决定该动作是"立即落"还是"出变更单",**不参与资格判定**(资格仍归 `forgetting.assess` 与写入闸门)。
75
+ - **计划外零变更**:计划模式下任何未在计划里的变更 = fail-closed 报错(带可执行 hint),不静默跳过。
76
+
77
+ ## 四 变更确认档:**复用既有审核队列(裁定④)**
78
+
79
+ - **队列复用**:直接复用既有审核队列与裁决通道(提案入口 `mdcos.propose`;裁决 `scripts/review_cli.py` / `cg(op=review, decision=accept|reject|edit|merge|noop)`)。**不新建第二套队列**——两套队列=两套台账、两处口径。
80
+ - **两类条目共用一个队列**,靠 **类型字段**区分:`kind="proposal"`(原有:新写入未获 ACCEPT 的提案)与 `kind="mutation"`(本设计新增:对既有记忆的 B/C/D 变更单)。裁决通道与统计口径共用。
81
+ - **变更单**(每张含):动作类(B/C/D)· 目标节点 id 与路径 · **前像**(可回滚句柄)· **后像**(将要写成的样子)· 影响面(边/索引/聚合行)· 回滚命令 · 提议者与理由。
82
+ - **回滚原语(已有,需通用化)**:
83
+ - 受保护节点:`_protected_history/<id>/<时间戳>.md` + `_protected_audit.jsonl`(`protect.py:32-33`)——**把这一对从"仅受保护节点"推广为"一切 C/D/B 动作"**;
84
+ - 软删:`trash/` + 删除清单,可 restore(`mcp_server.py:324`);
85
+ - 合并:聚合行自带 `- 【聚合 …】` 前缀(`forgetting.py:84` `AGG_MARK`、`:380`),可按前缀**定向剥离**回退到合并前正文;
86
+ - 分数类:各模块既有 `rollback`(`freshness.py:428` 等)。
87
+
88
+ ## 五 计划模式(我们制定计划,灵枢照计划执行)
89
+
90
+ - **形态已在**:睡眠周期的九步显式台账(`md_cg/sleep.py:596-612`,明文"不许悄悄跳过、不许改名",未接线步显式标注 `未接线`;`STEPS` 顺序即台账顺序)。这是"照计划做、可审计"的**现成骨架**。
91
+ - **本档增量**:把计划从**硬编码序列**变成**输入**——一份显式计划(步骤 · 每步允许的动作类 · 预期读数 · 是否允许落盘),灵枢逐条执行并逐步入台账;**计划由我们(教师/家长)制定**,它不自行增删步骤。
92
+ - **与睡眠周期的关系**:睡眠周期 = 一份**内置默认计划**(缺省计划:九步、周期 3600s、窗口 23:00–07:00、窗口外只记账不迭代);本档不改它,只让"计划可替换/可签收"。
93
+ - **同时是升档的载体**(裁定⑤):升档本身走本档——先出计划、经确认、再升。
94
+
95
+ ## 六 完全访问
96
+
97
+ - **语义**:A–E 全自动,不过问使用者。
98
+ - **准入**:必须**先满足 R1–R4**(§七);不满足时该档**不可选中**(fail-closed 并在启动面报"缺哪一条读数",不静默降级)。
99
+ - **义务(与自由对等)**:①一切破坏性动作**先留前像**(§四);②当日"改了什么 / 丢了什么 / 拒了什么"必须**可一眼查**(§九)。
100
+ - **升档程序**(裁定⑤):写计划 → 使用者确认 → 生效;**降档自动**。
101
+
102
+ ## 七 放权阶梯与准入读数(可机检 · 窗口按裁定③)
103
+
104
+ 三档是**阶梯**不是并列选项:**先证明判断可信,再放权**。四条读数:
105
+
106
+ | 读数 | 判据(机检) | 数据面 | **窗口(裁定③)** | 门槛 |
107
+ |---|---|---|---|---|
108
+ | **R1 判断非退化** | verdict 分布**非常量**:DROP/MERGE/DEFER 各自出现过,且单一 verdict 占比 < 90% | `_forgetting.jsonl`(`forgetting.py:80`)+ `forgetting.summary`(`:606`) | **长期 30 天** | 占比 <90% |
109
+ | **R2 会说"不"** | 负记忆两层有**近期**新增 | `rejected/` 与 `unresolved/` 层节点计数与最近 `created_at` | **短期 3 天**(另看 30 天总量 ≥1) | 3 天内各 ≥1(长期总量各 ≥1) |
110
+ | **R3 破坏可逆且"回过"** | 存在**实测回滚记录**(不是"理论上可回滚") | `_protected_history/`、`trash/`+删除清单、各模块 rollback 台账 | **长期 30 天** | 30 天内 ≥1 次真实回滚 |
111
+ | **R4 判断收敛** | 确认档下**驳回率**(reject/edit ÷ 全部裁定)随时间下降 | `review decisions`(`review_cli stats`) | **长期 30 天**内取 3 个 10 天子窗 | 逐窗下降且 < 20% |
112
+
113
+ **窗口口径(编排侧读法,偏差以使用者为准)**:**短期 3 天**="它最近还在不在行使判断"的**活性**读数(R2);**长期 30 天**="判断有没有在变好、破坏是否可逆"的**能力与收敛**读数(R1/R3/R4)。
114
+
115
+ - **升降档(裁定⑤)**:**升档=计划式确认**(写计划 + 使用者确认);**降档=自动执行**——读数跌破门槛即自动回落到变更确认档,并在启动面告警。
116
+ - **读数即断言**:R1–R4 做成常驻断言(`conformance`/`census` 家族,只告警不改数据),随时可答"它今天够格吗"。
117
+
118
+ ## 八 与 issue #50 的关系:本设计的**前置**
119
+
120
+ #50 复核在隔离沙箱实测到:用户消息通道上栅门的"半重复 → 待定复核"分支**结构性不可达**(重要性下限与外部来源权重基线恰好相等 ⇒ 恒过),实际退化成"精确重复丢弃 + ≥0.85 合并,否则新增"。
121
+
122
+ > **那条消失的 `DEFER`,正是"变更确认"这一档在用户通道上的实现体。**
123
+
124
+ 所以本设计有**两项前置**(属 #50 修复面):
125
+ ① 让"半重复"不再依赖重要性判定(或让重要性下限严格高于来源基线);
126
+ ② 保护线(≥0.70"不可遗忘")只由**显式声明**取得,启发式不得自行签发。
127
+ **在这两项落地前,变更确认档在用户通道上没有输入**——所有半重复都会直接变成新节点,队列里永远没有可确认的东西。
128
+
129
+ ### §八.1 实测更正(2026-10-01,改前基线 · 原判据被证伪)
130
+
131
+ 派发前按设计纪律做了**改前基线**(隔离沙箱写入后直读 frontmatter),结论是 §八 第②条**原判据不成立**,据实更正:
132
+
133
+ | 输入 | 审计面 reason | 裁决用重要度 | 落盘 frontmatter |
134
+ |---|---|---|---|
135
+ | 用户消息 · 显式 0.6 | 重要度 0.60≥0.3 | 0.6(hint) | importance=0.6,protected=None |
136
+ | 用户消息 · **不给** hint(全新) | **「重要度 0.84≥0.7(触发不可遗忘保护)」** | 0.837(启发式) | **importance=0.5,protected=None** |
137
+ | 工具输出 · 不给 hint | **「重要度 0.71≥0.7(触发不可遗忘保护)」** | 0.711(启发式) | **importance=0.5,protected=None** |
138
+ | 用户消息 · 显式 0.9 | 重要度 0.90≥0.7 | 0.9(hint) | **importance=0.9,protected=True** |
139
+
140
+ 1. **保护线实际只由显式声明取得**——启发式算出高分也**不落盘、不给保护**(落默认 0.5)。故「启发式自签保护」**不成立**,§八② 作废。
141
+ 2. 真正的缺陷换成了:**审计面文案会声称未发生的事**——启发式路径下 reason 写「触发不可遗忘保护」,而节点无保护位、重要度仍是默认 0.5;**裁决用的重要度与落盘记的重要度不同源**。属「汇报不实」,处置待使用者裁定(建议:文案只在真的落盘保护时出现;裁决用与落盘记的重要度同源或双记)。
142
+
143
+ **§八 第①条不受影响**,仍为落码第 1 步。
144
+
145
+ ### §八.2 实测更正之二(2026-10-01 · 第①条落码后复核去向面)
146
+
147
+ 第①条(半重复 → DEFER)已落地并通过改前/改后对拍(3 行变 / 5 行不变 / 0 越界;对拍见修复报告),编排侧复核**去向面**时发现一处**必须在落码前解决**的空缺:
148
+
149
+ - **遗忘闸门的 DEFER 没有复核入口**:`md_cg/mdcos.py:3717-3723` 对非 DROP 的裁决只写一行留痕(`node_id/layer/verdict/reason/importance/entropy/actor`,**不含正文**),**不调用任何入队入口**;对比 DROP 分支有 `forgetting.record_drop`(`mdcos.py:3702-3714`,留全文 + trace_id)。**审核队列里的条目来自另一条链**——审计/策略闸(`writepipe.py:260/325` 的 `moved_to="review_queue"`),与遗忘闸门不是同一条路。
150
+ - **后果**:第①条**单独**落地,会把半重复从「落成一个近似重复节点」改成「**不落盘、且正文不进队列**」——原文只留在会话/recent 时间线,而"待定复核"没有收件箱。**那等于把"噪声"缺陷换成"静默不记"缺陷**,正是本设计要消灭的那一类。
151
+ - **对 §十三 的次序修正**:第①条**必须与「遗忘 DEFER → 复核队列」接线同批落地**,否则不得单独落。该接线填的正是 §四(裁定④"复用既有审核队列")在这条路径上的空缺,且须自带守卫(DEFER 入队且带原文 / 裁定 accept 可落盘 / reject 不落盘 / 审计闸已入队的路径**不重复入队**)。
152
+ - **附带(既有守卫的编码问题)**:`md_cg/test_writelimit.py:123-127`(E 节"knowledge 不聚合不限流")把「半重复→ACCEPT」一并钉死在断言里,第①条落地后必然转红。经读码确认,该断言的**意图是层豁免**(限流器未介入),**编码**却依赖遗忘闸门的旧裁决——须按标题意图重写判据(改为「gate 里无 `limiter` 键」)并另加一条钉住新行为。**改的是断言编码,不是断言意图**,且须在提交信息里写明。
153
+
154
+ ### §八.3 落码登记(2026-10-01/02,三批 issue50-a/b/c 的裁定与结果)
155
+
156
+ | 项 | 裁定 | 落点 |
157
+ |---|---|---|
158
+ | ① 半重复→DEFER | 已落 | `md_cg/forgetting.py` 分支④删重要度合取 |
159
+ | 遗忘 DEFER→复核队列(带原文) | 已落(同批) | `md_cg/mdcos.py` DEFER 出口接 `propose`;限流 DEFER 不入队;payload_hash 幂等防重 |
160
+ | E1 重编码 / **H 夹具** | 已落(断言意图不变) | `md_cg/test_writelimit.py` E 节判据换「gate 无 `limiter` 键」+E2 钉新行为;H 节夹具改 `gated=False` 直造存量(四条断言一字未动) |
161
+ | F1 元数据透传 | 已落(使用者裁定扩面) | DEFER 分支 `propose(…, **kw)` 透传 tags/condition_space/verification_basis/non_applicable_conditions/derived_from/relation;accept 回写走**既有映射通道**(`review_decide` 未改);fm 逐键对拍白名单外差异=0 |
162
+ | F2 `node_id=None` | 已落(使用者裁定收口) | 兜底 `forgetting._prefeed_id(content)`(内容派生),兜底事实写返回体 `proposed_id_fallback`(非静默) |
163
+ | `defer_reason` 落 accept 后 fm | **使用者裁定接受**(登记) | 溯源语义:该节点曾因半重复待定、经确认落盘 |
164
+ | 越权层 DEFER → `AccessDenied` | **使用者裁定接受**(登记) | 由「静默返回」改 fail-closed,仅发生在 DEFER 入队路径 |
165
+ | 偶发红归因 | **定案,与本设计无关** | `scripts.test_utf8_boot_guard` 的 `E2E-HIVE-OK` c5 判据被**在役 serve 心跳**打假红(`_serve.json` 每 tick 改写=`poll_ms` 默认 400ms,原子写+伴生 `_serve.tmp<pid>`;早先转述的"每 ~20s"为采样伪影、已订正,心跳相位与采样周期耦合;最小复现 3 轮红 1);修法=`_pool_listing` 排除 `_serve*`(单点,判据强度不变),修后同型条件 3/3 绿 |
166
+ | **issue50-d 重要度同源三件套** | **使用者裁定"做"(2026-10-02)** | ①落盘=裁决值+fm 新增 `importance_source`(hint/heuristic,进索引条目);②自动保护**只认显式声明**(启发式过线只落分不打位,`add()` 既有调用方零回归由 source 缺省 None 构造保证);③保护分支文案按 `imp["from"]` 分叉。**F 组假设链验证(使用者"重要度↔因果推理"归因)**:主相关分 `_score` 不消费 importance,但终排破序(`-score,-importance,id`)、freshness 刷新档(≥0.7→+0.01)、兜底池序、RRF 破序、`_tier_of` 分层**都消费落盘值**——启发式恒落 0.5 使"重要度→排序→下游使用"链在**落盘点**断开;本批修复后该链接通。残余两项登记:`prefeed(write=True)` 同族第二落点未改;`protect.is_protected` 读面按分自动保护会把启发式 0.7x 认作"重要性保护"(保护语义面,待使用者裁定) |
167
+ | **issue50-e 读面保护只认显式来源** | **使用者裁定"让读面也只认显式来源"(2026-10-02)** | 上表残余第二项收口:`protect.is_protected` 按分分支加**来源资格闸**——`imp >= AUTO_PROTECT_IMPORTANCE and (_src is None or _src == "hint")`。三条边界:①键缺省(None)=存量节点(既有 `add(importance=…)` 直写、维护路径调分从未有该键)⇒按分保护**一字不变**(零回归,守卫 B 组锚定);②`"hint"`=显式声明⇒语义不变(写侧对 hint 过线本就打位,按分分支只是其无位形态兜底);③`"heuristic"` 及其它显式来源⇒机器推断的分不构成不可遗忘依据。层保护/`fm.protected` 位/`is_immutable` 一律不动;扩散面(遗忘与搬迁闸、scrub 净化与 confidence 校准 skip、`stats.auto_by_importance` 盘点)同闸生效;启发式的软用途(落盘、排序、freshness 刷新、兜底池序)不受本闸影响。**使用者语义确认**:读面只信「有来源依据的判断」而非转述——本条即该语义在保护面的落地。守卫 53/53+3 定点变异(heuristic 也认→11 红、缺省也判不认→10 红、来源闸整支删除→10 红) |
168
+
169
+
170
+ ## 九 可观测面(家长要的那一眼)
171
+
172
+ 三问做成一条只读读数(挂巡检,不动数据):
173
+
174
+ 1. **它今天拒绝过吗**——`rejected/` 层新增数;
175
+ 2. **它不确定过吗**——`unresolved/` 层新增数 + `_forgetting.jsonl` 中 `DEFER` 计数;
176
+ 3. **它改了什么、被确认过吗**——变更单台账(§四)的 生成/裁定/驳回/回滚 四个计数。
177
+
178
+ ## 十 不适用条件与边界(本稿**不做**的事)
179
+
180
+ - 不做前端/插件 UI,不改 DSH 桥接,不动检索面读数(本设计不改任何打分与召回行为)。
181
+ - **不解决跨进程互斥**:常驻循环按 `(根, 名字)` 进程内唯一,多实例并发是既有缺口,另项。
182
+ - `_sleep.jsonl` 无轮转、断面裁剪不保留前像,均**另项**登记,不在本轮。
183
+ - **不给"判断是否可信"贴 LLM 评分**:R1–R4 一律机检(可复算、可对拍),人只看读数。
184
+ - 不改 `writelimit`(它是文档化设计,只在其**之后**加确认,不重排判据)。
185
+
186
+ ## 十一 验收判据(落码时)
187
+
188
+ - 每档一只守卫(`md_cg/test_autonomy_modes.py` 类)+ **定点变异自证**(注入"档位不生效"必红);
189
+ - **不动面对拍**:切档前后的**非破坏性动作**(A/E)逐位不变;
190
+ - 回滚实测:每种破坏性动作各演一次"落 → 回滚 → 逐字节比对前像";
191
+ - 准入读数 R1–R4 各有独立断言与一组"门槛刚过/刚不过"的边界用例(含窗口边界:3 天 / 30 天各一条)。
192
+
193
+ ## 十二 裁定面(已并入 §〇.2)
194
+
195
+ 五条裁决点已全部签收,内容见 §〇.2;本稿据此冻结,后续变更走新版本号。
196
+
197
+ ## 十三 落码顺序(待使用者开工)
198
+
199
+ 1. **#50 前置其一:半重复 → DEFER**(§八①)**+「遗忘 DEFER → 复核队列」接线**(§八.2)——**两者必须同批落**:单独落①会把"噪声"换成"静默不记";同批另须按标题意图重编码 `test_writelimit.py` 的 E 节断言(§八.2 附带);
200
+ 2. 档位**单一入口** + 缺省 `confirm`(§三);
201
+ 3. 变更单与**回滚原语通用化**(§四);
202
+ 4. R1–R4 **断言与窗口**(§七);
203
+ 5. 每档**守卫 + 定点变异自证**、不动面对拍、回滚演练(§十一)。
204
+
205
+ ---
206
+
207
+ **本稿的证据面全部来自仓内只读普查**(grep + 读码,非测试文件),未写入任何数据、未改任何码。