Files
dsh_shenxian/dsh-server-docs/08-skills/agent-operating-rules/references/03-多棒接力编排.md
T

196 lines
12 KiB
Markdown
Raw Normal View History

# 参考 03 — 多棒接力编排(全文)
> 本文件是 `agent-operating-rules` 的**细节层**。入口已给硬规则与两条排期铁律;本文件给**完整骨架、七条防护与成本基线**。**按需读**。
---
## 0. 定位
| 谁 | 管什么 |
|---|---|
| **本参考** | **怎么把长任务排成一条自动接力的链条**(编排层) |
| 工作区纪律(参考 02) | 归属三律、锁、目录、提交、批量、环境 —— **本参考的前置** |
| 协作与上抛判据(参考 01) | 该不该问用户、回复排版、结论骨架 |
| 本工作区 `docs/**/会话接续规范*.md` | 上下文超限时的**接续包模板 / 开机步骤 / 多线并行**(本参考是它的"多棒编排"补充,⛔ 不重复已写的字段与成本公式) |
| 本工作区 `接续入口_<线名>_<日期>.md` | **每一条工作线的唯一执行依据**(本参考的核心依赖) |
---
## 1. 形态:规划棒 ↔ 执行棒 交替
```text
规划棒①(出交接单)→ 执行棒①(照单落地)→ 规划棒②(出下一单)→ 执行棒② → …
↑ 每棒 = 一个全新会话 + 一条一次性自动化,做完自己登记下一棒
```
**为什么拆成两种棒(不是随便切段)**
| 棒 | 只做什么 | 成本量级(实测) |
|---|---|---|
| **规划棒** | **只出交接单**:不改服务器、不改代码、不部署 | 23–56 次调用 / 5.7–9.4 积分 / 3–10 min |
| **执行棒** | **照单落地**:按单子的 S0–Sn 逐条执行、逐条验收 | 93–215 次调用 / 23–29 积分 / 21–41 min |
⇒ 这是「**规划与执行分离**」从纪律变成**机制**:规划棒物理上碰不到生产,执行棒物理上不必做取舍。
**⛔ 什么时候不要用这套**
- 一次性小任务(直接做,别排链条)
- 步骤可并行(用并行会话 + 全局锁,不需要串成链)
- **任务形态本身就贵**(例:批量改写 N 份文档)—— 那只该**先写脚本一次跑完**;接力**救不了**贵的活,只换场地
- 单棒做不完(会超出上下文预算)⇒ 说明**棒还要再切细**,或改用「接续包 + 开机步骤」
- 🔴 **链条上存在「需要用户拍板」的决策点** ⇒ 可自决的段落照常接力,但**必须在拍板点前停下**,不许自动跨过去(**见 §3.3 登记门禁**)
---
## 2. 六件套 prompt 骨架(照抄填空)
> **位置**:每棒的 prompt 写在自动化的 `prompt` 字段里。
> **要点**:整段 400–1,300 字符。**越长越糟** —— 每多抄一个技术细节,就多一个漂移源。
```text
<线名> · <第 N 棒:规划棒 / 执行棒>(本轮只做这一件事,做完即停)。
第 0 步:跑 `<绝对路径>/state.py` 看状态(只读、免抢锁、1 次调用拿到锁/git/入口/收口)。
第 1 步:抢全局执行锁 `bash "<绝对路径>/handoff-guard.sh" --claim-exec "<线名>-<第N棒>"`;**抢不到 = 有会话在跑 ⇒ 只报告并立刻停**。
第 2 步:读**唯一执行依据** = `<入口文件绝对路径>` 的 **§2「本轮动作」块**,按它点名的那份交接单开工。
(规划棒专属)本轮任务:出可执行交接单,落盘 `<路径>`,按 8 段模板:目标 / 只读前置 / 范围 / 决策点 / 步骤 S0–Sn / 逐条验收判据 / 回滚 / 回报格式。
(规划棒专属)⛔ 开工前先加载技能 `agent-operating-rules`(取舍判据以它为准,不凭记忆)。
约束:⛔ 不 commit / push;⛔ 不做 <明确点名的排除项>;⛔ 不重做 <已收官的序号>;⛔ 不扩大单子范围(单外发现的缺陷先报告、不动手)。
成本纪律:批量活先写脚本再让脚本跑;取证最多 3 条命令;⛔ 不要 Glob/Grep 全库摸底;一轮内工具调用次数尽量压低。
纪律:技术实现项**自决不上抛**;只有「没有客观优劣」的取舍才列候选,且每个候选必须写「优点 / 缺点」、**候选竖排成段**(不横排);判据必须可被第三方复现。
收尾(缺一即算未完成):① 释放锁 `--release-exec`;② **先过登记门禁(见 §3.3)**——只有「下一棒可自决」才登记,**`scheduledAt` = 此刻 + 5~8 分钟(见 §3.1.1 铁律①)**,且**同一时刻只挂一个接续棒**(铁律②:⛔ 不预登记队列,后续项写进入口 §2 的「本线下一项」由下一棒自己排);用**陈述句**告知「已登记自动接续、约 5~8 分钟后自动开新会话、接续点 = X」;③ 把入口 §2「本轮动作」推进到再下一棒;④ 写工作区日志。
```
### 2.1 三条骨架为什么长这样(都有实测出处)
| 骨架 | 治什么 | 实测依据 |
|---|---|---|
| **第 2 步 = 指向入口,不抄细节** | **细节漂移**(细节有两个来源 ⇒ 必然打架) | 某版 prompt 重述了整段技术细节 ≈1.2 KB,反而**挤掉了"开机步骤"那一行** ⇒ 40 次调用 / 9.37 积分(立项口径 ≤10 次 / ≈1 分) |
| **「本轮只做这一件事,做完即停」** | 无人值守时的**自我扩权** | 实测:用户只说「先确认待办」,第 28 次调用**已在写代码** |
| **「取证最多 3 条命令」** | 防御性过度取证 | 实测同一会话第 7–24 次**连续 17 次取证**,reasoning 里三连自我加码「取证非常完整了」 |
| **纪律块(自决不上下抛 + 候选写优缺点)** | **把决策方法内联**(新会话读不到旧上下文,方法论不会自己进来) | 实测:9 棒里 `Skill` 调用 **0 次** ⇒ 判据全靠这段内联文字撑住 |
### 2.2 ★ 已知缺口:Skill 调用 = 0(修法)
**实测**:全部 9 棒里 `function_call.name == "Skill"` **一次都没有**。判据是 prompt 里的**内联摘要**在起作用,完整方法论从未进上下文。
**修法**(分棒区别对待,别一刀切):
- **规划棒必须加**:`⛔ 开工前先加载技能 agent-operating-rules`(规划棒基数只有 23–56 次调用,+1 次可接受,且它确实要做取舍、要出单)
- **执行棒可以不加**:单子已经把判断写死了,再加载方法论是纯开销(执行棒基数已 93–215 次)
---
## 3. 收尾四件套(缺一即算未完成)
> 这四件里**第 ② 件是唯一会"断链"的地方**,也是钩子**做不到**的地方(钩子不能创建会话、不能创建自动化)。
| # | 动作 | 判据 |
|---|---|---|
| ① | 释放锁 `--release-exec` | 跑一次信息模式确认已释放 |
| ② | **先过 §3.3 登记门禁** → 登记下一棒的一次性自动化(`scheduledAt` = 此刻 + 5~8 分钟)+ **在给用户的回复里用陈述句告知** | 门禁不过 ⇒ **不登记,改为告知"链条已暂停待拍板"** |
| ③ | 把入口文件 §2「本轮动作」**推进到再下一棒** | 入口 = 下一棒的**第一信息源**;不推进 ⇒ 下一棒照旧口径做,做重工 |
| ④ | 写工作区日志(当日 `memory/YYYY-MM-DD.md` 追加自己的小节) | 只追加自己的小节,⛔ 不重写别人的段落 |
### 3.1 收尾陈述句模板(照抄)
```text
已登记自动接续:一次性 automation `<id>`,约 5~8 分钟后(08:37)自动开新会话,**不用你操作**;
接续点 = 序 ④「443/TCP 兜底」的规划棒(出 `05-交接单/交接单_xxx_20260917.md`)。
```
### 3.1.1 ⛔ 排期两条铁律
> 用户原话:「**首个接续任务 5-8分钟**」+「**最好不要建立多个接续任务,一个会话结束时在排下一个**」
| 铁律 | 内容 | 踩过的坑 |
|---|---|---|
| ① **首个(唯一)接续棒 = 收口 + 5~8 分钟** | 间隔指的是"**从收口到首棒开跑**",⛔ 不是"棒与棒之间";⛔ **不许留长等待窗口** | 曾把 `scheduledAt` 定成几十分钟后 ⇒ 用户当场纠正 |
| ② **同一时刻只挂一个接续棒** | 下一棒由**当棒收官时再排**;⛔ **不预登记队列** | 曾一次预登记多个 ⇒ 用户当场纠正 |
⚠️ `ACTIVE` ≠ 「待跑」⇒ 看 `scheduledAt` 是否已过。
### 3.2 「重挂改时间不触发」防护
**改时间不会触发** ⇒ 需要重排时**必须新建**一条一次性自动化,⛔ 不要改现有那条的 `scheduledAt` 期待它自动生效。
### 3.3 ★ 登记门禁:**要拍板的,等拍了再登记**
> **顺序不可颠倒**:**先判「是不是要拍板」,未命中才轮到「候选排不排得出优劣」。**
> ⛔ 顺序颠倒 = **自我扩权**(实测:因为"A 明显更优"就自己登记了下一棒 ⇒ 而拍板其实还没定 ⇒ 接续已开跑)。
**判据**:下一棒若含**边界外事项**(业务优先级 / 花钱 / 凭据 / 偏好 / 影响面 / 不可逆)⇒ **不登记下一棒**,停下等拍板;**拍板到手后再建**。
边界外八类见 `references/01-协作与上抛判据.md §1.2`。
### 3.4 七条实测防护
| # | 防护 | 说明 |
|---|---|---|
| 1 | **断链** | 收尾四件套缺失 ⇒ 链条断;第 ② 件是唯一断点 |
| 2 | **双开** | 抢锁失败仍开工 ⇒ 两个会话改同一批文件 |
| 3 | **once 不转完成态** | 一次性任务跑完不自动转"完成" ⇒ 看 `scheduledAt` 与状态判,别只看 `ACTIVE` |
| 4 | **跨过拍板点** | 见 §3.3 |
| 5 | **下一棒定太晚** | 见 §3.1.1 铁律① |
| 6 | **预登记多个接续棒** | 见 §3.1.1 铁律② |
| 7 | **重挂改时间不触发** | 见 §3.2 |
---
## 4. 自动化 = 开新会话的唯一通道
> ⚠️ **钩子无此能力** ⇒ 想"自动开新会话"只能靠一次性 / 定时自动化(否则是半自动)。
**每条自动化 prompt 的五要素**:
1. **开机第 0 步 = 跑状态脚本**(一次调用拿到锁 / 基线 / 入口 / 收口点)
2. **prompt ⛔ 不抄任务细节** —— 细节只有一个漂移源 = 入口文件的「本轮动作」块
3. **并行口令必带线名**(否则不知道是哪条线)
4. **抢不到锁 = 只报告,不接管、不删锁**
5. **登记后必用陈述句告知用户**("约 X 分钟后自动开新会话,不用你操作,接续点 = Y")
🔴 **下一棒 id 只来自工具返回值**(⛔ 不要自己编 id)。
🔴 **`cwds` = 本工作区**(见 `references/02-工作区纪律.md §1 律②`)。
🔴 **归属三律的收尾自检**:本棒 `cwds` 是否 = 我这条线自己的工作区?入口文件是否只在我这个工作区存在一份?
---
## 5. 成本纪律
> **成本 ≈ 单价 × 一轮内工具调用次数** ⇒ 杠杆 = **压一轮工具次数**,不是压轮数。
| 手段 | 做法 |
|---|---|
| **状态单点** | 用一条状态脚本(约 30 行输出)代替十几轮探索 ⇒ ⛔ **跑完它之前不许 Glob/Grep 全库摸底** |
| **大输出先落盘只读关键行** | 别把整份日志灌进上下文 |
| **限流** | `head -30` / 只取需要的字段 |
| **批量活写脚本** | 写一个脚本跑完,**只 print 摘要**;⛔ 不要一轮一轮手敲 |
| **取证上限** | 一轮最多 3 条取证命令 |
| **无人值守 prompt 必写** | 「本轮只做一件事,做完即停」 |
---
## 6. 交付门禁(编排视角)
> ⛔ 四条自我安慰**都不算交付**:「本机改完了」「build 通过了」「本地打包完成」「已 commit」。
**判据 = 在用户可见面复验** —— 按**生效链路**逐层走完,最后在**用户实际能看到的那一面**验证一次。
形态:静态页 → **传到目标环境**(⚠️ 注意 CDN 缓存)|有构建步骤 → **build + 重启**|插件 / 包 → **打包 → 投放 → 启用 → 重启**|文档 → **同步 + 对账**。
⚠️ 别回头问"要不要部署" —— 部署属 lane 内执行细节。
---
## 7. 落地到某个工作区前,先核对五项
本参考是通用形态。在某工作区使用前,先确认下面五项(都在**该工作区自己的规则文件**里):
1. **状态脚本**在哪、是否支持 `--ws`(跨工作区取状态**只调不抄**)
2. **入口文件**的命名、位置与「本轮动作」块的固定位置
3. **锁脚本**的抢 / 放命令
4. **交接单模板**(8 段:目标 / 只读前置 / 范围 / 决策点 / 步骤 / 验收 / 回滚 / 回报格式)
5. **日志与记忆**落点
> ⛔ **绝对不要**因为"另一个工作区是这么做的"就把那边的路径搬过来 —— 这正是归属事故的成因(`references/02-工作区纪律.md §1`)。