dsh-experience 0.0.0-stage → 1.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +225 -0
- package/CONTRIBUTING.md +87 -0
- package/LICENSE +21 -0
- package/README.md +156 -2
- package/USER-GUIDE.md +92 -0
- package/config.example.json +13 -0
- package/cordis.patch.yml +4 -0
- package/index.js +1207 -0
- package/lib/capture.js +663 -0
- package/lib/decay.js +253 -0
- package/lib/evidence.js +206 -0
- package/lib/lookup.js +53 -0
- package/package.json +60 -4
- package/store.example.json +10 -0
- package/tools/e2e.mjs +342 -0
- package/tools/selftest.mjs +925 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [1.0.4] — 2026-11-09 — npm 发布通道
|
|
4
|
+
|
|
5
|
+
- 新增 `.github/workflows/publish.yml`:推送 `v*` tag 时先校验 tag 与 `package.json` 版本一致、跑 selftest 与 e2e,再 `npm publish --access public`。
|
|
6
|
+
- 新增 `tools/pack-check.mjs`:发布前按 `files` 白名单解析实际入包文件,检查必需项缺失与运行时产物(`store.json`/`config.json`/`applied.json`/`probe.json`)泄露。
|
|
7
|
+
- `package.json`:新增 `publishConfig.access=public`,`files` 纳入 `tools/e2e.mjs`;发布后其他人可用 `install_bundle dsh-experience@<版本>` 安装并在插件页原地升级。
|
|
8
|
+
|
|
9
|
+
## [1.0.3] — 2026-11-09 — superseded 状态与 G8 闸门
|
|
10
|
+
|
|
11
|
+
自动捕获能学到经验,但学不到"这条经验已经被规则否决过"。于是出现过一个循环:某条经验与当前
|
|
12
|
+
AGENTS.md 冲突(例如沙箱里必须直跑测试,而经验写的是 `node --test`),人工 `reject` 之后,
|
|
13
|
+
下次同样的任务又被自动捕获成新候选,等人再拒一次。
|
|
14
|
+
|
|
15
|
+
### 新增
|
|
16
|
+
- **`superseded` 状态**:`/memory supersede <id> [原因]` 把经验标记为"与当前规则冲突"。
|
|
17
|
+
不删除(保留证据),写入 `supersede: { by, at, rule }`,清除 `verify`。
|
|
18
|
+
- **G8 闸门**:新轨迹若与某条 `superseded` 记录**结果指纹相同**,直接拒绝收录,理由写成
|
|
19
|
+
`G8: 与已否决经验 exp-N 指纹相同(原因)→ 不再收录`。改回 `verified` 后闸门自然解除。
|
|
20
|
+
- **`/memory review` 单列已否决记录**:不再把 `superseded` 混进候选,也不再提供 approve。
|
|
21
|
+
- `lib/capture.js` 导出 `gateSuperseded()`,纯函数,可单测。
|
|
22
|
+
|
|
23
|
+
### 测试
|
|
24
|
+
- `tools/selftest.mjs` → **72 pass / 0 fail**(新增 T61 G8 判定、T62 review 展示)。
|
|
25
|
+
- `tools/e2e.mjs` → **19 pass / 0 fail**(新增 T58:否决后不再注入、同指纹轨迹被 G8 拦下)。
|
|
26
|
+
- 合计 **91 pass / 0 fail**。
|
|
27
|
+
|
|
28
|
+
### 已知限制
|
|
29
|
+
- G8 依赖结果指纹,只对"同一组产物文件"生效;换了文件名或换了目录不会命中(这是刻意的:
|
|
30
|
+
同名产物才说明是同一条配方)。旧记录若没有 `fingerprint`,G8 不会触发。
|
|
31
|
+
|
|
32
|
+
## [1.0.2] — 2026-11-09 — 整机测试(e2e)与红线修复
|
|
33
|
+
|
|
34
|
+
这一版把 `index.js` 的接线第一次纳入自动化测试:新增 `tools/e2e.mjs`,用假的 Cordis context 驱动真实的 `apply()`、`pre-step`、`tools/result`、`turn-stopping` 与 `/memory` 命令,全部落在临时 `DSH_HOME` 上,不碰真实档案。18 条用例抓出 6 个真实缺陷。
|
|
35
|
+
|
|
36
|
+
### 修复
|
|
37
|
+
- **scope 闸门一直是瞎的(P0)**:`recordCall()` 用 `C.clip()` 存 hint,而 `clip()` 会脱敏路径,于是 `buildCandidate()` 拿到的已经是 `<path>/pad.js`。结果 `record.scope` 全为空数组、`record.fingerprint.targets` 只剩占位符——`scopeMustMatch` 与指纹合并在自动捕获上从未生效。改为 `hint` 存**未脱敏**原文(`C.clipRaw()`),只在写进 `store.turns` 前统一脱敏;渲染字段仍走 `clip()`。
|
|
38
|
+
- **恢复型轨迹无法按指纹合并**:`outcomeFingerprint().green` 原要求"本次没有任何测试失败",导致"先失败后跑通"的轨迹被判非全绿、退回 lexcial 合并而新建重复记录。改为**以最后一次测试结果为准**,失败本身进 `reverse_examples`。
|
|
39
|
+
- **反例只有异常类名**:`findRecoveries()` 只写 `(TypeError)`,丢掉了消息。新增 `errorDetail()`,写入 `失败(TypeError: pad is not a function)`。
|
|
40
|
+
- **`rendered` 标记不落盘**:`markRendered()` 只改内存,进程在组装与 turn 收尾之间崩溃就丢失"是否真的注入过"的唯一证据。改为立即 `persist()`。
|
|
41
|
+
- **新建捕获没有诊断理由**:`runCapture()` 的新建分支不写 `outcome.reason`,`/memory debug` 只显示 `PASS exp-N`。现在写明 `新建 exp-N(scope …;指纹 … 全绿)`。
|
|
42
|
+
- **scope 会录进用户名**:`mentionedDirs()` 取最深段但仍保留祖先段,路径里的用户目录名会被记成项目名。改为**只保留每段路径的最深非通用目录**,并忽略 `node-project/feature` 这类任务类型形状。
|
|
43
|
+
- **旧档案仍带绝对路径**:新增 `C.scrubRecord()`,`loadStore()` 时对历史记录做一次幂等脱敏(记录数会打一行 warn)。
|
|
44
|
+
|
|
45
|
+
### 测试
|
|
46
|
+
- 新增 `tools/e2e.mjs`(`npm run test:e2e`):18 条,覆盖注册/冷启动/捕获/G7 拒绝/批准后注入/部分命中查找/只读衰减报告/teach 钉住/agent 生命周期/重复配方合并/跨目录隔离/无关查询不注入/删除保护/review 只读/config 类型强转/双 agent 隔离/持久层无绝对路径/新建理由。
|
|
47
|
+
- `tools/selftest.mjs` 增至 70 条(新增 T58 目录识别、T59 幂等脱敏、T60 下划线产物命名)。
|
|
48
|
+
- 合计 **88 pass / 0 fail**。
|
|
49
|
+
|
|
50
|
+
### 运行时验证
|
|
51
|
+
- `applied.json` = `{"build":"r10-scope-fix"}`(重载后 `application: applied`)。
|
|
52
|
+
- 发布树重建:`leak scan: clean (0 hits)`,`tools/e2e.mjs` 已加入白名单。
|
|
53
|
+
|
|
54
|
+
### 已知限制
|
|
55
|
+
- 旧记录(本机 exp-1/5/13/15/16/17)的 `fingerprint.targets` 仍是 `<path>/…` 占位符,与新记录的裸 basename 不互通;它们会随时间衰减,不做回填。
|
|
56
|
+
- `experience_forget` 收单个 `id`,`experience_lookup` 收 `ids[]`,参数形状不一致(历史原因,已在 README 标注)。
|
|
57
|
+
|
|
58
|
+
## [1.0.1] — 2026-11-09 — r9 实测修复
|
|
59
|
+
|
|
60
|
+
### 修复
|
|
61
|
+
- **`experience_lookup` 部分命中不再静默**(P2,`694bd23`):新增 `lib/lookup.js` 的 `splitLookup()/renderLookup()`。命中项保持 store 顺序(与旧输出逐字一致),缺失 id 按请求顺序去重后追加 `未找到:exp-999`。全命中/全不中措辞未变。
|
|
62
|
+
|
|
63
|
+
### 新增
|
|
64
|
+
- **G7 步骤质量闸门**(P1,`903e4a6`):自动捕获不再把脚手架命令当配方。
|
|
65
|
+
- `summarizeCalls()` 丢弃 `、`New-Item`、`Test-Path`、`Get-ChildItem`、`Set-Location`、`Write-Host` 等前缀与裸赋值;
|
|
66
|
+
- `effectiveSteps()` 只数写操作与测试执行,有效步骤 < `minEffectiveSteps`(新配置键,默认 2)即放弃;
|
|
67
|
+
- `actionableTitle()` 要求标题是「动作 + 具体对象」,`写 <path>/<name>.js` 一类碎片被拒;
|
|
68
|
+
- `buildCandidate()` 优先用原始 basename 生成标题(`truncate.js` → `新增 truncate`),归一化占位符不再充当产物名;
|
|
69
|
+
- 判定失败写 `trace.skipReason = 'G7: …'`,不影响 G1–G6 短路链。原 10 个数值默认值未改动。
|
|
70
|
+
|
|
71
|
+
### 验证
|
|
72
|
+
- `node tools/selftest.mjs` → **67 pass / 0 fail**(T32 lookup 六种输入;T33 脚手架被拒;T34 真实配方通过;T35 标题规则;T36 1000 调用 < 20ms)。
|
|
73
|
+
- 运行时 `applied.json` = `{"build":"r9-step-gate"}`,`config` 含 `minEffectiveSteps: 2`。
|
|
74
|
+
- 已知:G7 的拒绝分支目前只有单测覆盖,真实 `capture: SKIP G7` 需一个纯脚手架 turn 才会出现。
|
|
75
|
+
|
|
76
|
+
## [0.2.0-m2] — 2026-11-09
|
|
77
|
+
|
|
78
|
+
### 新增
|
|
79
|
+
- **结果指纹合并(r7)**:`lib/capture.js` 的 `outcomeFingerprint()/fingerprintsMatch()`;写文件 basename 相同且本次测试全绿 → 直接认定同一终态,合并时不再看 stepsJaccard、也不看 mergeThreshold。
|
|
80
|
+
- **指纹等效证据**:`lib/evidence.js` 的 `markFingerprintEquivalent()`;`promotionState()` 里 `effective()` 让 `record.fingerprint.green` 或 `byFingerprint` 的运行稳定性记 1.0,detail 追加「指纹等效 N」。
|
|
81
|
+
- **G3 验证型放行**:全绿验证轨迹(无写操作)也算独立证据,`verificationOnly` 随 run 落库。
|
|
82
|
+
- **scope 硬闸门**:不同目标目录不合并(`scopeMustMatch`),`mergeThreshold` 默认 0.75。
|
|
83
|
+
- `/memory reevaluate [id]`、`/memory review --auto`;`[2.5 证据]` 层打印「为什么还没升级」。
|
|
84
|
+
|
|
85
|
+
### 修复
|
|
86
|
+
- 用户报 exp-11 指纹合并后仍被判 `stability 0.2 < 0.7`:判据从「仅比 steps」改为「指纹命中优先」。现在 `exp-11` 显示 `stability=1(原始 0.2)· ready`。
|
|
87
|
+
- 配置类型:`/memory config set` 走 `coerceConfigValue`,`"true"` 不再存成字符串。
|
|
88
|
+
|
|
89
|
+
### 事故与恢复(必须记录)
|
|
90
|
+
- **自伤**:用 `Get-Content -Raw | Set-Content` 改 `index.js` 帮助文案,按非 UTF-8 写回,90 处中文变 U+FFFD;后续用 codepage 936 反推进一步损坏,源文件不可逆。
|
|
91
|
+
- **恢复**:从会话日志(zstd 多帧 `session.v4.jsonl.zstd`)解出全部 `tool/call`,按 seq 重放 `write`/`edit` 得到 `index.js` 底线(r3.3 谱系),再用 `tools/_restore-r7.mjs` 一次性补回 16 处 r4–r7 接线(import evidence / migrateStore / isRecallable / noteEvidence / noteFailure / 指纹优先合并 / scope 否决 / `[2.5 证据]` / review --auto / config 强转 / 计数口径)。
|
|
92
|
+
- **教训(已写进规则)**:源码只允许 `write`/`edit` 工具或 `fs.writeFileSync(..., 'utf8')`;禁止 shell 文本重写。恢复类脚本统一放 `tools/`,每个锚点做唯一性断言。
|
|
93
|
+
|
|
94
|
+
### 验证
|
|
95
|
+
- `node --check index.js` 通过;`tools/selftest.mjs` **55 pass / 0 fail**。
|
|
96
|
+
- 运行时 `applied.json` = `{"build":"r7-fingerprint"}`;`experience_debug` 输出含 `[2.5 证据]` 与新计数口径。
|
|
97
|
+
|
|
98
|
+
## [0.1.0] — 2026-11-09 — MVP 封版
|
|
99
|
+
|
|
100
|
+
**状态**:已验收(用户 m00389 通过)。快照见 `archive/v0.1/`,安装方式为 Junction(`link:`),改动即热更。
|
|
101
|
+
|
|
102
|
+
### 交付
|
|
103
|
+
|
|
104
|
+
- 纯 Host bundle,零运行时依赖(只用 `node:fs/os/path/crypto`),`plugin_manager install_bundle target=link:...` 安装。
|
|
105
|
+
- 生命周期介入点:`agent/pre-step`(waterfall,装配后准入前)、`agent/turn-stopping`(trace 落盘)。
|
|
106
|
+
- 注入通道:`agent.ctx.systemPrompt.context({ name: 'experience-recall-v2', order: 9000, required: true })`,`text()` 每次准入前重读。
|
|
107
|
+
- 工具:`experience_record` / `experience_lookup` / `experience_forget` / `experience_debug`(Inspect `Tool.listTools` 已核验)。
|
|
108
|
+
- 命令:`/memory list|show|approve|reject|teach|why|debug`。
|
|
109
|
+
- 存储:`${DSH_HOME:-~/.dsh}/experience/store.json`,含 `experiences[] / injections[] / turns[]`。
|
|
110
|
+
- 六层诊断:存储 → 可召回 → 检索 → 注入 → 模型可见 → 生效,逐层 PASS/FAIL + `hintFor()`。
|
|
111
|
+
|
|
112
|
+
### 已核验证据
|
|
113
|
+
|
|
114
|
+
- `applied.json` 自证:`{"build":"r2-candidate-scoring","pid":360,...}`。
|
|
115
|
+
- 注入链:`inj-1 nonce=exp-22c77b rendered=true tokens=297`,同一 step 模型可见并回显 nonce。
|
|
116
|
+
- 检索:`exp-1=0.619(verified)`,阈值 0.15。
|
|
117
|
+
- 效率:首次任务 7 次调用(3 发现 + 2 写 + 2 测试);复用后 3 次调用(2 写 + 1 测试),零发现、零踩坑。
|
|
118
|
+
|
|
119
|
+
### 归档文件(SHA256 前 12 位)
|
|
120
|
+
|
|
121
|
+
| 文件 | 字节 | SHA256[:12] |
|
|
122
|
+
| --- | --- | --- |
|
|
123
|
+
| index.js | 25428 | 7C4714B9AAA7 |
|
|
124
|
+
| package.json | 363 | ABEF3E840327 |
|
|
125
|
+
| cordis.patch.yml | 113 | ADF70F518A12 |
|
|
126
|
+
| README.md | 2870 | 0EA5BEB4677A |
|
|
127
|
+
| ACCEPTANCE.md | 5508 | BCB02B5F31C9 |
|
|
128
|
+
|
|
129
|
+
### 已知限制(不修,进 v0.2 规划)
|
|
130
|
+
|
|
131
|
+
- 召回只在 turn 的 `step === 1` 触发;新 turn 首条消息必须是任务本身。
|
|
132
|
+
- `candidate` 永不自动召回;升级只能靠人工 `/memory approve`(Agent 无入口)。
|
|
133
|
+
- 沙箱 shell 对 `~/.dsh` 只读(写入 EPERM),改库只能走插件工具。
|
|
134
|
+
- token / 墙钟无同口径基线,效率只报调用数与测试次数。
|
|
135
|
+
- `file:` 安装是复制快照,务必用 `link:`,否则编辑不生效(已踩坑,见 ACCEPTANCE.md 第 0 节)。
|
|
136
|
+
|
|
137
|
+
## [0.3.0-m3.1-m3.3] — 2026-11-09
|
|
138
|
+
|
|
139
|
+
- 新增 `lib/decay.js`:`rankOf / freshnessOf / utilityOf / stateOf / isPinned / describeDecay / selectEvictions / markDecay / decayLine / renderDecayReport / applyEvictions / restoreRecord`,全部纯函数、`now` 注入。
|
|
140
|
+
- `[2.6 衰减]` 层接入 `experience_debug` 与 `/memory why`;`/memory debug` 追加整库衰减报告。
|
|
141
|
+
- `active → dormant`:每轮 `agent/turn-stopping` 写入 `record.decay`(只写判定字段,不动 score/status/steps);`recallable()` 跳过 dormant(pinned 豁免)。
|
|
142
|
+
- `/memory decay [--age N] [--apply]`:默认只列 Top-5 建议;`--apply` 移入 `store.archive` 并写 `store.evictions` 审计,**不物理删除**;`/memory restore <id>` 恢复。
|
|
143
|
+
- 单测 62 条全绿(新增 T29/T30/T31)。
|
|
144
|
+
|
|
145
|
+
## [0.2.0-m1] — 2026-11-09 — L1 自动捕获(已验收)
|
|
146
|
+
|
|
147
|
+
**状态**:用户实测 T1/T2/T3 通过(m00541)。运行 build `r3.3-steps-priority`;快照 `archive/v0.2-m1/`,哈希见该目录 `MANIFEST.md`。
|
|
148
|
+
|
|
149
|
+
### 交付
|
|
150
|
+
|
|
151
|
+
- 采集点:`tools/result`(emit,零 dispatch 延迟)→ `liveCalls[agentId]`;抽取在 `agent/turn-stopping`,纯字符串,无 IO、无模型调用。
|
|
152
|
+
- 六闸门(G1 成功调用≥2 / G2 非 `/memory`·非 `experience_*` / G3 有成功写或恢复链 / G4 同 taskType 且 score≥0.6 合并 / G5 配额 / G6 序列化≥120 字符),每次给出 `trace.capture.reason`。
|
|
153
|
+
- 脱敏:`sk-`/`ghp_`/`AKIA`/`xox`/Bearer/key=value/base64(混合字符) + Windows 用户目录与绝对路径归一化。
|
|
154
|
+
- 性能熔断:抽取 > `captureBudgetMs`(20ms) 即放弃;配额 `dailyLimit=10` / `libraryLimit=200` / `mergeThreshold=0.6` 全部走 `~/.dsh/experience/config.json`,`/memory config set` 可改。
|
|
155
|
+
- 命令:`/memory review [--approve-all | approve <n> | reject <n>]`、`/memory config`、`/memory stats`;工具 `experience_review` 只读、不可自批。
|
|
156
|
+
- 探针:首次 `tools/result` 把 `ToolExecution` / `ToolExecutionResult` 的真实字段写入 `probe.json`,据此收敛 `pickOk`/`pickError`。
|
|
157
|
+
- 观测:trace 增加 `calls[]`、`recallMs`、`capture{ok,reason,ms,id,merged,added}`。
|
|
158
|
+
|
|
159
|
+
### 已核验证据(用户实测)
|
|
160
|
+
|
|
161
|
+
- `recallMs=0`;`capture: PASS exp-5 (0ms)`——捕获对每轮耗时无可观测影响。
|
|
162
|
+
- `[2 可召回] PASS (verified=2)`;注入 `rendered=true tokens=388 ids=exp-1,exp-5`(双经验同时注入)。
|
|
163
|
+
- 步骤数 9 → 6。
|
|
164
|
+
|
|
165
|
+
### 修复
|
|
166
|
+
|
|
167
|
+
- `summarizeCalls` 曾把探索当核心步骤(exp-5 记录了 `跑 Get-ChildItem`、`跑 Get-Content …/slugify.js`)。新增 `stepPriority` 阶梯:测试执行 4 / 写 3 / 其他真实命令 2 / 探索 0(`Get-ChildItem`、`Get-Content`、`dir`、`grep`、`read_file` 等一律剔除)。补充 5 条用例,T0/T4 由 31 条升至 **35 pass / 0 fail**。
|
|
168
|
+
|
|
169
|
+
### 未做(进 M2)
|
|
170
|
+
|
|
171
|
+
- 自动/半自动升级仍不存在:`candidate` 只能由人批准。
|
|
172
|
+
- 无衰减、无版本化、无跨会话证据累积。
|
|
173
|
+
|
|
174
|
+
## [0.2.0-m2] — 2026-11-09 — L2 证据升级(M2.0–M2.2)
|
|
175
|
+
|
|
176
|
+
**状态**:代码与合成测试完成;真实链路(M2.5)等用户手动触发。
|
|
177
|
+
|
|
178
|
+
### 交付
|
|
179
|
+
|
|
180
|
+
- **schema v2(M2.0)**:每条经验新增 `proof = { runs[], distinctSessions, minStability, lastSuccessAt, lastFailureAt }`;`loadStore()` 读入即跑幂等迁移并回写,`version: 2`。
|
|
181
|
+
- **证据纯函数(M2.1)**:`lib/evidence.js` —— `emptyProof / ensureProof / stepsHash / jaccardSteps / recordEvidence / promotionState / promote / migrateStore`,零依赖、无 IO、不调模型。
|
|
182
|
+
- **接线(M2.2)**:`runCapture` 三条路径都记账——新记录、G4 合并、G3 失败(按 `mergeThreshold` 找最匹配经验记 `failure`);证据状态只由这段确定性代码写。
|
|
183
|
+
- **升级链**:`candidate →(≥2 个独立 session 成功 + 步骤 Jaccard ≥ 0.7 + 成功之后无失败)→ auto-verified →(人工)→ verified`。`promote()` 最多写 `auto-verified`(`verify.by = 'evidence'`,confidence 0.55),**永不写 `verified`**。
|
|
184
|
+
- **召回闸门**:`isRecallable()` —— 只有 `verified`;`auto-verified` 仅在 `allowAutoVerified === true` 时放行,默认 false。
|
|
185
|
+
- **诊断(M2.4)**:`/memory debug` 与 `experience_debug` 新增 `[2.5 证据]` 行,直接打印不升级的理由(`autoPromote=false:策略关闭…` / `未满 2 个独立 session;独立 session 1/2…` / `步骤稳定性 0.5 < 0.7,视为不同变体` / `最后一次成功之后出现失败,证据链作废`)。
|
|
186
|
+
- 配置新增 `autoPromote / minDistinctSessions / stepsJaccard / allowAutoVerified`,全部可经 `/memory config set` 读写。
|
|
187
|
+
|
|
188
|
+
### 已核验证据
|
|
189
|
+
|
|
190
|
+
- `node --check index.js lib/evidence.js` 均 exit 0。
|
|
191
|
+
- `tools/selftest.mjs`:**43 pass / 0 fail**(原 35 + M2 八条:T5 两 session 升级、T6 同 session 不独立、T7 失败作废、T8 步骤漂移、T9 策略关闭文案、T10 不碰已验证、T11 迁移幂等、T12 哈希/Jaccard)。
|
|
192
|
+
- 运行时:`applied.json` = `{"build":"r4-l2-evidence","pid":360}`;`store.json` 已迁移为 `"version": 2`,exp-1/exp-5 均补齐 `proof`;`experience_debug` 输出 `build: r4-l2-evidence`、四项新配置、`[2.5 证据]` 行。
|
|
193
|
+
|
|
194
|
+
### 未做(进 M2.3/M2.5)
|
|
195
|
+
|
|
196
|
+
- `/memory review --auto` 还没有单独视图(`reviewTargets` 已含 `auto-verified`,可被批量批准)。
|
|
197
|
+
- 真实链路(两次真实任务攒够证据)未跑,等用户触发;`autoPromote` 与 `allowAutoVerified` 默认关闭,本次不改变默认值。
|
|
198
|
+
|
|
199
|
+
## [0.2.0-m2.1] — 2026-11-09 — M2 缺陷修复(配置类型 / 计数口径 / 证据基线)
|
|
200
|
+
|
|
201
|
+
用户实测触发三个真实缺陷,全部修复并有单测。
|
|
202
|
+
|
|
203
|
+
### 修复
|
|
204
|
+
|
|
205
|
+
- **配置类型未转换**:旧逻辑 `Number.isFinite(Number('true'))` 为 false,`autoPromote` 落库成字符串 `"true"`;`isRecallable()` 用 `=== true` 比较,字符串永远不成立。新增 `C.coerceConfigValue(key, raw)`:按 `DEFAULT_CONFIG` 的类型把 `true/false/yes/no/on/off` 转布尔、数字串转 Number,类型不符直接报错;`loadConfig()` 对已落库的字符串配置同样纠正并回写(实测 `config.json` 由 `"autoPromote": "true"` 变为 `true`)。
|
|
206
|
+
- **`auto` 计数误导**:`experiences: … auto 1` 统计的是 `source.auto`(自动捕获条数),不是 `auto-verified`。现在分开打印 `auto-verified N, auto-captured M`。`distinctSessions` 本身累加正确(exp-5 已到 2)。
|
|
207
|
+
- **证据基线被历史污染**:`stability` 原以记录自身的 `steps` 为基线,而 exp-5 的 steps 来自 r4 前的探索污染(含 `跑 Get-ChildItem`、`跑 Get-Content`),首轮即算出 `0.182`,此后永远 `drift`。改为:
|
|
208
|
+
- 每次运行存 `steps` 快照;`stability = Jaccard(上一次成功的 steps, 本次 steps)`;
|
|
209
|
+
- 无快照的历史运行不参与比较(`minStability` 只取有快照运行之间的相邻比较);
|
|
210
|
+
- 快照不足时返回新状态 `needs-baseline` 并写明“还需 N 次同类成功运行”,不再伪造 `1`;
|
|
211
|
+
- `[2.5 证据]` 行同时打印 `runs/sessions/stability`,无快照显示 `n/a`。
|
|
212
|
+
|
|
213
|
+
### 已核验证据
|
|
214
|
+
|
|
215
|
+
- `tools/selftest.mjs`:**47 pass / 0 fail**(原 43 + T13 配置转换、T14 相邻运行基线、T16 无快照历史运行)。
|
|
216
|
+
- 运行时代码:`build: r4-l2-evidence`,`config: {…"autoPromote":true…}`(布尔),`[2.5 证据] WAIT exp-6 … runs=0 sessions=0 stability=n/a → 尚无结构化证据…`(冒烟后已删除 exp-6)。
|
|
217
|
+
- 纯函数实测:同一记录两次不同 session 成功后 `promotionState → code:ready / eligible:true`,`promote()` 只写 `auto-verified`。
|
|
218
|
+
|
|
219
|
+
### 未变
|
|
220
|
+
|
|
221
|
+
- `autoPromote` 仍默认 `false`,`allowAutoVerified` 默认 `false`:auto-verified 只是更高优先级的候选池,人工不点头就不进召回。
|
|
222
|
+
|
|
223
|
+
## 规划
|
|
224
|
+
|
|
225
|
+
- v0.2:经验库自动扩展(L1 自动捕获 / L2 证据升级)+ 衰减机制 → `docs/ROADMAP-v0.2.md`
|
package/CONTRIBUTING.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Contributing to dsh-experience
|
|
2
|
+
|
|
3
|
+
Thanks for taking a look. This is a small, zero-dependency plugin; the bar for a PR is
|
|
4
|
+
"adds a test, keeps all tests green, and does not add a runtime dependency".
|
|
5
|
+
|
|
6
|
+
## Setup
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git clone https://github.com/Aatzer0/dsh-experience.git
|
|
10
|
+
cd dsh-experience
|
|
11
|
+
node --version # needs >= 20
|
|
12
|
+
node tools/selftest.mjs
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
There is no build step and no `npm install` — the plugin only uses `node:` builtins.
|
|
16
|
+
For live development against a running Harness instance, install it by link:
|
|
17
|
+
|
|
18
|
+
```text
|
|
19
|
+
plugin_manager install_bundle target=link:<absolute path to this checkout>
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Then reload after edits:
|
|
23
|
+
|
|
24
|
+
```text
|
|
25
|
+
plugin_manager set_bundle dsh-experience enabled=true
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
`~/.dsh/experience/applied.json` contains the build id, PID and timestamp of the
|
|
29
|
+
currently loaded code — the fastest way to prove a reload actually happened.
|
|
30
|
+
|
|
31
|
+
## What to work on
|
|
32
|
+
|
|
33
|
+
- Bug reports with a reproducible trace are the most valuable contribution.
|
|
34
|
+
- New capture signals / gates: open an issue first. Every gate changes what gets
|
|
35
|
+
remembered, and a wrong gate silently poisons the library.
|
|
36
|
+
- Anything that makes the plugin call out to the network or add a dependency:
|
|
37
|
+
these need a design discussion, not a PR.
|
|
38
|
+
|
|
39
|
+
## Coding conventions
|
|
40
|
+
|
|
41
|
+
- **No runtime dependencies.** `node:fs`, `node:path`, `node:crypto` only.
|
|
42
|
+
- **Pure logic goes in `lib/`**, side effects stay in `index.js`. All `lib/` modules
|
|
43
|
+
must be importable without a Harness runtime so they stay unit-testable.
|
|
44
|
+
- **Never write source files through a shell pipeline.** On Windows,
|
|
45
|
+
`Set-Content -Encoding UTF8` writes a BOM and CRLF and corrupts non-ASCII text;
|
|
46
|
+
use an editor or `fs.writeFileSync(path, text, 'utf8')`.
|
|
47
|
+
- **Redaction is part of the contract.** If you capture a new field, run it through
|
|
48
|
+
the redactor and add a test asserting a secret-looking value does not survive.
|
|
49
|
+
- Comments in code are English; user-facing strings (command output, tool
|
|
50
|
+
descriptions, docs) are Simplified Chinese, matching the `/memory` surface.
|
|
51
|
+
|
|
52
|
+
## Tests
|
|
53
|
+
|
|
54
|
+
`tools/selftest.mjs` is a single-file, `node:assert`-based suite with two kinds of cases:
|
|
55
|
+
|
|
56
|
+
1. **T0/T4 synthetic** — pure function behaviour: scoring, gates, merge, fingerprints,
|
|
57
|
+
evidence promotion, decay math, eviction/restore.
|
|
58
|
+
2. **Regression fixtures** — every bug ever fixed gets a case named after the symptom.
|
|
59
|
+
|
|
60
|
+
Run it before and after your change:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
node tools/selftest.mjs
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The suite must stay at `0 fail`. If you change a default in `lib/capture.js`
|
|
67
|
+
(`DEFAULT_CONFIG`), update the deep-equal assertion in the suite as part of the same commit.
|
|
68
|
+
|
|
69
|
+
## Pull requests
|
|
70
|
+
|
|
71
|
+
1. Fork, branch from `main` (`feat/...`, `fix/...`).
|
|
72
|
+
2. Keep the diff focused: one behaviour per PR.
|
|
73
|
+
3. Include:
|
|
74
|
+
- what changed and why (one paragraph, not a changelog),
|
|
75
|
+
- the failing case that motivated it, if it is a fix,
|
|
76
|
+
- the selftest output line (`N pass / 0 fail`).
|
|
77
|
+
4. Update `CHANGELOG.md` under `## [Unreleased]`.
|
|
78
|
+
|
|
79
|
+
## Commit messages
|
|
80
|
+
|
|
81
|
+
Conventional Commits, imperative mood, English:
|
|
82
|
+
|
|
83
|
+
```text
|
|
84
|
+
fix(capture): skip verification-only turns when the suite is red
|
|
85
|
+
feat(decay): add --age simulation flag
|
|
86
|
+
docs: clarify recall-only-on-step-1 constraint
|
|
87
|
+
```
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Aatzer0
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,157 @@
|
|
|
1
|
-
#
|
|
1
|
+
# dsh-experience
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
> **带生命周期治理与指纹防伪的 DSH 跨会话自学习插件** —— 同类任务第一次慢,第二次直接用上第一次的经验,但绝不把一次偶然的变通当成真理。
|
|
4
|
+
|
|
5
|
+
[](tools/selftest.mjs)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://github.com/Aatzer0/dsh-experience)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 它解决什么问题
|
|
12
|
+
|
|
13
|
+
Agent 每次会话都从零开始:读同样的配置文件、踩同样的坑、走同样的探索路径。
|
|
14
|
+
|
|
15
|
+
`dsh-experience` 在插件层把「做过的事」变成「可复用的经验」,并用八道闸门(G1–G8)防止脏经验污染后续决策:
|
|
16
|
+
|
|
17
|
+
1. **自动捕获** —— 任务结束时从工具调用轨迹里提炼步骤与反例,不额外调用模型;
|
|
18
|
+
2. **指纹验证** —— 同一「结果指纹」在多个独立会话中复现才累计证据(步骤文本可以完全不同);
|
|
19
|
+
3. **生命周期治理** —— 按状态设定半衰期,排序分数自动衰减,容量超 80% 时给出归档建议,但**从不物理删除**。
|
|
20
|
+
|
|
21
|
+
## 核心特性
|
|
22
|
+
|
|
23
|
+
| 能力 | 说明 | 位置 |
|
|
24
|
+
| --- | --- | --- |
|
|
25
|
+
| **L1 自动捕获** | 监听 `tools/result`,在 `turn-stopping` 用纯字符串规则蒸馏;八道闸门过滤噪声(G7 步骤质量、G8 否决复现)(无写操作、无恢复、非全绿验证、自噬调用……) | `lib/capture.js` |
|
|
26
|
+
| **L2 指纹防伪** | `targets + green` 结果指纹;指纹命中即视为同一经验,绕开「步骤文本相似度」这一不可靠判据 | `lib/evidence.js` |
|
|
27
|
+
| **人工终审** | `candidate → auto-verified → verified`,最后一跳只能由人完成;Agent 没有任何写状态入口 | `/memory approve` |
|
|
28
|
+
| **M3 生命周期** | `rank = freshness × utility`,半衰期 verified 180 天 / auto-verified 60 天 / candidate 30 天;`dormant` 只降权不删除 | `lib/decay.js` |
|
|
29
|
+
| **零性能损耗** | 捕获是 O(≤40 次调用) 的纯字符串运算,实测 `avgCaptureMs: 1`;召回在本地做词覆盖打分,无网络、无向量库 | `experience_debug` |
|
|
30
|
+
| **可观测** | 六层诊断逐层 PASS/FAIL,直接回答「为什么这次没命中」 | `/memory debug` |
|
|
31
|
+
|
|
32
|
+
## 为什么经验必须由你批准
|
|
33
|
+
|
|
34
|
+
自动捕获的经验只会进入 `candidate` 状态,**永远不会被注入**。只有你执行 `/memory approve <id>` 之后,它才变成 `verified` 并进入召回池。Agent 侧没有任何写入状态的入口——`experience_record` 只能新建候选,`experience_review` 是只读的,「批准」这个动作只存在于 `/memory` 命令里。
|
|
35
|
+
|
|
36
|
+
这是有意的取舍:一条错误经验被注入的代价,远高于你多点一次批准。
|
|
37
|
+
|
|
38
|
+
`auto-verified` 是给未来留的中间档(同一指纹在两个以上独立会话复现才升级),默认**既不自动升级、也不参与召回**(`autoPromote=false`、`allowAutoVerified=false`),在人工批准之前不会污染召回池。
|
|
39
|
+
|
|
40
|
+
## 架构
|
|
41
|
+
|
|
42
|
+
```mermaid
|
|
43
|
+
flowchart LR
|
|
44
|
+
A[Turn 开始] --> B["agent/pre-step<br/>step 1"]
|
|
45
|
+
B --> C{召回<br/>score ≥ 0.15}
|
|
46
|
+
C -- 命中 --> D["PromptContext<br/>注入经验摘要"]
|
|
47
|
+
C -- 未命中 --> E[正常执行]
|
|
48
|
+
D --> E
|
|
49
|
+
E --> F["tools/result<br/>采集调用"]
|
|
50
|
+
F --> G["agent/turn-stopping<br/>蒸馏 + 八道闸门"]
|
|
51
|
+
G -- 指纹/同域合并 --> H[(已有经验)]
|
|
52
|
+
G -- 新建 --> I[candidate]
|
|
53
|
+
I --> J{独立会话<br/>指纹复现 ≥ 2}
|
|
54
|
+
J -- 是 --> K[auto-verified]
|
|
55
|
+
K --> L((人工批准))
|
|
56
|
+
L --> M[verified]
|
|
57
|
+
M --> N["rank 衰减<br/>dormant / 归档建议"]
|
|
58
|
+
H --> N
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
设计取舍写在明面上,而不是留给人猜:
|
|
62
|
+
|
|
63
|
+
- **注入走 `systemPrompt.context` 而非 `agent.inject()`** —— context 文本在 `pre-step` 之后会被重新读取,因此同一 step 就能生效,且不产生会话事件噪音;
|
|
64
|
+
- **不使用 `storageDomain`** —— 它会引入 `zod` / `@deepseek-ai/*` 依赖;本插件坚持零依赖,用 JSON sidecar 存 `$DSH_HOME/experience/store.json`;
|
|
65
|
+
- **召回只在每轮第 1 步** —— 后续 step 的上下文已被工作内容污染,此时注入等于干扰。
|
|
66
|
+
|
|
67
|
+
## 安装
|
|
68
|
+
|
|
69
|
+
### 方式一:作为 bundle 安装(推荐)
|
|
70
|
+
|
|
71
|
+
```text
|
|
72
|
+
plugin_manager install_bundle target=file:<PATH-TO-dsh-experience>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
开发模式(改代码即时生效,Junction 链接):
|
|
76
|
+
|
|
77
|
+
```text
|
|
78
|
+
plugin_manager install_bundle target=link:<PATH-TO-dsh-experience>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
安装后 `plugin_manager list_plugins` 应出现 `dsh-experience` 且 `fiberPhase: active`。
|
|
82
|
+
|
|
83
|
+
### 方式二:手工写进 profile
|
|
84
|
+
|
|
85
|
+
编辑 `~/.dsh/profiles/<profile>/package.json`:
|
|
86
|
+
|
|
87
|
+
```json
|
|
88
|
+
{
|
|
89
|
+
"dependencies": {
|
|
90
|
+
"dsh-experience": "link:<PATH-TO-dsh-experience>"
|
|
91
|
+
},
|
|
92
|
+
"dsh": {
|
|
93
|
+
"profile": {
|
|
94
|
+
"bundles": ["dsh-experience"]
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
重启 DSH 后,在任意会话里执行 `/memory list`,看到 `库 0 条` 即安装成功。
|
|
101
|
+
|
|
102
|
+
## 命令速查
|
|
103
|
+
|
|
104
|
+
| 命令 | 作用 |
|
|
105
|
+
| --- | --- |
|
|
106
|
+
| `/memory review` | 查看候选经验,附「为什么还没升级」;被规则否决的记录单列 |
|
|
107
|
+
| `/memory approve <id>` | 人工批准为 `verified`(`--approve-all` 批量) |
|
|
108
|
+
| `/memory reject <id>` | 否决并排除出召回池 |
|
|
109
|
+
| `/memory debug` | 六层诊断 + 整库衰减报告 |
|
|
110
|
+
| `/memory decay [--apply]` | 只读水位报告;`--apply` 归档(可用 `restore` 恢复) |
|
|
111
|
+
| `/memory supersede <id> [原因]` | 标记与当前规则冲突:永不召回,同指纹的轨迹也不再收录 |
|
|
112
|
+
|
|
113
|
+
完整命令见 [USER-GUIDE.md](USER-GUIDE.md)。
|
|
114
|
+
|
|
115
|
+
## 配置
|
|
116
|
+
|
|
117
|
+
运行时配置位于 `~/.dsh/experience/config.json`,可用 `/memory config set <key> <value>` 修改(值会按默认类型强制转换):
|
|
118
|
+
|
|
119
|
+
| key | 默认 | 含义 |
|
|
120
|
+
| --- | --- | --- |
|
|
121
|
+
| `dailyLimit` | `10` | 每日自动捕获上限 |
|
|
122
|
+
| `libraryLimit` | `200` | 库容量(达到 80% 触发归档建议) |
|
|
123
|
+
| `mergeThreshold` | `0.75` | 同任务合并的文本相似度阈值 |
|
|
124
|
+
| `scopeMustMatch` | `true` | 目录不同不合并(硬拦截) |
|
|
125
|
+
| `captureBudgetMs` | `20` | 单次捕获耗时熔断线 |
|
|
126
|
+
| `autoPromote` | `false` | 是否允许证据升级到 `auto-verified` |
|
|
127
|
+
| `allowAutoVerified` | `false` | `auto-verified` 是否参与召回 |
|
|
128
|
+
| `minDistinctSessions` | `2` | 升级所需独立会话数 |
|
|
129
|
+
| `stepsJaccard` | `0.7` | 步骤稳定性门槛 |
|
|
130
|
+
|
|
131
|
+
## 隐私与安全
|
|
132
|
+
|
|
133
|
+
- 只写 `$DSH_HOME/experience/`,**不发起任何网络请求**;
|
|
134
|
+
- 捕获时对 `sk-…`、`ghp_…`、`AKIA…`、`Bearer …`、`password=` 等模式脱敏,绝对路径替换为 `<path>/`;
|
|
135
|
+
- 注入前做长度截断(默认 2 条 / 1600 字符);
|
|
136
|
+
- 仓库不包含任何作者运行时数据,骨架见 [store.example.json](store.example.json)。
|
|
137
|
+
|
|
138
|
+
## 已知限制
|
|
139
|
+
|
|
140
|
+
- 召回仅在每轮第 1 步生效;
|
|
141
|
+
- `auto-verified` 默认不参与召回 —— 错误经验的代价高于多一次点击;
|
|
142
|
+
- 相似度是词覆盖打分,不做向量检索(零依赖的代价);
|
|
143
|
+
- 淘汰只归档不删除,需要 `restore` 才能回到召回池;
|
|
144
|
+
- 经验只描述「怎么做」,不包含业务代码本身。
|
|
145
|
+
|
|
146
|
+
## 开发
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
node tools/selftest.mjs # 72 pass / 0 fail(纯函数 + 闸门 + 衰减)
|
|
150
|
+
node tools/e2e.mjs # 19 pass / 0 fail(假 Cordis context 驱动真实 apply())
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
零依赖、零构建步骤:修改 `index.js` / `lib/*.js` 后重载插件即可。贡献流程见 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
|
154
|
+
|
|
155
|
+
## License
|
|
156
|
+
|
|
157
|
+
MIT © 2025 [Aatzer0](https://github.com/Aatzer0)
|
package/USER-GUIDE.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# dsh-experience 使用指南(v0.3 / r8-decay)
|
|
2
|
+
|
|
3
|
+
> 一句话:任务做完了会自动攒经验;你只需要偶尔确认、偶尔清理。
|
|
4
|
+
> 所有命令都在对话框里输入,命令名 `/memory`。
|
|
5
|
+
|
|
6
|
+
## 1. 每天最常用的四件事
|
|
7
|
+
|
|
8
|
+
### ① 看看攒了什么
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
/memory list # 每条一行:id [状态] (auto/manual) 标题 · dormant 标记
|
|
12
|
+
/memory show exp-12 # 某条经验的全文:步骤、反例、证据、衰减
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
### ② 确认新经验(人工闸门)
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
/memory review # 候选列表,逐条带“为什么没升级”
|
|
19
|
+
/memory review --approve-all # 一次全批准
|
|
20
|
+
/memory approve exp-12 # 单条批准
|
|
21
|
+
/memory reject exp-13 # 单条否决
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
状态含义:
|
|
25
|
+
|
|
26
|
+
| 状态 | 能否被召回 | 含义 |
|
|
27
|
+
| --- | --- | --- |
|
|
28
|
+
| `verified` | ✅ | 人工确认过,主力经验 |
|
|
29
|
+
| `auto-verified` | ❌(默认) | 多次独立运行+指纹自证,但仍需你点头才进召回池 |
|
|
30
|
+
| `candidate` | ❌ | 刚自动捕获,等 review |
|
|
31
|
+
| `rejected` | ❌ | 已否决 |
|
|
32
|
+
|
|
33
|
+
> 想让 `auto-verified` 也参与召回(不建议):`/memory config set allowAutoVerified true`。
|
|
34
|
+
|
|
35
|
+
### ③ 排查“为什么这次没用上经验”
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
/memory debug # 最近一轮的六层诊断 + 整库衰减报告
|
|
39
|
+
/memory why # 同上,只看六层
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
六层依次是 `[1 存储] → [2 可召回] → [2.5 证据] → [2.6 衰减] → [3 检索] → [4 注入] → [5 模型可见]`,第一处 FAIL 就是卡点,行尾会直接写原因。
|
|
43
|
+
|
|
44
|
+
### ④ 清理变老的记忆
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
/memory decay # 只读:容量水位 + rank 最低的 5 条,什么都不删
|
|
48
|
+
/memory decay --age 400 # 模拟“整库老化 400 天”看效果(演示用,不改数据)
|
|
49
|
+
/memory decay --apply # 真正归档(移入 archive,可恢复)
|
|
50
|
+
/memory restore exp-13 # 误归档就恢复
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**安全保证**:`--apply` 只是把记录移进 `store.archive` 并写 `store.evictions` 审计,**从不物理删除**;`verified` 与 `pinned` 永不被归档。
|
|
54
|
+
|
|
55
|
+
## 2. 冷启动 / 手把手教
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
/memory teach 为 Python 项目加 CLI 参数解析 || 读 pyproject; 用 argparse; 写 --dry-run; 跑一次
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
手教的经验默认 `pinned=true`,永不衰减、永不被淘汰。
|
|
62
|
+
|
|
63
|
+
## 3. 参数调节
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
/memory config # 看当前配置
|
|
67
|
+
/memory config set dailyLimit 10 # 每天最多自动捕获几条
|
|
68
|
+
/memory config set libraryLimit 200 # 库上限(80% 即 160 条时开始提示淘汰)
|
|
69
|
+
/memory config set mergeThreshold 0.75
|
|
70
|
+
/memory config set allowAutoVerified false
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 4. 日常节奏建议
|
|
74
|
+
|
|
75
|
+
- **每次做完一类新任务**:`/memory review` 扫一眼,值得留的批准。
|
|
76
|
+
- **每周一次**:`/memory decay` 看水位,库还小就什么都不用做。
|
|
77
|
+
- **发现某条经验总被召回却不合适**:`/memory reject <id>`,或直接告诉我改进它。
|
|
78
|
+
- **不确定为什么没生效**:先 `/memory debug`,把那一屏发我。
|
|
79
|
+
|
|
80
|
+
## 5. 我需要知道的三个事实
|
|
81
|
+
|
|
82
|
+
1. 召回只在**每轮的第 1 步**触发 → 新任务请开新的一轮(新消息)再描述任务。
|
|
83
|
+
2. `auto-verified` 默认不进召回池,这是有意的:错误经验的代价 > 多点一次批准。
|
|
84
|
+
3. 存档位置 `~/.dsh/experience/`:`store.json`(经验/轨迹/审计)、`config.json`、`applied.json`(构建自证)。
|
|
85
|
+
## 经验跟当前规则冲突了怎么办
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
/memory supersede exp-5 沙箱禁止 node --test,必须直跑测试文件
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
这条经验不会删除(留作证据),但从此不会被召回;同样的产物再出现时,G8 闸门会拒绝重新收录,
|
|
92
|
+
省掉"又被学一遍、又得再拒一次"的循环。规则改了以后想恢复,可以直接 `/memory approve exp-5`。
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dailyLimit": 10,
|
|
3
|
+
"libraryLimit": 200,
|
|
4
|
+
"mergeThreshold": 0.75,
|
|
5
|
+
"scopeMustMatch": true,
|
|
6
|
+
"captureBudgetMs": 20,
|
|
7
|
+
"maxRecordChars": 2000,
|
|
8
|
+
"maxCalls": 40,
|
|
9
|
+
"autoPromote": false,
|
|
10
|
+
"minDistinctSessions": 2,
|
|
11
|
+
"stepsJaccard": 0.7,
|
|
12
|
+
"allowAutoVerified": false
|
|
13
|
+
}
|
package/cordis.patch.yml
ADDED