Releases: 00080000/dsh-project-memory
Release list
v0.5.7
2026-09-20 · 331 checks(+18)
修改
- 数据完整性:旧库迁移时
index.json损坏会连带删掉entries.json(整库清空);store.load()不幂等;链接不落盘;畸形 shard/insight 条目让读取抛错。 - 召回与注入:只匹配
fix的查询会让整条提示通道沉默;文档挤掉符号层;CJK 文件名仍触发意图;when.writes在动手前不命中;常驻任务卡被会话额度截断;getTypeScript以外的entryOn/边界问题。 - insight:
decayDays失效;提升/降级不收口容量;跨层移动丢triggerDerived与命中数。 - 索引:watch 每轮重读整个仓库;chunk 行号漂移;
export interface扫不到;损坏 PDF 不销毁 worker;scoped 依赖 tag 错误。 - 工具命令:
query_memory(type:'task')读错字段;超限淘汰最热文件;/insight edit破坏 trigger。
验证
npm test→ 331 项,exit 0;注入 eval 仍 precision 1.00 / recall 1.00。- 一处旧测试(
insight-derive.test.mjs)原先依赖fitBody的 off-by-one 制造丢弃,已改用更小的maxTokens。
v0.5.6
2026-09-16
Changed
- Injection is now admission control, not retrieval. The old rule was "which entry shares the most with this text", where text meant the human message plus every tool argument — file contents included. A measured session produced 10 injections with 0 of them useful (5921 characters added permanently), among them a recover deleted files procedure pulled in by the literal string
dcterms(it containsrm) and an arXiv fetching note pulled in by a.pptxfile extension. A labelled 8-scenario set now scores precision 1.00 / recall 1.00 (was 0.48 / 0.72), and the control scenario injects nothing. - Only what the step is about to do can trigger an entry. A trigger is
when— normalized ops resolved from the tool call itself (file-write/file-delete/git-commit/release/npm-publish/render-doc/run-bench/ …), the files this step is about to write, and intent words from the human message after stripping quoted spans, paths and filenames.guardcan only narrow. File contents, raw arguments and filenames can never trigger anything, and extension/name globs (*.pptx,README*) are ignored outright. - Legacy triggers keep working — migrated in memory, nothing rewritten on disk.
actions→when.ops(dead ids mapped where possible), concretepaths→when.writes,keywords→when.intents, extension/name globs dropped, and weak actions likegit-commitdropped when the entry already has precise paths.npm run selfcheck:triggersshows exactly what changed and which entries can no longer push. - The hint channel needs an absolute floor, not just a relative one. "Half of this layer's top score" is satisfied even when the top score is itself noise — measured
relative:1.00on entries sharing nothing with the step. Hints now also need an IDF-weighted coverage floor (0.3), at least two shared terms, and a channel-level support ratio (0.15) so a long sentence that happens to share one word says nothing. - Injections are events, not a heartbeat.
gateCooldownSteps(2) bounds how often the item channel may speak, andmaxItemsPerSession/maxItemCharsPerSessioncap the session. The resident task card is exempt — it is a state snapshot and should update when it changes. The budget is a ceiling, not a target. - Prefix-cache discipline is explicit. Injections are appended as a user message at the tail of the history, so the cached prefix is never rewritten; what they add is resident cache-read tokens, not cache misses. Nothing is ever edited in place.
Added
injection-audit.jsonl— one line per actual injection under<root>/.dsh-project-memory/, with the reason it matched (op:/write:/intent:/ hint coverage), what lost the budget (budget/quota/cooldown/coverage:/thin:/support:), and the session budget snapshot. Appends only; rotates atauditMaxBytes; every failure is swallowed so the host request is never affected.npm run eval:injection— 8 labelled scenarios over a 24-entry pool whose triggers are copied verbatim from the real ones, asserting a precision ratchet, precision ≥ 0.90 and a clean control group.--store <insights.json>replays a real store;--selfcheckprints the trigger audit.npm run selfcheck:triggers— pushable vs pull-only, dead action ids, dropped globs, weak actions, entries whosescopecannot intersect the project tag space, and how many entries still lackprevents.trigger.when/guard/preventsare declared in thesave_lessonschema and persist throughnormalizeInsight, so new entries can be authored in the new shape.
v0.5.5
2026-09-15
Fixed
- The benchmark is finally in the npm package.
scripts/was missing fromfiles, so the tarball shipped a README telling you to runnpm run benchwhile including no such file. GitHub was fine — this was npm-only. - Silent injection was dead in a real host.
autoContext.relevanceMincarried a schema default that pinned the legacy overlap gate on, so the documentedsignalMinRatio: 0.5was unreachable and hints could never fire. - Memory was re-sent every step. 78% of the injections in a measured 66-step session were duplicates. Items are now remembered per session.
- A no-op
save()rewrote the store, wiping the IDF cache on every 15 s watch poll and resurrecting deleted watch roots. index_repocreated a literalD:\project\foodirectory for a Windows-style path on Linux/macOS.- The Task Panel "hide hints" toggle only hid two of the tooltips, and forgot the setting on refresh.
Added
- Insights are searchable —
query_memorygainedtype: 'insight'. - Triggers work for every insight kind, matched in two windows (the turn's human text and observed tool calls), before the action rather than after.
npm run bench -- <project>reproduces the performance numbers on your own project — no dsh, no network, no model calls.
Upgrade
- Restart
dsh web(server code and client bundle both changed). insights.jsonv1 → v2 migrates on load, automatically and idempotently.- The
degraded: … kept out by budgetline is quiet by default; setautoContext.budgetLog: onceorallto get it back.
v0.5.4
v0.5.4
索引期不调用任何模型,由构造保证。
buildDocEntries() 不再接受 LLM 参数,索引路径不可能碰到模型。用 stub 模型在 289 个文件 /
2,141 个条目上实测:0 次调用。
检索覆盖整个 chunk,而不只是前 300 字符。
每个文档条目新增有界(≤160)、确定性、去停用词的 terms 字段,覆盖整个 chunk;summary
仍 ≤300 字符专供注入,terms 只用于检索。本仓库文档实测(179 个 chunk):
- 可达的唯一 chunk 词项:27.3% → 100%
- 只出现在第 300 字符之后的词项:0% → 100%(entryHit@5)
- 原本可答的查询排序不受影响:MRR 0.958(含 terms)vs 0.955(不含)
旧 store 会在下一次索引 / watch 触发时自动回填 terms,无需手动重建。
注入的上下文块声明为 form: 'snapshot'。
它是会被后续快照取代的「当前状态」,而非一次性通知;投递通道不变。
新增采集信号与向前兼容的输出契约。
按文件记录 reads / writes(只采集,不改变任何排序或注入行为);query_memory 每行输出
status: 占位(默认 exact)。
辅助 LLM 调用显式且可观测。
仅剩的可选模型调用(查询扩展、反思,均默认关闭)显式解析路由,拿不到路由时留下可见的
degraded 记录,不再静默失败。
测试:231 项。发布包:58 个文件,约 199 kB。
上述基准只度量检索覆盖与排序,不含模型。完整细节见 CHANGELOG。
v0.5.3 — DSH 0.1.5-rc.1 compatibility
v0.5.3 — DSH 0.1.5-rc.1 compatibility
Changed (DSH 0.1.5-rc.1 compatibility)
- devDependencies aligned with the 0.1.5-rc.1 host:
@deepseek-ai/dsh-toolsanddsh-llmmoved from0.1.1-rc.2, anddsh-client-locale/dsh-client-store/dsh-client-ui-primitives/dsh-client-ui-slotsfrom0.1.2-rc.1, all to0.1.5-rc.1— type-checking and bundling now run against the same declaration surface the host ships. - Dropped
@deepseek-ai/dsh-client-runtimefromdevDependencies,dsh.client.injectand the clientCLIENT_EXTERNALS: upstream deleted the package in 0.1.5 (refactor(client): migrate consumers and remove Runtime; npm stops at0.1.1-rc.2). The bundle only ever requiredreact,react/jsx-runtimeanddsh-client-ui-primitives, and the host skips unknowninjectrows, so this is dead-config cleanup rather than a behaviour change — but a stale row would break any future re-bundle that treated it as an external. - Added
@types/react/@types/react-dom(^18.3) as devDependencies: 0.1.5'sdsh-client-ui-primitivesno longer pullsreact/react-dom, so a clean install lefttsconfig.client.json'stypes: ["react","react-dom"]unresolved. - Regenerated
package-lock.jsonvia a clean install: the old lock pinned an entire0.1.1-rc.2/0.1.2-alpha.2peer tree, which madenpm installfail with ERESOLVE once the direct devDependencies moved to 0.1.5-rc.1. - Rebuilt
client/client.js(99.96 kB, 23.4 kB gzip) against the new externals; the entry contract is unchanged (window.__ModuleLoader__.load({ id, factory })plusexports.name/exports.inject). - Verified the consumed host surface is unchanged in 0.1.5-rc.1:
defineTool,ctx.tools.register,BlockAssembler.push/message,createUserMessage,LlmRuntime.stream, theagent/pre-stepwaterfall and its{ kind: 'enter', messages }decision,fs/observed, plugin message sourceform: 'notice', and the client slotsshell.overlay/conversation.chat.commandviewwith servicesslots/sessions/remote/remote.commands/locale.
Fixed (task auto-adoption)
- Subagent sessions no longer mint project tasks: every delegated child runs
todo_write, so the bridge's auto-adopt path created one project task per child, titled from the child's prompt — a multi-audit turn could add several. Auto-creation (and auto-binding) is now skipped when the host session header marks a delegated child (origin: 'subagent'ordelegationDepth > 0);parentSessionis deliberately not used as a signal because it is fork/seed lineage, and a user-forked top-level session still needs tasks. Merging subagent work back into the parent task is left to a future design. - Auto-created task titles prefer the todo list:
pickTitlepreferredmeta.firstHuman, the first human message recorded since the plugin started — after a host restart that is a mid-conversation message, so an aside such as "刚刚你卡死了,注意点" could name a task whose steps belonged to something else. The first todo entry now wins and the human message (preferring the segment after the last:/:) is the fallback.
Tests
- 219 checks green (
taskbridge11 → 15).
Requirements
- DSH
0.1.5-rc.1(or any0.1.xhost whose declared peer ranges match). - Node
>= 18.
v0.5.2
v0.5.2 (2026-09-09)
This release is about speed and reliability: cold indexing is ~4× faster, task resume
surfaces the files you actually touched, and two classes of host-hook failures that could
make dsh stop replying are fixed.
Performance — cold index ~4× faster
| 5,000 files / 20k entries | before | after |
|---|---|---|
| Cold index | 1,093 ms | 272 ms |
| Cold load | — | 43 ms |
query_memory (cached) |
— | median 3.0 ms / p95 5.9 ms |
Indexing used to read every file twice (sha256OfFile + readFileSync) and pay a per-file
async readFile thread-pool round-trip. It now does a single synchronous read and reuses the
same buffer for hashing and decoding (readFileForIndex). The read+hash phase drops from
70% → 11% of the indexing pipeline.
Task resume & resident card
task.filesis kept in hot order — written/edited files first, then reads — so
select_task,query_memorytask rows,/tasksand the task panel all surface the files
worth looking at first.- The resident task card shows up to 3 “editing now” files.
- The card is no longer echoed back when the model just maintained its own todo list.
Reliability
agent/pre-stephardening — a missing/renamed continuation or a downstreamundefined
decision can no longer abort the step (the “dsh stops replying” failure mode). Both degrade
to a validenterdecision; genuine downstream errors still propagate.- Watch poll storms — invalid intervals (NaN/undefined) no longer collapse into a 1 ms
interval; slow polls no longer overlap and stack concurrent indexing. restorePersisted()now keeps persisted watch roots on a cache hit.- Injection no longer re-fires on hotspot churn — the dedupe fingerprint ignores the
volatile “editing now” list, so writing a file no longer re-injects the whole block. - Per-session injection fingerprints; bounded store cache.
Cleanup
- Removed the unused
wrapLlmStreamhelper — silent injection runs solely through the host’s
agent/pre-stepseam.
Upgrade
dsh plugin --profile web add @yolk_vat-y/dsh-project-memory -wTests
215 checks green (166 core + 11 TaskBridge + 11 insight-store + 5 reflection + 7 auto-inject
- 9 insight-actions + 6 host-contract).
v0.5.2 (2026-09-09)
本次聚焦速度与可靠性:冷索引快约 4 倍;续接任务时优先看到你真正改过的文件;并修掉了两类
会让 dsh「收不到回复」的宿主钩子故障。
性能 —— 冷索引约 4 倍
| 5,000 文件 / 20k 条目 | 优化前 | 优化后 |
|---|---|---|
| 冷索引 | 1,093 ms | 272 ms |
| 冷加载 | — | 43 ms |
query_memory(缓存命中) |
— | 中位数 3.0 ms / p95 5.9 ms |
索引原先对每个文件读两遍(sha256OfFile + readFileSync),还要为每文件付一次
async readFile 的线程池往返。现在改为单次同步读,同一 buffer 同时用于哈希与解码
(readFileForIndex),read+hash 相位占比从 70% 降到 11%。
任务续接与常驻卡片
task.files按热点顺序维护——写过/编辑过的文件排前,其次才是只读文件,因此
select_task、query_memory的任务行、/tasks与任务面板都会先给出最该看的文件。- 常驻任务卡最多显示 3 个「编辑中」文件。
- 模型刚自己维护过任务清单时,不再把任务卡回声回去。
可靠性
agent/pre-step加固——延续参数缺失/改名,或下游返回undefined,都不再中断该步
(即「dsh 收不到回复」的故障模式);两者都会降级为合法的enter决策,下游真实错误仍照常上抛。- watch 轮询风暴——非法间隔(NaN/undefined)不再退化成 1 ms 轮询;慢轮询不再叠加并发索引。
restorePersisted()在缓存命中时不再丢失已持久化的监听根。- 注入不再因热点文件变化而重复注入——去重指纹忽略易变的「编辑中」列表,写文件不再重发整块。
- 注入指纹按会话隔离;store 缓存设上限。
清理
- 移除未接线的
wrapLlmStream——静默注入只走宿主的agent/pre-step通道。
升级
dsh plugin --profile web add @yolk_vat-y/dsh-project-memory -w测试
215 项全绿(核心 166 + TaskBridge 11 + insight-store 11 + reflection 5 + auto-inject 7
- insight-actions 9 + host-contract 6)。
v0.5.1
0.5.1
Fixed
- Silent injection could crash every agent step (
next is not a function): theagent/pre-steplistener registered with the host waterfall arguments reversed; corrected to the host contract(payload, next), with root/session read frompayload.agent.session. - Silent injection crashed with
Cannot read properties of undefined (reading 'kind'): injected memory messages were bare{role, content}objects; they are now built withcreateUserMessageand a pluginsource, same as the host's plan-mode narration. Both paths stay inert on error and never break the host request.
Changed
- Task panel: click vs. double-click discrimination (~250 ms) so double-click rename no longer fights expand/collapse layout shifts.
- Step/task-title editing now uses auto-growing textareas instead of single-line inputs.
Fixed
- 修复静默注入在两处会导致会话崩溃的问题:宿主事件签名写反、注入消息缺少
source字段
Changed
- 任务面板双击改名不再与单击展开打架,步骤和任务名编辑框随内容自动变高
v0.5.0
dsh-project-memory v0.5.0
v0.5.0 新增了记忆的自动流转与静默注入能力:Insight 实体支持 Task → Project → Global 三级自动提升;auto-inject 在对话中自动带入相关记忆,模型无需显式调用查询工具即可感知已有的教训、决策与流程;同时引入可选自动反思管线作为沉淀记忆的辅助通道。
Breaking Changes
- 数据模型重构:
lesson/decision/procedure/skill四类合并为单一Insight实体(kind: lesson|decision|procedure|experience+scope: task|project|global) - 存储路径变更:Project 级迁移至
.dsh-project-memory/insights.json,Global 级迁移至~/.config/dsh-project-memory/global.json - v0.4
experience.json幂等迁移至insights.json(kind: experience),旧文件保留兼容
New Features
静默上下文注入(auto-inject)
- 常驻块:Task 卡 + 非草稿 insights 摘要作为独立消息置于 system 后,内容未变不重发,复用 KV cache
- 相关注入:Procedure trigger 命中时追加完整步骤;BM25 命中 insights 时追加 Top-3
- 预算 ≤ 400 tokens,带
[Memory Inject]标记,会话内指纹去重 - 接入宿主
agent/pre-step缝,无 root 时自动透传,默认开启(autoContext.enabled: true)
单一 Insight 实体三级自动流转
- Task(私有草稿)→ Project(≥2 任务命中且 confidence ≥ 0.7)→ Global(≥3 任务命中)
- 提升为 scope 字段变更(移动不复制,无双写期)
- 归档软删(
archived: true),不进召回与注入,UI 可恢复
自动反思管线(默认关闭)
- 触发时机:任务切换 / 归档 / 空闲 30 分钟 / 会话结束
- 仅写入 Task 级草稿(
draft: true, source: 'reflect'),不直接进入 Project/Global - 摘要 digest 门控 + 30 分钟冷却,失败异步重试不阻塞
TaskPanel 三视图
- Task / Project / Global 三视图单按钮循环切换
- 统一
InsightEditor(按 kind 切换表单),支持增删改查、提升、降级、归档、恢复、新建 - Procedure 勾选“作为 Skill”后直接编辑 trigger(keywords / symbols / scope)
Global 预置 Procedures
proc_npm_publish_wsl:WSL 下发布 npm 到官方源proc_dsh_plugin_local:dsh 插件本地开发 / 发布切换
Improvements
- 去重指标统一:双向 token overlap ≥ 0.7 合并(复用 experience 层实现),BM25 仅用于排序
- 近重复强化带:0.65–0.7 仅累积
sourceTaskIds/hitCount,不合并内容 - 容量策略:Project 100 条(LRU + 置信度归档),Global Procedures 200 条(归档软删)
- 密文过滤:写盘前拦截密钥 / token / 私钥形态内容
- 语言跟随 dsh
ctx.locale服务,不再读取navigator.language
Bug Fixes
/insight list大 JSON 载荷不再渲染进对话(注册commandview仅渲染摘要)- 任务卡内联 insights 双语化
select_task返回insights字段供面板展示
Configuration
reflection:
enabled: false # 默认关
cooldownMs: 1800000
idleMs: 1800000
windowEvents: 40
autoContext:
enabled: true # 默认开
maxTokens: 400
insight:
dedupOverlap: 0.7
reinforceBand: 0.65
maxProject: 100
maxGlobalProcedures: 200
promoteConfidence: 0.7
globalPromoteTasks: 3
decayDays: 90Migration
- 首次加载自动将
experience.json复制导入insights.json(kind: experience, source: migrate),标记insights.json.migratedAt保证幂等 format.json版本号保持 v2,不破坏现有工具链- 旧
experience.json保留兼容remember/forget/query_memory等既有工具
Testing
- 211 项测试(core 166 + TaskBridge 11 + insight-store 11 + reflection 5 + auto-inject 9 + insight-actions 9)
- Client + Full harness 构建通过
Installation
# 从 npm 安装
dsh plugin --profile web add @yolk_vat-y/dsh-project-memory@0.5.0 -w
# 或从本地构建安装
cd dsh-project-memory && dsh plugin --profile web add . -wv0.4.4
核心改进:任务面板架构重构
新增
- 数据/UI 完全分离:新增
task-data-store.ts(服务端同步数据)与task-ui-store.ts(本地 UI 状态),彻底解耦 - 显式打开机制:面板仅在用户主动输入
/tasks、/task或模型调用show_task_panel时打开 - 跨标签页数据同步:
BroadcastChannel仅同步任务数据,UI 状态各标签页独立 - 模型工具支持:新增
show_task_panel工具,模型可主动唤起面板
修复
- 启动默认隐藏:
closed: true强制默认关闭,不读取 localStorage 残留状态 - 刷新页面不自动显示:UI 状态不持久化
closed,刷新即恢复隐藏 - 会话切换不自动打开:仅同步数据,面板关闭时不触发
/tasks命令 - 收起面板不再崩溃:修复
useTaskDraghook 在事件处理器中违规调用导致的 "任务面板(点击重试)" 错误 - 命令节点无副作用:
TaskCommandNode仅同步数据,列表型命令显式调用open()
重构
- 删除废弃
task-store.ts(232 行) - 拆分为 4 个职责单一模块:
task-data-store.ts— 服务端数据 + 跨标签同步 (~180 行)task-ui-store.ts— 本地 UI 状态 + localStorage (~120 行)task-hooks.ts—useTaskDrag/useTaskEdit复用逻辑 (~150 行)TaskComponents.tsx—MiniBar/TaskCard纯展示组件 (~330 行)
TaskPanel.tsx精简为容器组件 (~380 行),仅负责数据获取、命令桥接、事件监听
迁移指南
无破坏性变更。现有配置、任务数据、localStorage 均兼容。
v0.4.3
dsh-project-memory v0.4.3
包含 0.4.2 的全部功能,并修复了 0.4.2 的 CI 依赖解析问题。
0.4.2 新增功能
Task Panel 重构:真实 dsh web 契约 + 任务清单双向同步
- Client 落地:按 dsh web 0.1.2-rc.1 真实 client 插件契约重写(cordis inject + apply,注册进宿主
shell.overlay槽);此前使用的槽位/接口在 rc.1 不存在,现已全部对齐真实注册面 - 浮动任务面板:卡片可拖拽、展开看步骤/文件(点击复制路径);折叠为可拖拽顶部迷你条;可彻底隐藏(输入
/task//tasks唤起);渲染错误有边界兜底,不再因一次崩溃被宿主整条退休 - 命令节点不再刷屏:
/tasks、/task在会话内只留一行状态,面板读同一载荷
任务清单双向同步(宿主 ↔ 插件任务)
- 反向接管:
select_task或/task switch把任务设为会话绑定时,任务步骤推成宿主todo/write——dsh 渲染的任务清单跟随我们维护的任务;配置tasklist.syncHostOnAdopt(默认开)可关 - 空
todo/write语义定为「清空」:未绑定会话清空清单不再误建垃圾任务;已绑定则清空该任务 steps(任务保留) - 用户编辑走同一镜像:面板改步骤/状态 = 写回绑定任务并推宿主清单,与模型
todo_write共用一套逻辑,无第二套同步 /task新增子命令:switch/archive/unbind/rename/todos(均不经模型,由面板按钮/双击调用);unbind同时清掉输入框上方的宿主任务清单
面板编辑与风格
- 绑定卡片:双击标题/步骤行内编辑(输入框随内容自动增高),点步骤状态图标循环 待办→进行中→已完成;非绑定卡片只读
- 四种氛围风格(点标题左侧文件夹图标切换,本地记忆):原生 / 玻璃拟态 / 粗野主义 / 终端等宽——只改材质、几何、字型与密度,颜色始终取自 dsw 别名令牌,跟随宿主明暗与主题插件
测试
- TaskBridge 测试增至 11 项(新增反向接管、空写语义等);既有 166 项全绿
- 清理:移除废弃 client 包依赖与死代码,样式收敛到 dsw token
0.4.3 修复
- CI 依赖解析:锁定 devDependencies 版本,新增
package-lock.json,修复 npm 单树依赖冲突 - 移除项目级
.npmrc,统一使用默认 registry
注:任务文件仍存于工作区
.dsh-project-memory/,无需联网/向量服务,查询零 token。