wycto/dsh-evolution ↗★ 0

dsh-evolution

Local-first self-evolution plugin for DSH:把开发会话记成本地账本,用你自己已配好的模型做跨会话复盘,将踩过的坑与有效做法沉淀成本地知识;默认不联网、不上传、可一键导出。 适合需要对开发会话进行复盘、沉淀本地知识库且注重隐私的用户。

패키지
dsh-evolution
호환성
미검증
버전
0.2.2
라이선스
MIT
최근 업데이트
2026. 10. 13.

같은 패키지 이름의 다른 저장소

설치

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:wycto/dsh-evolution

配置项

配置文件是 ~/.dsh-evolution/config.json,也可以用面板改。面板是纯数据驱动渲染的: 配置项的说明、范围、可选值都在 lib/config.js 的 SCHEMA_FIELDS 里, 加一个配置项不需要动面板代码。

主要分组:总开关 / 会话账本 / 自动复盘 / 隐私与脱敏 / 本地 skill 落点 / 接口对接(可选) / 数据库对接(可选) / 检索 / 注入 / 导出与草稿。

关于自动复盘(默认关)

自动复盘 这一组里,除了总开关还有几个真正影响"会不会花钱、花多少"的项:

配置项默认作用
review.enabled❌ 关自动链路的唯一总闸。关着时手动「现在复盘」仍然可用
review.provider / review.model空留空 = 用你当前会话用的模型;也可以指定一个更便宜的。面板里不用手填模型名:配置页顶部的选择器会列出宿主里真实可用的模型,选一个就把这两项一起写好(这两个字段在面板上不显示输入框)
review.extractAfterTurns10攒够多少轮才考虑跑一次
review.idleDebounceMs60000会话静默多久才触发(避免和你抢模型)
review.dailyTokenBudget200000每日 token 预算(默认 20 万,约够跑四十多次复盘),0 = 不限。超了当天直接拒绝,并把原因写进返回值
review.maxInsightsPerRun5一次最多收几条 —— 这是质量阀门,不是省钱开关
review.minNewRecordsPerRun20同一会话两次复盘之间至少新增多少条记录(防连点按钮重复烧钱)
review.timeoutMs120000单次调用超时,到点 abort 并标成 TIMEOUT
review.countUsageAgainstBudget✅ 开这次用量是否计入每日预算(关掉只影响统计)
review.pauseUntil空「暂停 24 小时」写的就是它
复盘用哪个模型:必须从列表里选一个,不选就不复盘

花谁的钱必须是你自己说的。 复盘曾经"跟随你当前会话用的模型",现在删掉了:

  • 会话模型往往正是你正在用的、最贵的那一个。后台功能悄悄顺着它跑,等于为一个你没同意的模型付费;
  • 它随你在 DSH 里随手切模型而变,于是"复盘花多少"变成一个你既看不见也控制不了的量;
  • 面板上写着"跟随当前会话",而这条信息在你没打开面板时随时会变 —— 事后没人能复现"当时为什么花这个钱"。

所以语义只剩两种:配了就用配的,没配就一次都不调(自动链路直接跳过,手动按钮给出"去配置"的提示)。 只填一半(provider 有而 model 没有,或反过来)同样按"没配"处理 —— 宁可不复盘,也不拿半截配置去猜模型名。

配置页「自动复盘」组顶部的选择器会把宿主里真实注册的 provider × model 列出 (对应 /dsh-evolution/models 这个只读能力),选一个就同时写好 review.provider 与 review.model; 面板还会直接告诉你这次会用哪个、来源是"配置里指定的"还是"未配置,不会复盘"。

这一项只有一个下拉,没有任何手填框 —— 能填的入口就会有人填错,而"哪些模型真的可用" 只有宿主知道。所以配置页也不再显示 review.provider / review.model 两个输入框 (它们仍在配置文件里,由选择器写入)。

几个刻意的细节:

  • 列表拿不到就说清楚:某个提供方的模型列表取不到(超时/401)时,只有它变空, 其余提供方照常列出,并在下面写明原因 —— 整页空掉会被误读成"一个模型都没有";
  • 单个提供方列模型最多等 4 秒,目录缓存 60 秒(「刷新」按钮强制取新的), 所以打开配置页不会卡在一次远端查询上;
  • 已有的旧值不会被静默改掉:如果你之前手改过 config.json、填了一个宿主目录里没有的 model id,下拉里会把它作为「当前配置里的值」显示出来并原样保留(选一个列表里的模型即可覆盖);
  • 试跑页的成本估算用的是同一个解析结果,不会出现"按 A 报价、按 B 计费"。

关于检索与注入

  • retrieval.candidatePool(默认 30)先按打分取一个候选池,再按各段预算渲染;
  • retrieval.minRecurrenceToInject(默认 1)是"至少见过几次才允许注入";
  • retrieval.perScopeLimit(默认 12)防止某一类条目把别的段挤掉;
  • inject.* 是四段各自的条数与字数上限(约束 3 条 / 项目洞察 3 条 / 团队 2 条 / 个人 1 条)。

打分是确定性的(同库同配置必然同顺序),否则"试跑看到的"和"真正注入的"会漂移。 排序权重、90 天半衰期、pin 加分这些都写在 lib/retrieve.js 里,面板上每条能看到自己的分数构成。

关于导出与草稿

  • 导出是纯本地行为:exports/ 下生成一对 insights-.md / .json, markdown 默认带证据链(export.includeEvidence),单次上限 export.maxEntries(500 条)。
  • 导入(「导出与草稿」页):选一份导出的 JSON 恢复。语义是按 id 恢复: 字段(复现次数、证据链、时间戳、人工状态)原样保留,库里已有的 id 自动跳过 —— 重复导入同一份文件零副作用,不会把复现次数越导越高(这是它与"复盘写入" 的本质区别)。适合换机器、误清空后把数据搬回来。
  • skill 草稿的门槛刻意高:默认要求 复现 ≥2 次(export.skillMinRecurrence) 且 你已采纳(export.skillRequireAccepted),最多一次 3 个(export.skillMaxDrafts)。 skill 是"可执行流程",比一条提醒重得多;把模型的一次性猜测写成流程,比什么都不写更糟。
  • 生成的 SKILL.md 会先按宿主解析规则自检一遍再允许写盘 —— 格式错了宿主只会静默跳过,表现为"技能没生效",一个静默失效的生成器比没有这个功能更糟。

关于晋升(个人提醒 / 团队规范)

注入的第三、四段(团队规范 / 个人提醒)只能由你手动晋升填进去:

  • promotion.personMinRecurrence(默认 2):在几次会话里复现过才列为候选。 跨仓库提醒会出现在每个仓库的上下文里,所以门槛比"进本仓库"高。
  • promotion.pinOnPromote(默认关):晋升只表示"适用范围更广",不等于"更重要"。
  • 插件不会自动做跨工作区聚合。 那会把同一台机器上不同雇主/项目的经验混在一起 (DESIGN 决策 5),所以「洞察」页只列出够格的候选与不够格的原因,点一下才发生。
  • 晋升是移动不是复制,来源记在条目里,随时可退回原作用域。
  • 晋升为团队规范会进入跨项目的第三段,影响面更大,所以面板会再要一次确认。

关于 skill 落点

面板里可选三种:

选项实际路径说明
插件数据目录(默认)~/.dsh-evolution/skills/不碰你的仓库、不需要改任何 DSH 配置
仓库内 .agents/skills/.agents/skills/DSH 原生发现,随 git 走,团队天然共享
仓库内 .dsh/skills/.dsh/skills/DSH 最高优先级的项目根
自定义路径你填⚠️ 需要你在 DSH 配置里额外加 customSkillDirs,否则写了不生效

⚠️ DSH 的 skill 发现根按 rank 顺序扫描(dsh-skill-filesystem 文档实测):

rank来源路径
100project-dsh/.dsh/skills
200project-agents/.agents/skills
300customConfig.customSkillDirs
400user-dsh/skills
500user-agents/skills
600bundled$DSH_BUNDLED_SKILL_DIR

项目根 = 包含 .git 的最近祖先目录(没有则用当前 cwd)。 用列表外的目录名(比如 .agent 单数)不会被自动发现 —— 这时要么选 customSkillDirs 并在 DSH 配置里加一行,要么就落插件数据目录。 这是选"自定义路径"时面板会提醒的原因。

关于接口与数据库(默认关)

本插件不实现、也不托管任何服务端。

  • 接口(远程存储已实现):api.enabled + storageBackend + baseUrl 三者就位后, 账本与洞察整体读写到该服务(⚠️ 这等于把数据交给那台服务,是显式的隐私决定)。 token 从 api.tokenEnv 指名的环境变量读;401/403 后客户端停止发送。 服务端可以用仓库附带的参考实现跑起来:node scripts/reference-server.mjs [端口] [--token ]; 协议细节见 docs/API-CONTRACT.md。改完配置需重启。
  • 数据库(SQLite 已实现):database.enabled + driver=sqlite 打开后,数据 搬进 Node 内置 node:sqlite 的单文件数据库(默认 /index.sqlite, 零依赖、无需编译)。首次启用会把存量 NDJSON 一次性导入(原文件保留不动, 删掉数据库文件再重启即可完整回退);之后数据库就是真相源,本地文件不再读写。 postgres 驱动只有契约(docs/DB-CONTRACT.md),打开会得到显式警告并回退文件。 面板「总览」页的"数据落点"会如实显示当前用的是哪个后端、数据在哪个文件。 改数据目录 / 数据库路径后需要重启宿主才生效(后端在启动时装配一次)。

用途是把知识存进你更放心的地方 / 共享给团队,不是把数据交给作者。