@zooique/memora 4.0.0 → 5.1.0
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/CHANGELOG.md +235 -1743
- package/README.en.md +43 -36
- package/README.md +308 -303
- package/dist/agent/agent.d.ts +46 -82
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +153 -220
- package/dist/agent/agent.js.map +1 -1
- package/dist/agent/assembler.d.ts +3 -16
- package/dist/agent/assembler.d.ts.map +1 -1
- package/dist/agent/assembler.js +76 -47
- package/dist/agent/assembler.js.map +1 -1
- package/dist/agent/backgroundTasks.d.ts +8 -1
- package/dist/agent/backgroundTasks.d.ts.map +1 -1
- package/dist/agent/backgroundTasks.js +8 -1
- package/dist/agent/backgroundTasks.js.map +1 -1
- package/dist/agent/budget.d.ts +23 -5
- package/dist/agent/budget.d.ts.map +1 -1
- package/dist/agent/budget.js +8 -2
- package/dist/agent/budget.js.map +1 -1
- package/dist/agent/builtinToolHandlers.d.ts +50 -10
- package/dist/agent/builtinToolHandlers.d.ts.map +1 -1
- package/dist/agent/builtinToolHandlers.js +67 -20
- package/dist/agent/builtinToolHandlers.js.map +1 -1
- package/dist/agent/builtinTools.d.ts +16 -0
- package/dist/agent/builtinTools.d.ts.map +1 -1
- package/dist/agent/builtinTools.js +15 -4
- package/dist/agent/builtinTools.js.map +1 -1
- package/dist/agent/constants.d.ts +0 -6
- package/dist/agent/constants.d.ts.map +1 -1
- package/dist/agent/constants.js +7 -8
- package/dist/agent/constants.js.map +1 -1
- package/dist/agent/contextManager.d.ts +8 -0
- package/dist/agent/contextManager.d.ts.map +1 -1
- package/dist/agent/contextManager.js +45 -3
- package/dist/agent/contextManager.js.map +1 -1
- package/dist/agent/contextPreparer.d.ts +1 -1
- package/dist/agent/contextPreparer.d.ts.map +1 -1
- package/dist/agent/contextPreparer.js +15 -10
- package/dist/agent/contextPreparer.js.map +1 -1
- package/dist/agent/guardRail.d.ts +25 -10
- package/dist/agent/guardRail.d.ts.map +1 -1
- package/dist/agent/guardRail.js +154 -46
- package/dist/agent/guardRail.js.map +1 -1
- package/dist/agent/loop.d.ts +46 -13
- package/dist/agent/loop.d.ts.map +1 -1
- package/dist/agent/loop.js +145 -32
- package/dist/agent/loop.js.map +1 -1
- package/dist/agent/managers/archiveCoordinator.d.ts +15 -3
- package/dist/agent/managers/archiveCoordinator.d.ts.map +1 -1
- package/dist/agent/managers/archiveCoordinator.js +13 -7
- package/dist/agent/managers/archiveCoordinator.js.map +1 -1
- package/dist/agent/managers/chatLockManager.d.ts +3 -9
- package/dist/agent/managers/chatLockManager.d.ts.map +1 -1
- package/dist/agent/managers/chatLockManager.js +7 -25
- package/dist/agent/managers/chatLockManager.js.map +1 -1
- package/dist/agent/managers/llmCaller.d.ts.map +1 -1
- package/dist/agent/managers/llmCaller.js +27 -1
- package/dist/agent/managers/llmCaller.js.map +1 -1
- package/dist/agent/managers/memoryInspector.d.ts +12 -7
- package/dist/agent/managers/memoryInspector.d.ts.map +1 -1
- package/dist/agent/managers/memoryInspector.js +32 -19
- package/dist/agent/managers/memoryInspector.js.map +1 -1
- package/dist/agent/managers/roundSummaryGenerator.d.ts +3 -1
- package/dist/agent/managers/roundSummaryGenerator.d.ts.map +1 -1
- package/dist/agent/managers/roundSummaryGenerator.js +14 -4
- package/dist/agent/managers/roundSummaryGenerator.js.map +1 -1
- package/dist/agent/managers/sessionArchiver.d.ts +20 -6
- package/dist/agent/managers/sessionArchiver.d.ts.map +1 -1
- package/dist/agent/managers/sessionArchiver.js +19 -5
- package/dist/agent/managers/sessionArchiver.js.map +1 -1
- package/dist/agent/managers/sessionManager.d.ts +21 -88
- package/dist/agent/managers/sessionManager.d.ts.map +1 -1
- package/dist/agent/managers/sessionManager.js +77 -278
- package/dist/agent/managers/sessionManager.js.map +1 -1
- package/dist/agent/seed/orchestrator.d.ts.map +1 -1
- package/dist/agent/seed/orchestrator.js +3 -3
- package/dist/agent/seed/orchestrator.js.map +1 -1
- package/dist/agent/seed/prepare.d.ts.map +1 -1
- package/dist/agent/seed/prepare.js +9 -4
- package/dist/agent/seed/prepare.js.map +1 -1
- package/dist/agent/seed/types.d.ts +11 -4
- package/dist/agent/seed/types.d.ts.map +1 -1
- package/dist/agent/seed/types.js +2 -2
- package/dist/agent/toolExecutor.d.ts +69 -18
- package/dist/agent/toolExecutor.d.ts.map +1 -1
- package/dist/agent/toolExecutor.js +188 -28
- package/dist/agent/toolExecutor.js.map +1 -1
- package/dist/agent/toolResultCache.js +1 -1
- package/dist/agent/toolRunner.d.ts +4 -2
- package/dist/agent/toolRunner.d.ts.map +1 -1
- package/dist/agent/toolRunner.js +7 -4
- package/dist/agent/toolRunner.js.map +1 -1
- package/dist/agent/types.d.ts +8 -25
- package/dist/agent/types.d.ts.map +1 -1
- package/dist/index.d.ts +9 -20
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -32
- package/dist/index.js.map +1 -1
- package/dist/logging/logger.d.ts +4 -1
- package/dist/logging/logger.d.ts.map +1 -1
- package/dist/logging/logger.js +5 -2
- package/dist/logging/logger.js.map +1 -1
- package/dist/memory/gcService.d.ts.map +1 -1
- package/dist/memory/gcService.js +3 -5
- package/dist/memory/gcService.js.map +1 -1
- package/dist/memory/inMemorySessionStore.d.ts +2 -2
- package/dist/memory/inMemorySessionStore.js +2 -2
- package/dist/memory/inMemoryStorage.d.ts +4 -3
- package/dist/memory/inMemoryStorage.d.ts.map +1 -1
- package/dist/memory/inMemoryStorage.js +2 -2
- package/dist/memory/inMemoryStorage.js.map +1 -1
- package/dist/memory/nodeSqliteStorage.d.ts +17 -0
- package/dist/memory/nodeSqliteStorage.d.ts.map +1 -0
- package/dist/memory/nodeSqliteStorage.js +393 -0
- package/dist/memory/nodeSqliteStorage.js.map +1 -0
- package/dist/memory/projectManager.d.ts +10 -20
- package/dist/memory/projectManager.d.ts.map +1 -1
- package/dist/memory/projectManager.js +27 -41
- package/dist/memory/projectManager.js.map +1 -1
- package/dist/memory/roundStore.d.ts +76 -1
- package/dist/memory/roundStore.d.ts.map +1 -1
- package/dist/memory/roundStore.js.map +1 -1
- package/dist/memory/roundSummaryLookup.d.ts +26 -0
- package/dist/memory/roundSummaryLookup.d.ts.map +1 -0
- package/dist/memory/roundSummaryLookup.js +19 -0
- package/dist/memory/roundSummaryLookup.js.map +1 -0
- package/dist/memory/sessionStore.d.ts +19 -2
- package/dist/memory/sessionStore.d.ts.map +1 -1
- package/dist/memory/sessionStore.js.map +1 -1
- package/dist/memory/sourceValidation.d.ts +2 -13
- package/dist/memory/sourceValidation.d.ts.map +1 -1
- package/dist/memory/sourceValidation.js +5 -16
- package/dist/memory/sourceValidation.js.map +1 -1
- package/dist/memory/storageInterface.d.ts +26 -16
- package/dist/memory/storageInterface.d.ts.map +1 -1
- package/dist/memory/supersedeResolve.d.ts +39 -0
- package/dist/memory/supersedeResolve.d.ts.map +1 -0
- package/dist/memory/supersedeResolve.js +16 -0
- package/dist/memory/supersedeResolve.js.map +1 -0
- package/dist/memory/types.d.ts +3 -2
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +2 -1
- package/dist/memory/types.js.map +1 -1
- package/dist/role-pack/rolePackManager.d.ts +33 -24
- package/dist/role-pack/rolePackManager.d.ts.map +1 -1
- package/dist/role-pack/rolePackManager.js +48 -42
- package/dist/role-pack/rolePackManager.js.map +1 -1
- package/dist/role-pack/strategyKeys.d.ts +8 -0
- package/dist/role-pack/strategyKeys.d.ts.map +1 -1
- package/dist/role-pack/strategyKeys.js +10 -0
- package/dist/role-pack/strategyKeys.js.map +1 -1
- package/dist/role-pack/strategyResolver.d.ts +6 -1
- package/dist/role-pack/strategyResolver.d.ts.map +1 -1
- package/dist/role-pack/strategyResolver.js +20 -2
- package/dist/role-pack/strategyResolver.js.map +1 -1
- package/dist/role-pack/types.d.ts +5 -1
- package/dist/role-pack/types.d.ts.map +1 -1
- package/dist/security/confirmEntries.d.ts +21 -6
- package/dist/security/confirmEntries.d.ts.map +1 -1
- package/dist/security/confirmEntries.js +21 -6
- package/dist/security/confirmEntries.js.map +1 -1
- package/dist/security/pathGuard.d.ts +44 -10
- package/dist/security/pathGuard.d.ts.map +1 -1
- package/dist/security/pathGuard.js +70 -10
- package/dist/security/pathGuard.js.map +1 -1
- package/dist/utils/backgroundTask.d.ts +56 -34
- package/dist/utils/backgroundTask.d.ts.map +1 -1
- package/dist/utils/backgroundTask.js +130 -99
- package/dist/utils/backgroundTask.js.map +1 -1
- package/dist/utils/errors.d.ts +3 -2
- package/dist/utils/errors.d.ts.map +1 -1
- package/dist/utils/errors.js +3 -2
- package/dist/utils/errors.js.map +1 -1
- package/dist/utils/eventEmitter.d.ts +20 -22
- package/dist/utils/eventEmitter.d.ts.map +1 -1
- package/dist/utils/eventEmitter.js +0 -3
- package/dist/utils/eventEmitter.js.map +1 -1
- package/dist/utils/time.d.ts +3 -3
- package/dist/utils/time.d.ts.map +1 -1
- package/dist/utils/time.js +3 -3
- package/dist/utils/time.js.map +1 -1
- package/dist/utils/toError.d.ts +1 -1
- package/dist/utils/toError.js +1 -1
- package/dist/web-fetch/loginWall.d.ts +39 -0
- package/dist/web-fetch/loginWall.d.ts.map +1 -0
- package/dist/web-fetch/loginWall.js +78 -0
- package/dist/web-fetch/loginWall.js.map +1 -0
- package/dist/web-fetch/types.d.ts +8 -0
- package/dist/web-fetch/types.d.ts.map +1 -1
- package/dist/web-fetch/webFetchProvider.d.ts.map +1 -1
- package/dist/web-fetch/webFetchProvider.js +3 -1
- package/dist/web-fetch/webFetchProvider.js.map +1 -1
- package/dist/web-search/fetchWebSearchProvider.js +28 -23
- package/dist/web-search/fetchWebSearchProvider.js.map +1 -1
- package/docs/architecture/role-pack-authoring-guide.md +7 -1
- package/docs/architecture/role-pack-spec.md +11 -6
- package/docs/memora-api-reference.md +1354 -1276
- package/docs/memora-/345/215/207/347/272/247/346/214/207/345/215/227-4.x-/345/210/260-5.0.0.md +385 -0
- package/docs/memora-/346/216/245/345/205/245/346/214/207/345/215/227.md +89 -49
- package/docs/role-pack-/345/274/200/346/224/276/351/224/256/346/214/207/345/215/227.md +148 -148
- package/package.json +13 -4
- package/role-packs/README.md +41 -40
- package/role-packs/memora/345/212/251/346/211/213/rules.md +5 -4
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/manifest.json +1 -0
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/persona.md +46 -46
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/rules.md +17 -16
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/emotion-wave.md +46 -46
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/foreshadow.md +29 -29
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/outline-expand.md +73 -48
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/project-init/scripts/init-novel-project.mjs +445 -441
- package/role-packs//345/205/261/351/270/243/345/260/217/350/257/264/345/256/266/skills/story-bible.md +62 -62
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/manifest.json +1 -0
- package/role-packs//347/231/275/350/257/235/346/226/271/346/241/210/350/256/276/350/256/241/345/270/210/rules.md +2 -1
- package/dist/agent/managers/dedupManager.d.ts +0 -85
- package/dist/agent/managers/dedupManager.d.ts.map +0 -1
- package/dist/agent/managers/dedupManager.js +0 -248
- package/dist/agent/managers/dedupManager.js.map +0 -1
- package/dist/agent/managers/goalConsistencyChecker.d.ts +0 -42
- package/dist/agent/managers/goalConsistencyChecker.d.ts.map +0 -1
- package/dist/agent/managers/goalConsistencyChecker.js +0 -178
- package/dist/agent/managers/goalConsistencyChecker.js.map +0 -1
- package/dist/agent/managers/llmJudgeHelper.d.ts +0 -21
- package/dist/agent/managers/llmJudgeHelper.d.ts.map +0 -1
- package/dist/agent/managers/llmJudgeHelper.js +0 -32
- package/dist/agent/managers/llmJudgeHelper.js.map +0 -1
- package/dist/agent/managers/memoryAdvisor.d.ts +0 -105
- package/dist/agent/managers/memoryAdvisor.d.ts.map +0 -1
- package/dist/agent/managers/memoryAdvisor.js +0 -322
- package/dist/agent/managers/memoryAdvisor.js.map +0 -1
- package/dist/agent/managers/memoryGovernance.d.ts +0 -24
- package/dist/agent/managers/memoryGovernance.d.ts.map +0 -1
- package/dist/agent/managers/memoryGovernance.js +0 -46
- package/dist/agent/managers/memoryGovernance.js.map +0 -1
- package/dist/memory/governance.d.ts +0 -17
- package/dist/memory/governance.d.ts.map +0 -1
- package/dist/memory/governance.js +0 -17
- package/dist/memory/governance.js.map +0 -1
- package/dist/memory/projectRegistry.d.ts +0 -47
- package/dist/memory/projectRegistry.d.ts.map +0 -1
- package/dist/memory/projectRegistry.js +0 -151
- package/dist/memory/projectRegistry.js.map +0 -1
- package/dist/utils/recallDefaults.d.ts +0 -16
- package/dist/utils/recallDefaults.d.ts.map +0 -1
- package/dist/utils/recallDefaults.js +0 -16
- package/dist/utils/recallDefaults.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,1743 +1,235 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
本文件记录 **@zooique/memora(内核 npm 包)**的版本变更。**宿主**(`hosts/memora-vscode`)不在发布包 `files` 白名单内(见 `package.json
|
|
4
|
-
|
|
5
|
-
格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。
|
|
6
|
-
|
|
7
|
-
> **版本定位(
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
- `
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
- `
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
-
|
|
59
|
-
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
`
|
|
101
|
-
|
|
102
|
-
`
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
`
|
|
112
|
-
|
|
113
|
-
`
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
-
|
|
120
|
-
- `
|
|
121
|
-
-
|
|
122
|
-
- `
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
###
|
|
137
|
-
|
|
138
|
-
**
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
-
|
|
154
|
-
|
|
155
|
-
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
`
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
`
|
|
186
|
-
|
|
187
|
-
`
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
`
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
- **测试**:`detachAll` 脱管不杀(3 处断言:status 仍 `running` / 仍可 `kill` 取回 / 再脱管仍能列出)
|
|
237
|
-
+ turn 终态脱管 + 报告文案不得含「已全部终止」+ 纯问答不产 `background_report`(反向守卫)
|
|
238
|
-
- **变异验证 2 组**(逐组精确转红):`detachAll` 改回 `killNow`+置 `killed` → 3 红;
|
|
239
|
-
恢复 `command-result` 丢弃行 → `aborted` 留存守卫红
|
|
240
|
-
- **方案文档**:`docs/方案-后台任务跨轮存活-20261004.md`(含主流对标实锤、SSOT 论证、刻意不做清单)
|
|
241
|
-
|
|
242
|
-
### Added(内核 · 用户角色包目录重扫对账 `resyncUserPacks` · 角色包「刷新」按钮内核落点)
|
|
243
|
-
|
|
244
|
-
- **背景**:`loadExtraDir` 仅在 Agent 装配时执行一次,面板折叠展开读内存快照——用户在用户
|
|
245
|
-
角色包目录新增/改名/删除/修改角色包后,不重启宿主不生效(真机 RP-EDIT-1 冒烟实证)。
|
|
246
|
-
- **语义(净差对账,对用户诚实)**:摘除全部运行时注入项(`runtimeNames` 记账名单)→ 重新
|
|
247
|
-
`loadExtraDir` → 同名重注入 = 内容更新生效(`updated`),不算新增/移除;真消失(目录已删 /
|
|
248
|
-
改名旧名)才进 `removed`,全新名字才计 `added`。
|
|
249
|
-
- **激活悬空走 §4.1 单链兜底**:原激活包被摘除时复用 `activateFallback()`(与 reload 激活包被删
|
|
250
|
-
同源同判据),经 `onActiveChanged` 同步宿主 UI;不自造第二套回退规则。
|
|
251
|
-
- **边界**:内置包不参与对账(磁盘真理源 = dist,构建期同步,运行中恒定);manifest.name 撞内置
|
|
252
|
-
的用户包继承重名跳过判据。
|
|
253
|
-
- **测试**:5 用例锁行为(新增注入 / 删除摘除 + 记账连续 / 改名 / 悬空兜底 / 内容更新净差)。
|
|
254
|
-
|
|
255
|
-
### Fixed(内核 · 读取防重分支②死路回放:台账替身回显补「原文仍在上下文」前置 · 数据源取证 round-1791449684099)
|
|
256
|
-
|
|
257
|
-
**真机死循环实锤**:一次 turn 内「整读文件 → 上下文压缩挤掉原文 → 中段重读」时,台账分支②
|
|
258
|
-
(替身回显)在**原文已不在上下文**的情况下仍以「已有覆盖」为由把请求拦截成摘要替身——模型拿不到
|
|
259
|
-
原文、重读又被拦,整读→压缩→重读→替身拦死循环(生产轮复现数据 round-1791449684099)。
|
|
260
|
-
|
|
261
|
-
- **契约前置**:`shouldEchoLedgerStub(subj, cov, stillInContext)` 增第三必填参数,前置不过则
|
|
262
|
-
一切区间判定短路为放行(放行真读,新结果入上下文后由分支① `read_dedup` 接手防重复)——
|
|
263
|
-
宁可多读一次不可误拦(两个失败方向不对称,防永动机语义不变)。
|
|
264
|
-
- **数据面收口**:`FileCoverage` 新增必填 `lastToolCallId` / `fingerprint`(定位锚 + 进上下文
|
|
265
|
-
内容指纹,与 toolResultCache 同口径同源计算)——禁 optional 兜底:缺锚则回退语义恒为「在」,
|
|
266
|
-
死路回放复发,宁编译期红。
|
|
267
|
-
- **判据单一收口**:新抽 `AgentLoop.isMessageStillUnmodified(toolCallId, fingerprint)`,
|
|
268
|
-
分支①(`isCachedResultStillInContext` 委托)与分支②(回显前置)共用同一「原文是否仍在
|
|
269
|
-
上下文」判据,不双轨。
|
|
270
|
-
- 测试:死路回放生产序列复现用例(整读→压缩→中段重读应放行 3 次真读、零回显)+ 压缩语境
|
|
271
|
-
放行组重写 + 归一拦截组重构保留;变异验证(短路放行分支 → 4 用例精确转红 → 恢复全绿)已做。
|
|
272
|
-
|
|
273
|
-
### Fixed(内核 · Windows 命令输出编码事实缺失:模型对 cmd OEM/GBK 乱码失明 · CMD-2 补宣告)
|
|
274
|
-
|
|
275
|
-
**实证坐实**:`run_command` 经 `cmd /c` 执行时,cmd 写管道输出用系统 OEM 代码页(简中系统为
|
|
276
|
-
GBK;实测 `chcp 65001` 下仍输出 GBK 字节),而内核执行器恒按 UTF-8 解码收流——非 ASCII 输出
|
|
277
|
-
必显示为乱码(ASCII 不受影响,故英文命令无感、中文场景模型反复踩坑且无法自查归因)。
|
|
278
|
-
|
|
279
|
-
- **裁决 = 事实宣告(非解码改造)**:`buildEnvironmentContextBlock` 新增 win32 平台条件行
|
|
280
|
-
「命令输出编码:cmd 管道输出按系统 OEM 代码页写出(简中系统为 GBK),内核按 UTF-8 解码——
|
|
281
|
-
非 ASCII 输出会显示为乱码(ASCII 不受影响);Node 脚本输出为 UTF-8」。纯事实链零行为引导
|
|
282
|
-
(对齐环境段「零解释转发」纪律);平台参数化与 `resolveShellCommand` 同先例,POSIX 不加噪音。
|
|
283
|
-
- 三方对照:内核执行路径(spawn `cmd /c` + UTF-8 收流)↔ 工具描述(无编码声明、不冲突)↔
|
|
284
|
-
环境宣告段(本条补齐)。
|
|
285
|
-
|
|
286
|
-
### Fixed(内核 · 后台任务回流通知首标签穷尽化:`timedOut` 不再谎报「完成」· 发版前审查 H1)
|
|
287
|
-
|
|
288
|
-
**行为修正**:`formatBackgroundTaskNotice` 旧首标签由二元三元推导(`killed ? '已终止' : '完成'`),
|
|
289
|
-
`timedOut` 产出「[后台命令完成] · 超时被终止」自相矛盾、`running` 被谎报完成。
|
|
290
|
-
|
|
291
|
-
- 新增穷尽表 `BACKGROUND_TASK_NOTICE_TAGS: Record<BackgroundTaskStatus, string>`(内核内部,
|
|
292
|
-
不挂公共面——消费面是内核回流通知文本,宿主无 import 需求;`Record` 穷尽键 = 状态枚举增补时
|
|
293
|
-
编译期红,同 `COMPRESS_TARGET_LABELS` 范式),四态各给诚实首标签;
|
|
294
|
-
状态文案渲染仍以既有 `BACKGROUND_TASK_STATUS_LABELS` 为唯一真源(不双轨)。
|
|
295
|
-
- 测试:`timedOut` 首标签不得谎报完成(回归锁)+ 四态逐条与穷尽表同源断言;
|
|
296
|
-
变异验证(表值串档 → 精确转红)已做。
|
|
297
|
-
|
|
298
|
-
### Fixed(内核 · 宿主退出孤儿进程:补实例终态杀树 · 观察点 ⑧ 真机定类闭环)
|
|
299
|
-
|
|
300
|
-
**真机实锤**:完全退出 VS Code 约 10 秒后,后台 `ping -n 300`(PID 15456)仍在运行,
|
|
301
|
-
其父进程(扩展宿主)已不存在——Windows 不回收脱离控制台的子进程,Job Object 兜底在此
|
|
302
|
-
环境不成立。旧代码 `Agent.close` 不处置后台注册表,每次退出留一批 OS 孤儿(dev server
|
|
303
|
-
类更会永久占端口)。
|
|
304
|
-
|
|
305
|
-
- **两个生命周期终点分开**(勿折叠):turn 终态 `detachAll` **不杀**(跨轮存活);
|
|
306
|
-
Agent 实例终态新增 `BackgroundTaskRegistry.killAllRunning()` **真杀**——注册表按
|
|
307
|
-
实例隔离是硬不变量,实例销毁后任务不可寻址,不杀即孤儿
|
|
308
|
-
- **接线**:`AgentLoop.shutdownBackgroundTasks()` 纯透传(未装配返 0);`Agent.close()`
|
|
309
|
-
在 loop null 化前调用;宿主 `deactivate` 本就 await close,**宿主侧零行为改动**。
|
|
310
|
-
主动终止逻辑抽单点 `terminate`(`kill` / `killAllRunning` 共用),不回调 listener
|
|
311
|
-
(退出时回流队列已无消费方),不推 UI 快照
|
|
312
|
-
- **诚实边界**:只覆盖扩展正常停用;扩展崩溃 / 被 OS 强杀时 `close` 来不及执行,该场景
|
|
313
|
-
依旧不承诺清理。文案三处(工具描述 / `[BACKGROUND_STARTED]` 回执 / turn 收尾报告)
|
|
314
|
-
统一为「正常退出 VS Code 时终止;崩溃 / 被强杀不保证」
|
|
315
|
-
⚠️ 本条的「正常停用」承诺当时仍是谎(见下一条 31ms 窗口实锤),由下一条补第二触发通路后才成真
|
|
316
|
-
- **测试**:注册表混合态收割(running 真杀 / completed、killed 不碰 / 不回调 listener)+
|
|
317
|
-
loop 透传(含未装配返 0)+ `Agent.close` 调用点 spy 守卫;**变异验证 2 组**(断 close
|
|
318
|
-
接线 → spy 红;收割改纯读 → 状态断言红)
|
|
319
|
-
- **定案沉淀**:ADR-036(后台命令任务双生命周期边界 + 回流留存;S2 固化触发 1 = src 引用
|
|
320
|
-
≥1),src 定案注释锚改指 ADR
|
|
321
|
-
- **顺带修测试夹具假活(同批实锤的既有缺陷)**:`backgroundTasks.test.ts` 的
|
|
322
|
-
`SLEEP_CMD` 原写法 `node -e "setTimeout(()=>{},120000)"` 在 Windows `cmd /c` 下
|
|
323
|
-
**引号被原样传给 node,eval 的是字符串字面量(空语句)→ 秒退 exit 0**,而既有用例
|
|
324
|
-
只在 start 占位 `running` 的窗口内断言,从未真验进程存活。改为平台分叉
|
|
325
|
-
(win32 无引号 function 版 / POSIX 双引号版,引号在两个 shell 命运相反),
|
|
326
|
-
`loop.test.ts` 同型夹具一并修;新用例以「起后 300ms 复查仍 running」挡占位假活
|
|
327
|
-
|
|
328
|
-
### Fixed(内核 · 关窗 31ms 窗口实锤:exit 钩子同步兜底收割 · 观察点 ⑧ 第二轮)
|
|
329
|
-
|
|
330
|
-
**真机实锤(第二轮,新 dist 含杀树重测)**:renderer 发 terminate 到扩展宿主进程消失仅
|
|
331
|
-
**31ms**(16:15:28.817 → 16:15:28.848,exit 0),Memora 日志零收割痕迹,`ping -n 300`
|
|
332
|
-
成孤儿跑至自然结束。async `close()` 深处的杀树在 Windows 正常关窗的清理窗口里根本
|
|
333
|
-
跑不到 ⇒ 上一条的「正常退出时终止」当时是谎(诚实边界承诺跑不到代码路径)。
|
|
334
|
-
|
|
335
|
-
- **exit 钩子同步兜底**:注册表构造时 `process.on('exit')`,钩子内遍历 running 用**同步**
|
|
336
|
-
杀树原语 `killProcessTreeSync`(Windows `execFileSync('taskkill', …)`;POSIX
|
|
337
|
-
`process.kill(-pgid)` 本就同步)。为何必须同步:异步 spawn 的 fork 由 libuv 线程池派发,
|
|
338
|
-
exit 钩子返回后 Node 即退出,fork 可能来不及完成 ⇒ 杀树静默失败(假阴性同族)
|
|
339
|
-
- **同源防双真理源**:同步 / 异步原语共享 `buildTaskkillArgs` 参数构造(改一处漏一处无测试
|
|
340
|
-
报警 = 第二真理源反模式);terminate 单点加 `mode` 档位且**必传**(缺省值语义 = 语境含糊
|
|
341
|
-
静默回落),close 通路走异步、exit 通路走同步,共用同一终止单点
|
|
342
|
-
- **注册/注销配对**:`shutdown()` = `killAllRunning()` + 注销钩子——钩子是**进程级**监听、
|
|
343
|
-
注册表是**实例级**对象,不配对 = 多实例钩子堆积 + 闭包泄漏;注销后经 `disposed` 判空转(幂等)
|
|
344
|
-
- **测试 +6**:同步原语机制级(taskkill 参数同源断言 / 128 静默达成 / 非 128 降级单杀 /
|
|
345
|
-
POSIX `kill(-pgid)`)+ 钩子注册恰一个、注销回原数(配对守卫)+ 兜底收割行为(置 killed、
|
|
346
|
-
不回调 listener、重复触发幂等)+ 注销后空转;存量用例收尾统一改 `shutdown()`
|
|
347
|
-
(测试自身不得复制「注册不注销」的堆积模式,防 Node MaxListeners 告警)
|
|
348
|
-
- **诚实边界更新**:「正常退出 VS Code 时终止」自本条起**成真**(close 通路一 + exit 钩子
|
|
349
|
-
通路二双触发);扩展崩溃 / 被 OS 强杀 / 断电时两通路都来不及执行,**依旧不承诺清理**。
|
|
350
|
-
定案锚 ADR-036 决策 1 已同步双通路口径
|
|
351
|
-
- **真机复测第三轮(2026-10-04 16:58)✅ 通过**:新 dist(16:56:39 构建,exitHook 符号确认)→
|
|
352
|
-
16:57 起后台 `ping -n 300`(自然寿命应到 ~17:02)→ 16:58:00 关 VS Code(**26ms** 窗口,
|
|
353
|
-
比第二轮更紧)→ 16:59 查证**零 ping 残留**。判定:ping 在自然寿命内消失 = 被杀树收割,
|
|
354
|
-
非自然结束;同轮「turn 终态脱管不杀」(ping 活过 turn)与「实例终态杀树」两个定案同机验证
|
|
355
|
-
⚠️ **通路归因存灰区(如实登记)**:OutputChannel 日志在退出瞬间来不及 flush,杀树日志未落盘,
|
|
356
|
-
无法从日志直接指认 exit 钩子还是 deactivate 恰好跑完;26ms 窗口下后者概率极低,
|
|
357
|
-
结果层验收锚(退出零孤儿)达成即本轮验收目标
|
|
358
|
-
|
|
359
|
-
### Fixed(内核+宿主 · 后台任务终态 UI 不准 + 终态行可手动收起 · CMD-1 阶段 3 补漏)
|
|
360
|
-
|
|
361
|
-
**缺口(阶段一自查漏判)**:脱管落地后,任务自然跑完时**宿主完全收不到通知**——
|
|
362
|
-
`setCompletionListener` 的回调只做 `enqueueCommandResult`(入队给模型),无任何出宿主的面。
|
|
363
|
-
而宿主推 UI 只有三个时机(`step_boundary` / `background_report` / kill 后回推),脱管后 turn 已结束,
|
|
364
|
-
三个全不覆盖 ⇒ **条上一律写「运行中」,实际早已跑完**。
|
|
365
|
-
|
|
366
|
-
> 比原缺陷更坏:原缺陷是「进程死了却显示已终止」(假终态),本漏是「进程活着却显示运行中」
|
|
367
|
-
> (**假活跃**)——让用户以为还有事在跑,而真相是结果早已躺在队列里。
|
|
368
|
-
|
|
369
|
-
- **新增内核事件 `backgroundTaskSettled`**(入 `AgentEventMap` + `AGENT_EVENTS`):挂在注册表
|
|
370
|
-
`notify` 单点链上(**仅自然终态 settle 经此;主动 kill 刻意不回调**——输出已直接返回,回调会
|
|
371
|
-
造成双份消费;UI 终止路径由宿主 kill 后自行回拉快照)⇒ `loop.setBackgroundTaskSettledEmitter` →
|
|
372
|
-
`agent.emit` → 宿主 `bindAgentNoticeEvents` 订阅。**不新增注册表 listener**
|
|
373
|
-
(`setCompletionListener` 是单点 setter 且已被回流占用,加第二个即第二真理源);
|
|
374
|
-
**走既有 `TypedEventEmitter`** 而非独立回调字段(与宿主 `off`/`on` 幂等模式对齐)。
|
|
375
|
-
载荷只带 `taskId` / `command` / `status`——**刻意不含输出**(同 `BackgroundTaskView`
|
|
376
|
-
不含 `result` 的口径)
|
|
377
|
-
- **终态行可手动收起**:webview 终态行给 `×` → `background_kill` + `reason:'dismiss'`;宿主记入
|
|
378
|
-
`Set` 并在投影出口过滤 ⇒ **只关掉「眼睛」**,内核条目与输出都留着(`kill_command` 随时取回)。
|
|
379
|
-
**可逆 > 不可逆**。**「记住了」放宿主不放 webview**(放 webview 则面板一折叠即忘,刚收起又冒出来)
|
|
380
|
-
- ⚠️ **running 行刻意不给 `×`**:只有「终止」(真杀)。进程在跑必须始终可见——不能让它能被藏起来,
|
|
381
|
-
那正是本缺口最初的样子(「派了人出去办事却不知道他还在不在」)
|
|
382
|
-
- **单通道复用**:`background_kill` 加 `reason?: 'terminate' | 'dismiss'`(缺省 `terminate`
|
|
383
|
-
兼容旧 webview)⇒ **协议通道 107 → 107 不变**(治理阈值 130)。一个通道两个明确动作优于开第二条
|
|
384
|
-
- **踩坑并已修(真缺陷,非测试问题)**:dismiss 后把签名哨兵置 `''` ⇒ **最后一条被收起时过滤后
|
|
385
|
-
`items` 为空、签名也是空串** ⇒ 去重判成 no-op ⇒ **条根本收不起来**。改用 `null` 哨兵
|
|
386
|
-
(`_backgroundSignature: string | null`)。这是「去重守卫 + 空集合」交互的典型陷阱
|
|
387
|
-
- **踩坑并已修**:回滚变异时误插成两行 `a.on(...)` ⇒ 一次终态推两遍相同快照(签名去重在处理器
|
|
388
|
-
内部拦不住,那是两条独立调用)。已加**订阅幂等守卫**(同一事件只 `on` 一次)并用变异验证其有效
|
|
389
|
-
- **测试**:内核 +2(终态触发发射回调 / 未注入回调时不抛);宿主 +5(dismiss 只收视图不碰内核 /
|
|
390
|
-
记在宿主侧面板重建不复活 / 终态事件推快照且桩 `on` 真转发 / 订阅幂等 / `×` 载荷带 `dismiss`
|
|
391
|
-
且 running 行无 `×`)。测试**桩的 `on` 必须是真转发**(`vi.fn()` 空实现会让「事件名错配」测不出来);
|
|
392
|
-
**不暴露 `emit`**(真实 Agent 上是 `protected`,测试直调会绕过事件名检查 ⇒ 改用捕获的订阅处理器)
|
|
393
|
-
- **变异验证 4 组**:拆终态发射 → 出口用例红 / 拆宿主订阅 → 事件用例红 / 拆 dismiss 过滤 → 2 条红 /
|
|
394
|
-
注入重复订阅 → 幂等守卫红
|
|
395
|
-
|
|
396
|
-
### Added(内核 · 后台任务宿主出口 `listBackgroundTasks` / `killBackgroundTask` · CMD-1 阶段 2 缺口)
|
|
397
|
-
|
|
398
|
-
**缺口**:后台任务运行态对用户零可见、无 kill 入口——`BackgroundTaskRegistry` 的 `list()` / `kill()` 能力早已齐备,但 `src/index.ts` **零导出**,宿主拿不到数据通道(不是「没画 UI」,是「取不到数」)。
|
|
399
|
-
|
|
400
|
-
- **新增门面方法**(纯委托,零新逻辑):`agent.listBackgroundTasks(): readonly BackgroundTask[]`、`agent.killBackgroundTask(taskId): BackgroundTask | null`;委托链 = agent → loop → 注册表,**不复制任何判据**(复制即第二真理源)
|
|
401
|
-
- **只出方法不出类**:注册表是 **Agent 实例级**(单例会让 `kill_command` 杀掉别的会话起的进程),导出类 = 把实例化权交给宿主 = 破坏隔离不变量
|
|
402
|
-
- **投影不泄漏句柄**:返回对象的键只有 `taskId / command / startedAt / status / result?`,`killNow` / `peek` 已由 `projection()` 剥离(有守卫测试钉死)
|
|
403
|
-
- **新增类型导出**:`BackgroundTask` / `BackgroundTaskStatus`(只读投影类型;**后注**:`BackgroundTaskStatus` 旋经 `REL-3.1` 导出面收敛收回——它在 3.0.1 导出面上不存在、本开发周期内曾短暂挂面,现版本已不挂面,本条保留真实历史)
|
|
404
|
-
- **状态词表单点**:`BACKGROUND_TASK_STATUS_LABELS`(`Record` 穷尽键 = 新增状态忘补文案即**编译期红**,同 `COMPRESS_TARGET_LABELS` 定案)。**2026-10-04 自审补**:方案文档 §2.3 曾写「复用内核 `STATUS_LABELS`」——该标识符当时是模块私有、内核零导出,属**引用不存在导出的文档失真**(与旧台账 `inlinePlanBoard` 同型)⇒ 改为公开导出,宿主 UI 直接消费、**禁自建第二套**
|
|
405
|
-
- **测试**:loop 层 5 条(未装配不抛 / 运行态可见 / kill 返回终态 / 未知 id 返回 null / 不泄漏句柄)+ 变异验证 2 组有效。**变异副产品**:原 `kill` 后的二次判空是**冗余分支**(`get()` 对未知 id 同为 null,删早退行为完全等价)→ 按无僵尸分支纪律删除,不留不可测代码
|
|
406
|
-
- **方案文档**:`docs/方案-后台任务可见性与kill入口-20261004.md`(实施规格真源;宿主侧协议 + UI 见下方宿主区同批条目)
|
|
407
|
-
|
|
408
|
-
### ⚠️ Breaking(内核 · 确认载荷与 chunk/事件变体 · 已定档 4.0.0)
|
|
409
|
-
|
|
410
|
-
**升级即需改代码**(TS 集成方必读):
|
|
411
|
-
|
|
412
|
-
- `WriteConfirmationInfo`(`onWriteConfirmation` 载荷)新增**必填**字段 `hasDiff: boolean`——**编译期破坏**(自建该对象的集成方需补字段;只消费不构造的集成方不受影响)。语义 = 「本次确认卡是否有 diff 对比域」:写入场景恒 `true`,命令 / 代码 / 脚本执行三类恒 `false`。**判据归内核单点**(`confirmGate` 的 `diff !== undefined`),宿主不再用 `beforeContent`/`afterContent` 的 truthy 自猜——那属「措辞折叠型带伤」(非写入场景被归一为 `beforeContent: null`,truthy 与 `!== undefined` 判据都会把命令确认渲染成假的「写入前/写入后」对比)
|
|
413
|
-
- `AgentChunk` 新增变体 `{ type: 'background_report'; content: string }`(turn 终态对存活后台进程**脱管**后 emit,报告「已转后台常驻(未被终止)」;无存活进程则不产。语义随阶段 3 脱管定案修订,见上方 Breaking)。消费方 `for await` 的 switch/exhaustive 检查需处理新变体
|
|
414
|
-
- `ProcessEvent` 新增同名变体 `{ type: 'background_report'; seq; ts; payload: { content: string } }`(落盘重放可见,与 `plan_snapshot` 同型)
|
|
415
|
-
|
|
416
|
-
### Added(内核+宿主 · 命令行执行能力 `run_command` / `kill_command` · `CMD-1`,已定档 4.0.0)
|
|
417
|
-
|
|
418
|
-
**能力缺口**:此前执行 shell 命令须「`write_file` 写脚本 → `run_project_script` 执行 → `delete_file` 清理」三步,且 `.sh` 在 Windows 上静默空跑(退出码 0 但输出全空)。
|
|
419
|
-
|
|
420
|
-
- **工具层**:`run_command`(任意 shell 命令字符串 + `cwd` + `timeoutMs` + `background`;`diskWrite:'opaque'` 与一切写互斥)+ `kill_command`(按 `taskId` 终止并取回截至当时的输出;只能杀本会话自起任务,非任意 pid)。两者入 `DEFAULT_EXPOSED_TOOLS` 常驻开放
|
|
421
|
-
- **安全边界**:`SecurityGuard.classifyCommand` 三档裁决(deny 黑名单恒拦 / always-ask 恒确认 / normal)+ `confirmCommandRun`(**复用既有 `confirmGate`**,零新确认通道)。⚠️ **已知边界(如实登记)**:deny 是**命令字面量护栏**,凡执行内容由间接载体承载处(脚本文件 / `run_code` 内联代码)结构性失效——裁决面登记见 `src/security/confirmEntries.ts`,绕过成本 = 一次工具调用
|
|
422
|
-
- **后台执行**:`background: true` 显式发起(**不做超时自动转后台**,拒绝隐式状态切换)→ 立即返回 `taskId`,完成后经 step 边界气口以 system 消息回流(role 语义隔离,不占插话满员);`LOOP_CONSTANTS.MAX_PENDING_COMMAND_RESULTS` 限量注入(超量留队续投,不截半丢弃);turn 终态(done/interrupted/error)对存活进程**脱管**(不杀)并出常驻报告,完成回流**跨 turn 留存**(阶段 3 修订见上方 Breaking 区)
|
|
423
|
-
- **进程治理**:`skillScriptRunner.buildSpawnOptions` + `attachGovernance` 收为单点(同步/后台共用),Windows 走 `taskkill /T /F` 杀树、POSIX 走 `kill(-pgid)`;`SYNC_MAX_TIMEOUT_MS`(600s) / `BACKGROUND_MAX_TIMEOUT_MS`(1800s=30min) 双常量分治(30min 只钳制**显式传入**的 timeoutMs,缺省不传 = 不限时,见上方诚实边界),`normalizeTimeoutMs(timeoutMs, maxMs)` 参数化取上限(不给 SSOT 函数开 mode 分支)
|
|
424
|
-
- **诚实口径**:「被主动终止」不是「执行失败」——强杀态独立 `formatKilledCommandOutput`,不声称任何退出状态(防 `[COMMAND_ERROR] 退出码 -1` 谎报);命令结果定长真源上移到格式化层(脚本/命令/后台回流三面共用,杜绝第二消费面看不到上限)
|
|
425
|
-
- **宿主**:工具中文名两键 + 行动叙述(叙述命令原文 + 后台标记)+ 设置面板「执行二次确认」补 `run_command` 并显式声明 git 写操作/发布不受开关影响(ALWAYS_ASK 恒询问);后台收尾报告上屏(「后台任务收尾」小节,实时/重放同源)
|
|
426
|
-
- **未做(如实登记)**:命令前缀 allow 白名单(阶段 2)、`.ps1` 运行时档(后台任务运行态列表与用户侧 kill 入口阶段 1 未做,已由同日阶段 2/3 补齐,见下方宿主区 Added 与阶段 3 Fixed 条目)
|
|
427
|
-
|
|
428
|
-
### Added(内核+宿主 · 环境能力宣告 · `CMD-2`,已定档 4.0.0)
|
|
429
|
-
|
|
430
|
-
**缺口**:`run_code` 描述曾写「如 python、node、shell」而宿主执行器只支持 JS(对模型说了假话);且模型对运行环境一无所知。
|
|
431
|
-
|
|
432
|
-
- **消灭谎言(声明列举)**:`ICodeExecutionProvider` 增**可选** `supportedLanguages?: readonly string[]`;`RUN_CODE_TOOL` 改工厂 `buildRunCodeTool(supportedLanguages?)`——声明时按实际生成语言清单,未声明退化为去承诺文案(零感知向后兼容)。工具描述与「暂不支持语言」回知文案**同源自宿主声明**,杜绝双写漂移
|
|
433
|
-
- **环境事实注入**:新增 `IEnvironmentProvider`(**同步** `getEnvironment(): HostEnvironmentInfo | null`)+ `HostEnvironmentInfo`(`os`/`shell`/`runtimes` 全可选),公开导出;`buildEnvironmentContextBlock` 纯函数格式化为 system prompt「## 运行环境」段(插作品投影后、时间戳前;全空字段不产生空壳标题段)。**零解释转发**——只做字段→文本机械映射,不加行为引导语
|
|
434
|
-
- ⚠️ **`shell` 字段语义 = 本会话执行器实际派发的 shell**(不是集成终端/登录 shell):内核 `resolveShellCommand` 恒定映射 win32 → `cmd /c`、其余 → `sh -c`,不读环境变量。两侧互为镜像,改一侧必须同批改另一侧(宿主测试从内核源码文本提取真源比对,防单边漂移)
|
|
435
|
-
- **刻意不做**:内核内置探测(派生判定律:环境事实不得升级为内核判据)、执行期自动语言切换(抢模型决策权)、cwd/git 分支注入(阶段 2 观察)
|
|
436
|
-
|
|
437
|
-
### Fixed(内核+宿主 · `compress_context` 单轮长 turn 压缩缺口 + 崩溃修复 · `CTX-WIN-2`,已定档 4.0.0)
|
|
438
|
-
|
|
439
|
-
**问题(诊断实锤,非推断)**:长单轮任务(一个提问跑几十个 step)把上下文顶满时,`compress_context` 结构性无可压目标——台账原描述「只能靠换区间重读硬扛」,实测**比这更严重**:
|
|
440
|
-
|
|
441
|
-
- `target=earliest_round` 在单轮 turn 内**恒返回 null**:锚点是「第一个 user vs 最后一个 user」,而单轮内只有一个 user(当前触发输入)⇒ 必然重合
|
|
442
|
-
- `target=largest_tool_result` **用了就崩**:原实现只压单条 tool 消息,其所属 `assistant.toolCalls` 留在上下文 ⇒ 发送边界守卫 `unpairedAssistantCall` fail-fast 抛错,**整个 turn 中断**
|
|
443
|
-
|
|
444
|
-
**根因**:不是「压缩能力不足」,而是**锚点粒度选错**——单轮内的历史是 **step 序列**,而既有定位器的锚点是 **user 消息**。
|
|
445
|
-
|
|
446
|
-
- **新增 `target=earliest_steps`**(step 粒度,长任务首选):step 边界 = 一条 `assistant` 消息 → 下一条 `assistant` 之前;「已回齐」判据 = 区间内每个 `assistant.toolCalls.id` 都有配对 tool 消息(未回齐不压,避免丢未完成语义)
|
|
447
|
-
- **`largest_tool_result` 改整段替换**:该 tool 消息 + 所属 assistant 消息同进同出 ⇒ 配对恒成立,修掉崩溃
|
|
448
|
-
- **target 枚举单点化并公开导出**:`CompressTarget` / `COMPRESS_TARGETS` / `COMPRESS_TARGET_LABELS`。标签表用 `Record<CompressTarget, string>` **穷尽键** ⇒ 日后加 target 忘改宿主文案 = **编译期红闸**(原宿主三元 `target === 'earliest_round' ? A : B` 会把新值静默显示成「最大工具结果摘要」= 对用户说谎)
|
|
449
|
-
- 工具描述补 target 选型指引;「无可压目标」的回传串列出合法 target 值(此前只说「目标不存在」,模型无法自纠)
|
|
450
|
-
|
|
451
|
-
**兼容性**:`target` 仍为可选参数,缺省/非法值仍降级 `earliest_round`——既有集成方零改动。新增导出为纯增量。
|
|
452
|
-
|
|
453
|
-
### Changed(内核 · 待注入插话上限裁决收口内核 · `KERNEL-QUEUE-LIMIT-1`,已定档 4.0.0)
|
|
454
|
-
|
|
455
|
-
**债务清偿**:INPUT-LIMIT-1 落地时插话条数上限只做在宿主两层(webview 预检 + extension 闸门),内核 `loop.interruptQueue` 本体 push 前无上限——第三方集成方绕过宿主直调 `agent.interject()` 仍可塞爆队列(队列是内核资源不变量,该内核自己堵,不能指望每个集成方自带限额)。
|
|
456
|
-
|
|
457
|
-
- **上限裁决单点收口内核**:`LOOP_CONSTANTS` 新增 `MAX_PENDING_INTERJECTIONS = 5`(值真源);`loop.interject` 返回 `boolean`——达上限**整条拒收**返回 false 不入队(插话是原子思路不截半条);`agent.interject` 改**先入队后持久化**(顺序即语义:拒收时零入队、零落盘,防「队列没进、落盘却写」数据不一致)
|
|
458
|
-
- **宿主消费真源**:extension 闸门改消费 `interject()` 返回值(快照预检自写判据退役,宿主零裁决逻辑);webview 预检仍用 `shared/constants.ts` 镜像常量(webview 无法 import 内核包),同值关系由宿主守卫测试锁定(漂移即红);pause 条目不受上限管辖(内部控制语义非用户输入洪流)
|
|
459
|
-
- **测试**:内核 loop 上限用例(满员拒收不入队 / 删一条可再入 / pause 不受限)+ 变异闭环(判据 off-by-one 精准红);`constants.test` 键数守卫 24→25 同步;agent 层 +4 用例(未初始化断言 / 受理入队返回 true / 满员拒收返回 false 队列不增 / 删一腾位再入——返回值透传与队列状态链路贯通;落盘内容无公开读口,闭环节点持久化由 messageHistory.test 既有覆盖);宿主 chatPanelInput 11 用例(桩默认受理态 / 满员拒收不上屏 / 防误伤上屏 / 跨包同值守卫)
|
|
460
|
-
- **版本**:内核语义变更(接口返回值 void→boolean + 新增常量),随已定档的 4.0.0 一并发布,不单独发版
|
|
461
|
-
|
|
462
|
-
### Fixed(宿主 · 轮次摘要失败可见化 + 摘要事件 handler 泄漏 · `MEM-1`)
|
|
463
|
-
|
|
464
|
-
**现象**:complete 轮缺少 round-summary 摘要记忆(记忆库无条目),而**用户与排查者都无从得知原因**。
|
|
465
|
-
|
|
466
|
-
**前提订正(原文「无任何可观测信号」只对一半)**:内核 `orchestrator.runSummary` **早已**在三条路径上
|
|
467
|
-
`emit('roundSummaryGenerated', { roundId, success })` —— 异步 reject / 同步 catch 均发 `success: false`,
|
|
468
|
-
「摘要关闭」发 `success: true`。**信号在事件层一直存在**;断点在**宿主消费点** ——
|
|
469
|
-
`chatPanel` 的 `onSummary` 只拿 `roundId` 解锁 UI 定时器,把 `success` **整个丢弃**。
|
|
470
|
-
|
|
471
|
-
- **观测出口接线**:`onSummary` 增 `if (!info.success)` → `post({ type:'notice', level:'error' })`,
|
|
472
|
-
走本文件既有的**错误级 `notice` 单通道**(`protocol.ts` 的 `level:'info'|'error'` 已有承载)——
|
|
473
|
-
**零协议变更、零内核改动、零判据改动**
|
|
474
|
-
- **⚠️ 对抗式审查推翻「记日志、不弹 UI」的原建议**:静默失败正是本缺陷的成因;低频(仅真失败时出现)
|
|
475
|
-
的错误提示条才真正闭合可观测链(用户可自证「这轮没沉淀」),仅日志留痕等于把问题继续藏着
|
|
476
|
-
- **顺带修同处第二个独立缺陷**:`agent.on('roundSummaryGenerated', …)` **非 `.once`**,此前仅
|
|
477
|
-
`setTimeout` 分支 `off`、**事件触发分支不解绑** ⇒ 每轮正常收场遗留一个 handler 累积;已补**对称解绑**
|
|
478
|
-
- **测试**:新增 `chatPanelSummaryFailure.test.ts` 4 用例(失败 → 错误 notice / 成功 → 不误报 /
|
|
479
|
-
notice 不阻断 UI 解锁 / 连跑三轮 handler 零残留)+ **变异双闸门已实证红→绿**(删 `if` → ①红;
|
|
480
|
-
删 `off` → ④红且报「3 handler 累积」)
|
|
481
|
-
- **⏳ 真机复验**:构造摘要失败(如摘要 LLM 返无效 JSON)时错误提示条应可见,且连跑多轮无 handler 累积
|
|
482
|
-
|
|
483
|
-
### Added(内核 · 会话离场自动归档链路接通 + 归档成功事件 · `HIST-INFO-1`,已定档 4.0.0)
|
|
484
|
-
|
|
485
|
-
**根因(注释谎报实锤)**:头注释与工具路标声称「会话切换前自动归档」,但 `switchToSession` 的归档
|
|
486
|
-
链路**从未接线**——所有会话的 `summary`/`keyTopics` 恒空,历史列表悬停 tooltip 假显宿主容器的
|
|
487
|
-
「当前会话」(真机 HIST-INFO-1 验收抓出)。三类自动触发(**切走 / 分叉离场 / 暂停超时**)统一由
|
|
488
|
-
Agent 归档监听器接通,fire-and-forget 不阻塞切换主流程。
|
|
489
|
-
|
|
490
|
-
**新增事件(2)**:
|
|
491
|
-
|
|
492
|
-
- `sessionSwitched`:旧会话切走时广播(载荷指向被切走的旧会话)。**内核自消费事件**——agent 归档
|
|
493
|
-
监听器收;宿主零消费 = 刻意设计(宿主是切换发起方,无增量信息),protocolGuard V-2 已登记
|
|
494
|
-
`KERNEL_SELF_CONSUMED_EVENTS` 豁免(⚠ 分表触发器:内核自消费事件增多时拆独立内部事件通道)。
|
|
495
|
-
- `sessionArchived`:归档写入成功(`updatedFields` 非空才发)发射,与 `archiveFailed` 对称,
|
|
496
|
-
手动触发同样经 ArchiveCoordinator 发射;宿主据此重拉会话列表。
|
|
497
|
-
|
|
498
|
-
**防重**:`SessionArchiver` 新增 `skipIfUnchanged`(仅自动触发透传):以上次**实际完成归档**的
|
|
499
|
-
消息数快照为判据,消息数未变即跳过 LLM 调用。快照为进程内内存态(重启清零,首次多归档一次可接受);
|
|
500
|
-
**写入成功才记账**——LLM 判无价值/写入失败不记,下次自动触发保守重试。手动触发无条件重新归档。
|
|
501
|
-
|
|
502
|
-
**注释清算(措辞折叠同族,5 处一次改齐)**:sessionArchiver 头注释 / archiveCoordinator 注释 /
|
|
503
|
-
builtinToolHandlers 路标 / agent.archiveSession JSDoc / ArchiveMode 注释中「切换前自动归档」
|
|
504
|
-
谎报全部订正为三类触发的真实枚举。
|
|
505
|
-
|
|
506
|
-
> 以下条目为 **4.0.0 定档(2026-10-08)之后、发布之前**落地的内核变更(此前沿提交散落、未在本文件归集),随 4.0.0 一并发布。
|
|
507
|
-
|
|
508
|
-
### Added(内核 · ask 超时后要求 LLM 代选推荐方案并声明 · `c2477907`)
|
|
509
|
-
|
|
510
|
-
- `ASK_TIMEOUT_NOTICE` 常量改写:ask 超时自动继续时,除陈述事实外,要求模型**从它自己给出的选项里
|
|
511
|
-
选一项推荐方案继续推进,并在答复中说明这是代选的及理由**;不可逆操作仍需向用户确认。
|
|
512
|
-
- **不改超时语义**:`ASK_TIMEOUT_MS`(120s 自动继续)与 `CONFIRM_TIMEOUT_MS`(30min 自动拒绝)的分级
|
|
513
|
-
刻意不同,本笔只补可观测性——不动时长、不动 fail-open/fail-closed 分级。
|
|
514
|
-
- 病灶(真机 round-1791449684099 实证):旧文案只说「已自动继续」⇒ 模型据此**暗中**替用户决策
|
|
515
|
-
(写完第 4 章后直接写死「下一步默认开工第 5 章」),用户回来只看到既定事实、无从否决。
|
|
516
|
-
- 一个字符串服务两个语境(渲染气泡给用户看 + 作 user 消息进模型上下文)⇒ 措辞两端都必须成立;
|
|
517
|
-
宿主 `chatPanel` 同名常量为镜像,两侧注释互相要求同值(防运行时 / 重放文案分叉)。
|
|
518
|
-
|
|
519
|
-
### Fixed(内核 · 收场取轮翻转 store-first:stale pending 快照不再覆盖已落盘事件 · `01388b1a`)
|
|
520
|
-
|
|
521
|
-
- `MessageHistory` 两处取轮顺序翻转:优先 `RoundStore`(SSOT,含宿主 step 检查点已落盘的
|
|
522
|
-
`processEvents`),pending 缓存降为 fallback。旧写法 pending 优先会用**无 processEvents 的
|
|
523
|
-
stale 快照覆盖 store** ⇒ 前段事件 / metrics 被静默清零、merge 结构性不可达(`METRICS-XFLOW-1`)。
|
|
524
|
-
- 订正 `appendInterrupted` 注释谎报(pending 优先时 `processEvents` 无从保留)。
|
|
525
|
-
|
|
526
|
-
### Fixed(内核 · 整读记账按请求起点 + 台账替身回显改为请求区间原文 · `912c1e5b` / `5cd77fdb`)
|
|
527
|
-
|
|
528
|
-
- **整读记账改按请求起点**:`loop` 依 handler 不变量(无脚注 = 从请求 offset 读到末尾)记
|
|
529
|
-
`coverStart=offset`、`totalLines=offset+正文行数-1`(`offset≤1` 与旧值等价)。旧写法把
|
|
530
|
-
`offset=54` 的续读(尾段无脚注)无条件记成 1–95 ⇒ ① `offset=1` 早段读(1–53 从未覆盖)被**假拦**;
|
|
531
|
-
② 回显按错误 `coverStart` 平移,把 L54+ 内容标成「第 1–53 行 / 共 95 行」——**行号与内容错位的
|
|
532
|
-
假事实**误导模型(真机 round-1791507775404 实锤)。
|
|
533
|
-
- 新增 `READ_FILE_NOTICE_PREFIX`(生成侧 / 识别侧同引):越界提示串带该前缀且**不进覆盖度台账**
|
|
534
|
-
(原会被记成覆盖,二次越界读命中归一判据被假拦)。
|
|
535
|
-
- 台账替身回显改为**请求区间原文**:防重拦截不再把模型逼进「拿不回整份视角」的死路(防绕道复发)。
|
|
536
|
-
|
|
537
|
-
### Fixed(内核 · denied 通道 PERMISSION_DENIED 前缀收口到单一构造点 · `0c7b6247`)
|
|
538
|
-
|
|
539
|
-
- `toolRunner` 的 denied 通道此前手写 `[ERR:TOOL:PERMISSION_DENIED]` 字面量,与 `builtinToolHandlers`
|
|
540
|
-
走 `failedOutcomeWithCode()` 的枚举派生构成第二真源漂移风险;改走
|
|
541
|
-
`failedOutcomeWithCode(ToolErrorCode.PERMISSION_DENIED, reason).text`,发射字符串逐字符不变,
|
|
542
|
-
denied 的机器维度 `reason` 保留。
|
|
543
|
-
- `READONLY_DENIED` 经 tsc 实锤**并非**枚举成员(仅为 `toolFailurePrefixGuard` 独立登记标签)
|
|
544
|
-
⇒ 保持手写字面量并补注释,避免误改成不存在的符号。
|
|
545
|
-
- 变异验证:`PERMISSION_DENIED → UNKNOWN` 使新增断言转红后还原(证断言非空洞)。
|
|
546
|
-
|
|
547
|
-
### Added(内核 · 发版前 Go/No-Go 中优先项清偿:文法盲区登记 + Reflection 设计口径显式声明 + 死分支不变式守卫 + 决策 ADR 补录 + §十六 限定句修正 · M3/M4/M6/M8/M10)
|
|
548
|
-
|
|
549
|
-
- **`toolFailurePrefixGuard` 新增文法盲区对账**(`GRAMMAR_BLIND_TAGS`):首字符即 `[` 但逃出
|
|
550
|
-
「大写蛇形」与「插值前置」两种文法的标记(上下文注入分节头 / 工具结果正文软提示 / 提取器
|
|
551
|
-
已知边界产物)原先对扫描面与排除清单**双双不可见**(双重静默),现按文件登记、全库双向钉死
|
|
552
|
-
——新增未登记盲区即红,登记项消失(如升级文法)即僵尸红。变异验证:删登记 / 生产新增盲区
|
|
553
|
-
标记均转红后还原。
|
|
554
|
-
- **api-ref §十五 显式声明「执行类失败不进自动 Reflection」(设计口径,非回归)**:
|
|
555
|
-
`run_command` / `run_code` / `run_project_script` / `run_skill_script` 四条执行链路失败返回
|
|
556
|
-
不带 `errorCode` 的失败结果,不满足 retryable 触发条件 ⇒ AgentLoop 不注入
|
|
557
|
-
`[REFLECTION_HINT]`;结局事实由返回文本承载,LLM 自行决定是否重试(错误码全集见 §十四)。
|
|
558
|
-
- **`strategyKeys` 死分支不变式守卫**:`describeStrategyKeys` 的 else 分支(check 无 range
|
|
559
|
-
且无专属分支的数值键)当前不可达——注释从「防御分支」改为「已登记的未来路径,由不变式测试
|
|
560
|
-
守卫」。新增全量不变式测试:遍历 `STRATEGY_KEY_RULES` 所有 check 键,断言「无专属分支的
|
|
561
|
-
check 键必带 range」。变异验证:删 `temperature` 的 `range` 后测试转红(精确点名该键),还原后全绿。
|
|
562
|
-
- **决策 ADR 补录**(`ADR-038` 工具结果三值契约 / `ADR-039` 公共导出面挂面判据):4.0.0 两条
|
|
563
|
-
Breaking 的决策 rationale 原只在不随包发布的过程稿里,现沉淀为仓库内定案锚;对外 rationale
|
|
564
|
-
入口不变(本文件上方 Breaking 条)。零代码、零消费面变更。
|
|
565
|
-
- **api-ref §十六 限定句修正**:⚠️ 注主句由全称「可具名导入的公开面以本节清单为准」收窄为
|
|
566
|
-
「正文表格里的类型名以本节清单为准(本节非全集,未列出的导出以 `src/index.ts` 为准)」——
|
|
567
|
-
原全称与同节首注「清单外导出以 index.ts 为准」当面矛盾(措辞折叠同族)。语义未变,只消除
|
|
568
|
-
误读面:§十六 本就是精选子集而非全集。
|
|
569
|
-
|
|
570
|
-
### Changed(示例包 · 共鸣小说家「纲是骨架、章是装箱」:正文落地前禁止预排章节)
|
|
571
|
-
|
|
572
|
-
- **规范本体**(`rules.md`):任何纲(大纲/细纲/场景清单)只限定故事骨架——情节序列、事件、
|
|
573
|
-
情绪走向;正文落地前不写"第N章"、不做逐章切分,章是成文装箱时才产生的弹性容器(核心框架间
|
|
574
|
-
随时可插支线/番外而章号不错位)。成文章号回填(时间线/伏笔台账)与逐章写作纪律(章末钩子/
|
|
575
|
-
单章篇幅)豁免。
|
|
576
|
-
- **消费面同步**:persona 阶段5 三幕骨架定情节节点(不预排章节)、outline-expand ③ 章纲→细纲
|
|
577
|
-
(事件序列,展开纪律 + 校验清单双判据)、foreshadow / story-bible 伏笔表头章节→事件/场景、
|
|
578
|
-
emotion-wave 落点列章节→事件、init 模板 `T_BIBLE_4` / `T_OUTLINE` 同构(顺手修正五级展开
|
|
579
|
-
描述与真源的既有漂移)。
|
|
580
|
-
- **验证**:role-pack 258 passed;prettier / terminology(71+82 载体)/ docs:links(45 随包 md
|
|
581
|
-
0 死链)/ lint 全绿;规划态章节限定词(「章纲」等)全包残留扫描 0。
|
|
582
|
-
|
|
583
|
-
## [Unreleased] · 宿主(随做随用 · 不占内核版本号)
|
|
584
|
-
|
|
585
|
-
> **本区归属**:仅**宿主**(`hosts/memora-vscode`)变更——不在内核发布包 `files` 白名单内、无独立 marketplace 节奏 ⇒ 不编内核版本号,随做随用,攒批随下次 `vsce package` 定版(`vscode@x.y.z` tag,ADR-033)。
|
|
586
|
-
|
|
587
|
-
### Fixed(宿主 · 多流续跑 metrics 同轮合并:前段指标不再被静默清零 · 零 schema 变更)
|
|
588
|
-
|
|
589
|
-
**真机实锤**:一次 turn 分多段流完成(软暂停续跑 / ask 回答后续跑)时,每段流尾各自 emit 一条
|
|
590
|
-
段级 metrics;`mergeProcessEvents` 旧实现把 prior 的 metrics **恒剔除** → 前段全部指标丢失,
|
|
591
|
-
回合终态只剩末段(前段 7 次工具失败被静默清零成 0,「不算成功收尾」诚实信号随之失真)。
|
|
592
|
-
|
|
593
|
-
- **同轮合并**(新私有助手 `mergeMetricsPayload`):`durationMs` / `tokenIn` / `tokenOut` /
|
|
594
|
-
`toolFailureCount` 求和;`success` 取末段(语义是「这段流程跑完没有」,终局收尾以最后一段
|
|
595
|
-
为准);三个可选诚实信号任一段携带即求和(缺段按 0)、两段都缺保持缺省(不伪造信号面)。
|
|
596
|
-
- **检查点路径保留**:incoming 无 metrics(step 检查点常态)时 prior metrics 原样保留待流尾
|
|
597
|
-
合并,防双计与丢失并存;emit 点与存储 schema 零变更。
|
|
598
|
-
- 测试:合并求和 + success 取末段 / 可选字段三态 / 检查点保留 3 用例;变异验证(恒剔回退 →
|
|
599
|
-
检查点用例红、合并分支拆除 → 求和双用例红 → 恢复全绿)已做;宿主全量 57 文件回归绿。
|
|
600
|
-
|
|
601
|
-
### Fixed(宿主 · 队伍对账语义变更:清理写回 → 只检测标注,删除权交还用户 · 含内核消费端同口径收口)
|
|
602
|
-
|
|
603
|
-
**真机实锤**:2026-10-07 构建中窗口(compile 先 `rmSync dist` 后重建)启动扩展,包池扫描为 0;启动对账把「扫描失败」当成「全部卸载」,用户所有队伍被静默物理删除写回(仅 console.warn,无 UI 通知,不可恢复)。
|
|
604
|
-
|
|
605
|
-
- **只检测不删除**:`reconcileTeams` / `reconcileRolePackTeams`(清理写回)退役 → `inspectTeamsHealth` / `inspectRolePackTeams`(只读派生,零写回零内核调用);启动接线点随之退役,唯一接线点 = `loadRoles` 读期检测。受损队伍保留在存储(SSOT:存储即真源,检测是视图)。
|
|
606
|
-
- **空池护栏**:包池为空 = 扫描失败窗口,跳过检测防误报(把瞬时状态当永久事实正是伤例根因)。
|
|
607
|
-
- **角色页持久标注**:遗留队伍独立区块(组长已卸载的组无卡片可挂)+「清理」按钮(复用 `roles_team_delete`);缺员组员名后缀「(已卸载)」,经组队弹窗编辑保存即修复;参会计数与内核先截断后过滤口径一致(不虚报)。
|
|
608
|
-
- **内核同口径收口**:`effectiveMembers`(截断 + 缺员过滤,单一实现)收口 `activeTeamMembers` / `getTeam`——名单输出 = 实际可参会者,会议任务项不为幽灵组员建发言项;存储原样不裁切。守卫:内核 3 用例(缺员过滤 / 存储原样 / 截断不回补)+ 宿主检测 8 用例 + 角色页渲染 3 用例。
|
|
609
|
-
- **语义变更记录**:ADR-028 收敛补记二(2026-10-08)。
|
|
610
|
-
|
|
611
|
-
### Added(宿主 · 角色包「刷新」按钮:用户角色包目录改动免重启生效)
|
|
612
|
-
|
|
613
|
-
- 角色页头部新增刷新按钮(对齐技能列表刷新形态):webview 发 `roles_refresh` → extension 调内核
|
|
614
|
-
`resyncUserPacks(userRolePacksDir)` 对账内存池 → notice 反馈净差结果(新增/更新/移除/兜底回退,
|
|
615
|
-
零变化明示「无变化」)+ `roles_loaded` 下发最新列表。
|
|
616
|
-
- **测试**:webview 按钮绑定(postMessage 契约)+ extension handler(净差文案 / 同名重注入报
|
|
617
|
-
「更新」不谎报 / 零变化明示 / 悬空回退提示 / 未就绪拒绝)共 6 用例锁定。
|
|
618
|
-
|
|
619
|
-
### Fixed(宿主 · 历史条目悬停假显「当前会话」+ 归档后条目不刷新 · `HIST-INFO-1`)
|
|
620
|
-
|
|
621
|
-
- **title 泄漏**:会话标题条容器级 `title="当前会话"` 被所有无 title 的后代继承——历史下拉任何条目
|
|
622
|
-
悬停都显示「当前会话」。title 移至内层 `#sessionTitleText`;条目无摘要时诚实无 tooltip。
|
|
623
|
-
骨架 title 防泄漏守卫测试锁定(测试夹具同步)。
|
|
624
|
-
- **归档完成无信号**:切走时归档异步执行,列表快照永远拿不到后到的 summary/keyTopics(悬停恒空)。
|
|
625
|
-
订阅内核 `sessionArchived` 重拉会话列表,条目摘要/keyTopics 即时更新。
|
|
626
|
-
- **守卫反噬两处**:iconLanguage 守卫头注释声明「注释里的符号不管」但只剥 JS 注释、未剥 HTML 注释
|
|
627
|
-
(补 `<!-- -->` 跨行剥离状态机,对齐自身声明;HTML 注释被浏览器解析为不可见注释节点,剥离不藏
|
|
628
|
-
真 offender);protocolGuard V-2 为内核自消费事件(`sessionSwitched`)增设显式豁免清单,
|
|
629
|
-
防造假订阅(订阅无真实语义 = 假账)。
|
|
630
|
-
|
|
631
|
-
### Fixed(宿主 · 异常终态轮缺「复制/分叉/删除 + 时间戳」底部栏 · settleRoundFooter 收口)
|
|
632
|
-
|
|
633
|
-
**真机实锤**:生成中点停止(尤其首 chunk 前的思考/工具相位),中断轮只剩停止行——无复制整链/分叉/删除/时间戳底部栏;重启渲染(重放)则正常显示。
|
|
634
|
-
|
|
635
|
-
- **根因**:容器 footer 显形由 `finalizeStreaming` 顺带移除 is-pending,前提 = 正文块已入容器——早相位中断时骨架未归位,`closest('.round-group')` 命中 null,显形信号静默丢失;done 恒在正文定稿后,故正常轮不受影响。附带伤:运行时建 footer 时首段 `dataset.ts` 恒空 → 时间戳元素从未创建
|
|
636
|
-
- **修法 = 显形真源回归终态事实**:新增 `settleRoundFooter(roundId, hostEl)` 单点收口(锚 = done/interrupted 终态消息携带的 roundId,不依赖 DOM 连通性):容器已建 → 移 is-pending + 时间戳补建;未建(早相位中断)→ hostEl 作首段建容器(与重放 `renderInterruptedRound` 同构);roundId 缺失诚实降级不建栏。`finalizeStreaming` 只保留段级 footer 职责,容器显形不再双写
|
|
637
|
-
- **复制源同源化**:中断 = 半截正文作废,rawText 覆盖为过程叙述(narrate)拼接——抽 `narrateChainText` 单点与重放共用(旧注释「运行时同源同形」只对「不显示正文」成立、rawText 拼接运行时缺失,属措辞折叠订正)
|
|
638
|
-
- error 不接入:error→done 两连发是既定架构(error 为末条属登记过的可接受残留),不扩面
|
|
639
|
-
- **测试**:`chatViewInterruptedFooter` 三相位用例(正文流中断/早相位中断/done 回归)+ 变异 2 组逐组精确转红(删 settle 调用 → 两中断用例红;删 narrate rawText → 复制源断言红)
|
|
640
|
-
|
|
641
|
-
### Fixed(宿主 · 插话丢弃信号「信号帧 → 快照帧」成对契约三路径补齐)
|
|
642
|
-
|
|
643
|
-
**变异验证暴露**:修复停止路径补 `syncPendingQueue` 时,「全部清空」存量用例红——`clear_pending_queue` 路径在「宿主从未投影过队列」场景(如 resume 恢复检查点带队列后 webview 重建)发信号但无成对快照帧。
|
|
644
|
-
|
|
645
|
-
- `handleStop` paused 分支补 `syncPendingQueue()`(三条丢弃路径中唯一漏跟契约的一条)
|
|
646
|
-
- **根因**:`_lastPendingQueueLen` 初始值 `0` 把「从未投影过」与「已投影为空」折叠成同一值——清空后长度未变被守卫误拦。改 `undefined`(从未投影 → 首次 sync 恒推),单点修正三条路径同时受益
|
|
647
|
-
- **测试**:停止/清空两用例补「信号先于新快照 turn_update」FIFO 时序断言(与删除单条路径同款);变异 2 组逐组转红(删停止路径 sync → 停止用例红;恢复折叠 0 → 清空用例红)
|
|
648
|
-
|
|
649
|
-
### Fixed(宿主 · 消息区自动吸底脆弱——MutationObserver 收口「高度变更不派发 scroll 事件」整类缺口)
|
|
650
|
-
|
|
651
|
-
**真机实锤(用户反馈)**:点开思考折叠块后拉到底部不吸底;部分工具运行期也不吸底——且「可能还有其他情况」。
|
|
652
|
-
|
|
653
|
-
- **根因**:吸底标记 `stickyMap` 仅由 `scroll` 事件经 `trackScroll` 刷新;展开/收起 `<details>`(思考块、工具行)、工具流式增删、长气泡展开、中断轮重建等**高度变更不派发 scroll 事件**却改写「是否真在底部」真值 → 标记与实际位置脱节(可双向错)。原注释「吸底判定在 DOM 变更前记录避开 tall-message 陷阱」只覆盖「新增内容前先记录状态」一侧,漏了「高度变更不刷新状态」一侧
|
|
654
|
-
- **修法(SSOT 收口)**:`helpers/scrollToBottom.ts` 新增 `followIfPinned(container)`——只读**既有**吸底意图(由 trackScroll 在用户滚动时记录、默认吸底),吸底则 rAF 滚到底、返回意图供「一键到底」按钮显隐;webview 在消息区挂 rAF 去抖 `MutationObserver`(`childList + characterData + attributes:['open'|'class'|'style'|'hidden']` subtree)delegate 到 `followIfPinned`。逻辑全收口于 helper,webview 只接线(不复制吸底逻辑、不碰 DOM 模板、不新增长度常量)。闭合整类而非两个症状
|
|
655
|
-
- **测试**:`scrollToBottom.test.ts` 2 条(jsdom 无布局,Object.defineProperty 注入几何);变异 2 组转红(删 `if (sticky)` 分支 → 吸底用例 scrollTop 断言红;删 `return sticky` → 非吸底用例返回值断言红)
|
|
656
|
-
|
|
657
|
-
### Fixed(宿主 · 渲染异常用户侧静默——onMessage 兜底补非阻断红条 · 观察点③)
|
|
658
|
-
|
|
659
|
-
**缺口(上一轮审计坐实)**:`onMessage` catch 仅 `console.error`,用户侧零呈现 → 渲染抛异常时看到「冻住/半成品 UI + 无报错」的可见性黑洞。
|
|
660
|
-
|
|
661
|
-
- **修法**:catch 内补 `showActivity('error', '界面渲染异常,详情见开发者控制台')` 非阻断红条,与 `console.error` 互补(根因定位不掩盖);`showActivity` 为既有活动条通道(P0 错误优先)
|
|
662
|
-
- **测试**:`chatViewRenderErrorBanner.test.ts` 1 条(dispatch 一条缺 `event` 字段的 `process_event` → `ev.type` 抛真实 TypeError 被兜 → 活动条 `data-level==='error'`);变异 1 组转红(删 showActivity 调用 → 断言红)
|
|
663
|
-
|
|
664
|
-
### Changed(宿主 · 终态 footer 显形与 commitTurnTs 前置防御性收口为单操作)
|
|
665
|
-
|
|
666
|
-
- **复核订正(2026-10-05)**:上一轮将「settleRoundFooter 顺序契约」诊断成「时间戳补建依赖 commitTurnTs 前置」——**实测不成立**:footer 时间戳元素由流式期 `ensureRoundGroupFooter` 按首段 `dataset.ts` 直接生成,`commitTurnTs` 缺位时三相位用例时间戳仍齐全。故该组合**不修复已复现的 bug**
|
|
667
|
-
- **保留价值(防御性)**:`settleRoundWithFooter(roundId, hostEl)` 把 `commitTurnTs`(删除按钮 ts 锚,`ensureRoundGroupFooter` 内 `deleteBtn.disabled = !firstSeg?.dataset.ts`)与 footer 显形收口为单操作,对任意「终态」路径保证 commitTurnTs 随 footer 显形恒执行,消除调用方需记的隐式顺序,防未来某终态路径未在建栏前回填 ds 致删除按钮恒禁用。属防御性收口,注释已对齐真源
|
|
668
|
-
|
|
669
|
-
### Added(宿主 · 后台任务可见性与 kill 入口 · CMD-1 阶段 2 · 协议 + 接线)
|
|
670
|
-
|
|
671
|
-
**缺口**:后台任务运行态对用户零可见、无 kill 入口(内核能力齐备但零导出,宿主取不到数——详见内核区同批条目)。
|
|
672
|
-
|
|
673
|
-
- **协议 +2 通道**(105 → 107,远低于 130 治理阈值):下行 `background_tasks`(快照)、上行 `background_kill`(taskId)
|
|
674
|
-
- **投影约束**:`BackgroundTaskView = Pick<BackgroundTask, 'taskId'|'command'|'status'> & { statusLabel }`——改内核字段名即编译报错,禁另立第二套字段;**刻意不含 `result`**(命令输出归模型消费,不搬进 UI 通道)。`statusLabel` 由 extension 侧读内核 `BACKGROUND_TASK_STATUS_LABELS` 填充后下发(webview 只做 type import,值导入内核会把整包打进 bundle)
|
|
675
|
-
- **刀 3 · webview UI**:StatusDock **第四条**(`DOCK_PRIORITY` += `background: 0`,优先级垫底 ⇒ 不顶掉 activity 主状态条;轮次收尾后 activity 归位、后台任务成为唯一活跃条时自动升主位,「终止」按钮恰在最需要它的时刻直接可见)。行 = 命令原文(过长截断 + `title` 全文)+ 状态标签 + 「终止」按钮(**仅 `running` 行有**,终态行无按钮——已结束再点即无反应 = 僵尸交互)。终止按钮**只 postMessage 回宿主**,杀进程不自实现(执行只能落 host)
|
|
676
|
-
- **UI 形态实施修订(相对方案文档 §2.3 原定案)**:初稿定「新增『后台 N』chip」,实施读穿 `resolveDock()` 后否决——既有 `+N` chip / `status-dock__panel` 已完备,再造第二个 chip = 两套 chip、两套展开态、两套显隐裁决,纯负收益。代价如实登记:收纳时先看到无语义的 `+1`,需点开才知是后台任务(与 fileChanges / pendingQueue 同一取舍,不为其破例)
|
|
677
|
-
- **推送点四个(零定时器、零轮询)**:`step_boundary`(任务刚启动的唯一气口——step 含一次 LLM 迭代 + 其工具执行,边界到达时快照已含它)/ `background_report`(终态批量变化)/ `background_kill` 处理后回推 / **`webview ready` 全量对齐**。三点共用**内容签名去重**(`taskId:status` 拼接串,变化才推)——用签名而非条数,因 kill 后 `running → killed` **条数恒为 1 而内容已变**,长度守卫会把这次关键刷新判成 no-op。⚠️ **阶段 3 补漏增补第五点**:内核 `backgroundTaskSettled` 事件(turn 结束后自然终态通知),现行推送点以代码 `postBackgroundTasks` 注释 / `protocol.ts` 五枚举为准,见上方阶段 3 Fixed 条目
|
|
678
|
-
- **⓿ ready 对齐必须走 `force` 绕去重(自审带伤第 4 条)**:三个周期性推送点漏了**时间面**(本项目已踩四次)——面板折叠/关闭再打开时新 webview 从未收到 `background_tasks` ⇒ **条凭空消失而进程还在跑、用户也砍不掉**。而签名存于 extension 实例、**跨重建残留** ⇒ 光加补推会被自己的守卫吞掉。故拆 `dedup`(周期降噪)/ `force`(视图重建后对齐)两语义,不合并成一条判据
|
|
679
|
-
- **接线**:`chatPanel` 增 `postBackgroundTasks()` / `killBackgroundTask()`;agent 未就绪时不推(否则「未就绪」被 UI 读成「没有后台任务」)
|
|
680
|
-
- **测试**:`chatPanelBackground.test.ts` 8 条(快照只下发 4 键不含 result / agent 未装配不推 / kill 后回推终态 / 签名未变不重推 / **签名降级为长度则吞掉 kill** / **force 绕过去重** / **ready 补推接线** / 经 `resolveWebviewView` 真实注册回调驱动的 `background_kill` 路由跳)+ `chatView.test.ts` 6 条(空快照零占用 / running 行三要素 / 终态行无按钮 / 终止只回宿主载荷带 taskId / 长命令截断 + title 全文 / 优先级垫底不顶 activity)
|
|
681
|
-
- **变异验证 7 组**(逐组确认对应用例转红):终态行按钮判据去掉 / 后台条优先级改 9 / 签名降级为长度 / 去掉签名去重守卫 / 路由跳改传常量 taskId / force 也走去重 / ready 补推改走 dedup
|
|
682
|
-
- ⚠️ **变异验证中抓到两处「验证本身不锐」**:① `force` 用例初版断言「总共推 N 条」,被两种不同错误实现同时满足(dedup 退化成不设限 / force 也被去重)⇒ 变异下仍绿,改为断言**增量恰为 1** 才变锐;② 变异写成 `'force' as 'dedup'`——**类型断言不改运行时值**⇒ 变异根本没生效,差点误判成「守卫无效」
|
|
683
|
-
- ⚠️ **已知取舍**:状态文案走协议下发而非 webview 自建词表(真源仍是内核那张表,宿主零自建);面板内色条复用 `--accent`(`--status-running` 在 `tokens.ts` 无定义,写了就恒走 fallback、不跟随主题)
|
|
684
|
-
|
|
685
|
-
### Fixed(宿主 · 任务项组层级与折叠箭头右置 · `TOP-UI-2` / `TOP-UI-3`)
|
|
686
|
-
|
|
687
|
-
**缺口(用户真机反馈)**:对话流任务表四级内容左对齐糊成一片;折叠箭头左置压迫行首,标题无法顶格。
|
|
688
|
-
|
|
689
|
-
- **定案形态**:组标题(`summary`)**顶格最外侧**、与叙述/工具行同列(组本身零 padding、无边线——边线恒在最左,与「标题最外侧」结构性冲突,分组语义由下方组内缩进独立表达);**组内过程行缩进一档**(`--sp-6` = 16px,与正文 markdown 列表缩进同档)
|
|
690
|
-
- **折叠箭头分槽**:chevron 移 `::after` 绝对定位右缘(收起「>」/ 展开「⌄」),状态环保留 `::before` 紧跟工具名——原「高特异性覆盖」方案的两条 `transform: none` 防漂移 hack 随分槽退役;summary 加 `position: relative` + `padding-right: 14px`;运行中工具行右缘 chevron 压掉(环即状态即类型,防双标识)
|
|
691
|
-
- **落地过程**:`bf2b8f0d` → `6b86973b`(推翻首刀「组整体右移」方案)→ `b82d7a21`(chevron 右置)三刀;运行时与重放共用 `getOrCreatePlanItemGroup` 唯一构造点,改样式即两路径同逻辑生效
|
|
692
|
-
- ⚠️ **零自动化测试覆盖**:纯 CSS 单文件改动(`chatStyles.ts`),DOM 断言不覆盖 ⇒ 验收口径为「点验前 `npm run compile` 重建 dist + 真机对照」(宿主 dist 已随本批过期)
|
|
693
|
-
|
|
694
|
-
### Fixed(宿主 · 角色页详情/编辑弹窗永不出现 · `RP-EDIT-1` 功能不可达回归)
|
|
695
|
-
|
|
696
|
-
**根因**:`roles_detail_data` 的重挂判据写成「弹窗已开才重挂」(`if (detailOverlay) renderDetailView()`)。该消息只有两个发送点——① `roles_detail` 应答(用户点卡片,**此时弹窗未开** → 首挂查看态)、② `roles_save` 成功回发(弹窗必然开着 → 先摘后挂回显)。判据把场景①整体挡死 ⇒ **详情/编辑功能从未弹出过**。
|
|
697
|
-
|
|
698
|
-
- **修法**:`roles_detail_data` 到达即无条件 `renderDetailView()`(`mountDetailModal` 幂等,`detailOverlay?.remove()` 先摘后挂,两场景同函数通吃)
|
|
699
|
-
- **纪律**:RP-EDIT-1 销项时判定为「✅ 已落地 · ⏳ 待真机点验」,真机一验即现**功能整体不可达**。同型于 `CMD-1-BYPASS-FIX` 已立纪律——新增判定分支必须同时补「该分支被走到」的用例,fixture 取生产真实形态;「单侧单测全绿」只证明没跑到
|
|
700
|
-
- **测试**:`rolesView.test.ts` +93 行 / 18 passed(2026-10-04 实测)
|
|
701
|
-
|
|
702
|
-
### Fixed(宿主 · 待发送区空条常驻 + 队伍幽灵引用清理 · `STATUS-DOCK-FIX` / `TEAM-GHOST-1`)
|
|
703
|
-
|
|
704
|
-
- **待发送区空条常驻**(`5aaff721`):空态判断**提前至懒创建前**(与文件改动条范式同构)——先判空再建 DOM,杜绝「有容器无内容」的空条常驻;新增 2 条测试锁定
|
|
705
|
-
- **组员侧标注退役 + 启动/面板读期队伍对账**(`b9c93eba`):`reconcileTeams` 纯函数 + 双接线点写回 `globalState`,清幽灵引用(队伍已删但标注仍在)
|
|
706
|
-
|
|
707
|
-
### Added(宿主 · 角色包编辑 UI `RP-EDIT-1`:键面查看与编辑——键面单源内核,保存全链路 extension 侧)
|
|
708
|
-
|
|
709
|
-
**缺口**:角色页此前全只读(卡片/来源徽章/策略 chips/健康区俱全),真缺口只有「改的入口」(先例同型 = FD-2 技能)。键面清单若放宿主 = 第二真相源,且未知策略键在内核校验中只 warning + 忽略 ⇒ UI 写错键名时保存不报错、该键静默不生效(健康徽章兜不住)。
|
|
710
|
-
|
|
711
|
-
- **内核键面单源**:`strategyKeys.ts` 新增 `describeStrategyKeys()` 导出(`StrategyKeyFace`:stage/key/kind/values?/options?/range?)——`check` 是闭包不可过协议、`askOn` 可选值藏于 `ASK_TRIGGERS`,键面派生收内核单点,宿主零清单维护;0 哨兵键按 `check(0)` 探测折算 UI 区间下限(0=不干预是合法填写,直接用 validator 区间会让用户填不了 0)
|
|
712
|
-
- **协议 +3 通道(102→105)**:上行 `roles_detail` / `roles_save`、下行 `roles_detail_data`、`roles_loaded` 扩 `keyface`(键面为静态派生与装配时序无关,rpm 未就绪分支也下发)
|
|
713
|
-
- **保存链路全在 extension 侧**:内置真拒绝(`rolePackSource` 单点判据,webview 隐藏编辑按钮只是呈现层,直接发消息也被拒)→ 读 manifest 原文**全量保真**只换 strategy 段(skills/displayName 等原样保留;空对象删键保持「未声明」语义)→ `validateManifestText` 首个 error 拦截不写盘 → 写盘必 `rpm.reload()` 失效装配缓存(下个 turn 立即用新配置)
|
|
714
|
-
- **表单初值 = manifest 文件原文,禁用装配值**:`rpm.get().strategy` 是合并默认值后的完整策略,回填保存会把默认值固化成显式声明,破坏「未声明」语义
|
|
715
|
-
- **webview 渲染层**:卡片点击开详情弹窗(复用 team-modal 令牌)+ 16 键中文表单(`STRATEGY_KEY_META` 标签/tooltip/选项文案,键集与内核双向一致守卫锁定)+ selfReview 做开关(默认 0=关,未勾=不写入不固化 0)+ askOn 多选 + **preserved 机制**(键面未覆盖的原文键保存时原样并入,防整段替换静默丢数据)+ enum 原文越界值回填「原文值」选项(防回填即改值)
|
|
716
|
-
- **测试**:内核键面派生 5 用例(含 0 哨兵折算与 askLimit 例外);宿主键面双向一致守卫(内核键集 ↔ META 键集,双向漂移都红 + 防假绿前置自证)+ 表单收集语义 5 用例;保存链路 6 用例——变异 M1 内置拒绝(不读不写不 reload)/ M2 全量保真(skills 不丢)/ M3 校验失败不写盘 / M4 reload 缺失全部锁定
|
|
717
|
-
- **验证**:内核全量 2840 passed | 4 skipped;宿主全量 883 passed | 2 skipped;宿主 tsc 0 / eslint 0 / prettier 0
|
|
718
|
-
|
|
719
|
-
### Fixed(宿主 · 挂起/插话补充输入渲染根治:骨架不删 + 正文单块续写统一)
|
|
720
|
-
|
|
721
|
-
**问题(真机三轮复测暴露)**:暂停申请态/插话态发送补充输入时,运行过程 UI 异常三连——①当前轮过程蒸发(界面只剩补充内容);②补充行散落在过程容器外;③吸收后重放出现内外双份。根因链三层语义错位:user 消息处理路径删除了骨架(flowShellEl),而 interject 契约「不 abort 旧流、runFlow 继续」意味着骨架非空壳、删除动作本身错误;打断分段形态(打断→新建正文块)与暂停锚续写(原位续写)两套形态并存,chunk 分支判定分裂。
|
|
722
|
-
|
|
723
|
-
- **① user 消息一律不删骨架**:骨架是当前轮过程容器宿主,清理职责单一路径归 meta(prepareFlowShell 重建时清旧)/ 重放(resetChatView),user 消息处理不参与
|
|
724
|
-
- **② 正文单块续写统一(打断分段形态退役)**:chunk 分支活动块复用判定统一为「活动块连接 + `isSameRoundContinue` roundId 护栏」——暂停锚块与插话前活动正文块两类来源共用同一判定,续写增量拼接(streamingRaw 不重置,打断前正文保留);跨轮 chunk(roundId 不等/缺失)走新建,防跨轮挂载串位(历史事故护栏保留)
|
|
725
|
-
- **③ 真新轮清理对称**:真新轮分支补 `resumePending = false`(残留 true 会被本分支误消费成续跑,与 done/interrupted 清理纪律对称)
|
|
726
|
-
- **验证**:宿主全量 **840 passed | 2 skipped**;盲区补测(打断后无续写直接 done:streamingRaw 残留旧文正常进 finalize,正文完整、补充行折入折叠块);真机复测通过
|
|
727
|
-
- **残留**:切界面不显示(流中 webview 重建不补重放)为独立问题,已登记在案
|
|
728
|
-
|
|
729
|
-
### Changed(示例包 · 共鸣小说家行为参数对齐白话方案设计师)
|
|
730
|
-
|
|
731
|
-
- `stepBudget` 40→100、`toolStepLimit` 20→100、`multiStepReasoning` manual→auto(`toolMode` 两包同 allow,未动;`temperature`/`outputLimit` 为创作特有设定保留)。**行为影响须知**:manual→auto 后请求不再强制 `reasoning_effort:'low'`——思考深度听服务端默认(变深、token 消耗上升),截断概率可能随之上升;截断救回(T2)不受影响,救回重试仍显式降 low(`llmCaller` 单点)。manual 原动机是 4096 紧预算下省思考防截断,outputLimit 放开(0-哨兵)后已弱化
|
|
732
|
-
- **验证**:内核 role-pack 域 244 passed + 内置包真实装载 8 passed(validator 域内)
|
|
733
|
-
|
|
734
|
-
### Changed(宿主 · chatView token 显示诚实口径:估算/正文标注 + 生效上限亮明 · `MAXTOKEN-SSOT-1` 销项)
|
|
735
|
-
|
|
736
|
-
**问题**:chatView 两处 token 显示(轮详情执行指标 / 活动指标聚合面板)直接展示 roundStore 估算值——「Tokens:入 X / 出 Y」中的「出」只累计**正文**(不含 thinking、不含工具轮叙述),推理模型下「出 89」与十几条思考严重不符,必被误读为总输出;而真实生效的输出上限(面板配置与角色包取小后的裁决值)用户看不见,被角色包收紧时无任何提示。
|
|
737
|
-
|
|
738
|
-
- **① 两处口径标注**:改为「Tokens(估算):入 X / 正文 Y(不含思考)」——入/出均为本地估算(非服务端 usage),输出只指正文
|
|
739
|
-
- **② 轮详情新增「输出上限(生效):N」行**:直读 meta 事件 `payload.maxTokens`(零新增数据通道),undefined → 「服务端默认」;配了面板却被角色包收紧时,生效值与面板不一致即可见
|
|
740
|
-
- **③ 共鸣小说家 outputLimit 维持 0 结案**:manifest 第三档已改 0——显式正数 = 重新引入隐形天花板 + 模型相关魔法数(小上限模型直接服务端报错),放大交给面板(已提示 32–64K)
|
|
741
|
-
- **验证**:chatView.test.ts 旧断言订正 + 新增生效行两分支断言(带值 / 缺省);变异(还原旧文案 + 生效行恒默认)恰红 2 用例,恢复复绿(244 passed)
|
|
742
|
-
- **残留**:「面板 vs 角色包哪一侧收紧」的并列标注未做(生效值已可见;增量标注需新字段,触发=真机误读再现);服务端实测 usage 通道未做(mimo 等上报可靠性未验证,内核已累计 actualInput/OutputTokens 未消费)
|
|
743
|
-
|
|
744
|
-
### Changed(输出上限裁决改「取交集」语义 · 与上下文窗口对齐 + 默认不再设天花板)
|
|
745
|
-
|
|
746
|
-
**问题**:输出上限有两个来源(per-LLM 面板「输出上限(K)」与角色包 `act.outputLimit`),旧实现是**角色包直接覆盖**(`Object.assign` 压过)——与「上限」的语义相反:上限应取交集(任何一侧说「不能超过 X」都必须满足),覆盖却允许角色包把用户配的小值顶大。同一件事在**输入侧**早已是正确写法:`min(provider 窗口, 角色包 contextLimit)`,两侧不对称。
|
|
747
|
-
|
|
748
|
-
- **① 改取交集**:`buildChatOptions` 末对 `maxTokens` 做 `min(per-LLM, 角色包)` 收敛(仅此键取小;`temperature` 等是「设定值」不是「上限」,维持覆盖语义)。裁决仍在该方法**单点**,宿主仍只读 `Agent.getEffectiveMaxTokens()`,不重算
|
|
749
|
-
- **② 默认不再设天花板**:`DEFAULT_BEHAVIOR_STRATEGY.act.outputLimit` 由 `4096` 改 `0`(= 不干预 → 回服务端默认 / 听面板)。**旧默认 4096 是隐形天花板**——未声明的包也被硬限到 4096,用户面板配 64K 无效且取证面看不出来
|
|
750
|
-
- **③ 表示法统一(0-哨兵同构)**:`act.outputLimit` 校验域由 `[1, 65536]` 扩为 `0 ∪ [1, 65536]`——`0` = 不干预哨兵(≡ 不写该键),与 `contextLimit` / `stepBudget` 完全同构。三个「上限类」键统一一条心智规则:**不写 = 默认立场;写 0 = 让路(听下一层真相源);写正数 = 显式上限(与 per-LLM 配置取小)**。schema.json `minimum` 同步 1→0;同构关系由守卫测试钉死(某键若漂回 intRange 即红灯)。消费点 `agent.buildChatOptionsFromStrategy` 既有 `> 0` 守卫零改动,`rolesView` chip 对 0 自动隐藏
|
|
751
|
-
- **影响面(行为变更,须知)**:①角色包未声明 outputLimit → 请求不再带 4096 上限(回服务端默认或听面板配置);②**显式声明** outputLimit 的包(如「共鸣小说家」4096)不受②影响,取小后仍是 4096 —— 想放大必须改该包的声明值或删掉该行
|
|
752
|
-
- **验证**:新增/改写用例(两侧收紧都生效、单侧缺位取另一侧);**变异**:min 退回 Object.assign → 恰红(`expected 4096 to be 1024`);内核 `tsc --noEmit` 0 错误、eslint `--max-warnings 0` 干净、受影响套件 352 passed
|
|
753
|
-
|
|
754
|
-
### Fixed(真机复核修正 · EMPTY-RESP-1:计数假阳 + 取证面改记生效值)
|
|
755
|
-
|
|
756
|
-
> **背景**:2026-09-29 的 T1/T2「真机验收」经 19 轮 round 数据复核后被推翻——详见 `tasks/审查-空响应根因排雷与优化方案-20260929.md` §七;新告警登记为观察项 `MAXTOKEN-SSOT-1`(待完成任务 .md)。**下方 2026-09-29 T1 / T2 条目的「真机取证」结论请以本条为准。**
|
|
757
|
-
|
|
758
|
-
- **① 内核 · 截断救回计数假阳(`truncationRecoveryCount`)**:原判据 `truncatedRetry && !isEmptyResponse` 中,`isEmptyResponse` 内含 `!aborted` ⇒ 用户在流中途点停止、流提早退出时也判为「非空」,于是**「用户放弃」被记成「换策略救回成功」**(真机 round-1790686368607 全程零产出事件却 recov=1)。修复 = 计数判据补 `!aborted`(单点,兑现原注释已声明而未实现的纪律)。变异验证:去掉 `!aborted` → 新增用例恰红,其余不受影响
|
|
759
|
-
- **② 内核 + 宿主 · 取证面改记「生效值」**:输出上限存在两个来源(per-LLM 面板与角色包 `act.outputLimit`,由 `loop.buildChatOptions` 单点裁决——两者取更小值,见上方 Changed①)⇒ meta 记用户配置值会把「配了 64K」误读成「发了 64K」。新增读取口 `AgentLoop.getEffectiveMaxTokens()` + `Agent` 薄委托,宿主 `buildRoundMeta` 以它为首选、配置面仅作回落——**宿主不再重算裁决规则**(宿主重算即第二真理源,正是本次误判根因)
|
|
760
|
-
- **③ 口径同步(去假 SSOT 声明)**:`protocol.ts` / `assemble.ts` 中的「唯一真理源 = per-LLM maxTokens」为假声明 → 改「底座值,非最终生效值」;`ProcessMetaPayload.maxTokens` 语义同步为生效值(旧数据语义差异已在注释标明)
|
|
761
|
-
- **④ 宿主 min agent 替身补齐**:`consumeFlow` 每轮经 `buildRoundMeta`,替身缺新方法会让整条落盘链路**静默空转**(8 条连带失败,已用对照实验确认非环境噪音),已在替身工厂单点补齐;`buildRoundMeta` 用例同步升级为守卫「生效值 ≠ 配置值」
|
|
762
|
-
- **验证**:内核 `tsc --noEmit`(含 scripts)0 错误 + 改动文件 `eslint --max-warnings 0` 干净;内核全量 **2820 passed / 12 failed(AssertionError = 0,全为 timeout ⇒ 环境性假红)**;宿主 `tsc -p ./` 干净 + 相关单测 **53/53**
|
|
763
|
-
|
|
764
|
-
### Fixed(宿主 · 纯删除块装饰改红:删除点被染成新增色的语义错位)
|
|
765
|
-
|
|
766
|
-
**问题**:`buildDecorationItems` 把纯删除块的锚行走与新增/修改**同一个绿色装饰**——绿底直觉是「这行是新内容」,而删除锚行本身是**未变的其他内容**(删除点在新文件中不覆盖任何行,装饰只能落在锚行),颜色语义相反;且行尾红色预览删除后,删除点只剩 hover 一层信息。
|
|
767
|
-
|
|
768
|
-
- **修法**:装饰成对化(`DecorationPair`:added 绿 / removed 红)。红侧 = 红竖条主信号 + 极淡红底(0.10,远淡于绿 0.18,避免「该行被删」误读)+ 红 overview ruler;同样**惰性构建**(模块顶层求值 `OverviewRulerLane` 会炸最小 mock 环境,同前轮教训)。`buildDecorationItems` 拆两侧返回,两侧用不同 decorationType
|
|
769
|
-
- **空侧不调 `setDecorations`**:空数组调用是纯噪音;曾挂载的装饰随旧 type 的 dispose 一并清除,无残留面
|
|
770
|
-
- **选择性吸收**(对照同类 IDE 变更确认视图的评估结论,详见方案文档 §11.14):只吸收行级「新增绿 / 删除红」分流;词级内联幽灵文本属扩展 decoration API 硬边界、渲染态叠加与「先改后审」模型(与 DIFF-7 残留同源,memora 先审后写天然避开)均**不追**
|
|
771
|
-
- **验证(先红后绿)**:新增守卫 2 条(修改/新增块挂绿且红侧空不产生调用 / 纯删除块挂红且 `renderOptions` 仍 undefined、hover 保留);**变异**(红/绿分流删除)→ **恰 1 红**、红在断言本体,还原复绿;宿主 `tsc` 0 / `eslint` 0 / fileChange 三套件 **90 passed**
|
|
772
|
-
|
|
773
|
-
### Changed(宿主 · 文件改动可视化的 SSOT 收口 + 描述层回扫)
|
|
774
|
-
|
|
775
|
-
**问题(SSOT 收敛 · 内核零改动)**:上一批「文案口径单源」提交(`COMPARE_LABEL`)自身仍留 **2 处并列真理源**,且 `docs/` 第 1 层回扫漏网——即「改一处碰一片」的反面:**两处各写一份,改一处只碰一处**。
|
|
776
|
-
|
|
777
|
-
- **① 忽略目录改派生内核真源**:`chatPanel.ts` 原手写 14 项 `IGNORED_DIRS`。内核 `IGNORED_DIR_NAMES`(`builtinToolHandlers.ts`,注释原文「宿主通过主入口 import 此常量对齐忽略目录,**避免数值/规则漂移**」)早已由 `src/index.ts` 导出、宿主 `projectSearchProvider.ts` 亦已 import 复用 ⇒ 本次新写的第二份是**并列副本**(6 项重合)。改 `new Set([...IGNORED_DIR_NAMES, ...宿主独有产物目录])`;危害面:内核新增忽略目录时快照仍扫它 → 内部数据混进改动可见性(静默)
|
|
778
|
-
- **② 降级提示抽单点常量**:写前降级 / 写后降级两条路径各写一遍同一句文案(相隔 9 行)⇒ 抽 `SNAPSHOT_OVERSIZE_NOTICE`,并把重复的 `post` + 重复的 `ok && !blocked` 判据收敛为两分支各一次调用(行为等价)
|
|
779
|
-
- **③ 描述层回扫(`docs/` 第 1 层)**:`方案-文件改动diff可视化-20260926.md` 尚有 **3 处「打开对比」(本轮改名漏扫)+ 10 处「恢复旧版」(上一轮改名漏扫)**,全落在 §3.4 / §3.5 / §7 等**现状断言**段 ⇒ 统一为实际发货标签(查看对比 / 回退本文件改动 / 确认改动)。`tasks/` 中的同名旧称属**历史过程记录**,按 `legacy-contract-audit-rules` §3.3 第 8 层边界**不动**
|
|
780
|
-
- **④ 同一设计真值去重复陈述**:「左右分栏 vs 自渲染上下视图」的选型理由原在 `fileChangeView.ts` 文件头与 `openCompare` jsdoc **各写一遍**(第二真理源)⇒ jsdoc 删复述改指针,文件头去日期编年、保留「勿改回」防回归信号;并去痕一个残缺变体选择符(U+FE0F)
|
|
781
|
-
- **⑤ 回退安全判据「判据面 / 通道面」分离**:§4.4 原措辞「必须经内核工具路径**或**同源校验」+「宿主 fs 直写属禁止项」读起来否定现状;§7 第 6 条(断言走内核写路径)与第 10 条(断言走宿主直写)**自相矛盾**。据实收敛:**判据面** = 必过 `assertPathAllowed`(与内核 SecurityGuard 同源,守卫缺失 fail-closed);**通道面** = 宿主直写(无活跃 loop 时内核工具不可达,且经工具会伪造 `tool_start`/`tool_result` 污染时间线),故**宿主直写为定案、非带伤**
|
|
782
|
-
- **验证(实测)**:宿主 `tsc` 0 / `eslint` 0;fileChange 四套件 **93 passed**(与改前同数,零行为变更);根 `terminology:check` 0;`prettier --check` 全绿
|
|
783
|
-
- **入档**:`CHAT-SNAP-1` 补第 ④ 条残留缺口(`scriptSnapshots` 异常流不回收,严重度按「全量快照 × 可并发驻留」记)
|
|
784
|
-
|
|
785
|
-
### Fixed(宿主 · 问答卡纳入工具批切段:外部可见条目作断面 BATCH-SPLIT-1)
|
|
786
|
-
|
|
787
|
-
**问题(登记在案缺陷 BATCH-SPLIT-1 · 纯宿主渲染层,内核零改动)**:`groupToolBatches` 只吃 `events`,而问答卡(`.round-block__input`)来自 `interactiveInputs` / 运行时缓存——**无 seq、不在 events 里** ⇒ 对切段判据天然不可见。两段工具之间夹一张问答卡时(工具 A → ask_user → 卡片 → 工具 B),A 与 B 被并成一批、批块锚在段内首工具 ts,卡片被推到整块**之后**(观感「问答卡之后的工具跑到卡片前面」)。复现路径 `renderReplayRound`(打开历史会话走它)+ 运行时流式(`renderProcessFlow`),两路同病。
|
|
788
|
-
|
|
789
|
-
- **根因(同屏两套键 · 与 PLAN-GROUP-ORDER-1 同族)**:切段判据按 **seq** 扫描(`[...events].sort((a, b) => a.seq - b.seq)`),条目落位按 **ts**(`insertPlanItemInOrder`)⇒ 无 seq 的外部可见条目对切段天然不可见
|
|
790
|
-
- **修法(最小 · 不碰内核)**:新增 `visibleInputTs(root, extra)` 抽出「同容器里实际可见的问答卡 ts」,作**虚拟断面**注入 `groupToolBatches`。判据 = 「桶号」(小于该工具 ts 的边界数)变化即断段——**与落位同用 ts 键**(呈现在哪、断面就在哪),不引入第三套键(缝合风险按此规避)
|
|
791
|
-
- **接线两处**:finalize 重建(DOM 快照 + `interactiveInputs` 入参)/ 运行时流式(`flow` 内已上屏问答卡)——同一判据、同一入参名,禁内联三份
|
|
792
|
-
- **清账**:封存期 `it.fails` 守卫(「期望失败」)**转红 ⇒ 升格为普通 `it`**,该动作即清账触发器、已触发;另补**流式对拍用例**一条(同一不变量),防「只修一路」
|
|
793
|
-
- **验证(先红后绿 + 变异)**:隔离 `3 passed`;**变异**(`bucketOf` 恒返回 0)→ 两条守卫**恰 2 红**、前置自检仍绿 ⇒ 守卫有牙;宿主全量 `785 passed | 2 skipped`、`tsc` 0
|
|
794
|
-
- **内核侧事实(已核实,非推理)**:提问走 `ask_user` 内置工具(唯一通道)⇒ 真实轮次在 A 与 B 之间必有该工具行(夹具已补,保真度修复);工具轮 narrate 为**条件产出**(`if (narration)`)⇒「无 narrate」边界真实可达;`willSuspendForAsk` 命中时**不产出** `plan_item_boundary`
|
|
795
|
-
- **入档**:判据并入 `docs/方案-工具批按step断段-20260926.md` §4.1 表 + §4.2 伪码(此前只存在于代码注释 ⇒ 真理源缺层)
|
|
796
|
-
- **真机待复验**:两处接线(重放打开历史会话 / 运行时流式)的真机效果需「重载扩展宿主 + 开一轮含提问的对话」复看——与上方批次真机复看同批待办。故本项定级 **✅ 测试级**(单测 + 重放 + 变异),非真机闭合
|
|
797
|
-
|
|
798
|
-
### Fixed(宿主 · 任务项组位置判据归位:纯 seq → 任务项 / 时间轴插入域的 (ts, seq))
|
|
799
|
-
|
|
800
|
-
**问题(SSOT 收敛 · 带伤收口,内核零改动)**:`insertPlanItemGroupInOrder` 摆组时只比 `dataset.seq`,而**任务项 / 时间轴插入域**唯一的排序键是 **(ts, seq)**——`bounds` 排序(`a.ts.localeCompare(b.ts) || a.seq - b.seq`)、「任务项 N」编号(`bounds.indexOf + 1`)、归属判定(`planItemContainerFor`)、行插入(`insertPlanItemInOrder`)四处同源,只有摆组这一处偏出 ⇒ 组的**视觉位置**与它的**编号**可出自两把不同的键。(注:`renderReplayRound` 的重放中段内容另有一处 ts-only 排序,属内容装配域、不在此键域内。)
|
|
801
|
-
|
|
802
|
-
- **实锤(先红后绿,非推理)**:补守卫测试喂「边界 ts 与 seq 逆序」的病理样本(时钟回拨 / 历史补写),旧实现下第一个组的标题是 **「任务项 2 · 任务甲」**——编号序与视觉序分家 → 红;判据归位后绿
|
|
803
|
-
- **修法**:比较键改 **(ts, seq)**(ts 优先、同 ts 回落 seq);签名加 `boundTs`,调用点改传 `bound.ts`
|
|
804
|
-
- **零正常差异**:正常数据下组按创建序插入 ⇒ `find` 恒空、旧判断等于未生效;本改动只在 ts/seq 逆序时改变行为——而那正是编号已按 (ts, seq) 排出的口径,属**向真理归位**
|
|
805
|
-
- **定性订正**:本题原以 `PLAN-GROUP-ORDER-1`「观察项」登记(定级偏轻);按 `legacy-contract-audit-rules` §1「从零不会这么写」+ §2「同语义多实现」实为**带伤**,本轮按 §5 收敛流程收口
|
|
806
|
-
- **验证**:宿主全量 **782 passed / 2 skipped / 0 failed**、`tsc` 0
|
|
807
|
-
|
|
808
|
-
### Fixed(宿主 · 任务项组外过程条目沉底:任务项组纳入统一 (ts, seq) 排序候选)
|
|
809
|
-
|
|
810
|
-
**问题(纯宿主渲染层,内核零改动)**:`plan_item_boundary` 排在**本轮首个工具之前**时(续会 / prepare 预置 / 上一 turn 遗留计划),本轮工具全被边界收进任务项组内、根层只剩组外条目(narrate / thought / 工具批块)。宿主 `insertPlanItemInOrder` 的候选集合原只列「行」、不含任务项组 ⇒「行 vs 组」永不比较,根层无同层行可锚时即走 `appendChild` 落尾 → 组外条目沉到**全部任务项组之下**(真机 `round-1790411133316` 表现为「建表工具夹在倒数第一与倒数第二个标题之间」)。
|
|
811
|
-
|
|
812
|
-
- **修法(喂料止血,零触碰排序判据)**:`getOrCreatePlanItemGroup` 补挂 `dataset.ts`(边界事件自身的排序键);`insertPlanItemInOrder` 候选集合加 `:scope > .round-block__plan-item`。比较判据(`ts` 升序、同 `ts` 回落 `seq`)**原样未动**——只是让组**进入**已有的那条排序逻辑,不新增第二条
|
|
813
|
-
- **组内零误伤**:候选限定 `:scope >`(直接子节点),而组不嵌套组(`getOrCreatePlanItemGroup` 的 root 恒为 flow / details)⇒ 往组**内**插行时该选择器恒 0 命中
|
|
814
|
-
- **守卫**:`chatView.test.ts` +2 例(真机两形态——边界前置于首个工具 / 建表工具在边界之前);变异退回候选那半 → 恰 1 红、零误伤。宿主全量 **781 passed / 2 skipped**、`tsc` 0、`eslint` 0
|
|
815
|
-
- **存量旁路(同批已收口)**:`insertPlanItemGroupInOrder` 原按**纯 seq** 定位组,与上行的 (ts, seq) 键偏离——见上方 `### Fixed(宿主 · 任务项组位置判据归位…)`
|
|
816
|
-
- **真机待复验**:`dist` 已随本批 `pre-push` full 档的宿主构建重建(实测 `dist/webview/scripts/chatView.js` 已含 `grp.dataset.ts`)⇒ 只剩「重载扩展宿主 + 开一轮带任务表的对话」复看建表工具落点
|
|
817
|
-
|
|
818
|
-
### Added(宿主 · 文件改动 diff 可视化 DIFF-1:打开真实文件 + 改动行内联高亮 + 顶/底各一组确认·回退)
|
|
819
|
-
|
|
820
|
-
**性质**:host-only,**内核零改动**(渲染与动作全在 `hosts/memora-vscode/src/extension/host/fileChange*.ts`)。
|
|
821
|
-
|
|
822
|
-
- **形态**:不强制弹 diff 窗口——改动已生效,直接打开真实文件,改动行**块级高亮**;hunk 首行行尾**内联旧内容**(删除线灰字)+ 悬停看完整旧内容(仅内存展示、全程零落盘);文件**顶部与底部各一组四按钮**(确认本文件 / 回退本文件 / 全部确认 / 全部回退)
|
|
823
|
-
- **为何不挂 per-hunk 按钮(2026-09-26 真机修正)**:CodeLens 渲染在**所在行上方**,挂在 hunk 首行时按钮紧贴**上一个 hunk 末尾**之下 → 真机上被读成「回退上一段」,而动作粒度本就是**整个文件**;收敛为顶/底两组
|
|
824
|
-
- **真机三连击的根因与修法**(已固化进技能 `memora-host-ui-consistency` 规则 6):① 装饰是 **per-editor** 绑定,切走再切回**不会**自动恢复;而 CodeLens 走 provider 模式自己活 ⇒ 症状恰是「高亮丢、按钮留」→ 对全部显示该文档的可见编辑器逐个 `setDecorations` + 挂 `onDidChangeVisibleTextEditors` 补齐;② 内核**直写盘、不经编辑器** ⇒ 文档缓存仍是旧行数时 range 会**画到错误的行** → 渲染前非 dirty 且内容不符即 `workbench.action.files.revert` 重载;③ 一个 step 内并发写同文件的多条 `tool_result` 连着触发渲染 ⇒ `renderSeq` 只让最新一次落地 + `await` 后**重取最新记录**
|
|
825
|
-
- **回退语义(勿按「清空」实现)**:回到 agent 动手前的状态——新建的文件→删除,已有文件中新增的行→去掉,而**已有文件被改过时是写回改动前正文**(清空会连原有内容一起抹掉)。两个入口统一走同一回退逻辑
|
|
826
|
-
- **守卫**:`__tests__/fileChangeCommands.test.ts` 命令 id **双向**对拍(3 个对外命令必须在 `contributes.commands` / 2 个 CodeLens 内部命令必须不在),断言**不复制 id 字面量**(从模块 import);`__tests__/fileChangeView.test.ts` 装饰存活 4 例。变异验证:删监听 → 3 红 1 绿;`slice(0,1)` 退化 → **恰 1 红**
|
|
827
|
-
- **同批修掉的 SSOT 违例**:`isRemovedOnly` 在 `fileChangeView` 的内联副本 → 改 import(该函数生产侧零消费,副本是真违例而非「同模式重复」)
|
|
828
|
-
|
|
829
|
-
### Fixed(宿主 · 文件改动回退的未保存编辑守卫 W2:fail-closed 闸 + 模态确认)
|
|
830
|
-
|
|
831
|
-
**问题(数据丢失类)**:`applyRestore` 不看 `doc.isDirty`——文件有未保存编辑时点「回退本文件改动 / 全部回退」,写回 `beforeContent` 会把用户缓冲区里的编辑**静默覆盖**(无 git 时无法找回)。上条的 `!doc.isDirty` 守卫只管渲染重载、不管回退。
|
|
832
|
-
|
|
833
|
-
- **修法(用户拍板「弹模态确认」)**:`applyRestore` 加 fail-closed 闸(返回改 `RestoreOutcome` 三态,`dirty` 单列、不混进失败原因),单文件回退遇 dirty **弹模态确认**(取消 = 不动文件、记录保留);批量回退**一个模态一次列出全部 dirty 文件**(明细含「(含未保存编辑)」+ 计数),`overwriteDirty` 只放行清单内文件——确认之后才变 dirty 的仍被拦、如实报失败
|
|
834
|
-
- **守卫**:`fileChangeView.test.ts` +4 例(全走真实命令路径,不私调内部方法)。变异验证:删 fail-closed 闸 → 恰 2 红;删 `isDirty` 判据 → 恰 1 红;零误伤
|
|
835
|
-
- **内核导出面同批收编(DIFF-2 闭合)**:内核 `pathGuard` 导出 `MAX_DIFF_CONTENT_LENGTH`、`WRITE_PATH_EXTRACTORS` 过 `src/index.ts`(见 [3.0.0] Added);宿主并列副本删除、`DISK_WRITE_TOOLS` 派生自内核键(跨包双枚举收编单源,字面量断言升为跨包契约钉)。⚠️ 只统一数值、不统一行为(两侧超限行为仍不同)
|
|
836
|
-
- **新缺口登记**:DIFF-4(无 `path` 改盘工具双盲)/ DIFF-5(写工具「谁会改盘」判据:新工具**整行漏写** `diskWrite` 声明位 = 串行不防 + 追踪不报 + 契约钉不红的三重静默。⚠️ 2026-09-27 订正:原登记写「两处枚举无对拍守卫」**机理已过时**——收编后是「一处声明 + 两级派生 + 契约钉」,无两处枚举,故不存在「补对拍守卫」这种修法)
|
|
837
|
-
|
|
838
|
-
### Fixed(宿主 · 对比预览体积闸在删除场景失效 + 回退审计 tool 名失真)
|
|
839
|
-
|
|
840
|
-
- **体积闸漏判(删除场景)**:`openCompare` 判据原为 `rec.afterContent !== null && max(before,after) > MAX_DIFF_CONTENT_LENGTH`——`delete_file` 时 `afterContent === null` **短路为假** ⇒ 删几 MB 的文件时整份旧内容照样进虚拟文档 + `vscode.diff` 渲染,正是这道闸要防的事(该 `!== null` 本意是防 null 解引用,非有意放行)。**修法**:两侧长度各自 `?? ''` 后取 max,null 与非 null 一视同仁
|
|
841
|
-
- **回退审计 tool 名失真**:`applyRestore` 恒传 `assertPathAllowed(path,'write_file')`,而「原为新建」的回退实际动作是**删除**。该参数**只进审计事件的 `tool` 字段、不参与放行判定**(判定只用黑名单 + 白名单前缀)⇒ 非安全洞,但审计里「删了什么」全记成写。**修法**:按实际动作传(`beforeContent === null ? 'delete_file' : 'write_file'`)
|
|
842
|
-
- **守卫**:`fileChangeView.test.ts` +3 例(8→11),全走真实路径(事件 / `registerCommand` 捕获的处理器):删除大文件→提示且**不开** `vscode.diff`;**反向守卫** 小文件删除→正常开对比;回退新建→走删除分支且审计记为 `delete_file`。**变异验证**:退回 `afterContent !== null &&` → 恰 1 红;退回恒传 `'write_file'` → 恰 1 红;零误伤
|
|
843
|
-
|
|
844
|
-
### Added(宿主 · 文件改动三层粒度归位:文件级上标题栏 + 新增块级「接受此处 / 拒绝此处」)
|
|
845
|
-
|
|
846
|
-
> **订正上节(形态已变,勿按旧文验收)**:上面 `Added(DIFF-1)` 里「顶部与底部各一组四按钮」与「为何不挂 per-hunk 按钮」两条 **已被 2026-09-27 真机反馈推翻**——按钮嵌在文件正文里用户明确不接受;且那里否决的是「**文件级**按钮挂在每个 hunk 上」(粒度 + 位置双重错位),不是「块级按钮」本身。现形态见本节。
|
|
847
|
-
|
|
848
|
-
- **文件级按钮迁出正文 → 编辑器标题栏**:`menus.editor/title` 的 `navigation` 组(标签栏右侧图标按钮),配 `when: memora.fileChangePending`(`setContext` 维护,取「活动文件是否有未确认改动」,不在每个文件上都挂按钮)。VS Code 扩展 API **没有**编辑器内悬浮操作条(Trae / Qoder 那条提示条是 fork 内核级 UI,扩展层拿不到),标题栏是扩展能拿到的最接近形态。命令 id 随之改名 `memora.fileChange.confirmFile` / `.restoreFile`(原 `…confirmInline` / `…restoreInline` 命名在迁走后失真),并从「内部命令」翻转为**必须贡献**(菜单依赖声明才渲染)⇒ 参数归一化 `string | Uri | undefined`、无参回落活动编辑器
|
|
849
|
-
- **块级按钮(命题 B)**:每个改动块末尾一组「接受此处 / 拒绝此处」,落点 `hunk.endLine + 1` —— CodeLens 渲染在所在行**上方** ⇒ 视觉上紧跟该块**之后**;挂首行会贴在上一个 hunk 末尾之下被误读(§11.8 旧伤)。纯删除块 `endLine = startLine - 1` ⇒ 落点正好是删除位置,无需分支
|
|
850
|
-
- **块级动作是纯逻辑派生,无新状态**(与 git `add -p` 的 index 模型同构):接受 = 基线改为「当前内容剔除未接受的块」(**不动盘**);拒绝 = `applyHunkReverts` 区间替换后写盘。块全部处理完 ⇒ diff 为空 ⇒ 与文件级确认**同一收口**,无特判、无「已接受块集」、无坐标迁移
|
|
851
|
-
- **纯逻辑层新增两个导出**(`fileChangeDiff.ts`,可 node 单测):`applyHunkReverts`(多块按 `startLine` **降序**——插入块还原会改行数,升序会让后一块 `splice` 打空)/ `hunkKey`(位置 + 内容指纹;渲染 → 点击若对不上即 **fail-closed**,绝不按下标猜块——回退是写盘动作,猜错即吃掉用户内容)
|
|
852
|
-
- **守卫**:`fileChangeCommands.test.ts` 分类断言翻转(5 个对外命令必须贡献 / 2 个块级命令必须不贡献)+ 新增「标题栏菜单必须带 `when`」守卫;`fileChangeView.test.ts` 改块级粒度与落点用例 + 新增块级动作 8 例。fileChange 四单测合计 **79 passed**。**变异验证**:落点改回块首行 → 恰 1 红;接受后不失效 `hunkCache` → 2 红;指纹失效按下标兜底 → 1 红(硬证据是**真的写了盘**)
|
|
853
|
-
- **⚠️ 变异验证的自我排雷**:最初「多块一次性还原 = 写前内容」用的是等长替换(行数不变 ⇒ 升序降序同结果),变异**不变红** ⇒ 先怀疑断言没咬住判据(补真机那组两块插入后才红),而不是怀疑代码
|
|
854
|
-
|
|
855
|
-
### Fixed(宿主 · 块级按钮「跑到改动上方」+ Changed:改动对照改上下排列)
|
|
856
|
-
|
|
857
|
-
> **本节的形态变化覆盖上节部分描述**:上节「块级按钮落点 `endLine + 1` ⇒ 视觉紧跟该块之后」在**末块贴文件最后一行**时不成立(见下第 1 条);对照视图由 `vscode.diff`(左右并排)**改为自渲染单列上下排列**。
|
|
858
|
-
|
|
859
|
-
- **BUG「点了一个按钮后,底部修改的按钮跑到上面去了」= 结构性边界,非行号算错**(2026-09-27 真机反馈,硬证据):真机文件 `创意杠杆候选.md` 为 `endsWithNewline = false` / `lineCount = 28`,被改行 = 第 28 行 = **文件最后一行** ⇒ 末块 `endLine + 1 = 28` 越界、`safeLineRange` clamp 回 27,而 **CodeLens 恒渲染在所挂行上方** ⇒ 末块按钮必然落在该块**上面**。VS Code 扩展 API **给不出「渲染在行下方」的 CodeLens** ⇒ 位置不可解。用户观感「点一下才跑上去」的真因:点掉前一块后只剩末块,场上唯一的按钮就是那颗被 clamp 的。
|
|
860
|
-
- **修法(位置解不了 ⇒ 让归属不依赖位置)**:块按钮标题**恒带序号** `(N/M)`(`$(check) 接受此处(1/2)`),单块也显 `(1/1)`,不搞「时有时无」;顺带补上旧根因「看不出共几处」。
|
|
861
|
-
- **守卫 2 例**(末行 clamp 形态 + 序号恒显);变异 `const suffix = ''` → **恰 2 红**。
|
|
862
|
-
- **对照视图由左右并排改为上下排列**(用户「现在的左右排列看不清楚原文」):`vscode.diff` 是左右分栏,窄编辑器里长行被挤成两个半栏。**为什么不能「把 diff 设成 inline 再打开」**——扩展 API 拿不到该入口:`vscode.diff` 第 4 参数(`TextDocumentShowOptions`)**不含布局**,布局只受用户全局 `diffEditor.renderSideBySide` 或**切换型**命令影响(盲调 = 改用户设置)⇒ 自渲染统一视图是唯一确定性路线。
|
|
863
|
-
- **纯逻辑新增 `formatUnifiedDiff(before, after, title)`**(`fileChangeDiff.ts`):单列 `- `/`+ ` 文本 + 每块分隔头 `──────── 改动 N/M · 新文件第 X 行 ────────` + `共 N 处改动`。⚠️ 与 `MAX_DIFF_CONTENT_LENGTH` 的关系:**只统一取值、不统一行为**(宿主仍「跳过对照只提示」)。
|
|
864
|
-
- **呈现层改用只读虚拟文档 + `showTextDocument`**:零落盘、天然只读;删除 `executeCommand('vscode.diff')` 路径、`existsSync` 导入与 `rightSeed`(「删除场景右侧给空虚拟文档」分支随左右并排一起消失)。
|
|
865
|
-
- **守卫**:正文为单列、同一处**先旧后新**、`executed` 中**不得出现 `vscode.diff`**。变异:把 `openCompare` 改回 `vscode.diff` → **3 红**。
|
|
866
|
-
- **⚠️ 方法论教训(变异验证的「守卫可达性」)**:等待条件最初写成「等虚拟文档已打开」⇒ 变异回 `vscode.diff` 时 `waitFor` **先超时变红**,形态守卫**根本没跑到**(红在等待、不在守卫)。改为「等对照视图以**任一形态**出现」+ 形态断言并列后才精确命中。**守则:变异必须红在断言上,不能红在等待/前置条件上。** 已固化到常驻载体(不留在本节):`memora-host-ui-consistency` 技能**规则 4**。
|
|
867
|
-
- **验证终值**:fileChange 四单测 **89 passed**;`tsc --noEmit -p ./` = 0;`eslint --max-warnings 0` = 0。宿主全量 `Tests 5 failed | 774 passed | 2 skipped`,**AssertionError = 0**;按「先数 AssertionError、再隔离复跑」定性:只跑那两个文件 → `1 failed | 32 passed`(**只剩 `projectSearchProvider` 501 文件 30s 超时**),另 4 条为并发 I/O 争用假红。**未改任何 timeout 迁就。**
|
|
868
|
-
- **同批修正(源文件裸 NUL 字节污染 git / ripgrep)**:`fileChangeDiff.ts` 的 `hunkKey` 里 `removed` / `added` 的拼接分隔符原为**裸 `0x00` 字节**,落在 **offset 7751**——恰好在 git 二进制判窗(头 8000 字节)之内 ⇒ `git diff --stat` 显示 **`Bin …`**、`Grep` 返回 **`binary file matches` 而非命中行**,该文件改动**在提交里完全不可读**(tsc / 单测全绿、门禁查不出)。改为 **`\u0000` 转义**(运行期仍是同一字符 ⇒ hash 与 89 项单测不变),并在 `hunkKey` 的 JSDoc 写明「勿写裸 NUL 及原因」。复验:`tsc --noEmit -p ./` = 0;fileChange 四单测 **89 passed**。⚠️ **提交前必须重新 `git add` 该文件**(`git diff` 比两侧,索引里仍是带 NUL 的旧 blob 则依旧判二进制)。**已归位真源载体**:`.trae/rules/generic/coding-convention-rules.md` **§10「源码文本卫生」**(源码禁裸控制字节——工具链整体失明属通用编码约束,不落在 host-UI 技能)。
|
|
869
|
-
|
|
870
|
-
### Changed(工具批按 step 断段:思考换步即断段,工具块与思考块对齐)
|
|
871
|
-
|
|
872
|
-
**问题证据(真机)**:一轮连做 9 步,每步思考后调工具;因步骤之间无 `narrate`(也无其它可见分隔物),前后相邻工具之间**无任何打断物** → 宿主 `groupToolBatches` 判为一大段连续工具,合并成**一个「工具×23」大块**(锚在第 1 步首个工具),用户看不到「哪几个工具属于哪一步」。根因 = 切段判据的打断物只有 `{narrate, text_self_review, plan_item_boundary}`,而 `thought` 明确「穿插不断段」→ 模型不吐叙述时跨 step 工具之间无判据可断。
|
|
873
|
-
|
|
874
|
-
- **判据扩展(宿主 `chatView.ts` `groupToolBatches`)**:新增打断物「**新 step 的思考**」——`thought.stepIndex` ≠ 当前批所属 step 时断段。**同 step 的思考碎片不断段**(step 内伴随物);**无思考分隔的连续 step 工具维持相邻合并**(无可见分隔物即不切)。`currentStep` 取自开批 `tool_start.stepIndex` → 该字段由「零消费」转为真实消费方(解除僵尸键疑云)
|
|
875
|
-
- **反转 09-25 决议(显式)**:前置方案曾「否决按 step 分组」(理由=跨 step 连续工具正是要合并的对象)。本次反转——依据=思考分桶落地后「一步 = 思考 + 工具」成真机预期(前提变了,非原判错)。已在前置方案 §一 / §六 落反转注
|
|
876
|
-
- **不带伤定性**:改切段判据(`legacy-contract-audit-rules` §7 高风险动作)→ 带 ②可观测(切段矩阵用例)+ ③可退出(单函数回退,无 schema / 协议 / 落盘变更)+ ①可追溯(真机反馈)。五类带伤预检全过
|
|
877
|
-
- **内核零改动**:纯宿主渲染投影,`ProcessEvent` 契约与落盘结构不变
|
|
878
|
-
- **验证(变异闭合)**:宿主 `chatView.test.ts` **230 passed**(+3 新用例:步切换断段 / 同 step 不断段 / 无分隔合并);`chatView + chatPanelHistory` **277 passed**;临时关闭判据 → 恰 1 红,恢复后全绿;宿主 `tsc --noEmit` EXIT=0、`eslint --max-warnings 0` EXIT=0;术语门禁 code 65 / text 77 无漂移
|
|
879
|
-
- **文档同步**:新增 `docs/方案-工具批按step断段-20260926.md`(闭合闭环,先文档后代码);前置方案 `方案-工具批折叠合并-20260925.md` §一 / §六 加反转注
|
|
880
|
-
- **口径收口(09-26 续落 · 零行为变更)**:打断物集合由**散落重述**收敛为**具名唯一声明** `BATCH_SPLITTER_TYPES`(`chatView.ts`,他处只指路——散落重述正是误称反复传播的土壤);订正全程误称「**正文(text)**」→「**自审查输出**」(`text_self_review` **非**正文:主回答正文走内容轨 `chunk`、落盘不产过程事件)。它**不是**批间常态切口(自审查只在工具循环后终审一次),但**可达**(审查轮交付后排队插话续跑、续跑再调工具)→ **保留,非僵尸键**;订正范围含内核 `stepBoundary.test.ts` 的「两层判定同构」错误断言(chunk `text` 含 `answer` / `self_review` 两档,**非严格同构**)与归档源头行。验证:宿主 **230 passed** / 内核 `stepBoundary` **10 passed** / `tsc`、`eslint`、术语门禁 EXIT=0 / 切段矩阵变异捕红**恰 1 红**
|
|
881
|
-
- **观察登记**:`BATCH-SPLIT-1`(QA/交互输入行是可见分隔物却不参与切段 → 潜伏错序;触发驱动,见台账观察区)
|
|
882
|
-
|
|
883
|
-
### Added(工具批折叠合并 TOOL-RUN-1 · 方案 B 纯宿主 · 内核生产代码 0 改动)
|
|
884
|
-
|
|
885
|
-
- **webview**:`groupToolBatches()`(`chatView.ts`,与 `groupThoughtBuckets` 同层并列)把**相邻连续、无打断物**的工具条目合并为「批」块——打断物 = `narrate` / 自审查输出(落盘层 `text_self_review`,**非**正文)/ 任务项边界,`thought` 穿插不断段;块内按工具名小计(「读取文件×2 · 网络搜索×1」),块标题「第 N 批」(挂 STEP-ID-1 文案约定);失败 / 被拒工具留段内、块级标红。**三渲染上下文共用同一分组单点**(流式增量 / finalize 重建 / pending 行升级归段,禁内联三份);单工具批视觉等价现状,纯渲染投影 → 旧数据零兼容成本。
|
|
886
|
-
- **内核(仅测试)**:`stepBoundary.test.ts` 登记第 5 条不变量「**打断物不劈同一 step 的工具段**」(TOOL-RUN-1 前提固化,STEP-BUCKET-1 同范式:测试固化前提,不加防御分支)。
|
|
887
|
-
- **方案文档**:`docs/方案-工具批折叠合并-20260925.md`(三口径定案 + `toolBatch` 命名契约 + 不带伤五类预检单;内部文档不进 npm 发布包,故去链接化)。
|
|
888
|
-
- **验证**:宿主 682(+10)/ 内核 2792(+1);变异捕红 3 场——「`thought` 也打断」回退 → 2 红;工具段中插打断物 → 2 红(含「无任务表不产任务项边界」连带守卫双命中);「内联分组」模拟(单上下文分组分歧)→ 2 红(切段矩阵·thought 穿插 + 三上下文一致,恰中方案 §五 预期);`ci:local --preset=full` 12/12 全绿。
|
|
889
|
-
- **两处设计判定留档**:①过程流中间文本型打断物在落盘层的承载 = `text_self_review`(**自审查输出,非正文**——主回答正文走内容轨 `text` chunk,落盘不产过程事件;判据只读落盘数据以保「运行时所见 = 重放所见」);②`data-tool-batch` = 段 id 挂批容器,行级 `data-tool-call-id` 保留为 `tool_result` 配对键(非僵尸 key)。
|
|
890
|
-
|
|
891
|
-
### Changed(工具批叙述口径收口:全链路统一到工具显示名 + 取消「第 N 批」序号)
|
|
892
|
-
|
|
893
|
-
- **问题(实锤)**:TOOL-RUN-1 初版落地后,屏上同一个事实长出**两条形成路径**——轮收尾摘要按类别粗分(`countEvents` + `toolActionType`:「读取 2 · 搜索 1」),工具批标题按工具名计数(`getToolDisplayName`:「读取文件×2」)。同一次调用在屏上被叫成两种名字;两份相隔一天各自落地,**不是历史遗留而是并行生长** = 漂移起点。
|
|
894
|
-
- **收敛(两步)**:①抽 `toolSummaryText()` 为唯一叙述形成点、取消批序号(连带删掉 finalize / 流式**各自一份**的 `batchOrder` 递增计数,消灭「两份计数器必须同步」的隐患);②**统一词表到工具显示名**——轮摘要也改用工具名小计,类别词(读取 / 搜索 / 写入 / 运行)整套退役。
|
|
895
|
-
- **为何不留「概览 / 明细」两层**:轮=概览、批=明细看似合理,但同一动词两套中文名 = **两张映射表**,可按不同节奏更新(新增工具只补 `toolNameMap` 不补类别 → 立刻不一致)。一个词表后这类漂移不再可能。
|
|
896
|
-
- **连带清理**:`countEvents` 的分型字段(tools/reads/searches/writes/runs/others)随类别词退役后清零消费者 → 按「不用就删」删除,只留 `countReviews`(不做僵尸结构留存);`toolActionType` 职责收窄为「该工具能否进句」(`other` 类不可辨识 → 只计入 N、不占一段);顺带消掉一处 `as` 断言。
|
|
897
|
-
- **取消批序号**:批按事件相邻性切段,与 `stepIndex` **无单调对应**,「第 N 批」必然和「思考 · 第 N 步」互不对齐——那是 STEP-ID-1 想消灭的第二套编号换了个马甲。连带删掉 finalize / 流式**各自一份**的 `batchOrder` 递增计数(两份计数器必须同步 = 潜在双源),净简化。
|
|
898
|
-
- **取舍(如实记)**:代价是折叠态一行可能变长(`toolNameMap` 现 24 键 vs 原 4 类别)。**暂不加「超过 N 段折叠为其他」**——属猜测性复杂度,若真机观察到换行 / 挤压再按观察驱动补(D6 触发驱动)。
|
|
899
|
-
- **文档同步**:方案 §3.4 口径重写并留「2026-09-26 口径修订」档;`process-event-log-replay-design.md` 的 `tool_start` 行加**零消费方**标注。
|
|
900
|
-
- **措辞订正(历史条目不改写,在此留注)**:上上条「tool×step 交叉事实(同号对齐 / 按 step 统计工具用量)自此有据可查」把「数据可落盘」说成了「价值已兑现」——宿主 UI 至今**零读取** `tool_start.stepIndex`(工具批按相邻性切段,不按 step 归组)。应按 single-truth-source「预留键 vs 僵尸键」口径理解:真实消费方落地前它是**预留键**,不是已兑现能力。
|
|
901
|
-
- **验证**:变异验证闭合——改断言时 227 中恰 4 红 / 223 绿(零误伤)→ 改实现后 227 全绿;`tsc -p ./` 0 / eslint 0(改动文件);dist 产物含 `toolSummaryText`、`countToolTypes` / `toolBatchTotalsText` / `toolBatchTitleText` 零残留;`terminology:check` code 64 / text 76 无漂移。宿主全量另有 3 个 `rmSync` 钩子超时红,经隔离复跑与 IO 基准定性为**环境假红**(本机递归删 501 文件 99.6s ≫ 10s hook 上限;三套件与本次改动零引用链)。
|
|
902
|
-
|
|
903
|
-
### Fixed(宿主 · 脚本类写工具文件改动可视化闭环:执行前后 workspace 快照 diff 收口 + 恢复文案诚实化)
|
|
904
|
-
|
|
905
|
-
- **问题(DIFF-4 可视化半盲,本轮闭环)**:脚本类写工具(`run_code` / `run_skill_script` / `run_project_script`,内核标 `diskWrite:'opaque'`)目标路径**运行时才可知**,静态无法定位 ⇒ 不进宿主 `DISK_WRITE_TOOLS` 可视化(只含 `diskWrite:'path'` 工具)。用户看不到脚本改了哪些文件,无法确认/回退。内核写串行闸的 opaque 屏障**已防并行丢内容**,盲区只在宿主可见性,非内核写闸。
|
|
906
|
-
- **修法(运行时事实回报,非静态枚举;零新增状态面,不破内核边界)**:ext 进程在脚本类 `tool_start` 扫一遍 workspace 文本文件快照、`tool_result` 再扫一遍,`diffWorkspaceSnapshots(before, after)` 产出外部变更集(新增/修改/删除三类),经 `FileChangeSink.noteExternalMutations` 按路径合并进 `FileChangeTracker`(复用 `upsert` 单源逻辑,保留最早 `beforeContent`、writeCount+1)。脚本目标不可静态知 ⇒ 改以「执行前后目录快照 diff」这一**运行时事实**收口。排除 `node_modules`/`.git`/`dist`/`.memora` 等目录、跳过 >2MB 与含 NUL 的二进制文件。真源 = 内核 `OPAQUE_WRITE_TOOL_NAMES`(新导出 `src/index.ts`),宿主派生 `SCRIPT_WRITE_TOOLS`,**禁并列维护第二份脚本清单**(两份必漂移 = 脚本类改动静默不追踪)。
|
|
907
|
-
- **恢复文案诚实化(DIFF-1 标签语义漂移 #7 闭环)**:部分接受后 `beforeContent` 已被改写为「已接受基线」,文件级「恢复旧版」写的其实是基线而非 agent 介入前原文。标签统一改为「回退本文件改动」,提示文案改为「恢复到『你尚未接受的改动之前』的内容」,与 git `add -p` 模型自洽、消除误导。涉及 `fileChangeView.ts` 通知 / CodeLens / 状态栏 / 确认模态四处文案。
|
|
908
|
-
- **守卫(fileChangeTracker.test.ts +6 例)**:`diffWorkspaceSnapshots` 新增/修改/删除三类 + 空集;`noteExternalMutations` 脚本新建文件 / 与 `write_file` 合并保留最早 `beforeContent` / writeCount 累加 / 空变更集无影响。变异:`!==` 改 `===` → 恰 2 红(修改检测漏报被咬住),还原复绿。
|
|
909
|
-
- **验证(实测)**:宿主 `tsc --noEmit` = 0;`eslint --max-warnings 0` = 0;fileChange 相关定向 **48 passed**(含新增 6);变异精确红 / 还原绿。内核 `npm run build` 已成功(本轮导出 `OPAQUE_WRITE_TOOL_NAMES` 经 dist 供宿主 tsc 解析)。⚠️ **宿主 dist 未含本轮**(本环境 esbuild 在 `copyRolePacks` 结构性超时)→ 真机验收前必须 `npm run compile`
|
|
910
|
-
- **台账 DIFF-4 状态**:可视化半盲已闭环(2026-09-27)
|
|
911
|
-
|
|
912
|
-
### Fixed(宿主 · 脚本类快照扫描上限守卫:大仓库防卡死 extension host)
|
|
913
|
-
|
|
914
|
-
- **问题(本轮新加,吸收最新养分重判)**:上一轮落地「脚本类执行前后 workspace 快照 diff」时,`scanWorkspaceTextFiles` 用同步 `readdirSync`/`statSync`/`readFileSync` 全量扫描 workspace 文本文件存入 `Map<path,content>`。功能正确、盲区已闭环,但**在 extension host 用同步全扫**违反 VS Code 扩展性能准则(扩展 host 同步 IO 反模式);同步阻塞的是整个扩展进程(所有扩展卡),不止本面板。量级:memora 自身排除忽略目录后约 800–1500 文本文件、同步读 ~100–600ms(亚秒,非秒级);仅病理级大 monorepo(排除后仍数万源码)才数秒。属「建议级架构瑕疵」,非逻辑带伤。
|
|
915
|
-
- **修法(止血型上限守卫,只加退出条件、不造复杂度)**:`scanWorkspaceTextFiles` 遍历中累计 `totalBytes`/`fileCount`,任一超阈值(`SNAPSHOT_MAX_TOTAL_BYTES=64MB` / `SNAPSHOT_MAX_FILES=8000`)即中止递归、清空已收集内容、返回 `null`。调用方(`chatPanel` tool_start/tool_result 分支)据 `null` 降级:不存快照、不跑 diff,仅经既有低扰 `notice` 通道提示「工作区文本文件过多,脚本改动未自动追踪——请用 git 核对改动」。正常仓库仍走完整快照 + 逐文件「回退本文件改动」;仅大仓库放弃自动追踪、交 git 核对。阈值常量与扫描同文件,零新增状态面、不破内核边界。
|
|
916
|
-
- **守卫(chatPanelScriptSnapshot.test.ts +5 例)**:正常目录返回 Map(不降级)/ 总字节超 64MB 返回 null / 判据边界精确(64×1MB 不降级、65×1MB 降级)/ IGNORED_DIRS 不被扫描且不误触发降级 / 含 NUL 二进制跳过不计入(旧逻辑未破坏)。变异:`>` 改 `<` → 恰 4 红(正常/边界/IGNORED/NUL 全转红)、降级用例巧合仍绿,还原复绿——判据可达性钉死。⚠️ **用例规模后续下调(2026-09-28 实测订正)**:原「64×1MB 不降级 + 65×1MB 降级」要写 129MB、删 129 个文件,本容器删 ~200ms/个 ⇒ 光清理就远超默认 10s 钩子(全量并发下必红,但 **AssertionError 计数为 0**)。改为 **32×2MB = 恰好 64MB 不降级**(I/O 减半、语义等价;降级侧由既有「33×2MB → null」覆盖),并给边界用例与两个清理钩子显式超时——放宽的是**等待时间**,判据与断言一律不变。
|
|
917
|
-
- **验证(实测)**:宿主 `tsc --noEmit` = 0;宿主 `eslint --config eslint.config.mjs`(测试文件在 `ignores` 内不查)= 0;定向 **5 passed**;变异红→绿。
|
|
918
|
-
- **残留缺口(如实记,登记技术债)**:① 降级推 `notice` 的**集成守卫未做**(逻辑在私有 `consumeFlow` 内联,全路径集成测试成本高 + 本环境 `rmSync` 删 8001 文件超时假红风险);逻辑直白、tsc 已保障类型,留待补 `consumeFlow` 集成测试。② 文件数 8000 阈值降级**缺单测**(真实构造 8001 文件删除超时);与总字节降级共用 `aborted` 机制,边界测试已证明该机制咬住判据。③ 阈值 64MB/8000 为经验值,真机大仓库反馈后再调。
|
|
919
|
-
- **生效前提**:改动在宿主 `chatPanel.ts`,**宿主 dist 未含本轮**(本环境 esbuild 在 `copyRolePacks` 结构性超时)→ 真机验收前必须 `npm run compile`。
|
|
920
|
-
|
|
921
|
-
### Changed(宿主 · 文件改动对照回滚为 git 同款左右分栏 + 删掉行尾红色预览,2026-09-28 真机反馈)
|
|
922
|
-
|
|
923
|
-
- **回滚 1:「查看对比」回到 `vscode.diff` 左右分栏**(推翻 2026-09-27 的「上下统一视图」)。真机再测结论相反:**git 同款左右分栏更直观**。`openCompare` 恢复 `executeCommand('vscode.diff', 左, 右, 标题)`:左 = 旧内容虚拟文档(`memora-diff:`,不落盘),右 = **真实文件**(`file:`,可编辑);删除场景无真实文件可指 ⇒ 右侧给空虚拟文档。`existsSync` 导入与 `rightSeed` 随回滚恢复。⚠️ **布局仍由用户全局设置 `diffEditor.renderSideBySide` 决定**(默认左右),扩展不去改它——扩展 API 给不出「以 inline 布局打开」的入口,改布局 = 动用户设置或盲调切换型命令,皆属侵入。
|
|
924
|
-
- **连带删除**:`formatUnifiedDiff`(`fileChangeDiff.ts`)专为上下统一视图而生,形态回滚后零生产消费 ⇒ 连同 6 个单测删除(净减债,git 历史可溯)。
|
|
925
|
-
- **回滚 ≠ 回退修复**:体积闸「两侧长度都判」**保留**——旧版 `afterContent !== null && …` 的前缀会在删除场景短路放行(该缺口已修,本次不回退)。
|
|
926
|
-
- **回滚 2:删掉行尾常驻的红色旧内容预览**(`INLINE_OLD_TEXT_STYLE` / `inlinePreview`,即 hunk 首行行尾那行红色删除线「⟵ 原: …」)。真机反馈:与 hover 说的是同一件事却长期占版面 = **视觉噪音**。**hover 保留**(旧内容只在内存里,hover 是用户看它的唯一入口);并排看新旧走「查看对比」。
|
|
927
|
-
- **守卫(fileChangeView.test.ts)**:对照形态 3 条(走 `vscode.diff`/左栏是虚拟文档且正文为改动前原文、**不带** -/+ 前缀/标题带相对路径)+右栏真实文件 1 条(另开真实临时目录——判据含 `existsSync`,内存 mock 下恒为「文件不存在」,只能走到空虚拟文档分支)+装饰不挂 `renderOptions` 1 条+体积闸 2 条(删除大文件跳过/小文件不误伤)。
|
|
928
|
-
- **变异验证 2 组**:① 把行尾预览加回 → **1 红**(装饰守卫);② 把 `openCompare` 改回上下视图(`showTextDocument`)→ **5 红**(形态守卫)。两组都**红在断言本体**:等待条件刻意不绑死形态(绑死则变异先超时、守卫根本跑不到)。
|
|
929
|
-
- **验证(实测)**:宿主 `tsc --noEmit -p ./` = 0;`eslint --config eslint.config.mjs`(改动源码文件)= 0;fileChange 两套件 **67 passed**(fileChangeView 32 + fileChangeDiff 35);变异红→绿。
|
|
930
|
-
- **文档同步**:`docs/方案-文件改动diff可视化-20260926.md` 加 §11.13 回滚注记;`docs/方案-文件改动分块呈现与块级动作-20260927.md` §8.7 第 2 条划线订正 + 新增 §8.8(历史正文不重写,只加注记)。
|
|
931
|
-
- **生效前提**:改动在宿主 `fileChangeView.ts` / `fileChangeDiff.ts`,**宿主 dist 未含本轮**(本环境 esbuild 在 `copyRolePacks` 结构性超时)→ 真机验收前必须 `npm run compile`。
|
|
932
|
-
|
|
933
|
-
### Fixed(宿主 · diff 模块复盘收口:文案口径单源 + 文档/台账失真订正 + 规则补第 8 层)
|
|
934
|
-
|
|
935
|
-
真机通过后的对抗式复盘(判据 = `.trae/rules/generic/legacy-contract-audit-rules.md` §2/§3/§3.3/§4):**代码侧不带伤、不违 SSOT**(§2 三条判别与 §3 五类带伤全不命中),问题全在「描述层」——形态回滚后描述没跟上代码。本段是这些问题的收口。
|
|
936
|
-
|
|
937
|
-
- **文案口径单源(口径带伤 → 已修)**:同一动作两个名字——通知按钮叫「查看对比」、QuickPick 与状态栏悬停叫「打开对比」。已统一并抽为常量 `COMPARE_LABEL`(`fileChangeView.ts`),三处入口(通知按钮 / QuickPick 项 / 状态栏 tooltip)**同一真源**,禁各自写字面量(字面量散落正是本次漂移的成因)。`$(diff)` 图标前缀属装饰、不并入措辞。
|
|
938
|
-
- **台账失真(最致命 · 已修)**:`tasks/待完成任务.md` DIFF-1 的**销项验收标准**写「对照页是否单列上下排列」,而该形态已回滚 ⇒ 照单验收会把刚通过真机的左右分栏**判成不合格**;同批 DIFF-6 行仍描述已删的 `formatUnifiedDiff`。均已订正。
|
|
939
|
-
- **docs 失真(已修)**:`可视化-20260926.md` 的「落地形态」表仍写行尾 `⟵ 原: …`(已删)与「每 hunk 上方 2 个 CodeLens」(09-27 已改),其「人工验收清单」第③⑤条同样失真;`分块呈现-20260927.md` 实证表加「当时现状」注记。
|
|
940
|
-
- **规则补第 8 层(新增判据,带观测 + 退出条件)**:§3.3 退役概念回扫清单原 7 层**漏了 `tasks/` 台账**——台账是验收标准的落点,失真比 docs 更致命。已补为第 8 层,并写明观测依据(本条 DIFF-1 实证)与退出条件(台账不再承载验收标准即可删)。
|
|
941
|
-
- **补守卫(隐私承诺)**:回滚后一条记录占**两个**虚拟 URI(左 = 旧内容、右 = 删除场景空文档),而上下视图只占一个 ⇒ `releaseVirtual` 漏清任一即违反「旧内容零落盘、可释放」。新增 1 例钉**非空**的左栏;变异(删掉左栏那行 `delete`)→ **恰 1 红**,还原复绿。
|
|
942
|
-
- **观测边界(如实记,不写假绿断言)**:右栏在删除场景是**空串**虚拟文档,而 provider 读路径是 `get(...) ?? ''` ⇒「已建立但为空」与「已释放」**返回同形** ⇒ 空串那一栏的释放**不可观测**。故不为它编恒真断言;空串侧靠同一段代码对称保证。
|
|
943
|
-
- **DIFF-7 登记(已知残留,触发驱动,不预支)**:右栏是真实文件(对齐 git 同款 ⇒ 可编辑)。用户在对比页手改并**保存**后文档不再 `isDirty` ⇒ 点「回退本文件改动」**无任何提示、直接整体覆盖**(未保存编辑有模态确认 ✅,已保存的没有 ❌)。与 git `discard` 语义同构 ⇒ **非带伤**,但属静默数据丢失面。触发:真实出现「我自己改过、点回退被吞」的反馈 ⇒ 把「文档内容 ≠ `afterContent`」纳入与 dirty 同级确认通道(约 1 判定 + 1 文案)。
|
|
944
|
-
- **自纠(本轮差点造的假注释)**:初稿把上述风险写成「已明确告知」——**不实**:模态文案只在 dirty 分支出现。已改为如实描述并同步登记台账。
|
|
945
|
-
- **验证(实测)**:宿主 `tsc --noEmit -p ./` = 0;`eslint --config eslint.config.mjs` = 0;fileChange 三套件 **88 passed**。
|
|
946
|
-
|
|
947
|
-
## [3.0.1] · 2026-09-30
|
|
948
|
-
|
|
949
|
-
### Changed(开源归口翻转:GitHub 升主仓库)
|
|
950
|
-
|
|
951
|
-
- **README / README.en**:反馈、宿主项目链接、ADR 位置共 6 处归口从 Gitee 翻转为 GitHub 主仓库(Gitee 降为同步镜像,保留国内访问提及)
|
|
952
|
-
- **package.json**:`repository` / `homepage` / `bugs` 指向 `github.com/zooique/memora`(npm 页面导流、dependents 与搜索入口随 GitHub 生态)
|
|
953
|
-
|
|
954
|
-
> 纯元数据与文档归口变更,`dist` 产物与 3.0.0 无差异。
|
|
955
|
-
|
|
956
|
-
## [3.0.0] · 2026-09-30
|
|
957
|
-
|
|
958
|
-
### Added(内核+宿主 · 截断救回计数 truncationRecoveryCount:换策略重试效力的观测面 + 文案口径订正)
|
|
959
|
-
|
|
960
|
-
**背景(EMPTY-RESP-R1,T1–T5 收官复审缺口)**:T2 换策略重试**成功救回**的轮落盘无任何「曾发生截断」痕迹(`empty_response` 证据只在最终仍空时落)⇒ 台账「T2 reasoning_effort 真机验证」观察项**结构上验不了**(无法从 round 文件确认救回发生过)。本条补观测面,同批捎带复审发现的文案 off-by-one 与两处注释口径漂移。
|
|
961
|
-
|
|
962
|
-
- **`truncationRecoveryCount` 诚实信号**(与 `emptyResponseCount` 互补镜像):llmCaller 空响应收场点判「曾截断换策略(`truncatedRetry`)+ 收场非空」→ 计数 +1(每 call 恒 ≤1);早退路径(degrade 降级文案 / 抛错 / aborted)不计入——降级文本非模型产出。链路同 `emptyResponseCount` 先例:`LoopMetrics` → `AgentMetrics.llm` → `ProcessMetricsPayload`(选填、旧数据缺省)→ 宿主流尾 diff 本轮增量 → chatView「截断重试救回:N 次」指标行(**观测信号不参与成功否决**——救回轮正文是真实模型产出,与 `emptyResponseCount` 语义相反)
|
|
963
|
-
- **文案 off-by-one 订正**:截断兜底文案「已自动**重试** N 次」传入的实为**尝试总数**(1 首试 + N 重试,恒多报 1)→ 中英双文案统一「尝试 N 次」口径(`empty after N attempts` / 「已自动尝试 N 次仍为空」),`UIMessages` jsdoc 钉死口径防改回
|
|
964
|
-
- **注释口径订正(HOST-S11 同族注释漂移)**:meta 取证包 `reasoningEffort` 原注释「与内核 llmCaller 转达口径同源」已被 T2 打破(`'low'` 有策略键 manual / `truncatedRetry` 运行时置入**两条**发送路径,meta 只镜像配置面)→ 改述「流首**配置面**快照,实际发送面以 `truncationRecoveryCount` 佐证」(chatPanel + roundStore 两处);`foldThoughtEvents` jsdoc 补**前提不变量**(seq 幂等依赖「检查点只在 step 边界触发」,破坏即静默丢内容——T4-FOLD-1 修法 A)
|
|
965
|
-
- **测试**:llmCaller 救回计数正反面(救回 +1 / 截断耗尽·瞬态救回·正常产出均 0)+ metrics 出闸守卫(镜像 `pairingGuardFires` 先例:只自增不外露 = 僵尸计数)+ roundEvidence 默认文案口径守卫(禁写 `retried N`)+ chatView 指标行/缺省面 2 例。**变异 4 方向**(摘计数行 / 去 `truncatedRetry` 条件致瞬态误计 / 摘指标行 / 文案改回 off-by-one)各恰红 → 恢复复绿。门禁:内核 `typecheck` / `eslint` 0 / 全量 **2830 passed | 4 skipped**、宿主 `tsc` / `eslint` 0 / 全量 **835 passed | 2 skipped**、format 0、`terminology:check` 零漂移(测试游标命名蹭了 step 族载体被门禁拦下,改 cursor 前缀消漂移)
|
|
966
|
-
- **真机复核收口(2026-09-29 · 小说项目)**:用户配置 maxTokens=64K 后连跑 2 轮(round-1790686368607 / round-1790686698903)——meta 取证包 `maxTokens: 64000`(T1 配置链路端到端实证);round-...6368607 `truncationRecoveryCount: 1`(真机截断被换策略重试**实战救活**,收场真实正文——T2 效力实证);两轮 `emptyResponseCount: 0`;round 文件 26KB / 37KB < 200KB(T4 折叠真机复核过)。T2 真机验证清单三件全答(组合策略有效 / 尾部注入被中转接受 / 救回计数可读),`EMPTY-RESP-1` 观察行核销(收据:`tasks/archive/completed-history.md` 2026-09-29 收口条)
|
|
967
|
-
|
|
968
|
-
### Fixed(内核 · maxTokens 上限不再静默丢弃:上限不裁决,交服务端可见报错)
|
|
969
|
-
|
|
970
|
-
**问题(哲学不对称 · 跨包镜像同源)**:`normalizeMaxTokens`(请求参数归一)原对 `maxTokens` 做 1–65536 区间裁决、超限**静默丢弃**(不传 `max_tokens`)——与同申请书参数 `contextWindow` 的既有裁决(`resolveContextWindow` 只做 undefined 回落默认、**不裁决区间**)不对称;且逼出宿主护栏**跨包数值复制**(宿主无法 import 内核私有常量,只能注释对齐 65536)——单侧漂移即重现「UI 显示值 ≠ 真实生效值」(护栏本要防的坑)。对第三方 npm 集成方是结构性考题:内核只要保留静默丢弃,集成方护栏无论松紧都难根治。
|
|
971
|
-
|
|
972
|
-
- **修法**:`normalizeMaxTokens` 只做**形态防御**(非数值 / 非有限 / <1 → undefined 不传,回服务端默认;正整数 floor 透传);**上限不裁决**(有意为之,注释钉死「勿加回」)。超模型能力的值原样进请求体,由服务端**可见报错**——本地任何一层静默替换都造「显示 ≠ 生效」的坑(与 contextWindow 同哲学)
|
|
973
|
-
- **宿主护栏定位重写(零行为变更)**:`providerStore.MAX_TOKENS_MAX = 65_536` 由「对齐内核」改述为**独立 sanity**(宿主是输入边界的唯一可见裁决点,只防手滑;真实上限由模型/API 决定)。UI 行为不变(仍 1–65536 可见拒绝)。跨包数值镜像由此消除,§7 登记不再必要
|
|
974
|
-
- **验证(变异双端)**:上限裁决加回 → 恰 1 红(70_000 被吞);形态防御去掉 → 恰 1 红(-5 透传);均还原复绿。门禁:内核 `typecheck` / `eslint` 0 / 全量 **2824 passed | 4 skipped**;宿主 `typecheck` / `eslint` 0 / 全量 **826 passed | 2 skipped**
|
|
975
|
-
- **文档清算**:`tasks/审查-空响应根因排雷与优化方案-20260929.md` §五 T1 行与「依赖与边界」两处过时表述修订(原文「护栏对齐 normalizeMaxTokens / 越界→undefined」已不成立)
|
|
976
|
-
|
|
977
|
-
### Changed(宿主 · thought 落盘按 step 聚合折叠:信封开销收敛)
|
|
978
|
-
|
|
979
|
-
**背景(EMPTY-RESP-1 · T4 · 附带观察销项)**:真机单轮 round 文件 1.37MB(7461 事件中 thought 占 99%)——主因是碎片**信封开销**(每条 seq/ts/type/payload 键)而非思考正文(正文约 67KB)。本条落盘前按 step 把碎片折成批次(排雷与方案见 `tasks/审查-空响应根因排雷与优化方案-20260929.md`)。
|
|
980
|
-
|
|
981
|
-
- **foldThoughtEvents**(纯函数,chatPanel 导出):同 stepIndex **相邻** thought 碎片合并为 ≤`MAX_THOUGHT_PAYLOAD_LENGTH` 批次事件——内容零损失(满批开新批,不二次截断)、seq/ts 取首碎片(同输入恒同结果,与 `mergeProcessEvents` 的 seq 去重幂等兼容)、**UI 流式不变**(emitEvent 逐碎片投影不动;重放渲染无差——webview 本就按 stepIndex 把连续碎片聚成折叠块,批次边界恰是其归桶边界)
|
|
982
|
-
- **接线**:`checkpointRound` 单点折叠(step 边界检查点 + 流尾终局两条落盘路径全覆盖)。估算真机场景信封数 7461 → ~20,round 文件约 70KB(验收线 <200KB;最终以真机观察复核)
|
|
983
|
-
- **测试**:foldThoughtEvents 3 例(同 step 合批 / 超限分批内容零丢失 / 异 step·隔断不合并)+ checkpointRound 调用点集成钉(3 碎片 → 落盘恰 1 条);变异 3 方向(不折叠 / 无分批上限 / 跨 step 合并)各恰红 → 恢复复绿。门禁:宿主 `typecheck` / `eslint` 0 / 全量 **833 passed | 2 skipped**(内核零改动,沿用 **2827**);`terminology:check` 零漂移
|
|
984
|
-
|
|
985
|
-
### Added(内核+宿主 · T5 取证与引导收尾:ALREADY_READ 条件引导句 + meta 关键调用参数包)
|
|
986
|
-
|
|
987
|
-
**背景(EMPTY-RESP-1 · T5)**:真机异常破案靠截图/口问(调用参数不可见);`ALREADY_READ` 替身回显不引导「引用已有原文」致 LLM 绕道写脚本(ALREADY-READ-1)。本条落地(排雷与方案见 `tasks/审查-空响应根因排雷与优化方案-20260929.md`)。
|
|
988
|
-
|
|
989
|
-
- **ALREADY_READ 引导句(对方案原句的规格订正)**:`formatLedgerStub` 补「**若原文仍在**本次对话上文,可直接引用」——方案原句「原文已在本次对话上文」是断言语气,与该函数 jsdoc 约束直接冲突(两语境共用:压缩链替换后原文已不在上文,断言即撒谎;既有真实性守卫 `not.toContain('被压缩')` 同族),故改**条件语气**(两语境皆真)+ 新增守卫断言禁改回断言
|
|
990
|
-
- **meta 取证包**:`ProcessMetaPayload` 扩四选填字段 `{ contextWindow, maxTokens, reasoningEffort, providerKind }`(role/llm 既有)——每轮 meta 自带关键调用参数面。宿主 `buildRoundMeta`(流首取激活 Provider 配置快照):contextWindow 取 `resolveContextWindow` 生效值(非裸透传)、maxTokens 取 per-LLM 配置(缺省=服务端默认不入包)、reasoningEffort 由策略键 `multiStepReasoning='manual'` 派生 'low'(与内核 llmCaller 转达口径同源,未发送即缺省)、providerKind 恒 'openai-compatible'(内核工厂唯一适配器形态,前向字段)
|
|
991
|
-
- **测试**:toolLedger 真实性守卫增强 + chatPanelHistory `buildRoundMeta` 2 例;变异 4 方向(断言语气 / 派生恒 'low' / contextWindow 裸透传 / 摘 providerKind)各恰红 → 恢复复绿。门禁:内核 `typecheck` / `eslint` 0 / 全量 **2827 passed | 4 skipped**;宿主 `typecheck` / `eslint` 0 / 全量 **829 passed | 2 skipped**
|
|
992
|
-
|
|
993
|
-
### Added(内核 · 截断型空响应换策略重试:降思考 + 纠正提示双轨)
|
|
994
|
-
|
|
995
|
-
**背景(EMPTY-RESP-1 · T2)**:同参重试对确定性截断无效(真机 3 连空、5 分钟白烧)——thinking 吃满输出预算后原参重发必然再炸。本条让截断型在**迭代内部**被救回(依赖 T3 的 finishReason 消费约定;排雷与方案见 `tasks/审查-空响应根因排雷与优化方案-20260929.md`)。
|
|
996
|
-
|
|
997
|
-
- **截断判定**:llmCaller 空响应分支消费末次 `finishReason='length'` = 截断型 → 换策略重试(粘性至收场);无 finishReason(中转不回传)= 瞬态型 → 维持同参重试(降级不劣化)
|
|
998
|
-
- **双轨策略**:① `effectiveOpts.reasoning_effort='low'`(复用 `multiStepReasoning='manual'` 既有转达通道,provider 支持才生效);② 纠正提示「上一次回复因思考耗尽输出预算被截断,请直接给出结论或工具调用」注入消息尾(`TRUNCATION_RECOVERY_HINT` 内联常量——协议级模型指令,非 UI 文案不进 UIMessages)——**每请求恰一条**:requestMessages 每次从 safeMessages 重建、提示不进历史,多轮重试恒 1 条(一次性 = 不堆叠,非只注首次)
|
|
999
|
-
- **测试**:2 例(换策略救回 + 双轨断言 / 粘性 + 恒 1 条不堆叠),mock 救回行为与双轨耦合——变异 2 方向(判定 `'length'`→`'stop'` / 摘提示注入)各恰红(「去策略则仍空」实证)→ 恢复复绿。门禁:内核 `typecheck` / `eslint` 0 / 全量 **2827 passed | 4 skipped**(宿主零改动,沿用上批 827)
|
|
1000
|
-
|
|
1001
|
-
### Added(内核+宿主 · 空响应诊断分型:证据三字段 + 兜底文案分型 + metrics 诚实信号)
|
|
1002
|
-
|
|
1003
|
-
**背景(EMPTY-RESP-1 · T3)**:真机空响应轮(round-1790649685702)暴露「截断型与瞬态型混为一谈」——finishReason 流层已透传但消费端未用、兜底文案单一无诊断、metrics 把兜底轮记成 `success:true`。本条落地诊断分型(排雷与方案见 `tasks/审查-空响应根因排雷与优化方案-20260929.md`)。
|
|
1004
|
-
|
|
1005
|
-
- **证据三字段**:`empty_response` 证据 payload 补 `{ finishReason, thinkingChars, attempts }`——llmCaller 逐 chunk 采集(finish_reason 末条覆盖、thinking 增量累计,重试重置取**末次尝试口径**)→ `LlmCallResult` 透传 → loop 落盘;`attempts` = 收场前 chat 尝试总数(空响应重试属**同一步内**多次尝试,step 术语红线不破)
|
|
1006
|
-
- **文案分型**:`UIMessages.emptyResponseFallbackTruncated(attempts)` 新键——末次 `finishReason='length'` 判截断型 →「模型思考过长耗尽输出预算,已自动重试 N 次——建议调大模型输出上限」(宿主中文覆盖,内核默认英文);无 finishReason(中转不回传)按瞬态型降级,维持现状文案不劣化
|
|
1007
|
-
- **metrics 诚实信号**:`ProcessMetricsPayload.emptyResponseCount`(可选、旧数据缺省,镜像 `unparsedToolIntentCount` 模式)——**不动 `success`**(其语义是「流程跑完没有」,空响应轮正常收场;置 false 会把「流程未完」与「产出不合格」压进一个布尔);宿主 chatPanel 流尾 diff 取本轮增量,chatView `finalSuccess` 合成 +「空响应兜底 N 次」指标行
|
|
1008
|
-
- **测试**:roundEvidence 2 例(瞬态/截断分型 + 末次口径 7≠15)+ llmCaller 三字段 + chatView 展示合成;变异 4 方向(分型判据 `'length'`→`'stop'` / thinkingChars 重置摘除 / `finalSuccess` 摘 `emptyResp` / 证据 payload 摘 `attempts`)各恰红 → 恢复复绿。门禁:内核 `typecheck` / `eslint` 0 / 全量 **2825 passed | 4 skipped**;宿主 `typecheck` / `eslint` 0 / 全量 **827 passed | 2 skipped**
|
|
1009
|
-
|
|
1010
|
-
### Added(内核 · `AgentOptions.maxTokens` 输出预算透传链 + 热切换)
|
|
1011
|
-
|
|
1012
|
-
**背景(EMPTY-RESP-1 根治)**:推理模型 thinking 与正文共享输出预算,无显式 `max_tokens` 时 thinking 吃满服务端默认 → 正文被挤空(空响应)。本条补齐配置向根治链(排雷与方案见 `tasks/审查-空响应根因排雷与优化方案-20260929.md`)。
|
|
1013
|
-
|
|
1014
|
-
- **内核**:`AgentOptions` 新增 `maxTokens` → assembler 解构 → loop 持有 `defaultMaxTokens` → `buildChatOptions` 填底座(角色包 `chatOptions` 可覆盖,优先级:角色包 > per-LLM 默认);`setMaxTokens` 热切换配套
|
|
1015
|
-
- **宿主**:配置面板新增「输出上限 (K)」(K = ×1000 口径,`TOKENS_PER_K` 单一真理源;厂商口径自相矛盾——gpt-4o 同卡混用 128,000/16,384、Claude 3.7 输出上限 64,000 十进制——按误差方向安全性裁决:×1000 低估优雅降级、×1024 高估有 400 硬风险)→ `LlmProviderConfig.maxTokens` → assemble → AgentOptions;providerStore 护栏 + chatPanel 热同步
|
|
1016
|
-
- **请求层归一**:`normalizeMaxTokens` 唯一收口;**归一语义后经上方 Fixed 条(2026-09-29)收敛**——只做形态防御、上限不裁决(本条落地时的 1–65536 越界裁决不再保留)
|
|
1017
|
-
- **测试**:内核 loop 新增 4 例 + 变异验证(摘注入 → 恰红 → 恢复复绿);宿主 configView / settingsView / providerStore 全绿;两侧 `tsc` / `eslint` 0 错
|
|
1018
|
-
|
|
1019
|
-
### Added(内核 · write_file 新增 `replace` 精确串替换 + mode 枚举双源收敛)
|
|
1020
|
-
|
|
1021
|
-
**问题(两项)**:① `write_file` 只有 overwrite/append/insert——大文件改一处局部时,模型手上没有整份内容(读不全),只能 overwrite 全量重写硬凑、或退回大量 append/insert 拼接,token 与出错面双高;② `mode` 枚举**双源并列**:schema 描述(`builtinTools.ts`)与 handler 校验清单(`builtinToolHandlers.ts`)各写一份,漏改一处即「描述允许而校验拒绝」的静默漂移(与 TASKTABLE-NAME-1 同族)。
|
|
1022
|
-
|
|
1023
|
-
- **收敛(SSOT)**:`builtinTools.WRITE_FILE_MODES` 作单一真理源(枚举 + 简介表);schema 描述与 handler `validModes` 均从它派生,工具描述里的模式数量也由 `length` 派生(不写死「三种」)⇒ 新增模式只改一处
|
|
1024
|
-
- **原语**:新增 `mode=replace`,配 `old_string`(须在文件中**唯一**出现)——只替换命中片段、不动其余。**匹配不到 → 报错**(禁静默 no-op);**多处匹配 → 报错**要求补足上下文,**不做 replace_all**(改错地方毁代码 > 让模型多试一次,与 `toolResultCache` 同哲学);目标文件不存在 → `FILE_NOT_FOUND`(新文件走 overwrite)
|
|
1025
|
-
- **零额外接线的自动对齐(本方案最省事处)**:`diskWrite:'path'` 派生 ⇒ replace 自动进同 step 写串行闸(`WRITE_PATH_EXTRACTORS`);`WriteExtensions.onBeforeWrite` 无条件调用 ⇒ 自动被已落地的 diff 可视化捕获;`invalidateFile` 按路径失效读缓存 ⇒ replace 自动作废旧读缓存
|
|
1026
|
-
- **描述引导**:`write_file` 描述改为「改局部优先 replace(无需持有整份文件);大文件没有完整内容无法 overwrite;文末追加 append / 单点插入 insert;只有新建或结构性多处重写才 overwrite」
|
|
1027
|
-
- **SSOT 问诊 · 炼化归元(同族静默回落 2 处,顺手收口)**:① 结果标签 `modeLabel` 原以 `: '精确替换'` 作三元链**隐式兜底** ⇒ 未来新增模式会被静默标成「精确替换」,改为显式 `replace` 分支 + `default: mode` 如实回显;② `computeWriteContent` 原 `default: return content` 会在模式表与本 switch 脱节时**静默按 overwrite 落盘**(假阴性)⇒ 改抛 `ARGUMENT_ERROR` 响亮失败。两处均属「静默回落 = 缺陷行为」同族
|
|
1028
|
-
- **验证**:handler `replace` 6 例(唯一匹配成功 / 未匹配报错且文件不变 / 多处报错且文件不变 / 新文件 FILE_NOT_FOUND / 缺 old_string ARGUMENT_ERROR / `onBeforeWrite` 收到替换前后完整内容)+ `builtinTools` 补「mode 描述与 `WRITE_FILE_MODES` 同源」守卫(防描述退回手工硬编码)。门禁:`typecheck` 0 / `eslint` 0 / `format:check` 0 / `docs:links` 0 / `rules:refs` 0 / `terminology:check` 0 / 全量 **2820 passed | 4 skipped**
|
|
1029
|
-
- **顺带对齐**:宿主 `fileChangeTracker.ts` 注释模式清单与 `docs/memora-api-reference.md` 工具表补 `replace` / `old_string`(描述层跟随,无行为变更)
|
|
1030
|
-
|
|
1031
|
-
### Fixed(内核 · 读取防重回显文案诚实化:删「原文已在流程中被压缩」状态断言)
|
|
1032
|
-
|
|
1033
|
-
**问题**:`formatLedgerStub`(台账替身文案)被两个语境共用——① 压缩链把 read_file 结果**原位替换**为台账摘要(loop 装配 `readFileReplacement`);② LLM 变体/同参重读被分支②拦截时的**回显**。文案写死「原文已在流程中被压缩」:压缩语境为真,但回显语境原文可能仍在上下文(变体重读不经 L2 精确判重的「仍在上下文」前提)⇒ **文案撒谎**——guardRail 防死锁前提(「告知基于已有 = 指令撒谎」)的同型问题在台账分支复现。
|
|
1034
|
-
|
|
1035
|
-
- **修法**:删状态断言,只陈述两语境皆真的事实(读过 / 覆盖区间 / 要点 / 续读出路);SSOT 不破(两语境仍共用一个 formatter,文档注释钉死「不得内嵌单语境状态断言」)
|
|
1036
|
-
- **验证**:守卫 `not.toContain('被压缩')`(二字根,咬住「已被压缩 / 已在流程中被压缩」一切改写回潮)+ **变异实弹**:子句回潮 → 恰 1 红(红在断言本体)→ 还原复绿。(守卫针头首版误写「已被压缩」——非真实字面的子串、恒绿咬不到人,排雷实证后与文案一并修正、变异补做通过)
|
|
1037
|
-
|
|
1038
|
-
### Fixed(内核 · 读取防重续读死结:无 limit 续读被台账分支②误拦)
|
|
1039
|
-
|
|
1040
|
-
**问题(可用性级 · 大文件必然触发)**:`shouldEchoLedgerStub`(分支②判定的单一真理源)原判据「无 limit 请求一律拦」只看了 limit 有无、未看 offset 落点。而 `offset=N` 不带 limit 的 handler 语义是「从 N 读到文件末尾」——**合法续读**。后果:文件被单次读取预算(`SINGLE_TOOL_RESULT_MAX_TOKENS` 5900,约 300–500 行)截断后,模型照分段脚注与拦截文案给出的写法(二者均为 `offset=coverEnd+1`、均不带 limit)续读,**会被同一条判据再次拦下** ⇒ 拦据与引导互为死结,memora 体量的大文件(如 `loop.ts` 约 4000 行,需约 10 次续读)永远读不到第二段。登记行「ADR-031 补缝过度拦截候选」的原始假设(「全文比对」类任务被迫绕路)由此**代码级实锤**——且成因比设想的更硬,非仅「摘要替身信息不足」。
|
|
1041
|
-
|
|
1042
|
-
- **修法(判据面,非场景特判)**:无 limit 分支改按 offset 落点判定——`(offset ?? 1) <= coverEnd` → 拦(起点落在已覆盖区间内,含省略 offset 的整读;截断后返回的仍是同一段已读头部);起点超出覆盖区间 → 放行(真续读,恰是引导给出的那一步)。`limit` 变体整读与区间续读两条既有判据不动。
|
|
1043
|
-
- **先红后绿(实证,非推理)**:探针复现旧行为下 `offset=401`(台账覆盖 1–400)判 `true`;原用例 `expect({ offset: 100 }).toBe(true)` 即**把该 bug 固化成期望**,一并订正为「整读拦 / 续读放行」两条。
|
|
1044
|
-
- **验证(变异双端)**:**变异 A**(判据还原旧行为「一律拦」)→ 恰 1 红、**恰红在续读放行断言本体**;**变异 B**(改「全放行」)→ 恰 1 红、红在整读拦断言 ⇒ 两端都真在咬人,均还原复绿。`typecheck` 0 / `eslint` 0 / `format:check` 0 / 全量 **2813 passed | 4 skipped**。
|
|
1045
|
-
- **未闭合(如实记)**:本修只解「无 limit 续读」这一成因;`ADR-031 补缝`(整读小文件记全覆盖)本身未动,§7 该登记行维持观察其余面向。
|
|
1046
|
-
|
|
1047
|
-
### Fixed(内核 · 读取防重证据字段面镜像收敛:三处手工枚举 → 一处定义 + 一处透传)
|
|
1048
|
-
|
|
1049
|
-
**问题**:`DedupSubject`(去重主体,形状真源 = `toolResultCache`)字段面被**三处手工枚举**——类型定义 ↔ loop 侧证据落盘逐字段展开 ↔ roundStore `read_dedup_block` payload。因 `memory → agent` **类型禁向**(真源 `.trae/rules/backend_layers_rules.md`,不随包故不作链接),roundStore 无法 import 该类型,只能人肉抄字段清单 ⇒ `DedupSubject` 增字段时另两处**静默漏采**(探针丢定位字段,逐案裁决无米下锅)。
|
|
1050
|
-
|
|
1051
|
-
- **修法(第三路,非登记时列的两路)**:loop 侧 `payload: { toolName, ...dedupSubject }` 整体 spread 透传(不再逐字段 `x !== undefined ? { x } : {}`);roundStore payload 改**开放式索引签名** `[dedupField: string]: string | number | undefined` **停止枚举**。镜像由此降为「一处定义(`DedupSubject`)+ 一处透传」,两侧零同步。**为何不走原两路**:下沉共享层 = 新增单元(违最小单元);`Record<keyof DedupSubject, …>` 编译期对拍仍要求 roundStore 侧知道字段清单 = 镜像未除。
|
|
1052
|
-
- **契约等价(实证)**:落盘 JSON 形状**不变**(`undefined` 值由 `JSON.stringify` 自然丢弃);`read_dedup_block` 全库**零代码消费**(grep 仅命中类型定义、落盘点与登记文档);`memory → agent` 类型禁向未破。
|
|
1053
|
-
- **验证**:`typecheck` 0 / `eslint` 0 / `format:check` 0 / `rules:refs` 0(闸门自检 8/8 + 裸路径引用全可解析)/ 全量 **2813 passed | 4 skipped**。`legacy-contract-audit-rules.md` §7「读取防重证据字段镜像」登记行 → **收敛(结案)**。
|
|
1054
|
-
|
|
1055
|
-
### Added(内核 · read_dedup 撞墙升级 + 兜底观测 + 读后即记引导)
|
|
1056
|
-
|
|
1057
|
-
- **撞墙升级**:同一读取主体被 `read_dedup` 硬拦 2 次后,第 3 次命中起文案升级为强禁令(`[ALREADY_READ] 你已第 {count} 次尝试重复获取…`)。出口引导收敛 `{tail}` 单源按主体分流:read_file 给 offset/limit 续读出口,非文件主体(query/url/会话等)不给——单语境断言不内嵌共用文案;另加 `search_memories` 记忆检索。阈值 `READ_DEDUP_ESCALATE_THRESHOLD = 2`(用户裁决 2026-09-28:第 2 次即升级太激进、第 3 次合适);计数经 `GuardRail.notifyBlocked` **拦截归属回喂**(新钩子 `onBlocked`)喂数——`onExec` 只知「被某种护栏拦」,台账替身回显等非本护栏拦截不会误计;随 `reset('perTurn')` 轮界归零
|
|
1058
|
-
- **兜底观测**:`readDedupBlockCount` 指标(`LoopMetrics` / `AgentMetrics.tools` / tracer 透传)+ `read_dedup_block` 裁决证据(`RoundEvidenceEvent` 新变体,含 toolName + 去重主体字段)——判「模型乒乓」vs「合理重读被误拦」的量化基线,与 `ledgerStubEchoCount`(L3 变体顶替)互补;证据字段面三处镜像已登记 `legacy-contract-audit-rules.md` §7 待验证候选(**该镜像已于同版收敛结案**,见上方 Fixed 条)
|
|
1059
|
-
- **读后即记引导(内核侧,非角色包)**:`read_file` 工具描述追加「读到需长期引用的要点随即 `remember_intel` 记入工作笔记,查证用 `search_memories`,不要靠重复读文件」——工具描述是工具行为的 how 单源(用户裁决:该引导属内核职责,不进角色包)
|
|
1060
|
-
- **验证(变异闭合)**:`guardRail.test.ts` 升级判定 6 例(前两次温和 / 第 3 次升级保留 read_file 出口 / web_search 主体不带 offset/limit / 主体隔离 / 轮界归零 / 阈值语义钉)+ `loop.test.ts` 集成 1 例(loop→guard 连线 + 指标 + 文案落位,按文案特征分流计数——压缩替身同含 `[ALREADY_READ]` 令牌,按令牌计数会误算);**变异四组均还原复绿**:阈值 2→1 → 恰 2 红、断开 `notifyBlocked` 连线 → 恰 1 红(集成)、断开 `promptArgs` 裁决连线 → 恰 2 红、出口分流回潮 → 恰 1 红。`typecheck` 0 / `eslint` 0 / `rules:refs` 0 / `format:check` 0 / 全量 **2812 passed | 4 skipped**
|
|
1061
|
-
|
|
1062
|
-
### Fixed(内核 · 写串行闸收口:`diskWrite` 声明位 + 不透明写屏障,DIFF-4/5)
|
|
1063
|
-
|
|
1064
|
-
- **问题**:「谁会改盘」散在两处枚举(builtinTools 工具表语义 ↔ `WRITE_PATH_EXTRACTORS` 键),新增写工具忘加提取器 = 串行不防 + 追踪不报 + 契约钉不红的三重静默(DIFF-5);且 `run_code` / `run_*_script` 等**无 `args.path` 的写工具**不进串行闸——同 step 并行脚本写/脚本×write_file 同目标 = DIFF-3 同型丢内容(DIFF-4)
|
|
1065
|
-
- **修复(SSOT:构造级单源)**:`ToolDefinition` 增 `diskWrite?: 'path' | 'opaque'` **行内声明**(真源 = 定义行,与 `readonly` 正交);`PATH_WRITE_TOOL_NAMES` / `OPAQUE_WRITE_TOOL_NAMES` / `WRITE_PATH_EXTRACTORS` 全部**派生**(漂移不可构造),`toolExecutor.builtinDefinitions` 与 loop 的「写后失效 read_file 缓存」分支**同批收编**各自的内联枚举(后者顺带修掉潜伏 miss:原用 raw 路径失效台账,`./a.md` 式入参会失效不中,改走同一提取器的归一路径)。契约钉 3 例(含 `'path'` 行必带 `path` 参数的语义自洽断言)
|
|
1066
|
-
- **串行闸补齐(不带伤三条件齐)**:不透明写(`run_code` / `run_skill_script` / `run_project_script` / `register_work`,后者经核查证实为异步读-改-写)升为**屏障**——与一切写互斥;声明 `'path'` 但目标提取失败 → **降级屏障**(不确定即保守串行);同路径串行维持现状、不同路径仍并发(反向守卫保绿)
|
|
1067
|
-
- **验证(变异闭合)**:loop 峰值活跃数断言 ×3 新例;变异 3 场精确命中(删声明→恰 1 红 / 短路屏障→恰 3 红 / 拆降级半→恰 1 红),既有 DIFF-3 两例与反向守卫全程零误伤
|
|
1068
|
-
- **边界(如实记)**:自定义工具的 `diskWrite` 声明暂不生效;「新工具整行忘声明」靠行内同处 + 契约钉复审兜住;脚本改盘的**可视化盲区**保留(宿主 FS watcher 触发驱动,见台账 DIFF-4)
|
|
1069
|
-
|
|
1070
|
-
### Added(内核 · 公开导出面补齐:`MAX_DIFF_CONTENT_LENGTH` / `WRITE_PATH_EXTRACTORS`)
|
|
1071
|
-
|
|
1072
|
-
- `src/security/pathGuard.ts` 导出 `MAX_DIFF_CONTENT_LENGTH`(diff 内容上限 10240),`src/index.ts` 安全层导出面收录——宿主 UI 展示阈值 `import` 对齐,消除跨包同值并列(DIFF-2)。⚠️ 两侧超限行为不同(内核 = 截断后加「已截断」标记照常展示 / 宿主 = 跳过对比只提示),导出只统一**数值**、不统一行为
|
|
1073
|
-
- `src/agent/toolResultCache.ts` 的 `WRITE_PATH_EXTRACTORS`(按 `args.path` 改盘工具清单,loop 同路径写串行闸判据)经 `src/index.ts` 导出——宿主改动追踪据其键派生触发集合,跨包双枚举收编为单源(内核新增按 path 写工具时宿主自动跟随)
|
|
1074
|
-
- **覆盖边界(如实记)**:清单只认 `args.path` 定位的写工具,`run_code` / `run_*_script` 类不在内(台账 DIFF-4 / DIFF-5 登记)
|
|
1075
|
-
|
|
1076
|
-
### Fixed(内核 · 同一 step 并行写同一文件会丢内容 DIFF-3:按目标路径批内串行)
|
|
1077
|
-
|
|
1078
|
-
**问题证据(真机两次实证)**:一个 step 内模型可能**并行**多次写同一文件(`round-1790411133316` / `round-1790412202553` 两轮实测 `insert` + `append` 同时发出)。`write_file` 是「读盘 → 改 → 写盘」,并行时两次都基于**同一份旧快照**(两条结果的 summary 各自自报「旧文件: 28 行」)⇒ 后落地者整体覆盖先落地者,**插入的行被静默吃掉**(31 → 34 行,插入内容丢失);模型串行重发才恢复。
|
|
1079
|
-
|
|
1080
|
-
- **改法**:新增 `WRITE_PATH_EXTRACTORS`(`toolResultCache.ts`)——与 `DEDUP_SUBJECT_EXTRACTORS` **并列而非合并**(后者是**防重**判据,写工具正是被防重刻意排除的对象;并入会让「同文件分次追加」被误拦,属语义反转)。loop 发起工具时按**规范化目标路径**(复用 `normalizePathKey`,路径等价语义只有一套)把同路径的写**串成链**;不同路径之间维持完全并发
|
|
1081
|
-
- **边界(不改单次语义)**:只串行「同路径的**写**」(`write_file` / `delete_file`),不排队所有写工具、**读不参与**(读-写竞态本次不动,未观察到损害);工具结果仍按 `toolCalls` 原序对齐回填,`tool_start` 仍批量先发。**覆盖边界(如实记)**:清单只认 `args.path` 定位的写工具 ⇒ `run_code` / `run_skill_script` / `run_project_script`(能改盘但无 `path`)不在闸内
|
|
1082
|
-
- **验证(变异闭合)**:`loop.test.ts` 新增 2 例——同路径写串行(峰值活跃数恒 1,且 `a.md` / `./a.md` 等价写法被归一为同一文件)、不同路径写仍并发(峰值 ≥ 2,**反向守卫**防「凡写工具一律排队」的退化实现)。**变异**:短路串行分支 → 串行例**恰 1 红**(`maxActive` 2→1 失守)、并发例仍绿;恢复后 `grep` 复核零残留。内核全量 **2795 passed**(较改动前 +2,零回归)
|
|
1083
|
-
- **归属口径**:原登记在 3.1.0,2026-09-26 决议**改归 3.0.0**——代码已过 13 步门禁落在 main,为保标签去切发布源的成本 > 收益;且它是带守卫的 bug fix,纳入 3.0.0 不破坏任何契约。决策留档见 `tasks/待完成任务.md` DIFF-3 行
|
|
1084
|
-
|
|
1085
|
-
### Fixed(内核 · 任务表工具契约收敛:必填参数删除不可达缺省 + `update` 模式全量替换语义钉死)
|
|
1086
|
-
|
|
1087
|
-
**问题(五类带伤复审 · 口径伤 + 命名伤)**:① `task_table_write` 的 `mode` 与 `task_table_update` 的 `status` 在 `builtinTools` 工具表标 `required`,却在 `toolExecutor` 派发处各给 `'overwrite'` / `'done'` 缺省——schema 与实现自相矛盾(**口径伤**);② `task_table_write` 的 `update` 模式按 `items` 索引全量重建(`writePlan` 整体替换 `checkpoint.plan`),对外描述只说「替换」,LLM 极易与单任务项工具 `task_table_update` 混淆、漏列即丢项(**命名伤 + 口径伤**)。
|
|
1088
|
-
|
|
1089
|
-
- **修法(止血不造伤 · 零行为变更)**:① 删 `task_table_write`/`task_table_update` 派发处两处**不可达**缺省(`strArg('mode')` / `strArg('status')` 不再给回退值)——`required` 校验层(`validateAndCoerceArgs`)本就在派发前拦截缺失,缺省是永不可达的死代码,删后唯一区别是「校验被绕过时 fail-loud 而非静默覆盖」;② `task_table_write` 的 `update` 模式描述补全「须传完整任务项列表,未列出的会被丢弃——勿与 `task_table_update` 混淆」(工具级描述 + `mode` 参数级描述双处对齐,单一口径)
|
|
1090
|
-
- **验证(回归钉锁死契约)**:新增 `sessionManager.test.ts` 守卫「`writePlan` update 模式全量替换:未列出的任务项被丢弃」(3 项基线 → update 传 2 项 → plan 长度=2、保留原 id、第 3 项消失)。**实测**:`builtinTools.test.ts` 70 passed / `toolExecutor.test.ts` task_table 14 passed / `sessionManager.test.ts` 整文件 74 passed,全绿零回归
|
|
1091
|
-
- **残留已知伤(已收口,见下方 Changed)**:`update` 模式 与 `task_table_update` 工具**撞名**是结构性命名带伤,描述缓解仅止血;改名已于同批落地(见下方 Changed 段),台账 `TASKTABLE-NAME-1` 销项
|
|
1092
|
-
|
|
1093
|
-
### Changed(任务表写入模式正名:`task_table_write` 的 `update` → `replace`,TASKTABLE-NAME-1 收口)
|
|
1094
|
-
|
|
1095
|
-
**问题**:`task_table_write` 的 `update` 模式(全量替换整张表)与单任务项工具 `task_table_update` 撞名——两种语义共用一个词,内核注释已被污染(`updatePlan` 头注释曾把生产点误写成 `task_table_update mode='update'`)。
|
|
1096
|
-
|
|
1097
|
-
- **改名窗口(证伪旧定性)**:`git tag` 最高 `v2.0.3`、`package.json` 虽为 3.0.0 但未发布 npm ⇒ **不存在任何已发布消费者**,改名是纯内部改动,无需 deprecation 周期(原「须走 deprecation」定性已被 tag 实证推翻)
|
|
1098
|
-
- **选词**:`replace` 与 `overwrite`(清空重写)/`append`(追加)三词互不重叠,与 `task_table_update`(单项状态)彻底不撞
|
|
1099
|
-
- **自愈路径**:mode 校验本就 fail-loud(`[ERR:INVALID_ARG]` 列出全部可用值)——模型输出旧词 `update` 会拿到含 `replace` 的明确错误,可自行重试;守卫钉死「旧词不得静默下发(writePlan else 兜底是 no-op,下发即静默丢写)」
|
|
1100
|
-
- **二次收口(自审揪出漏网)**:`assembler.ts` 任务表「未完成硬约束」nudge(每轮注入 LLM 的生产提示词)仍写 `task_table_write (update)`——首轮 grep 判据只扫 mode 字面量赋值,漏了形态相异的提示词文案;且该句语义本就与工具契约不符(`task_table_write` 任何 mode 都不改 status,「标记已阻塞」只有 `task_table_update` 能置 `blocked`)。一并正名 + 纠语义(改指 `task_table_update` 置 `blocked`),并补 `assembler.test.ts` 词表 + 语义双钉
|
|
1101
|
-
- **改动面**:`builtinTools.ts` 描述 ×2、`toolExecutor.ts` 校验 + 接口类型 + 注释、`sessionManager.ts` 类型/分支/注释(顺带修正生产点工具名笔误)、`assembler.ts` 未完成硬约束 nudge 正名 + 纠语义、测试 ×5;宿主零消费(只按工具名匹配)、docs/角色包零提及 mode
|
|
1102
|
-
- **验证(变异闭合)**:变异 A(判据改回 `update`)→ 新钉 2 条**恰 2 红**;变异 B(`replace` 分支短路 no-op)→ 语义钉**恰 1 红**;变异 C(nudge 还原旧词 + `task_table_write` 误引)→ `assembler.test.ts` 新钉**恰 1 红**,零误伤。恢复后 `tsc` 0、`eslint` 0、`sessionManager`+`builtinTools` **144 passed**、`toolExecutor` task_table **16 passed**、`assembler` **34 passed**
|
|
1103
|
-
|
|
1104
|
-
### Added(新增门禁 `rules:refs`:规则裸路径引用有效性 · 补 `docs:links` 同族盲区)
|
|
1105
|
-
|
|
1106
|
-
**问题证据(血训)**:`413e1046` 把 14 个规则文件从 `.trae/rules/` 移入 `.trae/rules/generic/`,引用漏改分**两类书写形态**——① markdown 链接形态(`](...)`,`docs:links` 能抓,已修 15 处);② **反引号 / 纯文本形态的裸路径**(本次修 12 处)。后者是**判据失明的盲区**:`docs:links` 只认 `](...)` 语法,且**主动剥离行内代码跨度**(见 `check-publish-links.ts` 的 `LINK_RE` / `INLINE_CODE_RE`)→ 裸路径根本不在其扫描面内。两类是同一族「参考腐烂」,只是书写形态不同。
|
|
1107
|
-
|
|
1108
|
-
- **新增 `scripts/check-rule-refs.ts`**:扫全仓文本文件(`.md` / `.ts` / `.mjs` / `.yml`)里的 `.trae/rules/` 裸路径引用,解析不到目标文件即 exit 1。与 `check-publish-links.ts` 同型(纯 FS / 零三方依赖 / 零网络 / 确定性 / 只读 + 退出码),可进 CI
|
|
1109
|
-
- **判据边界(刻意排除,非豁免清单)**:① 源文件位于 `.trae/skills/**` —— 技能手册是**可移植模板**,其中引用的规则文件由 big-tree-seeder 在**目标项目**生成,本仓内本就不该存在;② **脚本自身** —— 否则脚本内作为样例的旧路径文本会给「旧路径基线」续命(同术语门禁教训:扫自身 → 消失检测失效)
|
|
1110
|
-
- **闸门自检(每次运行都跑,不可关闭)**:先对 3 条内置样例跑**同一套判据**(`scanLine`,与主扫描同源,非另写一套),未全过即 exit 2 —— 「0 命中即成功」这类断言若判据本身失明(正则改坏 / 排除逻辑写反)会**静默假绿**
|
|
1111
|
-
- **修复 12 处陈旧裸路径引用(9 文件)**:`docs/` × 4、`prompts/` × 1、`tasks/` × 2、`vitest.config.ts` × 1 —— 全部补 `generic/`。其中 `vitest.config.ts` 一处是首轮 grep 正则漏掉下划线文件名所致(`[a-z0-9-]` → `[A-Za-z0-9_./-]` 才现形),属「排雷发现取证不完整」的实例
|
|
1112
|
-
- **接线**:`package.json` 新增 `rules:refs` 脚本;`scripts/local-ci.mjs` 步骤清单 full 档新增同名步骤(位于术语门禁之后、audit 之前)
|
|
1113
|
-
- **验证(变异闭合)**:自检 **3/3**、扫 **556** 文本文件、**0 命中** EXIT=0;临时把 `vitest.config.ts` 引用改回旧路径 → **恰 1 红**(正确定位到该行)→ 恢复全绿;`docs:links:repo` 自检 4/4 / 208 链接 / 0 死链;`terminology:check` 零漂移;`tsc -p tsconfig.scripts.json` / `eslint --max-warnings 0` EXIT=0
|
|
1114
|
-
### Changed(任务项折叠边界 `plan_item_boundary` 产出时机前移:边界产在它所罩住的内容之前)
|
|
1115
|
-
|
|
1116
|
-
**问题证据**:真机观察「触发任务表后 step 没收进任务项折叠块」。先打掉误判——宿主两条渲染路径(运行时 `renderProcessFlow` / 收尾 `renderRoundBlock`)共用同一归组判据 `planItemContainerFor`,实测(3 迭代 / 2 任务项 / 真实递增 `ts`)两路径结果**逐字相同**(组内 `t2,t3`、游离 `t1`),**不存在「运行时不收、收尾收」的机制差异**。真身是:**每个任务项的首个迭代(思考 + 首批工具)恒在折叠块外**——因为边界产在本迭代工具落定**之后**,而宿主判据 `b.ts < ts` 只能**向前**找边界,对首个迭代必然落空;且批块首次插入即定位容器、之后不搬家。
|
|
1117
|
-
|
|
1118
|
-
- **产出点前移**:`_maybeEmitPlanItemBoundary()` 从「工具落定后 / 无工具分支」**两处**调用点,收敛为**唯一一处**——`handleIteration` 内 `_handleInterrupt` 之后、`_prepareContext` 之前(迭代开始、LLM 调用前)。边界语义由「我现在在这项」回到「**以下内容**属于该项」
|
|
1119
|
-
- **落点必须早于 LLM 调用**(而非 `onPlanItemBoundary` 所在的「LLM 后 / 工具前」):后者会把边界插在本 step 思考流之后,把思考与它驱动的工具劈进两个任务项容器
|
|
1120
|
-
- **调用次数不变**:原实现每迭代调一次(工具分支经 `_emitStepBoundary` / 无工具分支单独调),前移后仍是每迭代一次(迭代开头),挂起/中止迭代因 `_handleInterrupt` 提前返回而不调——与原来一致。**不是新增开销**
|
|
1121
|
-
- **不带伤判定(五类逐条)**:双轨镜像——2 处产出点收敛为 1 处 🟢 净减伤;降级兜底残留——旧实现里边界产在内容**之后**,末尾那条边界之后已无内容 → 只剩标题的**空折叠块**;前移后边界必然罩住本迭代内容,空折叠块消失 🟢 净减伤(注意:**终态迭代仍会产边界**,旧实现同样会——工具分支的 `_maybeEmitPlanItemBoundary()` 原本就是无条件调用,只有 `step_boundary` 条件化。差别只在边界的**位置**,不在有无);类型 hack / 重复实现 🟢 无伤;僵尸声明 🟡 需注释回扫(已做)
|
|
1122
|
-
- **被否决的备选**:宿主侧放宽判据允许「归入紧随其后的边界」——判据与内核语义对不上,形成双判据,属拿实现迁就显示
|
|
1123
|
-
- **语义后果(可接受,非缺陷)**:任务表若由本轮某迭代的工具**新建**,该迭代仍留在组外(那个时刻任务表还不存在)。本次修的是「任务表在本轮开始前已存在」(续会 / prepare 预置 / 上一 turn 遗留 / checkpoint 恢复)的场景
|
|
1124
|
-
- **`lastBoundaryPlanItemId` 跨 turn 不重置**:刻意设计(`metrics.test.ts` 两个用例锁死),本次不动
|
|
1125
|
-
- **文档同步**:`docs/方案-任务项边界产出时机前移-20260926.md`(闭合闭环,先文档后代码);`docs/architecture/step-atomic-persistence.md` 档 3 两处订正(原述「复用两个既有调用点」「由 `_emitStepBoundary` 单函数内串联两者」已废止,先后序改由「分居迭代首尾」保证);`types.ts` 顺序契约注释、`assembler.ts` 装配注释、`loop.ts` 时序分叉注释同步
|
|
1126
|
-
- **验证(变异闭合)**:新增用例先红(`expected 4 to be less than 1`——边界下标 4 晚于思考下标 1,实锤旧行为)→ 改实现转绿;`stepBoundary.test.ts` 10/10,顺序契约 / STEP-BUCKET-1 / TOOL-RUN-1 三条老守卫全绿零误伤;内核 `tsc --noEmit` EXIT=0
|
|
1127
|
-
|
|
1128
|
-
### Removed(`ProjectContext.dbPath` 退役:内核不再持宿主持久化形态)
|
|
1129
|
-
|
|
1130
|
-
`ProjectContext.dbPath` 是「内核自带 SqliteStorage」时代的遗留字段。ADR-002 把 SqliteStorage 移出内核、持久化改由宿主经 `IMemoryStorage` 注入之后,它的消费者已清零:内核既不创建也不打开它,第一宿主 memora-vscode 的 `WorkspaceStorage` 走自己的 `.memora/memories.json`,从未读它。字段注释自称「Agent 级 `memora.db` 路径(全局共享)」,实值却是 `join(agentDataDir, 'memora.db')`,而 `agentDataDir` 由宿主传入的 `dataDir` 决定(vscode 宿主传的是项目级 `.memora`)——照它开库会得到「每个子项目一个 `memora.db`」,正撞架构规则明令禁止的形态。
|
|
1131
|
-
|
|
1132
|
-
- **删除 `ProjectContext.dbPath`** 字段声明与赋值;`ProjectContext.index` 注释去掉「SQLite 索引」具象化(内核不假设宿主持久化形态)
|
|
1133
|
-
- **文档同步**:`docs/memora-api-reference.md` 的 `ProjectContext` 字段表移除该行;`storage` × `dataDir` 对照表去掉 `join(dataDir, 'memora.db')` 与「内核推导 dbPath」两处表述
|
|
1134
|
-
- **破坏性但零成本**:`ProjectContext` 经 `src/index.ts` 导出的 `AgentContext` 别名对外可见,故此行属公共 API 变更;**不提供兼容层**——3.0.0 尚未发布(npm 最新为 2.0.3),无外部用户依赖该字段,且它本身零消费者、无行为可兼容
|
|
1135
|
-
|
|
1136
|
-
### Changed(`AgentOptions.dataDir` 收紧为必填 + `switchProject` 拒绝未解析的非绝对路径)
|
|
1137
|
-
|
|
1138
|
-
同一根因的两处收口:**「Agent 级数据目录」在内核与宿主之间没有定死**。`dataDir` 类型标可选、文档称「缺省 `~/.memora`」,代码却写着 `opts.dataDir!` 非空断言——而 `src/` 里从来没有 `~/.memora` 这个默认值(`homedir` 仅出现在 `expandHome` 内部;唯一的 `~/.memora` 在 `config.example.json`,且 `config.memory.dataDir` 内核**不消费**,全仓只有测试读它)。照文档省略 `dataDir` 的后果是 `expandHome(undefined)` 抛 `Cannot read properties of undefined`。
|
|
1139
|
-
|
|
1140
|
-
- **`dataDir` 改为必填**:`AgentOptions.dataDir?: string` → `dataDir: string`,并删掉 `agent.ts` 的 `!` 断言——把运行期爆炸换成编译期保证。目录位置与其层级语义(项目级 / 用户级)是宿主的产品决策,内核不提供默认值、也不做假设
|
|
1141
|
-
- **`registryDir` 注释诚实化**:缺省随 `dataDir`(原注释自称「优先宿主指定用户级路径,避免每项目重复存储」,而缺省分支恰恰就是每项目一份)。注册表的用途是**跨项目按名解析**,只有多项目共用一份目录时才兑现;`dataDir` 为项目级时,注册表随项目落盘、只含项目自身条目
|
|
1142
|
-
- **`switchProject` 加守卫**:`nameOrPath` 只接受「注册表中的项目名」或「项目根目录的绝对路径」,二者都不满足时抛 `configError`。此前未命中会原样当路径 → `resolve('...', '.memora')` 以 `process.cwd()` 为基准,**静默建出伪项目目录、占用其锁、写入注册表**
|
|
1143
|
-
- **文档同步**:api-reference §〇.3 去掉 `dataDir` 的假默认、补「`config.json` 的 `memory.dataDir` 内核不读」、订正「锁文件由 `dataDir` 推导」(锁固定落 `<projectPath>/.memora/.lock`,与 `dataDir` 无关);README 中英双版与接入指南的构造示例原先**漏传 `dataDir` 或传相对路径**,补绝对路径;接入指南 §8 拆「按路径(推荐)/ 按名(需先注册 + 注册表共享)」两式
|
|
1144
|
-
- **随包文档两处冲突表述订正**:api-reference「内部数据写入(不越界)」段与接入指南 §十 关键约束 3 原先分别称两个状态文件在 `~/.memora/`、`.memora/` 只放 `rules/`+`skills/`——均与本次收敛后的路径契约矛盾,同步改正
|
|
1145
|
-
|
|
1146
|
-
> **破坏性但零成本**(对齐本文件既有口径):`AgentOptions.dataDir` 由可选改必填是对外可见的类型变更;但仓内**无一处**省略它——内核 `tsc --noEmit`(`include` 覆盖 `src/**/*`,含全部测试文件)与宿主 10 处构造点全数通过,改动实质是把 `!` 断言换成编译期保证。`registryDir` 保留(它是宿主把注册表提到用户级的唯一通道),仅订正注释;宿主零消费 `switchProject`,故守卫不构成在网行为变更。
|
|
1147
|
-
|
|
1148
|
-
### Changed(术语正名:任务项 `PlanStep` → `PlanItem` + `step_boundary` 归位为迭代边界)
|
|
1149
|
-
|
|
1150
|
-
根治项目内两个「step」的术语撞车——① **loop 迭代 step**(一次 LLM 交互 + 其工具执行,`stepBudget` 属此阵营);② **任务表 plan step**(一行任务)。阵营②此前占用 `step_boundary` 事件名,导致阵营①没有自己的边界信号——这同时是「无任务表长工具循环零增量落盘」缺口的根因。
|
|
1151
|
-
|
|
1152
|
-
- **事件对调**:迭代边界 `iteration_boundary` **归位**为 `step_boundary`;任务表边界 `step_boundary` 改名 **`plan_item_boundary`**
|
|
1153
|
-
- **内核标识符**:`PlanStep` → `PlanItem`(连同 `planStepId` → `planItemId` / `getActiveStepMeta` → `getActivePlanItemMeta` / `updatePlanStepStatus` → `updatePlanItemStatus` / `appendPlanStep` → `appendPlanItem` / `completeStep` → `completePlanItem` / `STEP_DESC_MAX_CHARS` → `PLAN_ITEM_DESC_MAX_CHARS`)
|
|
1154
|
-
- **宿主标识符 / 协议 / 样式**:`PlanStepDto` → `PlanItemDto`、`currentPlanSteps` → `currentPlanItems`、`insertStepInOrder` → `insertPlanItemInOrder` 等;`plan_update` 消息字段 `steps` → `items`;CSS 类 `.plan-step*` → `.plan-item*`、`.round-block__step*` → `.round-block__plan-item*`;DOM 属性 `data-step` → `data-plan-item`(**仅任务项段**;`data-step-bucket` = thought 按 stepIndex 分桶,属 step 阵营,**不改、也不得改**);折叠块标题 `step-N` → **「任务项 N」**
|
|
1155
|
-
- **不动(硬边界)**:`stepBudget` / `multiStepReasoning` / `toolStepLimit`(角色包策略键 = 对外契约)、`task_table_*`(工具名,见下条)、CSS 关键字 `step-end`、历史档号与本文件旧版本条目(`step_id` / `steps` 两个**参数名**当时一并保留,已于 Unreleased 内后续条目正名)
|
|
1156
|
-
|
|
1157
|
-
> **对内核公共 API 非破坏**:改动集中在内部标识符与宿主协议;`Round.processEvents` / `SessionCheckpoint` 等持久化 schema 未动。**唯一语义变更是事件名 `step_boundary`**(原任务表边界 → 现迭代边界),宿主与内核须同批升级。**不提供兼容层**(测试阶段无外部用户;`.memora/` 为本地桌面数据,重新生成即可)。
|
|
1158
|
-
|
|
1159
|
-
### Changed(术语收口补完:函数名归位 + LLM 可见文案与错误码正名)
|
|
1160
|
-
|
|
1161
|
-
承接上条 `PlanStep → PlanItem` 正名——上条落到**事件名与标识符**为止,遗留两处半补丁:① `_maybeEmitStepBoundary` 名为 step 却产 `plan_item_boundary`、`_emitIterationBoundary` 用历史别名命名却产 `step_boundary`(**函数名与产出事件互换**——只修事件名不修函数名,正是术语锚点 §7 后果链第一环的复刻);② LLM 可见文案与错误码仍以「步骤」指任务项。3.0.0 未发布,此处无兼容代价,一次收口。
|
|
1162
|
-
|
|
1163
|
-
- **函数名归位**:`_maybeEmitStepBoundary` → `_maybeEmitPlanItemBoundary`、`_emitIterationBoundary` → `_emitStepBoundary`(均 `private`,零外部契约;`docs/architecture/step-atomic-persistence.md` 与 `loop-design.md` 同步)
|
|
1164
|
-
- **错误码正名**:`[ERR:STEP_NOT_FOUND]` → `[ERR:PLAN_ITEM_NOT_FOUND]`(LLM 可见,无外部消费者)
|
|
1165
|
-
- **LLM 可见文案与注释**:「步骤」→「任务项」——`builtinTools`(两个任务表工具描述)、`assembler`(任务表回执 / 未完成硬约束 / `updatePlanItem` 回执)、`toolExecutor`(寻址三类错误提示)、`taskTableRenderer`、`sessionManager`、`types.ts`、`scripts/test-tasktable-real.ts`
|
|
1166
|
-
- **宿主注释**:`protocol.ts` / `chatView.ts` / `chatStyles.ts` / `chatPanel.ts` 共 33 处「步骤」「步级」→「任务项」「任务项级」(**纯注释,零字符串与标识符变更**)
|
|
1167
|
-
- **仍不动(冻结例外)**:`task_table_*`(工具名)、`stepBudget` / `multiStepReasoning` / `toolStepLimit`、CSS 关键字 `step-end`、`data-step-bucket`(thought 按 stepIndex 分桶,属 step 阵营);`handoffPrompt` 属**同名异义**(角色接手话术,非已废的 Handoff 衔接决策)——已补入术语锚点 §3 冻结例外(`step_id` / `steps` 两个参数名当时暂留,见下条正名)
|
|
1168
|
-
- **fixture 边界**:录制轮次 fixture `realRound-*.ts` 内的「步骤 [xxx]」为**当时真实输出**,不改(改了即伪造证据)
|
|
1169
|
-
|
|
1170
|
-
### Added(术语载体扫描门禁:把「载体清单」机械化)
|
|
1171
|
-
|
|
1172
|
-
前两条落到「已发现的载体」为止,而三次半补丁(`.prettierignore` 只挡一半 / 函数名改了事件名没改 / 本文件过度声明)的共同根因是**载体清单不完整**。本轮把这个清单本身机械化。
|
|
1173
|
-
|
|
1174
|
-
- **新增 `scripts/terminology-carrier-snapshot.ts`**(`npm run terminology:report` 看报表 / `terminology:check` 做门禁,已接入 `ci:local` full 档):扫全仓抽取 `step` 正名族与 `iteration` / `迭代` / `内循环` 历史别名族的**全部载体**(标识符 / 事件名 / CSS 类 / DOM 属性 / 中文词 / 文件名与目录名),与基线集合比对,有新增或消失即 `exit 1` 并打印可直接粘贴的基线。
|
|
1175
|
-
- **不建第二份例外清单**:冻结例外由 `.trae/rules/terminology-anchor-rules.md` §3 表格**解析**得到(解析数不足即报错退出,防「静默返回空集 → 门禁永远绿」)。
|
|
1176
|
-
- **只锁集合、不锁次数**:次数会因任意一次注释改动而漂移,门禁天天红必然被绕过;锁集合只对「新词出现 / 旧词消失」报警,语义对错仍由人显式确认(git diff 即审计痕迹)。
|
|
1177
|
-
- **扫描范围边界(非逐词豁免)**:排除录制 fixture(`__tests__/fixtures/`,改了即伪造证据)与依赖 / 构建产物 / 工具内部状态。基线首版 102 个载体(随后续正名条目更新:见下两条)。
|
|
1178
|
-
|
|
1179
|
-
### Changed(术语载体扫描查出的 src 层三处漏网正名)
|
|
1180
|
-
|
|
1181
|
-
上一轮审计按「事件名 / 函数名 / 文案 / 错误码」分类去查,未扫全词根,漏了三处在 `src/` 生产代码里的 `step` 撞车——本轮由扫描清单反查出来。
|
|
1182
|
-
|
|
1183
|
-
- **`perStep` → `perTurn`**(`guardRail.ts` 的 `GuardRailDef.life` / `GuardRail.reset` + 4 处护栏定义、`loop.ts` 调用点、`guardRail.test.ts`):该 `life` 的归零点在 `resetTurnState`,其原注释亦自称「按闭环累计」——**名字说 step、语义是 turn**,与「step 指任务项」方向相反的同族撞车。`GuardRailDef` 未经 `src/index.ts` 导出、宿主零消费,改动无外部契约影响。
|
|
1184
|
-
- **`STEP_LOG_PER_STEP_LIMIT` → `PLAN_ITEM_LOG_PER_ITEM_LIMIT`**(`sessionManager.appendPlanItemLog`,连同其 JSDoc 4 处「step」):该段全程按 `planItemId` 分组,`step` 在此即任务项(术语锚点 §4.1 红线)。同步测试内局部量 `stepLogLenBefore` → `planItemLogLenBefore`。
|
|
1185
|
-
- **仍不动(冻结例外)**:`task_table_*`(工具名)、`stepBudget` / `multiStepReasoning` / `toolStepLimit`、CSS 关键字 `step-end` / `animation-iteration-count`、GitHub Actions 的 `steps`(外部生态词,非本仓术语)、过程文档与台账内的历史记录(`PlanStep` / `getActiveStepMeta` 等旧名属「怎么变过来的」,改写即伪造记录)(`step_id` / `steps` 两个参数名当时暂留,见下条正名)
|
|
1186
|
-
|
|
1187
|
-
### Changed(任务表工具参数正名:`step_id` → `plan_item_id` / `steps` → `items` + 同族 bare「步」收尾)
|
|
1188
|
-
|
|
1189
|
-
上三条把正名推到「事件名 / 函数名 / 文案 / 错误码」,仍把两个**工具参数名**留在冻结例外里。3.0.0 未发布 ⇒ 改名零成本;而工具参数名是**每轮都进 LLM 上下文的契约面**,长期占用 `step` 就是持续教坏模型与后来者(术语锚点 §4.1 明文禁止用 `step` 表任务表语义)。本轮把它降级为**历史别名**,并顺手扫掉同族漏网的第三种形态——bare「步」(前几轮只认「步骤 / 步级」两词,`某步` / `逐步` / `该步` / `active 步` 全在网外)。
|
|
1190
|
-
|
|
1191
|
-
- **工具参数正名**:`task_table_update` 寻址参数 `step_id` → **`plan_item_id`**;`task_table_write` 列表参数 `steps` → **`items`**。全链同步:内核 `builtinTools`(工具描述 + JSON schema)、`toolExecutor`(寻址解析 + 三类错误文案)、`assembler` / `sessionManager` 的 `writePlan` 形参、`scripts/test-tasktable-real.ts`、宿主 `chatView.test.ts`
|
|
1192
|
-
- **术语锚点同步**:§2 任务表阵营新增「任务表工具参数」行(`plan_item_id` / `items`);§3 **删除 `step_id` 条目**(冻结例外收敛为 3 个 `stepBudget` 词根键 + `handoffPrompt` 同名异义);§4.1 明列「含**工具参数名**」;§6 新增历史别名行——旧名只可用于读懂历史记录
|
|
1193
|
-
- **内核注释同族收尾(bare「步」形态)**:`assembler`(会议逐项切换 / 任务项边界回调 / 末项兜底)、`agent`(turn 收尾清空 / 可续跑判据 / 装配视角日志)、`loop`(任务项日志回调 / 在途判定注释 / 会议轮判据)、`sessionManager`(`ensureActivePlanItem` / `hasInflightPlan` / `completePlanItem` / `concludeActivePlanItemIfPlanFullyReached` / `getActivePlanItem` 的 JSDoc 与内联注释)、`orchestrator`(续跑对称刷新 / 兜底收尾)、`prepare`(会议骨架守卫 + 装配入口说明)、`rolePackManager`(会议组上下文文案注释)、`types`(`plan_item_boundary` / `plan` / `planItemLog` 字段注释)、`taskTableRenderer`(收尾验证 nudge 注释与**文案正文**)、`builtinToolHandlers`(保留文件名错误的建议条)、`needsPlanning`(`PLAN_NUDGE_PROMPT` 正文)
|
|
1194
|
-
- **活跃架构文档**:`docs/architecture/role-pack-exclusivity-relocation.md` 全篇把任务项称「步」的表述正名(含 §4.3 装配驱动点、§4.5 会议执行流、S5 行的 2026-08-29 补强注记、`task_table_write` 参数示例 `steps` → `items`);§6.3 的「实施步骤 S0→S8 / | 步 |」属**通用程序步骤**(第三种语义),不动
|
|
1195
|
-
- **边界(不改)**:测试样本数据字面量(`description: '步骤一'` / `id: 'a1b2c3d4-step-1'`)与录制 fixture 内「步骤 [xxx] 已标记为 done」是**内容而非术语载体**,改即纯 churn 或伪造证据;`step` 本义用法(`stepBudget` / 多步推理 / 工具步 / `data-step-bucket`)与通用程序用词(`needsPlanning` 的用户输入检测词 `多步` / `分步骤`)一并不动
|
|
1196
|
-
- **本条作废前三条的「仍不动」表述**:`step_id` / `steps` 曾被列为硬边界或冻结例外,正名后该表述作废;`task_table_*`(工具名)与 `stepBudget` / `multiStepReasoning` / `toolStepLimit` 仍在硬边界内不动
|
|
1197
|
-
|
|
1198
|
-
### Fixed(术语载体门禁结构性失效:脚本扫自身致「旧词消失」永不报警)
|
|
1199
|
-
|
|
1200
|
-
- **根因**:`scripts/terminology-carrier-snapshot.ts` 的 `walk()` 扫全仓时**包含自身**,而 `BASELINE` 常量里的字面量本身就是 step 族 token ⇒ 基线里的旧词永远被自己续命 ⇒「旧词消失」这条检测**结构性失效**(只报新增、不报消失)。实证:本轮正名后 `terminology:check` 仍报「无漂移(104 个载体)」。
|
|
1201
|
-
- **修复**:新增 `SELF_REL` 自排除(本文件是门禁工具=元数据,不属被纪律的载体对象),并在文件头「明确不扫」清单写明理由;复跑立刻得到真实的 `新增 0 / 消失 4`,删掉那 4 条基线条目后 104 → 100 复绿(`MIN_FROZEN` 仍为 3,与锚点 §3 解析数一致)。⚠️ 本条**刻意不列出那 4 个 token 的字面量**——本文件也在扫描范围内,写出旧名等于把它们重新挂回载体集合,门禁会立刻报「新增 4」。
|
|
1202
|
-
- **已知边界(设计使然,非缺陷)**:历史记录(本文件旧条目、`tasks/` 台账、`.trae/documents/` 过程方案)会被扫描且**理应**保留旧名 ⇒ 旧名只要还在记录里被引用,就不会被判为「消失」。集合纪律的重心在**新增报警**(新代码误用旧词根),消失报警只是次级信号。
|
|
1203
|
-
|
|
1204
|
-
### Changed(内核零运行时模块解析:移除 pino 可选 peer 与内核侧文件日志)
|
|
1205
|
-
|
|
1206
|
-
内核定位「零第三方运行时依赖」的收口——移除内核**唯一**的运行时第三方模块解析点,让声明与实现一致。
|
|
1207
|
-
|
|
1208
|
-
- **移除 `import('pino')`**:删除 `tryCreatePinoLogger()` / `wrapPinoAsLogger()` / `maybeUpgradeToPino()` 及配套懒升级机制;内核不再加载任何第三方日志库、不做任何运行时模块解析(此前该动态导入会被宿主 bundle 内联,把内核运行时绑到宿主模块图)
|
|
1209
|
-
- **`package.json`**:删除 `peerDependencies` / `peerDependenciesMeta`(pino 为唯一条目);`devDependencies` 删除 `pino` / `pino-pretty`
|
|
1210
|
-
- **内核侧文件日志退场**:随之删除 `MEMORA_DATA_DIR` / `MEMORA_LOG_FILE` 两个进程级隐式契约(仅文件日志在用,宿主从未设置)
|
|
1211
|
-
- **日志形态对宿主零影响**:仍为「默认内置 console fallback(写 stderr,级别由 `MEMORA_LOG_LEVEL` 控制)+ 宿主经 `setLogger()` 注入」,VS Code 宿主注入通道(`hosts/memora-vscode/src/extension/host/assemble.ts`)不变;`logger` 门面由 getter 改为普通委托闭包(函数身份稳定)
|
|
1212
|
-
- **`setLogger` 注入即唯一出口**:注入分支补齐 utils 层桥接(`utils/loggerHolder`),`scanner` / `eventEmitter` / `rolePackManager` 等 utils 侧模块随宿主注入统一切换(此前注入只覆盖 `logging/` 门面,utils 侧停留在 console fallback)
|
|
1213
|
-
- **文档收口**:api-reference / 接入指南 / ADR-002 补充节同步订正「零控制台输出」「pino 可选 peer」等过时表述
|
|
1214
|
-
|
|
1215
|
-
> 非破坏性变更:宿主注入通道与 `ILogger` 契约不变;未注入时行为从「尝试 pino、失败降级 console」变为「始终内置 console fallback」。README 双语(console fallback 口径)此前已一致,无需变更。
|
|
1216
|
-
|
|
1217
|
-
### Added(外部世界工具族:`web_fetch` 搜索→抓取闭环 + `run_code` 通用代码执行)
|
|
1218
|
-
|
|
1219
|
-
源自工具面盘点(tool-surface-roadmap.md):`web_search` 只搜不抓、通用计算缺失。沿既有范式(接口注入 + 条件性暴露 + 降级优先 + 零依赖边界)补齐两个「连接外部世界」的条件工具。
|
|
1220
|
-
|
|
1221
|
-
- **网页抓取(`src/web-fetch/`)**:`IFetchProvider` 接口(与 `IWebSearchProvider` 同构);`FetchWebFetchProvider` 零依赖默认实现(内置 fetch + 正则清洗 HTML + `<title>` 提取 + maxChars 截断);`safeFetch` 30s 超时保护包装(失败/超时降级友好提示,不中断主流程)
|
|
1222
|
-
- **代码执行(`src/code-exec/`)**:`ICodeExecutionProvider` 接口(沙箱完全由宿主 provider 决定,内核零运行时依赖);`safeExecuteCode` 120s 超时保护包装(失败/超时降级返回错误结果)
|
|
1223
|
-
- **工具集成(`agent/builtinTools.ts` + `toolExecutor.ts`)**:新增 `WEB_FETCH_TOOL` / `RUN_CODE_TOOL` 定义 + 幂等标记(web_fetch=idempotent,run_code=non-idempotent);条件性暴露(注入 provider 才进入 LLM 工具面);执行分支含 URL 协议白名单 / 长度上限 / 结果净化 / 三态格式化
|
|
1224
|
-
- **注入链打通**:`AgentOptions.fetchProvider` / `codeExecutionProvider` 经 `assembler.ts` → `agent.ts` → `index.ts` 导出(接口 + 默认实现 + safe 包装)
|
|
1225
|
-
- **能力映射**:`capabilityMap` 新增 `web:fetch` → web_fetch、`code:execute` → run_code
|
|
1226
|
-
- **文档收口**:api-reference(注入接口 / AgentOptions / 内置工具表 / §8.4-8.5 / 类型导出)、接入指南(§4.5 外部世界工具注入)、module-inventory(§3.5)、README(核心能力 + 示例角色包随包)
|
|
1227
|
-
- **测试**:新增 7 组(provider 纯函数 × 2、默认实现解析 × 1、工具定义 × 2、条件暴露/执行/冲突 × 2、capability 映射 × 2),含本次 web-fetch/code-exec 共 130 用例全绿
|
|
1228
|
-
|
|
1229
|
-
> 非破坏性变更:未注入 provider 时工具不暴露(零依赖边界保持);`run_code` 沙箱隔离等级由宿主 provider 决定,接入前需评估安全边界。
|
|
1230
|
-
|
|
1231
|
-
### Added(结构化信息保真 + 提炼侧视角下沉:`summaryFocus` 提炼视角机制)
|
|
1232
|
-
|
|
1233
|
-
源自 LLM 视角 memora-as-agent 体感评估 P1 缺口「结构化信息保真」 + P2「提炼侧视角对齐」——代码/diff/表格等结构化信息经 round-summary 浓缩后保真度低,且提炼侧「值得记什么」仍为通用视角。沿内核哲学(领域无关 + 角色包插卡)落地的通用机制,让角色包声明「摘要提炼的视角(判断维度 + 结构保留形式)」。
|
|
1234
|
-
|
|
1235
|
-
- **内核机制(`role-pack/types.ts`)**:`PrepareStrategy` 新增可选 `summaryFocus`(角色包提炼视角);新增 `resolveSummaryFocus` 解析函数(合法非空字符串采用、缺失/空白归位 undefined=通用浓缩)
|
|
1236
|
-
- **摘要参数化(`roundSummaryGenerator.ts`)**:拆出 `SUMMARY_JSON_CONTRACT`(JSON 输出 + SummaryType 硬契约,角色包不可替换,写路径 metadata 稳定)与 `DEFAULT_SUMMARY_PERSPECTIVE`(通用"意图/回答/决策"归纳);`generate` 第 5 参 `focus` 存在时以角色包提炼视角**替换**通用视角;缺省时逐字节零回归
|
|
1237
|
-
- **装配接线(`agent.ts`)**:postProcess 注入激活角色包的 `summaryFocus`(`resolveSummaryFocus(this.getActiveStrategy())`)
|
|
1238
|
-
- **验证器(`validator.ts`)**:`STRATEGY_KEY_RULES.prepare` 注册 `summaryFocus`(非空字符串校验),避免角色包声明产生未知键警告
|
|
1239
|
-
- **角色包消费者**:示例库 `代码助手`、两库 `方案设计师` 声明完整提炼视角(判断维度 + 结构保留,首个消费者,尚未触发「≥2 处复用」机制化提炼)
|
|
1240
|
-
|
|
1241
|
-
> 非破坏性变更:内核零领域特化(提炼视角内容全由角色包提供,未 hardcode 代码/表格);角色包未声明 `summaryFocus` 时摘要输出与升级前逐字节一致;typecheck + 全量测试通过。
|
|
1242
|
-
|
|
1243
|
-
### Added(插件 MVP:方案设计师 showcase 体验——空状态示例提问随角色特化)
|
|
1244
|
-
|
|
1245
|
-
插件 MVP 落地——让用户能通过插件一键体验 memora 最吸引人的设计魅力。审查插件与 memora 内核对齐情况后,聚焦「方案设计师 showcase」体验:把空状态示例提问从"文档打磨通用引导"升级为"随 showcase 角色动态渲染",新用户切到方案设计师时,首屏即见「种子收敛」引导示例。
|
|
1246
|
-
|
|
1247
|
-
- **空状态示例提问动态化(chatView.ts)**:新增 `ROLE_SUGGESTION_SETS`(SSOT 映射,key=角色显示名)+ `DEFAULT_SUGGESTIONS` 通用回退;`renderEmptySuggestions(name)` 按激活角色渲染示例 chips——方案设计师展示「设计知识库 / 设计记忆系统 / 找最小单元」种子收敛引导,其余角色回退「审阅架构 / 精简表达 / 对齐实现」通用打磨引导
|
|
1248
|
-
- **示例容器改造(chatPanel.ts)**:`#emptySuggestions` 从静态三个 chip 改为空容器,由脚本填充;HTML 注释同步更新
|
|
1249
|
-
- **事件委托**:chips 点击改为 document 级委托,兼容动态渲染新增元素(dropdown 同类惯例)
|
|
1250
|
-
- **测试**:chatView.test.ts 新增 showcase 特化用例(方案设计师专属 / 非 showcase 回退通用),测试骨架补 `#emptySuggestions` 容器
|
|
1251
|
-
|
|
1252
|
-
> 非破坏性变更:仅插件 UI 层空状态引导演进,内核与角色包内容零改动;插件 typecheck / 66 测试 / esbuild 构建(webview 打包)全通过。
|
|
1253
|
-
|
|
1254
|
-
### Added(方案设计师角色包:memora 设计哲学沉淀为可复用装载卡)
|
|
1255
|
-
|
|
1256
|
-
把 memora 的设计哲学(单一真理源 · 最小单元 · 网络为土壤)抽象为可复用的角色包「方案设计师」,供新开项目方案时直接装载复用——基于 `.trae/rules/` 的 `single-truth-source-mindset` / `network-soil-mindset` / `architecture_philosophy_rules` 提炼为 LLM 可执行的设计指令。
|
|
1257
|
-
|
|
1258
|
-
- **persona.md**:定位「从模糊想法设计自洽项目方案的顾问」,承载种子(最小单元锚点)/ 土壤(网络信息养分)两条设计主线
|
|
1259
|
-
- **rules.md**:设计指令——先搜索再构思、种子定位、SSOT、最小单元解题、识别补丁思维、外部方案种子过滤、搜索结论进入决策、记录来源、种子收敛交互、产出结构、SSOT 三问收敛自检、不越界生成骨架
|
|
1260
|
-
- **manifest.skills**:声明 `file:read` / `file:write` / `web:search` / `memory:recall` / `llm:summarize` 五个可调用能力,让角色能真正「先搜索再构思」、读写方案文档
|
|
1261
|
-
- **落地**:插件生产库(`hosts/memora-vscode/src/extension/role-packs/方案设计师/`,随 VSIX 分发)+ 根示例库(`role-packs/方案设计师/`,参考指引),两包 manifest 均通过标准校验(`validateManifestText` valid=true)
|
|
1262
|
-
|
|
1263
|
-
> 非破坏性变更:纯新增角色包,内核零改动;新增包经 validator 校验合规,全量测试无回归。
|
|
1264
|
-
|
|
1265
|
-
### Added(方案设计师:种子收敛交互引导)
|
|
1266
|
-
|
|
1267
|
-
设计评审收敛——最小单元(种子)藏在用户业务里,LLM 无法凭空替用户定义,故把角色包从"被动澄清"升级为"主动引导用户收敛种子"的交互方法论(承载于 persona.md + rules.md,非工具能力)。
|
|
1268
|
-
|
|
1269
|
-
- **persona.md 新增「种子收敛交互」章节**:收敛五步——问最小闭环(一次触发→处理→输出)→ 问边界(谁触发/给谁用)→ 问不可再拆 → 问三性(自足/可重复/可观察)→ 复述确认;拿到用户确认的种子前不急于设计
|
|
1270
|
-
- **核心能力「种子识别」→「种子引导收敛」**:从"替用户提炼"改为"引导用户自己收敛"
|
|
1271
|
-
- **rules.md「主动澄清」→「种子收敛交互」**:设计前先收敛种子,不替用户定义;用户明确拒绝探讨时,提示"种子未锁定可能返工"并按指示继续
|
|
1272
|
-
- 两库(生产 + 示例)persona.md / rules.md 同步更新;manifest 未变
|
|
1273
|
-
|
|
1274
|
-
> 非破坏性变更:仅角色包内容演进,内核与 manifest 零改动。
|
|
1275
|
-
|
|
1276
|
-
### Added(召回互斥前置过滤:跨会话记忆补位 top-limit)
|
|
1277
|
-
|
|
1278
|
-
基于设计评审(recall-mutex-pre-filter)落地——把"召回后互斥排除"改为"recall 内取 limit 前过滤",修复单会话聚焦时跨会话记忆被挤出 top-limit 的缺陷,补齐新会话 0 上下文时召回最近摘要的自然行为(memory-as-summary §4.3)。
|
|
1279
|
-
|
|
1280
|
-
- **`recall` 新增 `excludeRoundIds` 选项**:在 `hybridMerge` 排序取 limit **前**过滤命中集合的 round-summary,让跨会话/更早轮次记忆补位;保底补足同样应用该过滤,避免把正文已加载的摘要补回(重复注入)
|
|
1281
|
-
- **`agent.ts` 移除后置互斥过滤块**:`recallAndInject` 把 `getRecentRoundIds(recentRounds)` 结果作为 `excludeRoundIds` 传入 recall(),去重职责收敛到 recall 一处(SSOT)
|
|
1282
|
-
- **向后兼容**:`excludeRoundIds` 缺省为空集合,纯检索调用方(multiHop、memoryInspector 等)行为完全不变
|
|
1283
|
-
|
|
1284
|
-
> 非破坏性变更:仅新增可选参数;去重语义等价(同一 roundId 集合、同一 N 来源 `resolveRecentRounds`),跨会话召回能力修复。
|
|
1285
|
-
|
|
1286
|
-
### Added(建议B落地:"模型看到了什么"的指纹可追溯)
|
|
1287
|
-
|
|
1288
|
-
基于 Harness 排雷评估(harness-borrowing-assessment 建议B),落地可观测性指纹埋点——记录"模型看到了什么"的指纹 hash,**不记录全量内容、不入 sessionStore**(memory-as-summary §5.2.1 可追溯性边界)。
|
|
1289
|
-
|
|
1290
|
-
- **新增 `sha256Fingerprint`**:`src/utils/hash.ts` 通用 SHA-256 指纹纯函数,并复用于 `workProjection.ts`(消除重复 createHash 实现)
|
|
1291
|
-
- **`llm.call` span 补 `systemPromptHash`**:最终发给模型的全部 system 消息内容指纹(loop.ts LLM_CALL 埋点)
|
|
1292
|
-
- **`recall.recall` span 补 `attachedMemoryCount` / `attachedMemoryFingerprint`**:附着进上下文的记忆条数与 ID 集合指纹(loop.ts 记忆注入点埋点)
|
|
1293
|
-
- **零开销边界**:宿主未注入 Tracer(NOOP)时不计算指纹;span 属性由宿主自行采集/落盘/展示(机制/策略分离)
|
|
1294
|
-
|
|
1295
|
-
> 非破坏性变更:仅新增 span 属性与工具函数,无公共 API 变更。
|
|
1296
|
-
|
|
1297
|
-
### Added(召回保底:兜底最近记忆,保证每轮记忆下限)
|
|
1298
|
-
|
|
1299
|
-
基于会话冷启动评估收敛(放弃独立"固定注入摘要"、信任 recall)后的落地补充——当语义召回结果不足时,用最近记忆补足,避免"零召回/极少召回"导致 LLM 完全无记忆可依(memory-as-summary §4.7)。
|
|
1300
|
-
|
|
1301
|
-
- **`recall` 新增 `minFallback` 选项**:语义召回结果少于阈值时,经 `storage.search('', n)` 空查询通道按 score 降序补足最近记忆;补足项排语义命中之后、与主流程同过滤(excludeSources + 差异化时间窗口 + 去 superseded);置 0 彻底关闭
|
|
1302
|
-
- **角色包 `prepare.minFallback`**:宿主可配置召回保底下限,非法/缺失回退内核默认 2;`resolveMinFallback` SSOT 归位
|
|
1303
|
-
- **`DEFAULT_MIN_FALLBACK` 下沉 `utils/recallDefaults.ts`**:跨 role-pack 与 memory 共享同一默认值(SSOT 单一来源)
|
|
1304
|
-
|
|
1305
|
-
> 非破坏性变更:仅新增可选参数与配置维度,默认值 2 保持原有召回行为,无公共 API 破坏。
|
|
1306
|
-
|
|
1307
|
-
### Removed(洞察层移除,记忆收敛为 round-summary 单轨)
|
|
1308
|
-
|
|
1309
|
-
基于"摘要即记忆"架构定案(memory-as-summary §七 最终形态),移除独立洞察提炼层——其能力被 round-summary 的 type 分类吸收,记忆收敛为单一存储层。同时移除用户画像层(已收敛为 `type=preference` 差异化召回)。
|
|
1310
|
-
|
|
1311
|
-
- **移除 InsightExtractor 自动抽取**:`src/agent/managers/insightExtractor.ts` 删除,`assembler` 不再装配,`Agent.archiveInsight()` / `insight` getter 删除
|
|
1312
|
-
- **移除 `insightExtracted` 事件**:不再有发射方,从 `AGENT_EVENTS` 与 `AgentEventMap` 清除
|
|
1313
|
-
- **`archiveFailed.stage` 收敛为 `'content'`**:原 `'insight' | 'content'`,洞察阶段移除后仅剩 content
|
|
1314
|
-
- **`ArchiveMode` 三态收敛为二态 `'full' | 'manual'`**:原 `'insights-only'`(仅洞察自动)因洞察移除失去语义,与 `manual` 等价,一并移除
|
|
1315
|
-
- **memoryAdded 事件出口迁移**:由 RoundSummaryGenerator 在 round-summary 写入后发射(`setOnMemoryAdded`),替代原洞察层"已沉淀"通知
|
|
1316
|
-
- **SessionArchiver(content 会话归档)保留**:非洞察,承载会话级综合提炼,粒度(会话级)与 round-summary(轮次级)不同
|
|
1317
|
-
|
|
1318
|
-
> ⚠️ **破坏性变更**:移除 `ArchiveMode` 的 `'insights-only'` 值与 `insightExtracted` 事件。宿主若使用需适配(sprite 适配另行处理)。
|
|
1319
|
-
|
|
1320
|
-
### Changed(架构文档排雷:角色包优先级后置)
|
|
1321
|
-
|
|
1322
|
-
基于架构交叉审查(agent-design-philosophy / memory-as-summary / role-pack-spec / mvp-scope),确立**角色包优先级后置于内核基础**(问答闭环 + 记忆系统),并解除基础模块对未定型角色包键的耦合——避免角色包接口随基础演进反复横跳。纯文档/架构层变更,无公共 API 变更。
|
|
1323
|
-
|
|
1324
|
-
- **记忆模块解耦**:互斥窗口 N 改由内核上下文装配提供默认值,角色包 `recentRounds` 仅作后置可覆盖项(memory-as-summary §4.3),记忆模块不再依赖草案键即可独立运行
|
|
1325
|
-
- **召回开关 × type 差异化**:新增 §4.2.1 明确角色包召回开关(memoryRecall/summaryRecall,角色级总开关)与 type 差异化召回(召回内策略)的两层协作语义
|
|
1326
|
-
- **配额分层**:§6.5 补记忆/摘要 token 配额分层约束
|
|
1327
|
-
- **§14.3 定位澄清**:明确为 memora 内部设计全景,是否入标准由角色包标准双闸门裁决(避免僵尸键)
|
|
1328
|
-
- **主动提问定位**:§14.3 全局策略补 `askOn/askLimit`,统一"理解确认/用户追问/askOn"命名关系
|
|
1329
|
-
- **标准滞后修正**:`reflect.insightExtraction` 标注为兼容键(独立洞察层已随"记忆即摘要"移除)
|
|
1330
|
-
- **标准演进状态**:role-pack-spec 声明处草案演进期,v1 字段冻结延后至基础定型
|
|
1331
|
-
- **MVP 对齐**:角色包样例重写为 spec §2.3 标准格式;记忆措辞对齐"摘要即记忆";补记忆跨任务验收项;temperature 改为不承诺随包生效
|
|
1332
|
-
|
|
1333
|
-
第二轮质量审查(对齐设计哲学 + 2026 行业)排雷落地——纯文档/架构层变更:
|
|
1334
|
-
|
|
1335
|
-
- **记忆维护取舍声明**(memory-as-summary §5.4):显式声明 append-only 模型将"重复/冲突/过期"交 LLM 时间序聚合是有意取舍,type 分层作确定性兜底;记忆维护列为远期锚点(在闭环后处理内生长,不引入 merge/supersede 状态机)
|
|
1336
|
-
- **检索侧补写**(memory-as-summary §4.7):rerank / 同窗口优先对齐实现;query 改写等标远期不预埋
|
|
1337
|
-
- **自审查轮定义**(mvp-scope,正文已随 2026-09-18 瘦身):判据绑定外部确定性验证信号,防纯 LLM 自审的"自说自话"
|
|
1338
|
-
- **可观察契约**(agent-design-philosophy §13.x):闭环"可观察"固有属性产品化为"内核产活动事件、宿主渲染",守零依赖内核边界
|
|
1339
|
-
|
|
1340
|
-
第三轮对抗性审查(第一性原理 + SSOT 自检)排雷落地——纯文档/架构层变更:
|
|
1341
|
-
|
|
1342
|
-
- **G2 写路径取代检测**(memory-as-summary §5.4):记忆冲突消解从"读时靠 LLM 时间序猜"改为"写时定"——闭环后处理生成摘要时检测同类覆盖,给旧摘要打确定性 `superseded` 标记;SSOT 自检通过(不新增存储/系统/关系图,效率挪移)
|
|
1343
|
-
- **G5 结构化提问事件**(mvp-scope(正文已随 2026-09-18 瘦身)/ philosophy §13.x / §14.3):LLM 以 `[ASK]` 结构化输出 → 内核确定性解析为 `question_pending` 事件,消除"避免启发式却靠宿主猜文本"的逻辑矛盾;为活动事件流落地首个真实用例
|
|
1344
|
-
- **G4 对话记录定位统一**(memory-as-summary §5.2):从"展示层"改为"展示层 + 溯源兜底的运行依赖",消除定位分裂
|
|
1345
|
-
- **G1 摘要保真声明**(§5.4):摘要是"有损线索",保真由 traceSummary 兜底,诚实声明
|
|
1346
|
-
- **G3 串行边界声明**(philosophy §13):串行是单 Agent 阶段刻意约束,非普适真理,化解与多 Agent 愿景的张力
|
|
1347
|
-
- **G6 角色包差异化天花板**(role-pack-spec §三 L2):声明 L2 枚举只承诺行为参数,价值分层 = L1 专业性 / L2 行为偏好 / L3 能力扩展
|
|
1348
|
-
- **G9 删 Trigger 三元组预埋**(philosophy §2.1):删除 `{意图,载荷}` 预埋字段,保留扩展性说明,遵守"不预埋接口"
|
|
1349
|
-
- **G0 三阶段措辞**(philosophy §1.2):明确三阶段是"经验证的合理划分"而非"公理必然"
|
|
1350
|
-
|
|
1351
|
-
第四轮质量审查(安全 / 可观测 / 2026 生态)排雷落地——纯文档/架构层变更:
|
|
1352
|
-
|
|
1353
|
-
- **H1 信任边界**(philosophy §6.3):装配区分信任等级——召回/工具结果是 untrusted data、保持来源标记,system prompt 只由高信任源构成,防间接注入/记忆投毒
|
|
1354
|
-
- **H3 评估视角**(philosophy §13.x,远期):事件流承载 run/session 两级轨迹可回放,结合自审查轮验证信号导出回归用例;复用已有组件,不引入独立评估引擎
|
|
1355
|
-
- **H2 角色包安全审计**(role-pack-spec §七):确立"安全审计是角色包发布前提"硬门槛(行业实证 36% 注入),当前声明、远期实现
|
|
1356
|
-
|
|
1357
|
-
第五轮排雷落地(梁文锋视角对抗审查 → 真实代码核实)——ADR-023 + 设计文档更新:
|
|
1358
|
-
|
|
1359
|
-
- **C1 摘要成本重构**(philosophy §12.2 / ADR-023):修正"截断时现调 LLM"实现缺口——截断优先取用 round-summary、保留更多原始对话靠 prompt cache、摘要生成退出关键路径
|
|
1360
|
-
- **C2 即时注入防御**(philosophy §6.3 / ADR-023):工具结果 `<tool_result>` 隔离包裹 + 参数校验 + 返回净化,防间接注入
|
|
1361
|
-
- **C3 loop 收敛方向**(ADR-023):解耦 UI/可观测/外围策略,让最小闭环(调 LLM→路由→循环)渐进可见
|
|
1362
|
-
|
|
1363
|
-
SSOT 第三轮排雷:15 项契约/一致性缺陷清零,无公共 API 变更(内部修复)。
|
|
1364
|
-
|
|
1365
|
-
### Fixed(修复)
|
|
1366
|
-
|
|
1367
|
-
- **执行流单一收口**:`processEvent` / `executeChatLoop` / `resumeExecution` 统一走 `consumeExecutionStream`,清理放 finally;修复 async generator 被 `void` 调用导致函数体不执行(跨进程边界断裂)(T0-1)
|
|
1368
|
-
- **门面等宽**:`Agent.pause` 透传 `lowRisk`,连续暂停计数不再误计;`requestPause` 空闲态立即翻转、流中延迟翻转两端对称(T0-2 / T1-1 / T2-8)
|
|
1369
|
-
- **状态恢复强制归零**:`restoreFromCheckpoint` 统一 `resetToRunning()`,检查点与状态机不再分叉(T0-3)
|
|
1370
|
-
- **checkpoint schema 版本化**:`CURRENT_SCHEMA_VERSION` 写入/比对(T1-4)
|
|
1371
|
-
- **暂停超时信息事件化**:`sessionPauseTimedOut` 载荷携带 sessionId/date/session(T1-2)
|
|
1372
|
-
- **任务项状态唯一写点**:`completeRound` 改走 `updatePlanItemStatus`,消灭旁路直改(T2-1)
|
|
1373
|
-
- **暂停元数据时序修正**:`setPauseMeta` 首轮 checkpoint 兜底,注释纠正 onPaused 先于 pause()(T2-6)
|
|
1374
|
-
- **配置建议重建复活**:`confirmConfigSuggestion` upsert 前 restore 同名软删记忆 + name 白名单堵路径穿越(T2-4)
|
|
1375
|
-
- **暂停起点与心跳解耦**:新增 `checkpoint.pausedAt`,暂停后 touchCheckpoint 刷新不再推迟超时判定(T2-2)
|
|
1376
|
-
- **孤儿向量清理**:`writePurge` / `writePurgeExpired` 同步清理 vectorStore,消除 30 天自动清理后的孤儿向量(T2-5)
|
|
1377
|
-
|
|
1378
|
-
### Removed(移除)
|
|
1379
|
-
|
|
1380
|
-
- 零注册的 `onBootstrapSyncFailed` 死回调(失败可观测性由 logger.warn 承担)(T2-3)
|
|
1381
|
-
- `SessionStateMachine.onEvent` 空壳与失效注释(T2-7)
|
|
1382
|
-
|
|
1383
|
-
### Internal(内部变更,不影响公共 API)
|
|
1384
|
-
|
|
1385
|
-
- 测试用例总数 1949 → 1983(+34,80 个测试文件)
|
|
1386
|
-
|
|
1387
|
-
### Fixed(术语载体门禁「历史层续命」:旧词消失检测失效 + 旧词复活不可见)
|
|
1388
|
-
|
|
1389
|
-
- **根因**:CHANGELOG / ADR / 过程文档 / 台账按「历史不改写」纪律永久保留旧词,与代码共锁一份集合时旧词被历史层**续命**——①「旧词消失」对已正名词永不报警;②旧词**复活进代码**也不报警(集合没变)。与「脚本扫自身」是同一失效模式的第二个载体(`SELF_REL` 的教训推广到历史层)。
|
|
1390
|
-
- **收敛(同模式,非新机制)**:分层基线——**code 层**(`src` / `hosts` / `scripts` = 现行契约)与 **text 层**(文档 / 台账 / 历史档)各锁一份集合(`BASELINE_CODE` / `BASELINE_TEXT`)。旧词从 code 消失 = 正名完成信号;旧词出现在 code = 回归报警(门禁的牙在此)。text 层为弱判据(历史续命仍在层内,文档层回归靠审查)——边界写进脚本「范围边界与已知盲区」。
|
|
1391
|
-
- **本条更新两条旧表述**:①「Fixed(脚本扫自身)」条的「已知边界」——消失报警在 code 层内已是一级信号,且分层后该条「写出旧名即报新增」的自限不再适用于 text 层旧词;②同条 `MIN_FROZEN` 随锚点 §3 收口升为 6。
|
|
1392
|
-
- **变异实测(双向)**:`PlanStep` / `perStep` / `step_id` 注入 code 层 → code 层报警「新增 3」、text 层纹丝不动(修复前此场景静默绿);基线幽灵条目 → 报警「消失 1」;还原后 code 63 / text 75 双绿。
|
|
1393
|
-
|
|
1394
|
-
### Changed(冻结例外收口锚点 §3 单一真源 + 测试注释 bare「步」收尾)
|
|
1395
|
-
|
|
1396
|
-
- **冻结例外单一真源**:`step-end` / `data-step-bucket` / `animation-iteration-count` 补入术语锚点 §3(原先仅在本文件口头列为硬边界,门禁 frozen 解析不知情);门禁 `MIN_FROZEN` 阈值 3 → 6。
|
|
1397
|
-
- **测试注释收尾(58 处)**:测试文件注释与 it 标题中指任务表一行的「步骤 / 提问步 / 当前步 / 下一步」等正名为「任务项 / 项」;「工具步」(step 阵营 = 一次产工具调用的 LLM 调用)统一为「带工具调用的 step」。**边界不动**:样本数据字面量(`description: '步骤一'` 等,内容非载体)、断言引用的生产原文、通用词(同步 / 逐步 / 多步 / 按步推进)。
|
|
1398
|
-
|
|
1399
|
-
### Changed(收尾叙述句正名「执行 N 步工具」→「工具×N(分型)」+ 宿主测试注释收尾)
|
|
1400
|
-
|
|
1401
|
-
- **UI 文案(`hosts/memora-vscode` webview)**:收尾叙述句「执行 N 步工具(读取 x · 搜索 y)」把**一次工具调用**叫「步」——违术语锚点 §1「step 不是一次工具调用」+ 工具类文案「用批或纯计数」约定。改「工具×N(读取 x · 搜索 y · 写入 z)」:形状取纯计数,拼写并入既有 `工具×N`(U+00D7 语义乘号)形态,与同表达式 fallback 及 `iconLanguage` 判据同拼写,不造第二种乘号写法。测试断言联动 2 处。
|
|
1402
|
-
- **宿主测试注释收尾(14 处)**:`chatView.test.ts` 任务表语义「步 / 步骤 / 步级」(按步归组 / ≥3 步 / 当前步骤 / 两步边界 / 工具步)→「任务项 / 项」或「工具叙述」;样本数据字面量与 step 阵营断言(「第 1 步」等)不动。
|
|
1403
|
-
- **顺带**:webview 注释「active step」→「active 任务项」(同句 UI 文案本就是「执行任务项 N」)。
|
|
1404
|
-
- **门禁首次实战(消失信号)**:「步级」随正名从 code 层消失 → 分层基线报警「消失·code 1」→ 回填后 code 62 / text 75 双绿——「正名完成信号」按设计工作,非误报。
|
|
1405
|
-
|
|
1406
|
-
### Added(tool 的 step 归属补齐:`tool_start.stepIndex` 与 thought 同构)
|
|
1407
|
-
|
|
1408
|
-
- **内核事实层**:`AgentChunk.tool_start` 与 `ProcessEvent.tool_start.payload` 增可选 `stepIndex`(与 `thought.stepIndex` 逐字同构,缺省 = 无归属);`loop.executeToolCalls` 发射点单点打标(`handleToolCalls` → `executeToolCalls` 调用链逐级传号)。**单点纪律**:`tool_result` 刻意不盖章——经 `toolCallId` 归属 `tool_start`(防双写守卫测试在案)。
|
|
1409
|
-
- **宿主**:`chatPanel` `tool_start` 透传落盘——重放可读「工具是第几步执行的」,tool×step 交叉事实(同号对齐 / 按 step 统计工具用量)自此有据可查。
|
|
1410
|
-
- **测试**:内核 4 例(多 step 递增 / 同 step 并发同号 / 续跑续号 / 新轮起数)+ 防双写守卫 1 例 + 落盘断言 1 例;**变异捕红 2 场精确命中**(删打标 → 3 红零误伤;双写 tool_result → 恰 1 红 = 守卫)。
|
|
1411
|
-
- **设计裁决留档**:`step_boundary` **维持不落盘的既定契约**(`types.ts`「触发点非历史内容」)——`stepIndex` 落地后 step 边界在重放中可由序号跳变直接读出,再落盘 = 同一事实两处记载(双轨镜像),「同族半补丁」判断作废。
|
|
1412
|
-
|
|
1413
|
-
## 历史试验版本(已在 npm 作废,请勿使用)
|
|
1414
|
-
|
|
1415
|
-
## [2.1.0] - 2026-08-08
|
|
1416
|
-
|
|
1417
|
-
不中断工作模式 v2.0 与网络搜索接口版本。
|
|
1418
|
-
|
|
1419
|
-
### Added(新增)
|
|
1420
|
-
|
|
1421
|
-
- **不中断工作模式 v2.0**:支持会话暂停/恢复/分叉,通过检查点机制实现断点续跑;四级补全机制(P1-explicit / P2-memory / P3-builtin / P4-clarify)确保不中断场景下的输入完整性
|
|
1422
|
-
- **IWebSearchProvider 接口**:网络搜索能力抽象,宿主可注入自定义搜索引擎实现,内核提供默认降级策略
|
|
1423
|
-
- **FetchWebSearchProvider**:基于 DuckDuckGo HTML 的零依赖默认搜索实现,内置超时保护与错误降级
|
|
1424
|
-
- **web_search 工具**:条件性暴露,注入 IWebSearchProvider 时自动可用,未注入时 LLM 被告知搜索不可用
|
|
1425
|
-
|
|
1426
|
-
### Fixed(修复)
|
|
1427
|
-
|
|
1428
|
-
- **P0-1: MemoryRelation 孤儿边清理**:`memoryInspector.writeDelete()` / `writePurge()` 前置清理关系边,防止记忆删除后关系边残留
|
|
1429
|
-
- **P0-2: 运行时暂停超时检测**:暂停状态启动定时器,30 秒检测一次心跳,超 30 分钟自动清理检查点并重置状态机
|
|
1430
|
-
- **P1: Composer 停滞时忽略显式任务输入**:计划停滞路径前增加 `event.delta?.task === undefined` 判断,确保用户显式指定任务时优先走 P1 显式输入而非 P4 澄清
|
|
1431
|
-
- **P1-1: refreshBootstrapMemories 改为必选参数**:修复 SSOT 违反——CRUD 操作后 system prompt 中的 bootstrap 段必须同步
|
|
1432
|
-
- **P1-2: goalVersion 漂移强制暂停**:`updateGoal()` 检测到 drift 级别时自动暂停(低风险,不计入连续暂停计数)
|
|
1433
|
-
- **P2-1: consecutivePauseCount 时间衰减**:用时间戳数组替代简单计数,1 小时衰减窗口,旧暂停自动过期
|
|
1434
|
-
- **P2-2: ChatMessage 增加 name 字段**:`extractHotMemory()` 和 `restoreFromCheckpoint()` 透传 name 字段,LLM 上下文一致性增强
|
|
1435
|
-
|
|
1436
|
-
### Internal(内部变更,不影响公共 API)
|
|
1437
|
-
|
|
1438
|
-
- 版本号 v2.0.3 → v2.1.0
|
|
1439
|
-
- 新增 `src/web-search/` 模块(fetchWebSearchProvider.ts / webSearchProvider.ts / 类型定义)
|
|
1440
|
-
- `ToolExecutor` 扩展:支持 `IWebSearchProvider` 注入,条件性注册 `web_search` 工具
|
|
1441
|
-
- `builtinTools.ts` 新增 `WEB_SEARCH_TOOL` 定义与幂等性映射
|
|
1442
|
-
- 新增 16 个测试用例覆盖 web search 功能(工具结构完整性 / 执行逻辑 / provider 行为)
|
|
1443
|
-
- SSOT 修复新增 17 个测试用例(Composer 边缘场景 + checkpoint 全路径 + FetchWebSearchProvider 降级场景)
|
|
1444
|
-
- 测试文件总数 80 个,测试用例总数增至 1949 个
|
|
1445
|
-
|
|
1446
|
-
## [2.0.3] - 2026-08-01
|
|
1447
|
-
|
|
1448
|
-
npm 发布配置修复与质量加固版本。
|
|
1449
|
-
|
|
1450
|
-
### Added(新增)
|
|
1451
|
-
|
|
1452
|
-
- **`publishConfig.access = "public"`**:修复 scoped package 发布阻塞(@zooique/memora 是私有作用域,npm 默认拒绝发布)
|
|
1453
|
-
- **`keywords` 扩充至 18 个**:新增 memora / agent-memory / local-ai / embedding / vector-search / rag / zero-dependency / semantic-search / knowledge-base 及中文关键词,提升 npm 搜索曝光
|
|
1454
|
-
- **`exports` 增加 `default` 回退条件**:增强混合解析场景的兼容性
|
|
1455
|
-
|
|
1456
|
-
### Internal(内部变更,不影响公共 API)
|
|
1457
|
-
|
|
1458
|
-
- 版本号 v2.0.2 → v2.0.3
|
|
1459
|
-
|
|
1460
|
-
## [2.0.2] - 2026-07-27
|
|
1461
|
-
|
|
1462
|
-
设定模块(Persona/Skill/Rule)全链路审查与修复版本。核心收敛:角色/技能从 SQLite 记忆索引解耦、"万物皆记忆"升级为 v2 双轨模型、技能从延迟注入改为当轮实时生效。
|
|
1463
|
-
|
|
1464
|
-
### Changed(变更)
|
|
1465
|
-
|
|
1466
|
-
- **万物皆记忆 v2**:Persona 和 Skill 从 SQLite 索引解耦,改为纯文件 + 内存缓存(设定记忆不参与 recall 管线)
|
|
1467
|
-
- **Skill 当轮实时生效**:`matchAndInjectSkill()` 在 `chat()` 内 recall 后执行,匹配即注入,不再延迟到下一轮
|
|
1468
|
-
- **Persona 默认回退泛化**:`shouldFallbackToDefault()` 从硬编码 `'default'` 改为 `list[0]?.name`
|
|
1469
|
-
- **bootstrap 收敛**:`bootstrapMemories` 从 `rule + skill + persona` 收敛为仅 `rule`
|
|
1470
|
-
- **PersonaManager / SkillManager 去 SQLite 依赖**:移除 `IMemoryStorage` 构造参数,移除 `writeAllToIndex()` 调用
|
|
1471
|
-
- **自动匹配时机统一**:Persona 和 Skill 均在 `chat()` 开头执行匹配,LLM 当轮即用新设定
|
|
1472
|
-
|
|
1473
|
-
### Fixed(修复)
|
|
1474
|
-
|
|
1475
|
-
- **P0: Manual 模式角色回退**:`shouldFallbackToDefault()` 新增 mode 检查,manual 模式下不再自动回退
|
|
1476
|
-
- **P1: 消息角色标签不一致**:`chatStreamHandler` 的 `SPRITE_STREAM_START` 延迟到首个 chunk 后发送,确保 persona 已匹配
|
|
1477
|
-
- **Persona 切换参数同步**:锁定时长从 60s/3次/5分钟 更正为 30s/5次/2分钟(日志 + JSDoc + 测试)
|
|
1478
|
-
- **关键词匹配同分 tie-break**:Persona/Skill 匹配同分时增加 name 字母序二级排序
|
|
1479
|
-
|
|
1480
|
-
### Internal(内部变更,不影响公共 API)
|
|
1481
|
-
|
|
1482
|
-
- `PersonaManager.autoMatch()` 去 async(函数体无 await)
|
|
1483
|
-
- `configIndexWriter.ts` 移除(共享工具不再有消费者)
|
|
1484
|
-
- `skillManager.ts` 移除 `writeAllToIndex()` / `writeSkillToIndex()` 方法
|
|
1485
|
-
- `activeSkill` 字段移除(匹配改为当轮注入,无需跨轮状态)
|
|
1486
|
-
- `injectActiveSkill()` 方法移除(被 `matchAndInjectSkill()` 替代)
|
|
1487
|
-
- `personaManager.ts` / `skillManager.ts` 移除 `IMemoryStorage` 类型导入
|
|
1488
|
-
- 架构文档 `architecture_philosophy_rules.md` v0.8→v1.0(万物皆记忆 v2)
|
|
1489
|
-
- 分层文档 `backend_layers_rules.md` v1.1→v1.2(persona/skill 去 memory 依赖)
|
|
1490
|
-
|
|
1491
|
-
从 1.0.1 到 2.0.0 的架构收敛版本。核心目标:读写统一、记忆治理 L1~L4 全链路、god function 拆分、可观测性补全。
|
|
1492
|
-
|
|
1493
|
-
### Breaking Changes
|
|
1494
|
-
|
|
1495
|
-
> **升级指南**:以下变更需要消费者修改代码。
|
|
1496
|
-
|
|
1497
|
-
#### 1. MemoryMutator 移除,读写统一入口
|
|
1498
|
-
|
|
1499
|
-
`MemoryMutator` 类(1.0.0 引入的读写分离)已合并回 `MemoryInspector`。写方法以 `writeXxx` 前缀命名,与读方法统一在 `agent.memory` 上。
|
|
1500
|
-
|
|
1501
|
-
| 1.0.1 调用方式 | 2.0.0 迁移路径 |
|
|
1502
|
-
|---|---|
|
|
1503
|
-
| `agent.memoryMutator.upsert(memory)` | `agent.memory.writeUpsert(memory)` |
|
|
1504
|
-
| `agent.memoryMutator.delete(id)` | `agent.memory.writeDelete(id)` |
|
|
1505
|
-
| `agent.memoryMutator.restore(id)` | `agent.memory.writeRestore(id)` |
|
|
1506
|
-
| `agent.memoryMutator.purge(id)` | `agent.memory.writePurge(id)` |
|
|
1507
|
-
| `agent.memoryMutator.purgeExpired(before)` | `agent.memory.writePurgeExpired(before)` |
|
|
1508
|
-
| `agent.memoryMutator.addRelation(rel)` | `agent.memory.writeAddRelation(rel)` |
|
|
1509
|
-
| `agent.memoryMutator.removeRelation(...)` | `agent.memory.writeRemoveRelation(...)` |
|
|
1510
|
-
| `import type { MemoryMutator }` | 移除,不再导出 |
|
|
1511
|
-
|
|
1512
|
-
**保留在 `agent.memory` 的只读方法**:`snapshot()` / `search()` / `searchHybrid()` / `stats()` / `getById()` / `list()` / `listDeleted()` / 关系查询方法等(不变)。
|
|
1513
|
-
|
|
1514
|
-
### Added(新增功能)
|
|
1515
|
-
|
|
1516
|
-
- **LLM 记忆治理 L1~L4**:
|
|
1517
|
-
- L1 语义去重:`agent.deduplicateMemories()` — 扫描名称相似记忆对,LLM 判断语义等价,降级重复记忆
|
|
1518
|
-
- L2 时效性评估:`agent.evaluateTimeliness()` — 扫描低分记忆,LLM 判断是否过时,降级过时记忆
|
|
1519
|
-
- L3 冲突检测:`agent.detectConflicts()` — 同 source 内配对,LLM 判断语义冲突,仅检测不修复
|
|
1520
|
-
- L0 手动衰减:`agent.runMemoryDecayOnce()` — 触发一次 score 衰减
|
|
1521
|
-
- 新增类型:`DedupPair` / `DedupVerdict` / `DedupReport`、`TimelinessVerdict` / `TimelinessReport`、`ConflictVerdict` / `ConflictReport`
|
|
1522
|
-
- **TextPolishManager**:LLM 文本润色(语法修正 + 表达优化),独立于 Agent 生命周期,通过 `TextPolishManager` 类使用
|
|
1523
|
-
- **EvalRunner 公开**:评估框架从 `@internal` 提升为公开 API,新增 `EVAL_SCENARIOS` / `EvalRunner` / `EvalRunnerOptions` / `EvalSummary` 导出
|
|
1524
|
-
- **segmentLower**:分词工具扩展,返回小写分词结果(宿主 SqliteStorage 依赖)
|
|
1525
|
-
- **isPlainObject**:纯对象类型守卫(宿主 spriteConfig 依赖,校验 JSON.parse 结果)
|
|
1526
|
-
- **ChatLockManager**:对话锁管理器(从 AgentLoop 拆分),基于 token 的并发安全机制
|
|
1527
|
-
- **ArchiveCoordinator**:归档协调器(从 postProcessInner 拆分),统一管理会话归档 + 洞察提取 + 角色匹配
|
|
1528
|
-
- **MemoryDecayScheduler**:记忆衰减调度器(从 agent.ts 拆分),定时衰减 + L2 时效性评估 + 指标统计
|
|
1529
|
-
- **MemoryAdvisor**:记忆顾问(从 MemoryInspector 拆分),sourceHealth 诊断 + suggest 关联推荐 + L3 冲突检测
|
|
1530
|
-
- `TypedEventEmitter` 新增 `emitAsync` 方法(支持异步事件处理器的 await 等待)
|
|
1531
|
-
|
|
1532
|
-
### Changed(改进)
|
|
1533
|
-
|
|
1534
|
-
- **processUserInput 拆分**:从 550+ 行 god function 拆分为 4 个职责清晰的子方法(`handleRecallAndInputGuard` / `handleIteration` / `handleToolCalls` / `handleTextResponse`),每个方法独立可测
|
|
1535
|
-
- **nullifyAllComponents 统一**:Agent.close() 中 13 个组件字段置空集中到 `nullifyAllComponents()` 私有方法,消除遗漏风险
|
|
1536
|
-
- **requireNonNull 消除**:全量替换为局部变量提取 + non-null assertion `!`,减少代码噪音
|
|
1537
|
-
- **personaManager LLM 调用迁移**:角色匹配的 LLM 调用从 persona 层迁移到 agent 层(架构分层合规)
|
|
1538
|
-
- **toError 行为对齐**:跨模块统一错误处理,`toError(nonError)` 不再抛出 TypeError
|
|
1539
|
-
- **formatDateKey 提取**:消除 3 处重复的日期格式化逻辑
|
|
1540
|
-
- **抽象剪枝 3 轮**:DRY 收敛——消除重复的工具函数、常量定义、类型推导
|
|
1541
|
-
- **types.ts 依赖图注释**:index.ts 新增完整的类型依赖图,降低新开发者学习成本
|
|
1542
|
-
- 提示词优化 + 并发工具调用 + 可观测性补全(Tracer Span 覆盖衰减/归档/冲突检测)
|
|
1543
|
-
|
|
1544
|
-
### Fixed(修复)
|
|
1545
|
-
|
|
1546
|
-
- 神木回天 6 项修复:日志改进、硬约束测试补全、错误处理路径修复
|
|
1547
|
-
- 感知层模式陈旧 bug:`welcomeBack` 文案 + 冷启动 blend 逻辑修复
|
|
1548
|
-
- P3 静默 catch 修复:不再吞掉关键错误
|
|
1549
|
-
- 归档失败事件 `archiveFailed` 可观测性补全(11 处测试覆盖)
|
|
1550
|
-
|
|
1551
|
-
### Internal(内部变更)
|
|
1552
|
-
|
|
1553
|
-
- `memoryMutator.ts` 文件删除,写方法合并到 `memoryInspector.ts`(`writeXxx` 前缀)
|
|
1554
|
-
- `archiveCoordinator.ts` 独立模块(从 `agent.ts` 提取)
|
|
1555
|
-
- `chatLockManager.ts` 独立模块(从 `loop.ts` 提取)
|
|
1556
|
-
- `memoryDecayScheduler.ts` 独立模块(从 `agent.ts` 提取)
|
|
1557
|
-
- `memoryAdvisor.ts` 独立模块(从 `memoryInspector.ts` 提取)
|
|
1558
|
-
- `textPolishManager.ts` 新增模块(纯 LLM 调用,无存储依赖)
|
|
1559
|
-
- 测试补强:L2 时效性评估测试、衰减边界测试、各 Manager 测试大幅扩展(+500+ 测试用例)
|
|
1560
|
-
|
|
1561
|
-
## [1.0.2] - 2026-07-11
|
|
1562
|
-
|
|
1563
|
-
### Changed
|
|
1564
|
-
|
|
1565
|
-
- `EmbeddingOptions` 接口归属位置从 `llm/embedding.ts` 调整到 `memory/vectorStore.ts`(符合依赖倒置原则:消费者定义接口,提供者通过 `import type` 引入)
|
|
1566
|
-
- 顶层导出不变(`index.ts` 已同步更新导出路径),外部消费者无需修改导入语句
|
|
1567
|
-
|
|
1568
|
-
## [1.0.1] - 2026-07-08
|
|
1569
|
-
|
|
1570
|
-
### Fixed(P2 遗留项修复)
|
|
1571
|
-
|
|
1572
|
-
- coverage 阈值从 75/85/70/75 提升至 80/88/75/80
|
|
1573
|
-
- pathGuard 黑名单新增 `.envrc` 拦截规则(direnv 配置文件)
|
|
1574
|
-
- decisions/README.md ADR 索引补全 ADR-005 保留行
|
|
1575
|
-
- kernel-ci.yml 测试数量注释更新
|
|
1576
|
-
|
|
1577
|
-
## [1.0.0] - 2026-07-08
|
|
1578
|
-
|
|
1579
|
-
从 0.3.0 到 1.0.0 的完整架构收敛版本。核心目标:接口稳定化、职责分离、韧性补齐、公共 API 收敛。
|
|
1580
|
-
|
|
1581
|
-
### Breaking Changes
|
|
1582
|
-
|
|
1583
|
-
> **升级指南**:以下变更需要消费者修改代码。所有 Breaking Changes 均有 1:1 迁移路径。
|
|
1584
|
-
|
|
1585
|
-
#### 1. 记忆读写分离:`agent.memory` → `agent.memoryMutator`
|
|
1586
|
-
|
|
1587
|
-
`MemoryInspector` 中的写操作方法已迁移到新类 `MemoryMutator`,实现读写职责严格分离(ADR-010 补充)。
|
|
1588
|
-
|
|
1589
|
-
| 0.3 写方法(`agent.memory.xxx`) | 1.0 迁移路径(`agent.memoryMutator.xxx`) |
|
|
1590
|
-
|---|---|
|
|
1591
|
-
| `agent.memory.upsert(memory)` | `agent.memoryMutator.upsert(memory)` |
|
|
1592
|
-
| `agent.memory.delete(id)` | `agent.memoryMutator.delete(id)` |
|
|
1593
|
-
| `agent.memory.restore(id)` | `agent.memoryMutator.restore(id)` |
|
|
1594
|
-
| `agent.memory.purge(id)` | `agent.memoryMutator.purge(id)` |
|
|
1595
|
-
| `agent.memory.purgeExpired(before)` | `agent.memoryMutator.purgeExpired(before)` |
|
|
1596
|
-
| `agent.memory.addRelation(rel)` | `agent.memoryMutator.addRelation(rel)` |
|
|
1597
|
-
| `agent.memory.removeRelation(...)` | `agent.memoryMutator.removeRelation(...)` |
|
|
1598
|
-
|
|
1599
|
-
**保留在 `agent.memory` 的只读方法**:`snapshot()` / `search()` / `searchHybrid()` / `stats()` / `getById()` / `list()` / `listDeleted()` / `getDeletedById()` / 关系查询方法等。
|
|
1600
|
-
|
|
1601
|
-
#### 2. `VectorStore` 重命名为 `JsonVectorStore`
|
|
1602
|
-
|
|
1603
|
-
向量存储从具体类重构为接口 + 实现(ADR-016)。
|
|
1604
|
-
|
|
1605
|
-
| 0.3 导出 | 1.0 迁移路径 |
|
|
1606
|
-
|---|---|
|
|
1607
|
-
| `import { VectorStore } from '@zooique/memora'` | `import { JsonVectorStore } from '@zooique/memora'` |
|
|
1608
|
-
| `new VectorStore(path, embeddingProvider)` | `new JsonVectorStore(path, embeddingProvider)` |
|
|
1609
|
-
|
|
1610
|
-
新增 `IVectorStore` 接口,宿主可实现自定义向量存储(如 SqliteVectorStore / LanceDBVectorStore)。
|
|
1611
|
-
|
|
1612
|
-
#### 3. `ChatOptions.channel` 字段移除
|
|
1613
|
-
|
|
1614
|
-
`ChatOptions.channel?: 'chat' | 'background'` 字段从未被任何 LLM 调用路径读取,已移除。多 Provider 路由通过 `AgentOptions.backgroundProvider` 注入独立 LlmProvider 实例实现,不通过 `ChatOptions` 字段路由。
|
|
1615
|
-
|
|
1616
|
-
#### 4. `AgentChunk` 流式事件结构变化
|
|
1617
|
-
|
|
1618
|
-
多个 chunk 类型的字段结构发生变化,宿主需更新 chunk 处理逻辑:
|
|
1619
|
-
|
|
1620
|
-
| chunk 类型 | 0.3 结构 | 1.0 结构 |
|
|
1621
|
-
|---|---|---|
|
|
1622
|
-
| `recall` | `{ type: 'recall'; count: number }` | `{ type: 'recall'; memories: RecalledMemorySummary[] }`(携带记忆摘要列表,非计数) |
|
|
1623
|
-
| `text` | `{ type: 'text'; content: string }` | `{ type: 'text'; content: string; guardrailBlocked?: boolean }`(新增护栏阻断标志) |
|
|
1624
|
-
| `tool_start` | `{ type: 'tool_start'; name: string; args?: string }` | `{ type: 'tool_start'; toolCallId: string; name: string; args?: string }`(新增 toolCallId) |
|
|
1625
|
-
| `tool_result` | `{ type: 'tool_result'; name: string; ok: boolean; summary?: string }` | `{ type: 'tool_result'; toolCallId: string; name: string; ok: boolean; summary?: string }`(新增 toolCallId) |
|
|
1626
|
-
| `error` | 不存在 | `{ type: 'error'; message: string }`(新增,流式错误替代裸 throw) |
|
|
1627
|
-
| `retry` | 不存在 | `{ type: 'retry'; attempt; maxRetries; delayMs; error }`(新增,指数退避重试信号) |
|
|
1628
|
-
|
|
1629
|
-
新增 `RecalledMemorySummary` 类型(`{ id, name, score, source }`),仅暴露 UI 展示所需字段,不含 `content`。
|
|
1630
|
-
|
|
1631
|
-
#### 5. `Memory` 类型新增 `deletedAt` 字段(7→8 字段)
|
|
1632
|
-
|
|
1633
|
-
`Memory` 接口新增可选字段 `deletedAt?: string`(ISO 8601),支持软删除/回收站机制(ADR-004 GAP-6 扩展)。所有查询方法自动过滤 `deletedAt != undefined` 的记忆。
|
|
1634
|
-
|
|
1635
|
-
#### 6. `IMemoryStorage` 接口扩展(7→15 方法)
|
|
1636
|
-
|
|
1637
|
-
新增 8 个方法,宿主实现的 `IMemoryStorage` 需补全:
|
|
1638
|
-
|
|
1639
|
-
| 新增方法 | 用途 |
|
|
1640
|
-
|---|---|
|
|
1641
|
-
| `restore(id)` | 恢复软删除记忆 |
|
|
1642
|
-
| `purge(id)` | 物理删除(不可恢复) |
|
|
1643
|
-
| `listDeleted(limit?)` | 列出回收站 |
|
|
1644
|
-
| `getDeletedById(id)` | 按 ID 获取软删除记忆 |
|
|
1645
|
-
| `purgeExpired(before)` | 清理过期回收站 |
|
|
1646
|
-
| `decayScores(sources, now)` | 批量衰减 score |
|
|
1647
|
-
| `getAllSources()` | 获取 source→count 映射 |
|
|
1648
|
-
|
|
1649
|
-
(`close?()` 已在 0.3 存在)
|
|
1650
|
-
|
|
1651
|
-
#### 7. `AgentOptions` 字段变化
|
|
1652
|
-
|
|
1653
|
-
| 变化 | 0.3 | 1.0 | 迁移路径 |
|
|
1654
|
-
|---|---|---|---|
|
|
1655
|
-
| `logger` 字段移除 | `AgentOptions.logger?: ILogger` | 移除 | 改用全局 `setLogger(customLogger)` 注入 |
|
|
1656
|
-
| `archiveMode` 新增 | 不存在 | `archiveMode?: ArchiveMode`(默认 `'full'`) | 可选,不传则默认 `'full'` 全自动归档 |
|
|
1657
|
-
| `enableContextSummary` 默认值 | `false` | `true` | 如需关闭显式传 `false` |
|
|
1658
|
-
|
|
1659
|
-
#### 8. 事件载荷变化
|
|
1660
|
-
|
|
1661
|
-
三个事件的载荷结构变化,宿主事件处理器需更新:
|
|
1662
|
-
|
|
1663
|
-
| 事件 | 0.3 载荷 | 1.0 载荷 |
|
|
1664
|
-
|---|---|---|
|
|
1665
|
-
| `conflictDetected` | `{ memoryId, conflictingId, relationType }` | `{ newMemoryId, newInsight, targetId, targetContent }` |
|
|
1666
|
-
| `projectSwitched` | `{ from, to }` | `{ from: string \| null, to: string, projectName: string }` |
|
|
1667
|
-
| `skillMatched` | `{ skillName, keywords }` | `{ skill: string, score: number }` |
|
|
1668
|
-
|
|
1669
|
-
#### 9. 会话/项目方法迁移到专职 Manager
|
|
1670
|
-
|
|
1671
|
-
以下方法从 Agent 面类迁移到专职 Manager(P1-4 拆分):
|
|
1672
|
-
|
|
1673
|
-
| 0.3 调用方式 | 1.0 迁移路径 |
|
|
1674
|
-
|---|---|
|
|
1675
|
-
| `agent.switchSession(name)` | `agent.sessionManager.switchSession(name)` |
|
|
1676
|
-
| `agent.loadSessionMessages(date, session)` | `agent.sessionManager.loadSessionMessages(date, session)` |
|
|
1677
|
-
| `agent.restoreMostRecentSession(...)` | `agent.sessionManager.restoreMostRecentSession(...)` |
|
|
1678
|
-
| `agent.restoreSession(date, session)` | `agent.sessionManager.restoreSession(date, session)` |
|
|
1679
|
-
| `agent.listProjects()` | `agent.projects.listProjects()` |
|
|
1680
|
-
|
|
1681
|
-
**保留在 Agent 面类**:`switchProject()` / `rebuildComponents()` / `forkSession()`(常用入口)。
|
|
1682
|
-
|
|
1683
|
-
#### 10. `ToolExecutor` 移除 `getToolDefinitions()`
|
|
1684
|
-
|
|
1685
|
-
`agent.tools.getToolDefinitions()` 已移除,改用 `agent.tools.list`(getter)。
|
|
1686
|
-
|
|
1687
|
-
| 0.3 调用 | 1.0 迁移路径 |
|
|
1688
|
-
|---|---|
|
|
1689
|
-
| `agent.tools.getToolDefinitions()` | `agent.tools.list` |
|
|
1690
|
-
|
|
1691
|
-
#### 11. Agent 移除 `inspect()` / `getBuildCtx()`
|
|
1692
|
-
|
|
1693
|
-
`agent.inspect()` 和 `agent.getBuildCtx()` 已移除。宿主可通过事件系统、ITracer、`agent.memory.snapshot()` 观察内核状态。
|
|
1694
|
-
|
|
1695
|
-
### Added(新增功能)
|
|
1696
|
-
|
|
1697
|
-
- **`MemoryMutator`**:记忆写入器,与 `MemoryInspector` 严格分工(读写分离)
|
|
1698
|
-
- **`RelationBuilder`**:关系构建器,从 `InsightExtractor` 提取(P1-3),支持冲突检测回调
|
|
1699
|
-
- **`ProjectRegistry`** + **`LockManager`**:从 `ProjectManager` 拆分(P1-4),宿主可直接使用
|
|
1700
|
-
- **`IVectorStore`** 接口:向量存储抽象,宿主可注入自定义实现(ADR-016)
|
|
1701
|
-
- **`EmbeddingOptions`**:embedding 调用选项(`signal?: AbortSignal` + `timeoutMs?: number`),`EmbeddingProvider.embed/batchEmbed` 和 `IVectorStore` 方法支持外部取消 + 超时中断(P1-8)
|
|
1702
|
-
- **`ConflictInfo`** 类型:关系冲突信息,`RelationBuilder.bindOnConflict()` 回调参数
|
|
1703
|
-
- **`RecalledMemorySummary`** 类型:recall chunk 载荷,仅暴露 UI 展示所需字段(id/name/score/source),不含 content
|
|
1704
|
-
- **`archiveMode`** 选项:ADR-015 三态归档控制(`full` / `insights-only` / `manual`),默认 `full`
|
|
1705
|
-
- **AgentChunk 新增 `error` / `retry` 类型**:流式错误事件替代裸 throw,指数退避重试信号让宿主感知重试
|
|
1706
|
-
- **`mergeSignals`** 工具:AbortSignal 合并工具,将多个 signal 合并为一个(用于工具执行超时 + 用户取消合并)
|
|
1707
|
-
- **`guardrail.ts`** 独立模块:内容护栏纯函数 `runGuardrails()`,从 `AgentLoop` 提取(P1-1)
|
|
1708
|
-
- **`sourceValidation.ts`**:source 校验工具从 `types.ts` 拆分(P1-2)
|
|
1709
|
-
- **AgentChunk `guardrailBlocked`** 标志位:结构化护栏信号,替代中文字符串匹配(P0-7)
|
|
1710
|
-
- **`SessionArchiver`**:会话内容归档器,支持 content 类记忆归档
|
|
1711
|
-
- **`MemoryAdvisor`**:记忆建议器,提供 suggest / sourceHealth 查询
|
|
1712
|
-
- **`MemoryDecayScheduler`**:记忆衰减调度器,init 首次 + 每小时定时衰减
|
|
1713
|
-
- **ADR-016**:向量存储接口化决策记录
|
|
1714
|
-
- **ADR-015**:archiveMode 三态归档控制决策记录
|
|
1715
|
-
- **ADR-002/004/014 补充**:Logger 懒初始化、content 多用途、关系查询归属 + RelationBuilder 拆分
|
|
1716
|
-
|
|
1717
|
-
### Changed(改进)
|
|
1718
|
-
|
|
1719
|
-
- **zod schema 单一真理源**:`DEFAULT_CONFIG` 常量移除,配置默认值由 zod schema `.default()` 声明(P0-1)
|
|
1720
|
-
- **Logger 懒初始化**:`maybeUpgradeToPino()` 延迟触发,import 零 fs 副作用(P0-6)
|
|
1721
|
-
- **EmbeddingProvider 默认超时**:60 秒默认请求超时(可通过 `timeoutMs` 覆盖)
|
|
1722
|
-
- **`ProjectManager` 瘦身**:从 640 行缩减到 410 行,注册表/锁文件操作委托给 `ProjectRegistry`/`LockManager`
|
|
1723
|
-
- **`InsightExtractor` 瘦身**:关系构建逻辑委托给 `RelationBuilder`
|
|
1724
|
-
- **测试目录镜像**:`managers/__tests__/` 严格镜像 `src/` 目录结构(ADR-007)
|
|
1725
|
-
|
|
1726
|
-
### Fixed(修复)
|
|
1727
|
-
|
|
1728
|
-
- **zod schema 与 DEFAULT_CONFIG 不一致**:配置默认值单一真理源
|
|
1729
|
-
- **eval 护栏检测依赖中文魔法字符串**:改用 `guardrailBlocked` 结构化标志位
|
|
1730
|
-
- **Logger import 触发 fs 副作用**:懒初始化,import 零 IO
|
|
1731
|
-
- **Embedding 请求无超时/取消保护**:支持 AbortSignal + timeoutMs
|
|
1732
|
-
- **`insightExtractor.ts` inline `import()` 类型**:改为顶层 type import
|
|
1733
|
-
|
|
1734
|
-
### Internal(内部变更,不影响公共 API)
|
|
1735
|
-
|
|
1736
|
-
- `types.ts` 拆分为 `types.ts` + `sourceValidation.ts` + `segmenter.ts`(STOPWORDS 迁移)
|
|
1737
|
-
- `MemoryInspector` 移除写方法,保留只读编排职责
|
|
1738
|
-
- `safeTimer` 的 `clearAllSafeTimers`/`getActiveTimerCount` 已不在公共导出(早期迭代已收敛)
|
|
1739
|
-
- 11 个 manager 测试文件迁移到 `managers/__tests__/`
|
|
1740
|
-
|
|
1741
|
-
## [0.3.0] - 2026-06-27
|
|
1742
|
-
|
|
1743
|
-
Phase 5.1/5.2 初始 npm 发布版本。
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
本文件记录 **@zooique/memora(内核 npm 包)**的版本变更。**宿主**(`hosts/memora-vscode`)不在发布包 `files` 白名单内(见 `package.json`),不占内核版本号:内核与宿主各按自己的版本号成区(ADR-033),**已发布与否以 npm registry 为准**(内核 `npm view @zooique/memora dist-tags.latest`;宿主见 Marketplace / Open VSX)——本文件不复述该状态,只记各版本改了什么。
|
|
4
|
+
|
|
5
|
+
格式遵循 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/),版本号遵循 [Semantic Versioning](https://semver.org/lang/zh-CN/)。
|
|
6
|
+
|
|
7
|
+
> **版本定位(v5.x)**:**Node.js 专属 · 零第三方运行时依赖的 Agent 内核**(依赖 `node:*` 内置模块,不引第三方运行时依赖 / native / 宿主 API)。**4.0.0**:导出面收敛(−54)+ `agent.memory.search()` 退役(唯一入口 `searchByKeyword()`)。**5.0.0**:公开面大收面(删 23 导出 + 32 成员 + 3 事件)+ 多项目形态定案(一个 Agent = 一个项目)+ 三套空转机制退役 + SQLite 存储——逐项改法见[升级指南](docs/memora-升级指南-4.x-到-5.0.0.md)。**5.1.0**:MCP 工具接入的内核接口(`ToolDefinition.confirmPolicy` + `SecurityGuard` 单一确认入口)+ 脚本族执行面四面按正文裁决(`CMD-1-BYPASS` / `CMD-1-CONTENT`)——零删除、零既有签名变更。**4.0.0 及更早版本全文**:`docs/CHANGELOG-归档.md`(仓库内归档,npm 包不含)。内核不内置 agent 级行为评估(eval)/ 独立验证——由宿主基于内核可观测性(ITracer / 事件 / 指纹)自行承担;内核对接口契约与全量单测负责,不对"agent 整体行为稳定"作承诺。
|
|
8
|
+
>
|
|
9
|
+
> 本文件 2026-10-19 起按 `CHLOG-TRIM-1` 精简:只记「改了什么 + 为什么 + 对消费者的影响」;逐批拍板过程、变异验证收据、台账叙事的 SSOT 在仓库台账 `tasks/待完成任务.md` 对应 ID 条目(npm 包不含),此处只留 ID 锚保交叉引用。
|
|
10
|
+
|
|
11
|
+
## [5.1.0] · 2026-10-25
|
|
12
|
+
|
|
13
|
+
> **本区归属**:仅**内核**变更;SemVer = **minor**(零删除 / 零既有签名变更;**行为变化共三处、均为修复方向、不构成破坏性**:① 脚本族执行面按正文裁决,命中黑名单/恒弹清单的执行行为收紧;② 写侧护栏判据改为「无进展」(`write_loop` 只计整文件覆盖与连续失败写,增量写不再计数);③ `task_table_update` 不再被跨轮幂等跳过(防回喂旧任务表)。三者均见 Fixed 区)。公开面**分两层**:① **包入口符号面**增量 = **仅** `ToolDefinition` 加可选字段 `confirmPolicy`(类型面)——`SecurityGuard` 类与 `SCRIPT_READ_MAX_LEN` 均**未**从包入口 `src/index.ts` 导出;② **公开成员面**零新增(`publicMemberSurfaceGuard` 成员表未增元素),但 `agent.security` 本就是公开成员,其新增方法 `requestToolCallConfirmation(toolName, summary, needConfirm)` 对消费者**可达**(文档见 `docs/memora-api-reference.md` §2.6)。宿主侧 MCP 消费面(连接 / 设置页 / 审批卡)随宿主下一版独立成区、不占内核版本号(ADR-033)。逐条拍板与变异验证收据见仓库台账(npm 包不含):`D1-MCP` 在 `tasks/待完成任务.md` 内核 5.1.0 区;`CMD-1-BYPASS` 的实现收据见同文件 `㉔` 条、最后一面见 `tasks/archive/5.1.0-kernel.md` 的 `CMD-1-CONTENT` 条目;`CMD-1-CONTENT` / `GUARD-WRITE-PROGRESS-1` / `IDEM-TASK-TABLE-1` 均在 `tasks/archive/5.1.0-kernel.md`。
|
|
14
|
+
> **发版纪律**:本区标题日期即**实际发布日**——`scripts/verify-changelog-version.mjs`(挂 `release.yml`,不进 pre-push)校验「合法日历日期 + 与发布日相差 ≤1 天」;已发布版本的 npm tarball 不可变、改不回来(`RELEASE-CHLOG-DATE-1` 血训),故日期须在打 tag 前定稿。
|
|
15
|
+
|
|
16
|
+
### Added(内核)
|
|
17
|
+
|
|
18
|
+
**MCP 工具接入的内核接口(`D1-MCP` 切片 0 · 2026-10-23)**——MCP SDK 与传输全在宿主依赖,内核仍不认识 MCP、零第三方运行时依赖不变
|
|
19
|
+
|
|
20
|
+
- `ToolDefinition.confirmPolicy?: 'always' | 'audit'`:自定义/外部工具(如宿主接入的 MCP 工具)声明审批意图的**唯一字段**。**缺省 = 字段不存在 = 不过闸 = 现状**;刻意不设 `'never'`——宿主只需「关弹窗」,不需「关审计」。
|
|
21
|
+
- `SecurityGuard.requestToolCallConfirmation(toolName, summary, needConfirm)`:复用私有 `confirmGate` 的**单一确认入口**(一次入口、两种模式),`ToolExecutor.execute()` 的 custom 分支按上述字段过闸——`'always'` 弹确认、`'audit'` 自动放行但仍落审计,拒绝则不调 handler(`[ERR:TOOL_DECLINE]` + blocked outcome)。**为什么重要**:此前 custom 分支完全不过闸 = 动态工具源(MCP)零审批;补后**全仓仍只有一条审批路径**,不存在第二条。
|
|
22
|
+
- 审计**零新增类型**:确认统一走后恒落既有三值(`write-auto` / `write-confirm` / `write-decline`),工具调用补 `source: 'custom'` + `tool` + `path`(= 调用摘要,与 `run_command` 把命令塞 `path` 同构);`confirmGate` 加可选 `source` 末参并透传**全部四个**审计出口(写入类不传 = `undefined`,零行为变化)⇒ 宿主既有「denied 计数」自动覆盖 MCP,宿主审计面零改动。
|
|
23
|
+
- `ToolExecutor.removeTool()` 的 JSDoc 由「供测试场景使用」扩为「运行时可注销」(`K2`,零代码改动)——宿主据此实现 MCP server 停用与工具集整换。
|
|
24
|
+
- **对消费者**:纯增量。不声明 `confirmPolicy` 的既有自定义工具行为完全不变;要接入动态工具源的宿主声明字段即得审批 + 审计。
|
|
25
|
+
- ⚠️ **本期刻意不做**(`K3`,有判据的拒绝):不放宽 `ToolDefinition.parameters` 的 schema 类型(不支持嵌套 object / enum / anyOf)——`loop.ts` 的 prompt 渲染器只读顶层 `type`/`description`,放宽须连带改模型可见文案并回归全部内置工具,收益不抵风险;宿主侧以「结构映射 + 约束搬 description」适配。
|
|
26
|
+
|
|
27
|
+
**内置角色包 L1 增「编辑纪律基线」(`GUARD-WRITE-PROGRESS-1` 配套 · 2026-10-25)**
|
|
28
|
+
|
|
29
|
+
- 三个内置包(`memora助手` / `共鸣小说家` / `白话方案设计师`)的 `rules.md` 增一条**领域无关的编辑纪律**:增量写入优先(`replace` / `insert` / `append`)、同一文件多处修订在**同一回复内连续发出**、整文件覆盖仅用于确需重建且不反复覆盖、复核只读改动片段。`role-packs/` 在 `package.json#files` 内,**消费者可见**。
|
|
30
|
+
- 作者指南 §2.4 同步该基线,并明示 **L1(`rules.md` / `persona.md`)不得写运行时拒绝令牌**(`[WRITE_LOOP_STOP]` / `[WRITE_FAIL_STOP]`)——L1 常驻 system prompt,令牌会干扰「按令牌定位运行时拒绝消息」的消费方(纪律真源 `src/agent/guardRail.ts` GUIDELINES)。
|
|
31
|
+
- **为什么**:写侧护栏只拦「无进展」,**不拦「慢」**——真正决定模型行为的纪律必须写在 L1;真机 `round-1792904123909`(7 次被拦、5 处修订拖到下轮、27 分钟 / 116 万输入 token)即缺该条所致。
|
|
32
|
+
|
|
33
|
+
### Fixed(内核)
|
|
34
|
+
|
|
35
|
+
**脚本面内容裁决(`CMD-1-BYPASS` · 2026-10-25)**
|
|
36
|
+
|
|
37
|
+
- `SecurityGuard.confirmScriptRun` 接受可选第 4 参 `content`(= 将被执行的脚本/代码正文),内部喂给**同一个** `classifyCommand`:`deny` 恒拦(任何档位/权限,不进确认流程)/`always-ask` 恒弹(`owner` + `confirmScripts=false` 也弹)/`normal` 回落原档位判据。**为什么**:此前 `classifyCommand` 的唯一调用点是 `confirmCommandRun`,脚本面只看档位不看内容 ⇒「把 `git push` / `rm -rf` 写进脚本」零护栏,恒弹清单成了纸墙(一次工具调用即可绕过)。
|
|
38
|
+
- 已接入两面:`run_code`(内联代码传正文)、`run_project_script`(确认前读脚本文本);正文 > `SCRIPT_READ_MAX_LEN`(20 万字符)**拒绝执行**(fail-closed,不给「读不动就放行」的口子)。
|
|
39
|
+
- `ALWAYS_ASK` 清单补 `git clean`(此前落 normal 档 = 默认档直接执行,真洞)。
|
|
40
|
+
- `BuiltinToolHandlers.readScriptFile` 加可选 `label`(默认 `run_code script_path`):复用读正文时审计归属不再写死 `run_code`(原会把项目脚本的路径审计记到 `run_code` 头上 = 归属说谎)。
|
|
41
|
+
- 三处 decline 文案改中性措辞(「未获执行许可(命中恒拦 / 用户拒绝 / fail-closed)」)——原写「未获确认(用户拒绝…)」会把命中黑名单说成用户拒绝。
|
|
42
|
+
|
|
43
|
+
**技能脚本内容裁决(`CMD-1-CONTENT` · 2026-10-25)**
|
|
44
|
+
|
|
45
|
+
- `run_skill_script` 是脚本族最后一面(此前只判档位)。现确认点经装配期新注入字段 `ToolExecutor.resolveSkillScript`(与执行回调**共用** assembler 的 `resolveSkillScriptTarget`:角色包 → 全局池,解析顺序天然单点)定位脚本文件读正文,喂同一个 `classifyCommand`。
|
|
46
|
+
- 长度上限复用 `SCRIPT_READ_MAX_LEN`(本轮改为导出常量,三消费面共用,**不造第二上限**);**不走项目根白名单**——技能目录 = 可信根(脚本经作者审阅),路径防逃逸由解析器自身保证(角色包 layer3 白名单 + `resolveSafePath` 边界 / 全局 `resolveLayer3ScriptPath` + 存在性校验)。
|
|
47
|
+
- fail-closed 分级:解析不到 = 不传正文(维持 `[ERR:SCRIPT_NOT_FOUND]`,执行点同一解析必返 null);读失败 / 超长 = `[ERR:SCRIPT_DECLINE]` 拒绝执行。
|
|
48
|
+
- **对消费者**:`runSkillScript`(执行回调)契约与行为不变;不注入 `resolveSkillScript` 的装配(含既有单测)行为与补齐前完全一致。**至此四个执行面(`run_command` / `run_code` / `run_project_script` / `run_skill_script`)全部按正文裁决。**
|
|
49
|
+
|
|
50
|
+
> **不声称的内容(防误读)**:`classifyCommand` 是**字符串判据**——拦「模型手滑 / 幻觉 / 提示注入直接写出危险命令」,不是「危险执行总闸」;正文之外的间接载体(变量展开、编码混淆、执行期才决定的路径)拦不住。语义防护由**用户审批 + 审计溯源**承担,不由 denylist 承担。
|
|
51
|
+
|
|
52
|
+
**写侧护栏判据改为「无进展」(`GUARD-WRITE-PROGRESS-1` · 2026-10-25)**
|
|
53
|
+
|
|
54
|
+
- `write_loop` 原判据 = 「同路径连续写 N 次」,把 `mode=replace` 的逐处修订与整文件覆盖混算:第 5 次写入即硬拦,且被拦后 `read_file` **不复位**计数(`notifyExec` 原先只按 `matches` 分发,读事件根本喂不到该护栏)⇒ 该路径在**本 turn 内永久封死**。真机 `round-1792904123909` 实证:7 次被拦、5 处修订拖到下轮、27 分钟 / 116 万输入 token。
|
|
55
|
+
- 现判据 = **无进展信号**:① 仅整文件覆盖(`mode=overwrite`,缺省)计入连写(阈值 `writeLoop` 不变 = 5);② 增量写(`replace` / `insert` / `append`)每次改不同片段,**永不计数**;③ 同路径连续**失败写**达新增静态阈值 `writeFail`(= 3)即拦,读成功 / 写成功即清;④ `failed` 不再被当作一次写(原实现会推进 streak)。
|
|
56
|
+
- `notifyExec` 改为**全量分发**(各护栏在 `onExec` 内按工具自过滤)——原「借 `matches` 路由」让一个字段担两份职责,护栏文案承诺的「先读再写」出口从未生效。
|
|
57
|
+
- 新增**放行钩子** `onAllow` / `notifyAllow`(同批洞补丁,真机 `round-1792919558093`):同批工具调用先集中判定、后统一执行,判定阶段看不到结果 ⇒ 只靠执行后回喂的连写计数会被「一条回复内连发 N 次整文件覆盖」整批绕过(实测 6 次全部放行)。现于派发时**预登记整文件覆盖意图**,第 5 次同批覆盖即拦;执行回喂消费预登记(一次写只计一次),被拦未执行则撤销。增量写不登记(批量逐处修订仍零计数)。`write_fail` 刻意不预登记——批内看不到失败结果,预拦会误伤同批中本可成功的写。
|
|
58
|
+
- 文案:`[WRITE_LOOP_STOP]` 的出口改为**可执行**的「改用 replace/insert/append 增量写入」;新增 `[WRITE_FAIL_STOP]`(先读最新原文再写)。
|
|
59
|
+
- **对消费者**:`BlockedReason` 未新增/未改名(仍是 `write_loop`)、零公开签名变更、零新增 metrics 字段(拦截事实已在 round 事件的 `tool_result.blocked` 中,另立计数即第二真理源)。行为向修复:同一 turn 内对同一文件的增量修订不再被封顶。
|
|
60
|
+
|
|
61
|
+
**任务表更新不再被跨轮幂等跳过(`IDEM-TASK-TABLE-1` · 2026-10-25)**
|
|
62
|
+
|
|
63
|
+
- `BUILTIN_TOOL_IDEMPOTENCY.task_table_update`:`idempotent` → `non-idempotent`。**为什么**:幂等键只有 `name + 完整 args`,而 `task_table_update` 的 `plan_item_id` 是**位置序号**——跨轮 `task_table_write` 重写任务表后,同序号可能指向另一个任务项;此时同 args 重发会被「仅一次语义」跳过并回喂上一轮的旧任务表摘要 = **向模型谎报「已更新」而实际未更新**(真机观测:回显旧任务项)。重跑本身无害(状态确定),故与 `delete_file` 同判据——归入「禁止跳过」而非「重跑有害」。
|
|
64
|
+
- **对消费者**:`IdempotencyLevel` 枚举未变、零签名变更;仅该工具不再被跳过。内置映射现**无** `idempotent` 级工具(级别本身保留,供宿主自定义工具声明)。
|
|
65
|
+
- 同族**未改**(登记观察,不随本版动):`write_file`(`idempotent-key`)跨轮「同 path + 同 content」仍会跳过——若文件在两次调用间被外部删除/改动,同内容重写不会落盘。无真机实证,且该跳过是核心重试去重通道,改动面大。
|
|
66
|
+
|
|
67
|
+
## [5.0.0] · 2026-10-23
|
|
68
|
+
|
|
69
|
+
> **📖 升级必读**:[`docs/memora-升级指南-4.x-到-5.0.0.md`](docs/memora-升级指南-4.x-到-5.0.0.md) —— 本区所有 Breaking 项的**改法**逐项在那篇,本区不重复**怎么改**。
|
|
70
|
+
> 本区归属:仅**内核**变更;SemVer = **major**(编译期破坏:删 23 个导出符号 + 32 个公开成员 + 3 个事件)。
|
|
71
|
+
|
|
72
|
+
### ⚠️ Breaking Removed(内核)
|
|
73
|
+
|
|
74
|
+
**多项目链整体删除(形态定案:一个 Agent = 一个项目 · `PR-SWITCH-1` / `PR-SWITCH-2` / `PUB-API-PRUNE-3`)**
|
|
75
|
+
|
|
76
|
+
- 删:`Agent.switchProject()` / `projectSwitched` 事件 / `AgentOptions.registryDir` / `agent.projects`(`list`·`registerProject`·`unregisterProject`)/ `ProjectRegistry` 类导出 / `ProjectEntry` 类型 / `projects.json` 写入 / `Agent.init(projectPathOverride?)` 的路径参数(变无参)/ `Agent.rebuildComponents()`。
|
|
77
|
+
- 为什么:注入的 storage **不随切换重建**——切了项目、存储不跟着换,**用了会错**(不是「没人用」)。多项目改用「宿主为每个项目各建一个 Agent 实例」;项目名推断摘为 `projectManager` 模块级纯函数保留。
|
|
78
|
+
|
|
79
|
+
**目标漂移检测链退役(`GOAL-DRIFT-1`)**
|
|
80
|
+
|
|
81
|
+
- 删:`SessionManager.updateGoal()` / `goalDriftDetected` 事件 / `SessionCheckpoint` 的 `mainGoal`·`currentGoal`·`goalChangeSeq` / `createCheckpoint(mainGoal?)` 入参(变无参,返回类型收窄为非 null)/ `goalConsistencyChecker` 整模块。
|
|
82
|
+
- 为什么:字面相似度判据实测**零区分度**(12 组正常子任务 12/12 判漂移,与 6 组真漂移完全不可分);「两段文本是否意图一致」属语义判断,内核零依赖架构下永无可接模型。目标偏离防范交还用户在环 + `ask_user`(引导句属角色包 `rules.md` 范畴,当前零配置,见台账 `GOAL-DRIFT-2`)。
|
|
83
|
+
|
|
84
|
+
**记忆治理门面退役(`GOVERNANCE-SRC-1`)**
|
|
85
|
+
|
|
86
|
+
- 删:`MemoryGovernance` 类导出 / `agent.governance` getter / `dedupCompleted` 事件 / 装配产物 `dedupManager`·`memoryAdvisor`。
|
|
87
|
+
- 为什么:`deduplicate()` / `detectConflicts()` / `suggest()` 逐 `GOVERNANCE_SOURCES` 取样,而该常量是**字面量空数组**——代码路径永远拿不到输入,去重数恒 0、冲突报告恒空、推荐恒 `[]`。唯一有效的 `sourceHealth()` 计数口径已由 `agent.memory.stats().bySource` 覆盖(`daysSinceLastAccess` / `diagnosedAt` 无替代,宿主从未消费)。**写时治理不受影响**:`supersede` 写时取代 + `supersededBy` 软指针才是真实生效的治理路径。
|
|
88
|
+
|
|
89
|
+
**公开面通用工具收面(`PUB-API-PRUNE-1`,函数本体保留在内核内部)**
|
|
90
|
+
|
|
91
|
+
- 删导出:`truncate` / `isPlainObject` / `safeSetTimeout` / `safeSetInterval` / `clearSafeTimeout` / `clearSafeInterval` / `segmentText` / `escapeLike` / `serializeFrontmatter` / `toError`(11 个通用小工具,均与 Agent 领域无关、宿主零 import)+ `createLlmProvider`(与规范入口 `createProviderFromConfig` 重复)。唯一本体同删:`escapeLikeSnippet`(收面后零调用;SQLite 后端自实现仍须转义 `%`/`_` 并 `LIKE ? ESCAPE '\'`,规则在 `IMemoryStorage` 接口注释)。
|
|
92
|
+
|
|
93
|
+
**内部机制与默认实现收面(`PUB-API-PRUNE-2` / `PUB-API-PRUNE-4`,能力不撤、只收回公开位)**
|
|
94
|
+
|
|
95
|
+
- 删导出:`safeFetch` / `safeExecuteCode` / `safeSearchProjectFiles` / `safeSearchProjectText`(provider 超时包装,保护仍生效)/ `InMemoryStorage` / `InMemorySessionStore` / `LockManager`(默认实现收回——显式实现接口或用 `createNodeSqliteStorage`)/ `NOOP_TRACER`(不传 `tracer` 即可)/ `RolePackManager.tryBuildMeetingPlan`(队伍数据改经 `getActiveTeam()` / `getTeam()` 取)。
|
|
96
|
+
- 删 Agent 转发门面:`appendPlanItem` / `triggerError` / `recover`(经 `agent.sessionManager.*` 可达);`injectSystemMessage` 无公开替代(需引导模型写在 `chat()` 输入或角色包 rules)。
|
|
97
|
+
|
|
98
|
+
**Agent / SessionManager 成员删除(`PUB-API-PRUNE-5` · 2026-10-16 两批 · `CHKPT-1/2/3`)**
|
|
99
|
+
|
|
100
|
+
- Agent:`canContinueWithoutInput()`(软暂停模型下暂停恒安全,可续跑性由 waiting 原因位表达,方法本身是采样时机不可靠的带陷阱死面)/ `getRecentToolExecutions()`(订阅 `tool_start`/`tool_result` 事件自聚合)/ `getBackgroundTaskStats()` / `forceReleaseChatLock()`(承诺的超时兜底从未接线)/ `heartbeat()`(私有 `touchCheckpoint` 的机制外漏)。
|
|
101
|
+
- SessionManager:`flushNow()` / `flushOnShutdown()`(检查点不落盘,二者是 no-op 清脏,方法名谎报持久化)/ `loadSessionMessages()`(改锚点不 restore 工作记忆的陷阱出口)/ `restoreSession(date, session)` / `restoreMostRecentSession()`(恢复双入口并入 `switchToSession('YYYY-MM-DD-session')` 复合 ID,最近会话从自己的 store `listSessionMetas()[0]` 取)/ `isPauseLimitReached()` / `getConsecutivePauseCount()` / `resetConsecutivePauseCount()`(连续暂停计数链从未通电,生产恒传 `lowRisk=true`)/ `compensateTool()` / `compensateAllNonIdempotent()`(只生成文案、零状态变更)/ `isPaused()` / `isRunning()`(三态 `'running'|'paused'|'error'` 被两布尔吞掉 error 态——看 `status`)。
|
|
102
|
+
- ⚠️ 上述多项随 4.0.0 已发布,直删失去 deprecation 预警期,由本 Breaking 明示;`loadSessionMessages` 原走 `DEPRECATE-1` 周期,用户拍板提前直删。决策依据 = 三面零消费 + 5.0.0 定档时点未发布(npm 最新 4.0.0)零外部破坏窗口。
|
|
103
|
+
|
|
104
|
+
**选项与常量**
|
|
105
|
+
|
|
106
|
+
- 删 `AgentOptions.fileConsistencyCheck`(透传链路先删后字段零读取的僵尸)/ `LOOP_CONSTANTS.MAX_WEB_SEARCH_CALLS`(搜索上限改策略键后零读取的幽灵旋钮,缺省 6 真源归 `DEFAULT_BEHAVIOR_STRATEGY.global.webSearchLimit`)。
|
|
107
|
+
|
|
108
|
+
### Added(内核)
|
|
109
|
+
|
|
110
|
+
- **SQLite 存储切片**(2026-10-16,服务 `DSH-1` / `MCP-SERVER-1`):`createNodeSqliteStorage(dbPath[, { readOnly: true }])` 工厂 + `ReadOnlyMemoryStorage` 类型导出。基于 `node:sqlite` 内建模块**延迟加载**,零三方依赖、`engines` 不收紧(不可用抛 `NOT_AVAILABLE`);**可用性判据唯一来源 = 调用工厂结果**(宿主禁自行解析 `process.versions.node`)。只读形态写方法结构上不存在、连接只读模式打开不建库(库缺失抛 `MemoraError{FILE_NOT_FOUND}`,`HOST-ALIGN-1`)。语义与 InMemoryStorage 逐位对齐(共用契约套件参数化跑两实现);写模式 `journal_mode = WAL`。
|
|
111
|
+
- **归档防重意图解耦 + 跨进程持久化**(`ARCH-GAP-2`,2026-10-19):`ArchiveTriggerOptions.skipIfUnchanged?: boolean`(显式优先,否则随 `autoTriggered`,既有语义不动);防重快照落盘副本 `SessionMeta.archivedMessageCount`(内存 Map 优先双源读写)——宿主重启后不再对「内容未变」的会话重复烧 LLM。
|
|
112
|
+
- **记忆命中可见**(`MEM-EVENT-1` / `MEM-EVENT-2` / `MEM-EVENT-3`,2026-10-19):`memoryRecalled` 载荷补可选 `hits`(命中条目)与 `toolCallId`(与工具调用 1:1 配对,缺省不带键);`Round.evidence` 新增 `memory_hits` 变体——**实时面走事件、回看面走证据轨**,宿主重放历史轮不再丢命中明细。同批载荷扩展(`MEM-UI-1`):`hits[]` 元素补可选 `contentPreview`、`memoryAdded` 载荷补可选 `content`(实时轨与 evidence 落盘轨同批,支撑宿主记忆显示正文为主位)。
|
|
113
|
+
- **web_search 增强**(`GUARD-SEARCH-1` / `SEARCH-QUALITY-1` P1-1):联网搜索硬上限抬为角色包策略键 `webSearchLimit`(1~20,默认 6,与 `askLimit` 同构——只解决「不能调」,不改护栏);新增裁决证据 `web_search_result`(query/endpoint/count/titles 随 Round 持久化,`toolCallId` 配对根治证据错配,0 结果同样留痕)。
|
|
114
|
+
- **悬空取代单一判据**(2026-10-16):`hasActiveSuperseder()` 导出——替代物经物理删/软删移除时旧摘要回退为当前版本可正常召回;判据与移除路径解耦(原「移除点 eager 收敛」是半修复),零数据删除、不改写入语义。
|
|
115
|
+
- **单段文本 token 估算挂公共面**(2026-10-20):`estimateTokensText(text)` 导出——宿主注入量归因(`HOST-CTX-6②`)需要单段计量,原「不挂公共面」是当时无消费面的决定;若宿主自写换算即与运行时口径漂移(第二真理源)。单段用本函数;多段一律 `estimateTokensMessages`(逐段调用会放大取整误差)。
|
|
116
|
+
|
|
117
|
+
### Fixed(内核)
|
|
118
|
+
|
|
119
|
+
- **上下文占用快照补动态注入段**(`CTX-OCC-1`,2026-10-16):此前漏计全部动态 system 注入(最近对话块/情报区/任务表/压力提示等)⇒ `usedPct` 偏小、用户误以为剩余很多。`ContextOccupancy` 增**必填** `dynamicSystemTokens`(杜绝漏填静默归零),段值单点 `loop.getDynamicSystemTokens()`;截断超窗加观测守卫 + 复用摘要 20% 封顶;估算/实测比 >1.5 告警。
|
|
120
|
+
- **登录墙识别 + Bing 摘要错位**(`SEARCH-QUALITY-1` P2,2026-10-15):HTTP 200 登录页不再被洗成正文交付(保守判墙宁漏勿误);Bing 解析改 `<li>` 块内提取,根除「标题 + 干扰摘要」错位;`FetchedPage.fetchFailed?: true` 区分抓取失败与空内容(失败不谎报为需登录)。
|
|
121
|
+
- **技能脚本 cwd 逃逸**(`SKILL-CWD-1`,2026-10-15):`run_skill_script` 子进程 cwd 由宿主进程 cwd 改为项目根(实锤事故:29 个文件落进 VS Code 安装目录);`run_code` 内联模式同批对称收口,四执行面 cwd 判据对称。
|
|
122
|
+
- **归档模式顺延契约**(`ARCH-GAP-1` / ADR-041,2026-10-17):`setArchiveMode` busy 时暂存 + 抛错,`chat()` / `resumeExecution()` 双挂点轮终补执行——「对话结束后生效」从文案承诺变真实现。
|
|
123
|
+
- **会话替换入口状态闸对称**(2026-10-16):`assertSessionReplaceable` 单一前置闸,5 个替换入口全部受「非 running 态拒绝」保护(原仅 `switchSession` 有,暂停/错误态替换会留脏快照)。
|
|
124
|
+
- **提问链路收口**(2026-10-15):回答缺答案落 `[ASK_ABORTED]` 占位(杜绝回填他题答案);暂停记账统一收口 `pause()`,超时清理在途提问。
|
|
125
|
+
- **文档与守卫修正**(`DOC-CLAIM-1` / `GUARD-METHOD-1` / `DIST-ORPHAN-1`,2026-10-18):README 中英 6 处退役能力宣称收回(「发版即失信」级);API 手册补 9 字段 + 删幻觉符号;`prepublishOnly` 改 `prepack`(堵 `npm pack` 打出含已删模块的 tarball);新增手册 interface 成员双向守卫(面 B)。
|
|
126
|
+
|
|
127
|
+
### Changed(内核)
|
|
128
|
+
|
|
129
|
+
- **后台任务槽位按 Agent 实例隔离**(`MULTI-AGENT-1`,2026-10-18):模块级槽位 → `class BackgroundTaskScheduler` 实例级,同进程多 Agent 不再交叉等待/挤占(形态定案后多实例是必然)。非公开 API 变更。
|
|
130
|
+
|
|
131
|
+
## [0.3.0] · 未发布(Unreleased · 宿主轴 · 2026-10-25 开区)
|
|
132
|
+
|
|
133
|
+
> **本区归属**:仅**宿主**(`hosts/memora-vscode`)变更,随 `vsce package` 定版,不进内核 npm 包(ADR-033)。**开区原因**:`vscode@0.2.0` tag 早于宿主 MCP 接入 ⇒ 已发布版没有任何 MCP 能力。**主体条目(本地 stdio MCP 接入)发布前按 `git log vscode@0.2.0..HEAD -- hosts/` 补齐**——本区先记今日订正,切片叙事不复述(真源 = 台账「宿主 0.3.0」区)。
|
|
134
|
+
> **出包前必做**:与内核区同规——标题的「未发布」须改为**实际发布日期**(`scripts/verify-changelog-version.mjs` 校验)。
|
|
135
|
+
|
|
136
|
+
### Changed(宿主)
|
|
137
|
+
|
|
138
|
+
- **MCP 两键作用域 `application` → `machine`**(`H0-2`,2026-10-25):`memora.mcpServers` / `memora.mcpToolAllowlist` 不再随 VS Code Settings Sync 同步。**为什么**:`application` 会把 `headers` 里的明文令牌与免确认批准带到同账号的其他设备——批准的语义是「本机用户同意本机进程」,跨机继承等于替另一台机器点同意。**对消费者**:① 只写用户设置、工作区 / 文件夹写入仍被忽略(`.mcp.json` 不读的红线不变);② **升级后每台机器需各配一次**,原先靠设置同步带过来的 MCP 配置不会再自动出现;③ 本机已有配置不受影响。断言钉在 `mcpConfig.test.ts`(结构机制不在代码里,改 scope 只有这条测试能拦住)。
|
|
139
|
+
|
|
140
|
+
### Fixed(宿主)
|
|
141
|
+
|
|
142
|
+
- **MCP 连接失败归因订正**(`H0-1`,2026-10-25):没有 `tools` 能力的 server 此前被判成「server 未声明 tools 能力」并置 `failed`——但纯 `resources` / `prompts` 的 server 是**合法形态**,这是本宿主只接 tools 的**覆盖面边界**,不是对方故障。现文案改为「本宿主当前只接 tools 能力;该 server 只提供 X / Y,暂不支持(不是 server 故障)」,并对连上后被忽略的非 tools 能力打一次 info 日志(不静默)。**为什么**:谎报成因与谎报能力同族——原文案会让用户去查一台没坏的 server。**对消费者**:仅失败原因文案变化;无 tools 的 server 仍不注册空工具清单(不静默成功)。**登记**:方案-MCP工具接入 §10 新增「`resources` / `prompts` 零接入(能力边界 · 非功能缺口)」行。
|
|
143
|
+
|
|
144
|
+
## [0.2.0] · 2026-10-23 · 宿主
|
|
145
|
+
|
|
146
|
+
> 仅**宿主**(`hosts/memora-vscode`)变更,随 `vsce package` 定版。**随包内核代次 = `5.0.0`**(esbuild 内联 dist,内核自身变更见内核区)。逐条拍板与变异验证收据见台账对应 ID。
|
|
147
|
+
|
|
148
|
+
### Added(宿主)
|
|
149
|
+
|
|
150
|
+
- **`@problems`:把工作区错误 / 警告挂进对话(有界注入第一笔)**(`HOST-CTX-4`,2026-10-21):对话框原本只能挂「文件 / 目录 / 当前文件」——它们都只给**指针**,内容由模型自己读。但 VS Code 的诊断是**瞬态派生数据**,内核工具箱里没有 diagnostics(也没有 git / 终端读取),「提示模型去看」这条路根本不通 ⇒ 定案(`HOST-CTX-0`)为这类数据开了**唯一一处例外**:允许有界注入。本笔只落 `@problems` 一源(同版另有 `@git-changes` 有界注入二笔,见下条;terminal 源 spike 结论 = 不做、维持触发登记)。用法:输入框打 `@` → 列表置顶多一项「诊断(问题面板)」→ 选中挂一枚**与引用 chip 明显不同长相**的 chip(圆角矩形 + warn 色 + ⚠,形状/颜色/图标三通道可辨;**无锁**)→ 发送。**体验要点**:① 选中那一刻**不取数**,按下发送那刻才去问题面板拉最新(按严重度取前 20 条,每条带 `文件:行:列` + 错误文案 + 该行源码,超限明说「已截断」);② chip **发完即消**——注入的是那一刻的快照,钉住就是下轮拿过期数据糊弄模型,要新鲜的下轮重点;③ 圆环 hover 卡片底部出「本轮注入 N」回执(分项明细同屏:当前文件正文 / 工作区诊断),下一轮发送覆盖;④ 历史里你的消息仍只显示你打的字(注入块回放时剥掉),但模型确实收到了。**同一笔的类型级重构**:`ActiveFileProjection.injectedTokens` 迁出为 `injection_summary.segments` 的 `active-file` 分项(三个源各挂一个字段 = 并列腐化 + 违反「与 CTX-6 同一处呈现」),本轮注入量自此**按源分项**回推、「渲染两处、数据一次」。协议 +2 条(消息计数 126 → **128**,治理阈值 130,**余 2**)。逐条拍板过程与 14 次变异验证签名见台账 `HOST-CTX-4`。**真机验收第一项通过**(2026-10-21 用户实测功能通过;反馈「徽记突然出现在状态行有点奇怪」⇒ 已按 `.injection-badge` 样式注释里预登记的回退方向,把回执从状态行徽记整模迁入圆环 hover 卡片底部、分项明细同屏可见,新形态与浅色主题 chip 对比度均于 2026-10-23 真机复验通过,`HOST-CTX-4` 关账)。
|
|
151
|
+
- **`@git-changes`:把 git 未提交改动挂进对话(有界注入二笔)**(`HOST-CTX-4`,2026-10-21 落地 · 10-22 三轮硬化):@ 提及置顶项「未提交改动(git)」→ **发送时刻**宿主只读采集(`git status --porcelain -z` + `git diff` + `git diff --cached`;固定开关防中文路径八进制转义、防 ANSI 污染、防仓库配置借 diff 执行外部程序;子目录工作区按工作区根换算坐标),有界三道闸(≤20 文件 / 单文件 ≤200 行 / 合计 ≤12K 字符,超出明示截断),非 git 仓库 / git 缺失 / 执行失败一律给**事实行**、不给空。语义给的是真 `git diff`(未提交),不是「本会话助手改动快照」——「帮我的改动写提交信息」场景下模型看到的即 git 所见;未跟踪文件只给 `?? 路径`(git 不对未跟踪文件做 diff,如实为限)。注入形态与 `@problems` 同款(chip 无锁 · 发送即取即清 · 回执按源归因)。
|
|
152
|
+
- **输入框 @ 提及挂引用**(`HOST-CTX-1`,2026-10-20):主输入框键入 `@` 弹出工作区文件 QuickPick(多选、模糊过滤),选中即挂引用 chip——想加文件不再必须去资源管理器右键。引用模式红线守住:@ 只是「挂引用的快捷入口」,宿主侧零内容注入。触发时 `@` 先留在正文(Esc 取消文本零扰动),mention 通道挂载成功后按触发点精准撤除该字符(判据不猜,其余入口不带信源不撤——防误删正文里邮箱等合法 `@` 字样);文件列表逐项过首根归属判据(`relativeUnderPrimaryRoot`,第二根 / 根外连列表都不进,与 addToChat 拒挂同一契约两半)。协议最小改动:W→E `mention_open`(只报意图不传过滤词)+ E→W `addRef.source?: 'mention'`。守卫 webview 3 例 + 宿主 2 例,变异验证摘撤除调用即红。
|
|
153
|
+
- **@ 提及落地补强:判据守卫 + 截断明示 + 防重入**(`HOST-CTX-11`,2026-10-20,CTX-1 落地次日对抗式审查后当日修):① 撤除 `@` 的判据中真正带语义的只有「落点恰为 `@`」一条(另两条 null / 越界删掉行为等价),而它此前**零测试**——实测删掉该行 chatView 448 例全绿;现补 2 例守卫(触发后文本被编辑 / @ 已被删,均不撤不猜),并订正「判据三重」的夸大措辞。② `findFiles` 上限命中即**静默截断**(大仓里搜不到目标文件还以为仓库里没有)——现上限提为导出常量 `MENTION_FILE_LIMIT`,命中时 placeholder 明示「已截断,请输入关键词缩小范围」(不用「提示项」进列表:QuickPickItem 无 disabled,选中即变伪引用)。③ 连按 `@` 会各开一个 QuickPick、后开的静默覆盖先开的且只撤一个 `@`——现加 in-flight 守卫(try/finally 保证异常路径也归位)。④ 订正退化分支注释的**描述性撒谎**:该分支唯一可达场景是「QuickPick 打开期间视图被销毁」,不是注释原写的「webview 未就绪」;代价如实改写为「多出一个延迟注入的引用」。守卫 chatView 450 / chatPanelMention 4,变异三次均红后还原。
|
|
154
|
+
- **修复输入 `@` 无反应:未知消息不再静默丢弃 + 消息链获得可测入口**(`HOST-CTX-12`,2026-10-20,真机验收发现当日修):真机输入 `@` 字符正常落入输入框但 QuickPick 毫无反应。根因不是 `@` 分支写错,而是 **webview 脚本与扩展宿主不是同一版本**——webview 脚本是外部文件(`dist/webview/scripts/chatView.js`,从磁盘读 ⇒ 重编译后是新的),而宿主的消息分发活在进程内存里(旧的)⇒ 新 webview 朝旧宿主发 `mention_open`,旧宿主**没有任何分支匹配、静默丢弃**。修法第一动作是 Reload Window 重启扩展宿主,但真正的伤是「静默丢弃」本身:消息链**没有 else 兜底**,123 个类型里任何一个因版本错位不到达都表现为功能凭空消失、零反馈(「静默失败」族第三次踩)。① 加 else 兜底,未知类型落 `console.warn`(含类型名与「最可能原因:扩展宿主未重启」),不驱动 UI 不弹提示;② 🔴 把整条 120+ 分支的消息链从匿名回调**摘为 `private handleWebviewMessage`**——它原先零可测入口(加上兜底后立刻发现「有守卫却验证不了」),摘出后与 `handleInput` 等同构、测试可直接驱动。守卫 +1 例,变异(摘 `console.warn`)红后还原。
|
|
155
|
+
- **中文输入法 / 粘贴也能触发 `@` 提及**(`HOST-CTX-13`,2026-10-20,真机验收反馈当日修):原触发判据是 `keydown` 的 `e.key === '@'`——那是**按键事实**,依赖键盘布局与 IME 行为;中文输入法插入的 `@` 不保证走 keydown,粘贴 `@` 根本不产生 keydown,两条路都表现为「要英文 @ 才有反应」。改为在既有 `input` 监听里加兜底:`inputType` 属 `insert` 家族 + 光标前恰为 `@`(**文本事实**)。`inputType` 判据不可省——删除文本同样触发 `input`,用户在「帮我@x」里删掉「我」后光标仍停在 `@` 后,不判 inputType 会把删除误判成插入而误弹列表。keydown 快路径保留(offset 语义更直接),英文键盘一次 `@` 两条路径都 fire 由 CTX-11 的 in-flight 守卫拦掉(复用既有机制,不新建第二套防抖)。守卫 chatView 453(+3),变异红后还原。
|
|
156
|
+
- **当前文件 chip:上下文附加可见 + 本会话可关**(`HOST-CTX-3`,2026-10-20):输入框上方新增第三种 chip,把「当前打开文件会不会进本轮上下文」摊开——干净文件显示 `📄 docs/白话设计文档.md`(只给指针、不占预算),**有未保存修改 / 未命名 / 工作区外**时显示 `… · 未保存·全文已附`(这三类磁盘不是真相,注入正文),因此用户第一次能看懂「这条消息为什么突然贵了」。chip 上的 ✕ = **本会话**不再附加(关掉后整枚变虚线胶囊「当前文件未附加 · 点击启用」,点一下即回开,不留死角;重开面板复位为开)。开关状态与注入判据归宿主单点(同一份快照既拼信封又产出 chip),webview 只渲染不推断。
|
|
157
|
+
- **上下文透明性:指针提示 + 注入量归因**(`HOST-CTX-6`,2026-10-20):①引用 chip 的 title 首句改为「仅挂指针,正文由模型按需读取(不占预算)」——挂了 ≠ 注入了,目录引用尤其如此(信封只给一张目录地图,内容按需 `list_dir`);②发送后的本轮 chip 徽记短显注入规模(`未保存·全文已附 ≈3.3k`),title 给全数(`注入约 N token`)——「这轮贵在哪」有归因入口(圆环只示总量,这里示出处)。取数纪律:估算**只在发送时刻**取(正文块已在手,零额外读取),token 口径与内核 `estimateTokensText` 同源(宿主自估即第二真理源);实时投影刻意不带此字段,正文惰性(CTX-3 收尾)不被显示需求破坏。
|
|
158
|
+
- **会话大纲导航条**(`HOST-NAV-1`,2026-10-20):对话流右缘一列细横条,每轮用户输入一根;**视口内当前轮加粗高亮**,hover 弹浮层列出各轮输入预览(当前轮粗体),点击滚动定位——长会话「回到我上次说了什么」不再滚轮硬扒(ChatGPT 同款范式)。不足两轮或不可滚动时整条隐形。预览文本 = 上屏文本过 `stripInjectedContextPrefix` 归一(重放带注入前缀 / 运行时无前缀两路同源);条列重建挂既有 MutationObserver 拍子(签名比对防流式期每帧重建);点击定位后显式重算吸底标记(对齐一键到底纪律)。**2026-10-20 二轮加固(边界收口)**:长会话极端轮数不再外溢——改为**全量条 + 自适应压密**(轮数超出可用高时先压间隙、再压条高至下限,极端仍不足交条列自身滚动兜底,绝不画到输入区上);高度上限按视口高内联下发(**条列** CSS 不再设 `max-height`,上限单一真源;浮层面板的 `max-height` 与该比例同判、另留在 CSS);条更短、右缘更紧(条宽 `--sp-6`→`--sp-5`、`right` `--sp-2`→`--sp-1`、去横向内距);修复重建指纹「条数 + 首尾长」在重放 / 分叉(中段变化而首尾同长)下静默失效(改全量预览拼接);`resize` 触发压密重算。**2026-10-20 三轮复核(SSOT / 不带伤)**:轮次收集锚由 `.msg-wrapper` 改为 `.msg.user`——该外壳由 `append()` 的 else 分支创建、**同包 user 与 error**(错误气泡会被误算作一轮、错误文案进条列与预览),锚 `.msg.user` 天然筛除;压密常量(条高 / 间隙 / 高度比例)与设计令牌的镜像补**测试守卫**(漂移即红,闭合「仅注释自认」的静默风险)。
|
|
159
|
+
- **文档上下文改按引用模式注入**(`HOST-CTX-0` 落地,2026-10-20):活动文件**干净**时不再把全文塞进每轮消息(此前最多 12000 字符 ≈ 3~4k token),改为一行指针(`当前打开文件:path`)让模型按需 `read_file`;文件**有未保存修改 / 未命名 / 不在工作区内**时仍注入正文(这三种情形磁盘不是真相,只给指针会让模型读到旧版或读不到)。对消费者:预算显著下降;未保存编辑的可见性与「编辑器随手一开就注入」的旧观感不同——现在只有脏文件才注入。
|
|
160
|
+
- **引用 chip 点击跳回编辑器**(`HOST-CTX-8`,2026-10-20):chip 的路径与行号是两个独立可点域(补 `role=button` / `tabindex` / Enter-Space),点击打开文件并选中该行区间,目录则在资源管理器露出;失败走面板内提示单一出口。
|
|
161
|
+
- **编辑器选区引用带行号**(`HOST-CTX-2`,2026-10-20):右键「添加到对话」对当前编辑器文件挂 `path#L{start}-L{end}` 指针(1-based 闭区间,0→1 基准只在宿主转一次),信封把 `read_file` 的 `offset`/`limit` 预先算好给模型——选中 20 行不必读整个文件,引用模式仍不注入内容。
|
|
162
|
+
- **manual 归档入口**(`ARCH-GAP-2`,2026-10-19):历史浮层「移入留存区」双动作 = 本地留存 + `agent.archiveSession(…, { skipIfUnchanged: true })`;「归档」(LLM 摘要)与「留存」(视图分组)术语显式分家;按钮文案 = 运行时真值(`chat_archive_mode` 推送)。真机验收通过(跨进程防重真实生效)。
|
|
163
|
+
- **自定义搜索引擎**(2026-10-13):五档预设 + 自定义引擎;保存前实测验证门禁 + 差分探针(区分「策略选错」与「0 命中」);紧凑手风琴编辑器;重名/非 http(s) 护栏;装配侧脏配置过滤。
|
|
164
|
+
- **归档模式设置接线**(2026-10-16):设置面板「记忆」选项卡接 `agent.setArchiveMode()` 三段式,繁忙顺延不谎报「已生效」。
|
|
165
|
+
- **暂停按钮投影**(2026-10-16):TurnState 单通道投影接线——后被 `ARCH-GAP-F1` 撤除门控改恒显示(见 Fixed)。
|
|
166
|
+
- **webview 错误边界 + 丢弃留痕**(2026-10-11):error/unhandledrejection 兜底卡片 + `host_diag` 通道上报扩展日志(装配期错误也能抓);错位输入丢弃落日志可观测。
|
|
167
|
+
- **文件改动可视化**(DIFF-1~4,2026-09-26~28):真实文件行内高亮 + 标题栏文件级确认/回退 + 块级「接受/拒绝此处」(git `add -p` 同构模型)+ 脚本类写工具 workspace 快照 diff 追踪(`OPAQUE_WRITE_TOOL_NAMES` 单源派生)+ 未保存编辑 fail-closed 模态(W2)+ 大仓库扫描上限守卫。
|
|
168
|
+
- **后台任务可见性**(`CMD-1` 阶段 2):StatusDock 第四条 + 终止按钮;内容签名去重 + ready 全量对齐(防「面板重开条凭空消失」)。
|
|
169
|
+
- **角色包策略键编辑**(`RP-EDIT-1`):16 键键面单源内核 `describeStrategyKeys()`(宿主零清单维护);保存全链路 extension 侧(全量保真 + 校验拦截 + reload 失效缓存)。
|
|
170
|
+
- **命令注册面守卫 + 默认快捷键**(2026-10-11 / `HOST-KB-1`):`contributes` ↔ `registerCommand` ↔ `keybindings` 四向对拍;`memora.open` 默认 `ctrl+alt+m`。
|
|
171
|
+
- **skill 菜单搜索**(`UI-INPUT-3`,2026-10-11):名称+描述过滤;分容器重建保焦点(真机打字丢焦实锤修复)。附件行 skill chip 归位输入盒内(`UI-INPUT-1`)。
|
|
172
|
+
- **角色包「刷新」按钮**(2026-10-08):用户角色包目录改动免重启生效(`roles_refresh` → `resyncUserPacks`)。
|
|
173
|
+
- **终态标签收口底栏**(2026-10-13):勾/用户中断/异常中断三档统一 `data-status` 载体契约。
|
|
174
|
+
|
|
175
|
+
### Fixed(宿主)
|
|
176
|
+
|
|
177
|
+
- **当前文件气泡也只显示文件名**(`HOST-CTX-18`,2026-10-20 真机验收 CTX-16/17 通过后即修,CTX-17 同族延伸):输入盒上方「当前文件」chip 的可见文本同步降噪为文件名(`docs/白话设计文档.md` → `白话设计文档.md`)——复用 CTX-17 同一纯函数,不新建第二份判据;完整路径保留在 title 末尾括号(注入语义仍是第一问)与 ✕ 的 aria-label。活动文件永远只有一个,不存在引用气泡的同名撞车,纯文件名零歧义代价。守卫 +1 例、原「干净文件」例断言同步订正;变异(退回全路径)红后还原。
|
|
178
|
+
|
|
179
|
+
- **@ 提及列表收起后焦点自动回到输入框**(`HOST-CTX-16`,2026-10-20 真机验收通过后反馈即修):Esc 取消或确认选中文件后,VS Code 不会把焦点还给 webview 输入框(QuickPick 是宿主全局 UI,焦点被它拿走就不还)⇒ 想继续打字得先用鼠标点一下。协议加 E→W `focus_input`,宿主在 QuickPick dispose 后、确认/取消分叉前发一条(两条收场路共用一个出口;未开工作区 / findFiles 抛错时 QuickPick 从未开出,天然不发),webview 只 focus、不动文本(@ 撤不撤归 addRef 的 source 分支)。守卫 accept/cancel 两路 + webview focus 例,变异双红后还原。
|
|
180
|
+
- **引用气泡只显示文件名**(`HOST-CTX-17`,2026-10-20 真机反馈即修):附件行引用 chip 的可见文本从完整相对路径改为文件名(`src/webview/scripts/chatView.ts` → `chatView.ts`)——信息不丢:chip title 末尾括号(hover 消歧同名文件)、pin/remove 的 aria-label(屏幕阅读器)、open_ref 载荷与发送信封三处各司其职。范围只及用户添加的引用;活动文件 chip(自动投射)语义不同不动。已知限制:同名文件可见标签相同靠 hover 区分(刻意不上父目录消歧,复杂度守恒)。
|
|
181
|
+
|
|
182
|
+
- **@ 文件列表不再被 node_modules 挤爆 + 排除语义注释谎言订正**(`HOST-CTX-14`,2026-10-20 当日三审发现即修):输入 `@` 弹出的文件 QuickPick 此前给 `findFiles` 传 `undefined` 排除——VS Code 源码一手实读:legacy `findFiles` 只应用 `files.exclude`、**不应用** `search.exclude`、`.gitignore` **默认不尊重**(1.87 起硬编码,PR #204845)⇒ `node_modules`(本仓实测 32,040 文件)/ `dist` / `coverage` 全进列表、撞 2,000 上限**静默截断**,用户想引的源码文件随机缺席,而 placeholder 只说「已截断」不说原因(搜不到还以为没有)。修:① 新建 `extension/host/ignoredDirs.ts` 单一真源(派生自内核 `IGNORED_DIR_NAMES`,与 `search_project` / `list_dir` 同一套忽略规则),mention 与 `projectSearchProvider` 两处 `findFiles` 同挂(消一份行内第二基线);② placeholder 补「内置忽略目录已排除、仍超上限」;③ 订正两处注释的三项断两项谎话。守卫 chatPanelMention +1 例 + 截断例 +1 断言;变异三连均红后还原;全量 78 套件 1396 passed / 2 skipped。
|
|
183
|
+
|
|
184
|
+
- **编辑器右键「登记作品投影」在选中行时仍出现**(`HOST-MENU-2`,2026-10-20):该命令只登记整个文件(`works` 存储无区间字段),带选区时出现会让人以为「登记了这几行」⇒ `editor/context` 的 `when` 加 `!editorHasSelection`,编辑器入口只在无选区时出现;命令面板入口不变。
|
|
185
|
+
- **引用标签与定位的四处漂移**(`HOST-CTX-2` / `HOST-CTX-8` 收尾,2026-10-20):① `#L` 标签改由 `shared/refKey.formatRefRange` 单点产出——此前键 / chip / 行号 span / 信封各写一套,单行引用在 chip 显示 `#L7`、喂给模型却是 `#L7-L7`;② `open_ref` 定位改用与内核 `read_file` cwd **同源的首个工作区根**(原「逐根取第一个存在」在多根工作区会打开另一根的同名文件,用户核对的和模型读到的不是同一个);③ 非法行区间(`start > end`)统一降级为整文件引用,不再算出 0 或负数 `limit`;④ 目录引用的读取工具名改为 `list_dir`(原写 `read_file`,而 `read_file` 只读文件——等于给模型一条必然失败的指令)。
|
|
186
|
+
- **当前文件上下文:显示订阅不再每次击键读全文**(`HOST-CTX-3` 收尾,2026-10-20):为修「缓存撒谎」把快照改为发送时实时读之后,显示订阅(换文件 / 同文件被编辑 / 保存)按**每次击键**取快照,而旧快照顺带产出注入正文(`getText()` 全篇)⇒ 大文件下**每敲一个字就全量读一遍文档**。已拆为「廉价事实快照(文件名 / 脏态 / 相对路径,不读正文)+ `readDocBody` 惰性读取」,`resolveActiveFile(withBody)` 显示路径恒 `withBody=false`(零 `getText`)、仅发送且本轮**真要注入**时才读。守卫 `chatPanelHistory` +1 例(快照 `getText` 读取次数恒 0)。
|
|
187
|
+
- **多根工作区右键「添加到对话」挂出模型读不到的引用**(`HOST-CTX-9` 创建侧,2026-10-20):原 `addToChat` 用 `asRelativePath` 生成 `ref.path`(相对**「所在根」**),而模型 `read_file` 的 cwd 与 `open_ref` 定位都恒取**首个工作区根** ⇒ 在**第二根**下落引用,chip 显示正常、模型却按首根读到同名路径(不存在即失败)。新增根归属纯函数 `extension/host/refPath.relativeUnderPrimaryRoot`(以首根为唯一基准,越出即拒),`addToChat` 改为 **fail-closed**:不在首根下的目标不挂引用并提示(挂一条注定读错的指针比不挂更坏)。同批把**消费侧**(`open_ref` 点击定位的越界守卫)也收口到同一模块(`refPath.resolveUnderPrimaryRoot`,含规范形往返校验)——此前生成 / 消费两半各写一套判据且消费侧零测试,属第二真理源。
|
|
188
|
+
- **引用文件失效后信封仍给出死指针**(`HOST-CTX-9` 发送侧,2026-10-20):引用挂上后文件被删 / 改名,下一轮信封仍写 `- 参考文件:old/path.ts(offset=… limit=…)`,模型照读撞一次错、用户只看到「模型读文件失败」,不知道引用已过期。发送前新增**无状态**存在性核实 `extension/host/refProbe.collectMissingFileRefPaths(refs, rootFsPath, stat)`(`stat` 注入式、`Promise.all` 并发、空 root / 零文件引用短路;解析器**复用** `refPath.resolveUnderPrimaryRoot` 首根 SSOT,不另写守卫),失效者在 `docContext.refItemLine` 降级为**裸指针 + 「注意:添加后已不存在,请向用户确认」**,并**去掉 `#L` 区间与 `offset/limit`**(死文件上的精确读参数同样注定读空——纪律「绝不给 `read_file` 一条必然失败的指令」)。刻意**不维护「失效引用集合」**(那是第二真理源、必与磁盘漂移)。**偏离登记**:① 台账原写 `fs.stat`,实现改用 `vscode.workspace.fs.stat`(异步、兼容远程 / 虚拟 FS,与 `extension.ts` 既有用法同源);② 标记文案原拟 `⚠`,改**纯文本**——`iconLanguage` 守卫把 `⚠` 列为 webview 代码内禁用的字符图标,且该块被剥离契约从 UI 隐藏、只喂模型,纯文本无损。守卫 `refProbe.test.ts` 6 例(存在 / 不存在 / 目录忽略 / 解析失败计入 / 空 root / 多引用并发)+ `docContext.test.ts` +4 例(失效带 range 去参数 / 无 range / 目录不标 / 未命中与缺省原样)。
|
|
189
|
+
- **引用 chip 行缺批量出口**(`HOST-CTX-7`,2026-10-20):挂 6 个引用要逐个点 ✕ 六次。引用行在引用存在时追加**「清空全部引用(含常驻)」**按钮(范式照抄待发送行的 `pending-queue-bar__clear`),点击 = webview 本地清 `currentRefs` 并重渲染——**刻意不走上行消息**:待发送队列清空走 `clear_pending_queue` 是因为其 SSOT 在宿主,而引用 SSOT 在 webview(单删 ✕ 同为纯本地过滤),上行等于让宿主镜像一份引用状态(第二真理源)。范围**只及引用**:活动文件 chip(CTX-3 本会话开关、宿主投影)不受牵连;pinned 一并清(与 ✕ 语义一致,🔒 只管「发送后是否保留」)。样式零新增规则(`.ref-chips__clear` 并列进 `.skill-chip__remove` 既有选择器组,一份规则多锚点)。守卫 `chatView.test.ts` +4 例(批量清空 + 断言无上行 / pinned 一并清 / 活动文件 chip 不受牵连 / 无引用无按钮)。
|
|
190
|
+
- **运行时整轮无暂停按钮**(`ARCH-GAP-F1`,2026-10-19):撤除 `canContinue` 门控全链(采样时机在流前恒 false 且架构上不可靠),running 相位暂停按钮恒显示。
|
|
191
|
+
- **记忆命中明细三连修**(`MEM-EVENT-2/3` 宿主侧,2026-10-19):明细收进对应工具折叠行(不再沉底遮挡运行时状态);重渲染改读 `Round.evidence` 证据轨(100 字截断副本退位);中断轮一并补齐;磁盘实证 3 条命中与 toolCallId 1:1 配对零悬空。
|
|
192
|
+
- **底栏终态偶尔不显示**(2026-10-19):运行态 `data-status` 与终态 `data-terminus` 拆为双通道(SSOT 收敛),终态展示不再依赖容器存在。
|
|
193
|
+
- **历史浮层滚动分层**(2026-10-19):tab/搜索框恒置顶、条目容器成唯一滚动面(纯 CSS,含 dropdown display 特异性回归排雷)。
|
|
194
|
+
- **悬空取代展示判据归一**(2026-10-16):「已被取代」徽标与治理统计改用内核 `hasActiveSuperseder`(原 `!== undefined` 会把悬空指针误标)。
|
|
195
|
+
- **提问等待态输入走 answer 通道**(2026-10-15):修复同一意图两种落盘形态(答案退化成补充、提问原文不落盘);「拒答也是回答」。
|
|
196
|
+
- **真机复盘三连**(2026-10-13):提问等待对齐 30 分钟(`ASK-TIMEOUT-1`,与 confirm 超时「数值巧合、判据独立、禁合并」);token 累计口径标注(`ROUND-ANALYTICS-1`);成文文件分区纪律入技能文档(`ROLEPACK-BODY-1`)。
|
|
197
|
+
- **内核错误诊断不再被吞**(2026-10-13):`MemoraError` 经 `toNoticeText` 全文呈现(此前 37 处边界截断只留标题);CSP 补 `img-src data:`。
|
|
198
|
+
- **启动会话对齐**(2026-10-13):修「启动即分叉报当前会话不存在」(宿主 current 与内核惰性初值错位),挂 `refreshAfterAssemble` 唯一收口点。
|
|
199
|
+
- **配置 LLM 后免重启**(`HOST-BUG-1`,2026-10-12):装配失败 catch 重置缓存 + `retryAgentAssembly()` + 配置变更监听触发重试(僵尸 Promise 根因)。
|
|
200
|
+
- **角色页详情/编辑不可达回归**(`RP-EDIT-1` 后续,2026-10-04):重挂判据把首挂场景整体挡死,改到达即渲染(纪律:新增判定分支必须补「分支被走到」的用例)。
|
|
201
|
+
- **多流续跑 metrics 同轮合并**(2026-10-10):前段指标不再被静默清零(求和合并、success 取末段)。
|
|
202
|
+
- **队伍对账只检测不删除**(`TEAM-GHOST-1`,2026-10-08):清理写回退役、删除权交还用户(真机事故:瞬时扫描失败被当「全部卸载」静默物理删除队伍);空池护栏;内核 `effectiveMembers` 同口径收口。
|
|
203
|
+
- **历史条目悬停假显「当前会话」+ 归档后不刷新**(`HIST-INFO-1`):title 移内层防泄漏;订阅 `sessionArchived` 重拉列表。
|
|
204
|
+
- **异常终态轮缺底部栏**(2026-10-10):`settleRoundFooter` 单点收口(锚 roundId 不依赖 DOM 连通性),早相位中断也能拿到复制/分叉/删除/时间戳。
|
|
205
|
+
- **消息区自动吸底**(2026-10-10):`MutationObserver` 收口「高度变更不派发 scroll」整类缺口(思考折叠块/工具流式/长气泡)。
|
|
206
|
+
- **设计令牌 SSOT 收口弧**(2026-10-12,四批,`UI-TOKEN-PAIR-1` / `UI-TOKEN-MENU-1` / `UI-TOKEN-WARN-1` / `UI-TOKEN-LAYER-2`):同变量不同回退 8 组 → 0;`--dim-*` / `--line-*` / z-index / 行高 / 不透明度刻度收口,裸值债 74→20 升硬门;无障碍对比度、`--menu-*` 幻影变量(引不存在的 VS Code 主题键致暗色白底黑字)、角色包卡片双箭头修复。
|
|
207
|
+
- **工具批断段与口径收口**(2026-09-25~26,`TOOL-RUN-1`):思考换步即断段(反转「按 step 分组」前置决议,依据=前提变了);叙述词表统一到工具显示名、取消「第 N 批」序号;问答卡纳入断面(`BATCH-SPLIT-1`);任务项组位置判据归位 (ts, seq)、组外条目不再沉底。
|
|
208
|
+
- **diff 可视化复盘收口**(2026-09-28):对照回滚为 git 同款左右分栏(真机定案)、删行尾红色预览;文案口径单源 `COMPARE_LABEL`;台账/docs 失真订正 + 退役概念回扫清单补第 8 层(`tasks/`)。
|
|
209
|
+
- **空响应计数假阳**(`EMPTY-RESP-1`,2026-09-29 复核推翻 09-29 验收):截断救回计数补 `!aborted`(用户中断不再记成救回成功);取证面改记生效值 `getEffectiveMaxTokens()`(宿主不再重算裁决规则)。
|
|
210
|
+
- **市场上传撞键**(2026-10-14):截图文件名 ASCII 化(门户把非 ASCII 字节替换成 `?` 后等长撞键)。
|
|
211
|
+
- **插话丢弃信号成对契约**(2026-10-09):停止路径补 `syncPendingQueue`,`_lastPendingQueueLen` 折叠 0 误判修为 `undefined`。
|
|
212
|
+
- **渲染异常用户侧静默**(2026-10-10):`onMessage` 兜底补非阻断红条。
|
|
213
|
+
- **挂起/插话补充输入渲染根治**(2026-10-07):user 消息一律不删骨架 + 正文单块续写统一(打断分段形态退役)。
|
|
214
|
+
- **任务项组层级与折叠箭头右置**(`TOP-UI-2`/`TOP-UI-3`,2026-10-04)+ **待发送区空条常驻**(`STATUS-DOCK-FIX`,2026-10-04)+ **`backgroundProvider` 声明收口**(`HOST-RESET-2`,2026-10-13:删硬编码补丁,键清单回归纯派生)。
|
|
215
|
+
|
|
216
|
+
### Changed(宿主)
|
|
217
|
+
|
|
218
|
+
- **附件行改单轨横向滚动**(`HOST-CTX-10`,2026-10-20):输入框上方的技能 chip 行与引用 chip 行不再换行堆高(挂 3 枚以上就顶起输入区、压扁对话区),改为单轨排列、超出横向滚动、滚动条隐藏,**鼠标滚轮直接横切查看**(触控板原生横滑不受影响);两侧按溢出位置做边缘渐隐,作为「这一侧还有 chip」的唯一可见线索。拦截只在**真的溢出**时发生——装得下时滚轮照旧滚对话,不劫持。
|
|
219
|
+
- **记忆显示正文为主位**(`MEM-UI-1`,2026-10-19):设置记忆卡片(含回收站)与聊天命中项不再默认展示机器 id/name,改显示记忆正文预览(内核 `contentPreview`/`content` 新字段,旧内核按 name→id 回退链降级);id 保留于 dataset 反馈寻址与 tooltip、卡片详情保留全文与溯源。
|
|
220
|
+
- **输入条进度信号去重**(2026-10-18):占用构成条移入圆环 hover 卡片(四段→五段含「动态注入」,`CTX-OCC-1` 宿主侧 + 跨包字段对账守卫);会话记录量词订正。
|
|
221
|
+
- **输出上限裁决改取交集**(2026-09-28):per-LLM 面板与角色包 `act.outputLimit` 取 min(原角色包直接覆盖 = 允许把用户配的小值顶大);默认 4096 隐形天花板改 0(不干预),0-哨兵与 `contextLimit`/`stepBudget` 同构。
|
|
222
|
+
- **token 显示诚实口径**(`MAXTOKEN-SSOT-1` 销项):「估算/正文」标注 + 生效上限亮明。
|
|
223
|
+
- **示例包行为参数对齐**(2026-09-28):共鸣小说家 `stepBudget`/`toolStepLimit` → 100、`multiStepReasoning` manual→auto(思考深度听服务端默认)。
|
|
224
|
+
- **工程 SSOT 收敛**(2026-10-15):默认窗口同族数字指针化 ×16;删 `package-lock.json`(`HOST-LOCK-1`)。零行为变化。
|
|
225
|
+
- **0.1.0 定版与市场门面对齐**(2026-10-12):manifest 0.0.1→0.1.0、打包链三缺陷修复、README 市场定稿;真机装包实测通过。
|
|
226
|
+
|
|
227
|
+
## 历史版本
|
|
228
|
+
|
|
229
|
+
> 全文见 `docs/CHANGELOG-归档.md`(仓库内归档,npm 包不含;原文迁入,未改写)。
|
|
230
|
+
|
|
231
|
+
- **[4.0.0] · 2026-10-08** — 首个 major:导出面收敛(−54,桶导出时代收场)+ `agent.memory.search()` 退役(唯一入口 `searchByKeyword()`)+ 角色包 16 策略键定型。
|
|
232
|
+
- **[3.0.1] · 2026-09-30** — 开源归口翻转:GitHub 升主仓库。
|
|
233
|
+
- **[3.0.0] · 2026-09-30** — 架构收敛后第一个稳定基线(Node.js 专属 · 零第三方运行时依赖)。
|
|
234
|
+
- **[2.1.0] · 2026-08-08 / [2.0.3] · 2026-08-01 / [2.0.2] · 2026-07-27** — 探索性迭代期。
|
|
235
|
+
- **[1.0.2] · 2026-07-11 / [1.0.1] · 2026-07-08 / [1.0.0] · 2026-07-08 / [0.3.0] · 2026-06-27** — 早期版本。
|