dsh-plugin-t-expert 0.2.7 → 0.2.9
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 +20 -9
- package/THIRD-PARTY-NOTICES +16 -8
- package/data/experts/engineering/engineering-deepseek-harness-project-expert.md +256 -0
- package/data/source.json +2 -2
- package/data/t-team.config.json +16 -1
- package/data/team-profiles.py +80 -78
- package/data/teams.json +103 -47
- package/data/teams.resolved.json +17 -1
- package/data/zh/COVERAGE.json +15 -14
- package/data/zh/descriptions.json +2 -1
- package/data/zh/names.json +2 -1
- package/lib/catalog.js +134 -31
- package/lib/client.js +1 -1
- package/lib/command.js +4 -1
- package/lib/i18n.js +75 -11
- package/lib/index.js +167 -62
- package/lib/plan-check.js +14 -3
- package/lib/remote.js +82 -15
- package/lib/skill.js +102 -42
- package/lib/squads.js +51 -3
- package/lib/teams/assignee-contract.js +47 -0
- package/lib/teams/quality-gates.js +24 -1
- package/lib/teams/state.js +14 -2
- package/lib/teams/tools.js +9 -3
- package/package.json +10 -24
- package/skills/dsh-harness-languages/SKILL.md +175 -0
- package/skills/dsh-harness-project/SKILL.md +209 -0
- package/skills/t-expert-manager/SKILL.md +4 -3
- package/skills/t-expert-manager/references/ops-reference.md +2 -2
- package/vendor/third-party-licenses/README.md +1 -1
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-t-expert",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.9",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "T Expert — a
|
|
5
|
+
"description": "T Expert — a 316-expert, 22-division roster with full Chinese translations, as a standalone DeepSeek Harness plugin, with a built-in multi-agent team engine (T Team).",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "jiuaiwo",
|
|
8
8
|
"keywords": [
|
|
@@ -100,9 +100,6 @@
|
|
|
100
100
|
"@deepseek-ai/dsh": {
|
|
101
101
|
"optional": true
|
|
102
102
|
},
|
|
103
|
-
"@deepseek-ai/dsh-agent": {
|
|
104
|
-
"optional": true
|
|
105
|
-
},
|
|
106
103
|
"@deepseek-ai/dsh-api-remotes": {
|
|
107
104
|
"optional": true
|
|
108
105
|
},
|
|
@@ -124,33 +121,22 @@
|
|
|
124
121
|
"@deepseek-ai/dsh-client-ui-slots": {
|
|
125
122
|
"optional": true
|
|
126
123
|
},
|
|
127
|
-
"@deepseek-ai/dsh-llm": {
|
|
128
|
-
"optional": true
|
|
129
|
-
},
|
|
130
|
-
"@deepseek-ai/dsh-session": {
|
|
131
|
-
"optional": true
|
|
132
|
-
},
|
|
133
124
|
"@deepseek-ai/dsh-settings": {
|
|
134
125
|
"optional": true
|
|
135
126
|
},
|
|
136
|
-
"@deepseek-ai/dsh-subagent": {
|
|
137
|
-
"optional": true
|
|
138
|
-
},
|
|
139
127
|
"@deepseek-ai/dsh-system-prompt": {
|
|
140
128
|
"optional": true
|
|
141
129
|
},
|
|
142
|
-
"@deepseek-ai/dsh-tools": {
|
|
143
|
-
"optional": true
|
|
144
|
-
},
|
|
145
|
-
"@deepseek-ai/dsh-typert-protocol": {
|
|
146
|
-
"optional": true
|
|
147
|
-
},
|
|
148
|
-
"@deepseek-ai/schemastery": {
|
|
149
|
-
"optional": true
|
|
150
|
-
},
|
|
151
130
|
"react": {
|
|
152
131
|
"optional": true
|
|
153
|
-
}
|
|
132
|
+
},
|
|
133
|
+
"@deepseek-ai/schemastery": {},
|
|
134
|
+
"@deepseek-ai/dsh-tools": {},
|
|
135
|
+
"@deepseek-ai/dsh-llm": {},
|
|
136
|
+
"@deepseek-ai/dsh-typert-protocol": {},
|
|
137
|
+
"@deepseek-ai/dsh-session": {},
|
|
138
|
+
"@deepseek-ai/dsh-subagent": {},
|
|
139
|
+
"@deepseek-ai/dsh-agent": {}
|
|
154
140
|
},
|
|
155
141
|
"devDependencies": {
|
|
156
142
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dsh-harness-languages
|
|
3
|
+
description: Use when writing, reviewing, or debugging any code in the deepseek-harness monorepo and you need that language's rules, layout, or toolchain — TypeScript on Node, the React browser client (TSX/CSS Modules), the Python SDK, the C Node-API addon, Cordis YAML composition, SQLite storage, shell, or the build/test toolchain (pnpm, tsc, tsdown, vitest, tsx, oxlint, Electron, Vite).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DeepSeek Harness:语言与技术栈
|
|
7
|
+
|
|
8
|
+
一份按语言/技术栈拆的落地参考。先看清「这段代码属于哪一面、哪个语言面」,再动手。
|
|
9
|
+
|
|
10
|
+
## 总览
|
|
11
|
+
|
|
12
|
+
| 语言 / 技术 | 位置 | 运行时与工具链 |
|
|
13
|
+
|---|---|---|
|
|
14
|
+
| **TypeScript(Host/Node)** | `packages/**`、`apps/cli`、`apps/desktop*`、`scripts/` | Node ^22.19 \|\| >=24、ESM、`tsc -b` + `tsdown`、`tsx` 跑源码 CLI |
|
|
15
|
+
| **TypeScript/TSX(Client/浏览器)** | `packages/client/**`、`apps/web` | React 18、`react-jsx`、Vite、CSS Modules + `clsx` |
|
|
16
|
+
| **Python 3.10+** | `python/sdk`、`python/sdk-runtime` | hatchling、uv、pydantic v2、pytest;stdio 上的 JSON-RPC 客户端 |
|
|
17
|
+
| **C(C11)** | `native/system/packages/entry/src/*.c` | Node-API(NAPI_VERSION=8)、`cc`/`musl-gcc`、预编译平台包 |
|
|
18
|
+
| **YAML(Cordis 组合)** | `packages/bundle/**/*.cordis.yml`、preset 的 `agent.cordis.yml`、profile patch | Loader + Schemastery `Config` 校验 |
|
|
19
|
+
| **SQLite** | `packages/storage/storage-sqlite`、`packages/session-query/session-query-sqlite` | `node:sqlite` 的 `DatabaseSync`、FTS5 |
|
|
20
|
+
| **Shell** | `packages/shell/*`、`scripts/*.sh` | bash / pwsh executor + sandbox 包装 |
|
|
21
|
+
| **Markdown(文档)** | `docs/**`、包 README、`.agents/notes/**` | 文档门禁(`doc-sync`) |
|
|
22
|
+
|
|
23
|
+
所有 npm 包名是 `@deepseek-ai/dsh-<name>`;`@deepseek-ai/cordis` 是每个 harness 包的 peerDependency(+ dev)。
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## TypeScript(Host / Node)
|
|
28
|
+
|
|
29
|
+
**编译形态**(`tsconfig.base.json`):`target: es2024`、`module: esnext`、`moduleResolution: bundler`、`strict: true`、`exactOptionalPropertyTypes: true`。
|
|
30
|
+
|
|
31
|
+
- **到处是 ESM**(`"type": "module"`)。跨包用包名 import,**包内相对导入写 `.ts` 后缀**。
|
|
32
|
+
- `dsh` CLI 的源码启动走 `node --import tsx/esm`(tsx 的 ESM-only hook),所以它能触达的模块必须保持 ESM(不能有 CJS-only 导出)——Node 原生 TS 模式在 engines 范围内不可用。
|
|
33
|
+
- **Host / Client 是两个聚合工程**:Host 包注册进 `tsconfig.host.json`,Client 包注册进 `tsconfig.client.json`;`tsconfig.json` 是 solution(`files: []`),`tsconfig.base.json` 是路径映射门面(**永远不要给它加 `include`/`files`**)。原因:两侧都在同一批 key 上 declaration-merge cordis 的 `Context`,一个 program 同时看到两份会报冲突 —— 该冲突只存在于 `ts.Program` 内,模块解析不会触发。
|
|
34
|
+
- 需要构建整仓 `ts.Program` 的脚本要显式以 `tsconfig.host.json` 或 `tsconfig.client.json` 为种子,**绝不能用 root solution**。
|
|
35
|
+
- 六个包是 Host/Client 分裂包,各带两个 leaf config + 只用 solution 的根:`api/remotes`、`api/gateway`、`api/session-controller`、`api/workspace-controller`、`client/connection`、`session-query/session-log-export`。
|
|
36
|
+
|
|
37
|
+
**插件导出形态(最关键的一条)**:
|
|
38
|
+
|
|
39
|
+
- **service 包 `export default` 它的 service class。**
|
|
40
|
+
- **function plugin 命名导出 `name` / `inject` / `Config` / `apply`,且不能有 default export。** 混用会让 Loader 丢弃该 function plugin 的 namespace(见 [postmortem 0001](docs/postmortem/0001-acp-default-export-drops-inject.md))。
|
|
41
|
+
- 可选服务用 **`ctx.get(name)`**;`ctx.<name>` 只留给已声明 injection 的服务 —— 属性代理对拓扑敏感,`ctx.get` 读全局服务存储。
|
|
42
|
+
|
|
43
|
+
**类型与写法**:
|
|
44
|
+
|
|
45
|
+
- 类型化事件用 **declaration merging** 与可合并扩展的 map。`SessionEventMap` 成员默认 required-on-read;事件 JSDoc 需要 `@mode` 和 payload `@param`;payload 里没有的 scoped key 需要 `@dshScopeScan unsupported`。只有结构性格式变化才 bump `SESSION_FORMAT_VERSION`。
|
|
46
|
+
- 判别式 tag 上做 switch;封闭联合以 `assertNever`(`@deepseek-ai/dsh-util-values`)收尾。
|
|
47
|
+
- 跨边界的不透明 id 用 `Branded<B>` / `BrandedNumber<B>` + `brandString` / `brandNumber`(`packages/util/brand`,包名 `@deepseek-ai/dsh-brand`),不用裸 `string`。
|
|
48
|
+
- **每个 module 与 export 都要有简洁 JSDoc**,函数式导出要有 `@param`/`@returns` —— `verify-export-jsdoc` 强制。公有 service 方法要记参数与非 void 返回。
|
|
49
|
+
- 剩下的 `any` 要解释为什么无法收窄。
|
|
50
|
+
- `src/types.ts` 只放类型,不放运行时代码;测试放包级 `tests/`,不放 `src/__tests__/`。
|
|
51
|
+
- 空 `catch` 命名它吞掉什么、为什么别的到不了;`try` 只包一条语句。
|
|
52
|
+
- 注释写局部契约(行为、失败、时序、所有权、模态、例外、后果),**不写推理过程、不复述代码、不写测试走查**。
|
|
53
|
+
|
|
54
|
+
**远程过程调用(Typert)**:业务 service 在 Host 用 `@Remote` / `@RemoteScope` 声明可调用方法;Host 构建生成 Host-for-Client 类型与运行时贡献,Client 的 `api-remotes` 在 `ctx.remote` / `agentCtx.remote` 下加载它们。手工写的 `remote` 类型会漂移。
|
|
55
|
+
|
|
56
|
+
**边界校验**:只在 parser/config、queued、模型/工具 JSON、durable/file、worker、process、wire 边界做运行时校验。同一进程内的静态类型边界信任 TypeScript,不加多余校验。
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## TypeScript / React(浏览器客户端)
|
|
61
|
+
|
|
62
|
+
位置:`packages/client/**`(`ui-*` 插件 + `web` 引导内核 + `store`/`connection`/`slots`/`locale`/`modules`/`resources`),应用层在 `apps/web`。
|
|
63
|
+
|
|
64
|
+
- React **18**,`jsx: react-jsx`,浏览器 lib(`ES2024 + DOM + DOM.Iterable`),`types: []` 起步(需要 Node 类型的包局部覆写)。继承 `tsconfig.base.client.json`。
|
|
65
|
+
- **样式**:CSS Modules(`*.module.css`,约 130 个)+ `clsx`。**不要引入组件库,不要用 Tailwind。**
|
|
66
|
+
- **token 归 `ui-theme` 所有**:静态色阶、语义别名、排版、动效、渐变、阴影、滚动条、明暗偏好都在 `packages/client/ui-theme/src/styles/`,对外暴露 `--dsw-*`。特性包只用 `--dsw-alias-*` 语义别名,**不写死调色板值或字面颜色**,也不在特性组件 CSS 里写主题选择器。
|
|
67
|
+
- 全局样式表放 `ui-theme/src/styles/`;组件样式放组件旁边。组件可定义局部自定义属性,但共享的颜色/排版/高度/动效归 theme 包。
|
|
68
|
+
- **先复用再改样式**:[ui-primitives 组件目录](packages/client/ui-primitives/README.md#component-catalog)是唯一跨特性包的通道;刻意的视觉差异做成它的 prop,而不是再复制一份。
|
|
69
|
+
- 抬高面(菜单、popover、modal、面板、浮动按钮、composer)设 `border: 0` 并用 `var(--dsw-elevation-*)`;**不要把 `--dsw-alias-border-*` 边框和 elevation 阴影配在一起**(ui-theme 的 spec 会拒绝)。
|
|
70
|
+
- 中立实色边框与分隔线画 `0.5px`(Chromium 上正好一个设备像素);虚线语义与状态色边框保持 1px。
|
|
71
|
+
- 圆角继承 ui-theme 的 superellipse smoothing;每个整圆 `border-radius`(`50%`、`100%`、胶囊)都要配 `corner-shape: round`。
|
|
72
|
+
- 可点击的产物链接统一用 `--dsw-alias-link` + `font-weight: 500`,静止无下划线,hover/focus 为 3px 偏移点状下划线。
|
|
73
|
+
- 保留键盘焦点可见性与 reduced-motion 行为。
|
|
74
|
+
- **产品文案归 locale 所有**:走类型化字典 + `t` 座位或本地化 primitive props。JSX、模板、helper 返回值、可访问性属性、primitive 默认值里的硬编码产品文案会被 `verify-client-ui-i18n` 拒绝;用户/模型/wire 数据与代码 token 原样保留。
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Python 3.10+
|
|
79
|
+
|
|
80
|
+
位置:`python/sdk`(`deepseek_harness`,PyPI `deepseek-harness-sdk`)与 `python/sdk-runtime`(`deepseek_harness_runtime`,PyPI `deepseek-harness-runtime-bin`)。
|
|
81
|
+
|
|
82
|
+
- `requires-python = ">=3.10"`;`pydantic>=2.12,<3`;构建后端 hatchling(`hatchling==1.30.1`);依赖组测试用 pytest ≥8,`pytest.ini` 在仓库根。
|
|
83
|
+
- 包布局是 `src/` 布局:`python/sdk/src/deepseek_harness/{__init__,api,client,errors,models}.py`。
|
|
84
|
+
- **角色**:通过 stdio 上的换行分隔 JSON-RPC 驱动 dsh 子进程。`HarnessClient` 是同步客户端;`HarnessConfig` 持有 `dsh_bin`、`profile`(默认 `sdk`)、`patches`、`dsh_home`、`cwd`、`env`、各类超时。
|
|
85
|
+
- **每次启动都必须显式指定 Harness home;Python 绝不静默读 `~/.dsh`。**
|
|
86
|
+
- Python 侧暴露的是 profile 选择 + 有序 patch 文件,不是完整 Cordis 树;持久外部插件通过 `dsh plugin` 安装。
|
|
87
|
+
- 上游 `errors.py` 里的 `JsonRpcError` / `TransportClosedError` 是传输层的失败类型;模型结构在 `models.py`(`IncomingRequest`、`InitializeResponse`、`JsonObject`、`JsonValue`、`Notification`)。
|
|
88
|
+
- `sdk-runtime` 把正常 `dsh` CLI 打包成 `deepseek-harness-sdk-runtime-<platform>-<arch>`;`hatch_build.py` 注入运行时可执行文件,editable 安装走 `[tool.uv.sources]`。跨平台 CI 由 master-only 的 Python-runtime 工作流负责。
|
|
89
|
+
- agent-loop / session 生命周期 / `SessionEventMap` 改动必须同步更新 **Python SDK 的单可执行快照**(`scripts/snapshots/python-sdk-single-exe/`)。
|
|
90
|
+
|
|
91
|
+
---
|
|
92
|
+
|
|
93
|
+
## C(Node-API 原生插件)
|
|
94
|
+
|
|
95
|
+
位置:`native/system`(workspace 包 `@deepseek-ai/node-addon-system`,平台包 `darwin-arm64`、`darwin-x64`、`linux-arm64`、`linux-x64` + `entry`)。
|
|
96
|
+
|
|
97
|
+
- 两个能力:**Linux Landlock launcher**(`landlock-run`:`launcherPath`、`probe`、`grantArgs`)与 **POSIX flock**(`tryLockExclusive(fd): Promise<void>`)。
|
|
98
|
+
- 编译:`-std=c11 -Wall -Wextra -Werror`;Node-API 走 `-DNAPI_VERSION=8 -fPIC -fvisibility=hidden`;musl 用 `musl-gcc -static`。
|
|
99
|
+
- 源码是 `packages/entry/src/main.c` 与 `flock.c`,通过 `lib/` 的 TS 门面导出(`tc -b` 之后 `prepack` 跑 `verify-entry-lib.mjs`)。
|
|
100
|
+
- **消费者安装从不编译原生代码**:平台二进制放在平台包里,由 entry 包以 npm optionalDependencies 承载。
|
|
101
|
+
- 语义契约在 `native/system/docs/`(`architecture.md`、`cli-contract.md`、`flock-contract.md`、`naming.md`、`packaging.md`、`release.md`、`support-matrix.md`)—— 改行为同步改契约文档。
|
|
102
|
+
- 重要语义:import 任一 entry **不会**加载 addon;Landlock 可执行文件缺失时 `probe` 报不可用,flock binding 缺失时获取锁直接 reject。两者都不会静默降级或自行编译。
|
|
103
|
+
- flock 语义:非阻塞独占 flock;竞争以 `EAGAIN`/`EWOULDBLOCK` reject;打开文件的最后一个描述符关闭时释放锁;描述符要保持到完成。
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## YAML:Cordis 组合与配置
|
|
108
|
+
|
|
109
|
+
- `cordis.yml` 里 **`!!js` 只允许出现在 plugin 的 `config` 和 entry 的 `disabled` 下**(注意是双感叹号,不是 `!js`);其他元数据保持字面量。条件组合用 patch overlay 表达。
|
|
110
|
+
- 每个 row 的 `config` 由该插件导出的 Schemastery `Config` 校验;**配置字段都有 JSDoc**,生成的 `docs/config-catalog.md` 是穷尽权威。
|
|
111
|
+
- patch **按 `id` 定位 row**:替换整条 config,或插入新行。
|
|
112
|
+
- 裸插件(bare plugin)必须出现在其 resolver manifest 的 `dependencies` 里,`verify-cordis-config` 强制。
|
|
113
|
+
- agent preset 的 `agent.cordis.yml` 是 **agent 平面**:只放该 session 往注册表里贡献的东西;发布服务必须在带 `isolate` 的 group 内。`baseUrl` 在该文件中可用(preset 自身目录),`{{model}}`/`{{cwd}}` 是 persona 模板变量。
|
|
114
|
+
- preset 显示元数据在旁边的 `preset.yml`,只允许 `name` / `description` / `order`(`id` 是目录名,`trust` 来自发现根,二者不可在此声明)。
|
|
115
|
+
- 读失败一律降级为「无元数据」:**显示文本坏了不该让 preset 起不来**。
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## SQLite
|
|
120
|
+
|
|
121
|
+
- 用 **`node:sqlite` 的 `DatabaseSync`**(内建,无第三方驱动),不是 better-sqlite3。
|
|
122
|
+
- 两个后端:`packages/storage/storage-sqlite`(kv facet,`STORAGE_SQLITE_SCHEMA_VERSION = 1`)与 `packages/session-query/session-query-sqlite`(`SESSION_QUERY_SQLITE_SCHEMA_VERSION = 8`,FTS5 全文检索)。
|
|
123
|
+
- 版本存在 **`PRAGMA user_version`**:单调递增;`0` 视为未盖章并写入当前版本;**不匹配就报错拒绝打开**,不静默迁移、不降级。
|
|
124
|
+
- 会话数据本身是 append-only JSONL 日志(`session.jsonl[.zstd]`、v1+ 为 `session.vN.jsonl[.zstd]`)。已提交的 generation 路径**永不重命名、覆盖或删除**;SQLite 只服务查询与 kv 面。
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Shell
|
|
129
|
+
|
|
130
|
+
- 两个 executor provider:`dsh-bash-local` / `dsh-bash-sandbox`(Windows 上是 pwsh 对应实现),模型可见工具是 `dsh-tool-bash` / `dsh-tool-pwsh`。
|
|
131
|
+
- `ctx.shell` 的 request/spec 分离是「包边界显式优于隐式」的模板:默认值解析是拥有方显式的一步 `resolve(request): Spec`,不是 `run()` 里藏的 `?? default`。
|
|
132
|
+
- 子进程要经 sandbox backend 包装 argv。**不要把宿主的运行环境交给不受信输出**:spawn 的命令使用擦洗过的 env(丢弃 `*KEY*`/`*SECRET*`/`*TOKEN*`/`*PASSWORD*`),临时/溢出文件用私有 0700 目录、随机文件名、独占 owner-only 打开(`'wx'`、`0o600`)。
|
|
133
|
+
- 可能是符号链接或 Windows junction 的路径,先 `lstatSync().isSymbolicLink()` 再 `unlinkSync`;递归 `rmSync` 只留给确认的真实目录。
|
|
134
|
+
- 仓库脚本:`scripts/*.ts` 是主入口;只有 7 个 `.sh`(CI/打包辅助)。脚本里的诊断与门禁多数挂在 `scripts/run-gates.ts`。
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Markdown 与文档
|
|
139
|
+
|
|
140
|
+
见 [dsh-harness-project](SKILL.md) 的技能文档分层一节:一段一个物理行、只写当前状态、生成的参考文档不手改、跨引用用相对路径。
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
## 构建与验证工具链
|
|
145
|
+
|
|
146
|
+
| 工具 | 角色 |
|
|
147
|
+
|---|---|
|
|
148
|
+
| **pnpm 11.7.0**(corepack) | workspace + lockfile;workspace 目录:`vendor/*`、`packages/*/*`、`native/system`、`native/system/packages/*`、`apps/*`、`website` |
|
|
149
|
+
| **tsc 6**(project references) | `tsc -b tsconfig.host.json` → `lib/types`;Client 同理 |
|
|
150
|
+
| **tsdown** | 打包 runtime;`--env.DSH_BUILD_FACE host\|client` 选择阶段;只消费前一步 tsc 的产物,**不扫描已有构建产物来发现包** |
|
|
151
|
+
| **tsx** | 跑 TypeScript 脚本与源码 CLI(`node --import tsx/esm`) |
|
|
152
|
+
| **vitest 4** | 全部测试层;所有 vitest config 都通过 vite-tsconfig-paths 指向 `tsconfig.base.json`,**workspace import 永远解析到 `src`**,不走包 `exports` 到已构建的 `lib/`(那里会加载第二份 module singleton) |
|
|
153
|
+
| **oxlint** | lint(`.oxlintrc.json`);`lint:fix` 用 staged 配置 |
|
|
154
|
+
| **jscpd** | `duplication` 跨文件 TS 克隆检测 |
|
|
155
|
+
| **publint + NodeNext 消费者检查** | `hygiene` 门禁组 |
|
|
156
|
+
| **Vite** | `apps/web` 构建前端产物;`pnpm run dev:web` 需要先有一次完整构建 |
|
|
157
|
+
| **Electron 44** | `apps/desktop` 桌面应用;带私有的 Desktop Host 在打包的 Node 进程里加载后端与客户端图,走版本化分帧字节管道,**不开 Web server 或 loopback 端口** |
|
|
158
|
+
| **Playwright/Chromium(测试内)** | `test:web` 浏览器快照 |
|
|
159
|
+
| **hatchling / uv / pytest** | Python 侧 |
|
|
160
|
+
| **cc / musl-gcc** | 原生侧 |
|
|
161
|
+
|
|
162
|
+
**源码面 vs 产物面**:静态门禁与测试通过 tsconfig `paths` 解析到 `src`,必须在干净树上通过;消费已构建 `lib/` 的门禁(built smoke、`lib` 模式子进程)要显式声明该依赖。子进程启动模式由共享 dual-mode launcher 决定,**不要手写 `--import tsx`**。
|
|
163
|
+
|
|
164
|
+
**构建产物污染提醒**:`pnpm run typecheck` 会先跑完整的 Host lib 阶段再跑 Client tsc;`build` 会继续 Client tsdown 与 Web build。构建把版本、7 位源码 commit、脏标记嵌进去——改完代码别指望旧的 `lib/` 还有效。
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## 各语言共同的硬约束
|
|
169
|
+
|
|
170
|
+
1. **一个异步操作对应一个生命周期控制器或事务**;把 readiness/cancellation/disposal/reservation/sentinel 拆成多份状态就必须各有独立 owner 或结算点。
|
|
171
|
+
2. **在提交点发布状态**:通知与派生状态都在操作成功之后;缓存、prompt、UI 回声、replay、查询视图都从同一个权威源派生。
|
|
172
|
+
3. **边界施加在完整结果上**:字节/token/条目/时间上限要在完整产出(含包装与元数据)已知处施加,并测试极小值、精确值、超大单块、多字节边界。
|
|
173
|
+
4. **dispose 要到达静默**:teardown 必须 await 子项退出(kill → await `done`),并在 kill 之前关闭监听/通知注册表。
|
|
174
|
+
5. **回调异常要在 dispatcher 内被兜住**:一个坏监听器不能 reject 它所在的 promise,也不能饿死后面的监听器。
|
|
175
|
+
6. **正交结果独立上报**:超时 + exit 0 可以同时为真;`timedOut`/`signal`/`exitCode` 各报各的,不要把一个塞进另一个分支。
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: dsh-harness-project
|
|
3
|
+
description: Use when working in the deepseek-harness repository — the all-plugin Cordis agent harness — and you need the architecture, package map, profile/bundle boot model, extension points, repository conventions, quality gates, or the answer to "where does this change belong?". Load before writing, reviewing, or explaining code in this repo.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# DeepSeek Harness:项目知识
|
|
7
|
+
|
|
8
|
+
本仓库 = **DeepSeek Harness(dsh)**:一个以 [Cordis](docs/cordis-primer.md) 为底座的「全插件」Agent Harness。版本 `0.1.5-rc.2`,MIT,pnpm workspace monorepo,发布包统一为 `@deepseek-ai/dsh-<name>`。
|
|
9
|
+
|
|
10
|
+
**没有特权内核可打补丁。** 模型适配器、工具注册表、会话日志、甚至 agent loop 本身都是插件;扩展方式是「在旁边挂一个插件」,而不是修改核心。所有注册都是 effect,插件卸载时自动回滚。
|
|
11
|
+
|
|
12
|
+
## 先读什么(权威顺序)
|
|
13
|
+
|
|
14
|
+
1. [AGENTS.md](AGENTS.md) — 常驻规约(root)与 [packages/AGENTS.md](packages/AGENTS.md) — 包级规约。
|
|
15
|
+
2. [docs/architecture.md](docs/architecture.md) — 改动 `packages/` 前必读:组合、核心包、loop、seam、扩展点。
|
|
16
|
+
3. [docs/glossary.md](docs/glossary.md) — 一个概念一个权威术语(seam / scope / turn / step / round / goal / human command)。
|
|
17
|
+
4. [packages/README.md](packages/README.md) — 包组地图;再进目标组的 README,最后进具体包的 README。
|
|
18
|
+
5. `docs/subsystems/<subsystem>.md` — 类型定义、语义、生成的 Cordis API。
|
|
19
|
+
6. `.agents/notes/` — 决策依据(active 决策记录;`archived/` 是冻结历史,**不是**当前权威)。
|
|
20
|
+
|
|
21
|
+
冲突时以代码为准:文档与代码不符是文档缺陷,应报告而不是照抄。
|
|
22
|
+
|
|
23
|
+
## 仓库布局
|
|
24
|
+
|
|
25
|
+
| 路径 | 内容 |
|
|
26
|
+
|---|---|
|
|
27
|
+
| `vendor/` | Cordis 及其基础库的源码内联副本(重命名进 `@deepseek-ai` scope,见 [vendor/README.md](vendor/README.md))。改它要走 vendor 同步流程。 |
|
|
28
|
+
| `packages/<group>/<pkg>/` | 全部 npm workspace 包,按能力族分组(见下)。 |
|
|
29
|
+
| `apps/` | `cli`(`dsh` 可执行入口)、`web`(Vite 前端产物)、`desktop`(Electron)、`desktop-host`。 |
|
|
30
|
+
| `python/` | Python SDK(`sdk/`)与运行时载体(`sdk-runtime/`)。 |
|
|
31
|
+
| `native/` | `@deepseek-ai/node-addon-system`:Linux Landlock launcher + POSIX flock,Node-API 预编译。 |
|
|
32
|
+
| `docs/` | 架构、子系统、生成的参考目录、cookbook、user 指南、i18n。 |
|
|
33
|
+
| `.agents/` | `notes/`(Agent Notes)与 `skills/`(仓库级 skill)。 |
|
|
34
|
+
| `scripts/` | 生成器与质量门禁(`run-gates.ts` 是聚合入口)。 |
|
|
35
|
+
| `snapshots/`、`benchmarks/` | 录制会话快照与性能门禁。 |
|
|
36
|
+
| `website/` | docs/ 的 VitePress 投影。 |
|
|
37
|
+
|
|
38
|
+
包组:`core/`(session、system-prompt、tools、agent、agent-loop、scope)、`llm/`、`subagent/`、`shell/`、`fs/`、`sandbox/`、`session/`、`session-query/`、`storage/`、`settings/`、`credentials/`、`interaction/`、`client/`(`ui-*`)、`host/`、`api/`、`typert/`、`preset/`、`bundle/`、`skill/`、`workflow/`、`webhook/`、`guard/`、`extensions/`、`util/` 等 —— 完整表见 [packages/README.md](packages/README.md),不要在这里复述第二份清单。
|
|
39
|
+
|
|
40
|
+
## 三个平面(改动落点判断的第一步)
|
|
41
|
+
|
|
42
|
+
| 平面 | 拥有什么 | 判据 |
|
|
43
|
+
|---|---|---|
|
|
44
|
+
| **Host composition** | 注册表本体(tools/skills/subagents 注册表)、持久化、sandbox 与审批栈、模型路由、跨会话共享的服务 | 一个在 session 存在之前就完成注入的 host row;或 browser/其他 session 也要读的服务 |
|
|
45
|
+
| **Agent preset**(`agent.cordis.yml`) | 单个 session 往那些注册表里**贡献**什么:工具、prompt section、persona、skill | 每 session 可不同;发布服务时**必须**待在带 `isolate` realm 的 group 里 |
|
|
46
|
+
| **Session** | 该 session 自己的状态(日志、goal、plan、todo) | 按 Session/Agent 分键的状态 |
|
|
47
|
+
|
|
48
|
+
- preset 里发布服务却不带 `isolate` realm → 落进 root realm 变成进程全局,`dsh-agent-presets` 在 mount 时直接拒绝。
|
|
49
|
+
- `isolate: true` = entry-local realm(本次挂载私有);**同名 label 不会共享实例**,label 连接的是 realm。
|
|
50
|
+
- 用户自建 preset 放在 `${DSH_HOME:-$HOME/.dsh}/.agent-presets/<id>/`。**永远不要改内置 preset 安装目录**(升级会覆盖)。
|
|
51
|
+
|
|
52
|
+
## 启动模型:profile / bundle / patch
|
|
53
|
+
|
|
54
|
+
运行中的 `dsh` 是启动时按顺序分层组合出来的插件树。
|
|
55
|
+
|
|
56
|
+
- **profile**:Harness home 里的具名组合,列出它叠加的 bundle、树外插件和用户自己的 `cordis.patch.yml`。内置模板:`web`、`headless`、`sdk`、`sdk-minimal`、`acp`。
|
|
57
|
+
- **bundle**:Cordis config 行 + 其挂载代码的分发格式;在自身 `package.json` 的 `dsh.bundle` 指向 patch 文件,profile 用 `dsh.profile` 列 bundle。
|
|
58
|
+
- **分层顺序**(从空 entry 列表开始):profile 里各 bundle 的列出顺序 → profile 的 `cordis.patch.yml` → home 级 patch → `--patch` overlay。
|
|
59
|
+
- patch 按 **row id** 定位:替换整条 config,或插入新行。
|
|
60
|
+
- 覆盖 `web` profile 默认是 live reload;`headless`/`sdk`/`sdk-minimal`/`acp` 只在启动时应用一次(一次性或 stdio 应用在已拥有工作后替换依赖会破坏生命周期)。
|
|
61
|
+
|
|
62
|
+
```sh
|
|
63
|
+
dsh --profile web --dump-config # 看本机实际启动的树;打印出的任何一行都能被 patch 替换
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**应用启动只有一条路**:`dsh` CLI + 具名 profile(`dsh web` 是 `--profile web` 的别名)。package bin、demo、public SDK argv 直接拼 Cordis 树都是禁止的,`scripts/verify-application-entrypoints.ts` 会拒绝。
|
|
67
|
+
|
|
68
|
+
## 核心包(spine)
|
|
69
|
+
|
|
70
|
+
| 包 | 拥有 | ctx key |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `core/session` | append-only `SessionEvent` 日志与内存存储 | `ctx.sessions` |
|
|
73
|
+
| `core/system-prompt` | prompt section 与 tool schema 组装 | `ctx.systemPrompt` |
|
|
74
|
+
| `core/tools` | 按 scope 的工具注册表 + 受控执行管线 | `ctx.tools` |
|
|
75
|
+
| `core/agent` | `Agent` 接口、活体注册表、`agent/*` 事件 | `ctx.agents` |
|
|
76
|
+
| `core/agent-loop` | 默认 driver(可替换) | `ctx.agentLoop` |
|
|
77
|
+
| `core/scope` | 按 agent 的 scoped 注册原语 | 无 key |
|
|
78
|
+
| `llm/llm` | 消息/流词汇 + adapter seam | `ctx.llm` |
|
|
79
|
+
|
|
80
|
+
## turn / step 与三类事件
|
|
81
|
+
|
|
82
|
+
- **step** = 一次模型请求 + 它触发的工具调用;**turn** = 零或多个 step。
|
|
83
|
+
- 事件分三个域,选对域是大多数改动的第一个决定:
|
|
84
|
+
- **Session events**:追加进日志的持久事实(`turn/*`、`step/*`、`user/message`、`assistant/message`、`assistant/attempt`、`tool/*`、`system/message`)。要求 reload 后仍在,就用它。
|
|
85
|
+
- **Agent events**(`agent/*`):携带活体 `Agent`(inbox、step、status、request、validation、continuation)。观察或拦截进行中的工作用它。
|
|
86
|
+
- **Capability events**(`fs/*`、`tools/*`、`telemetry/*`):给 seam 挂策略和适配器,不必 import loop。
|
|
87
|
+
- **waterfall 监听器必须调用 `next()`** 才算委派;不调用就是短路整条链。`agent/pre-step`、`agent/request`、`llm/stream`、三个 `tools/*` 是 waterfall;`agent/turn-stopping` 是串行、没有 `next()`。
|
|
88
|
+
|
|
89
|
+
## 能力 seam
|
|
90
|
+
|
|
91
|
+
**seam = 可替换能力,三角色齐全**:Service Definition(拥有 `ctx.<key>` 和词汇类型的 Cordis `Service` —— 抽象类如 `ShellExecutor`,或具体注册表如 `WebRuntime`,**绝不是 TS `interface`**)、一个或多个 Service Provider、一个或多个 Consumer(通常是模型可见工具)。`packages/shell` 是范例:`dsh-shell` + `dsh-bash-local`/`dsh-bash-sandbox` + `dsh-tool-bash`。
|
|
92
|
+
|
|
93
|
+
- 只做一个角色不叫 seam。角色独立演化时才分包。
|
|
94
|
+
- **扩展插件依赖 Service Definition,绝不依赖具体 Provider**。
|
|
95
|
+
- 设计 Service Definition 要对齐所有当前 Consumer;让某一个 Consumer 决定 service 契约是反向坏味道。
|
|
96
|
+
|
|
97
|
+
## 新行为放哪里
|
|
98
|
+
|
|
99
|
+
| 目标 | 机制 |
|
|
100
|
+
|---|---|
|
|
101
|
+
| 加模型 provider | 在 `ctx.llm` 注册 adapter |
|
|
102
|
+
| 加模型可见能力 | 注册到 `ctx.tools`,schema 进入 prompt 组装 |
|
|
103
|
+
| 让某个 session 有不同能力集 | 组一个 agent preset(行内服务需 `isolate` realm) |
|
|
104
|
+
| 加 shell 执行 | 注册 `ctx.shell` backend |
|
|
105
|
+
| 加持久终端 | 注册 `ctx.terminals` backend + `dsh-tool-terminal` |
|
|
106
|
+
| 加人类命令(斜杠) | 注册 `ctx.commands`,不产生模型 turn |
|
|
107
|
+
| 加后台工作 | 注册 `ctx.jobs` |
|
|
108
|
+
| 外部 webhook 起 Session | 在 `ctx.webhookRuntime` 注册可信规则 + provider adapter |
|
|
109
|
+
| 文件系统访问或策略 | 注册 `ctx.fs` provider 或监听 `fs/*` |
|
|
110
|
+
| 限制子进程 | 用 `ctx.sandbox` backend |
|
|
111
|
+
| 拦截请求/工具/turn | 用对应 `agent/*` 或 `tools/*` 事件 |
|
|
112
|
+
| 加模型可见上下文 | `agent.inject()`,在下一次被接受的请求中落地 |
|
|
113
|
+
| 加 UI 或编辑器集成 | 驱动 `ctx.agents`,从 `session/event` 渲染 |
|
|
114
|
+
| 加 Web Client Chat 节点 | 注册 `ConversationNodeDefinition` + keyed renderer |
|
|
115
|
+
| 加持久 session 状态 | 扩展 `SessionEventMap`,从日志渲染与回放 |
|
|
116
|
+
| 把注册限定到某个 agent | 用该 agent 的 `agent.ctx` |
|
|
117
|
+
|
|
118
|
+
分步指南在 [docs/cookbook/](docs/cookbook/extension-cookbook.md):加包、加工具、加 LLM adapter、加设置卡片、加 session 格式版本。
|
|
119
|
+
|
|
120
|
+
## 会被拒绝的约定(改动前自查)
|
|
121
|
+
|
|
122
|
+
- **注册即 effect**:一切贡献走 `ctx.effect()` / `ctx.on()`;注册表 `register()` 返回 disposer;每个注册表都要有 HMR 安全测试(dispose fiber,断言清理)。
|
|
123
|
+
- **Model-visible ⟺ logged**:任何进入模型请求的东西都必须能从 session 日志重建(有运行时 invariant 断言)。新增模型可见输入 = 新增 session event + 从日志渲染。
|
|
124
|
+
- **插件,不是改 loop**:新行为挂到已文档化的扩展点;改 `agent-loop` 必须同步更新 `docs/architecture.md`。
|
|
125
|
+
- **不硬编码可调项**:随部署变化的取值是受校验的 `Config` 字段(可从 cordis.yml 改)。`DEFAULT_*` 常量或测试钩子不算可配置性。协议常量、外部规范、安全不变量保持固定。
|
|
126
|
+
- **显式 > 隐式(包边界)**:默认值解析是拥有方实现里显式的一步 `resolve(request): Spec`,不是 `run()` 里藏的 `?? default`。
|
|
127
|
+
- **跨边界的不透明 id 要 brand**(`Branded<B>`,来自 `dsh-brand`),不能是裸 `string`。
|
|
128
|
+
- **类型化边界信任 TypeScript**:不要为静态接口已保证的输入加运行时校验/兜底/敌意输入测试;只在 parser/config、排队、模型/工具 JSON、持久化/文件、worker、进程、wire 边界校验。
|
|
129
|
+
- **源码面 vs 产物面,永不混用**:静态门禁与测试通过 tsconfig `paths` 解析到 `src`,在干净树上通过;消费 `lib/` 的门禁必须显式声明该依赖。
|
|
130
|
+
- **失败要响**:自包含的错误在加载时失败,否则在最早已可解析点失败,绝不静默跳过缺失的引用。
|
|
131
|
+
- **switch 判别式 tag**:封闭联合以 `assertNever` 收尾;可合并扩展的联合走有文档的 default 分支。
|
|
132
|
+
- **测试描述行为而非正确性**:行为过时就连同测试一起改,并在 PR 里说明原因。
|
|
133
|
+
- **非平凡改动必须在同一个 PR 里带一篇 Agent Note**(仅机械/局部编辑豁免)。归档 note 冻结,不得编辑或当作当前权威。
|
|
134
|
+
- **客户端 UI 文案归 locale 所有**:产品文案走类型化字典 + `t`/本地化 props,`verify-client-ui-i18n` 会拒绝硬编码文案。
|
|
135
|
+
- **空 `catch` 要写明吞掉什么**、为什么别的到不了;`try` 只包一条语句。
|
|
136
|
+
- 文件以恰好一个换行结尾(pre-commit 的 `git diff --cached --check` 把关)。
|
|
137
|
+
|
|
138
|
+
## 命令
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
pnpm install # pnpm workspace;Node ^22.19 || >=24,pnpm 11.7.0
|
|
142
|
+
pnpm run typecheck # 先跑完 Host lib 阶段,再 tsc Client
|
|
143
|
+
pnpm run lint # oxlint(先 build:lib:host)
|
|
144
|
+
pnpm run test # vitest 单测
|
|
145
|
+
pnpm run test:coverage # CI 覆盖率门禁:packages/*/*/src 逐文件 100%
|
|
146
|
+
pnpm run test:e2e # 真 API 测试;无 DEEPSEEK_API_KEY 自行跳过
|
|
147
|
+
pnpm run test:expected # owner 本地进程期望输出
|
|
148
|
+
pnpm run test:snapshot # 无密钥录制会话回放(-t <name> 过滤)
|
|
149
|
+
pnpm run test:web # 浏览器快照(先 build)
|
|
150
|
+
pnpm run build # tsc 产出 lib/types,tsdown 打包 runtime
|
|
151
|
+
pnpm run hygiene # publint + workspace/包/依赖检查 + NodeNext 消费者检查
|
|
152
|
+
pnpm run doc-sync # 全量文档门禁
|
|
153
|
+
pnpm run test:docs # 快速文档检查(doc-quick)
|
|
154
|
+
pnpm run check:all # 聚合门禁
|
|
155
|
+
pnpm run duplication # 跨文件 TS 克隆检测(jscpd)
|
|
156
|
+
pnpm dsh --profile headless "task" # 从源码跑一次真实任务(需 key)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
改了代码之后选**覆盖该改动面**的最小检查,不要反射性地跑全量:行为测试、model/user 输出快照、文档用 `doc-sync`、发布路径用 built smoke、provider 用真 API e2e。CI 负责穷尽覆盖与平台矩阵。
|
|
160
|
+
|
|
161
|
+
## 测试分级与「什么时候必须有快照」
|
|
162
|
+
|
|
163
|
+
- **Unit**(`pnpm run test`):vitest,spec 与被测代码同区;每个注册表要有 HMR 安全测试;偏好边界、错误路径、事件顺序、并发竞争、契约回归的永久测试。
|
|
164
|
+
- **覆盖率门禁**(`test:coverage`):逐文件 100%。未覆盖的行往往是该删的死代码,而不是该补的测试。行覆盖必要但绝不充分。
|
|
165
|
+
- **真 API e2e**(`test:e2e`):无 key 自跳;**不要省真 API 测试**——无 key 只证明管道通,有 key 才证明 agent 能用。最高价值是启动 shipped profile 的 smoke。
|
|
166
|
+
- **快照**(`test:snapshot`):顶层 scenario 的最高父代 generation 提供用户输入与模型回放,并作为期望的持久结果。改模型 transcript 用 `test:snapshot:record`,输入仍有效用 `refresh`。
|
|
167
|
+
- **Web 浏览器快照**(`test:web`):Chromium 比对 `snapshots/web/`;CI 强制 `DSH_SNAPSHOT=replay` 只读。
|
|
168
|
+
- **任何非平凡、模型/协议/用户可见的改动,都要在同一个 PR 里新增或更新一个无密钥录制会话 scenario。** 包测试、e2e、mock-only 证据都不能替代组装后的 transcript。
|
|
169
|
+
- agent-loop / session 生命周期 / `SessionEventMap` 改动要同步更新 **TypeScript 与 Python 两套 SDK 期望输出**。
|
|
170
|
+
- **优先真实现,少用 mock**:只 mock 昂贵或不确定的边界(LLM adapter、网络、时钟),下游全部保持真实。
|
|
171
|
+
- **验证世界,不验证自述**:e2e 断言要重新执行命令或重新读文件;对 agent 自身输出的关键字探测会让作弊的 agent 通过。
|
|
172
|
+
- **测试真入口路径**:产品可见插件必须有非 unit 的 REAL 组合测试(通过 Loader 与 app/process 启动测试专用 `cordis.yml`)。
|
|
173
|
+
- spec 在 fork worker 里并发执行:端口、路径、子进程都要自己负责到 teardown;「单独跑才过」的 spec 是 spec 的缺陷。
|
|
174
|
+
|
|
175
|
+
## 文档分层(一个事实只有一个家)
|
|
176
|
+
|
|
177
|
+
| 层 | 职责 |
|
|
178
|
+
|---|---|
|
|
179
|
+
| root `AGENTS.md` | 常驻命令:每个 session 都要在上下文里的规则,每条 1-3 行并链到它的家 |
|
|
180
|
+
| 子树 `AGENTS.md` | 该子树特有规则 |
|
|
181
|
+
| `docs/architecture.md` | 有序地图:组合、核心包、loop、seam、扩展点 |
|
|
182
|
+
| `docs/subsystems/` | 每子系统一页参考:类型定义、语义、生成的 Cordis API |
|
|
183
|
+
| `.agents/notes/` | 决策记录:为什么、放弃了什么、需要什么验证 |
|
|
184
|
+
| `docs/postmortem/` | 事故叙事(唯一允许 war story 的层) |
|
|
185
|
+
| `docs/cookbook/` | 带编号验证步骤的 how-to |
|
|
186
|
+
| 包 README | 该包的契约:配置、语义、限制、扩展点、Model Experience |
|
|
187
|
+
| 生成参考(subsystems 的 `cordis-surface` 区、cordis-api、tool-catalog、config-catalog、persistence-catalog、module-graph) | 从源码生成、有新鲜度门禁;**不要手改** |
|
|
188
|
+
| `.agents/skills/` | 可复用工作流与专业判断标准 |
|
|
189
|
+
|
|
190
|
+
放置规则:bug → postmortem;why → Agent Note;how-to → cookbook;类型 → subsystems;包契约 → README;常驻规则 → root `AGENTS.md` + 依据链接。
|
|
191
|
+
|
|
192
|
+
写作规则:**只写当前状态,不写变更史**(不出现 previously/now/no longer/PR 编号);**每段一个物理行**(`verify-md-wrap`);`ts` 代码块必须能编译(`doc-typecheck`);改了被文档化的类型,同一改动里更新 owning subsystems 页面;跨引用用相对 Markdown 路径,`verify-md-links` 会拒绝死链;JSDoc 写完整契约,不写推理过程。
|
|
193
|
+
|
|
194
|
+
## 怎么找「谁拥有 X」
|
|
195
|
+
|
|
196
|
+
1. `grep` 服务 key(`ctx.<name>`)→ 命中 `Service` 声明所在包 = 拥有方。
|
|
197
|
+
2. `docs/subsystems/` 里找同名端点 → 拿到类型与语义。
|
|
198
|
+
3. `.agents/notes/` 里搜关键词 → 拿到为什么这么设计、放弃了什么。
|
|
199
|
+
4. `packages/<group>/README.md` → 确认它属于哪个能力族、同族还有谁。
|
|
200
|
+
|
|
201
|
+
## 常见坑
|
|
202
|
+
|
|
203
|
+
- 把 `interface` 当成 Service Definition(seam 的 Service Definition 必须是 Cordis `Service`)。
|
|
204
|
+
- 在扩展插件里直接依赖具体 Provider,而不是 Service Definition。
|
|
205
|
+
- waterfall 监听器忘记 `next()`,静默短路后续策略。
|
|
206
|
+
- 让一个新的模型可见输入绕过 session event —— 破坏「可重建」不变量。
|
|
207
|
+
- 在 preset 里裸发布服务(缺 `isolate` realm),mount 时被拒。
|
|
208
|
+
- 改行为却不同步包 README / JSDoc / Agent Note / 快照。
|
|
209
|
+
- 直接改 `vendor/` 或生成参考文档(手改会被门禁打回)。
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: t-expert-manager
|
|
3
|
-
description: T专家 运维台 ——
|
|
3
|
+
description: T专家 运维台 —— 316 位专家 / 22 分区的名册增删、名册一致性校验、统计与中文覆盖、小队(/t)成员编辑、装机到 DSH Desktop、发布到 npm。Use when the user asks to add/remove/validate/count T专家 experts, 新增专家 / 删除专家 / 校验名册 / 名册统计 / 改小队 / 重装插件 / 发布插件.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# T专家 运维(expert-manager)
|
|
@@ -16,8 +16,9 @@ description: T专家 运维台 —— 315 位专家 / 22 分区的名册增删
|
|
|
16
16
|
这些动作脚本都代劳了,绕开脚本换来的就是"源码加了、运行时没加"这类半成品状态。
|
|
17
17
|
2. **`data/experts/` 是真源**。增删由 `add-expert.py`(tz.sh 代跑)执行,它**同时写**源码与运行时
|
|
18
18
|
`~/.t-team/experts/`,两边永远一致。
|
|
19
|
-
3.
|
|
20
|
-
|
|
19
|
+
3. **统计必须递归**。有专家落在嵌套子目录(如 `game-development/unreal-engine/…`),
|
|
20
|
+
只看分类目录的第一层会漏掉它们。位数一律以 `tz.sh status` 的递归结果为准 ——
|
|
21
|
+
正文里不写死位数,因为每加一位专家它就会过期。
|
|
21
22
|
4. **数据更新不用重装、不用重启**(宿主按 mtime 指纹自动重载名册);**改插件代码**才需要
|
|
22
23
|
`tz.sh build` → `tz.sh install` → 重启 DSH Desktop。
|
|
23
24
|
5. **小队改完必须 `tz.sh squads` + 重启 DSH Desktop** 才对建队生效。
|
|
@@ -72,7 +72,7 @@ tz.sh publish-dry | publish [--patch|--minor|--major|--version X.Y.Z] [--retry]
|
|
|
72
72
|
|
|
73
73
|
| 内容 | 真源 | 说明 |
|
|
74
74
|
| --- | --- | --- |
|
|
75
|
-
| 专家名册 | `<ops>/dsh-plugin-t-expert/data/experts/` | 22 分类 /
|
|
75
|
+
| 专家名册 | `<ops>/dsh-plugin-t-expert/data/experts/` | 22 分类 / 316 位;运行时是它的同步副本 |
|
|
76
76
|
| 中文侧车 | `<ops>/dsh-plugin-t-expert/data/zh/` | **已冻结**,只读不写 |
|
|
77
77
|
| 小队定义 | 数据目录 `teams.json` | 人工维护;`data/` 与 `~/.t-team/` 同一份(软链) |
|
|
78
78
|
| 小队编译产物 | 数据目录 `t-team.config.json` | 由 `team-profiles.py` 生成,**不要手改** |
|
|
@@ -92,7 +92,7 @@ tz.sh publish-dry | publish [--patch|--minor|--major|--version X.Y.Z] [--retry]
|
|
|
92
92
|
|
|
93
93
|
| 现象 | 原因 / 处理 |
|
|
94
94
|
| --- | --- |
|
|
95
|
-
|
|
|
95
|
+
| 名册少了几位 | 只数了分类目录的第一层(嵌套子目录里的专家被漏掉)—— 必须递归,以 `tz.sh status` 为准 |
|
|
96
96
|
| `experts check` 报"运行时缺/多出" | 绕开脚本手工拷贝过文件;用 `experts add` 重做那一条 |
|
|
97
97
|
| 新增专家后面板看不到 | 面板按 mtime 指纹自动重载;仍看不到就查该专家是否被**启用**(设置页 T专家 标签,默认全禁用) |
|
|
98
98
|
| 改了小队但 `/t` 里没有 | 没跑 `tz.sh squads`,或没重启 DSH Desktop |
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
| 文件 | 覆盖的随包内容 | 来源 |
|
|
7
7
|
| --- | --- | --- |
|
|
8
|
-
| `agency-agents.LICENSE` | `data/experts/`(22 分区 /
|
|
8
|
+
| `agency-agents.LICENSE` | `data/experts/`(22 分区 / 316 位;其中 315 位来自第三方 —— 279 位为上游仓库逐字节镜像、35 位来自名册来源包快照;余 2 位为本仓自建,不由本许可覆盖) | The Agency / AgentLand 名册快照,MIT |
|
|
9
9
|
| `agency-agents-zh.LICENSE` | `data/zh/` 中的中文名字、简介与人格正文 | `agency-agents-zh` 中文翻译与本地化资产,MIT |
|
|
10
10
|
|
|
11
11
|
两份文本都是从实际用于生成快照的来源包内**逐字节复制**的,未经改写:
|