@furongjun1999/dsh-memory 0.7.3 → 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.
@@ -0,0 +1,305 @@
1
+ # 世界模型功能端 · 使用与运维指南(v1.0)
2
+
3
+ > **这一页回答一件事:语义时空图「状态层」上线后,你怎么记账、怎么查、开关在哪、怎么复跑读数、边界到哪。**
4
+ > 依据:`docs/plans/语义时空图补全_世界模型功能端_设计_v0.1.md`(六签收点)与 `docs/秤_记忆系统评测规范_v2.1.md` §5.1(账本完整性口径)。
5
+ > 使用者定位(2026-10-06):「0.7.4 把世界模型,也就是语义时空图的地基打好。」本页对应 P3 批(写侧入口 + 账本完整性探针 + 使用文档)。
6
+
7
+ ---
8
+
9
+ ## 一、一句话
10
+
11
+ **事件是源、槽位是投影、查询走 stg**:
12
+
13
+ ```
14
+ 记账(写口) 台账(源) 投影(物化视图,查询时现算) 查询面
15
+ cg(op=state_event) → <root>/_state_events.jsonl → md_cg/state_slots.py → stg(op=state_chain)
16
+ (MCP 面) append-only、不截断 (只读台账、不落盘、不缓存) (默认关)
17
+ ↘ CLI:python -m md_cg.state_slots
18
+ ```
19
+
20
+ 四个面各有单点真源,互不复制:写口只做权限/归一/落盘(`md_cg/mcp_server.py`),
21
+ 台账只管追加(`md_cg/state_events.py`),投影只管回放(`md_cg/state_slots.py`),
22
+ 查询面只管开关与返回体成形(`md_cg/stg.py`)。
23
+
24
+ ---
25
+
26
+ ## 二、台账(源)在哪、长什么样
27
+
28
+ | 项 | 内容 |
29
+ |---|---|
30
+ | 位置 | 库根下 `_state_events.jsonl`(与 `_recent.jsonl`、`_write_2pc.jsonl` 同级) |
31
+ | 性质 | **append-only**:只追加、不读改写、不截断(窗口滚动面 `_recent.jsonl` 不可作一等记录,故单立此账) |
32
+ | 一行一条 | `{t, subject, slot, old, new, kind, seq, evidence, actor}` |
33
+ | `kind` 五类 | `migration` 迁移 / `retraction` 撤回 / `enablement` 启用 / `acquisition` 获得 / `replacement` 替换;**未分类(None)合法** |
34
+ | 撤回语义 | `old` 有值、`new` 空 = 值作废、无新值;启用=old 空、new 有值;迁移/替换=皆有值 |
35
+ | 坏行 | 容忍 ≠ 静默:跳过时计数 + 有界样本 + stderr 告警(`state_events.BAD_ROWS` 可读) |
36
+ | 多进程 | 跨进程文件锁(`FileLock`),崩溃不留半截文件(flush+fsync) |
37
+
38
+ **记账不判语义**:`kind` 只是检索面标签,不进判据;「不是事实」的言语(玩笑/元层/回忆转述)
39
+ 之消歧标记(`not_fact`)**不在本批**(见 §八 边界)。
40
+
41
+ ---
42
+
43
+ ## 三、写:MCP 记账口 `cg(op=state_event)`
44
+
45
+ ### 用法
46
+
47
+ ```
48
+ cg(op="state_event", subject="鲸娘", slot="住所",
49
+ old="别墅", new="小屋", kind="migration", seq=1108, evidence="r1108")
50
+ ```
51
+
52
+ | 参数 | 必填 | 说明 |
53
+ |---|---|---|
54
+ | `subject` | 是 | 事件主体(谁的状态);去空白后为空即报错 |
55
+ | `slot` | 是 | 事件槽位(哪项状态);同上 |
56
+ | `old` / `new` | 至少一个 | 变更前/后值;**双空非法**(空事件无意义)。撤回=`new` 留空 |
57
+ | `kind` | 否 | 五类之一;缺省/空串/纯空白 → 归一为「未分类」(None);其它值报错 |
58
+ | `seq` | 否 | 轮或序号(回指语料位置用) |
59
+ | `evidence` | 否 | 出处(短证/轮号/文件路径皆可,回查用) |
60
+
61
+ 返回体:`{"ok": true, "event": {…落盘记录…}}`(`event` 即 append 落盘的那一行)。
62
+
63
+ ### 失败口径(fail-closed,不吞)
64
+
65
+ | 情形 | 结果 |
66
+ |---|---|
67
+ | 缺/空 `subject`、缺/空 `slot` | `ValueError`(点名缺哪项) |
68
+ | `old` 与 `new` 双空 | `ValueError` |
69
+ | `kind` 非法值 | `ValueError`(列出允许五类) |
70
+
71
+ 以上都是**原样上抛**的 `ValueError`(不是包装过的错误),客户端按普通错误处置即可——
72
+ **失败即不落盘**。
73
+
74
+ ---
75
+
76
+ ## 四、读:投影与查询
77
+
78
+ ### 1. 查询面 `stg(op=state_chain)`(默认关,见 §五)
79
+
80
+ ```
81
+ stg(op="state_chain", subject="鲸娘", slot="住所", include_retired=true)
82
+ ```
83
+
84
+ 返回体沿 stg 既有口径:`count`(条件命中总数,截断前)/ `items`(前 limit 条)/
85
+ `kept` / `truncated`。单元字段:
86
+
87
+ | 字段 | 语义 |
88
+ |---|---|
89
+ | `value` | 现值(撤回后为 null,直到下一个带值事件复活) |
90
+ | `state` | `active` / `retired`(**退役不删除**;缺省查询剔除 retired,`include_retired=true` 可见) |
91
+ | `t_from` / `t_to`、`seq_from` / `seq_to` | 生效区间与序号:`*_from` =最后产生当前值的事件;`*_to` =覆盖它的下一条事件(未被覆盖=null=仍有效/未闭合) |
92
+ | `tier` | 来源档位(台账行顶层 `tier` 透传;未带=`unspecified`,**不编造**) |
93
+ | `history` | 该槽位全部事件原样七字段(`t/seq/old/new/kind/evidence/actor`);`history=false` 时不带该键 |
94
+ | `alternatives` / `blindspots` | 结构在场、**恒空列表**(判定口径后置,见 §八) |
95
+ | `event_count` | 该槽位事件条数 |
96
+
97
+ **投影是物化视图不是第二真源**:查询时从台账现算,不落盘、不缓存——台账追加一条,
98
+ 下一次查询结果即变。
99
+
100
+ ### 2. CLI 人工入口(`md_cg.state_slots`,**恒可用**)
101
+
102
+ ```
103
+ python -X utf8 -m md_cg.state_slots --status
104
+ python -X utf8 -m md_cg.state_slots --subject 鲸娘 [--slot 住所] [--include-retired] [--no-history]
105
+ ```
106
+
107
+ 数据根取 `MDCG_ROOT`(缺省走 `datapath.mdcg_root()`)。本 CLI 与 `MDCG_STG_STATE`
108
+ 开关**无关**——那把开关管的是 MCP 读面;CLI 是只读人工排查入口(不改任何状态)。
109
+
110
+ ---
111
+
112
+ ## 五、开关
113
+
114
+ | 开关 | 缺省 | 管什么 |
115
+ |---|---|---|
116
+ | `MDCG_STG_STATE` | **关** | MCP 查询面 `stg(op=state_chain)`;关臂返回 `{"error": "disabled", "hint": …}`(**不是异常**——「没开」与「没命中」必须可分辨);与 `MDCG_STG_INDEX`/`MDCG_STG_QUALIFY` 同纪律 |
117
+ | (无开关) | — | `cg(op=state_event)` 记账口**恒可用**(受权限闸约束,见 §六);`md_cg.state_slots` CLI **恒可用** |
118
+
119
+ ---
120
+
121
+ ## 六、授权口径(与既有令牌面零新词)
122
+
123
+ - **`state_event` 走 `write` 词映射**:`cg` 面 op 作用域闸按 `write` 判定——
124
+ 凡 `ops_allow` 白名单含 `write` 的角色(或用 `"*"` 的设计者令牌)可记账;
125
+ guest/只读令牌照拒。令牌面**不引入新 op 词**(角色白名单与派生收窄面零改动)。
126
+ - **`actor` 恒取令牌**(请求参数不生效):落盘 `actor` 永远是令牌身份(无令牌形态为
127
+ `"system"`)——客户端不得改写归属(沿本仓既有防伪造口径)。
128
+ - **写闸双保险**:台账是直写盘面的 append-only 文件、**绕过库层节点写闸**,故记账口
129
+ 另显式补齐 `require_write("internal")`——`can_write` × `theory_ok` × 密级三态各自生效
130
+ (只读令牌、版本层校验未过、clearance 不足 internal 都会被拒且不落盘)。
131
+
132
+ ---
133
+
134
+ ## 七、读数与复跑:探针 + 守卫
135
+
136
+ ### 1. 账本完整性探针(《秤》5.1 口径)
137
+
138
+ ```
139
+ python -X utf8 scripts/probe_c_ledger_integrity.py \
140
+ --events %TEMP%/state_events.jsonl --expect-slots 住所,房贷,名字 \
141
+ [--out %TEMP%/probe_c_out]
142
+ ```
143
+
144
+ | 读数 | 口径 |
145
+ |---|---|
146
+ | ① 事件覆盖缺口率 | `--expect-slots` 清单中「台账无任何记录」的槽位占比(分子/分母都打印) |
147
+ | ② 无账可辨率 | 对「无记录槽位」+固定合成不存在槽位查询 `state_chain`:`count==0 且 items==[]`(**不编造、不反推**)的通过比例 |
148
+ | ③ 变迁史可查率 | 有记录槽位中 `state_chain`(`include_retired=True`、`history=True`)返回的 history 条数合计 == 台账该槽位记录数 的比例 |
149
+
150
+ 特性(硬性):只读输入;隔离 temp root(把 `--events` 拷为该 root 的
151
+ `_state_events.jsonl`)——**零记忆库写入**;`--out` 必须落在仓外(fail-closed);
152
+ **确定性**(同输入两次运行 stdout 与 `--out` 产物字节一致);
153
+ stdout 末行 `PROBE_C_LEDGER_JSON {...}` 摘要(机器可读),`--out` 时另落
154
+ `rates.json` + `probe_c_slots.jsonl`。
155
+
156
+ ### 2. 写口守卫
157
+
158
+ ```
159
+ python -X utf8 -m md_cg.test_state_event_op # 全链/双闸/防伪造/归一/校验/回归
160
+ python -X utf8 -m md_cg.test_state_event_op --mutate # 定点变异自证(每条机制必须能被断言钉红)
161
+ ```
162
+
163
+ ---
164
+
165
+ ## 八、边界(如实)
166
+
167
+ - `alternatives`(同期未决值)/ `blindspots`(声明缺口)判定口径**后置**:本批结构在场、
168
+ 恒空列表,**不臆造填充**。
169
+ - 「不是事实」的言语(玩笑/元层/回忆转述)之**消歧标记**(`not_fact` 等)不在本批
170
+ (P1 事件行无该信号)。
171
+ - 探针只测**账本面**可辨性;**生成器级「无账强答」未测**——那需要接生成器侧读数,后置。
172
+ - 槽位按**标签面精确匹配**(slot 名相等),不做同义归并/模糊匹配。
173
+ - `state_chain` 无 `time_axis` 语义:台账事件行只有落账时间戳 `t`,无第二轴(**不伪造**);
174
+ 需要轴语义请走 `stg` 的 timeline/relation/anchors。
175
+ - 单库=单台账:跨库/多租户合并不在此。
176
+
177
+ ---
178
+
179
+ ## 九、退役纪律:节点生命周期 `archived`(默认检索剔除)
180
+
181
+ > 《秤》v2.1 §5.2「退役纪律」口径的落地页。**先分清两个「退役」**(同名不同物):
182
+
183
+ | 说谁 | 字段 / 参数 | 谁管 |
184
+ |---|---|---|
185
+ | 台账**槽位单元**的生存态(§四) | 投影单元 `state` = `active`/`retired`,查询参数 `include_retired` | `md_cg/state_slots.py`(查询时现算) |
186
+ | **节点**(md 记忆条目)的归档态(本节) | frontmatter / 索引 `lifecycle_state` = `archived` | `md_cg/lifecycle.py` 状态机 + 读面剔除 |
187
+
188
+ ### 1. 语义(写定,逐档可对拍)
189
+
190
+ | `lifecycle_state` | 默认读/注入面(检索面 · stg 面 · 会话续接包全段) | 说明 |
191
+ |---|---|---|
192
+ | `active`(**缺键或非法值同此**) | 参与 | fail-open:存量节点零迁移、不误剔 |
193
+ | `converged` | 参与 | **降权轴**(同构聚合定型),不是退役 |
194
+ | `demoted` | 参与 | **降权轴**(弱化),不是退役 |
195
+ | `archived` | **默认剔除** | 退役不删除:节点文件仍在、可显式恢复 |
196
+
197
+ ### 2. 判据与落点(判据单点,三个消费面)
198
+
199
+ - 判据单点:`lifecycle.is_archived(e)`(`md_cg/lifecycle.py`)≡ `state_of(e) == "archived"`;
200
+ 全部消费点共同引用,不各写一份口径。
201
+ - 消费点 ①(**cg 检索面**):`MdCGOS._candidates`(`md_cg/mdcos.py`)——**检索类** cg 读 op
202
+ (`route` / `read` 的检索分支与 `budget_tokens` 预算召回分支 / `search` / `search_rrf` 及其
203
+ 内含的 lexical·bucket·entity·graph·chain·temporal 各路)都经这一个候选池;
204
+ `MdCGSecure._candidates` 经 `super()` 在其上叠加读可见性,判据同源。
205
+ 注意:cg 的读 op 并非全走候选池——见消费点 ③(会话续接面自持取数面)。
206
+ - 消费点 ②(**stg 扫描面**):`stg._scan_one`(`md_cg/stg.py`,`_scan` 的逐条实现单点)
207
+ ——`timeline` / `anchors` / `consistency` 三 op 的候选面同点覆盖,索引子集
208
+ (`MDCG_STG_INDEX=1`)与全量遍历两条分支逐位一致。`relation` 是显式 id 直读、
209
+ `state_chain` 走台账,两者都不经候选面(不受本节约束)。
210
+ - 消费点 ③(**会话续接注入面**):`MdCGOS.session_recall`(`md_cg/mdcos.py`)的
211
+ **四个取数段**——会话要点 `_session_notes`、活跃目标 `goals`、任务台账 `tasks`、
212
+ 未解问题 `unresolved`(`goals`/`tasks` 经 `_retired_by_id` 按 id 回查索引后交同一
213
+ 判据)。`cg(op=session, action=recall)` 自持取数面(不经 `_candidates`),它把节点
214
+ 内容装配成「续接包」回给调用方/注入上下文(=注入面),故同接本判据。台账两段
215
+ 取**全量窗**(`_LEDGER_WINDOW`)过滤后截断 `_PACK_ROWS=5` 条,故退役剔除不会让
216
+ 包「不足额」;`tasks.active_total/done_total` 随之取**剔除后**的全窗计数(与列表
217
+ 同源自洽)。`recent` 段是事件窗口(非节点)、`self_state` 是只读快照卡,不涉退役。
218
+ (独立复核 2026-10-06 两轮实测:接线前 archived 要点摘要、未解问题正文、活跃目标
219
+ 与任务卡均经该 op 照旧回出;现由守卫 R1.12/R1.13/R3.5/R3.6/R4.6 钉住。)
220
+
221
+ ### 3. 不受限面(「退役不删除」的另一半)
222
+
223
+ - `cg.get(node_id)` 直读、`cg(op=audit)` 证据审计视图:archived 期间**照常可达**;
224
+ - 工程台账面(`goal` / `task`)与统计面(`health` / `whoami` / conformance):直读索引,
225
+ 不受本节约束;
226
+ - **生命周期恢复**:库层入口 `MdCG.set_state(node, "archived"→"active")`
227
+ (`md_cg/mdcg.py:2619` → `lifecycle.set_state`,走合法迁移表、逐级不跳级);恢复后
228
+ 读面/续接面重新可见。**MCP 工具面没有独立生命周期入口**(`mcp_server.py` 全文无
229
+ `set_state` / `lifecycle` 字样)——「显式恢复」是库层调用面。
230
+ - 与 `op=restore` 的区别(易混,写明):`op=restore` 是 `op=forget` 的 `action=restore`
231
+ → `cg.restore`(`md_cg/mdcos.py:3029`)=把**已遗忘**(软删除进 `trash/`)的节点放回,
232
+ 是**删除轴**,与生命周期状态机无关;且放回时 `lifecycle_state` 按新节点(`active`)
233
+ 起判,`active→archived` 跳级被拒 ⇒ **不透传(落 `active`)**(既有行为,本轮未改)。
234
+
235
+ ### 4. 复跑读数
236
+
237
+ ```
238
+ python -X utf8 scripts/probe_d_retirement_discipline.py # 《秤》v2.1 §5.2 探针
239
+ python -X utf8 -m md_cg.test_lifecycle_retire_leak # 守卫 R1–R4
240
+ ```
241
+
242
+ | 读数(`PROBE_D_JSON`) | 口径 | 目标(面计数,括号内为比率) |
243
+ |---|---|---|
244
+ | ① 退役泄漏率 | 退役后 v2 仍出现在查证面(读面 search∪recall、时空面 timeline∪anchors)的面数 / 面数 | `0/2`(0.0) |
245
+ | ② 更新采纳率 | v2 写入后可见的面数 / 面数(防「一刀切全滤」的反向缺陷) | `2/2`(1.0) |
246
+ | ③ 旧事实残留率 | 退役步之后 v1 仍可见的面数 / 面数(不连带误剔) | `2/2`(1.0) |
247
+ | ④ 失效误判证伪率 | 退役节点被错误置 falsified/rejected 的条数 / 退役节点数(退役 ≠ 证伪) | `0/1`(0.0) |
248
+
249
+ (探针人读行打印的就是**面计数**「n/分母(目标 m)」;上表与它同单位,比率为换算值。)
250
+
251
+ 探针特性:隔离 temp root(零在役库写入)、纯 stdlib、无随机/无时间戳、
252
+ `--out` 必须落在仓外(fail-closed)、末行 `PROBE_D_JSON {...}`,**两遍运行 stdout 字节一致**。
253
+
254
+ ### 5. 边界(如实)
255
+
256
+ - 只剔 `archived`。要让 `converged`/`demoted` 不参与,请走既有其他维度
257
+ (`role` / `view` / `layer` / `session` / `validity`)——不得把它们并进退役判据。
258
+ - 台账单元退役(§四 `retired`)与节点退役(本节 `archived`)**各自独立、互不联动**。
259
+ - **面的判据(写死,供后续接线照此归类)**:**默认读/注入面**=调用方给查询/意图/会话视图,
260
+ **节点集合由库自选**且结果直接回给调用方或注入上下文 ⇒ 必须消费 `is_archived`;
261
+ **定向/管理/统计面**=调用方给出**显式节点选择键**(`node_id` / `subject:*` 标签 / 前缀 /
262
+ 层 / 状态)或面本身是诊断·统计·写面 ⇒ 直读,不受本节约束。
263
+ - 已接线消费面(3 处,4 子面):检索面 `_candidates`、stg 面 `_scan_one`、会话续接注入面
264
+ `session_recall` 的**全部四个取数段**(要点 `_session_notes` + 活跃目标 + 任务台账 +
265
+ 未解问题;后两段经 `_retired_by_id` 按 id 判据)(§2)。
266
+ - **已枚举但归入「定向/管理/统计面」(不受限,逐条申报)**:`cg.get` 直读、`op=audit`
267
+ 证据审计、**工程台账的显式管理查询面**(`cg(op=goal, action=list)` / `cg(op=task,
268
+ action=list)`——直读台账,archived 期间照样列出,守卫 R1.13c 钉住这一侧)、
269
+ `health`/`whoami`/`_role_counts`/`_sensitivity_counts`/`conformance`/`census`/`insight`
270
+ 统计、`review_records` 审核记录、`export`/`evidence` 导出与证据面、`crosscheck`/
271
+ `ghostref`/`consistency` 诊断面、`backfill*`/`writelimit`/`freshness`/`forgetting`
272
+ 维护写面、`mreview/govern` 治理面、白箱 KB 工具面。
273
+ **注意别与消费点 ③ 混读**:同一份 goal/task 台账,**注入面(续接包)剔除 archived、
274
+ 管理查询面直读**——这不是矛盾,是判据两侧的分工(守卫同时钉住两侧:R1.13b 剔除、
275
+ R1.13c 直读)。
276
+ 其中**会回内容且集合由库自选**的一个代表面如实点名:`identity.profile`
277
+ (`md_cg/identity.py:310`,按 `subject:<id>` 标签自选并回锚点正文摘录)——实测 archived
278
+ 锚点仍回出(取证:`identity.profile` 返回的 `anchors[0].content` 含归档节点正文标记);
279
+ 按上条判据它属**定向面**(`subject_id` 是显式选择键,与 `cg.get` 同族),故**本轮未接线**
280
+ (其文件不在本轮允许改动面内)。
281
+ - 已知未覆盖面(如实,**本轮不修**——均落在本轮允许改动面之外,须单独立项裁定):
282
+ - 基类 `MdCG.search`(`md_cg/mdcg.py:3677`):**plain `MdCG` 实例**(白箱 KB / 离线
283
+ 脚本 / 测试)走的默认检索面未接本判据,archived 仍出现在其候选里(取证:同一
284
+ 序列下 `MdCG` 实例 search 命中 `['a_v1','a_v2']`,`MdCGOS` 实例命中 `['a_v1']`);
285
+ MCP 工具面(`MdCGOS`/`MdCGSecure`)不受影响。
286
+ - **因果链/图面** `chain.adjacency`(`md_cg/chain.py:162`):以全部索引条目建出邻接表,
287
+ 只过读可见性闸(`_chain_visible`)、无 lifecycle 判据——`cg(op=causal, action=chain,
288
+ node_id=<种子>)` 会**扩散**到 archived 节点(取证:链里出现已归档的 `b_tgt`);
289
+ 检索面的 chain 路不受影响(其结果受 `_candidates` 的 entries 约束,守卫 R1.11 钉住)。
290
+ - **结构/拓扑面** `subgraph.children_index` / `parents_index`(`md_cg/subgraph.py:109` /
291
+ `:154`):同族 O(N) 结构索引,未接 lifecycle 判据(返回 id 映射、不回正文)。
292
+ - **rust 检索内核**(`rust/src/store.rs::load_index` + `engine.rs`):直读 `_index.json`
293
+ 条目、自带检索实现,全目录 `lifecycle`/`archived` 零命中(无退役处理)。
294
+ - 跨进程一致性:判据只读**本进程索引条目**(`lifecycle_state` 由
295
+ `lifecycle._sync_index` 随迁移同步并落 `_index_log`),他进程刚归档、本进程索引
296
+ 尚未重载的窗口内读数可能滞后(与 `lifecycle.set_state` 的既有落盘口径同源)。
297
+
298
+ ---
299
+
300
+ ## 修订记录
301
+
302
+ | 日期 | 要点 |
303
+ |---|---|
304
+ | 2026-10-06 | v1.0 首版(P3 批):全链(台账→投影→查询→记账口→CLI→探针)/ 开关 `MDCG_STG_STATE` 默认关与 CLI 恒可用 / 授权口径(`state_event`→`write` 词映射,actor 恒取令牌)/ 探针三读数复跑命令 / 边界如实(§一–§八) |
305
+ | 2026-10-06 | 补 §九「退役纪律」:节点 `lifecycle_state=archived` 的默认检索剔除(判据单点 `lifecycle.is_archived`,消费面 `MdCGOS._candidates` + `stg._scan_one` + 会话续接注入面 `session_recall` 四段〔要点/活跃目标/任务台账/未解问题〕)/ 两套「退役」词义分界 / 不受限面(直读·审计·**台账管理查询面**·统计)与「生命周期恢复 ≠ `op=restore`(删除轴)」/ 《秤》5.2 探针四读数(面计数口径)与守卫复跑 / 边界如实(未覆盖面:基类 `MdCG.search`、因果链面 `chain.adjacency`、结构面 `subgraph`、rust 内核、定向面 `identity.profile`) |
@@ -37,47 +37,48 @@ MCP stdio:md_cg/mcp_server.py
37
37
 
38
38
  <!-- FUNCMAP:BEGIN id=cg (scripts/cogmap_sync.py 自动生成 · 勿手改段内) -->
39
39
 
40
- **认知基元 `cg` · 37 个 op**(行号由本管线从真源自动提取,`check` 门禁守卫漂移):
40
+ **认知基元 `cg` · 38 个 op**(行号由本管线从真源自动提取,`check` 门禁守卫漂移):
41
41
 
42
42
  | 功能 | 显式调用 | 代码位置(点击直达源码行) |
43
43
  |---|---|---|
44
- | 按需披露(投影后完整工具 / 参数文档即时取回) | `cg(op=help)` | [`help`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2107) → [`_help_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2025) |
45
- | 验证态 / 双时间轴 / 履历(含冷路径队列;只读) | `cg(op=status)` | [`status`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2113) → [`_status_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1940) |
46
- | 三元组反查(派生边任意端 / 谓词 / 时间反查;只读) | `cg(op=edges)` | [`edges`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2116) → [`_edges_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1996) |
47
- | 理论检索(领域理论 / 方法论文) | `cg(op=theory)` | [`theory`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2119) → [`theory`](../../md_cg/theory.py) |
48
- | 记忆互链(节点间链接管理) | `cg(op=link)` | [`link`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2136) → [`evidence`](../../md_cg/evidence.py) → [`links`](../../md_cg/links.py) → [`provenance`](../../md_cg/provenance.py) → [`security`](../../md_cg/security.py) → [`signer`](../../md_cg/signer.py) |
49
- | 服务信息 / 健康 | `cg(op=info)` | [`info`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2252) → [`audit`](../../md_cg/audit.py) → [`generation`](../../md_cg/generation.py) → [`links`](../../md_cg/links.py) → [`nodefile`](../../md_cg/nodefile.py) → [`theory`](../../md_cg/theory.py) |
50
- | 路由:意图→知识+建议能力 | `cg(op=route)` | [`route`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2293) |
51
- | 读取(按 id / 召回 / 预算) | `cg(op=read)` | [`read`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2314) → [`refindex`](../../md_cg/refindex.py) |
52
- | 证据审计视图(现值/出处链/两存备择/盲区/退役史;只读) | `cg(op=audit)` | [`audit`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2369) → [`auditview`](../../md_cg/auditview.py) |
53
- | 写入(含冲突检测 / 闸门 / 审核) | `cg(op=write)` | [`write`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2389) → [`writepipe`](../../md_cg/writepipe.py) |
54
- | 目标(写入 / 状态 / 清单) | `cg(op=goal)` | [`goal`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2397) |
55
- | 任务实体(登记 / 计划 / 状态 / 结果;done 无结果拒收) | `cg(op=task)` | [`task`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2416) → [`_task_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2038) |
56
- | 最近记忆(事件窗口) | `cg(op=recent)` | [`recent`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2419) |
57
- | 外部裁决回填(节点证据验证) | `cg(op=verify)` | [`verify`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2431) |
58
- | 审核队列(DEFER / 提案裁决) | `cg(op=review)` | [`review`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2436) |
59
- | 主动遗忘 / 恢复 | `cg(op=forget)` | [`forget`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2457) |
60
- | 保护(不可遗忘) | `cg(op=protect)` | [`protect`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2466) → [`_protect_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1235) |
61
- | 身份维度 | `cg(op=identity)` | [`identity`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2469) → [`_identity_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1263) |
62
- | 一致性检测 | `cg(op=consistency)` | [`consistency`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2472) → [`_consistency_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1314) |
63
- | 元认知(盲区聚合) | `cg(op=metacognition)` | [`metacognition`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2475) → [`_metacognition_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1343) |
64
- | 自我状态 | `cg(op=self_state)` | [`self_state`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2478) → [`_self_state_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1378) |
65
- | 演化(记忆结构演化) | `cg(op=evolution)` | [`evolution`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2481) → [`_evolution_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1513) |
66
- | 飞轮 / 自愈 | `cg(op=sustain)` | [`sustain`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2484) → [`_sustain_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1605) |
67
- | 洗脑 / 去污染 | `cg(op=scrub)` | [`scrub`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2487) → [`_scrub_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1726) |
68
- | 预测 / 因果门 | `cg(op=predict)` | [`predict`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2490) → [`_predict_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1440) |
69
- | 因果链 | `cg(op=causal)` | [`causal`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2493) → [`_causal_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1474) |
70
- | 白箱能力库(AEIS 能力显式调用) | `cg(op=whitebox)` | [`whitebox`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2496) → [`_whitebox_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3169) |
71
- | 代码索引 | `cg(op=index_code)` | [`index_code`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2499) → [`refindex`](../../md_cg/refindex.py) → [`security`](../../md_cg/security.py) |
72
- | 文档索引 | `cg(op=index_doc)` | [`index_doc`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2543) → [`refindex`](../../md_cg/refindex.py) → [`security`](../../md_cg/security.py) |
73
- | 引用 / 反向引用 | `cg(op=ref)` | [`ref`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2586) → [`_ref_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3069) |
74
- | 会话管理(多会话归属与过滤) | `cg(op=session)` | [`session`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2589) → [`_session_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2790) |
75
- | 导入落图 | `cg(op=ingest)` | [`ingest`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2592) → [`_ingest_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2869) |
76
- | 导出 | `cg(op=export)` | [`export`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2595) → [`_export_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2894) |
77
- | 维护 | `cg(op=maintain)` | [`maintain`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2598) → [`_maintain_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2916) |
78
- | 记忆固化 / 整理 | `cg(op=consolidate)` | [`consolidate`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2601) → [`_consolidate_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2994) |
79
- | 洞察 / 自主探索(信息差驱动) | `cg(op=insight)` | [`insight`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2604) → [`_insight_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3019) |
80
- | CCG 六要素编译(对话→候选→编外复核→落库) | `cg(op=ccg)` | [`ccg`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2607) → [`_ccg_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2614) |
44
+ | 按需披露(投影后完整工具 / 参数文档即时取回) | `cg(op=help)` | [`help`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2125) → [`_help_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2043) |
45
+ | 状态事件记账(追加五元事件;查询走 stg(state_chain)) | `cg(op=state_event)` | [`state_event`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2452) |
46
+ | 验证态 / 双时间轴 / 履历(含冷路径队列;只读) | `cg(op=status)` | [`status`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2134) → [`_status_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1958) |
47
+ | 三元组反查(派生边任意端 / 谓词 / 时间反查;只读) | `cg(op=edges)` | [`edges`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2137) → [`_edges_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2014) |
48
+ | 理论检索(领域理论 / 方法论文) | `cg(op=theory)` | [`theory`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2140) → [`theory`](../../md_cg/theory.py) |
49
+ | 记忆互链(节点间链接管理) | `cg(op=link)` | [`link`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2157) → [`evidence`](../../md_cg/evidence.py) → [`links`](../../md_cg/links.py) → [`provenance`](../../md_cg/provenance.py) → [`security`](../../md_cg/security.py) → [`signer`](../../md_cg/signer.py) |
50
+ | 服务信息 / 健康 | `cg(op=info)` | [`info`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2273) → [`audit`](../../md_cg/audit.py) → [`generation`](../../md_cg/generation.py) → [`links`](../../md_cg/links.py) → [`nodefile`](../../md_cg/nodefile.py) → [`theory`](../../md_cg/theory.py) |
51
+ | 路由:意图→知识+建议能力 | `cg(op=route)` | [`route`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2314) |
52
+ | 读取(按 id / 召回 / 预算) | `cg(op=read)` | [`read`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2335) → [`refindex`](../../md_cg/refindex.py) |
53
+ | 证据审计视图(现值/出处链/两存备择/盲区/退役史;只读) | `cg(op=audit)` | [`audit`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2390) → [`auditview`](../../md_cg/auditview.py) |
54
+ | 写入(含冲突检测 / 闸门 / 审核) | `cg(op=write)` | [`write`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2410) → [`writepipe`](../../md_cg/writepipe.py) |
55
+ | 目标(写入 / 状态 / 清单) | `cg(op=goal)` | [`goal`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2418) |
56
+ | 任务实体(登记 / 计划 / 状态 / 结果;done 无结果拒收) | `cg(op=task)` | [`task`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2437) → [`_task_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2056) |
57
+ | 最近记忆(事件窗口) | `cg(op=recent)` | [`recent`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2440) |
58
+ | 外部裁决回填(节点证据验证) | `cg(op=verify)` | [`verify`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2472) |
59
+ | 审核队列(DEFER / 提案裁决) | `cg(op=review)` | [`review`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2477) |
60
+ | 主动遗忘 / 恢复 | `cg(op=forget)` | [`forget`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2498) |
61
+ | 保护(不可遗忘) | `cg(op=protect)` | [`protect`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2507) → [`_protect_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1253) |
62
+ | 身份维度 | `cg(op=identity)` | [`identity`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2510) → [`_identity_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1281) |
63
+ | 一致性检测 | `cg(op=consistency)` | [`consistency`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2513) → [`_consistency_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1332) |
64
+ | 元认知(盲区聚合) | `cg(op=metacognition)` | [`metacognition`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2516) → [`_metacognition_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1361) |
65
+ | 自我状态 | `cg(op=self_state)` | [`self_state`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2519) → [`_self_state_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1396) |
66
+ | 演化(记忆结构演化) | `cg(op=evolution)` | [`evolution`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2522) → [`_evolution_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1531) |
67
+ | 飞轮 / 自愈 | `cg(op=sustain)` | [`sustain`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2525) → [`_sustain_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1623) |
68
+ | 洗脑 / 去污染 | `cg(op=scrub)` | [`scrub`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2528) → [`_scrub_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1744) |
69
+ | 预测 / 因果门 | `cg(op=predict)` | [`predict`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2531) → [`_predict_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1458) |
70
+ | 因果链 | `cg(op=causal)` | [`causal`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2534) → [`_causal_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L1492) |
71
+ | 白箱能力库(AEIS 能力显式调用) | `cg(op=whitebox)` | [`whitebox`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2537) → [`_whitebox_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3210) |
72
+ | 代码索引 | `cg(op=index_code)` | [`index_code`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2540) → [`refindex`](../../md_cg/refindex.py) → [`security`](../../md_cg/security.py) |
73
+ | 文档索引 | `cg(op=index_doc)` | [`index_doc`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2584) → [`refindex`](../../md_cg/refindex.py) → [`security`](../../md_cg/security.py) |
74
+ | 引用 / 反向引用 | `cg(op=ref)` | [`ref`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2627) → [`_ref_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3110) |
75
+ | 会话管理(多会话归属与过滤) | `cg(op=session)` | [`session`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2630) → [`_session_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2831) |
76
+ | 导入落图 | `cg(op=ingest)` | [`ingest`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2633) → [`_ingest_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2910) |
77
+ | 导出 | `cg(op=export)` | [`export`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2636) → [`_export_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2935) |
78
+ | 维护 | `cg(op=maintain)` | [`maintain`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2639) → [`_maintain_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2957) |
79
+ | 记忆固化 / 整理 | `cg(op=consolidate)` | [`consolidate`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2642) → [`_consolidate_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3035) |
80
+ | 洞察 / 自主探索(信息差驱动) | `cg(op=insight)` | [`insight`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2645) → [`_insight_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3060) |
81
+ | CCG 六要素编译(对话→候选→编外复核→落库) | `cg(op=ccg)` | [`ccg`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2648) → [`_ccg_call`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L2655) |
81
82
 
82
83
  <!-- FUNCMAP:END -->
83
84
 
@@ -92,14 +93,15 @@ MCP stdio:md_cg/mcp_server.py
92
93
 
93
94
  <!-- FUNCMAP:BEGIN id=stg (scripts/cogmap_sync.py 自动生成 · 勿手改段内) -->
94
95
 
95
- **语义时空基元 `stg` · 4 个 op**:
96
+ **语义时空基元 `stg` · 5 个 op**:
96
97
 
97
98
  | 功能 | 显式调用 | 代码位置(点击直达源码行) |
98
99
  |---|---|---|
99
- | 两节点关系 | `stg(op=relation)` | [`relation`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3199) |
100
- | 时间线 | `stg(op=timeline)` | [`timeline`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3201) |
101
- | 锚点检索(时空窗口) | `stg(op=anchors)` | [`anchors`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3208) |
102
- | 时空一致性 | `stg(op=consistency)` | [`consistency`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3212) |
100
+ | 两节点关系 | `stg(op=relation)` | [`relation`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3240) |
101
+ | 时间线 | `stg(op=timeline)` | [`timeline`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3242) |
102
+ | 锚点检索(时空窗口) | `stg(op=anchors)` | [`anchors`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3249) |
103
+ | 时空一致性 | `stg(op=consistency)` | [`consistency`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3253) |
104
+ | 状态槽位投影(现值 / 区间 / 变迁史) | `stg(op=state_chain)` | [`state_chain`](https://github.com/FuRongJun-1999/dsh-memory/blob/main/md_cg/mcp_server.py#L3256) |
103
105
 
104
106
  <!-- FUNCMAP:END -->
105
107
 
package/lib/hooks.js CHANGED
@@ -46,6 +46,9 @@ import '@deepseek-ai/dsh-session';
46
46
  import '@deepseek-ai/dsh-system-prompt';
47
47
  import { escapePromptBraces, renderUntrustedMemoryBlock } from './lib/prompt_safety.js';
48
48
  import { HookAuditRecorder, kindOf } from './lib/hook_audit.js';
49
+ // 运行期会话状态单点(B 治本批):观测在 hooks 面,写归因注入在工具面
50
+ // (src/tools.ts)——两处共用同一状态,见 lib/session_state.ts 头注。
51
+ import { currentSession, noteSession, UNASSIGNED_SESSION } from './lib/session_state.js';
49
52
  /** 从 ContentBlock[] 提取纯文本。 */
50
53
  function extractText(blocks) {
51
54
  const parts = [];
@@ -291,16 +294,8 @@ function sessionIdOf(raw) {
291
294
  const v = s?.id ?? s?.sessionId;
292
295
  return typeof v === 'string' ? v.trim() : '';
293
296
  }
294
- /** 会话归属未知时的**显式占位**(H2③,2026-09-30)。
295
- *
296
- * ⚠️ 不可退回「不传 session 键」:md_cg 的 `Principal.__init__` 在 session 为假值时
297
- * 生成**进程级随机** `sess_<hex>`(md_cg/security.py:117)——插件不传,等于让一个
298
- * 进程内所有「宿主未给标识」的会话共用一个**不可辨认**的随机桶:归属在审计上既
299
- * 读不出是谁、跨进程也对不上,是静默的归属丢失。
300
- * 本常量把这一态写成**显式值**:跨进程一致、可辨认、可审计,且不是伪造的宿主
301
- * 会话 id(非 DSH 形态,服务端 `_normalize_session` 原样采用、不会被改写成别的桶)。
302
- * 要读这个桶:`stg(op=timeline, session="unassigned")`。 */
303
- const UNASSIGNED_SESSION = 'unassigned';
297
+ // UNASSIGNED_SESSION(会话归属未知时的显式占位常量)单点已移至
298
+ // lib/session_state.ts(B 治本批:本文件与工具面共用同一常量与同一会话状态)。
304
299
  /** H1 **会话级**判据:这条 session 是否「子代理/委派子会话」。
305
300
  *
306
301
  * 字段来源(DSH 类型面,dsh-session/lib/types/types.d.ts):实装 DSH 2.0
@@ -369,8 +364,24 @@ export function installMemoryHooks(ctx, mdcg, opts) {
369
364
  * 「写入失败/漏记」。审计失败静默降级(见 src/lib/hook_audit.ts),
370
365
  * 绝不冒泡进记忆路径、不改任何写入/过滤判定。 */
371
366
  const audit = new HookAuditRecorder(opts.auditPath);
372
- /** 最近一次观测到的宿主会话标识(见 sessionIdOf;空串 = 未知/无会话)。 */
373
- let lastSession = '';
367
+ /** 本实例是否曾观测到会话(B 治本批)。
368
+ *
369
+ * 会话状态本体是**进程级单点**(lib/session_state.ts;hooks 面观测、工具面
370
+ * src/tools.ts 的写归因注入共用);而「本实例有没有观测过」是**实例级**事实:
371
+ * 多实例并存时(测试;或宿主重装钩子),不得让**别的实例**的观测替本实例决定
372
+ * 召回过滤——否则新装的钩子在尚未观测到会话时就按别的实例的会话去读
373
+ * (读错会话,正是 P45 会话隔离要防的形态)。真机单实例下两者等价:首个
374
+ * session/event 之前模块状态为空,之后回落值恒为同一单点值。
375
+ *
376
+ * ⚠️ 这是**经 owner 裁定的契约字面偏离(dwfq-7b3a555e-1)**:契约给的形态是
377
+ * 下方回落处直接 `|| currentSession()`(无本门);但字面形态与硬边界
378
+ * 「test/session-attribution.test.ts 逐字未动且全绿」互斥——该守卫 ② 以
379
+ * 「新建 harness = 未观测」为前提,字面回落会读成前一实例的 sess_B。裁定
380
+ * 接受本门,两条理由:① 保留原闭包变量「新实例 = 干净状态」的**有意**语义
381
+ * (新装钩子未观测时不加召回过滤);② 冻结守卫零误伤。真机单实例与字面
382
+ * **逐位等价**(差异窗口「本实例未观测 ∧ 模块单点非空」单实例下不可达;
383
+ * HMR 重载时新实例回落 '' 属更保守行为)。 */
384
+ let observedSession = false;
374
385
  /** 记忆沉淀(fire-and-forget)。认知图未就绪则跳过并告警(不退回 AEIS)。
375
386
  * `role`=null 表示**读预热**(user-recall)——审计只统计写入路径,
376
387
  * 故读预热不参与 written/skipped 计数(它不写记忆)。 */
@@ -426,7 +437,13 @@ export function installMemoryHooks(ctx, mdcg, opts) {
426
437
  // 想读**所有**会话做了什么:别走自动召回(它会串台),显式调
427
438
  // `stg(op=timeline, session="*")`,返回项带 session 归属。
428
439
  const hostCtx = _ctx;
429
- const sid = sessionIdOf(hostCtx?.agent?.session) || lastSession;
440
+ // 回落 = **本实例观测门 × 模块单点值**(裁定项 dwfq-7b3a555e-1,见上方
441
+ // observedSession 注释):本实例尚未观测 → 回落 ''(保持「新实例 =
442
+ // 干净状态」,与 test/session-attribution.test.ts ② 的「未观测 → 不加
443
+ // 过滤」相容);已观测 → 取 lib/session_state.ts 的进程级单点值。
444
+ // 真机单实例下两者逐位等价(差异窗口不可达)。
445
+ const sid = sessionIdOf(hostCtx?.agent?.session)
446
+ || (observedSession ? currentSession() : '');
430
447
  const text = formatTimelineDecayed(await graph.timeline(recallLimit, sid ? { session: sid } : {}));
431
448
  if (text) {
432
449
  // 注入边界转义(issue #16):宿主 system-prompt 对 context 文本做严格
@@ -451,8 +468,9 @@ export function installMemoryHooks(ctx, mdcg, opts) {
451
468
  }
452
469
  ctx.on('session/event', (session, event) => {
453
470
  // H1(2026-09-30)**会话级**判据:子代理/委派子会话的自动记忆**整条会话**拦掉。
454
- // 位置在取 sid **之前**——子代理会话不得污染 lastSession,否则顶层会话的自动
455
- // 召回会拿子代理的 session 去读(读错会话)。字段缺失即不拦,见 isSubagentSession。
471
+ // 位置在取 sid **之前**——子代理会话不得污染会话状态(lib/session_state.ts
472
+ // 单点),否则顶层会话的自动召回会拿子代理的 session 去读(读错会话)。
473
+ // 字段缺失即不拦,见 isSubagentSession。
456
474
  if (isSubagentSession(session)) {
457
475
  ctx.logger.info('dsh-memory: 子代理会话的自动记忆被拦(H1:header.origin/delegationDepth)');
458
476
  audit.filtered('subagent');
@@ -460,10 +478,14 @@ export function installMemoryHooks(ctx, mdcg, opts) {
460
478
  }
461
479
  // 会话归属(P45):记忆写入必须带会话身份,用来区分不同会话的记忆。
462
480
  // 空串 = 宿主未给出会话标识 → **显式标注 unassigned**(H2③:不落内核的进程级
463
- // 随机 sess_*,也不编造宿主会话 id——见 UNASSIGNED_SESSION 的注释)。
481
+ // 随机 sess_*,也不编造宿主会话 id——见 lib/session_state.ts 的常量注释)。
464
482
  const sid = sessionIdOf(session);
465
- if (sid)
466
- lastSession = sid;
483
+ // 观测即记录(B 治本批):注入单点在 lib/session_state.ts——工具面
484
+ // (src/tools.ts 的写归因转发)读同一个状态;位置不动(H1 子代理闸之后)。
485
+ if (sid) {
486
+ noteSession(sid);
487
+ observedSession = true;
488
+ }
467
489
  const sessionTag = sid ? { session: sid } : { session: UNASSIGNED_SESSION };
468
490
  if (event.type === 'user/message' && opts.userMessage) {
469
491
  // 落盘审计(issue #56):source.kind 分布——先于两级判据记录**完整**输入分布
@@ -0,0 +1,56 @@
1
+ /**
2
+ * session_state.ts —— 插件侧「运行期会话状态」单点(观测 → 写归因注入)
3
+ *
4
+ * 为什么有这个模块(B 治本批,2026-10-06)
5
+ * ----------------------------------------
6
+ * DSH 单进程多会话:宿主的会话标识只经 `session/event` 到达插件。此前它只被
7
+ * 用在 hooks 面(自动记忆的 remember / read 带 extra.session);**agent 直调
8
+ * 工具面**(src/tools.ts 的 execute → bridge.callTool)转发时**不带会话**——
9
+ * 而部署侧 `MDCG_SESSION` env 一旦取消/为空,`md_cg/mcp_server.py` 的
10
+ * `_declared_session`(:3823-3850)就以**请求声明**为归因来源
11
+ * (优先级:env > 请求声明 > 进程身份),不传即落回进程身份——md_cg 的
12
+ * `Principal.__init__` 会为假值 session 生成**进程级随机** `sess_<hex>`
13
+ * (md_cg/security.py:117):归属在审计上既读不出是谁、跨进程也对不上,
14
+ * 是静默的归属丢失。
15
+ *
16
+ * 本模块把「观测会话」与「写归因注入」收成**单点**:
17
+ * · hooks 面:每收到 session/event 就 `noteSession(sid)`——调用点仍在 H1
18
+ * 子代理闸**之后**(子代理会话不得污染会话状态的位置不变量保持);
19
+ * · 工具面:写归因调用注入 `currentSession() || UNASSIGNED_SESSION`
20
+ * (判据矩阵见 `attributeSession`,只注入写面;读面一律不注入)。
21
+ *
22
+ * 模块级状态(`lastSession`)是**进程级**的:同一进程内多个会话共享它,
23
+ * 「最近一次观测」即当前活动会话——与 hooks 面的既有口径一致(见
24
+ * test/session-attribution.test.ts ④「取值每步稳定」)。
25
+ */
26
+ /** 会话归属未知时的**显式占位**(H2③,2026-09-30;原定义在 src/hooks.ts,
27
+ * B 治本批迁入本单点——注释要点保真搬迁)。
28
+ *
29
+ * ⚠️ 不可退回「不传 session 键」:md_cg 的 `Principal.__init__` 在 session 为假值时
30
+ * 生成**进程级随机** `sess_<hex>`(md_cg/security.py:117)——插件不传,等于让一个
31
+ * 进程内所有「宿主未给标识」的会话共用一个**不可辨认**的随机桶:归属在审计上既
32
+ * 读不出是谁、跨进程也对不上,是静默的归属丢失。
33
+ * 本常量把这一态写成**显式值**:跨进程一致、可辨认、可审计,且不是伪造的宿主
34
+ * 会话 id(非 DSH 形态,服务端 `_normalize_session` 原样采用、不会被改写成别的桶)。
35
+ * 要读这个桶:`stg(op=timeline, session="unassigned")`。 */
36
+ export declare const UNASSIGNED_SESSION = "unassigned";
37
+ /** 记录一次会话观测(H2③ 观测面单点)。
38
+ *
39
+ * trim 后非空才写入——空串/纯空白**不覆盖**旧值(否则「宿主给了一次空标识」
40
+ * 会把已观测到的真会话抹掉,后续注入退化为 unassigned)。 */
41
+ export declare function noteSession(sid: string): void;
42
+ /** 当前运行期会话标识(空串 = 未观测到;调用方按 `|| UNASSIGNED_SESSION` 兜底)。 */
43
+ export declare function currentSession(): string;
44
+ /** 把**运行期会话**注入**写归因调用**(args 的 session 键不可用时才注入)。
45
+ *
46
+ * 注入条件:`session` 键缺失 / 非 string 类型 / trim 后空串 ⇒ 注入
47
+ * (`null`/`''`/空白一律视为「未声明」——服务端 `_declared_session` 对假值
48
+ * 同样解析为无归属声明,原样转发只会落回进程级随机 sess_* 兜底桶);
49
+ * 显式非空声明一律**不覆盖**(调用方自报优先——插件不替调用方改归属)。
50
+ *
51
+ * 注入值:`currentSession() || UNASSIGNED_SESSION`(未观测到会话时用
52
+ * 'unassigned' 显式占位——与 hooks 面 H2③ 同口径)。
53
+ *
54
+ * 命中且需注入 → 返回**新对象** `{ ...args, session: v }`(绝不 mutate 输入);
55
+ * 否则**原样返回**(同一引用)——未命中的调用零开销、零可观察差异。 */
56
+ export declare function attributeSession(toolName: string, args: Record<string, unknown>): Record<string, unknown>;