dsh-continual-evolve 0.14.1 → 0.15.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/README.md CHANGED
@@ -7,25 +7,28 @@ English | [中文](README.zh.md)
7
7
  [![CI](https://github.com/ZK-Andy/dsh-continual-evolve/actions/workflows/ci.yml/badge.svg)](https://github.com/ZK-Andy/dsh-continual-evolve/actions/workflows/ci.yml)
8
8
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
9
  [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-339933)](package.json)
10
- [![Tests](https://img.shields.io/badge/tests-91%20passing-brightgreen)]()
10
+ [![Tests](https://img.shields.io/badge/tests-168%20passing-brightgreen)]()
11
11
  [![Coverage · statements](https://img.shields.io/badge/coverage_statements-96%25-brightgreen)]()
12
- [![Coverage · branches](https://img.shields.io/badge/coverage_branches-93%25-green)]()
12
+ [![Coverage · branches](https://img.shields.io/badge/coverage_branches-90%25-green)]()
13
13
  [![Coverage · functions](https://img.shields.io/badge/coverage_functions-100%25-brightgreen)]()
14
14
 
15
- A workspace-memory plugin for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`): one plain-markdown memory store per workspace (`<workspace>/.evolve/memory/`), the index injected at session start, used by the model with its **native file tools** — and nothing else.
15
+ A workspace-memory plugin for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`): every memory lives in one central SQLite database (`~/.dsh/evolve/memory.db`, rows partitioned by workspace), the index is injected at session start, and the plugin's code is the literal **sole writer** — the model proposes, code gates and lands.
16
16
 
17
17
  ## Why
18
18
 
19
- Reusable experience gathered in one session (user preferences, pitfalls, project context) is forgotten by the next. ZCode solves this with a folder: one fact per markdown file plus a `MEMORY.md` index, injected at session start, read and written natively by the model, with no dedicated machinery. This plugin brings that exact shape to DSH.
19
+ Reusable experience gathered in one session (user preferences, pitfalls, project context) is forgotten by the next. A folder of markdown files makes memory visible but leaves every write ungoverned: index drift, frontmatter rot, oversized files, and secrets are only visible *after* a bad write lands. This plugin keeps ZCode's memory shape (per-workspace partitioning, injected index, typed memories) but moves the store into one database whose every mutation passes mechanical gates.
20
20
 
21
21
  ## How it works
22
22
 
23
- 1. **Session-start injection** — the plugin registers a single system-prompt section: the `MEMORY.md` index content (whole-line truncated over budget, with a read-the-directory hint), the absolute store path, and the when_to_save guide. The section is computed once per session and reused byte-for-byte, keeping the system prompt stable and the prompt cache warm; an empty store costs zero tokens.
24
- 2. **Native read/write** — DSH fully permits file access inside the workspace (reads are never fenced; the write fence only covers paths outside the workspace, see [`docs/FAQ.md`](docs/FAQ.md) #6). The model reads, writes, and edits memory files and maintains the index directly; the store is bootstrapped on first use.
25
- 3. **Governance is the file** — no versions, no snapshots, no approvals, no background extraction: a bad memory is a visible file in the workspace, and deleting it is the retirement path. Memories are personal context — on bootstrap in a git workspace the store appends `.evolve/` to the workspace `.gitignore` (non-git workspaces are left untouched).
26
- 4. **Read-only card** — the plugin mounts a read-only memory card on its own page in the official plugin manager (the `plugins.bundle.config` slot; hosts without it silently degrade to no card), shaped like the market's own settings card (collapsed by default, header toggle with a rotating chevron, hover/open frame states) and aligned with ZCode's Settings → Memory viewer: one workspace at a time behind a dropdown scope selector fed by the host workspace registry, a file search box, per-file relative updated times, click-to-preview file bodies (5 MiB cap), plus index-drift warnings (unindexed files, index rows whose file is gone). The plugin's display name and description localize through the host's package `locale/*.json` metadata channel. The card follows the market's look — host theme tokens, the `Button` primitive for refresh, and zh/en copy that tracks the DSH language (plain themed elements on old hosts). The card is a request-time projection of the files on disk — the single source of truth remains `.evolve/memory/`; the card has no edit path, edit the files directly.
23
+ 1. **Session-start injection** — the plugin registers a single system-prompt section: the workspace's memory index as a store query (hooks only, whole-line truncated over budget, ordered feedback > user > reference), the central-library path, and a three-line guide. The section is computed once per session and reused byte-for-byte, keeping the system prompt stable and the prompt cache warm; an empty store costs zero tokens.
24
+ 2. **Two tools, one writer** — `memory_write` (create/update/delete) is the explicit path for "remember …" / "forget …": every proposal passes the code gates (id shape, type enum, the feedback Why/How contract, secret screening carried over from v1, 64KB body cap) inside one transaction. `memory_read` fetches bodies and searches by keyword — the injected index carries hooks only. On hosts without the tools service the plugin degrades to "tell the user" phrasing and stays functional.
25
+ 3. **Proposal-based extraction** — the only background automation, audited in the `extraction_log`: every `agent/turn-stopping` rearms an idle debounce (default 10 min, `memoryIndex.debounceMin`, single-flight with burst coalescing; `compaction/start` and session close flush). A run reads the session increment since its cursor, feeds FTS-similar existing memories to one LLM call, and the model's structured proposal lands through the same gates; failures and rejections never advance the cursor. Internal agents, empty increments, turns without real user prose, and turns that already carried an explicit `memory_write` are mechanically skipped — and every skip is ledgered.
26
+ 4. **Rollback is a ledger, not a mechanism** — every mutation lands an `extraction_log` row with full before/after snapshots; undo means rewriting the `before` values. A hygiene pass rides on every applied run: orphan FTS rows are dropped and secret-bearing rows are quarantined (hidden, never deleted). The read-only card surfaces quarantine anomalies.
27
+ 5. **Read-only card** — mounted on the plugin's page in the official plugin manager (the `plugins.bundle.config` slot; hosts without it silently degrade to no card), shaped like the market's own settings card and aligned with ZCode's Settings → Memory viewer: a dropdown scope selector over the store's workspace partitions, a search box, per-entry relative updated times, click-to-preview bodies (5 MiB cap), and patrol warnings. Localized through the host's `locale/*.json` metadata channel; host theme tokens, the `Button` primitive, and zh/en copy that tracks the DSH language. The card is a request-time projection of the database and has no edit path.
27
28
 
28
- Memory file format (same as ZCode): frontmatter with `name` / `description` (the hook that decides whether a future session recalls it) / `metadata.type` (`user | feedback | project | reference`); `feedback` bodies must carry **Why:** and **How to apply:** lines.
29
+ Memory types follow the ZCode taxonomy: `user` (profile and environment facts), `feedback` (corrected or confirmed practices — bodies must carry **Why:** and **How to apply:** lines), `reference` (resource pointers). The extraction boundary is person- and environment-scoped knowledge only: decisions and trade-offs are repo-scoped by nature and belong to the repo's ADR route, never to memory.
30
+
31
+ Legacy markdown stores (`<workspace>/.evolve/memory/*.md`) are imported losslessly on first contact and the directory is renamed aside as `memory-imported-<date>/` — never deleted.
29
32
 
30
33
  ## Install
31
34
 
@@ -41,16 +44,18 @@ After installing or updating, restart the DSH profile you actually use (`dsh web
41
44
 
42
45
  ## Usage
43
46
 
44
- No commands, no tools. On the first session after restart, `.evolve/memory/` is created and the index is injected automatically. Just tell the model "remember …" / "forget …" — the memory files plus their index lines are the entire persistent state. Memories written mid-session become visible in the next session (the section is frozen to protect the prompt cache); for an immediate look the model simply reads the directory. To see the whole store, open the plugin's page in the official plugin manager: the read-only card shows each workspace's entries and index drift.
47
+ No commands. On the first session after restart the index is injected automatically. Just tell the model "remember …" / "forget …" — it lands through `memory_write` and the gates. Memories written mid-session become visible in the next session (the section is frozen to protect the prompt cache). To see the whole store, open the plugin's page in the official plugin manager: the read-only card shows each workspace's entries, search, and patrol anomalies. The store requires Node ≥ 22.5 (`node:sqlite`, part of the desktop host's EnsureNode runtime); without it the plugin degrades to a no-op with a console warning.
45
48
 
46
49
  ## Configuration
47
50
 
48
51
  | Key | Default | Meaning |
49
52
  |---|---|---|
50
53
  | `memoryIndex.enabled` | `true` | Register the memory section |
51
- | `memoryIndex.guide` | `true` | Inject the when_to_save guide (zero tokens when off and the index is empty) |
54
+ | `memoryIndex.guide` | `true` | Inject the guide (zero tokens when off and the index is empty) |
52
55
  | `memoryIndex.order` | `400` | Section order (upstream named slots start at `PLAN_POLICY=500`) |
53
56
  | `memoryIndex.maxChars` | `6000` | Hard character budget for the injected index |
57
+ | `memoryIndex.extraction` | `true` | The proposal-based extraction run |
58
+ | `memoryIndex.debounceMin` | `10` | Idle debounce minutes after a turn (0 = run every turn) |
54
59
  | `memoryCard.enabled` | `true` | Read-only memory card in the official plugin manager (degrades to no card when the host lacks `webServer`/`plugins.bundle.config`) |
55
60
 
56
61
  Profile patch example:
@@ -60,13 +65,14 @@ Profile patch example:
60
65
  config:
61
66
  memoryIndex:
62
67
  maxChars: 8000
68
+ debounceMin: 5
63
69
  ```
64
70
 
65
71
  ## Development
66
72
 
67
73
  ```bash
68
74
  pnpm install && pnpm build # deps + tsc -> lib/
69
- pnpm test # vitest (91 tests)
75
+ pnpm test # vitest (168 tests)
70
76
  pnpm test:coverage # v8 coverage, CI-enforced thresholds
71
77
  pnpm lint # oxlint src test client
72
78
  ```
@@ -75,17 +81,23 @@ Layout:
75
81
 
76
82
  ```
77
83
  ├── src/
78
- │ ├── index.ts # registration: the one section + config + card route wiring
79
- │ ├── memory-section.ts # injection: read index / bootstrap / truncate / session freeze
80
- │ ├── memory-guide.ts # guide: when_to_save and upkeep (adapted from ZCode)
81
- │ ├── memory-snapshot.ts # card: read-only store projection (entries / drift / error degrade)
82
- │ ├── workspace-catalog.ts# card: workspace list from the host registry (the API read fence)
83
- │ ├── known-workspaces.ts# card: in-process LRU fallback source for the catalogue
84
- │ └── card-routes.ts # card: GET-only read API on the host webServer
84
+ │ ├── index.ts # registration: section + tools + extraction + card wiring
85
+ │ ├── store.ts # central SQLite store: DDL/WAL/FTS, reads, ledger, patrol, cursors
86
+ │ ├── store-apply.ts # the sole write gate: validate all, apply atomically, ledger
87
+ │ ├── memory-rules.ts # mechanical gates: enums, sizes, id shape, secret screening
88
+ │ ├── memory-section.ts # injection: store query / truncate / session freeze
89
+ │ ├── memory-guide.ts # the main-session guide (three lines)
90
+ │ ├── memory-tools.ts # memory_write + memory_read (host-shaped definitions)
91
+ │ ├── extraction.ts # runner + scheduler (debounce, single-flight, flush)
92
+ │ ├── extraction-surface.ts # trajectory slicing: cursor, eligibility, serialization
93
+ │ ├── extraction-prompt.ts # the extraction prompt + answer parsing
94
+ │ ├── import-md.ts # lossless legacy markdown migration
95
+ │ ├── memory-snapshot.ts # card: read-only store projection (entries / patrol / degrade)
96
+ │ └── card-routes.ts # card: GET-only read API on the host webServer
85
97
  ├── client/
86
98
  │ └── client.js # hand-written client bundle: read-only card in the plugin manager
87
99
  ├── locale/ # host package metadata: localized display name + description (zh/en)
88
- ├── test/ # vitest suite (8 files)
100
+ ├── test/ # vitest suite (15 files)
89
101
  ├── lib/ # build output (tsc)
90
102
  ├── docs/ # design.md (design) · FAQ.md (real-world pitfalls)
91
103
  └── .agents/ # AI collaboration layer (AGENTS.md, skills, ADR notes)
@@ -93,7 +105,7 @@ Layout:
93
105
 
94
106
  ## Docs
95
107
 
96
- - Design: [`docs/design.md`](docs/design.md) · Pitfalls: [`docs/FAQ.md`](docs/FAQ.md) · Teardown decision: [`.agents/notes/implemented/architecture/2026-10-04-zcode-alignment-teardown.md`](.agents/notes/implemented/architecture/2026-10-04-zcode-alignment-teardown.md)
108
+ - Design: [`docs/design.md`](docs/design.md) · Pitfalls: [`docs/FAQ.md`](docs/FAQ.md) · Store decision: [`.agents/notes/implemented/architecture/2026-10-06-sqlite-single-store.md`](.agents/notes/implemented/architecture/2026-10-06-sqlite-single-store.md)
97
109
 
98
110
  ## License
99
111
 
package/README.zh.md CHANGED
@@ -7,25 +7,28 @@
7
7
  [![CI](https://github.com/ZK-Andy/dsh-continual-evolve/actions/workflows/ci.yml/badge.svg)](https://github.com/ZK-Andy/dsh-continual-evolve/actions/workflows/ci.yml)
8
8
  [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
9
9
  [![Node](https://img.shields.io/badge/node-%5E22.19%20%7C%7C%20%3E%3D24-339933)](package.json)
10
- [![Tests](https://img.shields.io/badge/tests-91%20passing-brightgreen)]()
10
+ [![Tests](https://img.shields.io/badge/tests-168%20passing-brightgreen)]()
11
11
  [![Coverage · statements](https://img.shields.io/badge/coverage_statements-96%25-brightgreen)]()
12
- [![Coverage · branches](https://img.shields.io/badge/coverage_branches-93%25-green)]()
12
+ [![Coverage · branches](https://img.shields.io/badge/coverage_branches-90%25-green)]()
13
13
  [![Coverage · functions](https://img.shields.io/badge/coverage_functions-100%25-brightgreen)]()
14
14
 
15
- [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh`)的工作区记忆插件:每个工作区一个纯 markdown 记忆库(`<workspace>/.evolve/memory/`),会话开局注入索引,模型用**原生文件读写工具**直接使用——仅此而已。
15
+ [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(`dsh`)的工作区记忆插件:全部记忆住在一个中央 SQLite 库里(`~/.dsh/evolve/memory.db`,按工作区路径行分区),会话开局注入索引,插件的代码是字面意义的**唯一写者**——模型提议,代码门禁后落盘。
16
16
 
17
17
  ## 为什么
18
18
 
19
- Agent 每个会话积累的可复用经验(用户偏好、踩坑教训、项目背景)下个会话就忘。ZCode 用一个文件夹解决了这件事:一事一文的 md 记忆 + `MEMORY.md` 索引、开局注入、模型原生读写、没有任何专用机器。本插件把同一形态带给 DSH。
19
+ Agent 每个会话积累的可复用经验(用户偏好、踩坑教训、项目背景)下个会话就忘。文件夹式的 md 记忆让记忆可见,但每一条写入都不设防:索引漂移、frontmatter 腐坏、超尺寸膨胀、密钥泄漏——坏写入落地之后才可见。本插件保留 ZCode 记忆形态(按工作区分区、开局注入索引、类型化记忆),把存储搬进一个所有变更都过机械门禁的数据库。
20
20
 
21
21
  ## 工作原理
22
22
 
23
- 1. **开局注入** —— 插件只注册一个 system-prompt section:注入 `MEMORY.md` 索引正文(超预算按整行截断并提示读目录)、记忆目录绝对路径、when_to_save 指南。该 section 每会话只算一次并逐字节复用,system prompt 稳定、prompt cache 持续命中;空 store 零 token。
24
- 2. **原生读写** —— DSH 对工作区内文件读写全放行(读路径从不设防,写围栏只围工作区外,见 [`docs/FAQ.md`](docs/FAQ.md) #6)。模型直接 Read/Write/Edit 记忆文件并维护索引;store 不存在时自动 bootstrap。
25
- 3. **治理即文件** —— 无版本、无快照、无审批、无后台提取:一条坏记忆就是工作区里一个可见的文件,删掉它就是退役。记忆是个人上下文——bootstrap 时若工作区是 git 仓库会自动把 `.evolve/` 追加进 `.gitignore`(非 git 工作区不碰任何文件)。
26
- 4. **只读卡片** —— 插件在官方插件管理的本 bundle 页面挂一张只读记忆卡片(`plugins.bundle.config` slot,老宿主自动降级为无卡片):形态对齐市场自家设置卡(默认收起、头部整行可点 + 旋转 chevron、hover/展开框态),内容对齐 ZCode 设置的记忆选项卡——工作区一次选一个(下拉作用域选择器,目录取宿主工作区注册表)、文件搜索框、每个文件的相对更新时间、点击行内展开文件内容预览(5 MiB 上限),外加索引漂移警告(未索引文件与索引失联文件)。插件的显示名与描述走宿主包元数据 `locale/*.json` 通道双语切换。卡片与市场同款——宿主主题 token、`Button` 原语刷新按钮、中英文案跟随 DSH 语言(老宿主降级为同主题裸元素)。卡片是磁盘文件的请求时投影——单一事实源永远是 `.evolve/memory/` 里的文件,卡片没有编辑路径,编辑请直接改文件。
23
+ 1. **开局注入** —— 插件只注册一个 system-prompt section:注入本工作区的记忆索引(查库结果,只含钩子,超预算按整行截断,feedback > user > reference 排序)、中央库路径、三行指南。该 section 每会话只算一次并逐字节复用,system prompt 稳定、prompt cache 持续命中;空 store 零 token。
24
+ 2. **两个工具,一个写者** —— `memory_write`(create/update/delete)承接显式的"记住……"/"忘掉……":每条提案过代码门禁(id 规范、type 枚举、feedback 的 Why/How 契约、v1 移植的 secret 筛查、64KB 正文上限)后在一个事务内落盘。`memory_read` 按 id 取正文、按关键词检索——注入索引只有钩子。宿主没有工具服务时降级为"告诉用户"措辞,注入不受影响。
25
+ 3. **提案制提取** —— 插件唯一的后台自动化,全程 `extraction_log` 可对账:每个 `agent/turn-stopping` 重置空闲去抖计时器(默认 10 分钟,`memoryIndex.debounceMin`,单飞行合并突发;`compaction/start` 与会话收尾强制 flush)。一次运行读取该会话游标之后的轨迹增量,用 FTS 取相似既有记忆喂给一次 LLM 调用,模型的结构化提案过同一套门禁落盘;失败与被拒不推游标,下次触发重试。内部 agent、空增量、无真实用户文本的轮次、当轮已有显式 `memory_write` 的轮次机械跳过——每次跳过都记账。
26
+ 4. **回滚靠账本,不靠机制** —— 每次变更落一条带 before/after 全文快照的 `extraction_log` 行;undo 就是取 before 重写。每次应用后随跑一次巡检:孤儿 FTS 行清除、含密钥条目隔离(隐藏,不物理删除)。只读卡片显形巡检异常。
27
+ 5. **只读卡片** —— 挂在官方插件管理的本 bundle 页面(`plugins.bundle.config` slot,老宿主自动降级为无卡片):形态对齐市场自家设置卡,内容对齐 ZCode 设置的记忆选项卡——下拉作用域选择器列出库里的工作区分区、搜索框、每条记忆的相对更新时间、点击行内展开正文预览(5 MiB 上限)、巡检异常警告。显示名与描述走宿主 `locale/*.json` 通道双语;宿主主题 token、`Button` 原语、中英文案跟随 DSH 语言。卡片是数据库的请求时投影,没有编辑路径。
27
28
 
28
- 记忆文件格式(与 ZCode 一致):frontmatter 带 `name` / `description`(决定未来会话会不会想起它)/ `metadata.type`(`user | feedback | project | reference`);`feedback` 正文必带 **Why:** 与 **How to apply:**。
29
+ 记忆类型沿 ZCode 分类法:`user`(画像与环境事实)、`feedback`(被纠正/确认的做法——正文必带 **Why:** 与 **How to apply:**)、`reference`(资源指针)。提取边界只收"跟人与环境走的知识":决策与取舍天然属于仓库,走仓库的 ADR 路线,不进记忆库。
30
+
31
+ 旧版 markdown 记忆库(`<workspace>/.evolve/memory/*.md`)在首次接触时无损导入,原目录改名为 `memory-imported-<date>/` 保留——不删不丢。
29
32
 
30
33
  ## 安装
31
34
 
@@ -41,16 +44,18 @@ dsh plugin add ZK-Andy/dsh-continual-evolve
41
44
 
42
45
  ## 使用
43
46
 
44
- 无需命令、无需工具。重启后第一场会话,`.evolve/memory/` 会自动生成,索引自动注入开场;对模型直接说"记住……"/"忘掉……"即可,写入的记忆文件 + 索引行就是全部持久状态。会话中途写入的记忆下个会话生效(会话内冻结守 prompt cache);需要立即查看时,模型直接读目录。想看记忆库全貌,打开官方插件管理里本插件的页面:只读卡片展示各工作区的记忆条目与索引漂移。
47
+ 无需命令。重启后第一场会话索引自动注入开场;对模型直接说"记住……"/"忘掉……",经 `memory_write` 过门禁落盘。会话中途写入的记忆下个会话生效(会话内冻结守 prompt cache)。想看记忆库全貌,打开官方插件管理里本插件的页面:只读卡片展示各工作区的记忆条目、搜索与巡检异常。中央库需要 Node ≥ 22.5(`node:sqlite`,桌面宿主的 EnsureNode 运行时自带);运行时过旧时插件整体降级为无操作并打控制台告警。
45
48
 
46
49
  ## 配置
47
50
 
48
51
  | 键 | 默认 | 含义 |
49
52
  |---|---|---|
50
53
  | `memoryIndex.enabled` | `true` | 是否注册记忆 section |
51
- | `memoryIndex.guide` | `true` | 是否注入 when_to_save 指南(关闭且索引为空时该 section 零 token) |
54
+ | `memoryIndex.guide` | `true` | 是否注入指南(关闭且索引为空时该 section 零 token) |
52
55
  | `memoryIndex.order` | `400` | section 顺序(上游命名槽位自 `PLAN_POLICY=500` 起) |
53
56
  | `memoryIndex.maxChars` | `6000` | 注入索引的硬字符预算 |
57
+ | `memoryIndex.extraction` | `true` | 提案制提取运行 |
58
+ | `memoryIndex.debounceMin` | `10` | 轮末空闲去抖分钟数(0 = 每轮即跑) |
54
59
  | `memoryCard.enabled` | `true` | 官方插件管理内的只读记忆卡片(宿主缺 `webServer`/`plugins.bundle.config` 时自动降级为无卡片) |
55
60
 
56
61
  profile patch 示例:
@@ -60,13 +65,14 @@ profile patch 示例:
60
65
  config:
61
66
  memoryIndex:
62
67
  maxChars: 8000
68
+ debounceMin: 5
63
69
  ```
64
70
 
65
71
  ## 开发
66
72
 
67
73
  ```bash
68
74
  pnpm install && pnpm build # 依赖 + tsc -> lib/
69
- pnpm test # vitest(91 例)
75
+ pnpm test # vitest(168 例)
70
76
  pnpm test:coverage # v8 覆盖率,CI 强制阈值
71
77
  pnpm lint # oxlint src test client
72
78
  ```
@@ -75,17 +81,23 @@ pnpm lint # oxlint src test client
75
81
 
76
82
  ```
77
83
  ├── src/
78
- │ ├── index.ts # 注册:唯一 section + 配置 + 卡片路由接线
79
- │ ├── memory-section.ts # 注入:读索引 / bootstrap / 截断 / 会话冻结
80
- │ ├── memory-guide.ts # 指南:when_to_save 与维护纪律(改编自 ZCode)
81
- │ ├── memory-snapshot.ts # 卡片:记忆库只读投影(条目 / 漂移 / 错误降级)
82
- │ ├── workspace-catalog.ts# 卡片:工作区目录(宿主注册表;API 读围栏)
83
- │ ├── known-workspaces.ts# 卡片:目录的进程内 LRU 回退源
84
- │ └── card-routes.ts # 卡片:webServer 上的 GET-only 只读 API
84
+ │ ├── index.ts # 注册:section + 工具 + 提取 + 卡片接线
85
+ │ ├── store.ts # 中央 SQLite 库:DDL/WAL/FTS、读面、账本、巡检、游标
86
+ │ ├── store-apply.ts # 唯一写门:全量校验、事务原子应用、账本
87
+ │ ├── memory-rules.ts # 机械门禁:枚举、尺寸、id 规范、secret 筛查
88
+ │ ├── memory-section.ts # 注入:查库 / 截断 / 会话冻结
89
+ │ ├── memory-guide.ts # 主会话指南(三行)
90
+ │ ├── memory-tools.ts # memory_write + memory_read(宿主形状定义)
91
+ │ ├── extraction.ts # 运行器 + 调度器(去抖、单飞行、flush)
92
+ │ ├── extraction-surface.ts # 轨迹切片:游标、资格判定、序列化
93
+ │ ├── extraction-prompt.ts # 提取 prompt + 应答解析
94
+ │ ├── import-md.ts # 旧版 markdown 无损迁移
95
+ │ ├── memory-snapshot.ts # 卡片:记忆库只读投影(条目 / 巡检 / 错误降级)
96
+ │ └── card-routes.ts # 卡片:webServer 上的 GET-only 只读 API
85
97
  ├── client/
86
98
  │ └── client.js # 手写 client bundle:官方插件管理内只读卡片
87
99
  ├── locale/ # 宿主包元数据:显示名 + 描述双语(zh/en)
88
- ├── test/ # vitest 测试(8 个文件)
100
+ ├── test/ # vitest 测试(15 个文件)
89
101
  ├── lib/ # 构建产物(tsc)
90
102
  ├── docs/ # design.md(设计)· FAQ.md(踩坑)
91
103
  └── .agents/ # AI 协作层(AGENTS.md、技能、ADR 笔记)
@@ -93,7 +105,7 @@ pnpm lint # oxlint src test client
93
105
 
94
106
  ## 文档
95
107
 
96
- - 设计:[`docs/design.md`](docs/design.md) · 踩坑:[`docs/FAQ.md`](docs/FAQ.md) · 拆解决策:[`.agents/notes/implemented/architecture/2026-10-04-zcode-alignment-teardown.md`](.agents/notes/implemented/architecture/2026-10-04-zcode-alignment-teardown.md)
108
+ - 设计:[`docs/design.md`](docs/design.md) · 踩坑:[`docs/FAQ.md`](docs/FAQ.md) · 存储决策:[`.agents/notes/implemented/architecture/2026-10-06-sqlite-single-store.md`](.agents/notes/implemented/architecture/2026-10-06-sqlite-single-store.md)
97
109
 
98
110
  ## License
99
111