@a9i5k4/dsh-auto-memory 2.2.2 → 2.2.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/A3-RISK-ASSESSMENT-20260830.md +61 -0
- package/docs/COT-WATCH-RFC.md +88 -0
- package/docs/DUAL-TIER-RATIFICATION-PROMPT.md +71 -0
- package/docs/HANDOFF-HARNESS.md +78 -0
- package/docs/HANDOFF-M8-M9-M10.md +203 -0
- package/docs/HY4-TOUR-LOGO-HANDOFF-2.md +60 -0
- package/docs/HY4-TOUR-LOGO-HANDOFF.md +100 -0
- package/docs/ISSUE-REPLY-UNATTENDED.md +31 -0
- package/docs/K3-LANDING-HANDOFF.md +76 -0
- package/docs/LANDING-OUTLINE.md +85 -0
- package/docs/M-CM-PLAN.md +166 -0
- package/docs/M-CM-STATE.md +64 -0
- package/docs/M3B-CONTRACT.md +461 -0
- package/docs/M4-CONTRACT.md +1207 -0
- package/docs/M5-CONTRACT.md +383 -0
- package/docs/M6-CONTRACT.md +342 -0
- package/docs/M7-ACTIVATION-ALGO-REFERENCES.md +104 -0
- package/docs/M7-ACTIVATION-CALIBRATION.md +144 -0
- package/docs/M7-ACTIVATION-FEATURE-AGENT-PROMPT.md +79 -0
- package/docs/M7-ACTIVATION-FEATURE-CALIBRATION.md +58 -0
- package/docs/M7-ACTIVATION-FEATURE-DESIGN.md +124 -0
- package/docs/M7-ACTIVATION-V2-CONTROLLED-SHADOW.md +127 -0
- package/docs/M7-ACTIVATION-V2-HANDOFF.md +132 -0
- package/docs/M7-ACTIVATION-V2-HOLDEDOUT-EVAL.md +94 -0
- package/docs/M7-ACTIVATION-V2-HOLDEDOUT-SHADOW.md +60 -0
- package/docs/M7-ACTIVATION-V2-LIVE-SHADOW-PLAN.md +85 -0
- package/docs/M7-ACTIVATION-V2-PAPER.md +303 -0
- package/docs/M7-AGENT-HANDOFF-PROMPT.md +63 -0
- package/docs/M7-ALGORITHM-DECISION.md +174 -0
- package/docs/M7-AUTONOMOUS-STATE.md +252 -0
- package/docs/M7-BENCHMARK-PLAN.md +78 -0
- package/docs/M7-CLOSED-LOOP-WIRING.md +110 -0
- package/docs/M7-EMBEDDING-BENCHMARK.md +164 -0
- package/docs/M7-INTERFACE-DIGEST.md +144 -0
- package/docs/M7-LABEL-REVIEW-REPORT.md +107 -0
- package/docs/M7-LEXICAL-TUNING.md +58 -0
- package/docs/M7-LIVE-SHADOW-SCRIPT.md +30 -0
- package/docs/M7-PYTHON-IMPLEMENTATION-REPORT.md +92 -0
- package/docs/M7-RESEARCH-PAPER.md +442 -0
- package/docs/M7-TASKSET-DISPATCH.md +213 -0
- package/docs/M8-MEMORY-HUB.md +105 -0
- package/docs/MEMORY-SYSTEMS-SURVEY-2026-09.md +166 -0
- package/docs/NEXT-MAJOR-PROMO.md +363 -0
- package/docs/NEXT-MAJOR-README-DRAFT.zh.md +205 -0
- package/docs/NEXT-MAJOR-VISION.md +112 -0
- package/docs/PREVIEW-NEXT-STEPS.md +229 -0
- package/docs/PROJECT-FREEZE-AND-ROADMAP.md +200 -0
- package/docs/PROMO-STYLE-GUIDE.md +84 -0
- package/docs/PYTHON-SIDECAR-CONTRACT.md +539 -0
- package/docs/R2-POLICY-PLUMBING-BLUEPRINT.md +99 -0
- package/docs/RELEASE-READINESS-PLAN.md +91 -0
- package/docs/RELEASE-SEMANTIC-OPTION.md +181 -0
- package/docs/S1-SCIENTIFIC-RIGOR.md +269 -0
- package/docs/S2-DEEP-ABSORPTION.md +259 -0
- package/docs/S3-TARGET-ARCHITECTURE.md +172 -0
- package/docs/USER-GUIDE.zh-CN.md +283 -0
- package/docs/banner.jpg +0 -0
- package/docs/implementation-handoff-context.zh-CN.md +429 -0
- package/docs/landing/index.html +1745 -0
- package/docs/paper-figures/fig1_model_quality.png +0 -0
- package/docs/paper-figures/fig2_chunk_reversal.png +0 -0
- package/docs/paper-figures/fig3_latency.png +0 -0
- package/docs/paper-figures/fig4_hybrid.png +0 -0
- package/docs/paper-figures/fig5_rerank_tradeoff.png +0 -0
- package/docs/paper-figures/fig6_cluster_sweep.png +0 -0
- package/docs/paper-figures/fig7_resource.png +0 -0
- package/docs/paper-figures-v2/fig1_echo_trap.png +0 -0
- package/docs/paper-figures-v2/fig2_pr_paths.png +0 -0
- package/docs/paper-figures-v2/fig3_coefficients.png +0 -0
- package/docs/paper-figures-v2/fig4_calibration.png +0 -0
- package/docs/paper-figures-v2/fig5_order_ablation.png +0 -0
- package/docs/paper-figures-v2/fig6_containment.png +0 -0
- package/docs/proactive-associative-memory-architecture.html +659 -0
- package/docs/proactive-associative-memory-meta-code.html +1058 -0
- package/docs/proactive-associative-memory-research-report.zh-CN.md +685 -0
- package/docs/proactive-associative-memory-system-map.html +1580 -0
- package/docs/promo/first-run-guide.html +397 -0
- package/docs/promo/homepage.html +384 -0
- package/docs/screenshots/calendar-en.png +0 -0
- package/docs/screenshots/calendar-zh.png +0 -0
- package/docs/screenshots/connect-en.png +0 -0
- package/docs/screenshots/connect-zh.png +0 -0
- package/docs/screenshots/main-connect-en.png +0 -0
- package/docs/screenshots/main-connect-zh.png +0 -0
- package/docs/screenshots/overview-en.png +0 -0
- package/docs/screenshots/overview-zh.png +0 -0
- package/docs/screenshots/panel-hub.png +0 -0
- package/docs/screenshots/panel-overview.png +0 -0
- package/docs/screenshots/panel-refine.png +0 -0
- package/docs/screenshots/promo/promo-0-banner-v2.png +0 -0
- package/docs/screenshots/promo/promo-1-hero.png +0 -0
- package/docs/screenshots/promo/promo-2-tour.png +0 -0
- package/docs/screenshots/promo/promo-3-recall.png +0 -0
- package/docs/screenshots/promo/promo-4-unattended.png +0 -0
- package/docs/screenshots/promo/promo-5-external.png +0 -0
- package/docs/screenshots/promo/promo-6-greeting.png +0 -0
- package/docs/screenshots/reflections-en.png +0 -0
- package/docs/screenshots/search-zh.png +0 -0
- package/docs/screenshots/settings-2-zh.png +0 -0
- package/docs/screenshots/settings-debug-zh.png +0 -0
- package/docs/screenshots/settings-en.png +0 -0
- package/docs/screenshots/settings-zh.png +0 -0
- package/docs/screenshots/tour-core.png +0 -0
- package/docs/screenshots/tour-external.png +0 -0
- package/docs/screenshots/tour-toggles.png +0 -0
- package/docs/screenshots/tour-welcome.png +0 -0
- package/docs/screenshots/workspace-map-zh.png +0 -0
- package/docs/social-preview.png +0 -0
- package/lib/client.js +277 -118
- package/lib/index.js +329 -60
- package/lib/subagent-gc.js +239 -0
- package/lib/water-window.js +88 -0
- package/package.json +2 -1
|
@@ -0,0 +1,1207 @@
|
|
|
1
|
+
# M4 Shadow Retrieval 契约
|
|
2
|
+
|
|
3
|
+
> 状态:M4-0 契约冻结;M4 运行时代码尚未实施
|
|
4
|
+
>
|
|
5
|
+
> 工作区:D:\dsh-auto-memory(preview 分支)
|
|
6
|
+
>
|
|
7
|
+
> 唯一架构权威:docs/proactive-associative-memory-system-map.html
|
|
8
|
+
>
|
|
9
|
+
> 详细前置契约:docs/M3B-CONTRACT.md
|
|
10
|
+
>
|
|
11
|
+
> 后续 Python 契约:docs/PYTHON-SIDECAR-CONTRACT.md
|
|
12
|
+
>
|
|
13
|
+
> 前置状态:M0-R / T0 / M1 / M2 / P-A / M3a / M3b-1/2/3/4 均已 live verified;M3 整体完成
|
|
14
|
+
>
|
|
15
|
+
> 下一实施范围:只实施 M4-1 C-03 Retrieval Gate + 确定性词法检索纯核心;不得接入真实 Host 或持久审计
|
|
16
|
+
|
|
17
|
+
## 1. 本阶段目标
|
|
18
|
+
|
|
19
|
+
M4 在 M2 的会话级 ContextObserver 和 M3 的稳定 MemoryId/Anchor/Sidecar 之上,建立第一条可回放、可解释、默认关闭的主动检索链路:
|
|
20
|
+
|
|
21
|
+
~~~text
|
|
22
|
+
accepted ContextSegment
|
|
23
|
+
-> bounded RetrievalContextSnapshot + QueryPlan (pure, no IO)
|
|
24
|
+
-> C-03 Retrieval Gate
|
|
25
|
+
-> current-scope anchored corpus (retrieve/prefetch only)
|
|
26
|
+
-> deterministic lexical recall
|
|
27
|
+
-> C-05 rank / dedupe / candidate budget
|
|
28
|
+
-> ShadowAuditEvent
|
|
29
|
+
-> discard from model-visible path
|
|
30
|
+
~~~
|
|
31
|
+
|
|
32
|
+
本阶段交付:
|
|
33
|
+
|
|
34
|
+
1. C-03 Retrieval Gate:在检索前决定 retrieve / prefetch / suppress。
|
|
35
|
+
2. 无模型、无 Python、零依赖的确定性词法检索基线。
|
|
36
|
+
3. 只从 M3b 稳定 anchored Markdown 与 fresh sidecar 构建候选。
|
|
37
|
+
4. 明确 User / 当前 Workspace / External / 跨工作区边界。
|
|
38
|
+
5. 每个候选都有 MemoryId、版本、digest、scope、分数组件和丢弃原因。
|
|
39
|
+
6. per-runtime Shadow 状态、取消、去重、过期校验和 dispose 清理。
|
|
40
|
+
7. 最小化 Shadow 审计、离线回放和召回质量评测入口。
|
|
41
|
+
8. 默认关闭与关闭态零行为、零敏感内容留存、零新增 IO。
|
|
42
|
+
|
|
43
|
+
M4 的唯一模型行为是“不影响模型行为”。无论候选分数多高,本阶段都不得产生 MemoryPacket、不得写 Agent Inbox、不得修改 systemPrompt、不得推进 delivered cursor。
|
|
44
|
+
|
|
45
|
+
## 2. 明确不交付
|
|
46
|
+
|
|
47
|
+
M4 不交付:
|
|
48
|
+
|
|
49
|
+
- M5 Access Evidence Graph。
|
|
50
|
+
- seen / read / cite / reuse / success / correction 证据。
|
|
51
|
+
- M6 InjectionBroker、SafetyVerdict、MemoryPacket 或 pre-step Soft Injection。
|
|
52
|
+
- Python worker、embedding、向量检索、reranker、图扩散或 activation_request。
|
|
53
|
+
- Semantic/Profile 自动抽取或冲突合并。
|
|
54
|
+
- Procedure candidate、晋升、checklist 或执行。
|
|
55
|
+
- reasoning trace 采集或把可见思维链作为硬依赖。
|
|
56
|
+
- 流式中断、取消当前模型请求或原地改写已发请求。
|
|
57
|
+
- 跨工作区自动召回、外部原文件自动读取或 Calendar 检索。
|
|
58
|
+
- 新增设置页 UI、模型调用、subagent 调用或网络访问。
|
|
59
|
+
- 修改真实记忆 Markdown、Anchor、MemoryId 或 M3 sidecar 身份。
|
|
60
|
+
|
|
61
|
+
候选被 Shadow 检索命中不等于模型已看到该记忆;内部为打分读取记录切片也不等于 memory read evidence。
|
|
62
|
+
|
|
63
|
+
## 3. 不可协商约束
|
|
64
|
+
|
|
65
|
+
1. 唯一架构权威仍是 system-map;本文件细化 C-03、C-04 的 M4 词法切片、C-05 的候选预算、G-04 的回放入口和 G-05 的基础回退。
|
|
66
|
+
2. JS Host 始终拥有 session、scope、index、候选校验、审计和未来注入裁决权。
|
|
67
|
+
3. M4 只消费 M2/M3 事实,不创建第二套 session identity、MemoryId 或 sourceVersion。
|
|
68
|
+
4. 所有 session 派生状态必须在现有 SessionRuntime 内;不得按 _lastAgent、cwd 或 default workspace 猜归属。
|
|
69
|
+
5. M4 v1 不建立跨 runtime 的共享语料缓存;runtime 内的不可变 CorpusSnapshot 不得保存 query、gate、Agent 或候选归属之外的会话状态。
|
|
70
|
+
6. 只有稳定 anchored 记录可成为候选;legacy、conflict、oversized 或 stale 记录 fail closed。
|
|
71
|
+
7. memoryId 是长期身份;candidateId 和 retrievalId 只是一次 Shadow 尝试的身份,不得替代 memoryId。
|
|
72
|
+
8. 每个候选必须携带 sourceEpoch + sourceVersion + fileDigest + recordDigest;任一不匹配即 stale。
|
|
73
|
+
9. scope 先过滤、后打分。不能用高相似度绕过 scope。
|
|
74
|
+
10. 当前 Workspace 由受信任的 runtime 路径解析确定;不得由模型文本、记忆内容或 sidecar sourceFile 自行授权。
|
|
75
|
+
11. External 原文件、其他工作区和任意路径不进入 M4 v1 corpus。
|
|
76
|
+
12. Gate 不依赖 reasoning;可选 reasoning/monitor 信号缺失时按 0 处理,不得改变基础可用性。
|
|
77
|
+
13. Shadow 候选不得进入 prompt、context projection、Inbox、Session event、工具结果或任何模型可见位置。
|
|
78
|
+
14. 检索中间态不得写主 Session;持久化只能写最小化 audit-pre 元数据。
|
|
79
|
+
15. Shadow 命中不得产生 M5 AccessEvidence,不得标记 delivered,不得更新 Procedure 状态。
|
|
80
|
+
16. 关闭功能时不构造 Shadow ring/cache/job,不读 sidecar/Markdown,不建 audit 文件,不改变 prompt、工具、路由或记忆写入。
|
|
81
|
+
17. 真实文件、sidecar 或 contextVersion 在异步检索期间变化时,整份结果过期丢弃,不做部分接纳。
|
|
82
|
+
18. 所有输入、候选、审计、队列和文件扫描都有条数、字节、时间与保留上限。
|
|
83
|
+
19. 对外或持久化的新 preview 名称必须使用 _pre 或 -pre;禁止 _dev 或可能与正式版碰撞的裸名。
|
|
84
|
+
20. 所有新文本文件使用 UTF-8 无 BOM;不改变既有文件编码或换行。
|
|
85
|
+
|
|
86
|
+
## 4. 功能闸门与关闭语义
|
|
87
|
+
|
|
88
|
+
### 4.1 有效开关
|
|
89
|
+
|
|
90
|
+
M4 的有效启用条件为:
|
|
91
|
+
|
|
92
|
+
~~~js
|
|
93
|
+
const enabled =
|
|
94
|
+
config.associativeMemoryEnabled === true &&
|
|
95
|
+
config.shadowRetrievalEnabled === true &&
|
|
96
|
+
config.memoryAnchorEnabled === true
|
|
97
|
+
~~~
|
|
98
|
+
|
|
99
|
+
说明:
|
|
100
|
+
|
|
101
|
+
- associativeMemoryEnabled 是主动关联主开关,并保证 M2 Segment ring 可用。
|
|
102
|
+
- shadowRetrievalEnabled 是 M4 专用开关。
|
|
103
|
+
- memoryAnchorEnabled 保证候选拥有稳定身份和 live sidecar。
|
|
104
|
+
- memoryFileIndexEnabled 是 M3a 调试快照开关,不是 M4 授权条件;M4 直接消费 M3b sidecar/corpus snapshot。
|
|
105
|
+
- softInjectionEnabled、pythonBackendEnabled、reasoningObserverEnabled、procedurePromotionEnabled 和 streamingInterruptionEnabled 在 M4 中不产生任何效果。
|
|
106
|
+
|
|
107
|
+
### 4.2 默认关闭
|
|
108
|
+
|
|
109
|
+
仓库默认值继续保持:
|
|
110
|
+
|
|
111
|
+
~~~js
|
|
112
|
+
associativeMemoryEnabled: false
|
|
113
|
+
shadowRetrievalEnabled: false
|
|
114
|
+
~~~
|
|
115
|
+
|
|
116
|
+
当 M4 effective enabled 为 false:
|
|
117
|
+
|
|
118
|
+
- 不构造 Gate 状态、candidate cache、audit ring 或 AbortController。
|
|
119
|
+
- 不扫描 sidecar,不 stat/read 记忆 Markdown,不创建 retrieval-pre 目录。
|
|
120
|
+
- 不保存 query、term、candidate 或 memory excerpt。
|
|
121
|
+
- 仅允许已有 M0/M2 的最小关闭态计数语义;不得为 M4 增加敏感标量。
|
|
122
|
+
|
|
123
|
+
### 4.3 热切换与清理
|
|
124
|
+
|
|
125
|
+
true -> false 时必须立即:
|
|
126
|
+
|
|
127
|
+
1. abort 全部 M4 in-flight work。
|
|
128
|
+
2. 清空每个 runtime 的 Gate latch、query/candidate、dedupe cursor 与 volatile audit ring。
|
|
129
|
+
3. 清空含记忆文本或 token 的 CorpusSnapshot 缓存;纯文件版本统计可一并丢弃以简化证明。
|
|
130
|
+
4. 停止并结算 audit append queue;切换后不得再写新行。
|
|
131
|
+
5. 不删除历史 audit 文件,不修改 Markdown/sidecar。
|
|
132
|
+
6. 不清除 M2 ring,除非 associativeMemoryEnabled 同时从 true 切到 false;该情形沿用 M2 purgeObserverStorage。
|
|
133
|
+
|
|
134
|
+
## 5. 运行时所有权与处理时机
|
|
135
|
+
|
|
136
|
+
### 5.1 所有权
|
|
137
|
+
|
|
138
|
+
每个 SessionRuntime 增加惰性 Shadow 状态,概念形状为:
|
|
139
|
+
|
|
140
|
+
~~~ts
|
|
141
|
+
interface ShadowRuntimeState {
|
|
142
|
+
gate: {
|
|
143
|
+
latched: boolean
|
|
144
|
+
state: 'normal' | 'prefetch' | 'armed' | 'cooldown'
|
|
145
|
+
lastRawScore: number
|
|
146
|
+
lastDecisionContextVersion: number
|
|
147
|
+
processedSegmentCount: number
|
|
148
|
+
cooldownUntilSegment: number
|
|
149
|
+
enableEpoch: number
|
|
150
|
+
}
|
|
151
|
+
lastScheduledKey?: string
|
|
152
|
+
lastCompletedKey?: string
|
|
153
|
+
recentHits: BoundedRing<{ queryDigest: string; contextVersion: number }>(64)
|
|
154
|
+
completedKeys: BoundedSet<string>(256)
|
|
155
|
+
ignoredDigests: BoundedSet<string>(64)
|
|
156
|
+
inFlight?: {
|
|
157
|
+
retrievalId: string
|
|
158
|
+
contextVersion: number
|
|
159
|
+
memoryIndexVersion: string
|
|
160
|
+
abortController: AbortController
|
|
161
|
+
}
|
|
162
|
+
auditRing: BoundedRing<ShadowAuditEvent>
|
|
163
|
+
stats: ShadowRuntimeStats
|
|
164
|
+
}
|
|
165
|
+
~~~
|
|
166
|
+
|
|
167
|
+
该对象只在 effective enabled 且首个可评估 Segment 到达时创建。
|
|
168
|
+
|
|
169
|
+
### 5.2 Per-runtime Corpus
|
|
170
|
+
|
|
171
|
+
M4 v1 不建立跨 workspace 的 engine 级共享 CorpusRegistry。每个 runtime 按调度时捕获的 workspaceKey 惰性构建自己的不可变 CorpusSnapshot;User 文件只在该 snapshot 内作为明确的 User scope 源加入。这样 shadow 阶段不承担跨工作区缓存共享的隔离与失效复杂度。
|
|
172
|
+
|
|
173
|
+
CorpusSnapshot 至少包含:
|
|
174
|
+
|
|
175
|
+
~~~ts
|
|
176
|
+
interface SourceFingerprint {
|
|
177
|
+
size: number
|
|
178
|
+
mtimeMs: number
|
|
179
|
+
ino?: number
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
interface CorpusSnapshot {
|
|
183
|
+
workspaceKey: string
|
|
184
|
+
memoryIndexVersion: string
|
|
185
|
+
sourceFingerprints: Record<string, SourceFingerprint>
|
|
186
|
+
sources: CorpusRecord[]
|
|
187
|
+
totalBytes: number
|
|
188
|
+
}
|
|
189
|
+
~~~
|
|
190
|
+
|
|
191
|
+
要求:
|
|
192
|
+
|
|
193
|
+
- snapshot 不引用 Agent、SessionRuntime、AbortSignal 或 query。
|
|
194
|
+
- key 至少包含 session runtime identity 与 canonical workspaceKey;不能由 process.cwd 或 default runtime 补全。
|
|
195
|
+
- stat fingerprint 只用于快速判断缓存是否仍可复用;fingerprint 变化时必须重新读取并以 fileDigest/recordDigest 作权威校验。
|
|
196
|
+
- M4 v1 的实时语料只有 3 个受控源;未来扩展的 source/record 上限不能改变当前 v1 的 scope。
|
|
197
|
+
- 配置关闭、enableEpoch 变化或源 fingerprint 变化时,丢弃该 runtime snapshot;不做跨 workspace 共享淘汰。
|
|
198
|
+
|
|
199
|
+
### 5.3 触发边界
|
|
200
|
+
|
|
201
|
+
M4 观察 M2 ingestEnvelope 已接受并生成的 ContextSegment。推荐接线点是 Segment 入 ring 之后排入 per-runtime 异步队列;不得阻塞 session/event、tools/result 或 agent/pre-step。调度瞬间必须从同一 SessionRuntime 捕获 sessionId、agentId、workspaceKey、sessionClass、enableEpoch 和当前 Segment 计数;异步 tick 不得再裸调 resolvePaths()、currentRuntime()、_lastAgent 或 process.cwd() 推断语料归属。
|
|
202
|
+
|
|
203
|
+
处理顺序:
|
|
204
|
+
|
|
205
|
+
1. 验证调度时捕获的 runtime identity 仍有效,且 runtime 未 disposed。
|
|
206
|
+
2. 克隆 bounded RetrievalContextSnapshot,并将 workspaceKey 作为不可变语料键。
|
|
207
|
+
3. 先用无 IO 的 deterministic tokenizer 构建 bounded QueryPlan(用于 queryDigest 和 empty-query-signal),再由 C-03 决策;Gate 仍然先于 corpus IO 和候选检索。suppress 时不加载 corpus。
|
|
208
|
+
4. retrieve/prefetch 才按捕获的 workspaceKey 获取该 runtime 的 CorpusSnapshot。
|
|
209
|
+
5. 词法召回、scope/time filter、rank/dedupe/budget。
|
|
210
|
+
6. 完成时复核 sessionId、agentId、workspaceKey、enableEpoch、contextVersion、memoryIndexVersion 和每条 source identity。
|
|
211
|
+
7. 写 volatile audit;M4-3 后再写最小 durable audit。
|
|
212
|
+
8. 丢弃候选内容,不创建 pendingPacket。
|
|
213
|
+
|
|
214
|
+
## 6. RetrievalContextSnapshot
|
|
215
|
+
|
|
216
|
+
异步工作不得持有 live runtime 对象的可变投影。快照契约:
|
|
217
|
+
|
|
218
|
+
~~~ts
|
|
219
|
+
interface RetrievalContextSnapshot {
|
|
220
|
+
schemaVersion: 1
|
|
221
|
+
sessionId: string
|
|
222
|
+
agentId: string
|
|
223
|
+
workspaceKey: string
|
|
224
|
+
sessionClass: 'top-level' | 'child'
|
|
225
|
+
contextVersion: number
|
|
226
|
+
eventSeq: number
|
|
227
|
+
trigger: {
|
|
228
|
+
segmentId: string
|
|
229
|
+
segmentDigest: string
|
|
230
|
+
kind: 'user' | 'tool_call' | 'tool_result' | 'assistant'
|
|
231
|
+
eventType: string
|
|
232
|
+
nativeSeq?: number
|
|
233
|
+
ts: number
|
|
234
|
+
inputSource?: string | null
|
|
235
|
+
sourcePlugin?: string | null
|
|
236
|
+
toolName?: string | null
|
|
237
|
+
toolOk?: boolean | null
|
|
238
|
+
errorName?: string | null
|
|
239
|
+
errorCode?: string | null
|
|
240
|
+
callId?: string | null
|
|
241
|
+
rootCallId?: string | null
|
|
242
|
+
}
|
|
243
|
+
window: Array<{
|
|
244
|
+
segmentId: string
|
|
245
|
+
digest: string
|
|
246
|
+
kind: string
|
|
247
|
+
eventSeq: number
|
|
248
|
+
contextVersion: number
|
|
249
|
+
ts: number
|
|
250
|
+
text: string
|
|
251
|
+
toolName?: string | null
|
|
252
|
+
toolOk?: boolean | null
|
|
253
|
+
errorName?: string | null
|
|
254
|
+
errorCode?: string | null
|
|
255
|
+
}>
|
|
256
|
+
}
|
|
257
|
+
~~~
|
|
258
|
+
|
|
259
|
+
边界:
|
|
260
|
+
|
|
261
|
+
- window 最多取触发 Segment 加前 7 个 Segment,总计不超过 8 条。
|
|
262
|
+
- window 文本总计最多 4096 字符;从最新向前保留,单条仍受 M2 的 1200 字符上限。
|
|
263
|
+
- 快照必须深拷贝最小字段,不保存 envelope payload 对象。
|
|
264
|
+
- user/message 的 inputSource/sourcePlugin,以及 tool 的 name/ok/error/call 标量,从同 eventSeq 的 envelope 最小投影补入;找不到时为 null,不从 Segment.text 反向猜测结构化结果。
|
|
265
|
+
- trigger.ts 使用 M2 保存的原生事实时间;排序/回放不得用 observedAt 替代。
|
|
266
|
+
- sessionClass 从受信任的 session.header.parentSession 是否存在得出;M4 v1 对 child session hard suppress,避免后台子代理产生检索风暴,后续若开放必须单独评估。
|
|
267
|
+
- plugin 生成的 user/message 可进入 window 作为低权重上下文,但不得单独触发 retrieve;仅当 sourcePlugin 非空或 inputSource 命中版本化 plugin allowlist 时判定 plugin-generated,未知来源不得凭空归类。
|
|
268
|
+
|
|
269
|
+
## 7. Corpus 与 scope
|
|
270
|
+
|
|
271
|
+
### 7.1 M4 v1 允许的源
|
|
272
|
+
|
|
273
|
+
| Source class | Scope | 是否允许 | 说明 |
|
|
274
|
+
| --- | --- | --- | --- |
|
|
275
|
+
| 用户级 MEMORY.md | User | 是 | 对当前用户的所有 workspace 可检索 |
|
|
276
|
+
| 当前 workspace MEMORY.md | Workspace | 是 | 必须匹配 runtime 的 canonical workspaceKey |
|
|
277
|
+
| 当前 workspace YYYY-MM-DD.md 日志 | Workspace | 是 | 使用文件名日期做 recency,不改变身份 |
|
|
278
|
+
| 当前 workspace reflections/*.md | Workspace | 否(M4 v1) | M3 已建立稳定身份,但 M4 v1 暂不纳入;后续 flag/契约单独开启 |
|
|
279
|
+
| Session 临时记忆 | Session | 否 | M4 没有独立持久 Session memory source |
|
|
280
|
+
| 其他 workspace 的笔记/日志/反思 | Workspace | 否 | cross-workspace 自动召回为零 |
|
|
281
|
+
| 外部 AI 工具原文件/历史会话 | External | 否 | 不自动读取、跟随链接或索引 |
|
|
282
|
+
| CALENDAR.md | User/Workspace | 否 | M3 明确排除,M4 继续排除 |
|
|
283
|
+
| archive、cache、config、heartbeat、notices、Session JSONL | - | 否 | 不是 M4 memory corpus |
|
|
284
|
+
|
|
285
|
+
M4 v1 的 live SourceCatalog 严格限制为三类文件:用户级 MEMORY.md、当前 workspace MEMORY.md、当前 workspace 的今日日志 YYYY-MM-DD.md;这与现有 memoryIndexSnapshot() 的可验证范围一致。反思、其他日期日志、其他 workspace、外部原文件和历史 Session JSONL 均不自动检索,后续扩大语料必须单独升级契约与测试。
|
|
286
|
+
|
|
287
|
+
已经以链接块写入本地 MEMORY.md 的 external import 只被视为本地投影中的引用文本;M4 不解引用链接、不读取目标文件,也不把目标内容升级为 User/Workspace 事实。
|
|
288
|
+
|
|
289
|
+
### 7.2 SourceCatalog
|
|
290
|
+
|
|
291
|
+
SourceCatalog builder 必须接收调度时从同一 SessionRuntime 捕获的 canonical workspaceKey 与受控 source paths;不得在异步 tick 内裸调 resolvePaths()、currentRuntime()、_lastAgent 或 process.cwd()。sidecar 自报的 sourceFile 只能作为待校验字段,不能产生路径授权。
|
|
292
|
+
|
|
293
|
+
要求:
|
|
294
|
+
|
|
295
|
+
- 所有路径先 canonicalize;Windows 比较采用稳定的大小写与分隔符规则。
|
|
296
|
+
- sidecar.sourceFile 必须与 catalog 中该 canonical source 完全一致。
|
|
297
|
+
- symlink/reparse 后的真实路径不得逃逸允许的 User 或当前 Workspace 根。
|
|
298
|
+
- 用户文件、workspace MEMORY.md 和当前日志按固定 sourceRef 顺序纳入;M4 v1 不枚举反思目录。
|
|
299
|
+
- 当前日志使用受控 YYYY-MM-DD 文件名;不因目录中存在其他日期日志而扩大 corpus。
|
|
300
|
+
- 文件总数必须有硬上限;M4 v1 建议 128 个 source file,超出者以 source-budget 记录。
|
|
301
|
+
- 单文件继续沿用 M3 的 5 MiB 上限;超限整文件不检索。
|
|
302
|
+
|
|
303
|
+
### 7.3 Sidecar 与实际文件校验
|
|
304
|
+
|
|
305
|
+
Corpus loader 对每个源执行:
|
|
306
|
+
|
|
307
|
+
1. parseSidecar 校验 schemaVersion、namespace、source identity 和 record fields。
|
|
308
|
+
2. stat/read 实际 Markdown,校验不超过 5 MiB、无不受支持编码。
|
|
309
|
+
3. SHA-256 必须等于 sidecar.fileDigest。
|
|
310
|
+
4. 每个 record 的 byte range 必须在文件内,切片 digest 必须等于 recordDigest。
|
|
311
|
+
5. anchored record 必须有合法 memoryId/anchorId;legacy/conflict 不产候选。
|
|
312
|
+
6. sourceEpoch/sourceVersion/fileDigest/recordDigest 复制进 CorpusRecord。
|
|
313
|
+
|
|
314
|
+
缺失、损坏或 stale sidecar 的 M4 行为是 fail closed 并记录原因。M4 检索路径不得偷偷修改 Markdown。是否调用 M3 的显式 reconcile/rebuild 并持久化 sidecar属于 M3 维护入口;M4-2 可在内存中重建夹具用于诊断,但不得把未经事务验证的结果当作 live 候选。
|
|
315
|
+
|
|
316
|
+
## 8. MemoryIndexVersion
|
|
317
|
+
|
|
318
|
+
M4 为一次 corpus snapshot 计算确定性版本:
|
|
319
|
+
|
|
320
|
+
~~~text
|
|
321
|
+
source tuple = [scope, sourceRef, sourceEpoch, sourceVersion, fileDigest]
|
|
322
|
+
canonical tuple = JSON.stringify(source tuple)
|
|
323
|
+
canonical corpus = canonical tuples sorted by (scope, sourceRef) and joined with '\n'
|
|
324
|
+
memoryIndexVersion = idx_pre_ + first32hex(sha256(UTF-8(canonical corpus)))
|
|
325
|
+
~~~
|
|
326
|
+
|
|
327
|
+
规则:
|
|
328
|
+
|
|
329
|
+
- sourceRef 是 catalog 生成的稳定相对引用,不使用未经清洗的任意绝对路径。
|
|
330
|
+
- canonical tuple 排序只按 scope、sourceRef,完全相同时再按 sourceEpoch、sourceVersion、fileDigest;不得依赖目录枚举顺序。
|
|
331
|
+
- updatedAt、mtime、wall clock 和 candidate count 不进入版本 digest。
|
|
332
|
+
- 任一源增删、epoch/version/digest 变化都产生新 memoryIndexVersion。
|
|
333
|
+
- 空 corpus 仍有确定版本,但 Gate 结果为 suppress/no-corpus。
|
|
334
|
+
- 该版本将来直接作为 M7 请求和 M6 Packet 的 freshness precondition;preview 形式使用 idx_pre_ 前缀,正式发布转换时再统一为 idx_;M4 不得定义另一种同名语义。
|
|
335
|
+
|
|
336
|
+
## 9. C-03 Retrieval Gate
|
|
337
|
+
|
|
338
|
+
### 9.1 决策契约
|
|
339
|
+
|
|
340
|
+
~~~ts
|
|
341
|
+
type GateAction = 'retrieve' | 'prefetch' | 'suppress'
|
|
342
|
+
type GateState = 'normal' | 'prefetch' | 'armed' | 'cooldown'
|
|
343
|
+
|
|
344
|
+
type GateReason =
|
|
345
|
+
| 'no-owner' | 'disposed' | 'child-session' | 'no-segment'
|
|
346
|
+
| 'unsupported-trigger' | 'plugin-generated-trigger'
|
|
347
|
+
| 'empty-query-signal' | 'duplicate-context' | 'user-ignored'
|
|
348
|
+
| 'cooldown' | 'below-threshold' | 'armed' | 'warm'
|
|
349
|
+
|
|
350
|
+
interface GateSignals {
|
|
351
|
+
explicitRecall: number
|
|
352
|
+
novelty: number
|
|
353
|
+
unresolved: number
|
|
354
|
+
phaseShift: number
|
|
355
|
+
toolFailure: number
|
|
356
|
+
conflict: number
|
|
357
|
+
historical: number
|
|
358
|
+
repeated: number
|
|
359
|
+
unresolvedAge: number
|
|
360
|
+
goalDrift: number
|
|
361
|
+
monitor: number
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
interface GateDecision {
|
|
365
|
+
schemaVersion: 1
|
|
366
|
+
policyVersion: 'gate_pre_v1'
|
|
367
|
+
action: GateAction
|
|
368
|
+
state: GateState
|
|
369
|
+
reason: GateReason
|
|
370
|
+
rawScore: number
|
|
371
|
+
hesitation: number
|
|
372
|
+
latched: boolean
|
|
373
|
+
cooldownRemaining: number
|
|
374
|
+
signals: GateSignals
|
|
375
|
+
contextVersion: number
|
|
376
|
+
}
|
|
377
|
+
~~~
|
|
378
|
+
|
|
379
|
+
Gate 必须是同步、纯计算、无 IO。它在 corpus 加载和候选检索之前执行。
|
|
380
|
+
|
|
381
|
+
### 9.2 硬抑制顺序
|
|
382
|
+
|
|
383
|
+
以下条件按顺序优先于分数:
|
|
384
|
+
|
|
385
|
+
1. no-owner
|
|
386
|
+
2. disposed
|
|
387
|
+
3. child-session
|
|
388
|
+
4. no-segment
|
|
389
|
+
5. unsupported-trigger
|
|
390
|
+
6. plugin-generated-trigger
|
|
391
|
+
7. empty-query-signal
|
|
392
|
+
8. duplicate-context
|
|
393
|
+
9. user-ignored(M4 v1 数据集为空,仅保留接口)
|
|
394
|
+
10. cooldown
|
|
395
|
+
|
|
396
|
+
config-disabled 与 anchors-disabled 在 Host effective-enabled 闸门外直接短路:不调用 Gate、不创建状态、不写 audit。纯 fixture validator 可返回这两个诊断 reason,但 live 关闭态必须保持零留存。no-segment 与 unsupported-trigger 仅作为防御性 reserved reason:live tick 的唯一输入是 M2 已接受且 kind 属于白名单的 ContextSegment,其他输入在 ingest 层拒绝,不得扩展 M4 触发面。其余硬抑制在 effective enabled 时进入 volatile audit/counter。
|
|
397
|
+
|
|
398
|
+
### 9.3 基础信号
|
|
399
|
+
|
|
400
|
+
system-map 的信号分成三类:
|
|
401
|
+
|
|
402
|
+
**M4 v1 必须实现且可由 M2 事实确定:**
|
|
403
|
+
|
|
404
|
+
- novelty:触发 digest 是否未出现在前序 bounded window。
|
|
405
|
+
- toolFailure:触发或最近相关 tool_result 是否失败。
|
|
406
|
+
- repeated:bounded window 内同 tool name、同失败码或同动作模式的重复度。
|
|
407
|
+
- unresolved:版本化保守词典识别未解决/待办/失败/仍需等表达;不能调用模型推断。
|
|
408
|
+
- phaseShift:用户在一段 tool/assistant 序列后提出新阶段指令;只用事件种类和版本化转折词。
|
|
409
|
+
- conflict:用户纠正、否定旧结论或工具结果互相冲突的保守显式信号。
|
|
410
|
+
|
|
411
|
+
**M4 v1 只允许使用已存在的本 session Shadow 元数据:**
|
|
412
|
+
|
|
413
|
+
- historical:同 session 之前相同 queryDigest 有 fresh Shadow hit;不能先做候选检索再反向提高本次 Gate。
|
|
414
|
+
- unresolvedAge:只从 bounded window 的事实时间计算,缺失时为 0。
|
|
415
|
+
|
|
416
|
+
**M4 v1 缺失即为 0,不得猜测:**
|
|
417
|
+
|
|
418
|
+
- goalDrift 的语义模型。
|
|
419
|
+
- reasoning uncertainty / full CoT。
|
|
420
|
+
- dsh-anchored-monitor 强度。
|
|
421
|
+
- M5 conflict/evidence aggregate。
|
|
422
|
+
- Python activation suggestion。
|
|
423
|
+
|
|
424
|
+
锚定监控未来只能作为可选弱信号,不能成为硬依赖、授权或唯一触发器。
|
|
425
|
+
|
|
426
|
+
M4 v1 信号计算必须固定为以下纯函数(输入仅为 snapshot.window、trigger、QueryPlan、recentHits 和当前 Segment 计数):
|
|
427
|
+
|
|
428
|
+
- explicitRecall = 1 仅当 trigger.kind='user' 且命中 lexical_pre_v1 的明确回忆意图短语(例如“回忆/查找之前的记录/上次如何处理/remember what we decided”);仅出现“memory/记忆”等名词不算,其他情况为 0。它只要求执行 Shadow 检索,不是注入或动作授权。
|
|
429
|
+
- novelty = 1 if trigger.segmentDigest 不在前序 window,否则 0。
|
|
430
|
+
- repeated = min(1, max(0, sameToolNameCount - 1) / 2),sameToolNameCount 只统计 window 内相同非空 toolName 的 tool_call;缺少 toolName 为 0。
|
|
431
|
+
- phaseShift = 1 仅当 trigger.kind='user'、版本化转折词典命中,且 trigger 之前 window 存在至少一个 tool_call/tool_result;否则 0。
|
|
432
|
+
- unresolved = 1 仅当最近 user Segment 命中版本化未决词典,且其后没有针对性的 tool_result;否则 0。
|
|
433
|
+
- unresolvedAge = min(1, max(0, trigger.ts - oldestUnresolvedUserTs) / 300000),没有未决 user Segment 或事实时间缺失时为 0。
|
|
434
|
+
- historical = 1 if recentHits 中存在相同 queryDigest 且其对应 source identities 仍 fresh,否则 0。
|
|
435
|
+
- toolFailure = 1 if trigger.toolOk=false 或最近相关 tool_result 的 error 标量非空,否则 0。
|
|
436
|
+
- conflict 在 M4 v1 仅识别当前 window 内明确的用户纠正/否定词与失败结果并存,未实现时固定 0;不得读取 M5 evidence。
|
|
437
|
+
|
|
438
|
+
每个词典都必须带 lexical_pre_v1 版本并由 fixture 锁定;相同 window、trigger、recentHits、enableEpoch 输入必须逐字段得到相同 GateDecision。
|
|
439
|
+
|
|
440
|
+
### 9.4 v1 权重与滞回
|
|
441
|
+
|
|
442
|
+
M4-1 必须导出不可变 SHADOW_GATE_POLICY_PRE_V1,包含每个信号权重、词典版本和阈值,并由 fixture snapshot 锁定。不得把未审计的魔法数字散落在 Host 代码。v1 权重冻结为:
|
|
443
|
+
|
|
444
|
+
~~~text
|
|
445
|
+
explicitRecall 0.30
|
|
446
|
+
toolFailure 0.16
|
|
447
|
+
unresolved 0.16
|
|
448
|
+
repeated 0.12
|
|
449
|
+
novelty 0.08
|
|
450
|
+
phaseShift 0.08
|
|
451
|
+
historical 0.05
|
|
452
|
+
conflict 0.03
|
|
453
|
+
unresolvedAge 0.02
|
|
454
|
+
--------------------
|
|
455
|
+
sum 1.00
|
|
456
|
+
~~~
|
|
457
|
+
|
|
458
|
+
goalDrift、monitor 和 reasoning 在 v1 权重为 0;conflict 只有 M4 可计算的保守显式冲突信号,不能读取 M5 evidence。explicitRecall 只提升 Shadow 检索需要,不构成注入、工具执行或安全授权。任何权重、词典、explicitRecall 下限或阈值变化都必须升级 policyVersion。
|
|
459
|
+
|
|
460
|
+
阈值按最新 system-map 固定:
|
|
461
|
+
|
|
462
|
+
~~~text
|
|
463
|
+
hysteresis on = 0.65
|
|
464
|
+
hysteresis off = 0.42
|
|
465
|
+
retrieve = hesitation >= 0.80
|
|
466
|
+
prefetch = hesitation >= 0.55
|
|
467
|
+
suppress = hesitation < 0.55
|
|
468
|
+
~~~
|
|
469
|
+
|
|
470
|
+
要求:
|
|
471
|
+
|
|
472
|
+
- weightedRaw = clamp(sum(weight * clamp(signal, 0, 1)), 0, 1);rawScore = explicitRecall === 1 ? Math.max(weightedRaw, 0.82) : weightedRaw。
|
|
473
|
+
- latchedNext = previous.latched ? rawScore >= 0.42 : rawScore >= 0.65。
|
|
474
|
+
- hesitation = clamp(latchedNext ? Math.max(rawScore, 0.55) : rawScore, 0, 1)。
|
|
475
|
+
- cooldownRemaining > 0 且 explicitRecall !== 1 时 action=suppress、state=cooldown、reason=cooldown;显式回忆请求可绕过 Shadow cooldown,但仍受 no-owner/disposed/child/plugin/user-ignored 等硬抑制。否则 hesitation >= 0.80 为 retrieve/armed,hesitation >= 0.55 为 prefetch/prefetch,其余为 suppress/normal。
|
|
476
|
+
- GateDecision.latched 是 latchedNext;cooldownRemaining 以尚未处理的 Segment 数量计,不使用 M2 的 eventSeq 或 native step 作为冷却单位。
|
|
477
|
+
- retrieve 后进入固定的 Shadow cooldown;gate_pre_v1 常量为 SHADOW_GATE_COOLDOWN_SEGMENTS=2,不复用 injectionCooldownSteps。
|
|
478
|
+
- 冷却单位是本 runtime 已处理的 accepted Segment 数量,不是 M2 contextVersion/eventSeq/native step;cooldownUntilSegment 只在当前 enableEpoch 内有效。
|
|
479
|
+
- cooldown 只影响 Shadow 调度,不修改 M2 contextVersion。
|
|
480
|
+
- associativeMemoryEnabled 或 shadowRetrievalEnabled 从 false 再启用时递增 enableEpoch,并清零 processedSegmentCount、cooldown、latch、recentHits、completedKeys 与 ignoredDigests。
|
|
481
|
+
- 同输入、同前态必须得到同 GateDecision。
|
|
482
|
+
- M4-1 在纯 fixture 中冻结具体权重;权重若改变必须升级 policyVersion,旧 audit 仍可解释。
|
|
483
|
+
|
|
484
|
+
### 9.5 retrieve 与 prefetch 在 M4 的差别
|
|
485
|
+
|
|
486
|
+
- retrieve:执行完整 bounded lexical rank,并允许在内存中物化 top candidate 的 bounded excerpt 用于校验;仍不注入。
|
|
487
|
+
- prefetch:执行相同词法索引命中,但只保留 candidate metadata,不物化 excerpt。
|
|
488
|
+
- suppress:不加载 corpus、不扫描候选。
|
|
489
|
+
|
|
490
|
+
两种命中都只产 ShadowAuditEvent。prefetch 不是 delivered,也不是 M5 seen。
|
|
491
|
+
|
|
492
|
+
## 10. Query 与词法规范化
|
|
493
|
+
|
|
494
|
+
### 10.1 QueryPlan
|
|
495
|
+
|
|
496
|
+
~~~ts
|
|
497
|
+
interface QueryPlan {
|
|
498
|
+
schemaVersion: 1
|
|
499
|
+
policyVersion: 'lexical_pre_v1'
|
|
500
|
+
contextVersion: number
|
|
501
|
+
queryDigest: string
|
|
502
|
+
terms: Array<{
|
|
503
|
+
term: string
|
|
504
|
+
weight: number
|
|
505
|
+
origin: 'trigger' | 'recent-user' | 'tool-result' | 'tool-call' | 'assistant'
|
|
506
|
+
}>
|
|
507
|
+
phrases: string[]
|
|
508
|
+
truncated: boolean
|
|
509
|
+
}
|
|
510
|
+
~~~
|
|
511
|
+
|
|
512
|
+
限制:
|
|
513
|
+
|
|
514
|
+
- 最多 32 个去重 term、8 个 phrase。
|
|
515
|
+
- 单 term 最多 96 UTF-8 bytes;超限丢弃并记录 query-term-oversize。
|
|
516
|
+
- term 总 UTF-8 bytes 最多 2048。
|
|
517
|
+
- 当前 trigger 至少贡献一个有效 term,否则 Gate/Query suppress empty-query。
|
|
518
|
+
- queryDigest 由 policyVersion + canonical weighted terms/phrases 计算,不包含 sessionId 或 wall clock。
|
|
519
|
+
|
|
520
|
+
### 10.2 确定性 tokenizer
|
|
521
|
+
|
|
522
|
+
M4 v1 tokenizer 必须:
|
|
523
|
+
|
|
524
|
+
1. Unicode NFKC normalize。
|
|
525
|
+
2. Latin 做 locale-independent lowercase;不得依赖系统 locale。
|
|
526
|
+
3. 保留路径段、包名、版本号、错误码、snake_case、kebab-case、camelCase 和数字组合的可检索子词。
|
|
527
|
+
4. CJK 连续文本只在每个连续 run 内生成 2-gram,每个 Segment 最多保留 64 个 CJK gram,超出部分丢弃并计 query-term-oversize;同时保留长度合适的完整词串,不引入第三方分词器。
|
|
528
|
+
5. 移除版本化的中英文 stop words,但不能移除错误码、文件名或长度大于 1 的标识符。
|
|
529
|
+
6. 同一 term 多次出现时取最高来源权重,不通过重复堆高到无界。
|
|
530
|
+
7. 不执行 Markdown、HTML、shell、URL 或记忆中的任何指令;只把它们当文本 token。
|
|
531
|
+
|
|
532
|
+
phraseMatch 的边界规则:NFKC 后对 canonical phrase 做子串匹配;Latin/数字/标识符要求两端不是字母数字,CJK 不要求空格但要求匹配不被同一 CJK run 的相邻字符扩展。命中任一 phrase 即为 1。
|
|
533
|
+
|
|
534
|
+
初版窗口来源建议权重必须固化在 lexical_pre_v1:trigger > recent-user > tool-result > tool-call > assistant。具体数值由 M4-1 fixture 冻结;变更必须升级版本。
|
|
535
|
+
|
|
536
|
+
## 11. Candidate 契约
|
|
537
|
+
|
|
538
|
+
~~~ts
|
|
539
|
+
interface ShadowCandidate {
|
|
540
|
+
schemaVersion: 1
|
|
541
|
+
candidateId: string
|
|
542
|
+
retrievalId: string
|
|
543
|
+
memoryId: string
|
|
544
|
+
anchorId: string
|
|
545
|
+
|
|
546
|
+
scope: 'User' | 'Workspace'
|
|
547
|
+
sourceClass: 'user-memory' | 'workspace-notes' | 'workspace-log'
|
|
548
|
+
sourceRef: string
|
|
549
|
+
|
|
550
|
+
sourceEpoch: string
|
|
551
|
+
sourceVersion: number
|
|
552
|
+
fileDigest: string
|
|
553
|
+
recordDigest: string
|
|
554
|
+
lineStart: number
|
|
555
|
+
lineEnd: number
|
|
556
|
+
byteStart: number
|
|
557
|
+
byteEnd: number
|
|
558
|
+
heading?: string | null
|
|
559
|
+
|
|
560
|
+
scores: {
|
|
561
|
+
termCoverage: number
|
|
562
|
+
headingCoverage: number
|
|
563
|
+
phraseMatch: number
|
|
564
|
+
recency: number
|
|
565
|
+
total: number
|
|
566
|
+
}
|
|
567
|
+
matchedTermDigests: string[]
|
|
568
|
+
reasonCodes: string[]
|
|
569
|
+
estimatedBytes: number
|
|
570
|
+
excerpt?: string
|
|
571
|
+
}
|
|
572
|
+
~~~
|
|
573
|
+
|
|
574
|
+
身份规则:
|
|
575
|
+
|
|
576
|
+
~~~text
|
|
577
|
+
sessionIdHash = first32hex(sha256(UTF-8('retrieval-pre-v1\u0000' + sessionId)))
|
|
578
|
+
retrievalIdParts = ['retrieval-pre-v1', sessionIdHash, contextVersion, trigger.segmentId, memoryIndexVersion, gatePolicyVersion, lexicalPolicyVersion]
|
|
579
|
+
retrievalId = ret_pre_ + first32hex(sha256(UTF-8(JSON.stringify(retrievalIdParts))))
|
|
580
|
+
candidateIdParts = ['candidate-pre-v1', retrievalId, memoryId, sourceEpoch, sourceVersion, recordDigest]
|
|
581
|
+
candidateId = cand_pre_ + first32hex(sha256(UTF-8(JSON.stringify(candidateIdParts))))
|
|
582
|
+
~~~
|
|
583
|
+
|
|
584
|
+
- retrievalId/candidateId 可确定性重放,但不是长期内容身份。
|
|
585
|
+
- 同一个 memoryId 内容变化后仍是同一记忆,但 candidateId 因版本/digest 改变。
|
|
586
|
+
- durable audit 不保存 matched term 明文,只保存 term digest;volatile debug 也默认不返回 excerpt。
|
|
587
|
+
- excerpt 只允许 retrieve 模式在内存中持有,按 UTF-8 bytes 截断到 480 bytes,并经过既有敏感内容清洗;audit 与 /debug 不持久化全文。
|
|
588
|
+
|
|
589
|
+
## 12. 词法评分、排序、去重与预算
|
|
590
|
+
|
|
591
|
+
### 12.1 v1 分数
|
|
592
|
+
|
|
593
|
+
M4-1 的 lexical_pre_v1 使用可解释线性分数:
|
|
594
|
+
|
|
595
|
+
~~~text
|
|
596
|
+
total = 0.72 * termCoverage
|
|
597
|
+
+ 0.15 * headingCoverage
|
|
598
|
+
+ 0.08 * phraseMatch
|
|
599
|
+
+ 0.05 * recency
|
|
600
|
+
~~~
|
|
601
|
+
|
|
602
|
+
所有组件范围为 [0,1]:
|
|
603
|
+
|
|
604
|
+
- termCoverage:命中的 query term 权重 / query term 总权重。
|
|
605
|
+
- headingCoverage:标题中命中的 query term 权重 / query term 总权重;无标题为 0。
|
|
606
|
+
- phraseMatch:按 §10.2 的 NFKC/边界规则,任一 canonical phrase 命中则为 1,否则 0。
|
|
607
|
+
- recency:只对带可信 YYYY-MM-DD 文件名的 workspace-log 按 trigger.ts 计算 30 天半衰期:2^(-ageDays/30);User/notes 没有可靠事件日期时取中性值 0.5,不从 mtime 猜语义时间。
|
|
608
|
+
|
|
609
|
+
候选必须至少命中一个 term 或 phrase,且 total >= 0.10;否则分别以 no-lexical-match 或 below-score 丢弃。scope 是硬过滤,不进入加权分数。salience、confidence、embedding similarity 在 M4 v1 不可用,不得用固定高值伪装。
|
|
610
|
+
|
|
611
|
+
### 12.2 时间规则
|
|
612
|
+
|
|
613
|
+
- 日期来自受控 YYYY-MM-DD 文件名;标题中的日期只作显示,不覆盖文件分类。
|
|
614
|
+
- trigger.ts 是回放事实时间。
|
|
615
|
+
- 日志文件日期必须先按 DEFAULT_CONFIG.dayBoundaryMinutes=450 的插件日界换算 trigger.ts,再比较 future-dated;00:00-07:30 的事件归入插件前一日。
|
|
616
|
+
- 明显晚于经插件日界换算后的 trigger date 且超过 24 小时容差的当前日志以 future-dated 丢弃。
|
|
617
|
+
- 老记录只衰减不自动过期;M4 不发明 TTL。
|
|
618
|
+
- 时间解析失败时 recency 为 0.5 并记录 date-unknown,不以当前 wall clock 猜测。
|
|
619
|
+
|
|
620
|
+
### 12.3 确定排序
|
|
621
|
+
|
|
622
|
+
排序键依次为:
|
|
623
|
+
|
|
624
|
+
1. total 降序。
|
|
625
|
+
2. termCoverage 降序。
|
|
626
|
+
3. headingCoverage 降序。
|
|
627
|
+
4. scope:当前 Workspace 先于 User,仅作完全同分 tie-break,不改变授权。
|
|
628
|
+
5. memoryId 字典序。
|
|
629
|
+
|
|
630
|
+
不得使用文件枚举顺序、mtime、随机数或对象插入偶然顺序。
|
|
631
|
+
|
|
632
|
+
### 12.4 去重
|
|
633
|
+
|
|
634
|
+
依次执行:
|
|
635
|
+
|
|
636
|
+
- 同 memoryId:只保留当前 fresh 版本;出现多个来源/版本视为 index-conflict 并 fail closed,不静默择一。
|
|
637
|
+
- 同 recordDigest:保留排序更高者,其余 duplicate-content;不同 memoryId 仍保留 drop provenance。
|
|
638
|
+
- 同 retrieval key:同 session/context/index/policy 不重复执行或重复写 durable audit。
|
|
639
|
+
|
|
640
|
+
### 12.5 预算
|
|
641
|
+
|
|
642
|
+
M4 v1 硬预算:
|
|
643
|
+
|
|
644
|
+
| 项目 | 上限 |
|
|
645
|
+
| --- | --- |
|
|
646
|
+
| Context window | 8 segments / 4096 chars |
|
|
647
|
+
| Query terms | 32 terms / 2048 UTF-8 bytes |
|
|
648
|
+
| Source files | 3(M4 v1:user MEMORY.md、workspace MEMORY.md、当前日志;未来扩展硬上限 128) |
|
|
649
|
+
| Corpus records | 512(M4 v1;未来扩展硬上限 4096) |
|
|
650
|
+
| Corpus resident bytes | 64 MiB |
|
|
651
|
+
| 单文件 | 5 MiB(继承 M3) |
|
|
652
|
+
| 单记录评分扫描 | 标题 + 内容前 16 KiB |
|
|
653
|
+
| 初筛命中 | 64 |
|
|
654
|
+
| Ranked kept | 8 |
|
|
655
|
+
| 单 excerpt | 480 UTF-8 bytes,仅 retrieve volatile |
|
|
656
|
+
| fingerprint 未变化时 Gate/query/rank deadline | 50 ms,fixture 可注入 clock |
|
|
657
|
+
| source reload/hash IO deadline | 500 ms,超时整次 deadline |
|
|
658
|
+
| 单个 durable audit event | 32 KiB |
|
|
659
|
+
| per-runtime volatile audit ring | 64 events |
|
|
660
|
+
| recentHits | 64 entries |
|
|
661
|
+
| completedKeys | 256 entries |
|
|
662
|
+
| ignoredDigests | 64 entries |
|
|
663
|
+
|
|
664
|
+
超限必须有 drop reason,不得截断后伪装完整候选。deadline 超时整次结果状态为 deadline,不产生 future-deliverable candidate。
|
|
665
|
+
|
|
666
|
+
## 13. Drop reason 词典
|
|
667
|
+
|
|
668
|
+
M4 v1 reason 必须来自版本化枚举,禁止自由文本驱动逻辑。至少包括:
|
|
669
|
+
|
|
670
|
+
### Gate
|
|
671
|
+
|
|
672
|
+
- config-disabled(仅 pure validator;live Host 在 Gate 外零留存短路)
|
|
673
|
+
- anchors-disabled(仅 pure validator;live Host 在 Gate 外零留存短路)
|
|
674
|
+
- no-owner
|
|
675
|
+
- disposed
|
|
676
|
+
- child-session
|
|
677
|
+
- no-segment
|
|
678
|
+
- unsupported-trigger
|
|
679
|
+
- plugin-generated-trigger
|
|
680
|
+
- empty-query-signal
|
|
681
|
+
- duplicate-context
|
|
682
|
+
- user-ignored
|
|
683
|
+
- cooldown
|
|
684
|
+
- below-threshold
|
|
685
|
+
|
|
686
|
+
### Corpus/scope
|
|
687
|
+
|
|
688
|
+
- no-corpus
|
|
689
|
+
- source-budget
|
|
690
|
+
- record-budget
|
|
691
|
+
- corpus-byte-budget
|
|
692
|
+
- record-scan-budget
|
|
693
|
+
- source-fingerprint-changed
|
|
694
|
+
- source-out-of-scope
|
|
695
|
+
- cross-workspace
|
|
696
|
+
- external-disabled
|
|
697
|
+
- calendar-excluded
|
|
698
|
+
- sidecar-missing
|
|
699
|
+
- sidecar-invalid
|
|
700
|
+
- source-mismatch
|
|
701
|
+
- stale-source
|
|
702
|
+
- record-stale
|
|
703
|
+
- index-conflict
|
|
704
|
+
- oversized
|
|
705
|
+
- future-dated
|
|
706
|
+
|
|
707
|
+
### Query/rank
|
|
708
|
+
|
|
709
|
+
- empty-query
|
|
710
|
+
- query-term-oversize
|
|
711
|
+
- no-lexical-match
|
|
712
|
+
- below-score
|
|
713
|
+
- duplicate-memory
|
|
714
|
+
- duplicate-content
|
|
715
|
+
- candidate-budget
|
|
716
|
+
- excerpt-budget
|
|
717
|
+
- date-unknown
|
|
718
|
+
|
|
719
|
+
### Async/audit
|
|
720
|
+
|
|
721
|
+
- cancelled
|
|
722
|
+
- disposed-before-complete
|
|
723
|
+
- stale-context
|
|
724
|
+
- stale-index
|
|
725
|
+
- deadline
|
|
726
|
+
- audit-write-failed
|
|
727
|
+
- internal-error
|
|
728
|
+
|
|
729
|
+
Drop entry 至少包含 stage、reason、可选 memoryId/sourceRef 和 bounded scalar detail;不得保存原文、异常堆栈、凭据或完整绝对路径。
|
|
730
|
+
|
|
731
|
+
## 14. Freshness、并发与取消
|
|
732
|
+
|
|
733
|
+
### 14.1 调度 key
|
|
734
|
+
|
|
735
|
+
~~~text
|
|
736
|
+
sessionIdHash = first32hex(sha256(UTF-8('retrieval-pre-v1\u0000' + sessionId)))
|
|
737
|
+
retrievalKey = JSON.stringify(['retrieval-key-pre-v1', sessionIdHash, contextVersion, memoryIndexVersion, gatePolicyVersion, lexicalPolicyVersion])
|
|
738
|
+
~~~
|
|
739
|
+
|
|
740
|
+
同 key 最多执行一次。seed replay 与 live feed 对同一 Segment 必须得到相同 key,不能双计。
|
|
741
|
+
|
|
742
|
+
### 14.2 latest-wins
|
|
743
|
+
|
|
744
|
+
每个 runtime 最多一个 in-flight retrieval:
|
|
745
|
+
|
|
746
|
+
- 新 contextVersion 到达时 abort 更旧任务。
|
|
747
|
+
- retrieve 可替换同版本尚未开始的 prefetch。
|
|
748
|
+
- 不同 runtime 可并行;每个 runtime 只读自己的 CorpusSnapshot,不跨 workspace 共享。
|
|
749
|
+
- dispose/关闭开关/plugin dispose 必须 abort。
|
|
750
|
+
- 不使用无界 Promise 队列;只保留 latest pending snapshot。
|
|
751
|
+
|
|
752
|
+
### 14.3 完成校验
|
|
753
|
+
|
|
754
|
+
候选完成后、写 audit 前再次检查:
|
|
755
|
+
|
|
756
|
+
1. runtime 未 disposed 且 sessionId/agentId/workspaceKey/enableEpoch 未变。
|
|
757
|
+
2. runtime.contextVersion 等于 snapshot.contextVersion。
|
|
758
|
+
3. 对每个 source 比较调度时捕获的 stat fingerprint;未变化时复用 snapshot 的 memoryIndexVersion,变化时只重载该 source 并重新计算其 fileDigest/records,再整体替换 snapshot。
|
|
759
|
+
4. 每个 candidate 的 sourceEpoch/sourceVersion/fileDigest/recordDigest 仍匹配当前 corpus;recordDigest 是最终记录级权威。
|
|
760
|
+
5. retrievalKey 未被 completedKeys 成功提交。
|
|
761
|
+
|
|
762
|
+
M4 v1 不在每个已缓存 tick 上重读全部文件。Gate/query/rank 的缓存核心预算与 corpus IO/哈希预算分开:fingerprint 未变化时核心路径目标 <=50 ms;fingerprint 变化后的 source reload/hash 受独立 IO deadline(建议 <=500 ms),超时整次 outcome=deadline。
|
|
763
|
+
|
|
764
|
+
失败时整次结果变为 stale/cancelled;不得更新 lastCompletedKey、candidate cache、delivered cursor 或任何 evidence。
|
|
765
|
+
|
|
766
|
+
## 15. Shadow 审计
|
|
767
|
+
|
|
768
|
+
### 15.1 与 M5/G-02 的边界
|
|
769
|
+
|
|
770
|
+
M4 Shadow audit 是“检索算法发生了什么”的最小元数据,不是:
|
|
771
|
+
|
|
772
|
+
- M5 AccessEvidence。
|
|
773
|
+
- G-02 Injection Audit 的 packet delivery/result。
|
|
774
|
+
- 用户可见引用。
|
|
775
|
+
- 模型读取证明。
|
|
776
|
+
|
|
777
|
+
M4 audit 必须显式写:
|
|
778
|
+
|
|
779
|
+
~~~text
|
|
780
|
+
shadowOnly = true
|
|
781
|
+
injected = false
|
|
782
|
+
packetId = null
|
|
783
|
+
delivered = false
|
|
784
|
+
accessEvidenceCreated = false
|
|
785
|
+
~~~
|
|
786
|
+
|
|
787
|
+
### 15.2 事件 schema
|
|
788
|
+
|
|
789
|
+
~~~ts
|
|
790
|
+
interface ShadowAuditEvent {
|
|
791
|
+
schemaVersion: 1
|
|
792
|
+
namespace: 'dsh-auto-memory-pre'
|
|
793
|
+
retrievalId: string
|
|
794
|
+
recordedAt: number
|
|
795
|
+
triggerTs: number
|
|
796
|
+
|
|
797
|
+
contextVersion: number
|
|
798
|
+
eventSeq: number
|
|
799
|
+
triggerSegmentId: string
|
|
800
|
+
triggerSegmentDigest: string
|
|
801
|
+
triggerKind: string
|
|
802
|
+
|
|
803
|
+
memoryIndexVersion: string | null
|
|
804
|
+
gatePolicyVersion: string
|
|
805
|
+
lexicalPolicyVersion: string
|
|
806
|
+
queryDigest?: string
|
|
807
|
+
gate: GateDecision
|
|
808
|
+
|
|
809
|
+
outcome: 'suppressed' | 'completed' | 'empty' | 'stale' | 'cancelled' | 'error'
|
|
810
|
+
candidates: Array<{
|
|
811
|
+
candidateId: string
|
|
812
|
+
memoryId: string
|
|
813
|
+
anchorId: string
|
|
814
|
+
scope: string
|
|
815
|
+
sourceClass: string
|
|
816
|
+
sourceRef: string
|
|
817
|
+
sourceEpoch: string
|
|
818
|
+
sourceVersion: number
|
|
819
|
+
fileDigest: string
|
|
820
|
+
recordDigest: string
|
|
821
|
+
score: number
|
|
822
|
+
reasonCodes: string[]
|
|
823
|
+
}>
|
|
824
|
+
dropped: Array<{ stage: string; reason: string; memoryId?: string; sourceRef?: string }>
|
|
825
|
+
counts: { sources: number; records: number; legacyConflicts: number; rawHits: number; kept: number; dropped: number }
|
|
826
|
+
latencyMs: { gate: number; corpus: number; search: number; audit: number; total: number }
|
|
827
|
+
|
|
828
|
+
shadowOnly: true
|
|
829
|
+
injected: false
|
|
830
|
+
packetId: null
|
|
831
|
+
delivered: false
|
|
832
|
+
accessEvidenceCreated: false
|
|
833
|
+
}
|
|
834
|
+
~~~
|
|
835
|
+
|
|
836
|
+
### 15.3 隐私投影
|
|
837
|
+
|
|
838
|
+
Durable audit:
|
|
839
|
+
|
|
840
|
+
- retrievalId/retrievalKey 使用不含 salt 的 sessionIdHash;session id 是 DSH 生成的不透明高熵标识,salt 不参与确定性身份。
|
|
841
|
+
- durable audit 不保存 sessionRef、agentRef 或 workspace 的绝对路径;runtimeTag 仅允许作为 volatile/debug 字段,持久化投影必须省略。
|
|
842
|
+
- sourceRef 只使用 catalog 相对引用,例如 user:MEMORY.md、workspace:MEMORY.md、workspace-log:2026-08-22.md。
|
|
843
|
+
- 不保存 Segment text、query term 明文、memory excerpt、完整错误堆栈、凭据或绝对路径。
|
|
844
|
+
- M4 不创建 salt 文件;删除/重建 audit 不影响 retrievalId、retrievalKey 或 replay 确定性。
|
|
845
|
+
- matched terms 只保存不可逆 digest 或 aggregate count。
|
|
846
|
+
|
|
847
|
+
Volatile /debug 也默认返回相同最小投影;只有测试注入的纯 fixture API 可查看规范化 term/excerpt。
|
|
848
|
+
|
|
849
|
+
### 15.4 Durable audit 位置与保留
|
|
850
|
+
|
|
851
|
+
M4-3 才允许创建:
|
|
852
|
+
|
|
853
|
+
~~~text
|
|
854
|
+
<DSH_HOME>/memory/retrieval-pre/audit/YYYY-MM-DD.jsonl
|
|
855
|
+
<DSH_HOME>/memory/retrieval-pre/state-pre.json
|
|
856
|
+
~~~
|
|
857
|
+
|
|
858
|
+
规则:
|
|
859
|
+
|
|
860
|
+
- 每行一个完整 JSON object,append-only,UTF-8 无 BOM。
|
|
861
|
+
- 写入由 engine 级串行队列保证不交错;失败不重试写主 Session。
|
|
862
|
+
- 单事件最大 32 KiB;超限按 candidate/drop 尾部裁剪并标记 audit-truncated。
|
|
863
|
+
- 默认保留 14 天且总上限 32 MiB;按最旧日期清理,只清 audit,不动 Markdown/sidecar。日期只是存储分片,跨午夜的 retrieval 由 retrievalId/retrievalKey 关联,replay 必须读取涉及的多个日期分片。
|
|
864
|
+
- replay 模式默认 persist=false,不污染 live audit。
|
|
865
|
+
- effective enabled=false 时目录不存在或不发生任何新增写入。
|
|
866
|
+
|
|
867
|
+
## 16. Replay 与评测
|
|
868
|
+
|
|
869
|
+
### 16.1 Pure replay
|
|
870
|
+
|
|
871
|
+
M4 core 必须支持:
|
|
872
|
+
|
|
873
|
+
~~~ts
|
|
874
|
+
replay({
|
|
875
|
+
contextSnapshots,
|
|
876
|
+
corpusSnapshot,
|
|
877
|
+
gatePolicy,
|
|
878
|
+
lexicalPolicy,
|
|
879
|
+
labels?
|
|
880
|
+
}) -> CanonicalShadowResult[]
|
|
881
|
+
~~~
|
|
882
|
+
|
|
883
|
+
Canonical 结果排除 recordedAt、latency 和 volatile runtimeTag,只比较:
|
|
884
|
+
|
|
885
|
+
- Gate action/state/reason/signals。
|
|
886
|
+
- queryDigest。
|
|
887
|
+
- retrievalId 的 deterministic core。
|
|
888
|
+
- candidate memoryId/version/digest/score/order。
|
|
889
|
+
- drop reasons。
|
|
890
|
+
|
|
891
|
+
相同输入必须逐字段一致。
|
|
892
|
+
|
|
893
|
+
### 16.2 历史 Session 回放
|
|
894
|
+
|
|
895
|
+
M4-3 可提供 tools/replay-m4-shadow.mjs,但必须:
|
|
896
|
+
|
|
897
|
+
- 由用户显式给出 session fixture/export;不后台扫描全部会话。
|
|
898
|
+
- 使用 M2 的原生 seq 去重和事实时间。
|
|
899
|
+
- 默认读取冻结 corpus fixture;使用 live corpus 时在报告中标记非历史快照。
|
|
900
|
+
- 输出到显式临时/报告路径,不写主 Session,不写 live audit。
|
|
901
|
+
- 不启动 Python、不调用模型或网络。
|
|
902
|
+
|
|
903
|
+
### 16.3 M4 可评估指标
|
|
904
|
+
|
|
905
|
+
M4 可直接评估:
|
|
906
|
+
|
|
907
|
+
- Gate action distribution。
|
|
908
|
+
- 有标签 fixture 的 Trigger Precision / Trigger Recall。
|
|
909
|
+
- Recall@K、MRR、candidate drop distribution。
|
|
910
|
+
- duplicate candidate rate。
|
|
911
|
+
- stale/cancel/deadline rate。
|
|
912
|
+
- latency overhead 和 audit bytes。
|
|
913
|
+
- cross-session/cross-workspace leakage,必须为 0。
|
|
914
|
+
|
|
915
|
+
M4 不能声称 Helpful Injection Gain、Harmful Injection Rate、Token Overhead 或 delivered success;这些需要 M6 之后的 A/B。
|
|
916
|
+
|
|
917
|
+
## 17. Host Debug 契约
|
|
918
|
+
|
|
919
|
+
M4-3 在既有 /debug 的 associativeMemory 下增加 shadowRetrieval:
|
|
920
|
+
|
|
921
|
+
关闭时严格为:
|
|
922
|
+
|
|
923
|
+
~~~json
|
|
924
|
+
{ "enabled": false }
|
|
925
|
+
~~~
|
|
926
|
+
|
|
927
|
+
开启时可包含:
|
|
928
|
+
|
|
929
|
+
~~~json
|
|
930
|
+
{
|
|
931
|
+
"enabled": true,
|
|
932
|
+
"shadowOnly": true,
|
|
933
|
+
"gatePolicyVersion": "gate_pre_v1",
|
|
934
|
+
"lexicalPolicyVersion": "lexical_pre_v1",
|
|
935
|
+
"memoryIndexVersion": "idx_pre_...",
|
|
936
|
+
"corpus": { "sources": 0, "records": 0, "legacyConflicts": 0, "staleSources": 0 },
|
|
937
|
+
"stats": { "evaluated": 0, "retrieved": 0, "prefetched": 0, "suppressed": 0, "stale": 0, "errors": 0 },
|
|
938
|
+
"runtimes": []
|
|
939
|
+
}
|
|
940
|
+
~~~
|
|
941
|
+
|
|
942
|
+
每个 runtime 只显示 runtimeTag(不含盐 sessionIdHash 的前 8 hex,仅 volatile/debug)、contextVersion、Gate 标量、inFlight 布尔和最近 audit metadata;corpus 统计另显示 legacyConflicts。不得暴露 query/excerpt/full path。M4 不新增公开 Agent 工具和设置页。
|
|
943
|
+
|
|
944
|
+
## 18. 失败与降级
|
|
945
|
+
|
|
946
|
+
~~~text
|
|
947
|
+
Gate suppress
|
|
948
|
+
-> no corpus IO, audit/counter only
|
|
949
|
+
|
|
950
|
+
Corpus missing/stale/invalid
|
|
951
|
+
-> suppress retrieval for affected source or whole snapshot
|
|
952
|
+
-> reasoned audit
|
|
953
|
+
-> never fall back to arbitrary Markdown scan outside SourceCatalog
|
|
954
|
+
|
|
955
|
+
Deadline/internal error
|
|
956
|
+
-> cancel/drop
|
|
957
|
+
-> base conversation unchanged
|
|
958
|
+
|
|
959
|
+
Python disabled/unavailable
|
|
960
|
+
-> irrelevant in M4; JS lexical core is the primary implementation
|
|
961
|
+
|
|
962
|
+
Any stale/scope mismatch
|
|
963
|
+
-> drop/suppress
|
|
964
|
+
-> never inject
|
|
965
|
+
~~~
|
|
966
|
+
|
|
967
|
+
M4 的失败不得影响既有记忆工具、自动沉淀、当前维护快照或基础对话。
|
|
968
|
+
|
|
969
|
+
## 19. 测试矩阵
|
|
970
|
+
|
|
971
|
+
实现 M4 时至少覆盖:
|
|
972
|
+
|
|
973
|
+
1. DEFAULT_CONFIG 两个相关开关仍默认 false。
|
|
974
|
+
2. associative=false/shadow=false:零 Shadow object、零 corpus IO、零 audit 文件、prompt/工具/路由/Markdown 字节不变。
|
|
975
|
+
3. associative=true/shadow=false:M2 观察可运行,M4 仍零状态/零 IO。
|
|
976
|
+
4. shadow=true 但 master/anchor 任一 false:hard suppress,不检索。
|
|
977
|
+
5. Gate 无 reasoning/monitor 仍对 fixture 确定可用。
|
|
978
|
+
6. Gate on/off 滞回、retrieve/prefetch/suppress 阈值、2 accepted-Segment cooldown、explicitRecall 绕过 Shadow cooldown,以及 disable→enable 后 enableEpoch/状态清零。
|
|
979
|
+
7. child session 与 plugin-generated user trigger 不启动检索;普通 top-level user source 可触发。
|
|
980
|
+
8. 同事件 seed replay + live feed 不重复 Gate/audit。
|
|
981
|
+
9. tokenizer 覆盖中文、英文、NFKC、camel/snake/kebab、路径、版本号、错误码和多字节预算。
|
|
982
|
+
10. Query term/phrase 数量、bytes、来源权重和 digest 确定。
|
|
983
|
+
11. M4 v1 仅 User MEMORY.md、当前 Workspace MEMORY.md 与当前日志可见;反思、其他日期日志、其他 Workspace、External、Calendar、archive、Session JSONL 不可见。
|
|
984
|
+
12. canonical path、Windows 大小写/分隔符、symlink/reparse 逃逸拒绝。
|
|
985
|
+
13. sidecar missing/corrupt/sourceFile mismatch/fileDigest stale/recordDigest stale 全部 fail closed。
|
|
986
|
+
14. >5 MiB 文件、>3 v1 sources、>512 records、>64 MiB corpus、>16 KiB record scoring slice 的预算行为与 reason;未来扩展上限另测。
|
|
987
|
+
15. memoryIndexVersion 对同 snapshot 稳定;源 tuple 任一变化即改变。
|
|
988
|
+
16. candidate 携带完整 M3 provenance;候选版本变化不改变 memoryId。
|
|
989
|
+
17. total 分数组件、tie-break 和顺序在重复运行中完全一致。
|
|
990
|
+
18. duplicate memoryId 触发 index-conflict;duplicate content 有明确 dropped provenance。
|
|
991
|
+
19. retrieve 可物化 bounded sanitized excerpt;prefetch 无 excerpt;两者均不注入。
|
|
992
|
+
20. contextVersion 在异步完成前变化 -> stale-context 整次丢弃。
|
|
993
|
+
21. source stat fingerprint 变化触发 affected-source reload;fileDigest/recordDigest 变化 -> stale-index/record-stale 丢弃;未变化时不全量重哈希。
|
|
994
|
+
22. A/B 并发 runtime 的 Gate latch、query、candidate、audit、cancel 零串线;tick 无 Agent/ALS 上下文时仍使用调度瞬间捕获的 workspaceKey。
|
|
995
|
+
23. dispose/关闭/plugin dispose 中止任务且队列自然结算;插件日界 00:00-07:30 的 future-dated/recency 计算正确。
|
|
996
|
+
24. durable audit 无原文、无绝对路径、无 sessionId、无凭据、无 BOM,单行可独立 JSON.parse;legacy/conflict 只进入 legacyConflicts 统计,不产候选。
|
|
997
|
+
25. audit append 并发不交错;失败只记 audit-write-failed,不污染 Session/Markdown。
|
|
998
|
+
26. retention/size cap 只清 audit,不触碰 M3 sidecar/backups/plans 或记忆。
|
|
999
|
+
27. replay 同输入 canonical result 一致;persist=false 零 live 污染。
|
|
1000
|
+
28. Shadow hit 不创建 pendingPacket、AccessEvidence、delivered cursor 或 Session event。
|
|
1001
|
+
29. softInjection/Python/reasoning/procedure/streaming 开关即使误开也不改变 M4 输出。
|
|
1002
|
+
30. 既有 M0-M3 全量回归继续通过,真实记忆 SHA-256 在测试前后不变。
|
|
1003
|
+
31. 全部新增 JS/JSON/MD/fixture UTF-8 无 BOM,git diff --check 干净。
|
|
1004
|
+
|
|
1005
|
+
## 20. 实施分段
|
|
1006
|
+
|
|
1007
|
+
### M4-0:Contract Freeze(本轮)
|
|
1008
|
+
|
|
1009
|
+
交付:
|
|
1010
|
+
|
|
1011
|
+
- docs/M4-CONTRACT.md。
|
|
1012
|
+
- system-map currentScope/M4 row/nextBrief 回写。
|
|
1013
|
+
- PREVIEW-NEXT-STEPS 与 handoff/Python 恢复入口更新。
|
|
1014
|
+
|
|
1015
|
+
禁止:运行时代码、真实检索、audit 目录、真实记忆修改。
|
|
1016
|
+
|
|
1017
|
+
### M4-1:C-03 Gate + Deterministic Lexical Core
|
|
1018
|
+
|
|
1019
|
+
只实现纯模块和 fixtures:
|
|
1020
|
+
|
|
1021
|
+
- GateSignals/GateDecision + gate_pre_v1。
|
|
1022
|
+
- RetrievalContextSnapshot validator。
|
|
1023
|
+
- deterministic tokenizer/QueryPlan + lexical_pre_v1。
|
|
1024
|
+
- Candidate schema、词法 score、排序、去重、预算和 drop reason。
|
|
1025
|
+
- 纯内存 CorpusSnapshot fixture;不读真实文件。
|
|
1026
|
+
- replay pure core。
|
|
1027
|
+
|
|
1028
|
+
建议模块:lib/shadow-retrieval-pre.js。
|
|
1029
|
+
|
|
1030
|
+
禁止:lib/index.js Host 接线、真实 sidecar/Markdown IO、durable audit、GUI、M5-M7。
|
|
1031
|
+
|
|
1032
|
+
### M4-2:M3 Corpus Adapter + Scope/Freshness
|
|
1033
|
+
|
|
1034
|
+
交付:
|
|
1035
|
+
|
|
1036
|
+
- SourceCatalog 与 canonical scope guard。
|
|
1037
|
+
- M3b sidecar/Markdown slice adapter。
|
|
1038
|
+
- memoryIndexVersion、CorpusRegistry/invalidation。
|
|
1039
|
+
- 仅临时 DSH_HOME 与 shadow-copy 文件测试。
|
|
1040
|
+
|
|
1041
|
+
禁止:真实 Host 事件接线、live 开关、durable audit、注入。
|
|
1042
|
+
|
|
1043
|
+
### M4-3:Host Shadow Wiring + Audit/Replay
|
|
1044
|
+
|
|
1045
|
+
交付:
|
|
1046
|
+
|
|
1047
|
+
- 复用现有 SessionRuntime 的 lazy Shadow state。
|
|
1048
|
+
- accepted Segment 后异步 latest-wins 调度。
|
|
1049
|
+
- config 热切换、abort/dispose、/debug 最小视图。
|
|
1050
|
+
- retrieval-pre durable audit、retention、显式 replay CLI。
|
|
1051
|
+
- 全量回归和真实记忆零修改证明。
|
|
1052
|
+
|
|
1053
|
+
仍保持默认关闭;不得构建 Packet 或 Evidence。
|
|
1054
|
+
|
|
1055
|
+
### M4-4:Live Shadow Verification
|
|
1056
|
+
|
|
1057
|
+
需用户明确启动:
|
|
1058
|
+
|
|
1059
|
+
1. 重启现有 127.0.0.1:3080 加载 Host 改动;不得启动替代 server。
|
|
1060
|
+
2. 先验证关闭态 /debug={enabled:false}、零 retrieval-pre 新写入。
|
|
1061
|
+
3. 临时开启 associativeMemoryEnabled + shadowRetrievalEnabled,保持 softInjection/Python 等关闭。
|
|
1062
|
+
4. 用可控用户输入、tool failure、重复动作和低信号输入验证 retrieve/prefetch/suppress。
|
|
1063
|
+
5. 复核 audit 无原文、候选 provenance fresh、cross-workspace leakage=0。
|
|
1064
|
+
6. 对比 prompt/runtime projection/Session 事件,证明零注入。
|
|
1065
|
+
7. 关闭 shadow 后验证任务 abort、volatile 状态清理、无后续 audit。
|
|
1066
|
+
8. 回写本契约实施证据与 system-map;默认配置仍 false。
|
|
1067
|
+
|
|
1068
|
+
## 21. M4 完成门
|
|
1069
|
+
|
|
1070
|
+
只有以下全部成立,M4 才能标记 live verified:
|
|
1071
|
+
|
|
1072
|
+
- M4-1/2/3 自动测试和全量 M0-M3 回归通过。
|
|
1073
|
+
- M4-4 在现有 GUI 实际进程完成 on/off 验证。
|
|
1074
|
+
- 默认关闭零行为/零 IO 成立。
|
|
1075
|
+
- 所有候选都有稳定 MemoryId 和完整 fresh provenance。
|
|
1076
|
+
- cross-session/cross-workspace leakage 为 0。
|
|
1077
|
+
- durable audit 不含原文、绝对路径或凭据。
|
|
1078
|
+
- prompt、Inbox、Session、pendingPacket、delivered cursor、AccessEvidence 全部零变化。
|
|
1079
|
+
- 真实 Markdown 和 M3 sidecar 身份未被 M4 修改。
|
|
1080
|
+
- 无 Python worker、embedding、Procedure 或注入代码偷跑。
|
|
1081
|
+
|
|
1082
|
+
M4 完成后下一里程碑是 M5 Access Evidence Graph。M5 必须单独冻结契约,不能把 Shadow hit 追认成历史 seen/read 证据。
|
|
1083
|
+
|
|
1084
|
+
## 22. 压缩恢复入口
|
|
1085
|
+
|
|
1086
|
+
上下文压缩后按以下顺序恢复:
|
|
1087
|
+
|
|
1088
|
+
1. 读取 docs/proactive-associative-memory-system-map.html 的 progressLedger、C-03、C-04、C-05、M-06、G-01/G-02/G-04/G-05。
|
|
1089
|
+
2. 读取 docs/M4-CONTRACT.md 全文。
|
|
1090
|
+
3. 读取 docs/M3B-CONTRACT.md §19,确认 M3b-4 live 与 sidecar/备份状态。
|
|
1091
|
+
4. 读取 lib/index.js 的 DEFAULT_CONFIG、ContextSegment、SessionRuntime、ingestEnvelope、dispose 与 /debug。
|
|
1092
|
+
5. 读取 lib/memory-anchor-pre.js 的 parseSidecar/buildAnchoredIndex 和 lib/memory-writer-pre.js 的 sidecar 事务边界。
|
|
1093
|
+
6. 运行 git status --short --branch,保留全部既有改动与未跟踪文件。
|
|
1094
|
+
7. M4-4 已 live verified;当前下一阶段只冻结 M5 Access Evidence Graph 契约,不新增 M5 运行时代码、不启动 Python。
|
|
1095
|
+
8. M5 契约冻结后回写 system-map、docs/M5-CONTRACT.md 与 PREVIEW-NEXT-STEPS;不 commit、不 push、不 tag、不发布。
|
|
1096
|
+
|
|
1097
|
+
恢复时以 system-map 为唯一架构/进度权威;本契约是 M4 细化规范,代码和测试是实现事实。
|
|
1098
|
+
|
|
1099
|
+
## 23. 实施状态(M4-1 完成,2026-08-23)
|
|
1100
|
+
|
|
1101
|
+
状态:**M4-1 C-03 Gate + Deterministic Lexical Core 已完成并通过 fixture 测试**;纯模块 `lib/shadow-retrieval-pre.js`(588 行,零 IO,零依赖 node:crypto);**未接入 lib/index.js**(grep 零新增引用);未读真实文件、未建 audit。
|
|
1102
|
+
|
|
1103
|
+
| 交付 | 说明 |
|
|
1104
|
+
| --- | --- |
|
|
1105
|
+
| SHADOW_GATE_POLICY_PRE_V1 | 冻结权重(explicitRecall .30/toolFailure .16/unresolved .16/repeated .12/novelty .08/phaseShift .08/historical .05/conflict .03/unresolvedAge .02;goalDrift/monitor/reasoning=0)+滞回 0.65/0.42+retrieve 0.80/prefetch 0.55+cooldownSegments=2+explicitRecallFloor 0.82+版本化词典(Object.freeze) |
|
|
1106
|
+
| SHADOW_LEXICAL_BUDGET_PRE_V1 | §12.5 全预算(window 8/4096、terms 32/2048B、records 512、64MiB、sources 3、16KiB 切片、rawHits 64、kept 8、excerpt 480B) |
|
|
1107
|
+
| DROP_REASONS | §13 版本化枚举(Gate/Corpus/Query/Async 全集) |
|
|
1108
|
+
| validateSnapshot | §6 字段/window≤8/4096 校验 |
|
|
1109
|
+
| memoryIndexVersion | §8 canonical tuples 排序→idx_pre_+first32(sha256);顺序无关/变化敏感 |
|
|
1110
|
+
| tokenize/buildQueryPlan | §10 NFKC+locale-independent lowercase+CJK 2-gram(≤64/run)+词形保留(camel/snake/kebab/版本/错误码)+stop words;terms≤32/2048B/digest 确定/oversize 计账 |
|
|
1111
|
+
| computeSignals/gatePreV1 | §9.3 纯信号公式+§9.2 硬抑制顺序(8级)+§9.4 滞回/cooldown=2/explicitRecall floor 与绕过;同输入同决策 |
|
|
1112
|
+
| lexicalSearch | §11-§13 termCoverage/headingCoverage/phrase(NFKC 边界)/recency(log 30 天半衰+插件日界 future-dated)/total≥0.10;rawHits 64→排序(total/tc/hc/Workspace 先/memoryId)→跨 memoryId recordDigest 去重(duplicate-content)→同 memoryId 多版本 index-conflict fail closed→kept 8;record-budget/corpus-byte-budget/source-budget fail closed |
|
|
1113
|
+
| buildRetrievalId/buildCandidateId/sanitizeExcerpt | ret_pre_/cand_pre_ 确定性身份;excerpt 480B UTF-8 截断+控制符清洗(retrieve volatile) |
|
|
1114
|
+
| replay | §16 pure core:canonical 排除 recordedAt/latency/runtimeTag;latch/cooldown 跨快照序列;suppress 零 IO |
|
|
1115
|
+
|
|
1116
|
+
测试 smoke-test-m4-pre.mjs F1-F12 全绿(策略冻结/validator/indexVersion/tokenizer/QueryPlan/硬抑制/滞回冷却绕过/child-plugin 抑制/lexicalSearch 排序与 future-dated/去重两语义/三预算/replay 确定性+excerpt)。全量回归 **11 项**(M0-M3 十项+M4)全部 exit 0。
|
|
1117
|
+
|
|
1118
|
+
**实现注记**:
|
|
1119
|
+
1. snapshot.trigger 扩展可选 text 字段供 explicitRecall/phaseShift 词典匹配(validator 不强制;Host 接线时从 Segment.text 最小投影传入)。
|
|
1120
|
+
2. E9 式教训同步:smoke-test-memory-index-pre.mjs B5 原硬编码 '2026-08-22.md' 在跨天后失效(memoryIndexSnapshot 的 logPath=memToday().md)——已改为插件日界动态日期 plugToday(),该测试对当前日期的隐式依赖消除。
|
|
1121
|
+
3. 下一步 M4-2:M3 Corpus Adapter + SourceCatalog canonical scope guard + memoryIndexVersion live 化(临时 DSH_HOME shadow-copy 测试)。
|
|
1122
|
+
|
|
1123
|
+
## 24. 实施状态(M4-2 完成,2026-08-23)
|
|
1124
|
+
|
|
1125
|
+
状态:**M4-2 Corpus Adapter 已完成并通过 shadow-copy 测试**;纯模块 `lib/m4-corpus-pre.js`(157 行);仍未接入 lib/index.js、未建 durable audit、未读真实记忆。
|
|
1126
|
+
|
|
1127
|
+
| 交付 | 说明(契约 §7/§8/§14.3) |
|
|
1128
|
+
| --- | --- |
|
|
1129
|
+
| canonicalize | resolve+正斜杠+小写(Windows 大小写不敏感稳定规则) |
|
|
1130
|
+
| buildSourceCatalog | §7.2 三源固定顺序(user/workspace/workspace-log)+canonicalFile+sourceRef 稳定相对引用(user:/workspace:/workspace-log:) |
|
|
1131
|
+
| canonicalScopeGuard | sidecar.sourceFile 与 catalog canonical 完全一致(mismatch 拒绝);realpath 解析 symlink/reparse 后不得逃逸声明目录(cross-workspace 拒绝);文件不存在=sidecar-invalid |
|
|
1132
|
+
| loadCorpusSnapshot | §7.3 六步校验链:sidecar-missing/sidecar-invalid/source-mismatch/stale-source(fileDigest)/record-stale(range 越界或切片 digest)/oversized 全部带原因 fail closed;预算(sources≤3/records≤512/corpusBytes≤64MiB)fail closed;产出 CorpusRecord(完整 M3 provenance)+memoryIndexVersion(idx_pre_) |
|
|
1133
|
+
| sourceFingerprint | stat size+mtimeMs(§14.3 分层 deadline 的复用依据) |
|
|
1134
|
+
| CorpusRegistry.get | fingerprint 未变化→fromCache 复用零重读;变化→整体重建并报告 reloaded sources;invalidate 强制重建 |
|
|
1135
|
+
|
|
1136
|
+
测试 smoke-test-m42-corpus.mjs G1-G6 exit 0(shadow-copy fixture:三源 catalog/provenance 链/fail closed 四原因/stale-source/record-stale/scope guard 三态/fingerprint 缓存与失效)。全量回归 **12 项**(M0-M3 十项+M4 两项)7.4s 全部 exit 0。
|
|
1137
|
+
|
|
1138
|
+
**实现注记**:
|
|
1139
|
+
1. loader 的 record 校验顺序:byte range 越界→切片 digest,均以 record-stale 丢弃;guard(source-mismatch/cross-workspace)先于文件读取。
|
|
1140
|
+
2. 测试教训:G5 断言方向写反(把 guard 的正确拒绝当失败)、G6 变量名 sideDir/sidecarDir 不一致——均为测试侧问题,引擎行为经探针证实正确。
|
|
1141
|
+
3. 下一步 M4-3:Host Shadow Wiring(lazy Shadow state/latest-wins 调度/config 热切换/retrieval-pre durable audit+replay CLI),仍默认关闭。
|
|
1142
|
+
|
|
1143
|
+
## 25. 实施状态(M4-3 完成,2026-08-23)
|
|
1144
|
+
|
|
1145
|
+
状态:**M4-3 Host Shadow Wiring 已完成并通过 H1-H6 测试**;durable audit 落盘路径已实现并验证隐私投影;仍默认关闭、零注入;M4-4 live 验证待用户启动。
|
|
1146
|
+
|
|
1147
|
+
| 交付 | 说明 |
|
|
1148
|
+
| --- | --- |
|
|
1149
|
+
| lib/shadow-host-pre.js | Host 接线层:createShadowHost({engine})——per-runtime WeakMap state(enableEpoch/processed/cooldown/latch/recentHits≤64/completedKeys≤256)、latest-wins abort、volatile ring ≤64 |
|
|
1150
|
+
| index.js 三处最小接线 | ingestEnvelope segment accept 后 fire-and-forget 钩子;debug 视图 shadowRetrieval 字段(关闭=严格 {enabled:false});runtime dispose 与 plugin disposeAll 的 shadow 清理 |
|
|
1151
|
+
| paths 捕获 | refreshAll 完成后 capturePaths(engine.state 快照;§7.2 合规——异步任务只用捕获值,不裸调 resolvePaths);userFile 由 state.userDir/MEMORY.md 推导(state 无该字段) |
|
|
1152
|
+
| payload 标量投影 | trigger 的 inputSource/sourcePlugin 从 envelope.payload 最小投影(plugin-generated user trigger 抑制依据);child session 经 parentSession 检测 hard suppress |
|
|
1153
|
+
| durable audit | retrieval-pre/audit/YYYY-MM-DD.jsonl append-only(串行链);32KiB truncateAuditEvent 尾部裁剪+audit-truncated 标记;retention 14 天/32MiB sweep |
|
|
1154
|
+
| 隐私投影验证 | audit 无原文/无绝对路径/无 sessionId/excerpt 不落盘;sourceRef 仅相对引用;shadowOnly/injected=false/delivered=false/accessEvidenceCreated=false |
|
|
1155
|
+
|
|
1156
|
+
测试 smoke-test-m43-pre.mjs H1-H6 exit 0(默认关闭零留存/开关矩阵/三开 retrieve 链路含 audit 卫生与 provenance/cooldown/child-plugin 抑制/dispose)。全量 **13 项**回归(M0-M3 十项+M4 三项)10.3s 全部 exit 0。
|
|
1157
|
+
|
|
1158
|
+
**调试过程发现(修复闭环)**:
|
|
1159
|
+
1. CorpusRegistry.get 成功返回缺 ok 字段 → runRetrieval 误判 corpus 失败(补 ok:true)。
|
|
1160
|
+
2. engine.refresh 的 _doRefresh 未返回 p 且 state 无 userFile → capturePaths 改由 state.userDir 推导用户级路径。
|
|
1161
|
+
3. trigger 标量(inputSource/sourcePlugin)在 envelope.payload 内而非顶层 → host 改读 payload。
|
|
1162
|
+
4. plugin-generated user trigger 曾触发完整 retrieve → 补 payload 投影检测后正确抑制。
|
|
1163
|
+
|
|
1164
|
+
下一步:**M4-4 Live Shadow Verification**(需用户重启现有 3080 加载 Host 改动;按契约 §20 分八步验证 on/off;默认配置保持 false→验证后再决定线上开关状态)。
|
|
1165
|
+
|
|
1166
|
+
## 26. 实施状态(M4-4 Live Verification 通过,2026-08-23)
|
|
1167
|
+
|
|
1168
|
+
状态:**M4-4 八步 live 验证全部通过,M4 整体完成并已回滚到默认关闭**。anchor 保持 true(M3b-4 迁移成果),assoc/shadow 恢复 false。
|
|
1169
|
+
|
|
1170
|
+
| 步骤 | 结果 |
|
|
1171
|
+
| --- | --- |
|
|
1172
|
+
| 重启加载 | 用户重启现有 3080(无替代 server)✓ |
|
|
1173
|
+
| 关闭态基线 | debug shadowRetrieval={enabled:false} 严格投影;retrieval-pre 目录不存在(零 IO);真实记忆 SHA 基线记录 ✓ |
|
|
1174
|
+
| 三开临时 | assoc/shadow/anchor=true;softInjection/Python/reasoning/procedure/streaming 全程关闭 ✓ |
|
|
1175
|
+
| 自然流量 suppress | 3 个工具 segments → below-threshold suppress(hesitation=0);suppress 不加载 corpus(sources=0/miv=null,§9.5) ✓ |
|
|
1176
|
+
| plugin 误杀发现与修复 | GUI 用户输入 data.source 非空被误判 plugin-generated → 按 §6「未知来源不得凭空归类」修复为仅 sourcePlugin 非空判定 + policy.pluginInputAllowlist=[] 固化(需重启生效)|
|
|
1177
|
+
| dshHome 缺陷发现与修复 | host 的 dshHome() 漏拼 .dsh 后缀 → audit 写到 <home>/memory 错误位置;修正后 auditDirPath=C:\Users\JH Z\.dsh\memory\retrieval-pre\audit ✓;错位目录已清理 |
|
|
1178
|
+
| explicit recall retrieve | 用户发"回忆一下之前的部署流程记录"→ outcome=completed、gate=retrieve/armed、hesitation=0.82(floor)、explicitRecall=1;corpus 三源 sources=3/records=88/rawHits=50/kept=8(预算上限);候选 8 条全带 provenance(memoryId/scope/sourceRef/version/digest/score),User+Workspace 授权正确;dropped=80 带 reason(below-score/no-lexical-match) |
|
|
1179
|
+
| audit 卫生 | 单行可 JSON.parse;shadowOnly=true/injected=false/delivered=false/accessEvidenceCreated=false;无原文/无绝对路径/无 sessionId/excerpt 不落盘 |
|
|
1180
|
+
| 零注入证明 | candidates 仅存于 audit;prompt/runtime projection/Session 事件/pendingPacket/delivered cursor 零变化;injected=false 显式断言 ✓ |
|
|
1181
|
+
| 关闭恢复 | assoc=false/shadow=false POST 后 debug={enabled:false};audit 行数 before=1 after=1(零新增写入);anchor=true 保持(M3 迁移成果) |
|
|
1182
|
+
|
|
1183
|
+
**Live 发现并修复(2 项,均已进代码)**:
|
|
1184
|
+
1. plugin-generated 判定违反 §6(inputSource 非空即判)→ 只认 sourcePlugin + policy.pluginInputAllowlist=[]。
|
|
1185
|
+
2. host dshHome() 漏拼 .dsh → audit 错位写入 <home>/memory;修正并对错位目录清理。
|
|
1186
|
+
|
|
1187
|
+
**M4 完成门对照(§21)**:默认关闭零行为/零 IO ✓;候选稳定 MemoryId+完整 fresh provenance ✓;cross-workspace leakage=0 ✓;durable audit 无原文/绝对路径/sessionId ✓;prompt/Inbox/Session/pendingPacket/delivered/AccessEvidence 零变化 ✓;真实 Markdown 与 sidecar 身份未被 M4 修改 ✓;无 Python/embedding/Procedure/注入偷跑 ✓。
|
|
1188
|
+
|
|
1189
|
+
## 27. lexical_pre_v2 检索质量升级(2026-08-23,用户批准 C 轻量版)
|
|
1190
|
+
|
|
1191
|
+
背景:M4-4 live 验证通过后复审确认——v1 的朴素 termCoverage(子串命中权重占比)缺少词稀有度与频度饱和考量。经用户批准执行「C 轻量版」:只做有公开依据的加固(BM25 + 权威停用词表),不引入第三方库、不改架构分工。
|
|
1192
|
+
|
|
1193
|
+
**升级内容**:
|
|
1194
|
+
|
|
1195
|
+
1. **BM25 相关性替换朴素覆盖率**(termCoverage/headingCoverage 内部实现):
|
|
1196
|
+
- IDF 公式:`IDF(t) = ln(1 + (N - df + 0.5)/(df + 0.5))`(Lucene BM25Similarity 同式,保证非负)
|
|
1197
|
+
- tf 饱和:`tf*(k1+1)/(tf + k1*(1 - b + b*dl/avgdl))`,k1=1.2 b=0.75(经典默认),除以 (k1+1) 归一到 [0,1]
|
|
1198
|
+
- termCoverage = 命中词 Σ(idf × sat × weight) / 查询词 Σ(idf × weight)
|
|
1199
|
+
- DF 表在 loader 统计循环一次构建;效果:常见词贡献下降、稀有关键词(错误码/配置项)贡献上升、单文档内重复堆词无收益
|
|
1200
|
+
2. **中文停用词表扩充**:哈工大停用词表(github leiyusi123/stopwords,过滤符号后 507 词)以 STOPWORDS_HIT_PRE_V2 固化,isStopWord 合并查旧表兜底
|
|
1201
|
+
3. policyVersion 升级 **lexical_pre_v1 → lexical_pre_v2**;bm25 参数与 stopwordsSource 固化进 SHADOW_GATE_POLICY_PRE_V1.dictionaries
|
|
1202
|
+
|
|
1203
|
+
**明确不变**:total 公式结构(0.72/0.15/0.08/0.05)、门槛 0.10、排序五键、三层去重、全部预算——v2 只替换相关性内核与停用词数据。
|
|
1204
|
+
|
|
1205
|
+
**与 Python 分工的关系(重申架构定位)**:JS 词法核心是「Python sidecar 不可用时的安全回退 + M4 可解释基线」;最终检索主力(embedding/向量/rerank/hybrid)按 PYTHON-SIDECAR-CONTRACT.md 由 M7 承担。lexical_pre_v2 提升的是回退层下限,不改变 M7 定位。
|
|
1206
|
+
|
|
1207
|
+
验证:F1-F12 全绿(digest 因词典变化自然更新,断言同步 v2);全量 13 项测试 exit 0;diff-check 干净;无 BOM。
|