@shgroup/dsh-serenity-hooks 1.56.7 → 1.56.8

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
@@ -1,39 +1,39 @@
1
1
  # 宁静号 ACC —— 给 DeepSeek Harness 装一个「AI 工作区」
2
2
 
3
- > **一句话**:装上这个插件,你在电脑上给 AI 划一块自己的工作区(就是一个普通目录),
4
- > AI 在里面干活时就有了**记忆、纪律、工具和边界**——中途换模型、重启电脑、第二天再来,都能接着干。
3
+ > **一句话**:本插件为 AI 指定一个普通目录作为其工作区,
4
+ > AI 在其中工作时即获得**记忆、纪律、工具和边界**——中途更换模型、重启电脑、次日再来,均可继续。
5
5
  >
6
6
  > 适配 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(下称 DSH)的**两条发布线**:
7
7
  > `0.1.7-rc.1` 与 `0.2.0-rc.1`(声明为 `^0.1.7-rc.1 || ^0.2.0-rc.1`,双档并行支持)。
8
- > 想了解背后的想法(为什么叫"认知容器"),看 [docs/cognitive-container-theory.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/docs/cognitive-container-theory.md);本文只讲**能干什么、怎么用**。
8
+ > 设计动机(为何称"认知容器")见 [docs/cognitive-container-theory.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/docs/cognitive-container-theory.md);本 README 只述**能做什么、怎么用**。
9
9
 
10
- **几个词先说明白**(后面都用这几个词,不再解释):
10
+ **术语定义**(后文沿用下列术语,不再重复解释):
11
11
 
12
- | 词 | 说人话 |
12
+ | 术语 | 释义 |
13
13
  |---|---|
14
- | **工作区 / CCC** | 一个目录,里面放一个 `.serenity` 空标记文件。DSH 在别的目录里跑,插件完全不插手;一旦你进到这种目录,它自动生效 |
15
- | **插件 / ACC** | 就是这个仓库(npm 包 `@shgroup/dsh-serenity-hooks`)。它给 DSH 加工具、加约束、加记忆 |
16
- | **MSM** | 你写在工作区里的可执行小工具(一个脚本 + 一行注册)。AI 通过 `msm("名字", ["参数"])` 调用它们 |
17
- | **SESSION.md** | 工作区里的"工作日志"。AI 把目标、决定、进度写进去,中断后再来就从这里接着干 |
14
+ | **工作区 / CCC** | 一个目录,内含一个空的 `.serenity` 标记文件。DSH 在其它目录运行时,本插件不介入;进入此类目录后自动生效 |
15
+ | **插件 / ACC** | = 本仓库(npm 包 `@shgroup/dsh-serenity-hooks`)。为 DSH 增加工具、约束与记忆 |
16
+ | **MSM** | 编写在工作区内的可执行小工具(一个脚本 + 一行注册)。AI 通过 `msm("名字", ["参数"])` 调用它们 |
17
+ | **SESSION.md** | 工作区内的"工作日志"。AI 将目标、决定、进度写入其中;中断后再启动即从此处继续 |
18
18
 
19
19
  ---
20
20
 
21
- ## 1. 它到底解决什么问题
21
+ ## 1. 它解决什么问题
22
22
 
23
- 不吹概念,直接说四个每天都会遇到的麻烦:
23
+ 直接给出四个日常场景的对照:
24
24
 
25
- | 麻烦 | 没有它 | 有了它 |
25
+ | 场景 | 未安装 | 安装后 |
26
26
  |---|---|---|
27
- | **AI 干到一半忘了自己在干什么** | 上下文一满,之前的目标、决定全丢,你得重讲一遍 | 每个工作区有一本工作日志,AI 每推进一段就写进去;上下文满了就"换载体"重来,日志还在原地,接着干 |
28
- | **AI 到处乱翻、乱改文件** | 它能读你整台机器的文件,包括密钥 | 工作区有围墙:墙内随便用,墙外一律拒绝;密钥文件连"读"都读不到 |
29
- | **出门在外想用** | 只能坐在那台电脑前 | 自带一个带登录的网页入口(密码或手机验证码二选一),手机也能用 |
30
- | **家人想用微信问点事** | 得教他们装软件、开电脑 | 扫一次码把微信接上,家人在微信里说话,AI 用你定义的人格回话 |
27
+ | **AI 中途遗忘自身目标** | 上下文一满,先前的目标与决定全部丢失,须重新交代一遍 | 每个工作区有一本工作日志,AI 每推进一段即写入;上下文满则"更换载体"重来,日志留在原地,工作继续 |
28
+ | **AI 越界读取与修改文件** | 它可读取整台机器的文件,包括密钥 | 工作区有围墙:墙内可用,墙外一律拒绝;密钥文件连"读"都不可达 |
29
+ | **外出使用** | 只能坐在那台电脑前 | 自带带登录的网页入口(密码或手机验证码二选一),手机可用 |
30
+ | **家人经微信提问** | 须教他们安装软件、开启电脑 | 扫一次码接入微信后,家人在微信中发言,AI 以配置的人格回话 |
31
31
 
32
32
  ---
33
33
 
34
34
  ## 2. 快速开始(2 分钟)
35
35
 
36
- 前置:Node ≥ 20(或 bun)、DSH 0.1.7 或 0.2.0 任一发布线。
36
+ 需要 Node ≥ 20(或 bun),以及 DSH 0.1.7 或 0.2.0 任一发布线。
37
37
 
38
38
  ```bash
39
39
  # 1. 装插件(自动加入 DSH 的 web profile)
@@ -50,7 +50,7 @@ dsh web
50
50
 
51
51
  卸载:`dsh plugin --profile web remove @shgroup/dsh-serenity-hooks`
52
52
 
53
- 从源码装(自己改代码时用):
53
+ 从源码安装(改代码时使用):
54
54
 
55
55
  ```bash
56
56
  git clone https://github.com/tellmewhattodo/dsh-serenity-plugin.git
@@ -58,92 +58,92 @@ cd dsh-serenity-plugin
58
58
  dsh plugin --profile web add link:$(pwd)/hooks/dsh-serenity-hooks
59
59
  ```
60
60
 
61
- > ⚠️ 别用 `dsh plugin add github:...` 这种写法——那个地址指向的是仓库根目录(不是插件包本身),装上了也不会生效。用 npm 或上面的 `link:` 方式。
61
+ > ⚠️ 不得使用 `dsh plugin add github:...`:该地址指向仓库根目录,非插件包本身,安装后不生效。**改用 npm 或上面的 `link:` 方式。**
62
62
 
63
- **安全模式**:点一下网页端胶囊里的 SAFE 滑块,`bash` 就会从 AI 的工具列表里**直接消失**——它根本看不到这个工具。开关是给你用的:AI 看不见、也打不开。(机制细节见 [§3.2](#32-机械约束ai-绕不过去)。)
63
+ **安全模式**:拨动网页端胶囊中的 SAFE 滑块后,`bash` 即从 AI 的工具清单中**移除**——AI 看不到该工具,也无法调用。开关归使用者:AI 看不见、也打不开。(机制细节见 [§3.2](#32-机械约束ai-绕不过去)。)
64
64
 
65
65
  ---
66
66
 
67
- ## 3. 装完之后你多了什么
67
+ ## 3. 安装后新增的能力
68
68
 
69
69
  ### 3.1 十四个工具(其中三个按条件出现)
70
70
 
71
- | 工具 | 干什么 | 什么时候用 |
71
+ | 工具 | 功能 | 使用场景 |
72
72
  |---|---|---|
73
- | `container_fs` | 在工作区里管文件:列目录、找文件、复制、移动、新建、追加、在文件管理器里打开 | 需要看/整理工作区里的文件时 |
74
- | `container_trajectory` | **一条轨迹**:它的身体(SESSION.md)+ 它的时间轴。建/看/切换/原地重建之外,还能登记**未来唤醒**与**即时递话** | 任何多步骤的活儿,第一步就是它;想让 AI 未来某刻自动接着干也用它 |
75
- | `dashboard` | 仪表盘:工作区健康检查(三项)、当前时间、等待 | 进工作区先自查一下;等外部服务时用 |
76
- | `container_git` | git 操作:status / commit / push / log / pull / diff | 提交和推送代码;它绝不自动强推 |
77
- | `msm` | 小工具执行入口:`msm("名字", ["参数"])`;名字记不全就给候选;`inspect=true` 看用法 | 调用工作区里注册的任何小工具 |
78
- | `praxis` | 按需给 AI 注入四套"做事方法":输出自检(eap)、设计对齐(neat)、认知连续性(cce)、本体工程(ontology) | 要它把话说清楚 / 先对齐再动手 / 动手前先把领域结构显式化时 |
79
- | `ontology` | 本体工程**引擎**(能跑的那个):读 `.ttl` 本体文件,做结构校验、生成摘要、查"声明与实况是否一致"、出语义审查提示词、出合规清单,还能写一份新本体模板 | 想给某个领域建/校验本体时。⚠️ 与 `praxis ontology` 是**同一领域的两个面**:那个给**方法文本**(怎么建模),这个**真去检查**。路径必须在工作区内 |
80
- | `serenity-skill-creator` | 增强型技能标准(serenity-skill)的创建器:`guide` 编写方法 / `create` 生成骨架(基础链路径由它算)/ `check` 结构体检(三态可分辨:已建模通过 · 普通技能 · 建模了但没查成)/ `review` 逐条合规问题清单 / `index` 预览**模型实际会看到**的参考件清单 / `status` 全容器一览 | 新建或改造技能、给技能建本体、想知道"模型到底看不看得见我那些参考件"时 |
81
- | `handyman` | 杂工:派一个便宜模型的助手干活。**默认模式(foreground)**= 一次串行委派、拿回结果;**background 模式**= 循环干活直到完成(完成码校验 / 轮次上限 / 自动重启 / 进度文件),也可一次派多个并行 | 大批量、重复性的活(扫描几十个技能、逐用例回归) |
82
- | `localstore` | 存密钥和配置(凭据、偏好两个命名空间) | API key、密码集中放一处,不进 git |
83
- | `container_admin` | 机务舱:管理子角色、管理小工具注册表、查看全部配置 | 定义"子角色"、注册新小工具、改配置时 |
84
- | `im-bridge` | 给 IM 联系人发消息(目前是微信):发文本、发文件、查已配置联系人、查通道状态。每次成功发送自动进工作区的消息记录 | 想让 AI 主动给家人/同事发消息(见 §6.2)。**条件出现**:只在工作区配了微信桥时才可见 |
85
- | `acc-diag` | ACC 运行态诊断:一次调用出全报告——当前有多少会话活着、各自属于哪个工作区、唤醒时钟的武装态与 tick 次数、唤醒登记表的每一条 | **ACC 维护者专用**。**条件出现**:默认对所有工作区隐藏,只有在工作区配置里点名(`exclusiveTools`)才出现 |
86
- | `diagram` | 画图:AI 给一段**标签式源码**,插件**在进程内**把它画成 PNG 并**贴进对话**——不启浏览器、不截图、正常路径不落文件。坐标 = 画布像素、y 向下;写错的图元逐条报错并跳过,其余照画;自带四项体检(块重叠 / 标签溢出 / 悬空端点 / 线压字),**只告警不拦图** | 想把关系图/示意图直接放进对话时。**条件出现**:实验性 demo,**默认关**(关着时这个工具**根本不注册**,AI 看不到它、不占上下文);开关在设置面板「工具」组,拨动即时生效。中英文与常用符号都能画,是因为字体随插件内置(约 5 MB) |
87
-
88
- > **改过名**(旧名已彻底停用,无兼容别名;老会话里看到旧名,**一律取所在那一组的末项**):
73
+ | `container_fs` | 在工作区内管理文件:列目录、查找、复制、移动、新建、追加、在文件管理器中打开 | 需要查看或整理工作区内文件时 |
74
+ | `container_trajectory` | **一条轨迹**:其身体(SESSION.md)+ 其时间轴。除建/看/切换/原地重建外,还可登记**未来唤醒**与**即时递话** | 任何多步骤工作,第一步即调用它;需要 AI 在未来某刻自动继续时也用它 |
75
+ | `dashboard` | 仪表盘:工作区健康检查(三项)、当前时间、等待 | 进入工作区后先行自查;等待外部服务时使用 |
76
+ | `container_git` | git 操作:status / commit / push / log / pull / diff | 提交与推送代码;它绝不自动强推 |
77
+ | `msm` | 小工具执行入口:`msm("名字", ["参数"])`;名字记不全时返回候选;`inspect=true` 查看用法 | 调用工作区内已注册的任何小工具 |
78
+ | `praxis` | 按需向 AI 注入四套"做事方法":输出自检(eap)、设计对齐(neat)、认知连续性(cce)、本体工程(ontology) | 需要它把话说清楚 / 先对齐再动手 / 动手前先把领域结构显式化时 |
79
+ | `ontology` | 本体工程**引擎**(可执行者):读取 `.ttl` 本体文件,执行结构校验、生成摘要、检查"声明与实况是否一致"、输出语义审查提示词、输出合规清单,并可写入一份新本体模板 | 需要为某个领域建立或校验本体时。⚠️ 与 `praxis ontology` 是**同一领域的两个面**:前者提供**方法文本**(如何建模),后者**实际执行检查**。路径必须在工作区内 |
80
+ | `serenity-skill-creator` | 增强型技能标准(serenity-skill)的创建器:`guide` 编写方法 / `create` 生成骨架(基础链路径由它算)/ `check` 结构检查(三态可分辨:已建模通过 · 普通技能 · 建模了但检查未执行)/ `review` 逐条合规问题清单 / `index` 预览**模型实际会看到**的参考件清单 / `status` 全容器一览 | 新建或改造技能、为技能建本体、需要确认"模型究竟能否看到指定参考件"时 |
81
+ | `handyman` | 杂工:委派一个低成本模型的助手执行任务。**默认模式(foreground)**= 一次串行委派、取回结果;**background 模式**= 循环执行直至完成(完成码校验 / 轮次上限 / 自动重启 / 进度文件),也可一次委派多个并行 | 大批量、重复性的工作(扫描数十个技能、逐用例回归) |
82
+ | `localstore` | 存储密钥与配置(凭据、偏好两个命名空间) | API key、密码集中放一处,不进 git |
83
+ | `container_admin` | 机务舱:管理子角色、管理小工具注册表、查看全部配置 | 定义"子角色"、注册新小工具、修改配置时 |
84
+ | `im-bridge` | 向 IM 联系人发消息(目前为微信):发文本、发文件、查已配置联系人、查通道状态。每次成功发送自动写入工作区的消息记录 | 需要 AI 主动给家人/同事发消息时(见 §6.2)。**条件出现**:仅在工作区配置了微信桥时可见 |
85
+ | `acc-diag` | ACC 运行态诊断:一次调用输出全报告——当前活跃会话数、各自所属工作区、唤醒时钟的武装态与 tick 次数、唤醒登记表的每一条 | **ACC 维护者专用**。**条件出现**:默认对所有工作区隐藏,仅在工作区配置中点名(`exclusiveTools`)时出现 |
86
+ | `diagram` | 绘图:AI 给出一段**标签式源码**,插件**在进程内**将其绘制为 PNG 并**贴入对话**——不启动浏览器、不截图、正常路径不落文件。坐标 = 画布像素、y 向下;写错的图元逐条报错并跳过,其余照常绘制;自带四项检查(块重叠 / 标签溢出 / 悬空端点 / 线压字),**只告警不拦图** | 需要把关系图/示意图直接放进对话时。**条件出现**:实验性 demo,**默认关**(关闭时该工具**根本不注册**,AI 看不到它、不占上下文);开关在设置面板「工具」组,拨动即时生效。中英文与常用符号均可绘制,因字体随插件内置(约 5 MB) |
87
+
88
+ > **更名记录**(旧名已彻底停用,无兼容别名;旧会话中出现旧名时,**一律取所在那一组的末项**):
89
89
  > `cc_fs` → `container_fs` · `cc_git` → `container_git` · `session`+`session_rebuild` → `logbook` → `trajectory` → **`container_trajectory`**(今名) ·
90
90
  > `acc_kit` → `dashboard` · `acc_msm` → `msm`(执行)+ `container_admin`(管理) · `eap`/`neat`/`cce` → `praxis` ·
91
91
  > `skiff_admin` → `container_admin role` · `autopilot-trajectory` → `trajectory` → **`container_trajectory`**(今名)。
92
92
 
93
93
  ### 3.2 机械约束(AI 绕不过去)
94
94
 
95
- 这些不是"提示词里劝它别做",而是**机制上做不到**:
95
+ 这些不依赖提示词劝阻,而是**机制上无法执行**:
96
96
 
97
- | 约束 | 你会看到的效果 | 为什么这样做 |
97
+ | 约束 | 可观察到的效果 | 设计理由 |
98
98
  |---|---|---|
99
- | **安全模式** | bash 从工具列表里消失(每一步都同步一次),就算它想调也会被兜底拦下 | 走注册过的小工具,比让 AI 自己拼 shell 命令可靠得多 |
100
- | **工作区围墙** | 墙内什么都能干,墙外一律拒绝(连路径都解析不出去) | AI 不该碰工作区之外的东西 |
101
- | **黑名单 / 治理文件** | 可配黑名单;`.serenity` 这类治理文件禁止 AI 写 | 防止 AI 把自己所在的"地基"改坏 |
102
- | **密钥文件守卫** | `localstore.json` 对**所有**工具拒绝(包括 read/grep/glob) | 密钥值在结构上就出不来 |
103
- | **对外输出守卫** | 对外面的会话(子角色 / ACP / 重建会话)如果答出敏感词,会被打回重答,并告诉它命中了哪个词、该怎么改 | 外面的人不该看到内部机制 |
104
- | **轨迹提醒** | 做久了会提醒 AI"把进度写回工作日志",并要求它回一个确认码 | 提醒是机制,不是靠自觉 |
105
- | **工作日志体积提醒** | 工作日志(SESSION.md)超过 200KB 时提醒 AI"停下来重写一遍",并附四条重写原则(保留骨架 / 细节挪到附件文件 / 该合并的合并 / 其余你自己判断) | 日志越写越厚就没人读得完;重写比堆积便宜。阈值按工作区可调(`sessionKeeper.sessionMdMaxKB`,0 = 关) |
106
- | **重建前交接** | 要重建上下文时,会要求 AI 先把"手头做到哪了 / 还差什么 / 下一步做什么"写进**本轨迹目录下的 `REBUILD-TODO.md`**(固定文件名);重建后的它第一件事就是去读这个文件接着干 | 上下文被清空,但手头的事不能丢。这张便签是**只用一次的交界材料**:无格式义务、随时可丢;超过 10 KB 会提醒它清理(`SCRATCH PRUNE`,整份删掉都可以) |
99
+ | **安全模式** | bash 从工具列表里消失(每一步都同步一次),即使调用也会被兜底拦下 | 走已注册的小工具,比让 AI 自行拼接 shell 命令可靠 |
100
+ | **工作区围墙** | 墙内可用,墙外一律拒绝(路径无法解析) | AI 不应接触工作区之外的内容 |
101
+ | **黑名单 / 治理文件** | 黑名单可配置;`.serenity` 等治理文件禁止 AI 写入 | 防止 AI 破坏自身所在的"地基" |
102
+ | **密钥文件守卫** | `localstore.json` 对**所有**工具拒绝(包括 read/grep/glob) | 密钥值在结构上无法外流 |
103
+ | **对外输出守卫** | 对外向会话(子角色 / ACP / 重建会话)若答出敏感词,会被打回重答,并告知命中的词与修改方向 | 外部使用者不应看到内部机制 |
104
+ | **轨迹提醒** | 持续一段时间后会提醒 AI"把进度写回工作日志",并要求它回一个确认码 | 提醒是机制,不依赖自觉 |
105
+ | **工作日志体积提醒** | 工作日志(SESSION.md)超过 200KB 时提醒 AI"停下重写",并附四条重写原则(保留骨架 / 细节移至附件文件 / 可合并的合并 / 其余自行判断) | 日志持续增厚则无人读得完;重写成本低于堆积。阈值按工作区可调(`sessionKeeper.sessionMdMaxKB`,0 = 关) |
106
+ | **重建前交接** | 重建上下文前,要求 AI 先把"手头做到哪了 / 还差什么 / 下一步做什么"写入**本轨迹目录下的 `REBUILD-TODO.md`**(固定文件名);重建后的 AI 首先读取该文件并继续 | 上下文被清空,但在办的事不能丢。该便签是**只用一次的交界材料**:无格式义务、随时可丢;超过 10 KB 会提醒清理(`SCRATCH PRUNE`,整份删除亦可) |
107
107
 
108
108
  ### 3.3 对外的入口
109
109
 
110
- | 入口 | 默认端口 | 给谁用 |
110
+ | 入口 | 默认端口 | 使用者 |
111
111
  |---|---|---|
112
- | DSH 主界面 | 3080 | 你自己在本机用(插件不碰这个端口,也不起这个监听器) |
112
+ | DSH 主界面 | 3080 | 本机自用(插件不碰这个端口,也不起这个监听器) |
113
113
  | **网页登录入口** | 3081 | 外部/手机访问完整界面:登录后反向代理到 3080,可配工作区白名单 |
114
- | **微信主动发送入口** | 3082(只绑 127.0.0.1) | 工作区外的脚本/集成用它给微信发消息(公网到不了,所以不需要密钥)。工作区里的 AI 不走这个端口,直接用 `im-bridge` 工具 |
115
- | **子角色调试页** | 3099(只绑 127.0.0.1) | 你调试"子角色"时用,能切换工作区、看对话轨迹 |
114
+ | **微信主动发送入口** | 3082(只绑 127.0.0.1) | 工作区外的脚本/集成用它给微信发消息(公网不可达,所以不需要密钥)。工作区内的 AI 不走这个端口,直接使用 `im-bridge` 工具 |
115
+ | **子角色调试页** | 3099(只绑 127.0.0.1) | 调试"子角色"时使用,可切换工作区、查看对话轨迹 |
116
116
  | **ACP + 对外问答页** | 3100(只绑 127.0.0.1) | 程序化接入(JSON-RPC)+ 给别人用的问答页(key 认证,只返回答案,不返回内部轨迹) |
117
117
  | **微信桥** | 无需端口(出站长轮询) | 家人在微信里直接和 AI 说话 |
118
118
 
119
- > 3081 / 3099 / 3100 **默认关**(要自己开);3082 **默认开**(微信桥启用时才有意义)。默认只监听 127.0.0.1 的入口,要暴露到公网由你自己决定(隧道 / 反代 / 端口映射都行),插件不绑定任何特定做法。
119
+ > 3081 / 3099 / 3100 **默认关**(须自行开启);3082 **默认开**(微信桥启用时才有意义)。默认只监听 127.0.0.1 的入口,如需暴露到公网,由使用者自行决定方式(隧道 / 反代 / 端口映射都行),插件不绑定任何特定做法。
120
120
 
121
- ### 3.4 省你一步:用 opencode 的模型
121
+ ### 3.4 自动配置:用 opencode 的模型
122
122
 
123
- 想在 DSH 里用 opencode 的网关(`opencode.ai/zen`),本来除了配路由还得手抄一串请求头——
123
+ 要在 DSH 里用 opencode 的网关(`opencode.ai/zen`),本来除了配路由还得手抄一串请求头——
124
124
  这些头是 opencode 用来做**会话亲和路由**的,少写一个 `x-opencode-session`,`/zen/go` 面就直接 400 拒绝。
125
- **插件装好就自动配**,这一步你不用管:
125
+ **插件装好就自动配**,无需手工操作:
126
126
 
127
- | 你的情况 | 插件做什么 |
127
+ | 使用情况 | 插件行为 |
128
128
  |---|---|
129
- | 已经配了 opencode 路由,但缺头 | 只补缺的那几个;**你手写过的值一律不动**(头名不分大小写,`X-Title` 和 `x-title` 一样算数) |
129
+ | 已经配了 opencode 路由,但缺头 | 只补缺的那几个;**手写过的值一律不动**(头名不分大小写,`X-Title` 和 `x-title` 一样算数) |
130
130
  | 一个 opencode 路由都没有,但环境里有 `OPENCODE_API_KEY` | 自动建 `opencode-go` 路由并带全头(没有 key 的人不受影响,不会平白多出一组模型) |
131
131
 
132
132
  - **只管"会话族"的头**:`x-opencode-session` / `X-Session-ID` / `x-opencode-client` / `x-opencode-project`。
133
- 前两个名字是**同一个值的两个别名**——你写了其中一个,就用**你的值**补上另一个,不会出现两个互相打架的会话 id
133
+ 前两个名字是**同一个值的两个别名**——写了其中一个,即以**该值**补上另一个,不会出现两个互相冲突的会话 id
134
134
  - **不冒充 opencode 官方客户端**:`X-Title` / `HTTP-Referer` 这类"身份头"只在免费档的滥用判别里起作用,
135
- 插件不注入(替你骗额度不是我们该做的事,付费面本来也不需要它们);`User-Agent` 是 DSH 的保留名,想注也注不了
135
+ 插件不注入(代使用者骗取额度不是本插件该做的事,付费面本来也不需要它们);`User-Agent` 是 DSH 的保留名,想注也注不了
136
136
  - **会话标识是固定的**(`dsh-serenity`):DSH 的请求头在路由解析时一次算好,只能给静态值。
137
- 好处是同一台机器的请求稳定落同一个上游(对缓存友好);代价是做不到"按会话分区"
138
- - **配的是你自己的文件**:写入 DSH 的 settings(`llm-pi-ai.providers.<路由>.headers`),随时可改可删。
139
- 不想要这个自动配置,就把本插件的 `opencodeProvider.autoConfigure` 关掉(关掉后一切回到手抄)
140
- - **密钥不碰**:插件只补路由和头,`OPENCODE_API_KEY` 放环境变量即可
137
+ 优势是同一台机器的请求稳定落同一个上游(对缓存友好);代价是无法做到"按会话分区"
138
+ - **写入的是使用者自己的文件**:写入 DSH 的 settings(`llm-pi-ai.providers.<路由>.headers`),随时可改可删。
139
+ 不需要这个自动配置时,关闭本插件的 `opencodeProvider.autoConfigure`(关闭后一切回到手抄)
140
+ - **不接触密钥**:插件只补路由和头,`OPENCODE_API_KEY` 放环境变量即可
141
141
 
142
142
  ---
143
143
 
144
144
  ## 4. 一个工作区长什么样
145
145
 
146
- 工作区就是一个普通目录,加一个标记文件:
146
+ 工作区是一个普通目录,外加一个标记文件:
147
147
 
148
148
  ```
149
149
  my-workspace/ ← 工作区根目录(放一个 .serenity 就成)
@@ -163,29 +163,29 @@ my-workspace/ ← 工作区根目录(放一个 .serenity
163
163
  └── files_from_user/
164
164
  ```
165
165
 
166
- > 🔴 **技能的两层披露**:助手看到的 skill 目录**那一行就带参考件文件名**(插件按文件树即时生成 ⇒ 你新增一个文件它自己就更新,**不用手写**);
167
- > 真要用时它才去 `read` 打开正文 —— **正文不进上下文,除非它自己去取**。
166
+ > 🔴 **技能的两层披露**:助手看到的 skill 目录**那一行即带参考件文件名**(插件按文件树即时生成 ⇒ 新增一个文件它自己就更新,**不用手写**);
167
+ > 真要用时它才去 `read` 打开正文 —— **正文不进上下文,除非助手自己去取**。
168
168
 
169
169
  ---
170
170
 
171
- ## 5. 能拿它做什么(12 个真实用例)
171
+ ## 5. 12 个真实用例
172
172
 
173
- > 下面这些都在真实部署里跑着。地址、账号、路径都做了泛化。
173
+ > 以下用例都在真实部署里运行。地址、账号、路径均作了泛化。
174
174
 
175
- | # | 你想干的事 | 实际怎么走 |
175
+ | # | 目标 | 实际路径 |
176
176
  |---|---|---|
177
177
  | 1 | **长期项目不断线** | `container_trajectory create` 建轨迹 → 每推进一段写进去 → 中断后 `container_trajectory use` 接上 → 上下文满了 `container_trajectory rebuild` 原地重建并自动继续 |
178
178
  | 2 | **批量同步代码** | 当前仓库 `container_git commit/push`;多个子仓库一条命令全同步(自动提交 + 推送) |
179
179
  | 3 | **做一集字幕** | 搜片源 → 下载 → Whisper 转写 → 翻译 → 双语 SRT → 机械质检(7 项)→ 推送订阅/邮件 |
180
- | 4 | **服务器巡检** | 一条命令出 CPU/内存/GPU/容器/服务报告;重启容器也在同一条白名单通道里 |
180
+ | 4 | **服务器巡检** | 一条命令输出 CPU/内存/GPU/容器/服务报告;重启容器也在同一条白名单通道里 |
181
181
  | 5 | **内网服务定位** | 仓库全景(分类/技术栈/关联)+ 设备端口扫描 |
182
182
  | 6 | **家庭财务** | 结构化记录资产/负债/收支/预算,随时查询汇总;房贷利率对比这类宏观跟踪 |
183
183
  | 7 | **家人档案** | 成员资料统一维护,工作区是唯一真相源 |
184
- | 8 | **想法随手记** | 想到什么就聊,AI 访谈式问清 → 结构化归档 → 定期回顾你的思考模式 |
184
+ | 8 | **想法随手记** | 想到什么就聊,AI 访谈式问清 → 结构化归档 → 定期回顾思考模式 |
185
185
  | 9 | **手机/外出使用** | 浏览器打开 `http://内网地址:3081` → 输密码或 6 位验证码 → 直接用完整界面 |
186
186
  | 10 | **粘贴资料自动处理** | 粘图片 → 自动落盘 → 视觉模型识别(快递单/截图/图表);粘 PDF/压缩包 → 自动落盘 → 提取文本/解压/读表格 |
187
187
  | 11 | **微信里用 AI** | 面板扫一次码 → 家人在微信发消息(文字/语音/图片/文件)→ 路由到指定子角色 → 回复回到微信 |
188
- | 12 | **定时自己干活** | 给某条轨迹放一段 `continuous-re-occurrence.ts`(CRO,见 §6.5)→ 调度器每 5 分钟问它一次"现在该不该醒、醒了说什么"→ 由**程序**决定何时接着干。也可以让轨迹在每轮结束时自己排下一轮 |
188
+ | 12 | **定时自动工作** | 给某条轨迹放一段 `continuous-re-occurrence.ts`(CRO,见 §6.5)→ 调度器每 5 分钟问它一次"现在该不该醒、醒了说什么"→ 由**程序**决定何时接着干。也可以让轨迹在每轮结束时自己排下一轮 |
189
189
 
190
190
  **典型一天**:
191
191
 
@@ -204,7 +204,7 @@ my-workspace/ ← 工作区根目录(放一个 .serenity
204
204
 
205
205
  ### 6.1 网页登录入口(3081)
206
206
 
207
- 插件自己起第二个监听器,请求流程是:
207
+ 插件自行启动第二个监听器,请求流程如下:
208
208
 
209
209
  ```
210
210
  外部浏览器 → http://内网IP:3081
@@ -218,42 +218,42 @@ my-workspace/ ← 工作区根目录(放一个 .serenity
218
218
 
219
219
  ### 6.2 微信桥
220
220
 
221
- 工作区级配置(`.opencode/serenity.json` 的 `weixin` 段),**凭据放在工作区的 `localstore.json`**(不落 git 明文)。
222
- DSH 一个进程可以同时带多个工作区,每个工作区各自对接自己的微信。
221
+ 工作区级配置(`.opencode/serenity.json` 的 `weixin` 段),**凭据放在工作区的 `localstore.json`**(不以明文进入 git)。
222
+ 一个 DSH 进程可以同时承载多个工作区,每个工作区各自对接自己的微信。
223
223
 
224
224
  - **扫码绑定**:设置面板 → 微信桥 → 选工作区 → 扫码(手机微信确认)→ 机器人 token 自动写入凭据
225
225
  - **多账号**:每个账号独立扫码、独立移除
226
- - **能收什么**:文字、语音(微信服务端自带转写,无需额外识别)、图片、文件
227
- (图片和文件会从微信 CDN 下载并解密,落到 `_tmp/weixin-inbound/`,再把路径告诉 AI)
226
+ - **接收内容**:文字、语音(微信服务端自带转写,无需额外识别)、图片、文件
227
+ (图片和文件会从微信 CDN 下载并解密,落到 `_tmp/weixin-inbound/`,随后把路径告知 AI)
228
228
  - **正在输入**:处理期间微信会显示"正在输入…"
229
- - **回复干净**:自动剥掉思考过程,微信只看到正文
230
- - **记得住**:同一个微信号对应固定会话,重启后恢复历史,不会"失忆"
229
+ - **回复精简**:自动剥掉思考过程,微信只看到正文
230
+ - **会话保持**:同一个微信号对应固定会话,重启后恢复历史,不会"失忆"
231
231
  - **路由**:微信号 → 子角色(精确匹配优先,`*` 兜底)
232
232
  - **主动发消息**(v1.31.0):用 `im-bridge` 工具,AI 自己就能发——
233
233
  `im-bridge({channel:"weixin", action:"send", user:"yh", text:"内容"})`
234
234
  (发文件:`action:"send-file"` + `file:"<工作区内的路径>"`,可加 `caption`)。
235
- 没有"目标工作区"参数,所以它**发不错容器**;发出的消息会自动被记录(可见性见 §3.1)。
236
- - **让 AI 自己决定怎么回**(v1.30.10):配置 `"weixin": { "autoReplyWithLastMessage": false }`
237
- 后,插件不再自动把 AI 最后那段话转给用户,而是每轮告诉它"你必须自己发",并附上一条可直接照抄的 `im-bridge` 调用。
238
- 适合需要过程汇报、想分多条发、或者该安静就安静的角色。默认 `true`(保持原行为)。
235
+ 没有"目标工作区"参数,因此它**发不错容器**;发出的消息会自动被记录(可见性见 §3.1)。
236
+ - **由 AI 自行决定回复方式**(v1.30.10):配置 `"weixin": { "autoReplyWithLastMessage": false }`
237
+ 后,插件不再自动把 AI 最后那段话转给用户,而是每轮告知它"你必须自己发",并附上一条可直接照抄的 `im-bridge` 调用。
238
+ 适用于需要过程汇报、想分多条发、或者该安静就安静的角色。默认 `true`(保持原行为)。
239
239
  该发却没发时,插件会**打回提醒**(最多 2 次);还是不发送,可以再开
240
240
  `"fallbackOnNoSend": true` 让插件兜底把那轮的话转给用户(记录为 `source: "reply-fallback"`),
241
241
  保证"消息不丢"。
242
- - **消息记录**:配一个 `weixin.hook` 脚本,每收/发一条消息就把事件(JSON)喂给它,存哪里由你决定。
242
+ - **消息记录**:配一个 `weixin.hook` 脚本,每收/发一条消息就把事件(JSON)交给它,存储位置自行决定。
243
243
  记录里 `source: "reply"` 表示"回复用户",`source: "proactive"` 表示"AI 主动发起",
244
244
  `source: "reply-fallback"` 表示"AI 没发、插件兜底发的"。
245
245
  - **排障**:`msm("weixin-doctor", ["status"|"diag"|"verify"|"guide"])`
246
246
 
247
247
  ### 6.3 子角色(Skiff)
248
248
 
249
- 你可以从一个"什么都能干"的助手身上,切出一个**能力受限的小角色**——不只是问答,也可以带操作能力:
249
+ 可以从一个"什么都能干"的助手身上,切出一个**能力受限的小角色**——不只是问答,也可以带操作能力:
250
250
 
251
251
  ```jsonc
252
252
  {
253
253
  "skiff": {
254
254
  "roles": {
255
255
  "qa": {
256
- "model": "provider/model", // 这个角色单独用哪个模型
256
+ "model": "provider/model", // 该角色单独用哪个模型
257
257
  "msms": ["web-search", "vlm-describe"], // 它能调哪些小工具
258
258
  "tools": ["read", "grep", "glob"], // 它能用哪些平台工具
259
259
  "systemPromptFile": "roles/qa.md" // 它的人格与边界(也可以直接内联)
@@ -278,20 +278,20 @@ DSH 一个进程可以同时带多个工作区,每个工作区各自对接自
278
278
 
279
279
  **定时唤醒**:用 `container_trajectory send-later` 登记一条"唤醒" = 未来某时刻 + 一条消息——可以给自己预约,也可以唤醒别的轨迹;落在工作区内的 `AGENT_SESSIONS/wake-registry.json`(可读可审计),到点由中心调度器投递,**不阻塞、不等待、也不回执**。
280
280
 
281
- **即时投递**:用 `container_trajectory send-now` 把一条消息**现在**就递过去,并且**不排队**——目标在内存里且**正在跑轮次**,就 `steer` **当场注入当前轮**;目标空闲就**立即起一轮**;目标不在内存里就**冷载入后投递**(**等效于直接唤醒**,但**不等调度器的 5 分钟节拍**)。它**有同步回执**(告诉你走了 live 还是冷载入),**不落注册表**(那张表专管"未来时刻")。
281
+ **即时投递**:用 `container_trajectory send-now` 把一条消息**现在**就递过去,并且**不排队**——目标在内存里且**正在跑轮次**,就 `steer` **当场注入当前轮**;目标空闲就**立即起一轮**;目标不在内存里就**冷载入后投递**(**等效于直接唤醒**,但**不等调度器的 5 分钟节拍**)。它**有同步回执**(告知走了 live 还是冷载入),**不落注册表**(那张表专管"未来时刻")。
282
282
 
283
283
  - 两者只差两处:**时刻**(现在 / 未来)与**回执**(有 / 无)——"预约"天生是 fire-and-forget(不可回收、不回执),"递话"则是一次调用一次答复。各自语义干净,不把两种语义塞进同一个动作(🔴 更名:原名 `wake-later` / `send-message`,现名 **`send-later` / `send-now`**——族名取共享词干 `send-`,轴取 `-later`/`-now`)
284
- - ⚠️ **回执只到"已注入 / 已起轮"**:它**不表示**目标已经执行或答复。要确证"目标真的动了",得看它自己的 `SESSION.md`(**不得凭回执结案**)
285
- - ⚠️ **唯一的例外路径**:`steer` 不可用时**退回排队**(fail-safe:**宁可排队,不可静默丢消息**)——此时回执文案写明"steer 不可用 ⇒ 退回 followup"。**`send-later` 不受影响**:预约的本职是"到点唤起",在跑时排队不打断当前轮是它被实证验收过的行为
284
+ - ⚠️ **回执只到"已注入 / 已起轮"**:它**不表示**目标已经执行或答复。要确证"目标真的动了",须查看它自己的 `SESSION.md`(**不得凭回执结案**)
285
+ - ⚠️ **唯一的例外路径**:`steer` 不可用时**退回排队**(fail-safe:**宁可排队,不可静默丢消息**)——此时回执文案写明"steer 不可用 ⇒ 退回 followup"。**`send-later` 不受影响**:预约的本职是"到点唤起",在跑时排队不打断当前轮,这一行为已经过实证验收
286
286
  - **目标没打开也能唤醒**:冷载入不了则条目留在登记表里并记下原因,**不静默丢弃**
287
287
  - **"周期"归工作区自己**:要一轮接一轮,就由**收到唤醒的那条轨迹**在每轮结束时再排一次下一轮——ACC 只提供"到点投递一条消息"这个原语,不替工作区决定节拍(焦点、节拍、偏见都由工作区自定;任意条轨迹并行、互不干扰)
288
- - **轨迹可以带上 skill**(两种写法,**取并集**:容器级在前、轨迹级追加、同名去重):① **一处声明、全容器生效**——在 `.opencode/serenity.json` 写 `trajectory.skills: [名字, …]`(底座),**本工作区的每条轨迹**被绑定期间都注入这些 skill 的全文(**连子角色会话也算**);② **只给这一条**——在它的 `SESSION.md` 顶部 frontmatter 写 `skills: [名字, …]`(这条额外的)。⚠️ 是"**绑定期间一直供着**"而非"`use` 时灌一次"——改了配置或 frontmatter**立即生效**(每请求重新求值,不缓存),也不随对话压缩消失;而 `create` 只新建、**不夺走当前绑定** ⇒ 新轨迹要**显式 `use`** 才挂上。skill 名来自工作区数据,**先过安全校验才会用于拼路径**,找不到会在提示里明说"缺失"而**不静默跳过**;⚠️ **重写 `SESSION.md` 时务必原样保留顶部 frontmatter**(抹掉 = 静默撤销该轨迹的声明)
288
+ - **轨迹可以带上 skill**(两种写法,**取并集**:容器级在前、轨迹级追加、同名去重):① **一处声明、全容器生效**——在 `.opencode/serenity.json` 写 `trajectory.skills: [名字, …]`(底座),**本工作区的每条轨迹**被绑定期间都注入这些 skill 的全文(**连子角色会话也算**);② **只给这一条**——在它的 `SESSION.md` 顶部 frontmatter 写 `skills: [名字, …]`(这条额外的)。⚠️ 是"**绑定期间一直供给**"而非"`use` 时注入一次"——改了配置或 frontmatter **立即生效**(每请求重新求值,不缓存),也不随对话压缩消失;而 `create` 只新建、**不夺走当前绑定** ⇒ 新轨迹要**显式 `use`** 才挂上。skill 名来自工作区数据,**先过安全校验才会用于拼路径**,找不到会在提示里明说"缺失"而**不静默跳过**;⚠️ **重写 `SESSION.md` 时务必原样保留顶部 frontmatter**(抹掉 = 静默撤销该轨迹的声明)
289
289
 
290
- #### CRO —— 让轨迹**自己判断什么时候该被叫醒**
290
+ #### CRO —— 由轨迹**自行判断何时该被叫醒**
291
291
 
292
- **问题**:上面那两条都要求**先算好一个时刻**("3 点叫我")。可**该不该醒往往不是时间说了算**:某条轨迹应该在"天亮 + 家里有人 + 非高峰"才醒;已经在干活就不该再叫一次;日志快满了,下次叫它时该**要求它先整理**。
292
+ **问题**:上面那两条都要求**先算好一个时刻**("3 点叫我")。但**该不该醒往往不由时间决定**:某条轨迹应该在"天亮 + 家里有人 + 非高峰"才醒;已经在工作就不该再叫一次;日志快满了,下次叫它时该**要求它先整理**。
293
293
 
294
- **做法**:**让一条轨迹自己带一段程序**,由 ACC 在每次检查时跑它,**由这段程序决定"现在该不该叫我、叫我的时候说什么"**。
294
+ **做法**:**让一条轨迹自己带一段程序**,由 ACC 在每次检查时运行它,**由这段程序决定"现在该不该叫我、叫我的时候说什么"**。
295
295
 
296
296
  | | 内容 |
297
297
  |---|---|
@@ -304,14 +304,14 @@ DSH 一个进程可以同时带多个工作区,每个工作区各自对接自
304
304
 
305
305
  **几条设计上的硬约束**(都不是随便定的):
306
306
 
307
- - 🔴 **ACC 只"起进程",从不 import 你的程序**——进程边界同时挡掉两件事:ACC 不必依赖工作区的**源码路径**(装机版在别处,两条路径就是两个真相源),以及**一个用户程序的语法错会放倒整个容器**
308
- - 🔴 **半成品报错就行**:程序报错 / 超时(60 秒硬超时,超了 kill)/ 输出非法 ⇒ **记一行 + 跳过本轮**——任何失败都不影响既有机制(这条有实测用例钉住,不是口头承诺)
309
- - 🔴 **`reason` 强烈建议填**:改成程序判定之后,"当时为什么叫了"**不再能从时间表重建**(原因在程序肚子里);不写,以后出事无法复现
310
- - **程序想要记住"上次判了什么",得自己记**——写在**自己轨迹目录**里的状态文件(那是它自己的进程状态,ACC 物理上拿不到)。所以**防抖也归程序**:想"别叫太频繁"就自己记时间戳
311
- - ⚠️ **它不自带自测**:指南里给的流程是**先用开发名写**(如 `continuous-re-occurrence.dev.ts`,**不会被启用**)→ 配自测跑绿 → **再改名为正式名**(因为"文件在 = 启用",**改名这个动作就是上线动作**)
307
+ - 🔴 **ACC 只"起进程",从不 import 用户程序**——进程边界同时挡掉两件事:ACC 不必依赖工作区的**源码路径**(装机版在别处,两条路径 = 两个真相源),以及**一个用户程序的语法错会放倒整个容器**
308
+ - 🔴 **半成品报错就行**:程序报错 / 超时(60 秒硬超时,超了 kill)/ 输出非法 ⇒ **记一行 + 跳过本轮**——任何失败都不影响既有机制(这条由实测用例钉住,不是口头承诺)
309
+ - 🔴 **`reason` 强烈建议填**:改成程序判定之后,"当时为什么叫了"**不再能从时间表重建**(原因在程序内部);不写,以后出事无法复现
310
+ - **程序想要记住"上次判了什么",得自己记**——写在**自己轨迹目录**里的状态文件(那是它自己的进程状态,ACC 物理上拿不到)。所以**防抖也归程序**:想"不要叫太频繁"就自己记时间戳
311
+ - ⚠️ **不自带自测**:流程为**先用开发名编写**(如 `continuous-re-occurrence.dev.ts`,不会被启用)→ 自测通过 → **改为正式名**("文件在即启用",**改名即上线动作**)
312
312
 
313
313
  > ⚠️ **历史**:ACC 曾自带一套"周期自唤醒 autopilot",**v1.35.0 起整段退场**(机制、时钟、`container_admin autopilot` 域、面板开关一并删除)。
314
- > 老会话 / 老文档里看到 `container_admin autopilot`、`autopilot-trajectory`、`--auto` 目录后缀、`[Autopilot Trajectory · 唤起]` 等字样,均为**已删除的机制**。
314
+ > 旧会话 / 旧文档里看到 `container_admin autopilot`、`autopilot-trajectory`、`--auto` 目录后缀、`[Autopilot Trajectory · 唤起]` 等字样,均为**已删除的机制**。
315
315
  > CRO 不是它的回归:退场删掉的是**判据内容**(周期节拍 + 提示词),留下的是**调度能力**;CRO 补的是"**在没人醒着的时候判断该不该醒**"。
316
316
 
317
317
  ### 6.6 安全模型
@@ -331,7 +331,7 @@ DSH 一个进程可以同时带多个工作区,每个工作区各自对接自
331
331
 
332
332
  | 层 | 位置 | 放什么 |
333
333
  |---|---|---|
334
- | DSH 原生设置 | DSH 的 settings.yaml(就是设置面板那几项) | 开关与阈值:网关总开关、重建阈值、子角色开关与调试端口、ACP 与问答页开关、**CRO 总闸(`croEnabled`,默认为开)**、**无人值守代理回复(`unattendedEnabled`,默认为关)**、**图工具总闸(默认关)** |
334
+ | DSH 原生设置 | DSH 的 settings.yaml(即设置面板那几项) | 开关与阈值:网关总开关、重建阈值、子角色开关与调试端口、ACP 与问答页开关、**CRO 总闸(`croEnabled`,默认为开)**、**无人值守代理回复(`unattendedEnabled`,默认为关)**、**图工具总闸(默认关)** |
335
335
  | 插件全局文件 | `~/.dsh/serenity-hooks.json`(权限 0600) | 网关账号(scrypt + TOTP)、监听地址与端口、工作区白名单、cookie 安全开关、问答页 key |
336
336
  | 工作区配置 | `.opencode/serenity.json` | 助手模型白名单、日志阈值、安全模式黑名单、子角色、**轨迹级 skill 供给(`trajectory.skills`)**、微信(账号/路由/开关) |
337
337
  | 工作区凭据 | `localstore.json` | 密钥与本地偏好;微信机器人 token 也在这一层 |
@@ -341,11 +341,11 @@ DSH 一个进程可以同时带多个工作区,每个工作区各自对接自
341
341
 
342
342
  ---
343
343
 
344
- ## 8. 上下文快满了怎么办
344
+ ## 8. 上下文将满时的处理
345
345
 
346
- AI 一次能"记住"的内容有上限。满了不用你手动开新会话:
346
+ AI 一次能"记住"的内容有上限。满了不用手动开新会话:
347
347
 
348
- | 机制 | 说人话 |
348
+ | 机制 | 说明 |
349
349
  |---|---|
350
350
  | **工作日志(SESSION.md)** | AI 的"笔记本",永远留在原地。目标、决定、进度都写这儿 |
351
351
  | **原地重建(container_trajectory rebuild)** | 快满时它会提示 AI 主动重建:把这一轮对话清空,但重新注入"你是谁 + 继续 S### 的工作"——**载体换了,活儿接着干**。重建前它会把"手头做到哪了"写进同目录的 `REBUILD-TODO.md`,重建后的它先去读那张便签 |
@@ -354,7 +354,7 @@ AI 一次能"记住"的内容有上限。满了不用你手动开新会话:
354
354
 
355
355
  ---
356
356
 
357
- ## 9. 给插件开发者
357
+ ## 9. 面向插件开发者
358
358
 
359
359
  ```bash
360
360
  pnpm typecheck # 类型检查(node + 浏览器端两套)
@@ -364,7 +364,7 @@ pnpm build # 打包(lib/index.js + client.js)
364
364
 
365
365
  - **开发用小工具**:`scripts/dsh-develop.ts`——typecheck / test / build / status / commit / push / version / bump / deploy / **lockfile** / **host-upgrade** / restart-web / publish / pack-check / github-push 一条龙。
366
366
  `lockfile` = 重生成锁文件 + 用 `--frozen-lockfile` 自检(CI 的 `Install (hooks)` 同款判定);
367
- `pack-check` 会在发布前核对打包产物是否完整(曾经踩过"发到 npm 少了文件"的坑);`scripts/dsh-crash-investigate.ts` 用来查崩溃(只读)。
367
+ `pack-check` 会在发布前核对打包产物是否完整(曾出现"发到 npm 少了文件"的情形);`scripts/dsh-crash-investigate.ts` 用来查崩溃(只读)。
368
368
  ⚠️ **改完 `package.json` 依赖后必须跑 `lockfile` 并提交锁文件** —— 曾漏过这一步,CI 从此一直红(红在"测试根本没跑",见 CHANGELOG)
369
369
  - **宿主类型基准 = devDependencies**:`tsconfig.json` / `client/tsconfig.json` 的 `paths` 指向**仓库内** `node_modules/@deepseek-ai/*`,由精确钉版的 devDependencies 提供 → **新增 paths 条目必须同时加 devDependency**(否则 tsc 静默回落 node_modules = 假绿,CI 的 typecheck 也就形同虚设)。机械闸门见 `tests/compliance.test.ts`;升级宿主时只改 `package.json` 一处 + 重跑 `lockfile`
370
370
  - **升级宿主**:`dsh-develop host-upgrade <版本|dist-tag>` 全局升级 DSH CLI(包名硬编码 `@deepseek-ai/dsh`、默认官方源、`--dry-run` 预览)→ 把 `package.json` 的 peer/devDeps 基准抬到同一版本 + 重跑 `lockfile`(`compliance.test.ts` 与 `host-manifest.test.ts` 会强制各声明面同步,漏一处必红)→ `restart-web` → `dashboard health` 看 `dshVersion`
@@ -395,7 +395,7 @@ pnpm build # 打包(lib/index.js + client.js)
395
395
  ## 11. 常见问题
396
396
 
397
397
  **Q:装完没反应?**
398
- 先确认你进的是带 `.serenity` 标记的目录。不是工作区的话,插件完全不介入。进去后输入 `dashboard health` 看三项检查。
398
+ 先确认进入的是带 `.serenity` 标记的目录。不是工作区的话,插件完全不介入。进去后输入 `dashboard health` 看三项检查。
399
399
 
400
400
  **Q:bash 怎么不见了?**
401
401
  安全模式开着——这是设计,不是 bug。关掉胶囊里的 SAFE 滑块就回来了(机制见 §3.2)。
@@ -410,7 +410,7 @@ pnpm build # 打包(lib/index.js + client.js)
410
410
  不会。只返回答案本身,内部轨迹和工具结果都不出去。
411
411
 
412
412
  **Q:微信桥里,AI 的回复是怎么发出去的?**
413
- 默认由插件自动把它的最后一段话转发给你。如果配了 `autoReplyWithLastMessage: false`,插件就不转了,改由 AI 自己发——所以这时候它如果没发,你就收不到消息(除非另外开了 `fallbackOnNoSend` 让插件兜底)。
413
+ 默认由插件自动把它的最后一段话转发给用户。如果配了 `autoReplyWithLastMessage: false`,插件就不转了,改由 AI 自己发——所以这时候它如果没发,用户就收不到消息(除非另外开了 `fallbackOnNoSend` 让插件兜底)。
414
414
 
415
415
  **Q:主动发的微信消息会被记录吗?**
416
416
  会。和工作区里配的 `weixin.hook` 记录脚本走同一条路,事件里标 `source: "proactive"`;自动回复标 `source: "reply"`。
@@ -419,7 +419,7 @@ pnpm build # 打包(lib/index.js + client.js)
419
419
 
420
420
  ## 12. 延伸阅读
421
421
 
422
- - **这套东西的想法从哪来**:[docs/cognitive-container-theory.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/docs/cognitive-container-theory.md)——认知容器是什么、认知的"发生/存储/再发生"、轨迹与载体
422
+ - **理论来源**:[docs/cognitive-container-theory.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/docs/cognitive-container-theory.md)——认知容器是什么、认知的"发生/存储/再发生"、轨迹与载体
423
423
  - **权威标准**:[serenity-acc-specs](https://github.com/tellmewhattodo/serenity-acc-specs)——理论根基、注入规范、不变量
424
424
  - **改了什么**:[CHANGELOG.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/CHANGELOG.md)——每个版本做了什么、为什么这么做,**当前版本号也看这里**
425
425