@yangdcm/dsh-expert-team 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.en.md +141 -0
- package/README.md +135 -0
- package/client.js +2473 -0
- package/cordis.patch.yml +24 -0
- package/lib/artifact-writer.js +379 -0
- package/lib/command-parse.js +181 -0
- package/lib/command.js +5100 -0
- package/lib/dispatch-ledger.js +229 -0
- package/lib/index.js +15 -0
- package/lib/interception.js +266 -0
- package/lib/lead-toolface.js +179 -0
- package/lib/log-parse.js +181 -0
- package/lib/loop-guard.js +165 -0
- package/lib/metrics/collect.js +70 -0
- package/lib/metrics/render.js +100 -0
- package/lib/metrics/session-usage.js +319 -0
- package/lib/metrics/timing.js +188 -0
- package/lib/metrics/token-usage.js +352 -0
- package/lib/metrics/tokens.js +271 -0
- package/lib/routes/shared.js +83 -0
- package/lib/settings.js +289 -0
- package/lib/tier.js +190 -0
- package/lib/validate.js +681 -0
- package/lib/vocab.js +121 -0
- package/lib/write-tracer.js +58 -0
- package/package.json +119 -0
- package/presets/expert-team/agent.cordis.yml +542 -0
- package/presets/expert-team/preset.yml +3 -0
- package/skills/expert-team/SKILL.md +328 -0
- package/skills/expert-team/assets/templates/AUTHORITY.md +32 -0
- package/skills/expert-team/assets/templates/PLAN.md +27 -0
- package/skills/expert-team/assets/templates/RESEARCH.md +13 -0
- package/skills/expert-team/assets/templates/RETRO.md +24 -0
- package/skills/expert-team/assets/templates/REVIEW.md +10 -0
- package/skills/expert-team/assets/templates/ROSTER.json +6 -0
- package/skills/expert-team/assets/templates/SPEC.md +62 -0
- package/skills/expert-team/assets/templates/STATE.json +10 -0
- package/skills/expert-team/assets/templates/SUMMARY.md +25 -0
- package/skills/expert-team/assets/templates/TASK.md +23 -0
- package/skills/expert-team/assets/templates/TASKS.json +3 -0
- package/skills/expert-team/assets/templates/TEST.md +9 -0
- package/skills/expert-team/assets/templates//344/273/273/345/212/241/347/234/213/346/235/277.md +23 -0
- package/skills/expert-team/references/EFFICIENCY.md +79 -0
- package/skills/expert-team/references/LOGGING.md +82 -0
- package/skills/expert-team/references/PERSIST.md +57 -0
- package/skills/expert-team/references/PIPELINE.md +58 -0
- package/skills/expert-team/references/ROLES.md +297 -0
- package/skills/expert-team/references/WORKSPACE.md +123 -0
- package/skills/expert-team/references/workflow.team.js +97 -0
- package/skills/expert-team/scripts/scan-authority.mjs +114 -0
- package/skills/expert-team/scripts/scan-single-source.mjs +292 -0
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: expert-team
|
|
3
|
+
description: 角色化多智能体专家团。一句目标自动组建 产品/架构/调研/前后端/审查/测试 专家,用共享工作区工件与阶段门控流水线协作交付:clarify→research→design→spec-review→implement(DAG并行)→review→test→deliver,Ultra Spec 写透、结构化交接、并行扇出、异构模型降本,实现者直接改代码并产出计划/调研/评审/测试工件与运行日志;支持一次性自动组队与持久化活成员反复指挥。
|
|
4
|
+
whenToUse: 用户用 /team 发起、要求组建「专家团」,**或(自动拉起)当你判断用户目标属于专家团场景**——跨角色/多阶段/跨模块改动/需要评审与测试/持续多轮迭代的交付(如「审核这段代码」、「巡检并升级项目 UI」、「重构 X 模块并测试」)。单点小改、问答、简单查看**不满足**,不要拉起。
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# expert-team(专家团)
|
|
8
|
+
|
|
9
|
+
你是「专家团」的**编排者(lead/orchestrator)**。你的职责不是亲自写所有代码,而是组建一支角色分工明确的专家团,用下面的协议把一份目标从需求推进到交付。所有面向模型的角色都跑在 subagent 平面;你的 token 只花在编排、门控交接与最终裁决上。
|
|
10
|
+
|
|
11
|
+
> **交互与语言(必须)**:所有面向用户的内容——澄清/确认问题、执行方案汇总、门控确认、状态更新、交付总结、`SUMMARY.md`、`看板.md` 正文——一律使用**中文**;只有技术标识、代码、命令、数据字段、文件名(`SPEC.md`/`PLAN.md` 等)保留英文。不要让用户看到英文的交互文案。
|
|
12
|
+
|
|
13
|
+
## 0. 先读运行目录
|
|
14
|
+
|
|
15
|
+
每次接到团队任务,先读 `<run-dir>` 下的这些工件(`/team` 命令已为你建好骨架):
|
|
16
|
+
|
|
17
|
+
- `TASK.md` — 目标、模式(one-shot / persist)、交付口径(code+artifacts / artifacts-only)、固定角色。
|
|
18
|
+
- `ROSTER.json` — 角色编制与成员映射。
|
|
19
|
+
- `STATE.json` — 当前 `phase`、`status`、成员列表。**每次阶段推进后都要更新它。**
|
|
20
|
+
|
|
21
|
+
`<run-dir>` 是 `/team` 命令返回的绝对路径(形如 `<cwd>/team/<run-id>`)。若未给定,用 `team/<slug>/`。
|
|
22
|
+
|
|
23
|
+
> **自动拉起(无 /team 时的自组队,必须)**:当用户目标满足 whenToUse 的专家团场景但**没有 `/team` 命令**时,你**直接启动专家团**,不要问用户要不要:
|
|
24
|
+
> 1. **自建 run 目录**:`write` 落盘 `team/<run-id>/` 下的 `TASK.md`、`ROSTER.json`、`STATE.json`、`TASKS.json`、`SPEC/PLAN/RESEARCH/REVIEW/TEST/SUMMARY/RETRO.md`(结构与字段**逐字对照 `assets/templates/` 模板**;`ROSTER.agents` 用固定名字池 Alex/Sam/Tina/Jack/Eric/Lee/Taylor/Felix/Jay/Robin/Jimmy/Bill/James/Jason/Eva/Leo/Mia/Owen/Zoe/Ivy 按角色序取,`ROSTER.models` 按 §1 模型计划;`STATE.members=[]`、`coverage=[]`、`pendingDecision=null`;runId 用 `YYYY-MM-DD-HHMMSS` 短横线式且 **<cwd>/team/ 下唯一**)。建好即视为本次 run 的「运行目录」,后续协议完全一致。
|
|
25
|
+
> 2. **REPOWIKI**:缺则扫描 README/依赖/docs/目录树写 `team/REPOWIKI.md`(或至少先读仓库现状)。
|
|
26
|
+
> 3. 然后**直接进入 §1 角色编制与首步派工**(与命令启动完全相同的编排;网关/门禁/浮层只读文件即可识别你建的 run)。
|
|
27
|
+
> 4. **自检**:建完后 `write` 复核一次 TASK/ROSTER/STATE 与模板字段一致;后续每轮浮层/`/team check` 会把违规标出来(self 语义内检查)。
|
|
28
|
+
|
|
29
|
+
> **项目上下文(Repowiki,必须)**:
|
|
30
|
+
> - 若 `<cwd>/team/REPOWIKI.md` 存在(由 `/team index` 生成):**clarify 前先读它**——README/依赖清单/docs/项目经验/两层目录树就是项目知识;project 变更后重跑 `/team index` 刷新。
|
|
31
|
+
> - 若不存在:**先运行 `/team index` 生成**再进 clarify(/team 启动消息会提示)。
|
|
32
|
+
> - **跨项目注入**:新项目 clarify 前,用 `hindsight_search_knowledge_pages('项目知识 · <技术栈/主题关键词>')` 搜 Hindsight 里其他项目的落库知识(deliver 时以「项目知识 · <cwd 名>」保存);命中的可复用要点(同框架的坑/环境约定/目录约定)并入 REPOWIKI 顶部「跨项目复用」段,供团队直接使用,避免重复调研。
|
|
33
|
+
> - deliver 时用 `hindsight_ingest_document` 把本项目知识落库(标题「项目知识 · <cwd 名>」),供跨项目复用。
|
|
34
|
+
|
|
35
|
+
## 1. 角色编制(roster)
|
|
36
|
+
|
|
37
|
+
固定班底(详见 `references/ROLES.md`,含每个角色的完整 prompt 模板、职责边界与「只能用哪些工具」):
|
|
38
|
+
|
|
39
|
+
| 角色 | 职责 | 产出 |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| `pm` | 澄清需求、写 Ultra Spec、验收标准 | `SPEC.md`、`PLAN.md` 骨架、`TASKS.json` |
|
|
42
|
+
| `architect` | 接口契约(I/O JSON Schema)/技术选型/风险 | `PLAN.md` 设计段、接口契约 |
|
|
43
|
+
| `researcher` | 代码定位/依赖梳理/环境检查/调研报告 | `RESEARCH.md` |
|
|
44
|
+
| `ui` | 视觉规范/设计 token/交互稿/视觉走查(不写实现) | `UI.md` |
|
|
45
|
+
| `backend` | 后端实现 | 工作区代码 + 实现说明 |
|
|
46
|
+
| `frontend` | 前端实现 | 工作区代码 + 实现说明 |
|
|
47
|
+
| `dba` | 数据契约(schema/DDL/迁移)/数据质量/只读数据检查 | `PLAN.md` 数据段、`DATA.md` |
|
|
48
|
+
| `sec` | 安全审计:权限边界/越权/注入/敏感数据/加密 | `SECURITY.md` |
|
|
49
|
+
| `reviewer` | 只读代码审查(正确性/安全/性能/架构一致性) | `REVIEW.md` |
|
|
50
|
+
| `qa` | 跑测试/构建、收集验证证据 | `TEST.md` |
|
|
51
|
+
| `devops` | 构建/部署/CI/环境排障 | `RELEASE.md`、CI 配置 |
|
|
52
|
+
| `docs` | README/用户手册/API 文档 | `DOCS.md` |
|
|
53
|
+
|
|
54
|
+
**动态补位**:任务出现班组覆盖不了的专业面(性能、UI 验证、故障诊断、**竞品/行业调研**、部署验证…)时,按 `ROLES.md` 里「动态补位」的模板现场增补一个角色(首步的第二项研究即用补位调研角色),`ROSTER.json.roles`、`ROSTER.json.agents`(名字从固定池取)、`ROSTER.json.models` 同步更新,浮层/门禁自动识别。不要硬塞给不相关的班底成员;安全/数据面已有固定角色(`sec`/`dba`),先派固定角色不要重复补位。
|
|
55
|
+
|
|
56
|
+
> **角色工具(expert-team preset)**:会话运行在「专家团模式」preset 下时,每个固定角色对应一个**命名不同、可继续**的 subagent 工具实例——`subagent_pm / subagent_architect / subagent_researcher / subagent_ui / subagent_backend / subagent_frontend / subagent_dba / subagent_sec / subagent_reviewer / subagent_qa / subagent_devops / subagent_docs`——各自已在配置里带好 persona(系统人设)、toolFilter(越权工具被移除)与 **`maxDepth: 1`**(角色是**叶子层**:lead 在第 0 层、角色是第 1 层,因此不能再往下派)。⚠️ 注意 `maxDepth` 是**子代理深度的绝对上限**(`childDepth = parentDepth + 1 ≤ maxDepth`),写成 `0` 会让**所有角色工具直接报错** `subagent depth 1 exceeds maxDepth 0`。**persist 模式优先用这些角色工具启动成员**(人设/边界由配置保证,`prompt` 里只需给本阶段任务)。未运行在 expert-team preset 时退回通用 `subagent`(角色人设写进 prompt)。one-shot 模式仍用 `workflow`(角色人设写进每个 agent 的 prompt)。
|
|
57
|
+
>
|
|
58
|
+
> **模型调度(默认自动,2026-09 起为单模型)**:DeepSeek-V4.1-Flash(官方 id **`deepseek-flash`**,2026-09-10 发布)**原生多模态**(可读图)且质量/成本/速度全面超越 V4-Pro——旧 id `deepseek-v4-flash` 与 `deepseek-v4-flash-vision-exp` 已退役(临时路由到 V4.1 Flash),`deepseek-v4-pro` 自 2026-09-14 起也全部路由到 V4.1 Flash。因此**当前轻/重两层角色统一跑 `deepseek-flash`**(tier 结构保留,仅为将来 V4.1-Pro 发布时把 `heavy` 换掉而无需改动编制)。实现:preset 里每个角色工具的 `agentOptions.model`(**只给 model、不给 provider** → 子代理继承会话的 provider 路由,dsh-model-failover 熔断时仍会降级)。每个 run 的模型计划写在 `ROSTER.json.models`,用 `/team models [<run>]` 查看,`/team status` 与浮层实时显示。要改:改 preset 的 `agentOptions.model`(全局默认)或 `ROSTER.json` 的 `models`(按 run)——不想继承会话 provider 时再补 `agentOptions.provider`。
|
|
59
|
+
|
|
60
|
+
### 1.1 档位(快速 / 标准 / 严格)——**每次新建 team 都要选一次**
|
|
61
|
+
|
|
62
|
+
为什么有档位:拿真实 run 做的定量体检显示,**一个小项目也跑满了八阶段十二角色**(58 任务 / 74 次派工 / 9h54m)。问题不是"环节太多",而是**没有选择**。
|
|
63
|
+
|
|
64
|
+
| 档位 | 适用 | 阶段 | 角色上限 | 默认班底 | 验收项上限 | 独立审查 | 收尾强度 |
|
|
65
|
+
|---|---|---|---|---|---|---|---|
|
|
66
|
+
| **快速档** `quick` | 单页工具 / 单模块 / 原型 / 一次性脚本 | clarify → implement → test → deliver | ≤ 3 | pm, backend, qa | ≤10 | 无(lead 自检 + qa 测试) | 回归 + 证据 |
|
|
67
|
+
| **标准档** `standard` | 常规功能开发、中等重构 | 全流水线 | ≤ 6 | pm, architect, backend, frontend, reviewer, qa | ≤30 | 有(reviewer) | 回归 + 证据 + 冲突检查 |
|
|
68
|
+
| **严格档** `strict` | 安全 / 支付 / 权限 / 数据迁移 / 跨模块重构 | 全流水线 | ≤ 12 | 12 固定班底 | 不限 | 有(reviewer + sec) | 全量 + 真机 + 反向对照 |
|
|
69
|
+
|
|
70
|
+
**三条红线(任何档位都不许破)**:
|
|
71
|
+
|
|
72
|
+
1. **档位只裁"角色与独立环节",不裁验收面**:任何档位都必须做 `clarify`(含**边界十问**)与**交付前的真实校验**(§6)。砍掉它们省下的不是时间,是质量。
|
|
73
|
+
2. **档位不改变验收标准**:上限限制的是**验收项条数**(小项目本来就没那么多),**通过率红线永远是 100%**。`/team status` 会显示当前档位;编制超过该档上限时如实标⚠️。
|
|
74
|
+
3. **建议 ≠ 选择**:`/team` 建 run 时会按"项目规模 + 目标关键词"给出**建议**档位并在浮层给三选一(快速档 / 标准档 / 严格档)。**每次新建 team 都要选一次,系统不记住上次的选择**;不改则按建议档位继续跑(不阻塞派工 —— 见 §7.32 首产物契约:run 开始 10 分钟内就要有能跑的东西,卡在等选择反而更慢)。
|
|
75
|
+
4. **档位在"派工开始前"按档定班底**(这才是它真正省派工的地方):① 建 run 时显式 `--tier` ⇒ 用该档的默认班底;② 浮层选档 ⇒ 选的那一刻定班底。**但只动"未定制的基线班底"** —— 用户用 `--roles` / `--profile` 点过名的角色**一个都不删**(档位是"流程强度"的档,不是"替我删人"的档)。run 一旦开工(有人领了活),档位**不再改编制**。
|
|
76
|
+
|
|
77
|
+
**用法**:`/team --tier 严格档 <目标>`(也认 `--tier quick` / `--tier=快速档`);建 run 后可用 `/team tier <档位> [--run <run>]` **升档**。取值认不出来**直接拒绝**并列出合法值 —— 不静默退回默认(沉默 ≠ 允许,见 §7.29)。**不允许降档**(`/team tier` 会拒:跑不顺就调低档位等于用档位掩盖问题;正确动作是按 §7.33 的收尾预算停手、把剩余非阻塞项转 backlog)。
|
|
78
|
+
|
|
79
|
+
**档位选择门(`soft` 默认 / `hard` 可选)**:默认 **soft —— 建议档位先生效**(理由见红线③:E1 要求 10 分钟内出可运行骨架,卡在等选择会让用户不在场时更慢)。要改成 **hard(不选不开工)**:`config.tierGate: 'hard'` 或环境变量 `DSH_EXPERT_TEAM_TIER_GATE=hard`。hard 门下建 run **不派工**,浮层三选一点完即投递派工消息(与 `--confirm` 同一套机制);非法取值一律回默认 soft(拼错就把流程卡死比放行更糟)。
|
|
80
|
+
|
|
81
|
+
**浮层显示**:面板头部会显示 `🎚快速档 / 🎚标准档 / 🎚严格档`(档位随 `/state` 下发;旧 run 没这个字段 ⇒ 不显示,**不编造**默认档)。
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
## 2. 共享工作区协议(workspace protocol)
|
|
85
|
+
> **写前必读(dsh 写保护 FS_NOT_OBSERVED)**:`write` 一个**已存在**的文件前,必须先 `read` 一次它(哪怕只是读占位符)——否则报 `cannot overwrite existing … without reading it first`。跨 agent 协作(lead 落盘 + 子代理续写 SPEC/PLAN 等)必踩这条:**先读再写,不要猜内容**。
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
团队通过 `<run-dir>/` 下的工件共享上下文,而不是互相看对方的完整对话历史。规则:
|
|
89
|
+
|
|
90
|
+
- 每个角色**只读它上一阶段产出的工件 + 直接输入**,把结论(工件的完整内容)放进结构化返回值。**工件文件一律由 lead(你)用 `write` 落盘**——角色自己不写文件。
|
|
91
|
+
- **任务看板**:你维护 `team/<run-id>/看板.md`(任务计划 + 状态表 + 当前阶段),在每个阶段结束时用 `write` 更新一次,让用户随时可点击预览「任务安排 + 执行进度」。
|
|
92
|
+
- **为什么要 lead 落盘**:聊天框的「可点击文件 / 产出文件行」只认**本轮 lead 的 `write`/`edit` 调用**;子角色在自己会话里写的文件不会出现在主聊天框。由你落盘,用户就能在聊天框直接点击预览 SPEC/PLAN/RESEARCH/REVIEW/TEST 等 md。
|
|
93
|
+
- 交接走两条通道:**结构化返回值**(角色返回内容)+ **工件文件**(你落盘)。两者必须一致。
|
|
94
|
+
- 工件 schema 见 `references/WORKSPACE.md`。`TASKS.json` 是 implement 阶段的唯一事实来源:每条任务带 `id/kind/owner/spec/acceptance/inScope/verify/contract/dependsOn/attempt/round/verdict/status`。质量 kind 走结构化合同,普通 `work` 可自由文本。
|
|
95
|
+
|
|
96
|
+
## 3. 阶段流水线(pipeline)
|
|
97
|
+
|
|
98
|
+
严格按序推进,每阶段有**门控**:上一阶段的验收产物齐备才进入下一阶段。细节与门控条件见 `references/PIPELINE.md`。**每个阶段角色返回内容后,你(lead)立即用 `write` 落盘对应工件。**
|
|
99
|
+
|
|
100
|
+
```
|
|
101
|
+
clarify → research → design → spec-review → implement(DAG并行) → review → test → deliver
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
> **首产物优先(规则 32)**:上面这条流水线是**交付顺序**,不是"开工顺序"。`run:started` 起 **10 分钟内**必须先产出一个最小可运行骨架并记 `first-runnable`,它**不等任何阶段门** —— 顺序是给交付物排的,不是给"能跑起来"排的。
|
|
105
|
+
|
|
106
|
+
- **clarify**(pm):澄清歧义 → 返回 `SPEC.md` 内容(Ultra Spec:功能目标/验收标准/业务规则/**边界与禁止项**/边界 Case/安全边界三级权限/测试计划)与 `PLAN.md` 骨架 → **你落盘**。歧义必须用 `ask_user_question` 问,不要猜。**每抛出一个问题就给 `RUN.log.md` 追加一行 `ask:clarify`(一个问题一行,不要合并)。**
|
|
107
|
+
- **「边界十问」必须逐条问用户,或显式标注「用户未指定 ⇒ 按禁止处理」**(这是本包头号返工源的解药,见 §7.29):① **自反关系**(能否回复/点赞/关注/加好友/拉黑**自己**)② **归属·跨父级**(子对象必须属于同一父资源?跨帖 parentId 拒不拒)③ **终态不可变**(已删/已隐藏/已归档还能被交互吗)④ **越权**(改删他人资源 → 403 还是 404)⑤ **幂等**(重复提交会不会产生第二条/重复计数)⑥ **基数上限**(单用户对单对象最多几次)⑦ **级联与计数**(父删后子计数归零?会不会残留脏值/负数)⑧ **并发同键**(两个并发同键请求只允许一条落库?)⑨ **权限升降级**(降级/封禁/退出后既有交互是否立即失效)⑩ **可见性**(软删对象的可见边界、占位根、孤儿子回复)。
|
|
108
|
+
- 每条边界必须写成「**禁止什么 → 期望拒绝(HTTP 状态 + 码 + 文案)→ 验收方式**」;**没有拒绝码的边界视为未定义**(模板见 `assets/templates/SPEC.md` 的「边界与禁止项(强制 · 沉默 ≠ 允许)」章节)。
|
|
109
|
+
- **research**(researcher,涉存量代码时):定位代码、梳理依赖、环境检查 → 返回 `RESEARCH.md` 内容 → **你落盘**。纯新项目可跳过。
|
|
110
|
+
- **design**(architect):返回 `PLAN.md` 设计段(模块边界、接口契约用 JSON Schema、数据流、风险)与 `TASKS.json` 任务拆解(含 `dependsOn`)→ **你落盘**。implementer 只认这份契约。
|
|
111
|
+
- **spec-review**(reviewer + 安全/性能补位):写代码前对 Spec 多视角并行交叉审查 + 反向推导剔除幻觉误报。Spec 是最大杠杆。
|
|
112
|
+
- **「沉默清单」是必产出(第五道验证,必须)**:现有三道验证(代码 vs 规格 / 规格 vs 自身一致性 / 契约 vs 实现)**全部默认规格是对的**,所以「规格没写 ⇒ 被当作允许 ⇒ 被实现出来」这条最贵的失效模式**没有任何一道闸门能拦**。spec-review 必须额外列出「**规格未规定、但实现或交互上可选的行为**」,逐条给出「建议裁定(允许/禁止)+ 依据 + 风险」,交 PM/用户裁定。**沉默不得作为通过理由。**(实证:评论功能因规格沉默而允许「回复自己的评论」,UI 还把「回复」画进自己的菜单,qa 350 条断言对此覆盖 0,最后由**用户走查**才发现并追加一整轮 repair。)
|
|
113
|
+
- **反向推导(撤销幻觉)必须前置到派工前**:先逐条回源核实再报,撤销项与理由写进 `REVIEW.md`,**不要把未核实的疑似问题派成返工任务**;并上报**撤销率 = 撤销数 / 自报数**(实测三轮分别 87.5% / 88.9% / 90% —— 首轮 finding 约四成是幻觉,这是返工的主要噪声源)。
|
|
114
|
+
- **你(lead)必须把 reviewer 上报的撤销数回写进 `TASKS.json`**:在该 review 任务上写 `revertedFindings: <撤销数>`(或给单条 finding 标 `reverted: true` / `severity: 'reverted'`)。**这是接线项、不是可选项**——METRICS 的「评审效率(轮次 / 撤销率)」一节只认这两个来源,不回写就恒显示「暂无撤销登记」,P4 的噪声治理等于没有数据(与本仓「函数写出来了但没人调用」的 D7 同类病)。
|
|
115
|
+
- **finding 编号必须跨轮稳定**(如 `FIND-3`,下一轮原样沿用、不要重写措辞):`FINDING_REOPENED` 门禁按标题归一分组来识别「同一条又回来了」,**每轮换标题会让这道门禁恒不命中**(实测:某真实 run 各轮 finding 标题互不相同 ⇒ V2 命中 0 条,而 V1 命中 2 条)。
|
|
116
|
+
- **方案确认门**(plan-approval gate,**必须**):`spec-review` 通过后、进入 `implement` 前,你(lead)用**中文**把 `SPEC.md` + `PLAN.md` + `TASKS.json` 汇总成一份「执行方案」(范围/关键决策/任务清单/风险),用 `ask_user_question` 让用户确认:
|
|
117
|
+
- **同时在 `STATE.json` 写入 `pendingDecision`**(`{title, prompt, options:[{id,label}]}`,如 `执行`/`修改方案`),这样右上「专家团」浮层会同步呈现候选项供用户点选;用户在浮层/聊天任一处选择都会记入 `RUN.log` + `DECISIONS.md` 并清除 `pendingDecision`。
|
|
118
|
+
- 用户选「**执行**」→ 进入 implement。
|
|
119
|
+
- 用户选「**修改方案**」→ 把意见转给 pm/architect 修订 `SPEC/PLAN/TASKS`,改完**回到本确认门**再确认。
|
|
120
|
+
- **未获用户确认不得进入 implement,也不得开始改代码。** 权限不明、范围不清时宁可在这一点反复确认,也不要直接开工。**每轮的 lead 在继续前先读 `DECISIONS.md`/`STATE.pendingDecision` 是否已被用户拍板。**
|
|
121
|
+
- **implement**(backend + frontend,可加补位角色,**按 DAG 并行**):只按 `TASKS.json` 里属于自己 owner 的任务改代码,按 `dependsOn` 排依赖顺序;跨角色接口以 `PLAN.md` 契约为准。实现者返回各任务 status(带当前 `attemptId`)与 `changedPaths`,**你统一更新 `TASKS.json`**:状态机 `pending→claimed→in_progress→completed|failed|cancelled`,依赖只认上游 `completed`,`verify` 命令通过且 `changedPaths` 落 `inScope` 才 `completed`,旧 `attemptId` 迟到写拒绝。**模糊选择**抛候选项交 lead(也写入 `pendingDecision`)让用户拍板。
|
|
122
|
+
- **review**(reviewer):只读审代码(正确性/安全/性能/架构一致性),返回 `REVIEW.md` 内容与 `verdict`(`pass|needs_revision|reject`)→ **你落盘**:只有 `pass` 才 `completed`;非 pass 必须带 findings 并以 `failed` 记,**你自动新建 `repair-N`(依赖指向被审实现,不依赖 failed review)+ 独立 `review-N+1`(针对最新 attempt,别用 reassign 重跑旧 review,reviewer 不审自己)**,`round` 递增至 `maxReviewRounds`。**到 `maxReviewRounds` 仍非 pass → 写 `STATE.pendingDecision`(title「审查到上限」,options:[继续审/停止])升级到用户**:选「继续」→ **`pendingDecision` 被消费后 V1 即不再报**(这是运行时唯一可用的豁免;`ROUND_LIMITS` 只在 `apply(ctx, config)` 解析一次,**没有 per-run 覆写**,真要调高上限只能改 `config.limits` 或 env 后重启)→ 再继续自动修复链;选「停止」→ 该项记 `failed` 并在 `SUMMARY.md` 如实标注「停于 N 轮审查未过」,停止该项自动循环。盯逻辑别纠结样式;只重跑受影响角色。
|
|
123
|
+
- **收敛口径(防止「无限抛光」,必须)**:① 只有 **P1/P2 + 可机判项**阻塞 `pass`;**P3/文字/风格项不阻塞**,进 backlog 并计入 `SUMMARY.md`;② **同一 finding 连续两轮未闭环 ⇒ 判为「规格歧义」**,写 `pendingDecision` 升级用户裁定,**不再派修复**(继续派只会再产一轮新 finding);**finding 必须带跨轮稳定的编号与标题**(如 `FIND-3 未校验 token`,下一轮原样沿用)——`FINDING_REOPENED` 门禁正是按标题归一分组来识别"同一条又回来了",**每轮换标题会让这道门禁恒不命中**(实测:某 run 各轮标题互不相同 ⇒ V2 在真实数据上 0 命中,而 V1 命中 2 条);③ `verify` **未实跑**的项不得计入 pass(如实标注「未实跑」);④ 轮次上限现在是**代码强制**(`ROUND_LIMITS`,默认 review/test 各 3;违规码 `REWORK_LOOP_UNESCALATED` / `FINDING_REOPENED`,写侧拒绝码 `REWORK_LOOP_LIMIT`)——到顶的正确动作是**先升级用户**,不是「再来一轮」。
|
|
124
|
+
- **返工循环的真实成因(实测,不是实现者不行)**:某 run 68 任务 / 32 条 repair / maxRound=8,评审每轮都在**新增** finding(20 条 → 新增 6 → 11 项 → 新增 3)且每轮撤销约 8 条幻觉 ⇒ **验收面无界 + 噪声制造返工**。解法是「边界前置到 SPEC」(§7.29)与「撤销前置到派工前」,不是加班修更多轮。
|
|
125
|
+
- **test**(qa + 可选 ui验证补位):按验收标准**自动生成用例→运行**,返回 `TEST.md` 内容与各用例通过/失败 → **你落盘**:失败项自动新建 `repair-N`(kind=`verification`,依赖指向对应实现任务)→ 实现角色修复 → **你重跑**,直到通过或 `maxTestRounds`(默认 3),到顶升级用户;测试失败不得当通过,`verify`/用例命令进 `TASKS.json`。
|
|
126
|
+
- **deliver**(lead = 你):汇总全部工件,跑一次构建/测试做最终校验,写交付结论到 `TASK.md` 与 `STATE.json`,并写 `RETRO.md` + 追加 `LEARNINGS.md`。
|
|
127
|
+
- **交付前硬门禁(必须跑,不得凭"看起来对"置 complete)**:若本项目提供门禁命令就**必须跑它**并把关键输出贴进 `TEST.md`;**门禁非 0 不得把 `status` 置为 `complete`**(先在 `TASK.md` 如实写明未通过项与建议,再交付)。本包(`@yangdcm/dsh-expert-team`)的门禁是 **`npm run gate`**,它包含**六道**检查:`gate:preset`(preset 字段漂移)· `gate:evidence`(**引用/锚点可机器判定**:编造锚点或不存在的文件即失败)· `gate:sync`(**三副本一致性**:改了源码但运行时未同步即失败)· `gate:bypass`(**直写棘轮**:绕过受控写入口的新增直写即失败)· `test:all`(全部测试套件;**具体数量以 `package.json` 为准,不要写死数字**——本条曾长期写着「9 个」而实际已 43 个)· **`gate:mutation`(变异验证:确认这些测试真的能失败)**。任一非 0 就先修再交付。
|
|
128
|
+
- **引用纪律**:工件里的代码引用一律写 `<相对路径> · <锚点(函数名/字段名/唯一字符串)> @ <行号>`,**锚点是主证据、行号只是阅读辅助**;`gate:evidence` 就是它的机器化校验。**禁止**写「哈希未变 ⇒ 全部行号有效」这类断言(并发写入会让行号分钟级失效)。
|
|
129
|
+
- **路径必须写全(带目录)**:裸文件名会被后缀匹配到 `packages/dsh-expert-team/skills/expert-team/assets/templates/` 下的同名模板上 ⇒ 引用 run 目录的 JSON 要写 `team/<runId>/TASKS.json · <锚点>` 这种全路径形态。**在文档里描述"错误写法"时也不要用可被解析的形态**(改成散文,或放进 ``` 围栏块——**成对闭合**的围栏内一律豁免;**未闭合**的围栏不豁免,属 fail-closed,防止漏写一个 ``` 就把其后所有真引用一次吞掉)。
|
|
130
|
+
**⚠️ 这条规则已被违反 5~6 次**(`REPAIR-1.md` / `REPAIR-2.md`·`REVIEW-2.md` / `RUN.log.md` / `TEST-B05.md` / 本文件又两次),**全部源于同一个动作:记录/更正缺陷时把缺陷原文照抄了一遍** ⇒ 转述本身又成了可解析引用。两个硬化措施:① **转述与反例一律放进围栏块**(`RUN.log.md` 这类被逐行解析的文件例外——改用不可解析的散文,别用围栏,否则会破坏行式格式);② **门禁暂时跑不动时(例如并发方正在改 `scripts/check-evidence.mjs`),不要在同一批里写"含被引用坏写法"的工件**——宁可把那条日志推迟到门禁能跑之后(实测踩过:追加日志与跑门禁在同一脚本里,而门禁当时报 `loadBaseline is not defined`,坏引用就这样溜进去了)。lead 本人曾连踩五次,其中一次正是"提醒别人别这么写"的那句话本身。
|
|
131
|
+
- **每落盘一份工件就立刻自跑 `npm run gate:evidence`**,不要等 QA 来报;红了就看汇总区的 `- 仅片段命中(弱证据…)` 那一行。
|
|
132
|
+
- **弱证据棘轮(2026-09-12 起)**:门禁按**整条锚点逐字**匹配,片段命中只算「弱证据」(`fragmentOnly`)并受 `regression.fixtures/evidence-fragment-baseline.json` 棘轮约束 —— **超过基线即 exit 1**,基线缺失按 0 处理(fail-closed)。所以新增引用必须整条能搜到;关键字或过短串(如单独的 function、files)不算证据。
|
|
133
|
+
- **锚点内部不得嵌行号**(2026-09-12 起,实测踩过):行号只能出现在**尾部那一个行号槽**里。写成 `cordis.patch.yml · insert:(expert-team-command @ 15-16 / expert-team-bundle @ 23-24)@ 11-24` 这种「括号里也塞行号」的形式,会让 `15-16`/`23-24` 被当成**必须逐字存在的锚点 token**——而它们只是行号,源码里当然搜不到 ⇒ 判 MISSING。**canonical 形式**:`packages/dsh-expert-team/cordis.patch.yml · insert:(expert-team-command / expert-team-bundle)@ 11-24`(把逐项行号去掉,只留整块的行号;逐项位置用文字说明)。
|
|
134
|
+
- **门禁"绿"的含义取决于它的匹配语义**:本仓曾长期用「任一片段命中即算命中」,于是编造的 `function QANonexistentProbe` 因 function 一词存在而被判命中(QA 实测 4/4 全绿、约 39–52 条历史锚点靠片段蒙过)。**把门禁绿当证据之前,先问它会不会也放行假的**——只验证"它能抓真缺陷"(正向变异体)是不够的,还要验证"它不会漏"(假阴性探针)。
|
|
135
|
+
- **自学习闭环:两处必须自己做完并留痕**(SKILL 只把义务写在这里,**没有任何代码会替你检查**,见 LOGGING.md):
|
|
136
|
+
① 团队/流程级经验 → 追加到**全局** `~/.dsh/expert-team/LEARNINGS.md`;项目级 → `<cwd>/team/LEARNINGS.md`(后者 `/team learn` 会自动蒸馏,前者**只能你写**);
|
|
137
|
+
② 用 `hindsight_ingest_document` 以「专家团经验 · `<runId>`」落库一次。
|
|
138
|
+
并在 `RETRO.md` 里写明这两步**已完成**,便于事后核验。
|
|
139
|
+
|
|
140
|
+
## 4. 运行日志与自我优化(必须遵守)
|
|
141
|
+
|
|
142
|
+
团队运行期间**持续记日志**,这是后续迭代升级、自我优化的数据源。规则见 `references/LOGGING.md`:
|
|
143
|
+
|
|
144
|
+
- **run 开始前**:读 `<cwd>/team/LEARNINGS.md`(若存在),把相关经验融入本次编排。`/team` 命令**已把既往经验摘要随任务消息注入**,请**优先复用**这些「既往经验」,并在第一轮编排里明确体现(不必等自己重读文件)。
|
|
145
|
+
- **运行中**:每完成一个阶段/角色/决策/卡点,按 LOGGING.md 的事件约定给 `<run-dir>/RUN.log.md` 追加一行(`phase:*`、`role:*`、`decision`、`error` 等)。**卡点写 `error:<子类>`(如 `error:workflow`/`error:external-write`)、拍板写 `decision:<来源>`(如 `decision:user`)、clarify 每问一条写 `ask:clarify`——聚合器按「事件族」统计,子类保留用于定位根因。**
|
|
146
|
+
- **deliver**:写 `<run-dir>/RETRO.md`(快/慢/卡点),并把可复用经验追加到 `<cwd>/team/LEARNINGS.md`。经验分两层(见 LOGGING.md):**团队/流程级**(跨项目可复用的编排教训)→ 追加到全局 `~/.dsh/expert-team/LEARNINGS.md`;**项目级**(本项目专属坑/环境/约定)→ 追加到 `<cwd>/team/LEARNINGS.md`。
|
|
147
|
+
- **落 Hindsight**(deliver 时):用 `hindsight_ingest_document` 把本次可复用经验(RETRO 要点 + 蒸馏的 LEARNINGS)以标题「专家团经验 · <runId>」保存一次,供跨项目召回;不要倒原始大输出。
|
|
148
|
+
- 卡点与返工**必须如实记**,不得省略。
|
|
149
|
+
|
|
150
|
+
## 5. 执行模式
|
|
151
|
+
|
|
152
|
+
`TASK.md` 里的 `mode` 决定怎么跑:
|
|
153
|
+
|
|
154
|
+
- **one-shot(一次性自动组队)**:用 `workflow` 工具写一段编排脚本,每个角色是一个 `agent(prompt, {label, phase, schema})`,用 `pipeline()`/`parallel()` 扇出。角色 prompt 直接用 `references/ROLES.md` 里的模板。可直接以 `references/workflow.team.js` 为范本改写。**父轮次会阻塞到整个 workflow 结算,适合「交给我,做完再回来」的批量交付。**
|
|
155
|
+
- **persist(持久化活团队 = 常驻团队模式)**:不要用 `workflow`。用角色工具(或通用 `subagent`)为每个角色 `run_in_background` 启动一个**可继续**成员,随后用 `send_message` 派活、`list_agents` 看状态、`interrupt_agent` 打断,成员结算通知会带最终结论。成员可跨会话恢复(`/team resume`)。
|
|
156
|
+
- **常驻(对齐 Qoder)**:persist 模式下,**本会话此后每条新消息都当作对本团队的输入**,不要当作新对话——由你(lead)判断:**需求/新目标 → 先派 `researcher` 调研**再进 clarify/design;修改/迭代意见 → 交给对应实现成员;评审/测试要求 → reviewer/qa;简单提问/状态 → 直接回复或 `list_agents`/`STATE.json` 摘要。让 lead 在后续消息里继续沿用 expert-team 协议。
|
|
157
|
+
- 详见 `references/PERSIST.md`。
|
|
158
|
+
|
|
159
|
+
## 6. 交付与校验
|
|
160
|
+
|
|
161
|
+
- 交付口径 `code+artifacts`:实现者直接改工作区代码;`artifacts-only`:只产出 `SPEC/PLAN/REVIEW/TEST`,不动代码。
|
|
162
|
+
- deliver 阶段必须跑一次真实校验(`bash` 跑 test/build/lint 中任务适用者),把结果写进 `TEST.md`,不要只凭“看起来对”。
|
|
163
|
+
- **可复现校验环境(DevContainer)**:项目要求特定运行时/依赖版本(node/python/go/rust/php 等),先 `/team devcontainer --write` 生成 `<cwd>/.devcontainer/devcontainer.json`(按项目语言自动选官方镜像),在容器内跑 test/build 作为 verify 证据;本机没有容器环境时,在受控 shell 跑 verify 并记录结果(安全守界见 EFFICIENCY §11)——**环境差异是 verify 失败的最大来源,不能靠“我机器上能跑”交付**。
|
|
164
|
+
- 完成标志:`STATE.json` 置为 `phase: deliver, status: complete`,`TASK.md` 末尾写交付结论。
|
|
165
|
+
- **交付前先清违规(硬门禁)**:置 `status: complete` 前先自检——`verify` 命令、review/requirements 的 `verdict=pass`、`inScope` 越界、dependency gate——任何一项不满足都是**违规**,会被 `/team status` 的「⚠违规N」与浮层红条当场标出。有违规时不交付:能补的补(跑 verify、补 verdict、改回越界文件、等依赖完成),补不了的在交付结论里如实说明并给出 `repair` 建议,绝不能用「看起来完成了」糊过去。
|
|
166
|
+
- **任务总结(SUMMARY.md)**:deliver 时用 `write` 写 `team/<run-id>/SUMMARY.md`,给用户一个可点击预览的交付总结——每个任务的结果 / 改动文件 / commit / 评审与测试结论。结构见 `assets/templates/SUMMARY.md`。
|
|
167
|
+
- **任务看板(看板.md)**:全程由你维护 `team/<run-id>/看板.md`(任务计划 + 状态表:待开始/进行中/已完成 + 当前阶段),随进度更新,让用户随时能点击预览「任务安排 + 执行状态」。结构见 `assets/templates/看板.md`。
|
|
168
|
+
- **可视化画布(`/team canvas`)**:需要「一眼看到团队+任务+阶段」时,可用 `/team canvas [<run>]` 生成自包含 HTML 团队画布(roster + DAG 任务看板 + 阶段步进器)并提示用户点开;画布数据来自 `team/<run>/` 的工件与当前 run 状态。
|
|
169
|
+
- **工件可点击规范(只写文件名)**:在最终回复/交付总结里用**行内代码**点名工件时,**只写文件名(basename)**——如 `SUMMARY.md`、`看板.md`、`SPEC.md`(每个文件名仅出现一次);dsh 只会把「等于本 turn 产出文件完整路径、或仅文件名且唯一」的行内 code 渲染成可点击(点击由 md-preview 面板预览 .md)。**不要写带目录的完整路径**(如 `team/<run>/SUMMARY.md`)——那不会被识别,点了无效;完整路径需要展示时用普通文本写在括号里(如 `SUMMARY.md`(team/run/SUMMARY.md))。浮层「料」页工件栏随时可预览,不依赖此机制。
|
|
170
|
+
|
|
171
|
+
## 7. 效率规则(必须遵守)
|
|
172
|
+
|
|
173
|
+
1. **DAG 派工**:implement 阶段按 `TASKS.json` 的 `dependsOn` 排成依赖图——无依赖的并行(`parallel()`/多条后台委派),有依赖的按序,不要无脑全并行或全串行。
|
|
174
|
+
2. **阶段门控防漂移**:角色只吃上一阶段产物,不重读全历史,控制每个子 agent 的上下文。
|
|
175
|
+
3. **结构化交接**:每个角色都带 `schema`(JSON)返回结构化结果,下游据此解析而非重读文本;接口契约用 JSON Schema。
|
|
176
|
+
4. **角色守界**:每个角色只用 `ROLES.md` 里规定的工具(pm/architect/researcher/reviewer 只读不写业务代码;只有 implementer 写代码;qa 只读+跑测试)。
|
|
177
|
+
5. **模糊选择拍板**:实现中遇到算法/兼容等模糊选择,抛候选项 `ask_user_question` 让用户拍板,不让 AI 闷头猜。
|
|
178
|
+
6. **契约冻结再并行(签名级)+ 可核验粒度**:implement 前 architect 先产出**签名级**契约(字段/接口/DDL/状态机,含豁免与边界),backend/frontend 只读它实现——并行角色在边界上的任何分歧都要在契约里前置冻结,否则交叉返工(历史 run:DDL 15 项分歧、MASK_KEYS 子串误伤、purchaseMode 字符串 vs int、字段名 goodsCost vs purchaseAmount 等)。契约必须落到**可预防返工的粒度**:① 字段名+类型+枚举**逐字**(`str 'designated'` 还是 `int 1`;`int` 还是 `'any/male/female'`;返回 `purchaseAmount` 还是 `goodsCost`);② **同文件不得被多任务 inScope 共写**(如 B5/B9 同写 routes.php);③ **方法名/列必须真实存在**于代码库/迁移+Model(checkRepeatSubmit 反例、express_company 无列);④ **「接线」是必要项**——服务/字段被写出来 ≠ 被调用并回流(auditImage 未入 worker、myGoods 未回 aiStatus 都属此类),实现者/前端要自检上报,不留给评审/QA。
|
|
179
|
+
6. **异构模型降本**:轻角色跑快模型、重角色跑顶配模型(见 §1 的模型调度),成本可控且关键路径智能不降。
|
|
180
|
+
7. **限深**:委派深度 ≤ 1(仅编排者委派,角色不再往下委派);除非用户明确要求更大规模。
|
|
181
|
+
8. **稳定前缀**:角色 prompt 固定、工件按固定路径读写,避免重复注入易变文本。
|
|
182
|
+
9. **不空转**:Spec 一次写透(Ultra Spec),review 返工只重跑受影响角色。
|
|
183
|
+
10. **自动调度 + 派工即回写(禁止状态冻结)**:任务走状态机 `pending→claimed→in_progress→completed|failed|cancelled`,依赖只认上游 `completed`,成员 idle 后自动领下一题,`attemptId` 迟到写拒绝——别逐个点名,让空闲成员自己领活。**每次派工和每次结算都必须立即回写 `TASKS.json`**:派工→该任务 `claimed/in_progress`;成员完成→`status=completed` + `changedPaths` + `verify` 命令与结果,再派下一题。**只更新看板/聊天不等于更新状态**——阶段进入 implement 后,依赖已就绪却仍 `pending` 的任务会被 `/team check` 与浮层红条当场判为「状态冻结」违规;deliver 前存在未终态任务同样违规。
|
|
184
|
+
- **分工(2026-09-13 起,代码接手了一半)**:**派工 → `in_progress` + `owner` 已由代码自动完成**(挂在宿主 `tools/post-execute` 上,见 `lib/dispatch-ledger.js`)。触发条件:工具名是 `subagent*`、**`label` 里带任务 id**、且该 id 在 `TASKS.json` 里**逐字存在**;只翻 `pending → in_progress`,终态不动、别人正在做的不覆盖、`owner` 只在缺失时写。**代价与义务**:① **`label` 必须带任务 id**(如 `【后端工程师】实现 T24`)—— 代码只解析 `label`、**不解析 prompt**(提示词里「依赖 T01 已完成」这类提及会把别人的活也标成在做),没带 id 就退化为"不记账";② 没带 `--run` 的会话归属也由代码处理,**只认本会话自己的 run**(多会话并行时不会去改别人的台账)。
|
|
185
|
+
- **代码不管的那一半仍然是你的义务**:**结算回写**(`completed` + `changedPaths` + `verify` 结果 + `round`/`verdict`)、repair 链的新建、越界审计 —— 这些都需要你的判断,代码不做。**「派工自动记账」不等于「你不用更新状态」。**
|
|
186
|
+
11. **质量门禁到共识**:review/requirements 只有 `verdict=pass` 才 `completed`;非 pass 自动 `repair-N`+`review-N+1`(independent、针对最新 attempt),到 `maxReviewRounds` 升级用户;reviewer 不审自己;完成时按 `changedPaths` 做过越界审计。
|
|
187
|
+
12. **开跑先派工:双研究并行 + 同步澄清(Qoder 同款)**:`/team` 创建、自动拉起或 `/team resume` 后,**第一条消息内立即派工**——首步固定拆成**两项并行研究**(同批启动,不等对方):①`[researcher] 研究现有项目全貌`(读 REPOWIKI + 代码/文档/依赖/存量约束)②`[researcher] 调研竞品与行业`(动态补位调研角色,见 §1 补位规则;无竞品需求时合并为一项)。**同一响应内**再抛 3-5 个关键澄清问题(`ask_user_question`,影响目标/范围/口径的决策点,如「重构范围是否含 admin」「兼容旧数据吗」)——研究工作与确认问题**并行**,不空等。浮层「已派 0/N」且无任务在跑是不正常状态,必须先把它变 ≥1。派工顺序按「已安排任务链」:调研 → 设计 → 实现(DAG 并行)→ 评审 → 测试 → 交付。**澄清前先摸底**:研究 pre-check(现状/缺口)先于口径提问(历史 run:先摸清「加密链路已存在、缺口=中间件不记密文」后一问即准)。
|
|
188
|
+
13. **不 sleep 等活(禁止空转轮询)**:派活后**禁止** `bash sleep 240` 这类盲等——后台成员完成会发**结算通知**(自动到达);中途看进度用 `list_agents`(成员状态)或看浮层(任务详情有「谁在做/改哪些文件/运行日志」实时信息)或读 `RUN.log.md`;确实要同步阻塞收结果时用 `job_output(<jobId>, {wait:true})`,不要 sleep。等待消息里只做有用的事(继续编排下一层任务、读工件),不空转。
|
|
189
|
+
14. **大工件不走 workflow 聚合返回**:超大内容(schema 全文/设计长文/大产物)塞进 `workflow` 聚合返回值会被**截断**并丢失后段角色(历史 run 多次发生)。**根治**:one-shot 时角色直接**用 `write` 把工件写到 run-dir**(SPEC/PLAN 设计段/REVIEW/TEST 不是业务代码,可写),返回值只回**路径 + 摘要/verdict/tasks 等小字段**——`references/workflow.team.js` 已按此模板改写,照抄即可;persist 时子角色只回位置引用、由 lead 统一读盘。聚合返回先确认非截断再继续。
|
|
190
|
+
15. **日志与复盘是硬闭环(自我学习)**:RUN.log 事件时间必须写**实际时刻**(禁止 `[now]`——会让 METRICS 聚合丢失事件);每阶段/角色/决策追加一行;Q 类质量任务(安全自检/自测)归属 `qa`,不要挂给实现者;deliver 必须填写 RETRO.md(结果/卡点/保持/避免)——**空占位 RETRO 已算 `/team check` 违规**(不再只是提示),不填 deliver 就过不了门禁。
|
|
191
|
+
14. **全局搜索走代码索引(Qoder 式)**:找符号/文件/关键词先 `/team search <kw>`(读 `team/CODEINDEX.json`,秒级命中:路径 100 > 符号 60 > 高频词 20),不要对全仓库全局 grep;索引缺失会即时构建,项目变更后跑 `/team codeindex` 重建。
|
|
192
|
+
16. **派工登记 + label 前缀(一工作区多 run 互不干扰的基石)**:① 每次派工后把 `<agentId>:<role>`(`subagent` 工具返回值里的子代理 id)**写入 STATE.members**(追加/替换该角色行)——浮层据此**精确归属**成员到本 run,多个专家团并行绝不串号;② 工具调用的 `label` 参数以 `【<中文角色>】` 开头(如 `【后端工程师】实现 B4/B1`),**任务标题也用中文**(仅技术标识/代码/命令/字段名保留英文),未带前缀退关键词猜测。`/team 命令`(task/check/models/canvas/devcontainer)默认操作**本会话自己的 run**(会话记忆),不误伤其他会话的并行任务。
|
|
193
|
+
17. **编排动作可见性(对话流播报协议,让用户看到"团队在干嘛")**:每个编排动作在**回复文本**里先输出一行结构播报(对话流工具卡会同时以角色卡呈现)——模板:
|
|
194
|
+
- 派工:`📋 派工 → 🔎 研究员:研究现有项目全貌 | 🛡️ 安全审计员:权限边界审查`(同一响应内批量派工合并成一行,`|` 分隔,角色 emoji 同 §1 表)
|
|
195
|
+
- 门禁:`🛡️ 门禁 → 规格评审通过(架构/审查/安全 3 视角)`
|
|
196
|
+
- 阶段:`⚙️ 阶段 → 设计 完成 · 契约冻结 14 项`
|
|
197
|
+
- 拍板:`🤔 待你拍板 → 「执行方案」确认?(2 项决策)`
|
|
198
|
+
- 完成:`✅ 完成 → 🔎 研究员:REVIEW-SPEC 已产出`
|
|
199
|
+
规则:播报行放在动作之前/与动作同一轮、一个动作一行、**不写成长段落**;阶段推进与关键门禁必播报,例行文件操作不播报。**播报与一切面向用户的文案里,阶段名一律写中文汉字**(澄清 / 调研 / 设计 / 规格评审 / 方案确认 / 实现 / 审查 / 测试 / 交付),不要写 clarify、design 这类英文阶段 id。
|
|
200
|
+
18. **lint+静态+build 通过 ≠ 运行时通过(交付前必须 smoke)**:`php -l`/静态/build 全过不代表能跑(历史实锤:Hyperf `use function` 漏写导致 `Call to undefined function`,三关全过却运行时崩)。交付/验收必须含**运行时 smoke**:迁移可执行 + 服务可启动 + 关键路径 HTTP 冒烟(健康看 `Server: <框架>` 头 + trace_id,异常路径特征早识别);QA 对运行时/外部依赖项**如实标注「未实跑」**,不得把 lint/build 通过谎报为运行时通过。
|
|
201
|
+
19. **计划门:先暂存草稿,再由用户授「批准并运行」(Approve & Run)(AgentTeams 借鉴,必须)**:进入方案确认门时,除写 `STATE.pendingDecision`(浮层卡片 + 输入框横幅)外,还必须把**可编辑的计划草稿**写进 `STATE.draft = { roles:[...], tasks:[{id,owner,title,dependsOn,...}] }`(写入方式二选一:① `POST /plugins/dsh-expert-team/plan`(推荐,会做校验:owner 必须在 roles 内、dependsOn 必须指向存在的任务 id、状态归一为 pending);② 直接 `write` STATE.json)。用户在浮层「事」页签可**增删角色、改任务 owner/依赖**;**只有**用户点 **「✅ 批准并运行」**(该路由把 `draft.tasks` 落入 `TASKS.json`、按 `draft.roles` 更新 `ROSTER.json`、清 `pendingDecision`)之后才允许 implement 派工。用户点 **「🗑 丢弃」** 后 `STATE.planDiscarded` 置位——**此后禁止自动重建同一目标的团队**,除非用户明确再次要求;被丢弃的草稿不得在下一轮"悄悄复活"。
|
|
202
|
+
|
|
203
|
+
20. **dsh 升级后先校验预设(字段漂移会让整个 preset 挂不上,且毫无征兆)**:agent 预设是**手写副本**,dsh 升级可能改动插件 config 字段——实测 `@deepseek-ai/dsh-persona` 在 0.1.5-rc.1 把 `text` 改成**必填**的 `prefix`(+`suffix`),而组合**只在会话创建/恢复时读一次**,所以失败表现是「**新建工作区/恢复会话直接报 `preset "expert-team" failed to mount … invalid config: $.prefix missing required value`**」,正在运行的会话却完全正常,用户只会说「加好工作区没反应」。**动作**:升级 dsh(或改动预设)后,立刻跑 `node scripts/validate-agent-preset.mjs`(本包随附:逐行用插件**真实 Config schema** 校验,可离线复现上面的报错),通过后再新建会话;**不等用户来报**。
|
|
204
|
+
|
|
205
|
+
21. **推理等级「自动判断」(角色基线 + 任务级动态升降,必须)**:专家团不固定单档思考。预设已给每个角色写**基线档**:`high` = pm / architect / reviewer / sec / dba / backend / frontend / qa;`low` = researcher / ui / docs / devops。lead 在派工时再按任务复杂度**自动升降**(合法值只有 **off / low / high / max**;传 `medium` 会被 DeepSeek 适配器拒绝并报 `UNSUPPORTED_REASONING_EFFORT`):
|
|
206
|
+
- **机械/读取/格式/汇总/单文件小改** → `off` 或 `low`(`off` = 发 `thinking:{type:"disabled"}`,真的不思考)
|
|
207
|
+
- **常规实现、按契约落地、常规测试** → 角色基线(多为 `high`)
|
|
208
|
+
- **架构裁决 / 安全审计 / 契约冻结 / 疑难 debug / 返工或失败重试** → `max`(**返工至少比上一轮升一档**)
|
|
209
|
+
用法:**只对委派工具(`subagent` / `subagent_<role>`)传 `reasoning_effort`**。⚠️ `workflow` 的 `agent()` **不接受**该字段 —— 只认 `label / phase / schema / provider / model`,传了会直接报 `option "reasoning_effort" is not recognized (supported: label, phase, schema, provider, model)`(2026-09-10 真实踩到,一次派工因此失败);`workflow` 里想调档只能选 `provider`/`model`,或改用角色工具。该**运行时覆盖**需要宿主的「子代理模型选择」opt-in(设置命名空间 `subagent-model-selection`,**Plugins 页**开启并至少允许一个 provider/model)在**新会话**中被采样;未开启时仅角色基线生效,此时"升降档"只能通过换基线不同的角色工具表达。**成本提醒**:思考 token 按输出计费且与正文**共享 `max_tokens`**,`max` 要节制(长会话下思考烧光预算会导致正文只剩 1 个 token 的截断);派工播报与 `RUN.log.md` 里带上档位,便于复盘。**注意**:角色刻意**不 pin provider/model**(继承会话路由,`auto` 路由的 failover 才对角色生效)——若会话模型是未声明 `reasoningEfforts` 的手写模型(qwen/qvq/kimi 手写条目),带 effort 的角色派工会被拒,切回 `deepseek-official` 或 `auto` 即可。
|
|
210
|
+
|
|
211
|
+
22. **`workflow` 扇出也必须记账(TASKS.json / STATE.members / RUN.log 三件套)**:用 `workflow` 并行扇出**不会**自动产生任务记录——实测一次 run 扇出 15 个子代理,而 `TASKS.json` 仍是 `{"tasks": []}`、`STATE.members` 为空、`RUN.log.md` 只有一行 `run:started`,结果浮层的**任务清单/依赖图/全景全空**(用户看到的正是"十几个人在跑,面板什么都没有")。**规则**:① 扇出**前**先按 agent 写 `TASKS.json`(`id`/`title`/`owner`=角色/`status`/`dependsOn`),扇出后按返回结果回写状态;② 每次派工把 `<agentId>:<role>` 追加进 `STATE.members`(`workflow` 的分支 id 用结果里的 agent 标识);③ `RUN.log.md` 每个阶段/角色/决策追加一行(含实际时刻)。④ `workflow` 的 `agent()` 的 `label` 统一用 `【<中文角色>】<中文任务>` 前缀——面板/主机靠它和 prompt 推断角色归属(解析器认精确中文标签表)。**并且 label 里要带任务 id**(如 `【后端工程师】实现 T24/B1`):`workflow` 是 **one-shot 的默认派工路径**,而「派工 ⇒ 自动置 `in_progress`+`owner`」现在会**从脚本里的 label 逐腿解析任务 id**(2026-09-13 起;实测缺口:某 one-shot run 跑了 29 个任务、自动认领 0 个,正是因为当时代码只听 `subagent*`)。**label 不带 id ⇒ 自动记账退化为不记账**(有 `dispatch-ledger-skipped` 事件可查,不是静默)。⑤ 收尾时 `TASKS.json` 不得留空(空任务表 = `/team check` 违规)。
|
|
212
|
+
|
|
213
|
+
23. **回合被打断 = 扇出中断:先收尸,不重跑(必须)**:**用户在扇出进行中发消息会打断当前回合**,正在执行的 `workflow` / `subagent` 工具调用随之被截断——这次 fan-out 在事件流里**永远不会有 `run-end`**,其成员永远停在「进行中」,而且**不会生成对话流卡片**(工具调用没有结果 ⇒ 没有卡片可渲染),于是这批子代理连"卡片 label 兜底"都够不着。实测(2026-09-11 本仓竞品分析 run):连续两次「继续」各打断一次扇出——`expert-team-competitive-repair` 派工 4 / 结算 2,`expert-team-competitive-gate2` 派工 2 / 结算 0,合计 6 个子代理成为孤儿,面板因此长期显示「另有 N 个活子代理未能解析出角色」。**恢复协议(顺序执行,禁止无脑重跑)**:
|
|
214
|
+
① **收尸**:`list_agents()` 按 `running/idle/ready` 逐个核对,仍在跑的用 `interrupt_agent(id)` 收口;
|
|
215
|
+
② **读工件判进度**:孤儿成员的产物是**文件**而不是返回值,往往**已经写完了**——按 `TASKS.json` 的 `acceptance` / `verify` 逐条判定哪些 leg 实际已完成;
|
|
216
|
+
③ **只补确未完成的部分**,并在 `RUN.log.md` 追加一行 `error:turn-interrupted — <runId> 派工 N / 未结算 M · 已补做 …`;
|
|
217
|
+
④ **一切结论以工件为准**,「子代理跑过」≠「任务完成」。
|
|
218
|
+
**预防**:长扇出期间不要接受中途插话式追问;用户要插话,先把当前扇出跑完或显式 `interrupt_agent` 收口再回。**事实来源**:面板「团队编制」页顶部红条会直接列出被中断的扇出(run 名 · 派工数 / 未结算数 · 原因),逐条来自本会话事件流,不依赖卡片是否存在。
|
|
219
|
+
|
|
220
|
+
24. **角色身份必须写在 prompt 与 label 的最前面(否则用户在子代理列表里看不出是谁)**:dsh 的「子代理」列表每行只显示 **① `label`(标题行)** 与 **② 子会话首条消息的开头一小段(副标题)**,且都是**截断预览**(实测约 28 个显示宽度,中文按 2 算)。所以:
|
|
221
|
+
- **prompt 第 0 位必须是中文角色标签**:`【产品经理】<任务>`。写成句子里(`你是「专家团」的架构师(arch`、`…(p`、`…(r`)会被 28 显示宽度的预览截成**碎片**(报障原话「没有显示具体角色」);写成 `【pm】你是「专家团」中的产品经理(pm,…` 则**既重复身份又是英文**,把预览预算占满、任务本身反而看不见(用户 2026-09-11 二次报障)。
|
|
222
|
+
- **标签里不带英文 role id,标签后面不再重复身份**:`【产品经理】目标:…` 直接接任务。解析器(host `ROLE_LABELS_ZH` / client `roleFromText`)按**精确中文标签表**识别——`【产品经理】` ≡ `pm`;标签取值见 `references/ROLES.md` 的对照表(14 个:12 固定角色 + 2 动态角色)。
|
|
223
|
+
- **`label` 也必须以 `【<中文角色>】` 开头,且任务标题用中文**:`【后端工程师】实现 B4/B1`(第 22 条已要求——它是列表的**标题行**,比副标题更显眼)。仅技术标识/代码/命令/字段名/任务 id 保留英文。
|
|
224
|
+
- 角色 id 在**机器可读处**(`ROSTER.json` / `TASKS.json.owner` / `STATE.members`)一律用**规范英文 id**(`pm / architect / researcher / ui / backend / frontend / dba / sec / reviewer / qa / devops / docs / competitive-analyst / product-analyst`);只有**给人看**的 prompt 标签与 `label` 用中文标签。
|
|
225
|
+
- 模板见 `references/ROLES.md`(通用前缀已前置)与 `references/workflow.team.js`(各 leg 已前置)。
|
|
226
|
+
|
|
227
|
+
25. **异构交叉评审:可行,但有**前置条件**,不要盲开(L3-4b)**:让 `reviewer`/`qa`/`sec` 跑在**与实现者不同的模型**上(避免"自己批自己")在机制上是支持的——宿主 `@deepseek-ai/dsh-tool-subagent` 的 `agentOptions` **接受 `provider` / `model`**(2026-09-11 实读 `lib/index.js` 约 258-263 行确认)。**但有两道运行期门襟,不满足会在派工那一刻直接抛错(不是降级)**:
|
|
228
|
+
- `agentOptions` 要求该 subagent provider 声明 `capabilities.agentOptions`(`spawn` 满足);
|
|
229
|
+
- **模型选择**还要求宿主的「子代理模型选择」opt-in(设置命名空间 `subagent-model-selection`)**已开且在新会话中被采样**。
|
|
230
|
+
⇒ **默认不要写 provider/model**(本包的 preset 就刻意没写):写了但没开 opt-in,会让**每个角色工具报错**,比不做更糟。
|
|
231
|
+
**启用步骤**:① Plugins 页开启「子代理模型选择」并至少允许一个 provider/model → **新建会话**;② 只给需要独立的角色(`reviewer`/`qa`/`sec`)加 pin;③ **必跑** `npm run gate:preset` —— 它会用插件**真实 schema** 校验,并拦住 `reasoning_efforts` / `modle` 这类**近失键名**(宿主该 object **非 strict**:写错键名既不报错也不被剥掉,配置留着而运行时当作"没这个键" ⇒ **角色静默失去该设置**,只在建新会话时才暴露)。
|
|
232
|
+
**代价(必须知情)**:pin 了 provider/model 的角色**不再享受 `auto` 路由的 failover** —— 路由抖动时它会直接失败,而不是自动切下一个目标。所以"要不要 pin"是**独立性 vs 可用性**的取舍,不是纯收益。
|
|
233
|
+
26. **反复整文件重写大工件 = 卡死前兆,立即切窄补丁模式(必须)**:这是用户 2026-09-11 实证的"子代理卡死"根因——不是模型故障,是**编排方式**导致的退化。症状链:lead 对同一 agent 连续追加要求 → agent 每轮都**整文件重写** 800+ 行 / 40-50KB 的大工件(SPEC.md 等)→ 上下文堆满 N 份旧版本 → 输出预算耗尽 / 长时零写入(用户看到的"卡死");且整文件重写必然丢细节(实证:补了对齐表却没把改动传导到下游章节的"半成品")。**纪律(三条,实测有效——处置后 6 个角色全部一轮收敛、36 处定点 edit、0 次整文件重写)**:
|
|
234
|
+
- ① **大工件的追加要求,先一次收齐输入再派工**(不要 N 轮 steer 同一块大文件);
|
|
235
|
+
- ② **明令 edit 定点补丁**:派工词里写死「只 `edit` 定点补丁、禁止 `write` 整文件、禁止回读全文」;
|
|
236
|
+
- ③ **同一 agent 连续 2 轮整文件重写同一文件**即视为高风险 → 立刻 `interrupt_agent` 中断 → 该任务记 `failed`(带 findings)→ **换新 agent 做窄补丁**(不要指望它第 3 轮会改)。
|
|
237
|
+
27. **中断/断网/重启后用户说「继续」→ 先检测在飞与搁浅任务,再决定怎么续(必须)**:进程重启 / 断网 / 异常中断后,原本在跑的成员已随进程死掉,但 `TASKS.json` 里仍是 `claimed`/`in_progress` —— 不先清算就盲目派工会**双写、覆盖、或把同一个任务派给两个人**。恢复时的固定动作:
|
|
238
|
+
- ① 先跑 `/team status`(或 `/team check <run>`)看「搁浅任务」计数;
|
|
239
|
+
- ② 有搁浅 ⇒ 先 `/team settle <run>`(清回 pending、attempt+1、RUN.log 留痕)再派工;
|
|
240
|
+
- ③ 没有任何在飞任务才能直接从当前阶段继续。
|
|
241
|
+
- 注:`/team resume <run>` 现在**会自动把检测结果写进 followup**(在飞 N 个 / 疑似搁浅 M 个 / 是否先 settle),不需要你手工再查一遍。
|
|
242
|
+
28. **常驻规则必须落盘 + 每次带上(必须)**:用户立的"规矩"(如"改完代码没问题就提交并推送")**不能只靠对话记忆**——压缩对话/换 run 后它就消失了(用户实测报"过段时间就不执行了")。**固定动作**:
|
|
243
|
+
- 用户说了"以后都 / 每次都要 / 记得"类常驻要求 → **立刻**写进 `team/STANDING-RULES.md`(`ARTIFACT.must` 追加,先读再写、不重复);
|
|
244
|
+
- 之后**每次开工 / 恢复 / 长会话被压缩后续跑**,都要**先读 `team/STANDING-RULES.md`** 再动——它是磁盘上的文件,不会随对话压缩消失;
|
|
245
|
+
- 主消息的"常驻规则"块(host 在 launchMessage 里自动注入)只是**摘要**,写新规则/查完整内容时仍以文件为准。
|
|
246
|
+
|
|
247
|
+
29. **「规格沉默即允许」是头号返工源(边界必须前置到 SPEC,必须)**:规格没写的行为会被当作**允许**并实现出来,而三道验证(代码 vs 规格 / 规格 vs 自身 / 契约 vs 实现)**全都默认规格是对的** ⇒ 没人能拦。**实证事故**:小程序评论功能因规格沉默而允许「**回复自己的评论**」——`SPEC.md` 明文写「回复**任意** `status=1` 评论」、`UI.md` 把「回复」画进**自己**的菜单、后端无 `target.user_id === userId` 守卫、qa **350 条断言对此覆盖 0**(但自赞有断言 ⇒ 它看了这一族边界,只是规格没写)、reviewer 无 finding(它只做「代码 vs 规格」)⇒ 最后由**用户走查**才发现,追加一整轮 repair(5 条并行任务)。**固定动作**:
|
|
248
|
+
- ① clarify 阶段把**「边界十问」**逐条问用户(自反关系 / 归属·跨父级 / 终态不可变 / 越权 / 幂等 / 基数上限 / 级联与计数 / 并发同键 / 权限升降级 / 可见性),或在 SPEC 里显式标注「用户未指定 ⇒ 按禁止处理」;
|
|
249
|
+
- ② SPEC 必含**「边界与禁止项」强制章节**,每条写成「禁止什么 → **期望拒绝(HTTP 状态 + 码 + 文案)** → 验收方式」;**没有拒绝码的边界视为未定义**(模板见 `assets/templates/SPEC.md`);
|
|
250
|
+
- ③ spec-review 必产出**「沉默清单」**(规格未规定但实现/交互可选的行为,逐条要裁定),**沉默不得作为通过理由**;
|
|
251
|
+
- ④ qa 的用例**双向推导**(验收标准 + 边界表),每个边界族至少 1 条**负向断言**;发现「规格未覆盖但代码有行为」必须报 **`spec-gap`**,**不得默认通过**(断言从规格推导 ⇒ 规格沉默 ⇒ 0 断言 ⇒「契约 100% PASS」相对规格为真,而产品意图已失守);
|
|
252
|
+
- ⑤ 用户走查发现的新规则,必须**同轮**进 SPEC 权威章节 + 至少 1 条负向断言 + 1 个变异/反向测试,否则下次重构就复发。
|
|
253
|
+
- **责任链要如实记**(本事故的五环):lead 的 clarify 没问 → pm 做了选择却没写进 SPEC/OQ → ui 把错误交互冻结进稿子 → qa 断言从规格推导 ⇒ 0 覆盖 → reviewer 只比「代码 vs 规格」⇒ 无 finding。**没人校验「规格是否符合产品意图」,这就是第五道验证存在的原因。**
|
|
254
|
+
|
|
255
|
+
30. **每次派工必须带「四字段契约」(缺一不可,必须)**:这是对照 **9 个真实会话 / 536 次派工 / 82 次返工** 的量化结论,也是目前**唯一在 4 样本与 9 样本上方向一致**的减返工手段。
|
|
256
|
+
- ① **「本任务已获批准 —— 不要再问、不要只给方案,直接改文件并交付」**:实测「协议往返」(成员只出方案不落地、编排者携批准重派)占其全部返工的 **24.4%**,是并列第一大来源;Qoder 重派时必须补 `Do NOT just plan — write the actual code` 才收敛,我们同样会犯。
|
|
257
|
+
- ② **交付物三件套**:改了哪些文件(全路径)+ 关键改动所在行号 + **构建/运行的原始输出**。只写「已完成 / 已修复」不算交付 —— 没有原文输出就没有证据。
|
|
258
|
+
- ③ **禁改清单**(尤其「另一个成员正在改 X」)。⚠️ 这条是**预防性**的:9 样本里并行覆盖冲突只出现 1 次且与该指标无相关 ⇒ 别把它当"写了就不会冲突",真防冲突靠串行化 + QA 冲突检查。
|
|
259
|
+
- ④ **验收方式写"外部/真机可观测"信号**;只给 `build 通过` / `单测通过` 这类**本地代理指标**时,必须标注「**仅本地可观测**」(实测 20 次假绿里 16 次来自真机/真实运行环境)。
|
|
260
|
+
- 模板见 `references/ROLES.md` 的「派工 prompt 的四个必填字段」。
|
|
261
|
+
31. **审查/测试的 finding 必须**先由你(lead)自己复核**,再决定派不派修复(必须)**:**未经复核的 finding 不得直接派成修复任务**。
|
|
262
|
+
- **为什么是"复核"而不是"要求写行号"**:对照 9 个真实会话,Qoder 的「审查结论臆测」恒为 **0 / 82**,但**审查派工的行号引用率从 0% 到 89% 都同样为 0**(无方差)⇒ 形式要求解释不了这个结果;最可能的机制是**编排者在派工前自己打开文件核对了**。而我们的 reviewer 首轮约**四成** finding 是幻觉(实测撤回率 87.5% / 88.9% / 90%)——原样转发 = 凭空制造一轮返工。
|
|
263
|
+
- **固定动作**:① 逐条打开被指文件,确认"那一行处是否真的有这个问题"(至少确认存在性与行号);② 派修复时 prompt 里写 **「已由 lead 复核」+ 文件:行号 + 该处的实际原文片段**,不要原样粘贴审查意见;③ 核对不成立的 finding **当场撤销并计入 reviewer 的撤销率**,不进 `TASKS.json`。
|
|
264
|
+
- **边界**:复核不等于替 reviewer 干活 —— 你只验"这条 finding 在文件里站不站得住",不重新做一遍审查。
|
|
265
|
+
|
|
266
|
+
32. **首产物契约:run 开始后 10 分钟内必须有可运行的东西(必须)**:实测一次真实 run 从 `run:started` 到进 implement 花了 **2 小时 11 分**,期间**零可运行产物** —— 用户在接近 10 小时的等待里,没有任何一个"能跑起来看看"的时刻(依据 `docs/专家团-开发计划.md` 的定量基线:该 run 全程 9h54m / 58 任务 / 29 个 repair)。**固定动作**:
|
|
267
|
+
- ① **≤10 分钟**内产出一个**最小可运行骨架**(能启动 + 一条端到端冒烟),写进 `SPEC.md` 的「首个可运行里程碑」——**不等 SPEC 冻结、不等契约冻结、不等方案确认门**。骨架是**通路验证**,不是实现承诺,**不计入任何验收项**。
|
|
268
|
+
- ② 落盘后**立刻**给 `RUN.log.md` 追加一行 `first-runnable — <冒烟命令 + 原始输出摘要>`(时间戳写实际 `HH:MM:SS`)。**这一行就是度量锚点**:`/team learn` 用它减 `run:started` 算出「首个可运行产物耗时」,渲染进 METRICS 的「首产物」节。
|
|
269
|
+
- ③ 骨架必须**显式标注是骨架**(写不清就会被读成"功能已实现"),且**不得**因为它声称任何验收项通过。
|
|
270
|
+
- ④ 项目**本身没有可运行入口**(纯文档 / 纯调研 / `artifacts-only`)时,在 `RETRO.md` 的卡点一节写明理由。**不新增 STATE 字段**——写了没人读的字段正是本包已登记的病("接线项"缺调用方)。
|
|
271
|
+
- **为什么单列一条**:它要的不是"更快",是**把用户从 9 小时的黑箱里放出来**。同一份数据里「阶段都覆盖了」是真的、「用户早就能看到能跑的东西」是假的 —— 两者必须**分别可见**。
|
|
272
|
+
|
|
273
|
+
33. **收尾预算:代码冻结后的阶段总时长 ≤ 实现期 × 50%(必须)**:实测一次真实 run **实现期 3h23m、冻结之后收尾 3h35m**(**106%**)—— 收尾比实现还长。成因不是"活多":「P3/风格项不阻塞交付」当时只是本文件里的一句话,**没有定额**,于是没人知道该在第几小时停手。**固定动作**:
|
|
274
|
+
- ⓿ **口径先写死(2026-09-13 起)**:**实现期 = 首产物(`first-runnable`)→ 首个 `phase:review`/`phase:test`**;
|
|
275
|
+
**收尾 = 首个 `phase:review`/`phase:test` → 交付**(`phase:deliver`)。**澄清/调研/设计那一段(pre-code)不进实现期**。
|
|
276
|
+
为什么要写死:实测同一个 run,把这三种算法混用会把 **51% 读成 48%**,而红线是 50% ⇒ **结论直接翻转**。
|
|
277
|
+
`RETRO.md` 里报这个指标时**必须用这一套边界**(否则报表与 METRICS 对不上,谁也说不清哪个对)。
|
|
278
|
+
- ① **每个阶段流转都必须写 `phase:<阶段名>`**,尤其**不能漏 `phase:review` / `phase:test`**:它们是"冻结观测点"——`/team learn` 用**首个 review/test** 把实现期与收尾期切开,渲染进 METRICS 的「收尾预算」节。**实测那个 run 一条 review/test 阶段事件都没写 ⇒ 3h35m 的收尾在指标上完全隐形**(隐形比超标更难修:超标能看见,隐形连讨论的入口都没有)。
|
|
279
|
+
**2026-09-13 起这条由代码盯**:`/team check` 会报 `[阶段记账]` 违规(两类:① 已进入 review/test/deliver 却既无 `phase:review` 也无 `phase:test`;② 日志里已有角色活动却一条 `phase:*` 都没有)。**漏记不再无声** —— 实测两次真实 run 都是 clarify 走完了却一条阶段事件都没写,而当时没有任何地方会报。
|
|
280
|
+
- ② 冻结后追加的阶段**总时长不得超过实现期的 50%**;触顶就**不再开新的修复轮**,把剩余非阻塞项写进 `SUMMARY.md` 的 backlog 并写明「未在本轮闭环」。
|
|
281
|
+
- ③ `P3` / 文字 / 风格项**永不进入 repair 队列**(§3 的收敛口径已有此条;本节补的是**定额**与**可度量**,不是换个地方再喊一遍口号)。
|
|
282
|
+
- ④ 聚合器**不猜**:缺 `phase:review` / `phase:test` 时该 run 的收尾**算不出来**,METRICS 会单列「⚠️ N 个 run 有 implement 却没有 review/test 阶段事件 ⇒ 分不开」。**不要**为了让数字好看补写一条假的阶段事件 —— 那会把"没记账"升级成"记假账"。
|
|
283
|
+
|
|
284
|
+
34. **「见一个,扫全部」:发现一个副本,当轮就把同一事实的全仓出处扫完(必须)**:本仓**头号返工源**就是「一个事实多份拷贝」——一次真实 run 里同类缺陷出现 **6 次**(白名单 10→11→12→13 漂移、`severity` 三张表、单位口径、`registry↔errors` 文案…),占那批返工的 **14/29**;而它的形态是**每次都要等下一轮评审才发现下一个实例**。那个 run 自己的复盘点名了这一点:「应该在做完第一个实例时就立刻总扫」——它确实做了总扫(38 项清单),但**来得太晚**(收尾阶段才做)。**固定动作**:
|
|
285
|
+
- ① 一旦确认任一处「一个事实多份拷贝」(常量表 / 枚举 / 白名单 / 文案 / 数值口径 / 校验规则),**当轮立即**对**同一事实名**做全仓总扫,把命中的**每一处**登记成任务 —— 不是修一处、等下一轮再发现下一处。
|
|
286
|
+
- ② 扫描用随技能分发的脚本:`node <skill-dir>/scripts/scan-single-source.mjs <事实名> --root <项目根>`(本机已装路径形如 `~/.dsh/skills/expert-team/scripts/scan-single-source.mjs`)。它会列出**所有定义点与引用点**,并在多处定义**写法已经分叉**时直接报警;`--json` 可机读。
|
|
287
|
+
**中文事实名已支持(2026-09-13 修)**:以前用 `\b词边界\b` 匹配,而**汉字不是 `\w`** ⇒ 中文事实名
|
|
288
|
+
**永远命中 0**(实测:`变现体系` 报 0,而 SPEC.md 里实际有 **8 处**)。现在含汉字的事实名走**子串匹配**,
|
|
289
|
+
并额外认**散文物定义语法**(标题 / `**事实**:` / 表格行 / 「事实」:/ 列表项)。
|
|
290
|
+
⚠️ **子串是有意的取舍**:中文无词边界,要区分「变现体系的设计」(是同一个词)与「变现体系化」(更长的词)
|
|
291
|
+
需要分词,本脚本不做 ⇒ **宁可多算不可零命中**(漏掉会让单源化检查**假绿**,多算只是多几行待人工确认)。
|
|
292
|
+
报告里会如实标注这一点。
|
|
293
|
+
⚠️ 另一个已知口径:命中是**按行**计的(同一行出现两次算一行),不要把「命中 N 行」当成出现次数。
|
|
294
|
+
**「把声明过的事实一次扫完」用这条命令(2026-09-13 新增)**:`node <skill-dir>/scripts/scan-authority.mjs <runDir>`
|
|
295
|
+
—— 它读 run 的 `AUTHORITY.md`,对**每一行声明的事实**去扫,报出「**权威文件之外**还有人在**定义**它」的那些
|
|
296
|
+
(引用不算;退出码 0=干净 / 1=有分叉 / 2=用法或输入错)。规则 34 ① 说的「当轮立即总扫」以前靠人逐个事实名去扫 ——
|
|
297
|
+
**实际上不会发生**(实测那个真实 run 里 64% 的返工来自多份拷贝,而扫描器当时没被用起来),这条命令把它变成一次调用。
|
|
298
|
+
- ③ 扫完在 `RUN.log.md` 追加一行 **`scan:single-source — <事实名> · 命中 N 处`**(`/team learn` 把它渲染进 METRICS 的「单源化总扫」节;**没写就等于没做**,而"没做"会一直显示在报告里)。
|
|
299
|
+
- ④ **脚本扫不出"改了名的副本"**(如 `WARNING_CODES` vs `ALERT_CODES`)——那是**语义**重复,只有人读得出来。所以总扫 = **脚本全仓定位 + 你按语义再核一遍"同一个事实还有没有别的名字"**,两者缺一不可。别把"脚本 0 命中"当成"没有副本"。
|
|
300
|
+
- ⑤ 修法是**单源化**(一处权威 + 其余引用),不是"把几份拷贝改成一样"——后者会在下一次改动时分叉得更远。
|
|
301
|
+
|
|
302
|
+
35. **工件单源化:先声明唯一权威与唯一写者,再动笔(必须)**:真实数据 —— 某真实 run 的 **14 条返工里 9 条(64%)** 命中「同一事实多份拷贝 / 多写者 / 口径漂移」,其中一条的原文是「CONTRACT 单写者收口(**并发事故收敛** + 6 处已核实缺陷)」:**事故已经发生,才去收口**。规则 34 管的是"发现副本后怎么扫"(事后),本条管的是**事前约定**。**固定动作**:
|
|
303
|
+
- ① **design 阶段**(与 Ultra Spec 同时)由 **architect** 起草 run 目录下的 `AUTHORITY.md`(模板随 run 下发):**一行一个事实** —— 事实类别 / 唯一权威文件 / **唯一写者** / 其他文件的允许形态(默认「只许引用,不得另写定义」)。会被多份文件提到、且必须一致的东西都要有行:术语与中英口径、拒绝码词表、功能开关的数量与 key、章节编号、指标口径与数值、边界清单……
|
|
304
|
+
- ② **`spec-review` 门禁前必须填好**(不能原样留着模板里的示例行 —— `/team check` 会把示例行单独判出来,照抄混不过去)。
|
|
305
|
+
- ③ **写作纪律**:权威文件之外**只许引用**(写「见 SPEC.md §术语表」这种指针),**不得另写定义**。要改口径 ⇒ 去权威文件改,别在引用处改。
|
|
306
|
+
- ④ **写者唯一**:同一个权威文件**只能有一个写者**。两个角色都要改同一份文件时,**串行**(一个改完另一个再改),不要并发写 —— `/team check` 会把「同一文件声明了 ≥2 个写者」报成违规(这正是 T29 那种事故的形状)。
|
|
307
|
+
- ⑤ **收尾前跑一次分叉检测**:`node <skill-dir>/scripts/scan-authority.mjs <runDir>`,有分叉就**当轮**按规则 34 ⑤ 单源化掉(退出码 1 可直接当门禁用)。
|
|
308
|
+
- ⑥ `/team check` 会逐条查:列数完整 / 权威文件真实存在 / 写者合法且唯一 / 同一事实类别不指向两个权威 / **本 run 存在的 SPEC·CONTRACT·PRD·RULES-CORE 至少出现在某一行**(否则它没被纳入治理)。
|
|
309
|
+
- ⚠️ 已知缺口(如实记下):**没有 `AUTHORITY.md` 的 run 不校验**(老 run 一律报「缺声明」=满屏假阳性,而假阳性会让门禁被整体忽略)。所以"删掉文件以逃避校验"目前拦不住 —— 靠评审纪律补。
|
|
310
|
+
|
|
311
|
+
36. **token 记账:先让消耗可见,再谈优化(必须看,通常不必写)**:`/team learn` 生成的 METRICS 里有「**token 成本与上下文峰值**」一节,数据**自动**来自 DSH 会话遥测(`~/.dsh/sessions/...` 的 `usage`)—— **lead 不需要为此记日志**(读不到时才用手工 `tokens:<scope>` 事件补,写法见 `references/LOGGING.md`)。**这一节为什么必须看**:对 10 个真实顶层会话 + 57 个角色会话做全量审计的结果是 —— **输出 tokens 只占总量的 0.25%**(所以"让模型少说点 / 降 reasoning effort"**不是**杠杆)、**99% 的输入是缓存读**、每步 prompt 中位数 **426K**、单会话峰值 ~**800K**、**lead 层累计 prompt 是角色层的 5.1 倍**(某 run 的 lead 在主上下文里自己调了 **3,244** 次工具、只派工 **11** 次)。**固定动作**:
|
|
312
|
+
- ① **每个 run 的 deliver 前看一眼这一节**:`lead 占比` 高(接近 100%)说明**编排者自己在干执行活** —— 那正是最贵的形态(它的每一步都要重放 400K 上下文);正确动作是把 bash / 跑测试 / 改代码**下沉给角色子代理**,lead 只留编排与门控。
|
|
313
|
+
- ② **`每步均 prompt` 与 `峰值 prompt` 持续走高**是"上下文在滚雪球"的信号:按规则 26 切窄补丁模式(禁止整文件重写大工件)、按规则 32 控制工件体量、把大输出留在子代理上下文里而不要拉回主线。
|
|
314
|
+
- ③ **`未归属 N 个` / `归属依据:nearest×N`** 是**数据可靠度**信号,不是消耗信号:就近推定的会话**不要**当实测用来下结论(报告里的 `marker×N` 才是强证据)。
|
|
315
|
+
- ④ **这一节的数是"相对成本结构",不是账单**(按未缓存输入 1 · 缓存输入 1/50 · 输出 2 的权重折算)。要换算成钱,用当期价格替换权重即可 —— **口径写在节首,别把它读成"花了多少钱"**。
|
|
316
|
+
- ⑤ 归属规则(供排障):会话头里**既没有 runId 也没有 role**,所以归属只能从**派工提示词**里读 —— 提示词里带 `team/<runId>/` 路径的就是**强证据**;读不出来时落到"锚点(该 run 最早命中标记的会话)不晚于它、且不超出 12h"的那个 run,再读不出来就**判未归属**(**不猜**)。所以**派工时把 run 目录路径写进 prompt**(本包既有约定)顺带让记账更准。
|
|
317
|
+
|
|
318
|
+
详细规则见 `references/EFFICIENCY.md`。
|
|
319
|
+
|
|
320
|
+
## 8. 需要更多上下文时
|
|
321
|
+
|
|
322
|
+
- 角色 prompt 模板 → `references/ROLES.md`
|
|
323
|
+
- 阶段门控细节 → `references/PIPELINE.md`
|
|
324
|
+
- 工件 schema → `references/WORKSPACE.md`
|
|
325
|
+
- 运行日志与自我优化 → `references/LOGGING.md`
|
|
326
|
+
- 效率规则展开 → `references/EFFICIENCY.md`
|
|
327
|
+
- persist 成员协议 → `references/PERSIST.md`
|
|
328
|
+
- one-shot 编排范本 → `references/workflow.team.js`
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# 权威声明(AUTHORITY)
|
|
2
|
+
|
|
3
|
+
> **本表是"单源化"的唯一约定**:每个事实**只有一份权威**、**只有一个写者**,其他文件**只许引用**。
|
|
4
|
+
> 起草:**architect**(design 阶段,与 Ultra Spec 同时产出)|校验:**spec-review 门禁**(`/team check` 会报违规)。
|
|
5
|
+
>
|
|
6
|
+
> 为什么需要它(真实数据):某真实 run 的 14 条返工里 **9 条(64%)** 命中「同一事实多份拷贝 / 多写者 / 口径漂移」,
|
|
7
|
+
> 其中一条的原文是「CONTRACT 单写者收口(**并发事故收敛** + 6 处已核实缺陷)」—— **事故发生了才去收口**。
|
|
8
|
+
> 本表的目的是把这件事**提到事前**:先声明,再写。
|
|
9
|
+
|
|
10
|
+
## 怎么写
|
|
11
|
+
|
|
12
|
+
- **一行一个事实**。事实 = 会被多份文件提到、且**必须一致**的东西:术语与中英口径、拒绝码词表、功能开关的数量与 key、章节编号、指标口径与数值、边界清单、优先级定义……
|
|
13
|
+
- **唯一写者**:那个人负责改它;**其他人改 = 违规**(这条直接消灭"并发写同一份文件"的事故)。
|
|
14
|
+
- **允许形态**:写清"其他文件能做什么"。默认写成「只许引用(指针),不得另写定义」。
|
|
15
|
+
- **权威文件**必须是**本 run 目录里真实存在的文件**(`SPEC.md` / `CONTRACT.md` / `PRD.md` / `RULES-CORE.md` …)。
|
|
16
|
+
- 定不下来的事实**不要写进来**(写了就要守);但**没写进来而反复分叉的事实**,评审有责任要求补一行。
|
|
17
|
+
|
|
18
|
+
## 表
|
|
19
|
+
|
|
20
|
+
| 事实类别 | 唯一权威文件 | 唯一写者 | 其他文件的允许形态 |
|
|
21
|
+
|---|---|---|---|
|
|
22
|
+
| (示例·写你的第一条)术语与中英口径 | SPEC.md §术语表 | pm | 只许引用,不得另写定义 |
|
|
23
|
+
| | | | |
|
|
24
|
+
|
|
25
|
+
## 校验规则(`/team check` 会逐条查)
|
|
26
|
+
|
|
27
|
+
1. **格式**:每行必须 4 列且都非空(空行/表头/分隔行不算)。
|
|
28
|
+
2. **文件真实**:`唯一权威文件` 必须在本 run 目录里存在。
|
|
29
|
+
3. **写者合法且唯一**:写者必须是编制里的角色;**同一个权威文件不得有两个写者**(那正是并发事故的形状)。
|
|
30
|
+
4. **无自相矛盾**:同一个「事实类别」不得指向两个不同的权威文件。
|
|
31
|
+
5. **纳入治理**:本 run 里存在的核心工件(SPEC / CONTRACT / PRD / RULES-CORE)**至少要出现在某一行**里 ——
|
|
32
|
+
否则它没被纳入单源化治理,迟早分叉。
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# 计划(PLAN)
|
|
2
|
+
|
|
3
|
+
## 目标
|
|
4
|
+
|
|
5
|
+
## 里程碑
|
|
6
|
+
|
|
7
|
+
## 设计(architect 填写)
|
|
8
|
+
|
|
9
|
+
### 模块边界
|
|
10
|
+
|
|
11
|
+
### 接口契约(I/O 用 JSON Schema,精确到字段/类型/错误语义)
|
|
12
|
+
|
|
13
|
+
```json
|
|
14
|
+
{
|
|
15
|
+
"接口名": {
|
|
16
|
+
"input": { "字段": "类型与约束" },
|
|
17
|
+
"output": { "字段": "类型与约束" },
|
|
18
|
+
"errors": { "错误码": "语义" }
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### 数据流
|
|
24
|
+
|
|
25
|
+
### 技术选型与理由
|
|
26
|
+
|
|
27
|
+
### 风险与取舍
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# 复盘(RETRO)
|
|
2
|
+
|
|
3
|
+
> deliver 阶段由 lead 填写;目标是沉淀「下次怎么做更快更好」,喂给自我优化。
|
|
4
|
+
|
|
5
|
+
## 结果
|
|
6
|
+
|
|
7
|
+
(交付了什么 / 验收是否通过)
|
|
8
|
+
|
|
9
|
+
## 时间与卡点
|
|
10
|
+
|
|
11
|
+
- 各阶段大致耗时:澄清 __ / 调研 __ / 设计 __ / 规格评审 __ / 实现 __ / 审查 __ / 测试 __ / 交付 __
|
|
12
|
+
- 卡点与原因:__
|
|
13
|
+
|
|
14
|
+
## 做得好的(保留)
|
|
15
|
+
|
|
16
|
+
- __
|
|
17
|
+
|
|
18
|
+
## 做得慢/反复的(下次避免)
|
|
19
|
+
|
|
20
|
+
- __
|
|
21
|
+
|
|
22
|
+
## 本次产生的可复用经验(写入 team/LEARNINGS.md)
|
|
23
|
+
|
|
24
|
+
- __
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# 规格说明(SPEC / Ultra Spec)
|
|
2
|
+
|
|
3
|
+
> pm 填写;维度要写透,写到 AI 能直接照着做,把会导致返工的问题在写代码前摊开。每一条都要具体输入输出,不允许「视情况而定」。
|
|
4
|
+
|
|
5
|
+
## 功能目标
|
|
6
|
+
|
|
7
|
+
(含存量视角:影响哪些已有模块 / 复用哪些组件)
|
|
8
|
+
|
|
9
|
+
## 验收标准
|
|
10
|
+
|
|
11
|
+
(逐条、可测)
|
|
12
|
+
|
|
13
|
+
- [ ] A1:
|
|
14
|
+
- [ ] A2:
|
|
15
|
+
|
|
16
|
+
## 业务规则
|
|
17
|
+
|
|
18
|
+
(每条对应具体「输入 → 输出」;把存量系统的隐性规则显式写出,不靠 AI 猜)
|
|
19
|
+
|
|
20
|
+
| 规则 | 输入 | 输出/行为 |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| R1 | | |
|
|
23
|
+
|
|
24
|
+
## 边界与禁止项(强制 · 沉默 ≠ 允许)
|
|
25
|
+
|
|
26
|
+
> **规格没写的行为,默认视为「允许」并被实现出来** —— 这是本包头号返工源(实证:一次 run 因规格沉默,把「能回复自己的评论」实现了出来,最后由**用户走查**才发现,并追加一轮 repair)。
|
|
27
|
+
> 每条边界必须写成「**禁止什么 → 期望拒绝(码/文案/HTTP 状态)→ 如何验收**」;**没有拒绝码的边界视为未定义**。
|
|
28
|
+
> 拿不准的边界**必须问用户**(clarify 的「边界十问」),不得留空、不得用「视情况而定」。
|
|
29
|
+
|
|
30
|
+
| 边界族 | 规则(禁止什么) | 期望拒绝 | 验收方式 |
|
|
31
|
+
|---|---|---|---|
|
|
32
|
+
| 自反关系 | 不能回复/点赞/关注/加好友/拉黑**自己** | | |
|
|
33
|
+
| 归属 / 跨父级 | 引用不属于本父资源的子对象(如跨帖 parentId) | | |
|
|
34
|
+
| 终态不可变 | 已删除 / 已隐藏 / 已归档对象不可再交互 | | |
|
|
35
|
+
| 越权 | 改 / 删他人资源(含管理端越权) | | |
|
|
36
|
+
| 幂等 | 同一请求重复提交不产生第二条 / 不重复计数 | | |
|
|
37
|
+
| 基数上限 | 单用户对单对象最多 N 次(回复 / 点赞 / 名额 / 次数) | | |
|
|
38
|
+
| 级联与计数 | 删除后计数归零、不残留脏值、不出现负数 | | |
|
|
39
|
+
| 并发同键 | 两个并发同键请求只允许一条落库 | | |
|
|
40
|
+
| 权限升降级 | 降级 / 封禁 / 退出后既有交互失效 | | |
|
|
41
|
+
| 可见性 | 软删对象的可见/不可见边界(含占位根、孤儿回复) | | |
|
|
42
|
+
|
|
43
|
+
## 边界 Case
|
|
44
|
+
|
|
45
|
+
- 空输入 / 非法输入:
|
|
46
|
+
- 权限边界:
|
|
47
|
+
- 并发 / 竞态:
|
|
48
|
+
- 历史脏数据 / 向前兼容:
|
|
49
|
+
|
|
50
|
+
## 安全边界(三级权限)
|
|
51
|
+
|
|
52
|
+
- **必须做**:
|
|
53
|
+
- **先询问**(遇到要抛给用户拍板):
|
|
54
|
+
- **严禁做**(列出不能碰的代码区 / 不可逆操作):
|
|
55
|
+
|
|
56
|
+
## 测试计划
|
|
57
|
+
|
|
58
|
+
- 单元 / 集成:
|
|
59
|
+
- 对存量功能的回归:
|
|
60
|
+
- 端到端(如有 UI):
|
|
61
|
+
|
|
62
|
+
## 假设(不阻塞的小决策,标注即可)
|