@furongjun1999/dsh-memory 0.7.4 → 0.7.5
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 +631 -630
- package/codebuddy/CODEBUDDY.md +5 -5
- package/docs/discipline/templates/zcode-user.md.tmpl +4 -1
- 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 +1 -1
- package/docs/eval//345/217/221/345/270/20313_/344/270/212/344/270/213/346/226/207/350/207/252/347/256/241/347/220/206/346/234/272/345/210/266_v1.0.md +114 -0
- 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 +80 -1
- package/docs/plans//347/201/265/346/236/242/350/272/253/344/275/223/303/227/350/204/221_/344/270/226/347/225/214/346/250/241/345/236/213/345/257/271/346/216/245/350/256/276/350/256/241_v0.1.md +76 -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 +461 -461
- package/docs//350/256/260/345/277/206/347/263/273/347/273/237/345/215/263/347/231/275/347/256/261/345/214/226/346/231/272/350/203/275_/346/236/266/346/236/204/345/257/271/347/205/247_v0.2.md +121 -0
- package/docs//350/256/260/345/277/206/347/263/273/347/273/237/345/215/263/347/231/275/347/256/261/345/214/226/346/231/272/350/203/275_/346/236/266/346/236/204/345/257/271/347/205/247_v0.3.md +117 -0
- package/lib/hooks.d.ts +34 -0
- package/lib/hooks.js +165 -0
- package/lib/index.js +22 -1
- package/lib/lib/mdcg_client.d.ts +37 -0
- package/lib/lib/mdcg_client.js +44 -0
- package/md_cg/audit.py +7 -1
- package/md_cg/bench_governance.py +4 -1
- package/md_cg/bench_locomo_zh.py +12 -2
- package/md_cg/bench_zh_mad.py +12 -2
- package/md_cg/interop.py +25 -9
- package/md_cg/sleep.py +223 -103
- package/md_cg/sustain.py +150 -4
- package/md_cg/test_sustain_bounded.py +624 -0
- package/md_cg/units.py +4 -1
- package/package.json +1 -1
- package/skills/plugin.json +1 -1
- package/src/hooks.ts +177 -0
- package/src/index.ts +22 -1
- package/src/lib/mdcg_client.ts +48 -0
- package/zcode/AGENTS.md +5 -5
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# 记忆系统即白箱化智能——神经网络架构 ↔ 记忆系统架构对照 v0.2
|
|
2
|
+
|
|
3
|
+
> **版本性质**:v0.2 在 v0.1(十一条核心对照+主裂缝)基础上,完成从"同构观察"到"可证伪理论"的升级。吸收外部评审建议,但**砍掉了评审引入的装饰性数学**——凡不可证伪的公式一律删除,凡外推处恢复证据分级标注(〔实证〕/〔同构〕/〔推断〕)。
|
|
4
|
+
> **证据纪律**:〔实证〕=既有文献/事实;〔同构〕=本对照发现的功能对应;〔推断〕=外推,须设计反证实验。
|
|
5
|
+
> **v0.1 保留**:总命题、十一条对照表、主裂缝表、续页清单均不改动,本版为其续写。
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## 4. 从"同构"到"功能同构"(评审意见 · 采纳)
|
|
10
|
+
|
|
11
|
+
v0.1 的十一条对照证明了机制层面的对应,但"注意力=检索、参数=记忆"这类一一对应若继续扩大,会从理论退化为类比。需增加中间层:
|
|
12
|
+
|
|
13
|
+
**智能系统三层**:目标层(为什么做)→ 机制层(怎么做)→ 状态层(当前知道什么)。神经网络把三层压缩进参数与连续状态;记忆系统把三层展开为可读的离散结构。
|
|
14
|
+
|
|
15
|
+
**功能同构的定义**:两个机制若在"输入信息 × 系统当前状态 × 当前目标"下对系统状态或决策产生**相同功能位置**的变化,即为功能同构——**不要求物理实现相同**。这解释了黑箱与白箱为何能做"同一种东西"。
|
|
16
|
+
|
|
17
|
+
〔推断〕功能同构是工作定义,其有效性须由 §17 的反证实验检验,而非由定义自证。
|
|
18
|
+
|
|
19
|
+
## 5. 智能的四个基本动作(评审意见 · 采纳并修正)
|
|
20
|
+
|
|
21
|
+
十一条机制可归并为四个基本动作:**取、算、改、存**。
|
|
22
|
+
|
|
23
|
+
| 动作 | 神经网络(黑箱) | 记忆系统(白箱) | 级别 |
|
|
24
|
+
|---|---|---|---|
|
|
25
|
+
| 取 | 注意力按相关性取回并加权 | 检索按相关性取回并注入 | 〔同构〕 |
|
|
26
|
+
| 算 | 前向传播使用信息推理 | 生成器使用交付信息推理 | 〔同构〕 |
|
|
27
|
+
| 改 | 梯度更新修正参数 | 可逆修订修正断言账本 | 〔同构〕 |
|
|
28
|
+
| 存 | 参数=长期记忆,KV 缓存=短期状态 | 断言账本=长期记忆,会话纪程=短期状态 | 〔同构〕 |
|
|
29
|
+
|
|
30
|
+
**评审数学的处置**:评审以公式 `智能 = 取+算+改+存` 表述。此式**不可证伪**(无反例形态),降级为分类学助记,不作为理论命题。可证伪的表述见 §17。
|
|
31
|
+
|
|
32
|
+
## 6. 记忆不是智能本身(评审意见 · 采纳)
|
|
33
|
+
|
|
34
|
+
"有信息 ≠ 能找到信息 ≠ 能正确使用信息 ≠ 能判断信息是否仍有效 ≠ 能根据新信息修正判断"。完整链:信息→记忆→检索→解释→推演→判断→行动→反馈→修正记忆。
|
|
35
|
+
|
|
36
|
+
〔实证〕此链与《秤》v2.1 的被测链条(写入→表示→检索→呈现→生成)同构——**评测规范的分段即理论的分段**。
|
|
37
|
+
|
|
38
|
+
## 7. 可修订性(评审意见 · 采纳)
|
|
39
|
+
|
|
40
|
+
智能系统必须面对现实变化,故须能改变自身状态。神经网络以梯度更新改变参数;记忆系统以验证→保留/修订/退役/撤销改变断言。核心共同点:**新信息必须能改变旧状态**。
|
|
41
|
+
|
|
42
|
+
〔实证〕《秤》v2.1 §5.2 的退役纪律探针(现役/退役/撤销/删除/未知五状态)即此条的评测化。
|
|
43
|
+
|
|
44
|
+
## 8. 记忆决定智能的连续性(评审意见 · 采纳)
|
|
45
|
+
|
|
46
|
+
无记忆系统每次面对世界都重新开始;有记忆系统的当前状态包含过去状态的可恢复影响。**记忆是智能的时间维度**——它让一个以单次推理为单位的智能获得跨时间的状态连续性。
|
|
47
|
+
|
|
48
|
+
## 9. 白箱化的真正对象(评审意见 · 采纳并修正)
|
|
49
|
+
|
|
50
|
+
白箱化不是"打开神经网络的权重"(既不可能也不必要),而是**把智能状态从不可解释的连续参数空间,映射到可观察的状态空间**。
|
|
51
|
+
|
|
52
|
+
**评审未说透、本版补强**:白箱化有代价,且必须写进总命题。神经网络之强大正在于把结构压入高维参数空间;白箱化提升可解释/可审计/可干预/可修订,同时损失泛化、压缩率、计算效率、隐式关联能力。故真正的目标不是"白箱取代黑箱",而是**分工**:
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
黑箱(神经网络):负责高维计算——算得对
|
|
56
|
+
白箱(记忆系统):负责状态治理——记得什么、为什么记、何时改变、改变了什么、还能不能撤回
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
〔推断〕"黑箱管算、白箱管记与裁"是分工假说,其边界(哪些功能必须留在黑箱)须由实证划定。
|
|
60
|
+
|
|
61
|
+
## 10. 白箱化的终极对象是状态转移(评审意见 · 采纳)
|
|
62
|
+
|
|
63
|
+
传统可解释方法问"模型为什么得出这个答案";白箱记忆系统进一步问"模型在何时改变了什么状态、依据是什么、改变前后各信什么、哪条证据触发了改变、删掉这条证据结论是否还成立"。解释对象从"答案"升级为"状态→证据→转移→新状态→行动"。
|
|
64
|
+
|
|
65
|
+
〔实证〕《秤》v2.1 的边界子测试(干预一个前提,问失据/照旧/未知)正是"删掉这条证据结论是否还成立"的评测化。
|
|
66
|
+
|
|
67
|
+
## 11. 四簿的重解释(评审意见 · 采纳)
|
|
68
|
+
|
|
69
|
+
《秤》的四簿在白箱理论下获得新含义——**账簿不是数据库设计,而是智能状态的显式表示**:
|
|
70
|
+
|
|
71
|
+
| 簿 | 回答的问题 | 对应智能环节 |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| 账簿 | 系统曾经知道什么 | 状态 |
|
|
74
|
+
| 源簿 | 系统为什么知道 | 证据 |
|
|
75
|
+
| 推簿 | 系统如何从知道得到结论 | 推理 |
|
|
76
|
+
| 增簿 | 引入记忆后智能发生了什么变化 | 增量 |
|
|
77
|
+
|
|
78
|
+
## 12. 第二种训练(评审意见 · 采纳,标〔推断〕)
|
|
79
|
+
|
|
80
|
+
可区分参数学习(改变模型参数)与状态学习(改变长期记忆)。外部记忆系统实际上在尝试**把"学习"从参数空间迁移到状态空间**——让智能主体拥有可审计、可修订、可持续的经验状态。
|
|
81
|
+
|
|
82
|
+
〔推断〕此条为全稿最大外推。"学习能否迁出参数空间"无既有实证支撑,须设计专门实验(§17 丁)。
|
|
83
|
+
|
|
84
|
+
## 13–16. 评审扩写的处置说明
|
|
85
|
+
|
|
86
|
+
评审稿 §13–16(训练与记忆更新的对应、两种训练的分解、白箱化是否损失能力、新总命题)的核心论点已被本版 §9、§12 吸收。其数学包装(状态转移方程、boxed 公式)因不可证伪而未采纳;其"黑箱智能把状态藏进参数、白箱智能把状态写出来"一句作为**口号**保留,不作为命题。
|
|
87
|
+
|
|
88
|
+
**新总命题(v0.2)**:
|
|
89
|
+
|
|
90
|
+
> **神经网络与记忆系统共享智能的基本计算原语(取、算、改、存),但神经网络将这些原语压缩进参数与隐状态,而记忆系统将其展开为可观察、可验证、可修订的显式状态。因此,记忆系统不是神经网络的附属数据库,而是智能状态的白箱化实现。**
|
|
91
|
+
|
|
92
|
+
此命题的两个可证伪后果:①破坏记忆系统的某机制,应出现与破坏对应神经机制**相似功能位置**的行为退化(§17 甲);②白箱系统应能定位错误到具体环节,黑箱不能(§17 丙)。
|
|
93
|
+
|
|
94
|
+
## 17. 反证实验(评审意见 · 采纳并接驳《秤》)
|
|
95
|
+
|
|
96
|
+
理论到此不能再靠增加类比推进。四个反证实验:
|
|
97
|
+
|
|
98
|
+
### 甲 · 功能同构验证
|
|
99
|
+
人为破坏记忆系统的检索/路由/短期状态/长期状态/更新/压缩,观察是否出现与对应神经机制失效**功能位置相似**的行为退化。**若破坏检索不出现类似注意力失效的退化,则"检索↔注意力"的同构被证伪。**
|
|
100
|
+
|
|
101
|
+
### 乙 · 层级可替换性
|
|
102
|
+
普通检索→向量检索→结构检索→断言检索,若实现相同功能即可在相同任务承担相同角色,则功能同构获支持。
|
|
103
|
+
|
|
104
|
+
### 丙 · 白箱定位能力(=《秤》v2.1 §6 校准零号试验)
|
|
105
|
+
故意制造写入/检索/呈现/推理错误,测试评价系统能否准确指出错在智能链的哪一层。**此实验即《秤》的校准零号——五个受控破坏系统(无记忆/坏写入/坏检索/坏呈现/正常),指标须认出破坏方向。** 理论稿与评测规范在此闭环:《秤》是白箱理论的检验工具。
|
|
106
|
+
|
|
107
|
+
### 丁 · 状态学习验证(针对 §12 最大外推)
|
|
108
|
+
构造只能通过"状态学习"(修改外部记忆)而非"参数学习"(重新训练)获得的能力,检验系统是否真能不改参数而习得新行为。**若不能,则"学习迁出参数空间"被证伪。**
|
|
109
|
+
|
|
110
|
+
## 18. 闭环
|
|
111
|
+
|
|
112
|
+
若白箱命题成立,则灵枢、CTP、记忆系统评测标准、蜂巢基准不再是四个孤立项目,而是在验证同一理论:**若智能可拆成可观察的状态、证据、更新与推理,则智能可被部分白箱化;记忆系统正是这层白箱化智能的实验载体,而《秤》是检验这层白箱是否名副其实的秤。**
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## 变更记录
|
|
117
|
+
|
|
118
|
+
| 日期 | 版本 | 变更 |
|
|
119
|
+
|---|---|---|
|
|
120
|
+
| 2026-10-06 | v0.1 | 总命题+十一条对照+主裂缝+续页清单 |
|
|
121
|
+
| 2026-10-06 | v0.2 | 功能同构定义;取算改存四动作;白箱化代价补入总命题;砍装饰性数学,恢复证据分级;新增 §17 反证实验四则,丙接驳《秤》校准零号 |
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# 记忆系统即白箱化智能——神经网络架构 ↔ 记忆系统架构对照 v0.3
|
|
2
|
+
|
|
3
|
+
> **版本性质**:v0.2 把对照升级为"可证伪理论"(功能同构定义/四动作/白箱化代价/§17 反证实验四则)。
|
|
4
|
+
> v0.3 换一个视点续写:**不再从"神经网络像什么"出发,而从灵枢载体出发**——灵枢(大脑仓 dsh-memory +身体仓 lingshu)
|
|
5
|
+
> 是这套理论的**第一载体与现成实验台**。本版把 v0.2 的抽象命题落到灵枢的**具名机制**上,用载体的
|
|
6
|
+
> 工程事实修正理论(三处修正:§20 改的层次/§21 自治面/§22 算的边界),并把 §17 四实验写成**可在
|
|
7
|
+
> 灵枢上直接执行的落地设计**(§23),最后做一轮**证据回填**(§24:把若干〔推断〕升级或维持)。
|
|
8
|
+
> **证据纪律照旧**:〔实证〕=既有文献/事实(含本仓可查的工程与读数);〔同构〕=功能对应;〔推断〕=外推,须反证实验。
|
|
9
|
+
> **v0.1/v0.2 保留**:不改动;本版为其续写(§19 起)。
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## 19. 四动作的灵枢具名机制(把 §5 的表换成可查的实体)
|
|
14
|
+
|
|
15
|
+
v0.2 §5 的四动作(取/算/改/存)在灵枢里各有**可点名、可运行、可取证**的机制。全部标〔实证·工程〕——引用的模块与读数在本仓/tag v0.7.4 上可复跑:
|
|
16
|
+
|
|
17
|
+
| 动作 | 灵枢的具名机制 | 关键读数/形态 |
|
|
18
|
+
|---|---|---|
|
|
19
|
+
| **取** | `cg(op=read/recall/search)` 多路融合召回(RRF;可点名路:⑤模糊、⑥条件语义、⑦因果、⑧时间——按裁定「全进默认检索」,可单关)+ `stg` 五 op(timeline/anchors/consistency/relation/**state_chain**)+ `cg(op=route)` 条件路由 | 检索 4.4ms(LoCoMo 对照机);条件先行+截断可观测(issue #52) |
|
|
20
|
+
| **算**(浅) | 库层**判定面**:`judge_qualification` 四态(ACCEPT/REJECT/DEFER/BLINDSPOT)· `causal`(path/gate/chain)· `state_slots` 投影 · `predict`(沿因果/时序边生成候选未来) | 确定性、零 LLM、白箱可审计(见 §22「浅裁」) |
|
|
21
|
+
| **改** | **四层**(v0.3 修正,见 §20):判定层(verify 三态/consistency 三级决策)· 状态机层(active→converged→demoted→archived,**退役不删除**)· 回滚层(rollback 原语,前像=执行时点)· 授权层(三档自治+审核队列) | 退役纪律探针 leak 0/2(《秤》5.2);回滚实测逐字节复原 |
|
|
22
|
+
| **存** | 节点库(md 真源)+**台账族**:`_audit`(谁在读谁在写)· `_state_events`(状态转移)· `_evolution`(每次修改=一条缺失条件的补充)· `_lifecycle`/`_trust`/`_sustain`/`_sleep`/`_deletions`/`_refindex` | 「状态显式」的工程体(§11 四簿的载体对应见 §24) |
|
|
23
|
+
|
|
24
|
+
**取/存之间的旧对照(注意力与参数)在此获得工程含义**:白箱的"取"不是一次相似度计算,而是**多路可审计的融合**(每路可单开关、可复现);白箱的"存"不是一张表,而是**一族按语义命名的台账**。
|
|
25
|
+
|
|
26
|
+
## 20. 修正一:v0.2 的「改」行太薄——灵枢的"改"是四层结构
|
|
27
|
+
|
|
28
|
+
v0.2 §5 把"改"对为「梯度更新 ↔ 可逆修订」,§7 展开为"新信息必须能改变旧状态"。灵枢载体的工程事实表明这一行**严重欠写**——白箱的"改"是四层结构,且每层都有黑箱没有的性质:
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
① 判定层:这次改动该不该发生?(verify 三态 / consistency 三级决策 / 主动遗忘闸门四态)
|
|
32
|
+
② 状态机层:改动把状态推到哪个合法位置?(五状态、只允许逐级降级与逐级回升——跳级即拒)
|
|
33
|
+
③ 回滚层:这一步能退回吗?(rollback 原语:前像=执行时点、可逆、可审计)
|
|
34
|
+
④ 授权层:谁有权改?(三档自治 [计划/变更确认/完全访问] + 审核队列 + 写入闸门)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**与黑箱的差异是结构性的**:梯度更新是**全局、连续、不可局部回溯**的(改一个样本的影响弥散在全部参数里);四层的"改"是**定点、可逆、可审计**的(某条断言的退役可点名、可撤销、留痕到 `_state_events` 五元)。⇒ **白箱化的具体优势不只是"可解释",而是"改动本身的治理"**——这是 v0.2 没有明说的第三类优势(次于可解释/可审计,先于效率)。
|
|
38
|
+
|
|
39
|
+
## 21. 修正二:新增第五验证面——自治面(自维护)
|
|
40
|
+
|
|
41
|
+
v0.2 §18 的闭环列了四个验证面(灵枢/CTP/《秤》/蜂巢基准)。灵枢载体的视角认为**缺一维**:白箱化不只"被观察"(状态可读)与"被干预"(可修订),还有**自维护**——系统按自己的周期主动治理自身状态。灵枢的工程形态:
|
|
42
|
+
|
|
43
|
+
- **六档自维护循环**(`sustain`):心跳/自愈/自净/演化/整理/**睡眠(自迭代)**;
|
|
44
|
+
- **自我检验**:两层《秤》探针(账本完整性/退役纪律)已脚本化可复跑;
|
|
45
|
+
- **实证反面**:issue #63(2026-10-06 外部报告)——循环单线程串行,任一档无界阻塞即**整个自治面停摆 9.5 小时**,且当时外部不可诊断。修复后:有界化(超时+stdin 切断)+活体进度面(`current_tick`/`stale_tick`)。
|
|
46
|
+
|
|
47
|
+
⇒ **自治面失效是可观测、可归因、可修复的**——这本身是"白箱"命题的加强证据:一个黑箱系统的心跳停摆你无法从内部观测其"卡在哪一步",而白箱自治面能(修复后 `stale_tick` 直接点名当前档与已运行时长)。**第五验证面**:**自治面实验**(§23 戊)。
|
|
48
|
+
|
|
49
|
+
## 22. 修正三:「算」的边界在灵枢上首次可操作——深算/浅裁
|
|
50
|
+
|
|
51
|
+
v0.2 §9 的分工假说("黑箱管算、白箱管记与裁")边界待实证。灵枢载体让这条边界**首次可操作**:它把"算"分成两类并分别归位——
|
|
52
|
+
|
|
53
|
+
- **深算(黑箱)**:生成器。参数化推理、开放域泛化——白箱不承担,只**备料**(装包/注入)。
|
|
54
|
+
- **浅裁(白箱)**:确定性判定与投影——四态资格裁决、因果可达性、槽位投影、候选未来生成。**零 LLM、可复跑、逐位可复现**。
|
|
55
|
+
|
|
56
|
+
**可证伪形态**:挑一类本可由真实判定回答、但含开放式成分的题(如"某状态是否仍成立")——分别用浅裁与深算作答并对比:浅裁应在**有账面证据**的题上不劣(且可复现),在**账面不足**的题上应显式判 BLINDSPOT/DEFER 而非强答(无账强答=失败)。此实验与《秤》5.1/5.4 探针天然衔接(§23 甲、丁复用其跑道)。
|
|
57
|
+
|
|
58
|
+
## 23. §17 四实验的灵枢落地设计(+第五)
|
|
59
|
+
|
|
60
|
+
**甲 · 功能同构验证**——最短路径=**扩展《秤》校准零号**(规范件已有五系统骨架)。把"破坏面"从规范的写入/检索/呈现扩成 §17 甲列出的**六机制**,每机制**预注册行为签名**(机械可判):
|
|
61
|
+
|
|
62
|
+
| 破坏机制 | 灵枢的破坏点(现成) | 预注册签名(示例) |
|
|
63
|
+
|---|---|---|
|
|
64
|
+
| 检索 | 多路融合单路关闭/打分倒序 | "像记得但用不上":命中率降而写入探针不降 |
|
|
65
|
+
| 路由 | `route` 条件面破坏 | 建议能力名错配率升 |
|
|
66
|
+
| 短期状态 | 注入包/会话纪程损坏 | 当轮指代错误升、跨轮不变 |
|
|
67
|
+
| 长期状态 | 节点库抽样删除(校准零号乙) | 写入/检索/交付三维齐降 |
|
|
68
|
+
| 更新 | 退役/回滚面禁用 | 旧事实残留率升、失效误判升 |
|
|
69
|
+
| 压缩 | 装包截断改激进(《秤》丁坏呈现近亲) | 逐字正常、结构保真降 |
|
|
70
|
+
|
|
71
|
+
**警告(防混用)**:工程侧的"变异自证/定点红基线"是**实现级**(代码对不对),**不能充数**甲实验——甲是**行为级**(生成质量退化形态),须走判官+题池。
|
|
72
|
+
|
|
73
|
+
**乙 · 层级可替换性**——**灵枢本身就是多层检索的载体**(工程归纳,非规范命名):词法层(bm25/jaccard 类)/语义融合层(RRF 多路:可点名 ⑤–⑧)/结构层(`stgidx` by_session/by_layer/by_time+分支)/断言层(`state_chain` 槽位投影+`audit` 审计面)。设计:同一题池多层分别承担 → 行为分数对比;**若各层可在相同任务承担相同角色,乙获支持**。题池现成(LoCoMo/《秤》题库/鲸娘语料)。
|
|
74
|
+
|
|
75
|
+
**丙 · 白箱定位能力**——已闭环(=《秤》v2.1 §6 校准零号);本仓两层《秤》探针已产真读数(5.1:缺口 3/14、无账可辨 5/5、史可查 11/11;5.2:leak 0/2)。直接复用,无需新造。
|
|
76
|
+
|
|
77
|
+
**丁 · 状态学习验证**(v0.2 最大外推)——灵枢的记忆注入回路即载体(记忆→召回→注入→行为)。设计要点:**控制变量**=参数与系统提示逐字不变,**只改记忆库**;判据=目标题答对率显著上升**且消融成立**(移除所注入的具体条目后上升消失——把"学习"归因到可点名的状态改变,而非弥散效应)。
|
|
78
|
+
|
|
79
|
+
**戊(第五 · 本版新增)· 自治面实验**——破坏/停摆自维护循环(issue #63 提供了天然破坏形态:无界等待),观测:①行为面(自治停摆期间注入面的新鲜度/时效面退化);②诊断面(`stale_tick` 能否点名卡点)。**若停摆不可诊断或退化不可见,自治面命题被削弱**。
|
|
80
|
+
|
|
81
|
+
## 24. 证据回填(v0.2 条目 → 灵枢证据 → 级别变动)
|
|
82
|
+
|
|
83
|
+
| v0.2 条目 | 原级 | 灵枢证据(可查) | v0.3 级 |
|
|
84
|
+
|---|---|---|---|
|
|
85
|
+
| §9 分工假说 | 〔推断〕 | LoCoMo 20 题对照(同生成器同判官):灵枢 60%=OpenViking 60%>BM25 55%;检索 4.4ms(OV 42.6ms)、写入 76ms 零 LLM。边界:单会话小样本,非正式读数 | 〔实证·小样本〕(假说获初步支持) |
|
|
86
|
+
| §12 状态学习(最大外推) | 〔推断〕 | **未回填**(丁实验未跑);但载体就绪(§23 丁) | 维持〔推断〕 |
|
|
87
|
+
| §5 取 | 〔同构〕 | §19 多路融合为工程实体(可单开关/可复现) | 〔同构〕→〔实证·工程〕 |
|
|
88
|
+
| §7 可修订性 | 〔实证〕 | §20 四层"改"(比"梯度更新"对照丰富一个量级) | 〔实证·工程〕加强 |
|
|
89
|
+
| §8 记忆与时间维度(v0.2 原文未标级) | 〔—〕 | 双时间轴(effective/observed)· 时间核 γ 半衰期 30 天 · 会话纪程 · `state_chain` 区间 | 〔实证·工程〕 |
|
|
90
|
+
| §10 状态转移的白箱化 | 〔实证〕 | `state_events`(五元台账)→ `state_slots`(查询时现算投影)→ `stg(op=state_chain)`:**"状态→证据→转移→新状态"四段全链**在 0.7.4 发布 | 〔实证·工程〕加强(理论原文的四段=工程四件) |
|
|
91
|
+
| §11 四簿 | 〔同构〕 | 账簿=`_audit`/`_state_events`;源簿=ref 协议(`code_ref/doc_ref` 逐字节回读);推簿/增簿=〔同构〕(`_evolution` 近增簿语义) | 账/源〔实证〕,推/增〔同构〕 |
|
|
92
|
+
| §6 链=《秤》分段 | 〔实证〕 | 两层探针真读数落地(见 §23 丙) | 〔实证〕保持 |
|
|
93
|
+
|
|
94
|
+
## 25. 把 §18 闭环写全(五面)
|
|
95
|
+
|
|
96
|
+
v0.2 §18:灵枢/CTP/《秤》/蜂巢基准=同一理论的四个验证面。v0.3 补第五面后:
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
若智能可拆成可观察的状态、证据、更新与推理,则智能可被部分白箱化;
|
|
100
|
+
回 路:灵枢(载体:状态显式 + 自维护)
|
|
101
|
+
协 议:CTP(多主体间的状态/证据交换最小契约)
|
|
102
|
+
尺 度:《秤》(这层白箱是否名副其实的秤)
|
|
103
|
+
基 准:蜂巢(单机之上的编排基准)
|
|
104
|
+
自 治:自维护循环(状态治理的时间形态——第五面)
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
黑箱管深算,白箱管记·裁·维;**灵枢是这条分工线目前的完整实验台**。
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 变更记录
|
|
112
|
+
|
|
113
|
+
| 日期 | 版本 | 变更 |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| 2026-10-06 | v0.1 | 总命题+十一条对照+主裂缝+续页清单 |
|
|
116
|
+
| 2026-10-06 | v0.2 | 功能同构定义;取算改存四动作;白箱化代价补入总命题;砍装饰性数学,恢复证据分级;§17 反证实验四则,丙接驳《秤》校准零号 |
|
|
117
|
+
| 2026-10-06 | v0.3 | 视点换到灵枢载体:§19 四动作具名机制表;§20 修正一「改」为四层结构(定点/可逆/可审计);§21 修正二新增第五验证面「自治面」;§22 修正三「深算/浅裁」边界可操作;§23 四实验灵枢落地设计(甲=校准零号扩六机制+预注册签名;乙=四层检索载体;丁=记忆注入 A/B+消融)+新增戊自治面实验;§24 证据回填(LoCoMo 等);§25 闭环补第五面 |
|
package/lib/hooks.d.ts
CHANGED
|
@@ -24,10 +24,29 @@
|
|
|
24
24
|
* `delegationDepth=0` 真实在写);**仍未观测**的是 `origin='subagent'` /
|
|
25
25
|
* `delegationDepth>0` / `form='relay'` 的真实出现(见 installMemoryHooks 内注释)。
|
|
26
26
|
*
|
|
27
|
+
* contextWindow(滑动窗口,2026-10-06):**短期记忆 = 运行态事件窗口**。
|
|
28
|
+
* 写侧把每条 user/assistant 消息(经既有 sanitize 的原文)追加进灵枢的
|
|
29
|
+
* `_recent.jsonl` 滚动窗口(`cg(op=recent, action=add)`);注入侧在每次
|
|
30
|
+
* system-prompt/assemble 时注入独立的「【本会话近期对话】」块
|
|
31
|
+
* (`cg(op=session, action=recall)` 的 recent 段)——宿主压缩(retained 置空
|
|
32
|
+
* 后重新投影)时该块随既有块一起自然重现,即「上下文满后早期对话的接续锚」。
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ **两轨关系(勿混)**:
|
|
35
|
+
* · 知识面轨:`opts.userMessage` / `opts.assistantMessage` 管「消息沉淀成
|
|
36
|
+
* 记忆节点」(role:user/assistant,进检索正排);使用者 2026-09-27 的
|
|
37
|
+
* `userMessage=false` 决策关的是**这一轨**(消息不自动进知识面)。
|
|
38
|
+
* · 窗口轨:`opts.contextWindow`(enabled/turns)管「消息进运行态窗口」
|
|
39
|
+
* (`_recent.jsonl`:滚动淘汰、**不占知识层、不进检索正排、不是知识节点**)。
|
|
40
|
+
* 两轨**独立开关、互不替代**:知识面关掉时窗口照常工作(这正是本机制存在的
|
|
41
|
+
* 意义——压缩后的续接锚不依赖自动记忆的写入开关)。
|
|
42
|
+
*
|
|
27
43
|
* autoRecall:通过 system-prompt/assemble 事件(waterfall,异步允许)在每次
|
|
28
44
|
* 模型请求组装 system prompt 时自动注入灵枢最近记忆
|
|
29
45
|
* (`stg(op=timeline)`,最近记忆节点时间线),让记忆"自动可用"而不只依赖
|
|
30
46
|
* Agent 主动调用 recall/think 工具。失败静默(不影响请求)。
|
|
47
|
+
* contextWindow 的注入面是**独立第二块**(`lingshu:session-window`)——既有块
|
|
48
|
+
* (timeline / `lingshu:auto-recall`)的行为一字不动;第二块的注入门控 =
|
|
49
|
+
* 注入面总开关 `opts.autoRecall` × 本机制开关 `contextWindow.enabled`。
|
|
31
50
|
* ⚠️ 该注入块的**稳定性**决定宿主是否新追加快照:内容没变时也必须照旧 push
|
|
32
51
|
* (宿主按渲染后的整段文本去重);跳过 push 反而会各追加一份「有块/无块」的快照
|
|
33
52
|
* —— 详见 installMemoryHooks 里的长注释。
|
|
@@ -67,6 +86,21 @@ export interface MemoryHooksOptions {
|
|
|
67
86
|
* apply 探针同目录同惯例),供测试与定制注入;审计自身失败静默降级,
|
|
68
87
|
* 绝不冒泡进记忆路径。不改任何既有选项语义。 */
|
|
69
88
|
auditPath?: string;
|
|
89
|
+
/** **短期会话窗口**(滑动窗口,2026-10-06):enabled(缺省 true)控制整条
|
|
90
|
+
* 机制(写侧 + 注入侧同时静默);turns(缺省 10)= 窗口取数条数
|
|
91
|
+
* (`session_recall` 的 `recent_limit`,语义是**条**不是轮)。
|
|
92
|
+
*
|
|
93
|
+
* ⚠️ **两轨关系(勿混,头注有详述)**:`userMessage` / `assistantMessage`
|
|
94
|
+
* 管**知识面**(消息沉淀成记忆节点,进检索正排);本组管**运行态窗口**
|
|
95
|
+
* (`_recent.jsonl`:滚动淘汰、不占知识层、不进正排、不是知识节点)。
|
|
96
|
+
* 两轨独立开关、互不替代——知识面开关关掉时窗口照常工作。
|
|
97
|
+
*
|
|
98
|
+
* 可选(缺省视为 `{ enabled: true, turns: 10 }`):既有调用方不传本项时
|
|
99
|
+
* 行为与缺省一致,不改变任何既有选项语义。 */
|
|
100
|
+
contextWindow?: {
|
|
101
|
+
enabled: boolean;
|
|
102
|
+
turns: number;
|
|
103
|
+
};
|
|
70
104
|
}
|
|
71
105
|
/** 两宽「词字符」类:半角 + 全角 字母/数字/下划线(`\w`/`\b` 的替代判据面)。
|
|
72
106
|
* 导出供守卫核对字面量规则的同源性(test/fullwidth_redact.test.ts ⑦);
|
package/lib/hooks.js
CHANGED
|
@@ -24,10 +24,29 @@
|
|
|
24
24
|
* `delegationDepth=0` 真实在写);**仍未观测**的是 `origin='subagent'` /
|
|
25
25
|
* `delegationDepth>0` / `form='relay'` 的真实出现(见 installMemoryHooks 内注释)。
|
|
26
26
|
*
|
|
27
|
+
* contextWindow(滑动窗口,2026-10-06):**短期记忆 = 运行态事件窗口**。
|
|
28
|
+
* 写侧把每条 user/assistant 消息(经既有 sanitize 的原文)追加进灵枢的
|
|
29
|
+
* `_recent.jsonl` 滚动窗口(`cg(op=recent, action=add)`);注入侧在每次
|
|
30
|
+
* system-prompt/assemble 时注入独立的「【本会话近期对话】」块
|
|
31
|
+
* (`cg(op=session, action=recall)` 的 recent 段)——宿主压缩(retained 置空
|
|
32
|
+
* 后重新投影)时该块随既有块一起自然重现,即「上下文满后早期对话的接续锚」。
|
|
33
|
+
*
|
|
34
|
+
* ⚠️ **两轨关系(勿混)**:
|
|
35
|
+
* · 知识面轨:`opts.userMessage` / `opts.assistantMessage` 管「消息沉淀成
|
|
36
|
+
* 记忆节点」(role:user/assistant,进检索正排);使用者 2026-09-27 的
|
|
37
|
+
* `userMessage=false` 决策关的是**这一轨**(消息不自动进知识面)。
|
|
38
|
+
* · 窗口轨:`opts.contextWindow`(enabled/turns)管「消息进运行态窗口」
|
|
39
|
+
* (`_recent.jsonl`:滚动淘汰、**不占知识层、不进检索正排、不是知识节点**)。
|
|
40
|
+
* 两轨**独立开关、互不替代**:知识面关掉时窗口照常工作(这正是本机制存在的
|
|
41
|
+
* 意义——压缩后的续接锚不依赖自动记忆的写入开关)。
|
|
42
|
+
*
|
|
27
43
|
* autoRecall:通过 system-prompt/assemble 事件(waterfall,异步允许)在每次
|
|
28
44
|
* 模型请求组装 system prompt 时自动注入灵枢最近记忆
|
|
29
45
|
* (`stg(op=timeline)`,最近记忆节点时间线),让记忆"自动可用"而不只依赖
|
|
30
46
|
* Agent 主动调用 recall/think 工具。失败静默(不影响请求)。
|
|
47
|
+
* contextWindow 的注入面是**独立第二块**(`lingshu:session-window`)——既有块
|
|
48
|
+
* (timeline / `lingshu:auto-recall`)的行为一字不动;第二块的注入门控 =
|
|
49
|
+
* 注入面总开关 `opts.autoRecall` × 本机制开关 `contextWindow.enabled`。
|
|
31
50
|
* ⚠️ 该注入块的**稳定性**决定宿主是否新追加快照:内容没变时也必须照旧 push
|
|
32
51
|
* (宿主按渲染后的整段文本去重);跳过 push 反而会各追加一份「有块/无块」的快照
|
|
33
52
|
* —— 详见 installMemoryHooks 里的长注释。
|
|
@@ -281,6 +300,57 @@ function formatTimelineDecayed(payload) {
|
|
|
281
300
|
}
|
|
282
301
|
return out.join('\n').slice(0, RECALL_MAX_CHARS);
|
|
283
302
|
}
|
|
303
|
+
// ---------------------------------------------------------------- 会话窗口渲染
|
|
304
|
+
// 「短期会话窗口」(contextWindow)的取数/渲染常量。与上方 RECALL_* 同款纪律:
|
|
305
|
+
// 常量写死在此处(而非 config schema——未知键会被 schema 剥离)。
|
|
306
|
+
/** 窗口块取数的整包 token 预算(服务端 `session_recall` 的 budget_tokens)。
|
|
307
|
+
*
|
|
308
|
+
* ⚠️ 这是**整包**预算,不是 recent 段的独立预算:notes/goals/tasks/self_state
|
|
309
|
+
* 与 recent 共享(服务端裁剪循环交替丢 recent / notes 尾部,md_cg/mdcos.py:
|
|
310
|
+
* 3351-3362)。取 600 是**有意保守**——本块定位是「存在性锚点 / 接续提示」,
|
|
311
|
+
* 宁可少注入几条,也不挤占宿主上下文。实测(空库 + 10 条窗口条目):
|
|
312
|
+
* budget_tokens=600 → recent 段 8 条;1200 → 10 条。 */
|
|
313
|
+
const WINDOW_BUDGET_TOKENS = 600;
|
|
314
|
+
/** 单条窗口条目预览上限(字符)。 */
|
|
315
|
+
const WINDOW_ITEM_CHARS = 120;
|
|
316
|
+
/** 窗口块总长上限(字符)。 */
|
|
317
|
+
const WINDOW_MAX_CHARS = 800;
|
|
318
|
+
/** 会话窗口载荷 → 注入文本(限幅沿 RECALL 分级渲染的风格:单条 ≤120 字、
|
|
319
|
+
* 整块 ≤800 字)。
|
|
320
|
+
*
|
|
321
|
+
* `cg(op=session, action=recall)` 的 `recent` 段 = `{role, text, t}` 列表,
|
|
322
|
+
* 按**新→旧**排列(服务端 `recent_events` 的 newest_first)。渲染取**旧→新**
|
|
323
|
+
* (对话流水的自然阅读序),但**裁剪保最新**:先按服务端序(新→旧)逐条
|
|
324
|
+
* 试放入上限(放不下就**停在更旧的条目上**,整条不放入),最后整体反转
|
|
325
|
+
* ——总长受限时丢掉的是**最旧**条目(近因优先),且**不切条目中间**
|
|
326
|
+
* (逐条整放/整弃;最后才 slice 是错的——那会把最新一条切掉半截)。
|
|
327
|
+
*
|
|
328
|
+
* 空载荷 / 无 recent 段 / 全空条目 → 返回空串(调用方据此**不 push** 第二块)。 */
|
|
329
|
+
function formatSessionWindow(payload, limit) {
|
|
330
|
+
const items = (payload && typeof payload === 'object'
|
|
331
|
+
&& Array.isArray(payload.recent))
|
|
332
|
+
? payload.recent
|
|
333
|
+
: [];
|
|
334
|
+
const rows = [];
|
|
335
|
+
const max = Math.max(1, Math.floor(limit) || 10);
|
|
336
|
+
let used = 0;
|
|
337
|
+
for (const it of items.slice(0, max)) {
|
|
338
|
+
const role = String(it['role'] ?? '').trim() || 'user';
|
|
339
|
+
const preview = String(it['text'] ?? '').replace(/\s+/g, ' ').trim();
|
|
340
|
+
if (!preview)
|
|
341
|
+
continue;
|
|
342
|
+
const body = preview.length > WINDOW_ITEM_CHARS
|
|
343
|
+
? preview.slice(0, WINDOW_ITEM_CHARS) + '…'
|
|
344
|
+
: preview;
|
|
345
|
+
const row = `[${role}] ${body}`;
|
|
346
|
+
const next = used === 0 ? row.length : used + 1 + row.length;
|
|
347
|
+
if (used > 0 && next > WINDOW_MAX_CHARS)
|
|
348
|
+
break;
|
|
349
|
+
rows.push(row);
|
|
350
|
+
used = next;
|
|
351
|
+
}
|
|
352
|
+
return rows.reverse().join('\n');
|
|
353
|
+
}
|
|
284
354
|
/** 取宿主会话标识(只用于**归因/隔离**,不参与任何权限判断)。
|
|
285
355
|
*
|
|
286
356
|
* 动机:记忆写入必须带会话身份才能区分不同会话;读取默认只看本会话(防串台),
|
|
@@ -364,6 +434,62 @@ export function installMemoryHooks(ctx, mdcg, opts) {
|
|
|
364
434
|
* 「写入失败/漏记」。审计失败静默降级(见 src/lib/hook_audit.ts),
|
|
365
435
|
* 绝不冒泡进记忆路径、不改任何写入/过滤判定。 */
|
|
366
436
|
const audit = new HookAuditRecorder(opts.auditPath);
|
|
437
|
+
// ── 短期会话窗口(contextWindow):与知识面写入**独立成轨**(见文件头)──
|
|
438
|
+
// 缺省开启({ enabled: true, turns: 10 });enabled=false → 写侧与注入侧
|
|
439
|
+
// **同时静默**。turns = 窗口取数条数(session_recall 的 recent_limit 语义是
|
|
440
|
+
// **条**不是轮);clamp 到 1~50(与既有 recallLimit 同款纪律,防配置失手)。
|
|
441
|
+
const cw = opts.contextWindow ?? { enabled: true, turns: 10 };
|
|
442
|
+
const cwEnabled = cw.enabled !== false;
|
|
443
|
+
const cwTurns = Math.max(1, Math.min(50, Math.floor(cw.turns || 10)));
|
|
444
|
+
/** 窗口条目判定(contextWindow 写侧):这条事件是否值得进「近期对话」窗口。
|
|
445
|
+
* 返回 null = 不写。
|
|
446
|
+
*
|
|
447
|
+
* 过滤面与知识面**同源**(复用同一组谓词函数,故两处口径不会各自漂移):
|
|
448
|
+
* · user/message:`form==='relay'`(H1 消息级)与 `kind!=='user'`(插件注入 /
|
|
449
|
+
* 系统上下文)不写——与自动记忆同一判定;有文本才写;
|
|
450
|
+
* · assistant/message:有文本即写;
|
|
451
|
+
* · 其它事件类型(tool/result 等):一律不写(窗口是**对话**记录)。
|
|
452
|
+
*
|
|
453
|
+
* ⚠️ 两处**有意不同门**(这是设计,不是遗漏):本判定**不看**
|
|
454
|
+
* `opts.userMessage` / `opts.assistantMessage`——那两个开关管知识面(消息沉淀
|
|
455
|
+
* 成记忆节点),本机制由 `contextWindow.enabled` 管(运行态窗口)。若把窗口写
|
|
456
|
+
* 也挂到那两个开关上,使用者既有的 `userMessage=false` 就会连带关掉窗口,
|
|
457
|
+
* 「知识面关、窗口开」的独立轨道即不成立(两轨关系见文件头)。
|
|
458
|
+
*
|
|
459
|
+
* ⚠️ 子代理会话(H1 会话级)由调用点**更早**拦回(在取 sid 之前),不在此重判
|
|
460
|
+
* ——与自动记忆同口径:委派指令不进真人窗口。 */
|
|
461
|
+
const windowEntry = (event) => {
|
|
462
|
+
if (event.type === 'user/message') {
|
|
463
|
+
if (isRelayedMessage(event.data.source))
|
|
464
|
+
return null;
|
|
465
|
+
if (event.data.source?.kind !== 'user')
|
|
466
|
+
return null;
|
|
467
|
+
const text = extractText(event.data.content);
|
|
468
|
+
return text ? { role: 'user', text } : null;
|
|
469
|
+
}
|
|
470
|
+
if (event.type === 'assistant/message') {
|
|
471
|
+
const text = extractText(event.data.message.content);
|
|
472
|
+
return text ? { role: 'assistant', text } : null;
|
|
473
|
+
}
|
|
474
|
+
return null;
|
|
475
|
+
};
|
|
476
|
+
/** 窗口写入(fire-and-forget):失败只记 warn,**绝不炸会话流**(沿 memorize
|
|
477
|
+
* 的 catch 风格)。桥未就绪静默跳过(窗口是运行态面,不阻塞对话;「未就绪」
|
|
478
|
+
* 的告警已由 memorize 路径负责,不在此重复刷屏)。
|
|
479
|
+
*
|
|
480
|
+
* ⚠️ 同步抛出也必须被吞(catch 两段):真实部署下 graph 是 MdcgClient 全量
|
|
481
|
+
* 实现;但桥替换实现 / 降级替身缺该方法时,抛错同样不得越过会话流边界。 */
|
|
482
|
+
const noteRecent = (role, text, meta) => {
|
|
483
|
+
if (!graph.isReady())
|
|
484
|
+
return;
|
|
485
|
+
try {
|
|
486
|
+
void graph.recentAdd(role, text, meta, ['dsh', 'recent-window'])
|
|
487
|
+
.catch((err) => ctx.logger.warn(`dsh-memory: 短期窗口写入失败: ${err.message}`));
|
|
488
|
+
}
|
|
489
|
+
catch (err) {
|
|
490
|
+
ctx.logger.warn(`dsh-memory: 短期窗口写入失败: ${err.message}`);
|
|
491
|
+
}
|
|
492
|
+
};
|
|
367
493
|
/** 本实例是否曾观测到会话(B 治本批)。
|
|
368
494
|
*
|
|
369
495
|
* 会话状态本体是**进程级单点**(lib/session_state.ts;hooks 面观测、工具面
|
|
@@ -460,6 +586,29 @@ export function installMemoryHooks(ctx, mdcg, opts) {
|
|
|
460
586
|
text: escapePromptBraces(renderUntrustedMemoryBlock(`【灵枢最近记忆】\n${text.slice(0, RECALL_MAX_CHARS)}`)),
|
|
461
587
|
});
|
|
462
588
|
}
|
|
589
|
+
// ── 独立第二块:「【本会话近期对话】」(contextWindow 注入面)──
|
|
590
|
+
// 与上方 timeline 块**块名/取数/开关各自独立**(既有块一字未动)。
|
|
591
|
+
// 稳定性口径与既有块同等:**每步都 push**(内容随新轮增长属预期——
|
|
592
|
+
// 宿主对内容变化追加快照的既有行为不变;窗口不变时两块逐字节相同)。
|
|
593
|
+
// fail-soft:取数/渲染失败 → 静默、不 push 第二块,绝不抛——且因
|
|
594
|
+
// 上方既有块已先 push,本块的失败**不影响**既有块(反之亦然)。
|
|
595
|
+
// 门控 = 注入面总开关 autoRecall(本 handler 的注册条件)× 本机制开关
|
|
596
|
+
// contextWindow.enabled。
|
|
597
|
+
if (cwEnabled) {
|
|
598
|
+
try {
|
|
599
|
+
const win = await graph.sessionRecall(sid, cwTurns, WINDOW_BUDGET_TOKENS);
|
|
600
|
+
const winText = formatSessionWindow(win, cwTurns);
|
|
601
|
+
if (winText) {
|
|
602
|
+
// 注入边界同规(文件头硬约束):不可信内容边界 + `{{` 转义,
|
|
603
|
+
// 都只改注入副本——窗口原文在库内保真。
|
|
604
|
+
assembly.contexts.push({
|
|
605
|
+
name: 'lingshu:session-window',
|
|
606
|
+
text: escapePromptBraces(renderUntrustedMemoryBlock(`【本会话近期对话】\n${winText}`)),
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
catch { /* 静默:窗口取数失败不影响请求,也不影响既有块 */ }
|
|
611
|
+
}
|
|
463
612
|
}
|
|
464
613
|
}
|
|
465
614
|
catch { /* 静默:召回失败不影响请求 */ }
|
|
@@ -562,5 +711,21 @@ export function installMemoryHooks(ctx, mdcg, opts) {
|
|
|
562
711
|
...sessionTag,
|
|
563
712
|
}));
|
|
564
713
|
}
|
|
714
|
+
// ── 短期窗口写侧(contextWindow):与上方知识面写入**独立成轨** ──
|
|
715
|
+
// 位置在既有分支链**之外**:不受 opts.userMessage / opts.assistantMessage
|
|
716
|
+
// 门控(那两个开关管知识面;本机制由 contextWindow.enabled 管——两轨关系
|
|
717
|
+
// 见文件头与 windowEntry 注释)。
|
|
718
|
+
// 过滤面与知识面同源:H1 会话级(子代理整条会话)已在函数首拦回;此处经
|
|
719
|
+
// windowEntry 复用同一组谓词(relay / kind),再经**同一个** sanitize 脱敏
|
|
720
|
+
// ——纯凭据消息(sanitize 返回 null)同样不写(不把明文凭据引进窗口)。
|
|
721
|
+
// 失败只记 warn(noteRecent),绝不冒泡进会话流。
|
|
722
|
+
if (cwEnabled) {
|
|
723
|
+
const entry = windowEntry(event);
|
|
724
|
+
if (entry) {
|
|
725
|
+
const safe = sanitize(entry.text);
|
|
726
|
+
if (safe !== null)
|
|
727
|
+
noteRecent(entry.role, safe, { ...sessionTag });
|
|
728
|
+
}
|
|
729
|
+
}
|
|
565
730
|
});
|
|
566
731
|
}
|
package/lib/index.js
CHANGED
|
@@ -107,8 +107,29 @@ export const Config = z.object({
|
|
|
107
107
|
autoRecall: z.boolean().default(true),
|
|
108
108
|
autoRecallLimit: z.number().default(4),
|
|
109
109
|
desensitize: z.boolean().default(true),
|
|
110
|
+
/** **短期会话窗口**(滑动窗口,2026-10-06)——「短期保留近 N 条对话记录」
|
|
111
|
+
* 的机制实现(长期记忆仍走灵枢的显式调用)。
|
|
112
|
+
*
|
|
113
|
+
* enabled(缺省 true)控制**整条机制**(写侧 + 注入侧同时静默);
|
|
114
|
+
* turns(缺省 10)=窗口取数条数(服务端 `session_recall` 的
|
|
115
|
+
* `recent_limit`,语义是**条**不是轮)。
|
|
116
|
+
*
|
|
117
|
+
* ⚠️ **两轨关系(勿混,机制头注见 src/hooks.ts / mdcg_client.ts)**:
|
|
118
|
+
* · 知识面轨:`userMessage` / `assistantMessage` 管「消息沉淀成记忆
|
|
119
|
+
* 节点」(role:user/assistant,进检索正排)。使用者 2026-09-27 的
|
|
120
|
+
* `userMessage=false` 决策关的是**这一轨**——消息不自动进知识面;
|
|
121
|
+
* · 窗口轨:本组管「消息进**运行态窗口**」(`_recent.jsonl`:滚动淘汰、
|
|
122
|
+
* 不占知识层、不进检索正排、**不是知识节点**)。
|
|
123
|
+
* 两轨独立开关、互不替代:知识面关掉时窗口照常工作(这正是本机制存在
|
|
124
|
+
* 的意义——上下文压缩后的续接锚不依赖自动记忆的写入开关)。 */
|
|
125
|
+
contextWindow: z
|
|
126
|
+
.object({
|
|
127
|
+
enabled: z.boolean().default(true),
|
|
128
|
+
turns: z.number().default(10),
|
|
129
|
+
})
|
|
130
|
+
.default({ enabled: true, turns: 10 }),
|
|
110
131
|
})
|
|
111
|
-
.default({ userMessage: true, assistantMessage: false, toolResult: false, importance: 0.6, autoRecall: true, autoRecallLimit: 4, desensitize: true }),
|
|
132
|
+
.default({ userMessage: true, assistantMessage: false, toolResult: false, importance: 0.6, autoRecall: true, autoRecallLimit: 4, desensitize: true, contextWindow: { enabled: true, turns: 10 } }),
|
|
112
133
|
toolCallTimeoutMs: z.number().default(60_000),
|
|
113
134
|
maxRetryDelayMs: z.number().default(30_000),
|
|
114
135
|
failOnStartupError: z.boolean().default(false),
|
package/lib/lib/mdcg_client.d.ts
CHANGED
|
@@ -19,6 +19,8 @@
|
|
|
19
19
|
* 外部裁决回填 → MdcgClient.verify() → MCP cg(op=verify)
|
|
20
20
|
* 最近记忆时间线 → MdcgClient.timeline() → MCP stg(op=timeline)
|
|
21
21
|
* 近期事件窗口 → MdcgClient.recent() → MCP cg(op=recent)
|
|
22
|
+
* 窗口追加事件 → MdcgClient.recentAdd() → MCP cg(op=recent, action=add)
|
|
23
|
+
* 会话续接包 → MdcgClient.sessionRecall() → MCP cg(op=session, action=recall)
|
|
22
24
|
* 身份读取 → MdcgClient.identity() → MCP cg(op=identity)
|
|
23
25
|
* 白箱能力验证 → MdcgClient.whitebox() → MCP cg(op=whitebox)
|
|
24
26
|
* 服务信息 → MdcgClient.serviceInfo()→ MCP cg(op=info)
|
|
@@ -182,6 +184,41 @@ export declare class MdcgClient {
|
|
|
182
184
|
verify(nodeId: string, evidence: string, verdict: string): Promise<unknown>;
|
|
183
185
|
/** 最近记忆。 */
|
|
184
186
|
recent(limit?: number): Promise<unknown>;
|
|
187
|
+
/** 追加一条**近期事件窗口**记录(`cg(op=recent, action=add)` →
|
|
188
|
+
* `md_cg` 的 `remember_event(role, text, tags, meta, window)`)。
|
|
189
|
+
*
|
|
190
|
+
* 这是「滑动窗口」写侧:事件落 `_recent.jsonl`(**运行态面**),按窗口滚动
|
|
191
|
+
* 淘汰(服务端缺省 200 条,`mdcg.py:91 DEFAULT_RECENT_WINDOW`)——它**不是
|
|
192
|
+
* 知识节点**:不占 knowledge 层、不进检索正排,与 `remember()` 的知识面沉淀
|
|
193
|
+
* 是两条独立的轨道(见 src/hooks.ts 文件头的 contextWindow 头注)。
|
|
194
|
+
*
|
|
195
|
+
* ⚠️ **不注入 as_unit**(与 `write()` 同款理由的反面):本调用不写任何层的
|
|
196
|
+
* 节点(服务端 `remember_event` 不做层白名单校验),收窄单元无收益且可能压低
|
|
197
|
+
* 事件密级(缺省 internal);`meta.session` 由调用方显式给出(沿本文件
|
|
198
|
+
* `remember()` 的 sessionTag 口径)。
|
|
199
|
+
*
|
|
200
|
+
* ⚠️ 服务端对 `meta` 做 `setdefault`(tenant/session/harness/unit,见
|
|
201
|
+
* `mdcos.py:5057 remember_event`):调用方已写的键**不被覆盖**。 */
|
|
202
|
+
recentAdd(role: string, text: string, meta?: Record<string, unknown>, tags?: string[]): Promise<unknown>;
|
|
203
|
+
/** **会话续接包**(`cg(op=session, action=recall)` → `md_cg` 的
|
|
204
|
+
* `session_recall`):一次取回 notes / goals / tasks / **recent 事件窗口** /
|
|
205
|
+
* unresolved / self_state,按 `budget_tokens` 整包裁剪(服务端
|
|
206
|
+
* `mdcos.py:3351-3362`:交替丢 recent / notes 尾部)。
|
|
207
|
+
*
|
|
208
|
+
* 本插件消费其中的 `recent` 段——滑动窗口的**注入面**(见 src/hooks.ts)。
|
|
209
|
+
* `recent_limit` 语义 = 近期事件**条数**(非「轮数」);服务端读取时会按
|
|
210
|
+
* `max(1, recent_limit or 10)` 归一(`mdcos.py:3309`)。
|
|
211
|
+
*
|
|
212
|
+
* ⚠️ 两条服务端事实(决定注入侧的可达性,勿据本方法名臆测):
|
|
213
|
+
* ① `recent` 段取 `recent_events(limit=recent_limit)` —— **不按 session
|
|
214
|
+
* 过滤**(近期事件是运行态滚动窗口,会话归属只写在每条事件的 meta 里);
|
|
215
|
+
* ② budget 是**整包**预算:库内 notes/tasks/self_state 占位越多,同样
|
|
216
|
+
* budget 下 recent 段被裁得越短(实测:空库 + 10 条窗口条目,
|
|
217
|
+
* budget_tokens=600 → recent 8 条;1200 → 10 条)。
|
|
218
|
+
*
|
|
219
|
+
* 只读调用,不注入 as_unit(同其它读路径:读无副作用,收窄只会压低 owner
|
|
220
|
+
* 的 private 读能力)。 */
|
|
221
|
+
sessionRecall(session: string, recentLimit: number, budgetTokens: number): Promise<unknown>;
|
|
185
222
|
/** 最近记忆**时间线**(AEIS `timeline` 的对应物):`stg(op=timeline)` →
|
|
186
223
|
* `{count, limit, items:[{id, layer, start, end, preview}]}`,按时间倒序。
|
|
187
224
|
*
|