@yolk_vat-y/dsh-project-memory 0.4.4 → 0.5.1

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 CHANGED
@@ -1,5 +1,51 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1 (unreleased)
4
+
5
+ ### Fixed
6
+
7
+ - **Silent injection could crash every agent step (`next is not a function`)** — the `agent/pre-step` listener registered with the host waterfall arguments reversed (it consumed the event payload as the continuation, then called it). Signature corrected to the host contract `(payload, next)`; project root and session id now come from `payload.agent.session` (`header.cwd` / `id`).
8
+ - **Silent injection crashed with `Cannot read properties of undefined (reading 'kind')`** — injected `[Memory Inject]` messages were bare `{ role, content }` objects, but the host reads `message.source.kind` while assembling requests. Injection now builds full host messages via `createUserMessage` with a plugin `source` (`form: notice`, the same pattern as the host's own plan-mode narration).
9
+ - Both paths stay inert on any error or missing session cwd: they return the host's default decision and never break the request.
10
+
11
+ ### Changed (task panel editing)
12
+
13
+ - **Click vs. double-click discrimination on card heads**: single-click expand/collapse waits ~250 ms to rule out a double-click, so double-click-to-rename no longer fights layout shifts (the first click no longer toggles before the second click lands, and a double-click no longer toggles twice).
14
+ - **Auto-growing inline editors**: step and task-title editing switched from single-line inputs to content-sized textareas (capped, then internal scroll); Enter commits, Shift+Enter inserts a newline, Esc cancels.
15
+ - Step content renders with `white-space: pre-wrap`, so committed multi-line text stays readable.
16
+
17
+ ### Files
18
+ - src/auto-inject.js, src/client/TaskComponents.tsx, src/client/TaskPanel.module.css, client/client.js (+ map), package.json
19
+
20
+ ## 0.5.0 (unreleased)
21
+
22
+ ### Added — v0.5 tiered insight memory (lessons / decisions / procedures)
23
+
24
+ - **Single insight entity across three scopes**: task (private drafts inside tasks.json) / project (.dsh-project-memory/insights.json) / global (~/.config/dsh-project-memory/global.json). One schema, one dedupe, one capacity policy.
25
+ - **New model tool save_lesson** — write at any scope (explicit scope > task_id > bound task > project). Bidirectional token-overlap dedupe: >= 0.7 merges, 0.65~0.7 reinforces (task-hit accumulation, no content write).
26
+ - **Promotion = scope change, not a copy**: the same insight hit by 2 tasks auto-promotes task → project, 3+ tasks project → global (sourceTaskIds accumulate; no double-write ever). Manual promote/demote available via panel.
27
+ - **Soft archive**: archived:true hides from recall/injection and stays restorable; capacity decay (decayDays, hitCount==0) and overflow prune only archived entries.
28
+ - **Secret filter on write**: token/private-key/password-shaped content is rejected before persisting.
29
+ - **Non-destructive migration**: v0.4 experience.json notes are imported into insights.json once (kind: experience, source: migrate, migratedAt marker); legacy experience file keeps serving remember/forget/query_memory until the recall-unification PR retires it.
30
+ - **Reflection pipeline (PR 1b)**: optional LLM reflection (reflection.enabled: false by default) that only writes task-level drafts (source: reflect) on task switch-away/archive with cooldown + content-digest gating and silent failure. reflectTaskAfter / isReflectDue / fireReflect + test.
31
+ - **Silent injection engine (PR 2)**: entry resident block + relevance-gated injection; project-profile tags (package.json/go.mod/Cargo.toml); scope-tags intersection filter for global procedures; content fingerprint dedupe (60 s window); fully inert (returns the default decision) on any error or missing session cwd. Wired via the host's official **agent/pre-step** seam (`ctx.on('agent/pre-step', …)`, appending a plugin-source `[Memory Inject]` UserMessage to each step's `enter` messages) — patching `llm.stream` cannot intercept the host's internal reference. `installAutoInject` in index, `autoContext.enabled: true` default.
32
+ - **TaskPanel memory views (PR 3)**: header button cycles Task / Project / Global; lists + actions confirm/promote/demote/archive/restore/delete/edit + create form (procedures carry an "as Skill" trigger); task cards now show their insights inline. New user command /insight (server side commands/insight-actions.js: list/save/edit/actions).
33
+ - **New config groups**: insight.* (dedupOverlap 0.7, reinforceBand 0.65, maxProject 100, maxGlobalProcedures 200, promoteConfidence 0.7, globalPromoteTasks 3, decayDays 90, globalFile), reflection.* (enabled false, cooldownMs 1800000, maxLessonsPerReflect 3, maxDecisionsPerReflect 2), autoContext.* (enabled true, maxTokens 400, relevanceMin 0.25). select_task cards now include insights.
34
+
35
+ ### Files
36
+ - src/similarity.js, src/insight-store.js, src/global-seed.js, src/types.js, src/tools/lesson-tools.js, src/reflection-pipeline.js, src/auto-inject.js, src/project-profile.js, src/commands/insight-actions.js, src/client/MemoryView.tsx
37
+ - Changed: src/store.js, src/index.js, src/tools/task-tools.js, src/commands/tasks.js, src/commands/task-actions.js, src/client/{TaskPanel,TaskComponents,task-data-store,locales}.ts(x), TaskPanel.module.css, package.json
38
+ - Tests: insight-store 11 / reflection-pipeline 5 / auto-inject 9 / insight-actions 7 (total 209, exit 0)
39
+
40
+ ### Notes
41
+ - Design rationale, deviations (non-destructive migration; reflection triggers subset; auto-inject host verification) and the live-verification checklist live in PLAN-v0.5.0.md §10–§12.
42
+ - Requires a dsh web restart to load the new server code and rebuilt client bundle.
43
+
44
+ ### Fixed
45
+ - **/insight flooding the conversation**: `/insight list` returns a large JSON payload; it is now registered into `conversation.chat.commandview` (with `/tasks`, `/task`) and renders as a one-line summary, so switching memory views no longer dumps megabytes of JSON into the chat. Task-card memory labels localized (`mem.section-label`).
46
+ - **Task panel "任务面板(点击重试)" crash (`Cannot read properties of undefined (reading 'filter')`)**: root cause was a latent BroadcastChannel bug — its handler used a functional updater but `setDataState` only accepted a plain object, so the first cross-tab sync replaced the store with a function and `data.tasks` became undefined. `setDataState` now accepts object or updater and always normalizes to the full shape; `TaskPanel` reads defensively (`Array.isArray(data.tasks)`).
47
+ - **Memory view infinite refresh loop flooding the conversation**: `refresh`'s `useCallback` included `loading` in its deps while the effect re-ran it, so every `loading` toggle recreated `refresh` → effect → `/insight list` → … (each command execution appends a chat node). Now guarded by refs (`inflightRef` + 800 ms `lastRunRef`) with `loading` kept out of the dependency array; a memory view fetch happens once per scope change/mount only.
48
+
3
49
  ## 0.4.4 (2026-09-06)
4
50
 
5
51
  ### Added
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # dsh-project-memory
2
2
 
3
+ > 如果这个插件帮你省下 1 小时 Debug 时间,请点个 Star。
4
+
3
5
  [English](README.md) | [简体中文](README.zh-CN.md)
4
6
 
5
7
  [![ci](https://github.com/00080000/dsh-project-memory/actions/workflows/ci.yml/badge.svg)](https://github.com/00080000/dsh-project-memory/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![npm](https://img.shields.io/npm/v/@yolk_vat-y/dsh-project-memory)](https://www.npmjs.com/package/@yolk_vat-y/dsh-project-memory) [![Listed on dsh-plugin.org](https://dsh-plugin.org/badges/listed.svg)](https://dsh-plugin.org/plugins/00080000/dsh-project-memory) [![Awesome](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
@@ -35,6 +37,7 @@ The workflow panel is collapsible, automatically adapts to dsh and theme plugin
35
37
  - **BM25 memory recall** — ranked search over documents, symbols, and experience notes, with optional LLM query expansion to handle vocabulary mismatch. **CJK-optimized**: precise phrase boost (3+ char phrases ×1.5 score on title/keywords match), synonym table (e.g. 数据库连接池 ↔ 连接池 ↔ DB pool), and CJK-aware word boundaries for doc↔symbol linking.
36
38
  - **blindSpots-aware recall** — document summaries carry a `blindSpots` field (what the summary explicitly does NOT cover). When a query hits a blind spot, `query_memory` appends a warning pointing the model to read the source file, preventing hallucination from partial summaries.
37
39
  - **Experience notes** — problems → solutions; similar problems supersede instead of duplicating, and notes are returned only when a search matches. The note store is bounded: capacity scales with project size (clamped to 100–2000), and the oldest notes are pruned when the limit is exceeded. **Supersede tightened to bidirectional 0.7 overlap** (was 0.6); **experience `problem` field now participates in CJK phrase boost** for long-tail query recall.
40
+ - **v0.5 tiered insight memory (lessons / decisions / procedures)** — one `insight` entity across three scopes: `task` (private drafts in `tasks.json`), `project` (`.dsh-project-memory/insights.json`), `global` (`~/.config/dsh-project-memory/global.json`). `save_lesson` writes any scope; dedupe is bidirectional token overlap ≥ 0.7 (merge) with a 0.65–0.7 reinforce band; **promotion is a scope change, not a copy** — 2 tasks hitting the same insight promote it to project, 3+ to global. Archive is soft (`archived`), decay/capacity prune archived entries only; writes are filtered for secret/token-shaped content. LLM **reflection is off by default** and only ever writes task-level drafts (`source: reflect`) on task switch-away/archive. Panel gains a Task / Project / Global memory view with approve, promote/demote, archive/restore, delete, edit and a create form (procedures can carry an “as Skill” trigger). Old `experience.json` notes are imported into `insights.json` once, non-destructively. Defaults & rationale: `PLAN-v0.5.0.md`.
38
41
  - **Streaming TF + IDF caching** — query path caches IDF (term inverse frequency) per store version; on cache hit, single-pass streaming scores 20k entries in ~8 ms (5k files) / ~1 ms (1k files) with zero intermediate objects; write path is O(1) version bump.
39
42
  - **Lock-free sync transactions** — all writes (index / watch / remember / forget / watch_repo) go through synchronous transactions `store.commit(fn)`; fn succeeds then atomic write; JS single-threaded event loop guarantees no interleaving; `remember`/`forget` never blocked by watch re-indexing.
40
43
  - **Minimal dependencies** — pure JavaScript; the only runtime dependency is `pdfjs-dist` (PDF text extraction), no native builds required.
@@ -120,8 +123,10 @@ The tools below are **invoked by the agent**, not typed by the user. In the chat
120
123
  | `show_task_panel` | Show the task panel in the UI. Call when the user asks to see the task list or when you want to display the panel. |
121
124
  | `/tasks` (typed by the user, not the model) | Shows the task stack: title, step progress, involved files, and which task the current session is bound to. |
122
125
  | `/task` (typed by the user, not the model) | Task panel subcommands: `switch` / `archive` / `unbind` / `rename` / `todos`. Invoked by panel buttons/clicks; does not go through the model. |
126
+ | `/insight` (typed by the user, not the model) | v0.5 memory view actions (panel buttons): `list [task|project|global]`, `confirm` / `promote` / `demote` / `archive` / `restore` / `delete` `<scope> <id>`, `save <scope> <json>`, `edit <scope> <id> <json>`. |
123
127
  | `remember problem solution` | Save an experience note. Similar problems supersede instead of duplicating. |
124
128
  | `forget id_or_query` | Delete stale experience notes. |
129
+ | `save_lesson` (agent tool) | Save a lesson/decision/procedure at task/project/global scope (single insight entity). Near-duplicates merge (≥ 0.7 overlap) or reinforce (0.65–0.7); 2+ tasks hitting the same insight auto-promote task → project, 3+ → global. Params: `title`, `kind`, `scope`, `pattern`/`fix` or `choice`/`reason` or `steps`/`trigger`, `task_id`, `files`, `symbols`, `confidence`, `root`. |
125
130
 
126
131
  ## Design
127
132
 
@@ -134,6 +139,7 @@ The tools below are **invoked by the agent**, not typed by the user. In the chat
134
139
  watch.json watched roots
135
140
  tasks.json TaskBridge task entities (cross-session)
136
141
  binding.json current session ↔ task binding
142
+ insights.json v0.5 project-scope insights (lessons/decisions/procedures); v0.4 experience notes imported once, non-destructively
137
143
  ```
138
144
 
139
145
  Stores created before v0.2.0 (single `entries.json` / `index.json`) migrate automatically and idempotently on first load. Within one dsh process, all tool calls share a single in-memory store per project, so hot-path indexing writes only the shard that changed.
@@ -229,7 +235,7 @@ These are deliberate scope choices.
229
235
 
230
236
  **Why:** Experience notes are low-stakes, high-volume, and retrieval-only. Aggressive deletion prevents stale noise from polluting search. For precision, delete by ID (shown in `query_memory` output).
231
237
 
232
- ### 11. TypeScript enhancement is optional, lazy, and cached
238
+ ### 10. TypeScript enhancement is optional, lazy, and cached
233
239
 
234
240
  **We do:** L2 TS Compiler API enhancement runs async in a priority queue (P0 on `fs/observed`, P1 on `watch`, P2 on `index_repo`), results cached by content hash in `type-cache/`. Zero config — just `npm i -D typescript@5` or `typescript@6`. Falls back to L1 regex if TS absent or disabled.
235
241
 
@@ -257,6 +263,9 @@ These are deliberate scope choices.
257
263
  | `watchInterval` | 15 | poll interval (seconds) |
258
264
  | `tsPath` | (auto) | optional absolute path to a specific `typescript` install; if omitted, resolves from project cwd → plugin node_modules |
259
265
  | `enableTypeScript` | true | set `false` to disable L2 TS enhancement entirely (L1 regex only) |
266
+ | `insight.*` | dedupOverlap `0.7` · reinforceBand `0.65` · maxProject `100` · maxGlobalProcedures `200` · promoteConfidence `0.7` · globalPromoteTasks `3` · decayDays `90` · `globalFile` (auto) | v0.5 insight dedupe / reinforce / promotion / capacity / archive settings |
267
+ | `reflection.enabled` | false | v0.5 LLM reflection, **draft-only at task level** (fires on task switch-away / archive). `cooldownMs` `1800000`, `maxLessonsPerReflect` `3`, `maxDecisionsPerReflect` `2` |
268
+ | `autoContext.enabled` | true | v0.5 silent injection wrapper (entry block + relevance). Inert (full passthrough) until the host exposes a resolvable session cwd; `maxTokens` `400` |
260
269
 
261
270
  ### Toggling features
262
271
 
@@ -292,7 +301,7 @@ These commands are for **maintaining the plugin code** — regular users do not
292
301
 
293
302
  ```bash
294
303
  npm install
295
- npm test # 177 tests (166 core + 11 TaskBridge)
304
+ npm test # 211 tests (166 core + 11 TaskBridge + 11 insight-store + 5 reflection + 9 auto-inject + 9 insight-actions)
296
305
  ```
297
306
 
298
307
  ## License
package/README.zh-CN.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # dsh-project-memory
2
2
 
3
+ > 如果这个插件帮你省下 1 小时 Debug 时间,请点个 Star。
4
+
3
5
  [English](README.md) | [简体中文](README.zh-CN.md)
4
6
 
5
7
  [![ci](https://github.com/00080000/dsh-project-memory/actions/workflows/ci.yml/badge.svg)](https://github.com/00080000/dsh-project-memory/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) [![npm](https://img.shields.io/npm/v/@yolk_vat-y/dsh-project-memory)](https://www.npmjs.com/package/@yolk_vat-y/dsh-project-memory) [![Listed on dsh-plugin.org](https://dsh-plugin.org/badges/listed.svg)](https://dsh-plugin.org/plugins/00080000/dsh-project-memory) [![Awesome](https://awesome-dsh-plugin.com/badge.svg)](https://awesome-dsh-plugin.com)
@@ -36,6 +38,7 @@
36
38
  - **BM25 记忆召回** — 对文档、符号与经验笔记进行排序召回,可选 LLM 查询扩展以应对表述不一致。**CJK 增强**:精确短语乘法加分(3+ 字短语在标题/关键词命中 ×1.5)、同义词表(如 数据库连接池 ↔ 连接池 ↔ DB pool)、CJK 感知的文档↔符号链接边界。
37
39
  - **blindSpots 感知召回** — 文档摘要携带 `blindSpots` 字段(明确说明摘要未覆盖的内容)。查询命中盲区时,`query_memory` 追加提示引导模型去读原文,防止半截摘要误导。
38
40
  - **经验笔记** — 记录问题 → 方案;相似问题覆盖而非重复;笔记仅在检索命中时返回。笔记数量有界:容量随项目规模伸缩(钳制在 100–2000),超限时淘汰最旧的笔记。**覆盖阈值收紧为双向 0.7 重叠**(原 0.6);**经验 `problem` 字段现参与 CJK 短语加分**,提升长尾问句召回。
41
+ - **v0.5 分层 insight 记忆(教训 / 决策 / 流程)** — 一个 `insight` 实体贯穿三级:`task`(任务私有草稿,存 `tasks.json`)、`project`(`.dsh-project-memory/insights.json`)、`global`(`~/.config/dsh-project-memory/global.json`)。`save_lesson` 三级可写;去重采用双向 token overlap ≥ 0.7(合并)外加 0.65–0.7 近重复强化带;**提升 = scope 字段变更而非复制**——同一 insight 被 2 个任务命中升 project、3+ 升 global。归档为软删(`archived`),容量/衰减只清归档区;写盘前过滤密钥/token 形态内容。LLM **反思默认关闭**,且只产任务级草稿(`source: reflect`,触发于任务切走/归档时)。面板新增 Task / Project / Global 记忆视图:审核、提升/降级、归档/恢复、删除、编辑与新建表单(procedure 可带"作为 Skill"触发关键词)。旧 `experience.json` 笔记**非破坏**导入 `insights.json` 一次。默认值与设计说明见 `PLAN-v0.5.0.md`。
39
42
  - **流式 TF + IDF 缓存** — 查询路径按存储版本缓存 IDF(词逆频率);命中时单次流式遍历 20k 条目仅需 ~8 ms(5k 文件) / ~1 ms(1k 文件),零中间对象;写入路径仅 O(1) 版本号递增。
40
43
  - **无锁同步事务** — 不采用锁:所有写入(index / watch / remember / forget / watch_repo)统一走同步事务 `store.commit(fn)`,fn 成功后才一次落盘;JS 单线程事件循环保证事务间不交错,`remember`/`forget` 不会被 watch 重索引阻塞排队。多实例并发写入同一项目存储时,得益于 CAS 幂等更新与原子提交,自然具备幂等性,无数据损坏风险。
41
44
  - **依赖极简** — 纯 JavaScript;唯一运行时依赖是 `pdfjs-dist`(PDF 文本提取),无需原生构建。
@@ -121,8 +124,10 @@ dsh plugin --profile web add /path/to/dsh-project-memory.tgz
121
124
  | `show_task_panel` | 在 UI 中打开任务面板。用户要求查看任务列表或你想展示面板时调用。 |
122
125
  | `/tasks`(用户输入,不经模型) | 展示任务栈:标题、步骤进度、涉及文件、当前会话绑定哪套任务。 |
123
126
  | `/task`(用户输入,不经模型) | 任务面板子命令:`switch` / `archive` / `unbind` / `rename` / `todos`(面板按钮/点击触发,不经模型)。 |
127
+ | `/insight`(用户输入,不经模型) | v0.5 记忆视图动作(面板按钮触发):`list [task|project|global]`、`confirm` / `promote` / `demote` / `archive` / `restore` / `delete` `<scope> <id>`、`save <scope> <json>`、`edit <scope> <id> <json>`。 |
124
128
  | `remember problem solution` | 保存经验笔记。相似问题覆盖而非重复。 |
125
129
  | `forget id_or_query` | 删除过期经验笔记。 |
130
+ | `save_lesson`(模型工具) | 在 task/project/global 任一作用域保存教训/决策/流程(单一 insight 实体)。近重复按双向 overlap ≥ 0.7 合并、0.65–0.7 强化;同一 insight 被 2+ 任务命中自动 task→project、3+ → global。参数:`title`、`kind`、`scope`、`pattern`/`fix` 或 `choice`/`reason` 或 `steps`/`trigger`、`task_id`、`files`、`symbols`、`confidence`、`root`。 |
126
131
 
127
132
  ## 设计
128
133
 
@@ -135,6 +140,7 @@ dsh plugin --profile web add /path/to/dsh-project-memory.tgz
135
140
  watch.json 被监听根目录
136
141
  tasks.json TaskBridge 任务实体(跨会话)
137
142
  binding.json 当前会话 ↔ 任务绑定
143
+ insights.json v0.5 项目级 insights(教训/决策/流程);v0.4 经验笔记非破坏导入一次
138
144
  ```
139
145
 
140
146
  v0.2.0 之前创建的库(单文件 `entries.json` / `index.json`)在首次加载时自动幂等迁移。同一个 dsh 进程内,所有工具调用共享每个项目的单一内存 store 实例,热路径索引只写发生变化的那一个分片。
@@ -228,7 +234,7 @@ TaskPanel (Container)
228
234
 
229
235
  **为什么:** 经验笔记低风险、高量、仅检索。激进删除防止陈旧噪音污染搜索。精确删用 ID(`query_memory` 输出里有)。
230
236
 
231
- ### 11. TS 增强可选、异步、缓存
237
+ ### 10. TS 增强可选、异步、缓存
232
238
 
233
239
  **我们做:** L2 TS Compiler API 在优先级队列异步跑(P0 `fs/observed`、P1 `watch`、P2 `index_repo`),结果按内容哈希缓存 `type-cache/`。零配置——`npm i -D typescript@5` 或 `npm i -D typescript@6` 即用。无 TS 或禁用时优雅回退 L1 正则。
234
240
 
@@ -256,6 +262,9 @@ TaskPanel (Container)
256
262
  | `watchInterval` | 15 | 轮询间隔(秒) |
257
263
  | `tsPath` | (自动) | 可选:强制指定特定 `typescript` 安装路径;省略时按项目 cwd → 插件 node_modules 向上解析 |
258
264
  | `enableTypeScript` | true | 设为 `false` 彻底禁用 L2 TS 增强(仅保留 L1 正则) |
265
+ | `insight.*` | dedupOverlap `0.7` · reinforceBand `0.65` · maxProject `100` · maxGlobalProcedures `200` · promoteConfidence `0.7` · globalPromoteTasks `3` · decayDays `90` · `globalFile`(自动) | v0.5 insight 去重/强化/提升/容量/归档设置 |
266
+ | `reflection.enabled` | false | v0.5 LLM 反思,**只写任务级草稿**(触发于任务切走/归档)。`cooldownMs` `1800000`、`maxLessonsPerReflect` `3`、`maxDecisionsPerReflect` `2` |
267
+ | `autoContext.enabled` | true | v0.5 静默注入包装(entry 常驻块 + relevance)。宿主无法解析会话 cwd 时完全透传(零副作用);`maxTokens` `400` |
259
268
 
260
269
  ### 功能开关
261
270
 
@@ -291,7 +300,7 @@ dsh web --patch ./config.yml
291
300
 
292
301
  ```bash
293
302
  npm install
294
- npm test # 177 项测试(核心 166 + TaskBridge 11)
303
+ npm test # 211 项测试(核心 166 + TaskBridge 11 + insight-store 11 + reflection 5 + auto-inject 9 + insight-actions 9)
295
304
  ```
296
305
 
297
306
  ## 许可证