dsh-plugin-prompt-tool 3.0.0 → 3.0.2

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.
Files changed (33) hide show
  1. package/engine/actions/catalog.mjs +2 -1
  2. package/engine/actions/shared.mjs +26 -12
  3. package/engine/actions/tool-visibility.mjs +27 -13
  4. package/engine/fillers.mjs +26 -2
  5. package/lib/client.js +4 -4
  6. package/lib/client.js.map +1 -1
  7. package/lib/index.mjs +96 -49
  8. package/modules/ponytail/module.yml +1 -1
  9. package/modules/soul/assets/layers.md +1 -1
  10. package/modules/soul/assets/manifest.yml +1 -1
  11. package/modules/soul/assets/reference/00-layers.md +27 -27
  12. package/modules/soul/assets/reference/01-criteria.md +32 -32
  13. package/modules/soul/assets/reference/02-echo.md +161 -158
  14. package/modules/soul/assets/reference/03-vital.md +183 -183
  15. package/modules/soul/assets/reference/04-manifest.json +106 -106
  16. package/modules/soul/assets/reference/05-doctor.md +67 -67
  17. package/modules/soul/assets/reference/06-reference.md +189 -189
  18. package/modules/soul/assets/reference/07-bundle.json +431 -431
  19. package/modules/soul/assets/reference/08-/350/270/251/345/235/221/345/256/236/345/275/225.md +59 -59
  20. package/modules/soul/assets/reference/09-dev-workflow.md +109 -109
  21. package/modules/soul/assets/reference/10-echo-anatomy.md +109 -100
  22. package/modules/soul/assets/reference/11-self.md +80 -80
  23. package/modules/soul/assets/reference/12-ledger.md +159 -159
  24. package/modules/soul/assets/reference/ECHO-/346/235/203/345/250/201/345/217/243/345/276/204.md +202 -0
  25. package/modules/soul/assets/reference/ECHO/345/205/255/345/261/202/344/270/216mnemon/345/215/217/345/220/214/350/257/264/346/230/216/344/271/246.md +229 -0
  26. package/modules/soul/assets/reference/README.md +4 -2
  27. package/modules/soul/assets/templates/agents-template.md +1 -1
  28. package/modules/soul/module.yml +2 -2
  29. package/modules/superpowers/module.yml +1 -1
  30. package/modules/tool-surface/module.yml +7 -4
  31. package/package.json +1 -1
  32. package/skills/dsh-module/reference.md +3 -3
  33. package/templates/80-tool-surface.yml +7 -6
@@ -1,431 +1,431 @@
1
- {
2
- "version": "0.1.0",
3
- "what": "参考实现清单 —— 我们已经做出来的一套。这一份和 04-manifest.json 性质不同:04 说「这一类该满足什么」(不绑任何实现),本文件说「我们具体用了什么」(可替换)。",
4
- "读了它你该知道": [
5
- "你可以全部采用、部分采用、或者一个都不用 —— 它只是参考实现,不是必要条件",
6
- "每一件都标了它填哪一层、管哪种稀缺资源、缺了会怎样",
7
- "装之前先读 skeleton/00-authority.md —— 不先定权威源,装什么都双重记账"
8
- ],
9
- "repo": {
10
- "url": "https://github.com/cyanwell/dsh-agent-organs",
11
- "kind": "monorepo",
12
- "note": "一个仓库里放了多个独立的 DSH 插件,每个子目录是一个完整的包(各自有 package.json / cordis.patch.yml / index.js / client.js)。"
13
- },
14
- "install": {
15
- "先读这一条": "★ 桌面端(profile = desktop)**不能用 CLI 安装**。实测报错原文:`error: profile \"desktop\" is managed exclusively by the Electron application`。桌面端只能手动两步,见 methods.desktop。web / 其它 profile 可以用 CLI,见 methods.cli。",
16
- "methods": {
17
- "desktop": {
18
- "适用": "桌面端(Electron 应用管理 profile)",
19
- "步骤": [
20
- "① 把插件目录复制进 <profile>/node_modules/<包名>/(四个文件一个不能少:package.json / cordis.patch.yml / index.js / client.js)",
21
- "② 在 <profile>/package.json 的 dsh.profile.bundles 数组里加上这个包名",
22
- "③ 重启 DSH"
23
- ],
24
- "警告": [
25
- "★ 第 ② 步必须用 JSON.parse / JSON.stringify 改,不要用容忍 BOM 的解析器 —— 那会给假通过",
26
- "★ 写完读回来验一次,并确认别的包一个没少",
27
- "★ 判据是「路由通了 / 设置页那一项出现了」,不是「文件复制过去了」"
28
- ]
29
- },
30
- "cli": {
31
- "适用": "web / 其它由 CLI 管理的 profile",
32
- "命令": [
33
- "dsh plugin --profile <名字> add file:<本地路径>",
34
- "dsh plugin --profile <名字> add github:<owner>/<repo>"
35
- ],
36
- "前置": [
37
- "pnpm 与 corepack 都必须在 PATH 上(corepack 由 node 自带,在 node 安装目录下)",
38
- "先 where corepack 确认能找到,否则一定失败"
39
- ],
40
- "警告": [
41
- "★ 装完必须重启 DSH(客户端入口图是启动时一次性组合的)",
42
- "★ pnpm 会顺带对账,可能剪掉不在 lockfile 里的包 —— 装完逐一核对关键插件还在不在",
43
- "★ 安装那一刻建立的硬链接不可依赖:用原子写入的编辑器改完源文件,链接会断。改完要么复制覆盖,要么重跑一次 add"
44
- ]
45
- }
46
- },
47
- "monorepo怎么装": "本仓库是 monorepo。如果你的 profile 用 CLI,且 CLI 支持仓库内子目录,可以直接指向子目录;**如果不支持,就先把子目录单独取出来(git clone 后本地路径)**,再按 file: 的方式装。★ 这一条请以你手上的 CLI 实际行为为准 —— 装一次就知道,不要猜。"
48
- },
49
- "parts": [
50
- {
51
- "dir": "compaction",
52
- "name": "上下文压缩",
53
- "layer": "I-echo",
54
- "manages": "空间 —— 上下文满了要丢,丢了要能找回来",
55
- "provides": "压缩 + 裁剪,且每个产物都带得回原文的指针",
56
- "required": true,
57
- "check": "它产出的摘要里带不带原文指针?拿不到精确位置时它怎么写(写检索入口还是猜一个坐标)?",
58
- "depends": [],
59
- "needs": [],
60
- "reads": [
61
- {
62
- "what": "会话日志",
63
- "why": "要压的东西来自这里",
64
- "missing": "压不出东西 —— 会话本身就没跑起来"
65
- }
66
- ],
67
- "依赖说明": "实际依赖 DSH 自带的 @deepseek-ai/dsh-compaction-basic(不是本仓库的包)。"
68
- },
69
- {
70
- "dir": "pruner",
71
- "name": "工具结果裁剪",
72
- "layer": "I-echo",
73
- "manages": "空间 —— 大头通常是工具返回的原始文本",
74
- "provides": "超长工具结果的裁剪,保留首尾 + 中间可回取的标记",
75
- "required": true,
76
- "check": "裁掉的部分还能不能找回来?它留的是指针还是「省略 N 字」?",
77
- "depends": [],
78
- "needs": [],
79
- "reads": [
80
- {
81
- "what": "会话日志",
82
- "why": "要裁的工具结果来自这里",
83
- "missing": "没有可裁的"
84
- }
85
- ],
86
- "依赖说明": "实际依赖 DSH 自带的 @deepseek-ai/dsh-compaction-tool-result-pruner。"
87
- },
88
- {
89
- "dir": "memory",
90
- "name": "记忆注入",
91
- "layer": "I-echo",
92
- "manages": "空间 —— 哪些记忆进上下文、哪些不进",
93
- "provides": "有限预算内的记忆投影",
94
- "required": true,
95
- "check": "★ 它省略掉的条目,还留不留「存在过」的线索?投影不是搬家,是省略 —— 省略而不留线索,等于丢失。",
96
- "depends": [],
97
- "needs": [],
98
- "reads": [
99
- {
100
- "what": "SELF.md",
101
- "why": "推送层要注入的就是这一页",
102
- "missing": "★ 推送层变成摆设:文件在磁盘上,但每轮注入时读不到。这是最容易假绿的一项。"
103
- },
104
- {
105
- "what": "热记忆(USER.md / MEMORY.md)",
106
- "why": "L1 是运行时给的",
107
- "missing": "热记忆那一段空着"
108
- }
109
- ],
110
- "依赖说明": "★ selfPath 必须配到实际位置。不配的话它默认读 ./SELF.md,而 scaffold 建在 memory/hub/SELF.md —— 两者不是一个地方。"
111
- },
112
- {
113
- "dir": "echo",
114
- "name": "哨兵",
115
- "layer": "I-echo",
116
- "manages": "空间 —— 校验前面几件是不是还活着",
117
- "provides": "分级体检(ok / warn / error / pending)+ 只读状态面板 + **换气每轮判词的观测面**(读 huanqi 写的 JSONL,列出最近每一轮的 kind / 最后一条消息形状 / 判词 / 额度)",
118
- "required": true,
119
- "check": "它有 pending 级吗?「跳过」会不会被显示成「通过」?它自己承认查不到什么吗?★ 它能不能回答「另一个零件到底有没有在看着这一轮」—— 而不是只告诉你文件在不在?",
120
- "depends": [],
121
- "needs": [
122
- {
123
- "what": "huanqi",
124
- "why": "★ 2026-10-19 起它多了一块「换气 · 每轮判词」,读的是 huanqi 写的 state/huanqi-turns.jsonl。技术上不依赖(文件不在就显示「还没有记录」,不会崩),但没有 huanqi 时那一块永远是空的。"
125
- }
126
- ],
127
- "reads": [
128
- {
129
- "what": "三个数据根(soul / memory / sessions)",
130
- "why": "体检要读它们",
131
- "missing": "报「还没配好」,11 项检查全部不跑"
132
- },
133
- {
134
- "what": "echo-doctor.mjs + echo-config.mjs",
135
- "why": "体检器是 spawn 出去的子进程",
136
- "missing": "★ 面板报「输出不是 JSON」—— 而真因是子进程 ERR_MODULE_NOT_FOUND,隔了三层"
137
- },
138
- {
139
- "what": "<DSH_HOME>/state/huanqi-turns.jsonl(换气写的每轮判词)+ dsh-huanqi.json(额度账本)",
140
- "why": "「换气 · 每轮判词」那一块要读它 —— 这是唯一能把「它到底有没有在看着」变成可见证据的地方",
141
- "missing": "★ **不报错,只是空着** —— 面板上写「还没有记录」。这正是 reads 这一类最典型的坑:装好了、看着正常、而它其实一次都没跑过。"
142
- }
143
- ],
144
- "依赖说明": "★ 它必须是最后崩的那个 —— 它崩了,就没人能告诉人哪里坏了。★★ 2026-10-19 起它同时是「稳态引擎的观测面」:换气的判断以前只进 ctx.logger,而桌面端 logger 不落盘,所以「它有没有在看着这一轮」在机器上没有任何痕迹。现在换气每轮写一条 JSONL,回声读它。"
145
- },
146
- {
147
- "dir": "mnemon-probe",
148
- "name": "记忆空间探针",
149
- "layer": "I-echo",
150
- "manages": "外部记忆空间的使用量",
151
- "provides": "容量预警(接近上限时提醒精简)",
152
- "required": false,
153
- "check": "接近上限时它提醒的是「精简现有条目」还是「扩容」?前者才是对的。",
154
- "depends": [],
155
- "needs": [],
156
- "reads": [
157
- {
158
- "what": "mnemon 运行时目录",
159
- "why": "读记忆空间的使用量",
160
- "missing": "报「未配置」;不会崩"
161
- }
162
- ],
163
- "依赖说明": "可选件。不装不影响六层,只是看不到容量预警。"
164
- },
165
- {
166
- "dir": "riji",
167
- "name": "日记",
168
- "layer": "IV-archive",
169
- "manages": "档案 —— 对内的自我记录",
170
- "provides": "按天沉淀的日记文件",
171
- "required": false,
172
- "check": "它是「任务」还是「东西」?如果变成每天要交的作业,它就不是日记了。",
173
- "depends": [],
174
- "needs": [],
175
- "reads": [],
176
- "依赖说明": "可选件。★ 它是「东西」不是「任务」—— 变成每天要交的作业,它就不是日记了。"
177
- },
178
- {
179
- "dir": "clock",
180
- "name": "时钟",
181
- "layer": "II-vital",
182
- "manages": "时间 —— 会话自己不知道「现在几点、距上次多久」",
183
- "provides": "可查的时间锚点",
184
- "required": false,
185
- "check": "它给的是绝对时间还是相对时间?两者都要,缺一个就会误判「刚刚」和「很久以前」。",
186
- "depends": [],
187
- "needs": [],
188
- "reads": [],
189
- "依赖说明": "完全独立 —— 它只回答「现在几点」,不需要任何产物。"
190
- },
191
- {
192
- "dir": "model-statusbar",
193
- "name": "模型状态栏",
194
- "layer": "II-vital",
195
- "manages": "预算 / 状态 —— 当前模型、上下文水位",
196
- "provides": "可见的水位与模型读数",
197
- "required": false,
198
- "check": "★ 它读的是「真正喂进模型的量」还是「可见消息面」?这两个数字能差一倍,用错了会让闸门在错误的位置响。",
199
- "depends": [],
200
- "needs": [],
201
- "reads": [
202
- {
203
- "what": "会话日志的 usage",
204
- "why": "水位要从这里算",
205
- "missing": "显示不了水位"
206
- }
207
- ],
208
- "依赖说明": "★ 它读的必须是「真正喂进模型的量」(input + cacheRead),不是「可见消息面」—— 两个数字能差一倍。"
209
- },
210
- {
211
- "dir": "huanqi",
212
- "name": "稳态引擎",
213
- "layer": "II-vital",
214
- "manages": "方向 —— 漂移检测(推理泄漏、重复、原地打转)",
215
- "provides": "检测 + 干预 + **每轮判词落盘**(写 state/huanqi-turns.jsonl,给回声面板读)",
216
- "required": false,
217
- "check": "它的每一条阈值背后挂着哪个具体失败?答不上来的阈值会误伤。它的干预有没有对应的观测面(误伤记录)?★ 它跑起来了吗 —— 是「文件在」还是「apply() 真的进了、而且走到底了」?后者要能看到日志或产物,不能靠配置正确来推断。",
218
- "depends": [],
219
- "needs": [],
220
- "reads": [
221
- {
222
- "what": "会话日志里的推理内容",
223
- "why": "漂移检测要看「它是不是在重复 / 原地打转」",
224
- "missing": "检测不出东西"
225
- }
226
- ],
227
- "依赖说明": "实际依赖 DSH 自带的 @deepseek-ai/dsh-agent 与 dsh-llm。★★ peer 范围必须含 >=0.2.1-rc2 <0.3.0 这一条,而且**必须单独写一条 comparator** —— semver 只在同一组里出现同 major.minor.patch 的 comparator 时才 admit 那处的 prerelease;写成 >=0.1.2-rc.1 <0.3.0 既不 admit 0.2.1-rc2、又会误 admit 没测过的 0.2.x 正式版,两头都错。★★ 2026-10-19 起它每轮结束往 <DSH_HOME>/state/huanqi-turns.jsonl 写一条判词(kind / 最后一条消息形状 / 有没有产出 / 判词 / 剩余额度),由 echo 面板读 —— 这是它从「不可视」变成「可视」的那一步,也是「它到底有没有在看着这一轮」第一次有了机器可读的证据。★ 它的每条阈值背后都该挂一个具体失败 —— 答不上来的阈值会误伤。",
228
- "来源": {
229
- "性质": "自创。功能设计、三档动作、额度账、面板联动都是我们定的。",
230
- "吸收了什么": [
231
- "推理侧的周期检测思路 —— 来自 dsh-loop-guard(MIT)。它检测的是「可见输出」的重复,我们把它扩到推理通道。",
232
- "「从流内部切断」而不是「调用结束后判定」—— 同一个来源。因为退化循环的流永远不会正常结束,任何事后检测都够不着。"
233
- ],
234
- "和它不一样的地方": [
235
- "★ 判断三档动作(截断 / 续命 / 记账)是我们定的,它不是这个形状。",
236
- "★ 额度账(延续额度)是我们加的 —— 它只管剪断,不管「还能续几次」。",
237
- "★ 阈值是在我们自己的真实数据上重新校准的,不是沿用它的默认值。"
238
- ],
239
- "为什么不再保留原作者署名": "Copyright 行原先是从上游带过来的残留;功能设计与实现都是本仓库的,所以版权归 dsh-agent-organs contributors。思路来源在上一条里写清了 —— 这是开源精神的做法:吸收要说明,不必照抄署名。",
240
- "内部标识没改": "测试里还有 source.kind === 'loop-guard' 这类断言。留着是因为它记录真实来源;改名只是形式统一,不影响功能,不急着动。"
241
- }
242
- },
243
- {
244
- "dir": "huanqi-panel",
245
- "name": "稳态面板",
246
- "layer": "II-vital",
247
- "manages": "同一件事的观测面",
248
- "provides": "huanqi 的可视化(触发次数 / 误伤记录)",
249
- "required": false,
250
- "check": "★ 没有面板的稳态系统,你永远不知道它误伤过几次。这一件是 huanqi 的配套,不建议单独装。",
251
- "depends": [],
252
- "needs": [
253
- {
254
- "what": "huanqi",
255
- "why": "★ 它编辑的就是 huanqi 的配置。技术上不依赖(读的是 cordis.patch.yml 的字节),但没有 huanqi 的话,改完的配置没人用。"
256
- }
257
- ],
258
- "reads": [
259
- {
260
- "what": "cordis.patch.yml 里的 - id: huanqi 那一段",
261
- "why": "字节级编辑,不重新序列化整个 YAML",
262
- "missing": "面板能开,但写不进去"
263
- }
264
- ],
265
- "依赖说明": "★ 全篇最要紧的一条:绝不能重新序列化 cordis.patch.yml —— 那里塞满了注释、!!js 表达式和手排的分节,读成对象再写回会全丢掉。"
266
- },
267
- {
268
- "dir": "splash",
269
- "name": "启动画面",
270
- "layer": "IV-archive",
271
- "manages": "(对外可访问性)",
272
- "provides": "启动时的状态一屏",
273
- "required": false,
274
- "check": "它报错时显示的是真实错误,还是「没有配置」这类吞掉错误的兜底文案?后者会让你多查一小时。",
275
- "depends": [],
276
- "needs": [],
277
- "reads": [
278
- {
279
- "what": "dsh/home/splash.json",
280
- "why": "启动画面注入代码启动时读它",
281
- "missing": "用默认启动画面"
282
- }
283
- ],
284
- "依赖说明": "三条硬教训:CORS 头必须写 / export const inject 必须写 / 配置读写不让异常冒出去。"
285
- },
286
- {
287
- "dir": "mobile-adapt",
288
- "name": "移动端适配",
289
- "layer": "III-capability",
290
- "manages": "(不管理稀缺资源 —— 所以这一层不进权威源)",
291
- "provides": "竖屏触摸设备的界面收拢",
292
- "required": false,
293
- "check": "把它整个删掉,你的身份判据还成立吗?成立就对了 —— 这正是 III 层的定义。",
294
- "depends": [],
295
- "needs": [],
296
- "reads": [],
297
- "依赖说明": "★ 判据:把它整个删掉,身份判据还成立吗?成立就对了 —— 这正是 III 层的定义。"
298
- },
299
- {
300
- "dir": "yantai",
301
- "name": "工作台面板",
302
- "layer": "IV-archive",
303
- "manages": "(对外可访问性)",
304
- "provides": "一屏可读的状态:未结的活、最近记录、几扇门",
305
- "required": false,
306
- "check": "一个从没见过你的人,能不能只靠它知道你在干什么?",
307
- "depends": [],
308
- "needs": [],
309
- "reads": [
310
- {
311
- "what": "账本(02-墨.jsonl)",
312
- "why": "未结的活和最近记录都从这里读",
313
- "missing": "★ 面板能开,但三块内容是空的 —— 新人最容易在这里以为插件坏了,其实是还没写账本"
314
- },
315
- {
316
- "what": "会话日志的 usage",
317
- "why": "水位那一栏",
318
- "missing": "水位显示不了"
319
- }
320
- ],
321
- "依赖说明": "★ 它的空不是故障,是「还没开始用」。判据:账本里有几条,它就该显示几条。"
322
- },
323
- {
324
- "dir": "dsh-mnemon",
325
- "name": "记忆空间(mnemon)",
326
- "layer": "I-echo",
327
- "external": true,
328
- "manages": "空间 —— 可复用的技术结论放在哪、怎么按语义取回",
329
- "provides": "一个 19 包的组合:主包 + 11 个 provider(byterover / hindsight / holographic / honcho / mem0 / mnemon-native / openviking / retaindb / supermemory)+ 3 个 source(documents / memory-spaces / runtime)+ 5 个 strategy(auto-capture / default-three-tier / general / light-context / scoped)",
330
- "required": true,
331
- "来源": "第三方(github.com/omdsh-dev/dsh-mnemon),npm 上有正式发布,MIT。不是我们写的,我们只用它。",
332
- "和我们的关系": "★ 我们的 dsh-agent-mnemon-probe 是自创的探针,读它的记忆空间并报使用量。两个包名字很像,但一个是别人的引擎、一个是我们的仪表。",
333
- "装法": [
334
- "desktop profile: 已经在 npm dependencies 里(dsh-mnemon = 0.5.20 + 18 个子包)",
335
- "CLI profile: dsh plugin --profile <名字> add dsh-mnemon",
336
- "★ 主包会连带装 18 个子包 —— 装之前确认它能拉全,否则记忆空间是空的"
337
- ],
338
- "check": "★ 判据不是「装上了」,是「有空间可用」:跑一次 mnemon_status / mnemon_memory_bodies,看有没有 active 的 space。装上了但一个 space 都没有,和没装一样。",
339
- "depends": [],
340
- "needs": [
341
- {
342
- "what": "dsh-agent-mnemon-probe",
343
- "why": "★ 反向依赖:探针依赖它。没有 mnemon 的话,探针只能报「未配置」—— 那不是探针坏了,是它要读的东西不存在。"
344
- }
345
- ],
346
- "reads": [],
347
- "为什么必备": {
348
- "一句话": "架构里「两套记忆」的分工是核心判断之一。缺了它,那半边没有登记处 —— 可复用的技术结论只能退化成「写在某个文档里,靠人记得去翻」。",
349
- "具体丢什么": [
350
- "一手事件进账本,可复用的技术结论进记忆空间 —— 这是两条不同的路。只有账本,就等于只留了「当时发生了什么」,丢了「我们以前对这类问题下过什么结论」。",
351
- "跨会话语义检索是它的长处:账本搜得准,但账本不是为「找判据」设计的。"
352
- ],
353
- "不装会怎样": "六层体检不会红,mnemon-probe 只会报「未配置」——它不是坏了,是它要读的东西不存在。★ 这就是为什么它被漏了这么久:没装看起来像没配好。",
354
- "已发生过的事": "沙箱 profile 从第一天起就没装(19 个包全缺),而没有人注意到。"
355
- }
356
- }
357
- ],
358
- "tools": [
359
- {
360
- "dir": "tools/ledger",
361
- "name": "账本工具",
362
- "role": "权威源的读写接口",
363
- "note": "写入接口应当有权限闸门(越权写入直接失败,而不是写进去再记日志)",
364
- "depends": [],
365
- "needs": [],
366
- "reads": [
367
- {
368
- "what": "账本文件",
369
- "why": "读写它",
370
- "missing": "读空、写失败"
371
- }
372
- ],
373
- "依赖说明": "★ 写入接口要有权限闸门:越权写入直接失败,而不是写进去再记日志。"
374
- },
375
- {
376
- "dir": "tools/gateway",
377
- "name": "门",
378
- "role": "搜 / 开 / 时间 三动词",
379
- "note": "搜的结果要标来源类别(原文 / 索引 / 程序),否则你会把摘要当原文引用",
380
- "depends": [],
381
- "needs": [],
382
- "reads": [
383
- {
384
- "what": "索引目录",
385
- "why": "搜索要查它",
386
- "missing": "只能扫原文,慢但不会错"
387
- }
388
- ],
389
- "依赖说明": "★ 搜索结果必须标来源类别(原文 / 索引 / 程序),否则会把摘要当原文引用。"
390
- },
391
- {
392
- "dir": "tools/self",
393
- "name": "自我层装配",
394
- "role": "生成并体检推送层",
395
- "note": "自动生成段与手写段必须有明确分界;改自动段会被下次装配覆盖",
396
- "depends": [],
397
- "needs": [],
398
- "reads": [
399
- {
400
- "what": "SELF.src.md",
401
- "why": "装配推送层的输入",
402
- "missing": "生成不出 SELF.md"
403
- }
404
- ],
405
- "依赖说明": "★ 自动生成段和手写段必须有明确分界;改自动段会被下次装配覆盖。"
406
- }
407
- ],
408
- "after_install": [
409
- "重启 DSH(不是刷新页面)",
410
- "验证:工具列表里出现了新的工具名 —— 「文件复制过去了」不是判据",
411
- "验证:每个插件自己的路由能通(curl 一次,看响应头有没有 CORS —— 有 = 插件活了,没有 = 它没跑到)",
412
- "跑一次哨兵的体检,确认有 pending 级而不是一片绿",
413
- "回到 skeleton/04-doctor.md,把可机械查的那张表填上你自己的命令"
414
- ],
415
- "不在这里的": {
416
- "说明": "本仓库只收「可移植的能力半」。下面这些是身份半 —— 交出去只会让别人变成模仿品,长不出他自己的灵魂。",
417
- "例": [
418
- "人格 / 关系 / 说话方式",
419
- "日记内容、账本内容",
420
- "本机路径、私有服务名、端口",
421
- "某个人的具体偏好与审美"
422
- ]
423
- },
424
- "三种依赖怎么读": {
425
- "depends": "硬依赖 —— 不装这个,那个就跑不起来。package 级。现在 14 个零件全是空的:它们只依赖 DSH 自带的包,互相之间没有 npm 依赖。",
426
- "needs": "软依赖 —— 缺了它这个零件就没有意义。功能级。例:huanqi-panel 缺了 huanqi,改完的配置没人用。",
427
- "reads": "★ 对产物的依赖 —— 它咬在哪份数据上。这是三种里最有价值的一种:它回答「装了这个零件,我还必须建出什么,它才有用」。缺了这份数据,零件不会报错,它会「成功但空着」。"
428
- },
429
- "关于吸收": "这个仓库吸收过别人的思路(不是代码)。判据:功能设计是我们的、实现是重写的、阈值是在我们自己的数据上校准的 —— 那就写「自创」,但在条目里注明吸收了什么。吸收要说明,这是开源精神的一半;另一半是「不必因为吸收过就把自己说成搬运工」。",
430
- "外部零件": "parts 里带 \"external\": true 的,不是本仓库的包,是外部依赖 —— 但它们仍然属于装配清单的一部分,因为「装哪些」和「谁写的」是两件事。"
431
- }
1
+ {
2
+ "version": "0.1.0",
3
+ "what": "参考实现清单 —— 我们已经做出来的一套。这一份和 04-manifest.json 性质不同:04 说「这一类该满足什么」(不绑任何实现),本文件说「我们具体用了什么」(可替换)。",
4
+ "读了它你该知道": [
5
+ "你可以全部采用、部分采用、或者一个都不用 —— 它只是参考实现,不是必要条件",
6
+ "每一件都标了它填哪一层、管哪种稀缺资源、缺了会怎样",
7
+ "装之前先读 skeleton/00-authority.md —— 不先定权威源,装什么都双重记账"
8
+ ],
9
+ "repo": {
10
+ "url": "https://github.com/cyanwell/dsh-agent-organs",
11
+ "kind": "monorepo",
12
+ "note": "一个仓库里放了多个独立的 DSH 插件,每个子目录是一个完整的包(各自有 package.json / cordis.patch.yml / index.js / client.js)。"
13
+ },
14
+ "install": {
15
+ "先读这一条": "★ 桌面端(profile = desktop)**不能用 CLI 安装**。实测报错原文:`error: profile \"desktop\" is managed exclusively by the Electron application`。桌面端只能手动两步,见 methods.desktop。web / 其它 profile 可以用 CLI,见 methods.cli。",
16
+ "methods": {
17
+ "desktop": {
18
+ "适用": "桌面端(Electron 应用管理 profile)",
19
+ "步骤": [
20
+ "① 把插件目录复制进 <profile>/node_modules/<包名>/(四个文件一个不能少:package.json / cordis.patch.yml / index.js / client.js)",
21
+ "② 在 <profile>/package.json 的 dsh.profile.bundles 数组里加上这个包名",
22
+ "③ 重启 DSH"
23
+ ],
24
+ "警告": [
25
+ "★ 第 ② 步必须用 JSON.parse / JSON.stringify 改,不要用容忍 BOM 的解析器 —— 那会给假通过",
26
+ "★ 写完读回来验一次,并确认别的包一个没少",
27
+ "★ 判据是「路由通了 / 设置页那一项出现了」,不是「文件复制过去了」"
28
+ ]
29
+ },
30
+ "cli": {
31
+ "适用": "web / 其它由 CLI 管理的 profile",
32
+ "命令": [
33
+ "dsh plugin --profile <名字> add file:<本地路径>",
34
+ "dsh plugin --profile <名字> add github:<owner>/<repo>"
35
+ ],
36
+ "前置": [
37
+ "pnpm 与 corepack 都必须在 PATH 上(corepack 由 node 自带,在 node 安装目录下)",
38
+ "先 where corepack 确认能找到,否则一定失败"
39
+ ],
40
+ "警告": [
41
+ "★ 装完必须重启 DSH(客户端入口图是启动时一次性组合的)",
42
+ "★ pnpm 会顺带对账,可能剪掉不在 lockfile 里的包 —— 装完逐一核对关键插件还在不在",
43
+ "★ 安装那一刻建立的硬链接不可依赖:用原子写入的编辑器改完源文件,链接会断。改完要么复制覆盖,要么重跑一次 add"
44
+ ]
45
+ }
46
+ },
47
+ "monorepo怎么装": "本仓库是 monorepo。如果你的 profile 用 CLI,且 CLI 支持仓库内子目录,可以直接指向子目录;**如果不支持,就先把子目录单独取出来(git clone 后本地路径)**,再按 file: 的方式装。★ 这一条请以你手上的 CLI 实际行为为准 —— 装一次就知道,不要猜。"
48
+ },
49
+ "parts": [
50
+ {
51
+ "dir": "compaction",
52
+ "name": "上下文压缩",
53
+ "layer": "I-echo",
54
+ "manages": "空间 —— 上下文满了要丢,丢了要能找回来",
55
+ "provides": "压缩 + 裁剪,且每个产物都带得回原文的指针",
56
+ "required": true,
57
+ "check": "它产出的摘要里带不带原文指针?拿不到精确位置时它怎么写(写检索入口还是猜一个坐标)?",
58
+ "depends": [],
59
+ "needs": [],
60
+ "reads": [
61
+ {
62
+ "what": "会话日志",
63
+ "why": "要压的东西来自这里",
64
+ "missing": "压不出东西 —— 会话本身就没跑起来"
65
+ }
66
+ ],
67
+ "依赖说明": "实际依赖 DSH 自带的 @deepseek-ai/dsh-compaction-basic(不是本仓库的包)。"
68
+ },
69
+ {
70
+ "dir": "pruner",
71
+ "name": "工具结果裁剪",
72
+ "layer": "I-echo",
73
+ "manages": "空间 —— 大头通常是工具返回的原始文本",
74
+ "provides": "超长工具结果的裁剪,保留首尾 + 中间可回取的标记",
75
+ "required": true,
76
+ "check": "裁掉的部分还能不能找回来?它留的是指针还是「省略 N 字」?",
77
+ "depends": [],
78
+ "needs": [],
79
+ "reads": [
80
+ {
81
+ "what": "会话日志",
82
+ "why": "要裁的工具结果来自这里",
83
+ "missing": "没有可裁的"
84
+ }
85
+ ],
86
+ "依赖说明": "实际依赖 DSH 自带的 @deepseek-ai/dsh-compaction-tool-result-pruner。"
87
+ },
88
+ {
89
+ "dir": "memory",
90
+ "name": "记忆注入",
91
+ "layer": "I-echo",
92
+ "manages": "空间 —— 哪些记忆进上下文、哪些不进",
93
+ "provides": "有限预算内的记忆投影",
94
+ "required": true,
95
+ "check": "★ 它省略掉的条目,还留不留「存在过」的线索?投影不是搬家,是省略 —— 省略而不留线索,等于丢失。",
96
+ "depends": [],
97
+ "needs": [],
98
+ "reads": [
99
+ {
100
+ "what": "SELF.md",
101
+ "why": "推送层要注入的就是这一页",
102
+ "missing": "★ 推送层变成摆设:文件在磁盘上,但每轮注入时读不到。这是最容易假绿的一项。"
103
+ },
104
+ {
105
+ "what": "热记忆(USER.md / MEMORY.md)",
106
+ "why": "L1 是运行时给的",
107
+ "missing": "热记忆那一段空着"
108
+ }
109
+ ],
110
+ "依赖说明": "★ selfPath 必须配到实际位置。不配的话它默认读 ./SELF.md,而 scaffold 建在 memory/hub/SELF.md —— 两者不是一个地方。"
111
+ },
112
+ {
113
+ "dir": "echo",
114
+ "name": "哨兵",
115
+ "layer": "I-echo",
116
+ "manages": "空间 —— 校验前面几件是不是还活着",
117
+ "provides": "分级体检(ok / warn / error / pending)+ 只读状态面板 + **换气每轮判词的观测面**(读 huanqi 写的 JSONL,列出最近每一轮的 kind / 最后一条消息形状 / 判词 / 额度)",
118
+ "required": true,
119
+ "check": "它有 pending 级吗?「跳过」会不会被显示成「通过」?它自己承认查不到什么吗?★ 它能不能回答「另一个零件到底有没有在看着这一轮」—— 而不是只告诉你文件在不在?",
120
+ "depends": [],
121
+ "needs": [
122
+ {
123
+ "what": "huanqi",
124
+ "why": "★ 2026-10-19 起它多了一块「换气 · 每轮判词」,读的是 huanqi 写的 state/huanqi-turns.jsonl。技术上不依赖(文件不在就显示「还没有记录」,不会崩),但没有 huanqi 时那一块永远是空的。"
125
+ }
126
+ ],
127
+ "reads": [
128
+ {
129
+ "what": "三个数据根(soul / memory / sessions)",
130
+ "why": "体检要读它们",
131
+ "missing": "报「还没配好」,11 项检查全部不跑"
132
+ },
133
+ {
134
+ "what": "echo-doctor.mjs + echo-config.mjs",
135
+ "why": "体检器是 spawn 出去的子进程",
136
+ "missing": "★ 面板报「输出不是 JSON」—— 而真因是子进程 ERR_MODULE_NOT_FOUND,隔了三层"
137
+ },
138
+ {
139
+ "what": "<DSH_HOME>/state/huanqi-turns.jsonl(换气写的每轮判词)+ dsh-huanqi.json(额度账本)",
140
+ "why": "「换气 · 每轮判词」那一块要读它 —— 这是唯一能把「它到底有没有在看着」变成可见证据的地方",
141
+ "missing": "★ **不报错,只是空着** —— 面板上写「还没有记录」。这正是 reads 这一类最典型的坑:装好了、看着正常、而它其实一次都没跑过。"
142
+ }
143
+ ],
144
+ "依赖说明": "★ 它必须是最后崩的那个 —— 它崩了,就没人能告诉人哪里坏了。★★ 2026-10-19 起它同时是「稳态引擎的观测面」:换气的判断以前只进 ctx.logger,而桌面端 logger 不落盘,所以「它有没有在看着这一轮」在机器上没有任何痕迹。现在换气每轮写一条 JSONL,回声读它。"
145
+ },
146
+ {
147
+ "dir": "mnemon-probe",
148
+ "name": "记忆空间探针",
149
+ "layer": "I-echo",
150
+ "manages": "外部记忆空间的使用量",
151
+ "provides": "容量预警(接近上限时提醒精简)",
152
+ "required": false,
153
+ "check": "接近上限时它提醒的是「精简现有条目」还是「扩容」?前者才是对的。",
154
+ "depends": [],
155
+ "needs": [],
156
+ "reads": [
157
+ {
158
+ "what": "mnemon 运行时目录",
159
+ "why": "读记忆空间的使用量",
160
+ "missing": "报「未配置」;不会崩"
161
+ }
162
+ ],
163
+ "依赖说明": "可选件。不装不影响六层,只是看不到容量预警。"
164
+ },
165
+ {
166
+ "dir": "riji",
167
+ "name": "日记",
168
+ "layer": "IV-archive",
169
+ "manages": "档案 —— 对内的自我记录",
170
+ "provides": "按天沉淀的日记文件",
171
+ "required": false,
172
+ "check": "它是「任务」还是「东西」?如果变成每天要交的作业,它就不是日记了。",
173
+ "depends": [],
174
+ "needs": [],
175
+ "reads": [],
176
+ "依赖说明": "可选件。★ 它是「东西」不是「任务」—— 变成每天要交的作业,它就不是日记了。"
177
+ },
178
+ {
179
+ "dir": "clock",
180
+ "name": "时钟",
181
+ "layer": "II-vital",
182
+ "manages": "时间 —— 会话自己不知道「现在几点、距上次多久」",
183
+ "provides": "可查的时间锚点",
184
+ "required": false,
185
+ "check": "它给的是绝对时间还是相对时间?两者都要,缺一个就会误判「刚刚」和「很久以前」。",
186
+ "depends": [],
187
+ "needs": [],
188
+ "reads": [],
189
+ "依赖说明": "完全独立 —— 它只回答「现在几点」,不需要任何产物。"
190
+ },
191
+ {
192
+ "dir": "model-statusbar",
193
+ "name": "模型状态栏",
194
+ "layer": "II-vital",
195
+ "manages": "预算 / 状态 —— 当前模型、上下文水位",
196
+ "provides": "可见的水位与模型读数",
197
+ "required": false,
198
+ "check": "★ 它读的是「真正喂进模型的量」还是「可见消息面」?这两个数字能差一倍,用错了会让闸门在错误的位置响。",
199
+ "depends": [],
200
+ "needs": [],
201
+ "reads": [
202
+ {
203
+ "what": "会话日志的 usage",
204
+ "why": "水位要从这里算",
205
+ "missing": "显示不了水位"
206
+ }
207
+ ],
208
+ "依赖说明": "★ 它读的必须是「真正喂进模型的量」(input + cacheRead),不是「可见消息面」—— 两个数字能差一倍。"
209
+ },
210
+ {
211
+ "dir": "huanqi",
212
+ "name": "稳态引擎",
213
+ "layer": "II-vital",
214
+ "manages": "方向 —— 漂移检测(推理泄漏、重复、原地打转)",
215
+ "provides": "检测 + 干预 + **每轮判词落盘**(写 state/huanqi-turns.jsonl,给回声面板读)",
216
+ "required": false,
217
+ "check": "它的每一条阈值背后挂着哪个具体失败?答不上来的阈值会误伤。它的干预有没有对应的观测面(误伤记录)?★ 它跑起来了吗 —— 是「文件在」还是「apply() 真的进了、而且走到底了」?后者要能看到日志或产物,不能靠配置正确来推断。",
218
+ "depends": [],
219
+ "needs": [],
220
+ "reads": [
221
+ {
222
+ "what": "会话日志里的推理内容",
223
+ "why": "漂移检测要看「它是不是在重复 / 原地打转」",
224
+ "missing": "检测不出东西"
225
+ }
226
+ ],
227
+ "依赖说明": "实际依赖 DSH 自带的 @deepseek-ai/dsh-agent 与 dsh-llm。★★ peer 范围必须含 >=0.2.1-rc2 <0.3.0 这一条,而且**必须单独写一条 comparator** —— semver 只在同一组里出现同 major.minor.patch 的 comparator 时才 admit 那处的 prerelease;写成 >=0.1.2-rc.1 <0.3.0 既不 admit 0.2.1-rc2、又会误 admit 没测过的 0.2.x 正式版,两头都错。★★ 2026-10-19 起它每轮结束往 <DSH_HOME>/state/huanqi-turns.jsonl 写一条判词(kind / 最后一条消息形状 / 有没有产出 / 判词 / 剩余额度),由 echo 面板读 —— 这是它从「不可视」变成「可视」的那一步,也是「它到底有没有在看着这一轮」第一次有了机器可读的证据。★ 它的每条阈值背后都该挂一个具体失败 —— 答不上来的阈值会误伤。",
228
+ "来源": {
229
+ "性质": "自创。功能设计、三档动作、额度账、面板联动都是我们定的。",
230
+ "吸收了什么": [
231
+ "推理侧的周期检测思路 —— 来自 dsh-loop-guard(MIT)。它检测的是「可见输出」的重复,我们把它扩到推理通道。",
232
+ "「从流内部切断」而不是「调用结束后判定」—— 同一个来源。因为退化循环的流永远不会正常结束,任何事后检测都够不着。"
233
+ ],
234
+ "和它不一样的地方": [
235
+ "★ 判断三档动作(截断 / 续命 / 记账)是我们定的,它不是这个形状。",
236
+ "★ 额度账(延续额度)是我们加的 —— 它只管剪断,不管「还能续几次」。",
237
+ "★ 阈值是在我们自己的真实数据上重新校准的,不是沿用它的默认值。"
238
+ ],
239
+ "为什么不再保留原作者署名": "Copyright 行原先是从上游带过来的残留;功能设计与实现都是本仓库的,所以版权归 dsh-agent-organs contributors。思路来源在上一条里写清了 —— 这是开源精神的做法:吸收要说明,不必照抄署名。",
240
+ "内部标识没改": "测试里还有 source.kind === 'loop-guard' 这类断言。留着是因为它记录真实来源;改名只是形式统一,不影响功能,不急着动。"
241
+ }
242
+ },
243
+ {
244
+ "dir": "huanqi-panel",
245
+ "name": "稳态面板",
246
+ "layer": "II-vital",
247
+ "manages": "同一件事的观测面",
248
+ "provides": "huanqi 的可视化(触发次数 / 误伤记录)",
249
+ "required": false,
250
+ "check": "★ 没有面板的稳态系统,你永远不知道它误伤过几次。这一件是 huanqi 的配套,不建议单独装。",
251
+ "depends": [],
252
+ "needs": [
253
+ {
254
+ "what": "huanqi",
255
+ "why": "★ 它编辑的就是 huanqi 的配置。技术上不依赖(读的是 cordis.patch.yml 的字节),但没有 huanqi 的话,改完的配置没人用。"
256
+ }
257
+ ],
258
+ "reads": [
259
+ {
260
+ "what": "cordis.patch.yml 里的 - id: huanqi 那一段",
261
+ "why": "字节级编辑,不重新序列化整个 YAML",
262
+ "missing": "面板能开,但写不进去"
263
+ }
264
+ ],
265
+ "依赖说明": "★ 全篇最要紧的一条:绝不能重新序列化 cordis.patch.yml —— 那里塞满了注释、!!js 表达式和手排的分节,读成对象再写回会全丢掉。"
266
+ },
267
+ {
268
+ "dir": "splash",
269
+ "name": "启动画面",
270
+ "layer": "IV-archive",
271
+ "manages": "(对外可访问性)",
272
+ "provides": "启动时的状态一屏",
273
+ "required": false,
274
+ "check": "它报错时显示的是真实错误,还是「没有配置」这类吞掉错误的兜底文案?后者会让你多查一小时。",
275
+ "depends": [],
276
+ "needs": [],
277
+ "reads": [
278
+ {
279
+ "what": "dsh/home/splash.json",
280
+ "why": "启动画面注入代码启动时读它",
281
+ "missing": "用默认启动画面"
282
+ }
283
+ ],
284
+ "依赖说明": "三条硬教训:CORS 头必须写 / export const inject 必须写 / 配置读写不让异常冒出去。"
285
+ },
286
+ {
287
+ "dir": "mobile-adapt",
288
+ "name": "移动端适配",
289
+ "layer": "III-capability",
290
+ "manages": "(不管理稀缺资源 —— 所以这一层不进权威源)",
291
+ "provides": "竖屏触摸设备的界面收拢",
292
+ "required": false,
293
+ "check": "把它整个删掉,你的身份判据还成立吗?成立就对了 —— 这正是 III 层的定义。",
294
+ "depends": [],
295
+ "needs": [],
296
+ "reads": [],
297
+ "依赖说明": "★ 判据:把它整个删掉,身份判据还成立吗?成立就对了 —— 这正是 III 层的定义。"
298
+ },
299
+ {
300
+ "dir": "yantai",
301
+ "name": "工作台面板",
302
+ "layer": "IV-archive",
303
+ "manages": "(对外可访问性)",
304
+ "provides": "一屏可读的状态:未结的活、最近记录、几扇门",
305
+ "required": false,
306
+ "check": "一个从没见过你的人,能不能只靠它知道你在干什么?",
307
+ "depends": [],
308
+ "needs": [],
309
+ "reads": [
310
+ {
311
+ "what": "账本(02-墨.jsonl)",
312
+ "why": "未结的活和最近记录都从这里读",
313
+ "missing": "★ 面板能开,但三块内容是空的 —— 新人最容易在这里以为插件坏了,其实是还没写账本"
314
+ },
315
+ {
316
+ "what": "会话日志的 usage",
317
+ "why": "水位那一栏",
318
+ "missing": "水位显示不了"
319
+ }
320
+ ],
321
+ "依赖说明": "★ 它的空不是故障,是「还没开始用」。判据:账本里有几条,它就该显示几条。"
322
+ },
323
+ {
324
+ "dir": "dsh-mnemon",
325
+ "name": "记忆空间(mnemon)",
326
+ "layer": "I-echo",
327
+ "external": true,
328
+ "manages": "空间 —— 可复用的技术结论放在哪、怎么按语义取回",
329
+ "provides": "一个 19 包的组合:主包 + 11 个 provider(byterover / hindsight / holographic / honcho / mem0 / mnemon-native / openviking / retaindb / supermemory)+ 3 个 source(documents / memory-spaces / runtime)+ 5 个 strategy(auto-capture / default-three-tier / general / light-context / scoped)",
330
+ "required": true,
331
+ "来源": "第三方(github.com/omdsh-dev/dsh-mnemon),npm 上有正式发布,MIT。不是我们写的,我们只用它。",
332
+ "和我们的关系": "★ 我们的 dsh-agent-mnemon-probe 是自创的探针,读它的记忆空间并报使用量。两个包名字很像,但一个是别人的引擎、一个是我们的仪表。",
333
+ "装法": [
334
+ "desktop profile: 已经在 npm dependencies 里(dsh-mnemon = 0.5.20 + 18 个子包)",
335
+ "CLI profile: dsh plugin --profile <名字> add dsh-mnemon",
336
+ "★ 主包会连带装 18 个子包 —— 装之前确认它能拉全,否则记忆空间是空的"
337
+ ],
338
+ "check": "★ 判据不是「装上了」,是「有空间可用」:跑一次 mnemon_status / mnemon_memory_bodies,看有没有 active 的 space。装上了但一个 space 都没有,和没装一样。",
339
+ "depends": [],
340
+ "needs": [
341
+ {
342
+ "what": "dsh-agent-mnemon-probe",
343
+ "why": "★ 反向依赖:探针依赖它。没有 mnemon 的话,探针只能报「未配置」—— 那不是探针坏了,是它要读的东西不存在。"
344
+ }
345
+ ],
346
+ "reads": [],
347
+ "为什么必备": {
348
+ "一句话": "架构里「两套记忆」的分工是核心判断之一。缺了它,那半边没有登记处 —— 可复用的技术结论只能退化成「写在某个文档里,靠人记得去翻」。",
349
+ "具体丢什么": [
350
+ "一手事件进账本,可复用的技术结论进记忆空间 —— 这是两条不同的路。只有账本,就等于只留了「当时发生了什么」,丢了「我们以前对这类问题下过什么结论」。",
351
+ "跨会话语义检索是它的长处:账本搜得准,但账本不是为「找判据」设计的。"
352
+ ],
353
+ "不装会怎样": "六层体检不会红,mnemon-probe 只会报「未配置」——它不是坏了,是它要读的东西不存在。★ 这就是为什么它被漏了这么久:没装看起来像没配好。",
354
+ "已发生过的事": "沙箱 profile 从第一天起就没装(19 个包全缺),而没有人注意到。"
355
+ }
356
+ }
357
+ ],
358
+ "tools": [
359
+ {
360
+ "dir": "tools/ledger",
361
+ "name": "账本工具",
362
+ "role": "权威源的读写接口",
363
+ "note": "写入接口应当有权限闸门(越权写入直接失败,而不是写进去再记日志)",
364
+ "depends": [],
365
+ "needs": [],
366
+ "reads": [
367
+ {
368
+ "what": "账本文件",
369
+ "why": "读写它",
370
+ "missing": "读空、写失败"
371
+ }
372
+ ],
373
+ "依赖说明": "★ 写入接口要有权限闸门:越权写入直接失败,而不是写进去再记日志。"
374
+ },
375
+ {
376
+ "dir": "tools/gateway",
377
+ "name": "门",
378
+ "role": "搜 / 开 / 时间 三动词",
379
+ "note": "搜的结果要标来源类别(原文 / 索引 / 程序),否则你会把摘要当原文引用",
380
+ "depends": [],
381
+ "needs": [],
382
+ "reads": [
383
+ {
384
+ "what": "索引目录",
385
+ "why": "搜索要查它",
386
+ "missing": "只能扫原文,慢但不会错"
387
+ }
388
+ ],
389
+ "依赖说明": "★ 搜索结果必须标来源类别(原文 / 索引 / 程序),否则会把摘要当原文引用。"
390
+ },
391
+ {
392
+ "dir": "tools/self",
393
+ "name": "自我层装配",
394
+ "role": "生成并体检推送层",
395
+ "note": "自动生成段与手写段必须有明确分界;改自动段会被下次装配覆盖",
396
+ "depends": [],
397
+ "needs": [],
398
+ "reads": [
399
+ {
400
+ "what": "SELF.src.md",
401
+ "why": "装配推送层的输入",
402
+ "missing": "生成不出 SELF.md"
403
+ }
404
+ ],
405
+ "依赖说明": "★ 自动生成段和手写段必须有明确分界;改自动段会被下次装配覆盖。"
406
+ }
407
+ ],
408
+ "after_install": [
409
+ "重启 DSH(不是刷新页面)",
410
+ "验证:工具列表里出现了新的工具名 —— 「文件复制过去了」不是判据",
411
+ "验证:每个插件自己的路由能通(curl 一次,看响应头有没有 CORS —— 有 = 插件活了,没有 = 它没跑到)",
412
+ "跑一次哨兵的体检,确认有 pending 级而不是一片绿",
413
+ "回到 skeleton/04-doctor.md,把可机械查的那张表填上你自己的命令"
414
+ ],
415
+ "不在这里的": {
416
+ "说明": "本仓库只收「可移植的能力半」。下面这些是身份半 —— 交出去只会让别人变成模仿品,长不出他自己的灵魂。",
417
+ "例": [
418
+ "人格 / 关系 / 说话方式",
419
+ "日记内容、账本内容",
420
+ "本机路径、私有服务名、端口",
421
+ "某个人的具体偏好与审美"
422
+ ]
423
+ },
424
+ "三种依赖怎么读": {
425
+ "depends": "硬依赖 —— 不装这个,那个就跑不起来。package 级。现在 14 个零件全是空的:它们只依赖 DSH 自带的包,互相之间没有 npm 依赖。",
426
+ "needs": "软依赖 —— 缺了它这个零件就没有意义。功能级。例:huanqi-panel 缺了 huanqi,改完的配置没人用。",
427
+ "reads": "★ 对产物的依赖 —— 它咬在哪份数据上。这是三种里最有价值的一种:它回答「装了这个零件,我还必须建出什么,它才有用」。缺了这份数据,零件不会报错,它会「成功但空着」。"
428
+ },
429
+ "关于吸收": "这个仓库吸收过别人的思路(不是代码)。判据:功能设计是我们的、实现是重写的、阈值是在我们自己的数据上校准的 —— 那就写「自创」,但在条目里注明吸收了什么。吸收要说明,这是开源精神的一半;另一半是「不必因为吸收过就把自己说成搬运工」。",
430
+ "外部零件": "parts 里带 \"external\": true 的,不是本仓库的包,是外部依赖 —— 但它们仍然属于装配清单的一部分,因为「装哪些」和「谁写的」是两件事。"
431
+ }