dsh-plugin-t-expert 0.2.16 → 0.3.24

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,109 +1,54 @@
1
1
  # T专家(dsh-plugin-t-expert)
2
2
 
3
- DeepSeek Harness 插件:**22 个分类 / 316 位专家**的名册(中文名、简介全量覆盖,人格正文回退英文 2 位),
4
- 外加插件内自带的**多智能体团队引擎**(小队模板、任务 DAG、调度、活动面板)。
3
+ dsh-plugin-t-expert 插件:包含 **22 个分类 / 316 位专家**的名册(中文名、简介全量覆盖),
4
+ 外加插件自带的**多智能体团队引擎**(T Team:小队模板、任务 DAG、调度、活动面板)。
5
5
 
6
6
  装上以后你能做四件事:
7
7
 
8
8
  | 做什么 | 怎么做 |
9
9
  | --- | --- |
10
- | 用专家 | 输入框打 `@` → 按分类分组的菜单 → 选中的专家作为引用 chip 进本轮对话;模型也可用 `summon_t_expert` 召唤 |
10
+ | 用专家 | 输入框打 `@` → 按分类分组的菜单 → 选中的专家作为引用 chip 进本轮对话;模型也可自行 `summon_t_expert` |
11
11
  | 拉起一支小队干活 | `/t <小队> <目标>`(`/t` 单跑列出现有小队) |
12
12
  | 管名册 | 设置 → T专家 → **专家**(启停 / 看提示词 / 新建自建专家) |
13
- | 管分类与小队 | 设置 → T专家 → **分类**(新建 / 改名 / 删除自建分类)、**队伍**(小队模板 + 运行中的团队) |
13
+ | 管分类与小队 | 设置 → T专家 → **分类**(自建分类增删改)、**队伍**(小队模板 + 运行中的团队) |
14
14
 
15
- 设置页一共**三个标签**:**专家**(启停 / 看提示词 / 新建自建专家)、**分类**(自建分类的增删改)、
16
- **队伍**(小队模板 + 运行中的团队)。
17
-
18
- 真实的后台任务列表不在设置页。右上角有一个**常驻的小徽章**(与团队徽章同一层、同一视觉体系),
19
- 它是随时点开查看的入口;只有真的还有东西在跑时才亮起来并给出运行中数量(安静时只是一个灰点,不显示数字),
20
- 点开就是任务面板:当前会话及其子代理的后台任务,只读(状态、退出码与耗时,
21
- 不含输出与终止)。面板可拖动,位置记在本机。
22
-
23
- 徽章只在"从无到有"时冒出,**面板绝不自动展开**——展开与否完全由你决定,关掉之后同一批任务不会再打扰你。
24
- 子代理区显示的是**子代理的真名**(取自语宿主的子代理目录 `label`,而不是从提示词生成的会话标题),
25
- 点一行即可跳到那个子代理的会话(与官方任务页同一个 `openSubagent` 接口)。
26
- 每行副标题显示该子代理的**请求文本前一段**(会话标题就是从它生成的),并标注运行中/已结束;
27
- 列表顺序沿用宿主子代理目录的原生次序——与官方任务页一致(快照里没有创建时间字段,不自造一种序)。
28
- 输入区 **T专家** 按钮弹开的浮层里也有一个**任务**页(与团队 tab 同层),随时手动查看。
29
-
30
- ---
31
-
32
- ## 一、安装
15
+ ## 安装
33
16
 
34
17
  ```bash
35
18
  dsh plugin --profile web add dsh-plugin-t-expert
36
19
  ```
37
20
 
38
- **DSH Desktop 请在插件市场里装**(搜 `dsh-plugin-t-expert` 一键安装)。
39
- `dsh plugin --profile desktop …` 会被 CLI 拒绝(desktop profile 由 Electron 应用独占),
40
- 这不是本插件的限制——任何插件都一样。
41
-
42
- 依赖:DSH 宿主 `0.1.5-rc.1` / `0.1.5-rc.2`;Node `^22.19.0 || >=24`;`pnpm` 在 PATH 上
43
- (`dsh plugin` 本质是在 profile 目录里转发 pnpm)。`python3` 只在**设置页保存小队**时需要
44
- (要调用小队编译器);缺它插件照常加载,只是小队编译会报错并回滚。
45
-
46
- 装完重启 DSH,然后在 **设置 → T专家** 里启用专家——**默认全部未启用**,未启用的专家不能被召唤。
47
-
48
- ### 兼容性与两个已知依赖
21
+ DSH Desktop 请在插件市场里搜 `dsh-plugin-t-expert` 安装(`--profile desktop` 由 Electron 应用独占,
22
+ CLI 会被拒绝 —— 任何插件都一样)。
49
23
 
50
- 团队引擎里有两处**贴着宿主实现细节**的适配,升级 DSH 前值得知道:
24
+ - 依赖:DSH 宿主 `0.1.5-rc.1` / `0.1.5-rc.2`;Node `^22.19.0 || >=24`;`pnpm` 在 PATH 上。
25
+ `python3` 只在**保存小队**时用到(缺它插件照常加载,只是小队编译会报错并回滚)。
26
+ - 装完**重启 DSH** 即可用;第一次怎么上手见下面的「快速上手」。
51
27
 
52
- | 依赖 | 说明 | 失效时的表现 |
53
- | --- | --- | --- |
54
- | 子代理投递契约(`ctx.subagents` 的 `followup` / `sendMessage` 与两个 `Symbol.for` 内部接口) | 插件要在"成员已退役"时拦住投递,而宿主没有公开的 retire/forget 扩展点,只能按**实测过的版本**包装这几个方法;已实测版本写在 `lib/teams/harness-compat.js` 的 `TESTED_HARNESS_VERSIONS`(当前 `0.1.5-rc.1` / `rc.2`) | 引擎**降级**(团队功能不可用,名册与召唤不受影响),日志与 `/t` 会给出原因。若上游把服务冻结或改成 accessor,会明确报「属性不可写」而不是一个裸 `TypeError` |
55
- | 活动面板的客户端物化用 `new Function` 求值内联产物 | 因此需要宿主允许 `eval`。当前 DSH 壳**没有**设置 CSP,本机实测可用 | 壳将来若加严格 CSP,面板模块会加载失败——失败会记 `console.error` 并跳过,不影响名册与团队引擎 |
28
+ ## 快速上手
56
29
 
57
- 这两条都不是"插件写坏了",而是宿主还没提供文档化扩展点。要根治第一条,需要宿主提供一个
58
- 文档化的退役/投递拦截扩展点,插件改为挂在那里。
30
+ 1. **启用专家**:设置 → T专家 → **专家**,把要用的打开 —— **默认全部未启用**,未启用的不会被召唤。
31
+ 2. **用一位专家**:输入框打 `@`,按分类挑一位,它以引用 chip 进入本轮对话;也可以直接说"让 XX 专家看看",
32
+ 由模型调 `summon_t_expert`。
33
+ 3. **拉一支小队**:`/t` 看有哪些小队(随包自带 48 支),`/t <小队> <目标>` 让它干活 —— 先给成员与任务草案,
34
+ 你 review 后开跑。
59
35
 
60
- ---
36
+ ## 界面入口
61
37
 
62
- ## 二、数据目录
63
-
64
- 插件对任何机器都**自包含**:包内带一份名册快照,启动时与 `~/.t-team/` 对齐(不是只在首次播种)。
65
-
66
- ```
67
- ~/.t-team/
68
- ├── experts/ 名册:<分类>/<slug>.md(22 个分类、316 位)
69
- ├── zh/ 中文侧车:names.json、descriptions.json、<分类>/<slug>.md、divisions.json
70
- ├── custom/ 你在面板里自建的专家
71
- ├── teams.json 小队定义(设置页「队伍」写回这里)
72
- ├── t-team.config.json 小队编译产物(引擎配置,人格已内联)
73
- ├── teams.resolved.json 小队编译产物(/t 列表用)
74
- ├── team-profiles.py 小队编译器的播种副本(实际跑的是包内那份)
75
- ├── source.json 名册清单(专家数 / 分类 / 更新时间)
76
- └── .t-team-snapshot.json 上次对齐的记录(版本 / 漂移计数,用于「升级与送不到」出声)
77
- ```
78
-
79
- - **升级会送达,用户内容不动**(2026-09-13 起按条目同步,不再是「首次播种后一律不动」):
80
- - 包内**新增**的专家、小队、译文键:直接补齐到你的数据目录;
81
- - 包内**修订**的只读条目(`experts/`、`source.json`、`team-profiles.py`、`zh/` 的覆盖表与分区表):
82
- 与包内对齐;
83
- - `zh/names.json`、`zh/descriptions.json`、`teams.json`:**只补缺失的键**,你改过的键一个都不动;
84
- - 你改过或补译的 `zh/<分类>/<slug>.md` 正文:**保留盘上那份**,并在日志里明确告知;
85
- - 包内已移除的条目:只报告,不删你的文件。
86
- - 一句话:**送得到的送到,送不到的一定出声**(日志里给出数量与例子,删掉对应文件后重启即可重新播种)。
87
- - 唯一始终用包内那份的是小队编译器 `team-profiles.py`——它是代码,随插件版本走。
88
- - 想换目录位置,用配置项 `root` / `zhRoot` / `customRoot` 覆盖即可,不必改代码。
89
-
90
- ---
91
-
92
- ## 三、自建专家与分类
93
-
94
- **新建专家**:设置 → 专家 → 「+ 新建专家」,选分类(官方 22 个或你自建的),填名称 / 简介 / 人格正文。
95
-
96
- - 自建专家写在 `customRoot`(默认 `~/.t-team/custom/<分类>/<slug>.md`),**与随包发布的名册分开**:
97
- 内置名册升级时整棵替换,自建的不受影响。
98
- - 归到官方分类名下是**允许且安全**的:分类只是归属,文件仍在 `customRoot`,内置名册一个字节不动。
99
- - 自建专家自带中文(frontmatter 里的 `name` 就是显示名),不依赖中文侧车。
100
-
101
- **新建分类**:设置 → 分类 → 填目录名(小写 ASCII)+ 显示名(中文)。
102
- 官方分类只读(名字与存亡随包内名册);删除自建分类时若里面还有专家会被拒绝,不会静默连删。
38
+ | 位置 | 是什么 |
39
+ | --- | --- |
40
+ | 设置 → T专家 | 管理页,一共**三个标签**:**专家**(启停 / 提示词 / 新建自建专家)、**分类**(自建分类增删改)、**队伍**(小队模板 + 运行中的团队) |
41
+ | 输入框 `@` | 按分类分组的专家菜单,选中即插入引用 chip |
42
+ | 输入区「T专家」按钮 | 浮层四个标签:**专家 → 小队 →(有运行中的团队时才出现)团队 → 任务**,默认停在**专家** |
43
+ | 会话标题栏徽章 | 后台任务只读面板(当前会话及其子代理的任务:状态、退出码、耗时);只在真有任务在跑时亮起并给出数量,**面板绝不自动展开**,可拖动、位置记在本机 |
44
+ | 左侧栏「新会话」下方 | **定时任务**入口(与「新会话」同款按钮外观),点开在右侧主区域显示管理页;点任意会话即回到会话视图 |
103
45
 
104
- ---
46
+ ## 专家
105
47
 
106
- ## 四、工具与命令
48
+ - 名册随包发布,启动时与 `~/.t-team/` 对齐(按条目送达,见「数据目录」)。
49
+ - **自建专家**:设置 → 专家 → 「+ 新建专家」,写在 `customRoot`(默认 `~/.t-team/custom/<分类>/<slug>.md`),
50
+ 与内置名册分开 —— 内置名册升级时整棵替换,自建的不受影响;归到官方分类名下也安全(分类只是归属)。
51
+ - **自建分类**:设置 → 分类 → 目录名(小写 ASCII)+ 显示名。官方分类只读;删除自建分类时若里面还有专家会被拒绝。
107
52
 
108
53
  | 工具 | 作用 |
109
54
  | --- | --- |
@@ -112,159 +57,95 @@ dsh plugin --profile web add dsh-plugin-t-expert
112
57
  | `summon_t_experts` | 并行召唤多位(最多 8 位、并发 4;部分失败仍返回成功的结果) |
113
58
  | `t_team_plan_check` | 只读 DAG 预检:一批团队任务先跑一遍引擎校验,一次报出全部问题 |
114
59
 
115
- | 命令 | 行为 |
116
- | --- | --- |
117
- | `/t` | 列出所有小队(key、别名、人数、成员中文名) |
118
- | `/t <小队\|别名>` | 选定小队,队长列出成员并问你目标 |
119
- | `/t <小队\|别名> <目标>` | 拉起小队干活(先给成员与任务草案,你 review 后开跑) |
120
- | `/t <一句话目标>` | 没匹配到小队名时,按目标自动挑最合适的小队 |
60
+ ## 小队与团队引擎
121
61
 
122
- 团队引擎另注册 **13 个 `t_team_*` 工具**(`t_team_create` 建队、`t_team_approve` 审批、
123
- `t_team_create_task` 建任务、`t_team_reassign_task` 派发、`t_team_status` 看状态、`t_team_resume` 恢复等),
124
- 随插件一起提供;队长与成员各看到其中一个子集。
125
-
126
- 另有 **3 个按需加载的 skill**(`skills/`,插件启动时注册):
127
-
128
- | skill | 何时用 |
129
- | --- | --- |
130
- | `t-expert-manager` | 维护这个名册的人:名册增删、一致性校验、统计、小队编辑、装机与发布都走它 |
131
- | `dsh-harness-project` | 在 `deepseek-harness` 检出里读写代码的人:架构、包地图、profile/bundle 启动模型、扩展点、门禁 |
132
- | `dsh-harness-languages` | 同一个仓库的各语言面规则与工具链(TypeScript / React / Python / C / YAML / SQLite / shell) |
133
-
134
- 它们都不占常驻提示段;宿主没有 skill 注册表的组合里会静默跳过,不影响其它任何功能。
135
- `t-expert-manager` 正文里的 `tz.sh` 路径是注册时按本机解出来的,不是写死的。
136
- 后两个是 `dsh-project-expert`(项目专家模式)这个 agent preset 里同名 skill 的随包副本。
137
-
138
- ### 本地活动的可见范围
139
-
140
- 设置页「团队」标签读的是插件在本机注册的只读接口(`/plugins/t-team/…`):每个请求都先过宿主的
141
- Host/Origin 校验与浏览器认证,静态资源另有白名单,非白名单一律 404。其中团队活动接口会**遍历
142
- 当前机器的所有工作区**,所以任何已认证的本机浏览器上下文都能看到这些工作区里的团队名、成员名
143
- 与任务标题(这是内置引擎的既有行为,不是 T专家 自己引入的)。DSH 是单用户本地应用,风险有限;
144
- 只在你的机器上有不信任的浏览器扩展或共享浏览器配置时才需要留意。
62
+ ```bash
63
+ /t # 列出所有小队(key、别名、人数、成员中文名)
64
+ /t <小队|别名> # 选定小队,队长列出成员并问你目标
65
+ /t <小队|别名> <目标> # 拉起小队干活(先给成员与任务草案,你 review 后开跑)
66
+ /t <一句话目标> # 没匹配到小队名时,按目标自动挑最合适的小队
67
+ ```
145
68
 
146
- ---
69
+ 引擎另注册 **13 个 `t_team_*` 工具**(建队 / 审批 / 建任务 / 派发 / 状态 / 恢复 / 删除…),随插件一起提供;
70
+ 队长与成员各看到其中一个子集。
147
71
 
148
- ## 五、小队
72
+ **设置 → 队伍**里改成员 / 别名 / 启停,保存写回 `~/.t-team/teams.json` 并调用小队编译器:
73
+ **保存后立即生效,无需重启 DSH**——编译成功后运行中的插件就地重载引擎配置,`/t` 与新建队随即看到新小队,
74
+ 已经跑起来的团队继续用启动时的成员表。**编译失败会自动回滚**,盘上仍是旧配置,设置页直接报错并说明引擎是否可用。
149
75
 
150
- 设置 → 队伍 里搜索、修改成员 / 别名 / 启停,然后保存:改动写回 `~/.t-team/teams.json`,
151
- 再调用小队编译器生成引擎配置;**编译失败会自动回滚**,不会把坏定义留在盘上。
76
+ 约束:小队 key 只能 ASCII `a-z0-9-`(中文放 `description` / `aliases`);每队 ≤ `maxMembers`(默认 8);
77
+ 小队总数 ≤ 48;别名全局唯一;成员必须是名册里真实存在的专家。
152
78
 
153
- **保存后立即生效,无需重启 DSH**:编译成功后运行中的插件会就地重载引擎配置,
154
- `/t` 列表与新建队(含队长提示段)随即看到新小队;已经跑起来的团队不受影响,继续用启动时的成员表。
79
+ ## 定时任务
155
80
 
156
- - 编译失败并**回滚**时不会重载:盘上还是旧配置,建队照旧按旧小队走,设置页会直接报错。
157
- - 引擎重载本身失败时会留下可诊断的信号(日志里有 `[t-team]` 的 error/warn),
158
- 并且报错时会带着原因说清引擎当前是否可用,不会静默假装已生效。
81
+ 到点自动**新开一个会话**执行提示词,也可以随时「立即执行」。
159
82
 
160
- 约束:小队 key 只能 ASCII `a-z0-9-`(中文放 `description` / `aliases`);每队 ≤ `maxMembers`(默认 8,见「六、配置项」);
161
- 小队总数 ≤ 48;别名全局唯一;成员必须是名册里真实存在的专家。
162
- > 成员上限由插件透传给小队编译器(`data/team-profiles.py --max-members`),两边同一个真源:
163
- > 改 `maxMembers` 就能真正生效,不必再动编译器。只有在用**旧版本**编译器(不认这个参数)时,
164
- > 才会退回它内置的默认值并打印一条 warn —— 正常升级路径下包内编译器会一起更新。
83
+ | 能力 | 说明 |
84
+ | --- | --- |
85
+ | cron 执行 | 每条 = 标题 + 提示词 + 五段 croner 表达式(`分 时 日 月 周`) |
86
+ | 结构化选择器 | 快捷模板 + 「每小时 / 每天 / 每周 / 自定义」逐级选,周几多选;也可直接写原始表达式 |
87
+ | 实时预览 | 面板显示**最近 5 次执行时间**(宿主用 croner 算,保存前就能确认周期) |
88
+ | 立即执行 | 任意一条一键跑一次,不必等 cron 到点 |
89
+ | 绑定工作区 | **默认绑好**:新建即绑定自动创建的「定时任务」工作区(目录 = 默认工作目录下的 `tesk`);下拉里还能选「+ 自定义目录…」填任意绝对路径(不存在会建出来,工作区名取目录名),或选「不绑定工作区」 |
90
+ | 会话自动命名 | 「任务标题 · MM-DD HH:mm」,同一任务多次运行在侧栏里分得清 |
91
+ | 执行记录 | 每条保留最近 20 次(时间、成败、失败原因、会话 id) |
92
+ | 启用 / 停用 | 停用的事项保留数据但不再触发 |
93
+ | 点名专家 | 提示词框下的「🧩 T专家」浮层只列**已启用**专家(可搜、可键盘选、可多选),把 `@专家名` 插在光标处;到点执行时宿主把它改写成召唤指令(1 位 → `summon_t_expert`,多位 → `summon_t_experts`),不在已启用名册里的名字**原样提交、绝不猜** |
165
94
 
166
- ---
95
+ **开关**:设置 → T专家 → 「显示定时任务按钮」。关掉它**不只是藏按钮**:宿主同时停掉全部定时触发,
96
+ 手动执行也被拒;任务与执行记录完整保留,重新打开立刻按 stored 状态恢复调度。
167
97
 
168
- ## 六、配置项
98
+ 数据写在 `~/.t-team/schedule.json`(插件自己的数据根下,不进宿主存储域),与 `@weibaohui/dsh-tasks`
99
+ **可同时安装、同时使用**:各跑各的定时器、各存各的任务、各用各的侧栏入口与 remote 服务,互不可见。
169
100
 
170
- 全部以插件 `Config` 定义为准(`lib/index.js`,共 15 项)。常用的几个:
101
+ ## 数据与目录
171
102
 
172
- | 配置项 | 默认值 | 含义 |
173
- | --- | --- | --- |
174
- | `root` | `~/.t-team/experts` | 名册目录 |
175
- | `zhRoot` | `~/.t-team/zh` | 中文侧车目录 |
176
- | `customRoot` | `~/.t-team/custom` | 自建专家目录(与 `root` 分开是硬要求) |
177
- | `provider` | `"spawn"` | 召唤专家用的子代理 provider |
178
- | `divisions` | `[]` | 留空=自动扫描 `root` 下所有含 `.md` 的分类 |
179
- | `maxSummonBatch` / `summonConcurrency` | `8` / `4` | 批量召唤上限与并发 |
180
- | `stateDir` | `.agent-teams` | 团队状态目录(**工作区内的相对路径**),团队状态落在 `<工作区>/<stateDir>/<teamId>/`。内置团队引擎、设置页「队伍」标签与只读预检工具 `t_team_plan_check` 都按它定位团队——**三处都读这一个字段**,不存在第二来源(自检 8f 有静态 + 行为双断言兜着)。要挪团队状态目录只改这里 |
181
- | `memberProvider` / `memberModel` / `maxMembers` | — | 转给内置团队引擎;`maxMembers` 还由插件透传给小队编译器(见「五、小队」) |
103
+ **全部数据都在你本机**:不连任何网络服务、不做遥测;名册、中文译文与小队的编译器都随包分发,运行时不向上游拉取。
182
104
 
183
- ---
105
+ ```
106
+ ~/.t-team/
107
+ ├── experts/ 名册:<分类>/<slug>.md(包内快照 22 个分类、316 位;你自建的另计)
108
+ ├── zh/ 中文侧车:names.json、descriptions.json、<分类>/<slug>.md
109
+ ├── custom/ 你在面板里自建的专家
110
+ ├── teams.json 小队定义(设置页「队伍」写回)
111
+ ├── schedule.json 定时任务:任务、cron 表达式与最近 20 次执行记录
112
+ ├── t-team.config.json 小队编译产物(引擎配置,人格已内联)
113
+ ├── teams.resolved.json 小队编译产物(/t 列表用)
114
+ ├── team-profiles.py 小队编译器的播种副本(实际跑的是包内那份)
115
+ ├── source.json 名册清单(专家数 / 分类 / 更新时间)
116
+ └── .t-team-snapshot.json 上次对齐的记录(版本 / 漂移计数)
117
+ ```
184
118
 
185
- ## 七、许可
119
+ - 启动时**按条目**与包内快照对齐:包内新增的专家 / 小队 / 译文键补齐;只读条目(`experts/`、`source.json`、
120
+ `team-profiles.py`、`zh/` 的覆盖表与分区表)与包内对齐;`names.json` / `descriptions.json` / `teams.json`
121
+ **只补缺失的键**(你改过的键一个都不动);你改过的译文正文保留盘上那份;包内已移除的条目只报告、不删你的文件。
122
+ - 一句话:**送得到的送到,送不到的一定出声**(日志给出数量与例子)。唯一始终用包内那份的是小队编译器
123
+ (它是代码,随插件版本走)。想换目录位置,用配置项 `root` / `zhRoot` / `customRoot` 覆盖。
186
124
 
187
- 本插件 MIT(见 `LICENSE`)。随包分发的专家名册、中文译文与内置团队引擎各自按其原许可使用:
188
- 来源、版本与署名写在 `THIRD-PARTY-NOTICES`,完整许可文本随包放在 `vendor/`。
189
- 再分发(含修改版)时请一并保留这三样。
125
+ ## 常见问题
190
126
 
191
- ---
127
+ | 现象 | 原因与处理 |
128
+ | --- | --- |
129
+ | 召唤不了某位专家 | 它没被启用(设置 → T专家 → 专家);名册默认是"全部未启用" |
130
+ | `/t` 不可用或提示引擎降级 | 宿主版本不在实测范围内(见「安装」的依赖一行)时团队引擎会降级:`/t` 会给出原因,名册与 `@` 召唤不受影响 |
131
+ | 保存小队报错 | 缺 `python3`,或新定义没通过编译 —— **失败会自动回滚**,盘上仍是旧配置,设置页会说明引擎是否可用 |
132
+ | 定时任务没有按时跑 | 设置 → T专家 → 「显示定时任务按钮」若被关掉,宿主会停掉**全部**定时触发(手动执行也会被拒),这是有意为之 |
133
+ | 改完插件看不到变化 | 客户端与宿主代码都要重启 DSH 才生效;设置 → T专家 标题行有当前版本号(`v0.3.x`)可核对 |
192
134
 
193
- ## 八、开发
135
+ ## 卸载与反馈
194
136
 
195
- ```bash
196
- npm install # 装开发期依赖(.npmrc 里开了 legacy-peer-deps,原因见该文件)
197
- npm run typecheck # 类型检查(tsconfig.json 只覆盖自研 Host 文件,不碰并入的引擎)
198
- npm run verify # 自检套件(现 521 项断言):插件契约、工具、remote、客户端产物、播种与快照,
199
- # 外加「发布包自洽」(真打一份 tgz、解开、再用插件解析器读一遍)
200
- npm run invariants # 引擎不变量门禁:真 cordis + 真 lib/teams + 桩 Agent,只报「违反集 D」
201
- npm run build # 构建客户端产物(lib/client.js)
202
- npm run sync-data # 把运行时数据同步进包内 data/
203
- ```
137
+ - **卸载**:DSH Desktop 在插件市场里卸载;CLI 用 `dsh plugin --profile web remove dsh-plugin-t-expert`。
138
+ 卸载不会删数据目录 `~/.t-team/`(名册、自建专家、小队、定时任务都在那儿),要清干净手动删它即可。
139
+ - **反馈与源码**:<https://github.com/jiuaiwo/dsh-plugin-t-expert> —— 问题请走 Issues。
204
140
 
205
- `tools/` 里的构建 / 自检 / 同步脚本**随仓库走**,所以干净 clone 就能跑 `typecheck` 与 `verify`;
206
- 需要运维台(`tz.sh`、`add-expert.py`)的那几节在本机没有运维目录时会**显式打印 skip**,不会
207
- 静默少跑。推送与 PR 由 `.github/workflows/ci.yml` 跑同一套门禁(含 `npm run invariants`)。
141
+ ## 许可
208
142
 
209
- ### 引擎不变量(`npm run invariants`)
143
+ 本插件以 **MIT** 发布(见 `LICENSE`)。
210
144
 
211
- `lib/teams/**` 是内置的团队引擎(约 9,600 行)。它没有「读一遍代码」的判据,所以这里用
212
- **可执行探针**把引擎声称永远成立的契约钉住,只看**违反集 D**:`D = ∅` 即本轮干净。
145
+ 随包内容包含第三方成果 —— 内置团队引擎(派生自 `@nanmicoder/dsh-agent-teams`)、专家名册与中文译文
146
+ (`msitarzewski/agency-agents`、`jnMetaCode/agency-agents-zh` 等)、以及运行时依赖 `croner` ——
147
+ 它们各自保留原许可。完整来源、版本与署名见 `THIRD-PARTY-NOTICES`,完整许可文本随包放在 `vendor/`。
213
148
 
214
- | 不变量 | 钉住什么 |
215
- | --- | --- |
216
- | `INV-1` | 任务被转交/重试后**旧 `attempt_id` 必须失效**(旧主人与伪造令牌都被拒) |
217
- | `INV-2` | 两个未完成的**写**任务不得共用同一 `inScope` 路径;`implementation` 必须带 `inScope` |
218
- | `INV-3` | 一成员同时只能有一个未完成任务(顺序与**并发**都成立,并发恰好 1 胜) |
219
- | `INV-4` | `halted` 语义:停→取消未完成任务并拒新单;`resume` 必须带非空 reason,之后才恢复派发 |
220
- | `INV-5` | 并发写不丢更新:N 次并发建单全部落盘、id 唯一、状态文件始终可解析 |
221
- | `INV-6` | `review` 必须带 `reviewedTaskId`;`needs_revision` 走 `failed` 且自动生成 `repair`;`verdict=pass` 才算完成 |
222
- | `INV-7` | 质量类建单契约:`implementation` 必须带 `objective`/`acceptance`/`inScope`/`verify` |
223
- | `INV-8` | 调度器契约:`approve` 后 pending 任务会被自动派给空闲成员(不是停在池里等人 claim) |
224
- | `INV-9` | 宿主路径契约:`agents` 未就绪时快照不得抛错(用**真 cordis 受门控 ctx** 钉住;旧写法会抛 `without inject`,那一瞬间所有团队会从面板消失) |
225
-
226
- **聚合入口**:`npm run invariants -- --all` 会把引擎不变量与既有的三道门禁一起跑,统一输出违反集 `D`:
227
-
228
- | 聚合项 | 说明 |
229
- | --- | --- |
230
- | 引擎不变量 | 本文件的 9 条(真 cordis + 真 `lib/teams` + 桩 Agent) |
231
- | 插件契约 | 以**黑盒**调用 `tools/verify.mjs`(521 项),只取退出码与摘要行 |
232
- | 宿主 skill 漂移 | `tools/skill-drift.mjs`(它现在也能独立跑:有漂移即退出码 1) |
233
- | 数据快照一致 | `tools/sync-data.mjs --check`(**源目录不存在时显式记 SKIP**,不算违反) |
234
-
235
- 约定:门禁报告「已跳过」不算违反(与 `verify.mjs` 的 skip 规矩一致)。CI 里仍分别跑 `verify` 与
236
- `invariants`(不重复跑一遍 `--all`)。
237
-
238
- 探针基座的三条忠告写在 `tools/invariants.mjs` 的文件头(成员 id 要 approve 后才出现、团队 id
239
- 会被 slug 化、工具执行上下文必须带 `signal` 且成员 agent 要有 `status`/`whenIdle`)——它们都是
240
- 写这个门禁时踩出来的,改探针前先读那段。
241
-
242
-
243
- 四条容易踩的开发约定:
244
-
245
- - **线格式(remote)的 schema 只有一份**:`lib/remote-schemas.js`,host 的 `lib/remote.js`
246
- 与客户端 `src/client.jsx` 都从它取;两端各自只保留**信封**(`descriptor()` / `direct()`)。
247
- 改字段只改 schema 文件;改方法签名要同时改两端信封——自检会机械比对每个方法的**参数名与
248
- typeSymbol 是否两端一致**,漏改一处就会被拦下(不用等调用期)。
249
- - `lib/client.js` 是**入库的构建产物**(≈1 MB)。改客户端只改 `src/client.jsx`,
250
- 然后必须重跑 `npm run build` —— 自检里有一条「产物新鲜度」门禁,忘了重跑会拦下来。
251
- - `package-lock.json` 管的是**本插件自己的 devDependencies**;用户装插件用的 `pnpm`
252
- 是宿主 `dsh plugin` 在 profile 目录里跑的,两者互不冲突,不要为了方便删掉 lock。
253
- - `lib/squads.js` 这类数据层**不写 `console`**:诊断一律走注入的宿主 logger
254
- (`ctx.logger`),桌面与 Web 里 stderr 用户看不见。编译团队配置是**异步**的
255
- (`execFile`,不是 `execFileSync`)—— 同步跑会把整个 Host 事件循环卡住。
256
-
257
- 内置团队引擎(`lib/teams/`)是**手工维护的源码**,改引擎直接改这里;
258
- 名册(`data/experts/`)与中文侧车(`data/zh/`)就是发布源,两者都不再从任何上游同步。
259
-
260
- ### `dsh.client.inject` 为什么写着 `dsh-client-ui-primitives`
261
-
262
- 那是**承重的声明,不是笔误**。`@deepseek-ai/dsh-client-modules` 的到达顺序契约里,
263
- `dsh.client.inject` 让被点名的包**先于本插件的 client module 到达**;而 `lib/client.js`
264
- 里确实有 `require("@deepseek-ai/dsh-client-ui-primitives")`(构建时只把 `react` 外部化)。
265
- 删掉它并不会让构建失败,却可能让本插件赶在 primitives 之前物化、require 当场抛错。
266
-
267
- 顺带说明两个容易误判的点:**①** 这个包没有 `exports["./client"]`,所以它不作为「client module」
268
- 参与 `dsh.client.inject` 的常规扫描——但名字仍必须留在这里;**②** 自检 `[20b]` 已经把
269
- 「bundle 里每个 `@deepseek-ai/*` 外部 require 都必须在名单里」固化成不变量,以后新增 require
270
- 忘了声明会当场红,不必再靠人肉比对。
149
+ 本插件及随包内容按**「原样」提供,不附带任何明示或默示担保**;与上述上游项目及 DeepSeek Harness
150
+ 官方无隶属或背书关系。再分发(含修改版)时请保留 `LICENSE`、`THIRD-PARTY-NOTICES` 与 `vendor/`
151
+ 下的许可文本。
@@ -59,7 +59,23 @@
59
59
  `data/zh/manual.json` 与 `data/zh/manual-bodies/` 是**本项目的补充翻译**(用于补齐尚未覆盖的条目
60
60
  或在译文不准确时覆盖),随本插件以 MIT 发布,同样保留在包内。
61
61
 
62
- ## 3. 分发要求
62
+ ## 3. 定时任务调度器(运行时依赖)
63
+
64
+ | 项 | 值 |
65
+ | --- | --- |
66
+ | 上游包 | [`croner`](https://www.npmjs.com/package/croner) |
67
+ | 上游仓库 | https://github.com/Hexagon/croner |
68
+ | 版本 | `^9.1.0`(`package.json` 的 `dependencies`) |
69
+ | 许可 | MIT — Copyright (c) 2015-2021 Hexagon <github.com/Hexagon> |
70
+ | 位置 | **不作为源码内联**:按普通 npm 依赖安装(`node_modules/croner`),由 `lib/schedule.js` 在运行期 `import { Cron }` |
71
+ | 许可全文 | `vendor/third-party-licenses/croner.LICENSE`(随包分发,便于再分发者与离线安装核对) |
72
+
73
+ 用途:T专家 的定时任务(cron 表达式解析、下次触发时间预览、定时器)由它提供;本插件不修改其源码。
74
+
75
+ > 与 `@weibaohui/dsh-tasks` 的关系:两者都用 `croner`,但**各自声明依赖、各装各的**,
76
+ > 数据文件、服务名与定时器互不共享(见 README 的「定时任务」一节)。
77
+
78
+ ## 4. 分发要求
63
79
 
64
80
  再分发本插件(或其修改版)时请一并保留以下文件(它们都在 npm 包内):
65
81
 
@@ -68,3 +84,4 @@
68
84
  - `vendor/dsh-agent-teams/LICENSE`(内置团队引擎)
69
85
  - `vendor/third-party-licenses/agency-agents.LICENSE`(英文名册)
70
86
  - `vendor/third-party-licenses/agency-agents-zh.LICENSE`(中文译文)
87
+ - `vendor/third-party-licenses/croner.LICENSE`(定时任务调度器,运行时依赖)