Files

335 lines
25 KiB
Markdown
Raw Permalink Normal View History

# 协同监管棒 · 作业规程(SOP)
> ## ⛔ 已退役(2026-09-30)
> **本件(作业规程)的内容已并入 → `E:/ProgramData/.workbuddy/skills/session-mechanism/references/architecture.md`(协作机制的唯一权威文档)**
> ⇒ ⛔ **别再引用本件做判断**(曾因它把旧结论当现状);本件**只作历史沿革留档**,⛔ 已不再维护。
> 依据:用户 2026-09-29 定案「**只有一份架构文档**」「**一切迭代都在 skill 内**」「⛔ 不在工作区或别处另开平行文档」。
> ⚠️ **术语已退役(2026-09-29)**:**⛔ 不存在"协同监管棒"这个角色**。本文件是**「入口会话被叫起来干一轮」的作业规程**;
> 协同 = **两个动作**:**收尾自判**(棒内、零额外会话)+ **心跳巡检**(全局、1 会话/小时)。
> 📖 顶层设计与"打转清单" ⇒ `交付物/多会话协同-顶层设计-20260929.md`(**加组件前先过它的 §7 判据表**)。
> ⚠️ 文件名保留历史名(被自动化 prompt 引用),**内容以上述口径为准**。
> **本文件是「协同监管棒」的唯一作业规程**;所有监管类自动化(一次性/循环)只需在 prompt 里写
> 「读 `E:/ProgramData/AIProject/ai1net-dsh-server/交付物/协同监管棒-SOP.md` 并按它跑一轮,做完即停」。
> ⇒ 改规程只改本文件,**一处生效全体**(⛔ 不必逐个改自动化 prompt)。
> 角色:本工作区(`ai1net-dsh-server`)是「手机接入」的**目标与协同唯一入口**。
>
> 📌 **机制定义(权威)⇒ `交付物/多会话协同机制-定稿-20260929.md`**(三个角色/四条通道/节奏/**派活模板**/异常处置表/收敛)。
> 本文件是它的**作业规程(更细)**;🔴 **冲突以本文件为准**。**派活的可复制 prompt 模板 ⇒ 定稿件 §4.1**。
---
## 0 触发方式(三层 · **先用本地脚本,AI 只做判断**)
> 原则(2026-09-29 用户点破):**"查文件在不在 / rc 是否为 0 / 哈希是否一致 / 锁空不空闲" 这类判断不需要 AI**;
> 而且 —— 🔴🔴 **"各线干完了没有、结论是什么" 也不需要轮询:宿主已经把它落库了。**
### 0.1 🔴 收结果 = **一条 SQL,不是轮询**
**宿主每次跑完自动化,会把该次运行的收官结论直接写进宿主库 `automation_runs.thread_title`**(`status` 含 `IN_PROGRESS` / `ACCEPTED` 等)。
⇒ **"让那个会话把结果告诉你"已经由宿主实现了**:读库即可,**⛔ 不需要扫别线文件、⛔ 不需要叫 AI、⛔ 不需要轮询**。
```python
# 只读,⛔ 不写库、⛔ 不改 WorkBuddy 任何状态
import sqlite3, os, pathlib
db = pathlib.Path(os.environ.get("CODEBUDDY_CONFIG_DIR") or r"E:\ProgramData\.workbuddy") / "workbuddy.db"
con = sqlite3.connect("file:%s?mode=ro" % str(db).replace("\\", "/"), uri=True, timeout=4)
for row in con.execute("select rowid,status,thread_title,automation_id from automation_runs order by rowid desc limit 8"):
print(row)
```
(`advance-watch.py` 已内置,见下;`rowid` 用作水位 ⇒ 只报"新出现的结论"。)
**已实测的读数样例**(07:45):
```
[IN_PROGRESS] 2981522e · (空) ← 棒 1b 正在跑(能看见"在跑")
[ACCEPTED] 6c4fefe8 · 判定:G-A 三步全部执行到位、逐步取证通过,verify rc=0…
[ACCEPTED] 928b269c · 对接单已按 09-29 实测同步完毕…
[ACCEPTED] 796bb627 · 棒 1 代码层完成+对真网关取证全过(50/50 无 429),但未真装…
```
⚠️ **另一条不通的路(已实测否掉)**:`GET /api/v1/jobs` 是**后台智能体实例**,本机实测 **0 条** ⇒ 它**不是**我们派出去的那些 UI 会话的通道,⛔ 别拿它当"会话间通讯"用。
### 0.2 三层
| 层 | 谁 | 延迟 | 成本 | 做什么 |
|---|---|---|---|---|
| **⓪ 机械层**(第一道) | **钩子**在会话收尾时调 **`.workbuddy/tools/advance-watch.py`** | **即时(<1s)** | **零 token、零会话** | ① **直读 `automation_runs` 拿各线收官结论**(含 `IN_PROGRESS`)② 机械判三线靶点 + 全局靶点 + 锁状态 ③ 覆写 `tmp/supervise-inbox/advance.md` + 写 `needs-ai.json`。自带 120s 节流、异常全吞(fail-open) |
| **① 决策层**(主) | 各线棒做完后创建一次性自动化叫本棒(`scheduledAt = now + 2 分钟`,`cwds = ai1net-dsh-server`);⛔ 也可只在 `needs-ai=true` 时叫 | ≈2 分钟 | 一个会话 | **需要 AI 判断的部分**:判 V1–V7、写看板措辞、定缺口、派下一棒 |
| ② 兜底层 | 每小时循环(`1eaf45c3`,至 09-30 12:00) | ≤60 分钟 | 一个会话 | 防链条断掉;先看 `needs-ai.json`,**need=false 且无新结论 ⇒ 只刷看板不派活** |
⚠️ **已撤销**:原先那 4 档"每 20 分钟"的一次性自动化(`392f4f97`/`a0f6bd2a`/`201b2a62`/`48adad96`)**已删**。
⚠️ **为什么不能彻底去掉自动化**:要"**另一个 AI 会话**"来干活,**只能靠自动化**(钩子是本地子进程,**开不了新会话** —— 宿主硬边界,已实测)。
⇒ 正确的减法 = **自动化只用来"派活"(必须开新会话那一步)**;**"收结果/检测"一律下沉到 ⓪ 层直读库**。
**钩子侧已确认覆盖三线**:`wb-result-hook.py` 的 `LINE_WS = {ai1net-dsh-desktop: 客户端线, ai1net-dsh-anywhere: 手机接入线, ai1net_ui}` ⇒ 三线收尾事件都会驱动 ⓪ 层。
> **为什么不让钩子直接派活**:钩子**不能开新会话**(自动化才是唯一通道),钩子侧只能**观察**(写台账/刷 `tmp/supervise-inbox/`,已覆盖三线:`ai1net-dsh-desktop` / `ai1net-dsh-anywhere` / `ai1net_ui`)。
> **为什么不用常驻进程**:把长跑服务放进**会话后台任务** ⇒ 每轮输出唤醒宿主 ⇒ **会话永不空闲 ⇒ 用户看到"卡死"**(已实测)。⛔ 一律不许。
---
## 1 开工第 0 步:抢锁
```bash
bash "D:/github/dsh_shenxian/dsh-server-docs/07-scripts/handoff-guard.sh" --claim-exec "<你的会话名>" --domains ai1net-dsh-server/
```
**抢不到 ⇒ 只报告并停**,⛔ 不写任何东西(R9:不删锁、不接管)。
---
## 2 先读权威件
- `交付物/手机接入-目标与协同计划-20260929.md` —— §一 **V1–V7** · §四 棒次 · §五 协同与纪律 · §六 红线
- `交付物/手机App经覆盖网络操作WorkBuddy-架构定稿v3-20260929.md` —— **§0.5 硬约束 T1–T7** + §6 G-C
- ⛔ 以 v3 为准,**别照 v2 抄**(v2 已降为过程档案)
---
## 3 每轮做四件事
### ① 收产出(只读,⛔ 不改别线文件)
| 线 | 看什么 | 靶(要达到的样子) |
|---|---|---|
| `ai1net-dsh-desktop` | `docs/执行单_GA_desktopprofile结论_20260929.md` + 本轮恢复产出 | `C:/Users/Administrator/.dsh/profiles/desktop` **存在** 且 `mount-into-profile.mjs verify` **rc=0** |
| `ai1net_ui` | `docs/执行单_棒1_垫片归并与改造_20260929.md` + 棒1b 产出 | **T1–T7 逐条有读数** + 装后读数(自检不回显口令 · 50×200 无 429 · 剥 Origin 生效 · 与直连数据一致) |
| `ai1net-dsh-anywhere` | 对接单同步 / 端侧调整产出 | 对接单已按 C1–C6 更正;端侧按 v3 §2.2 会话契约调整 |
**是否真开工的佐证(防纸面派活)**:三者的 `.workbuddy/memory/2026-09-29.md` 最后修改时间 + `D:/github/dsh_shenxian/dsh-server-docs/05-交接单/.locks/` 是否有对应域锁。
### ② 判 V1–V7 逐项
状态取 `✅过 / 🟡部分 / ⛔未过 / ⛔被前置挡住`;**挡住必须写清"被谁挡"**。
**V7(硬约束)=连续 1 小时 / ≥50 次操作**:WorkBuddy 主进程 **pid 恒定** · 宿主会话**能回 idle** · 桌面**"当前对话"未被改** · **无 429** · **无新增对外端口** · WorkBuddy 配置目录**哈希零差异**。
### ③ 覆写进度看板
`交付物/手机接入-进度看板.md`(表:棒 | 线 | 状态 | V 判据 | 阻塞 | 下一动作 + 更新时间 + 一句话总况)。
⇒ 这是给用户"**一眼看进度**"用的,⛔ 不长篇、⛔ 不写流水账。
### ④ 按缺口派下一棒
**规矩**:一棒一线 · **每条线只挂一个** · 排期=**收口+5~8 分钟** · 派活用**一次性定时自动化**。
**停滞判定(自动重派)**:某线**既无新产出、又不持有锁**,且距上次派活 **>25 分钟** ⇒ **重派**,并在看板"下一动作"里写明重派原因。
**派什么(按缺口)**:
- G-A 未完成 ⇒ 派 `ai1net-dsh-desktop`
- 垫片未真装 或 T1–T7 有缺 ⇒ 派 `ai1net_ui`
- 端侧/联调未动 ⇒ 派 `ai1net-dsh-anywhere`
- 无缺口 ⇒ 派「**棒 4 真机端到端联调**」
🔴 **新派活的 prompt 必须逐字包含三条**:
1. 「抢不到锁 ⇒ 只报告,⛔ 不写任何东西」
2. 「**v3 §0.5 硬约束**:不得影响 WorkBuddy 本身的运行 · 不夺会话(借用必归还)· 口令不落盘 · 不起常驻任务 · 不给网关加 CORS 白名单」
3. 「**【收尾即叫监管】做完后立即创建一个一次性自动化:name=`协同监管棒 · 立即轮(<线> 收尾)`,cwds=`E:/ProgramData/AIProject/ai1net-dsh-server`,scheduledAt=当前时间+2 分钟,prompt=读 `交付物/协同监管棒-SOP.md` 并按它跑一轮,做完即停。**」
⇒ 这样**上游一完成,本棒立刻被叫起来**,⛔ 不用等整点、⛔ 不用等用户催。
📋 **可直接复制的派活 prompt 模板 ⇒ `交付物/多会话协同机制-定稿-20260929.md §4.1`**(含上述必含三条款)。
---
## 4 收尾(每轮都做)
1. 本轮结论**追加**进 `.workbuddy/memory/2026-09-29.md`
2. `--release-exec` 释放锁
3. **停下**(一次只做一件事、做完即停)
> ⛔ 旧版这里有一条"删 `.dispatch-claim` 释放去抖窗口" —— **已作废**(自造去抖协议已删,改用**域锁**当单例 ⇒ **没有任何需要记得清理的东西**)。
---
## 5 硬约束(每轮自检)
- ⛔ 本功能不得影响 **WorkBuddy 本身的运行**(v3 §0.5 T1–T7)
- ⛔ **绝不用会话后台任务跑长跑**(会把宿主会话反复唤醒 ⇒ 用户看到"卡死")
- ⛔ 不替别线干活 · ⛔ 不给网关加 CORS 白名单 · ⛔ 口令不落盘 · ⛔ 不删锁/不接管
## 6 收敛条件
**V1–V7 全过** ⇒ 看板标「**目标达成**」;此后 ⛔ **不再派新棒**(只刷新看板),并在报告里明说"**可结束监管**"。
(循环类自动化设了 `validUntil = 2026-09-30 12:00` 作为兜底终止线。)
---
## 7 🔴🔴 自我保护:**别把自己卡死**(2026-09-29 用户明令 · 本轮已踩两次)
> 用户原话:「**还有要注意别把自己又卡死了**」。以下每条都是**实测事故**换来的,⛔ 不得违。
| # | 禁令 | 为什么(实测) |
|---|---|---|
| **S1** | ⛔ **绝不在会话里起后台任务 / 常驻长跑**(尤其别用"会话后台任务"跑服务) | 后台任务的**每轮输出都会唤醒宿主会话 ⇒ 会话永不空闲 ⇒ 用户看到"卡死"**。09-29 我因此违反 6 次 |
| **S2** | ⛔ **单条前台命令控制在 ~90 秒内**;长活**拆短步**或**走异步** | 实测**合计 >~45~100 秒的前台命令会被沙箱杀掉**(`Exit -1` / `SIGTERM`,且**无输出**);⚠️ **被杀时会连带杀掉你先前后台起的进程** |
| **S3** | **一轮只做四件事就停**(收产出 → 判 V → 刷看板 → 派一棒) | 长会话=长回合=更易被中断、也更贵;"一次只做一件事、做完即停"是项目既有纪律 |
| **S4** | ⛔ **不对正在运行的宿主会话做 `load` / 接管**;⛔ 不抢 `writer_occupied` | 会把用户正在用的会话夺走;且 load 会改桌面"当前对话"(违 V7/T2) |
| **S5** | ⛔ **不试凭据、不轮询**;探活只用不计失败额度的路径 | 网关失败限流 `2/min + 12/h`(只计失败)⇒ 试错会把自己锁死一小时 |
| **S6** | **所有对外调用都带短超时**(读 ≤5s、写 ≤10s) | 无超时=把"等待"传导成"卡住" |
| **S7** | **卡住时的正确动作=关掉自己**(释放锁 → 报告 → 停),⛔ 不是"重试到成功" | fail-safe 方向见 v3 §0.5 |
**自查(每轮收尾时问自己一句)**:本轮我有没有起过后台任务?有没有跑超 90 秒的前台命令?有没有碰别人的活会话?——有 ⇒ 下轮纠正并在记忆里记一笔。
---
## 8 汇总与协同的落点(用户:"所有的信息汇总和协同都在你这")
| 用途 | 唯一落点 |
|---|---|
| **一眼看进度** | `交付物/手机接入-进度看板.md`(每轮覆写) |
| **目标 / 验收 / 棒次 / 协同纪律** | `交付物/手机接入-目标与协同计划-20260929.md` |
| **架构权威(含硬约束 §0.5)** | `交付物/手机App经覆盖网络操作WorkBuddy-架构定稿v3-20260929.md` |
| **监管作业规程(本文件)** | `交付物/协同监管棒-SOP.md` |
| **机制定义 / 实施方案** | `交付物/多会话协同机制-定稿-20260929.md` / `…实施方案-20260929.md` |
| **过程取证** | `tmp/wb-phone/`(⛔ 不入库)+ 各线自己的 `docs/执行单_*.md` |
⇒ 用户只需看**看板**;其余都是支撑件。⛔ 别再让用户来催。
---
## 9 🫀 队列 · 并发 · 心跳(**不依赖任何会话 · 不靠任何常驻程序**)
### 9.1 队列:**宿主表就是队列**(⛔ 不用自己造)
- `automation_runs` 是 **append-only + `rowid` 自增有序** ⇒ **多条线同时提交 = 各写各的行,互不覆盖** —— **这就是队列**。
- 我的游标 = **`rowid` 水位**(`tmp/supervise-inbox/runs.watermark`)⇒ 只处理**新出现的行**;重复读不重复处理(**幂等**)。
- 🔴 **我只读、不写** ⇒ **永远不参与写竞争**(不需要锁、不会丢更新、不会假绿)。
- 判定"该线最新结论" = 取该线**最大 rowid** 的那一行(⛔ 不依赖时间戳,避免时钟问题)。
- ⚠️ `[IN_PROGRESS]` 行标题可能为空 ⇒ **判"在跑"看 `status`,⛔ 不把空标题当"没干活"**。
### 9.2 串行化(不重复派活):**读表 + 域锁**
- 派活前先读 `automations` 表:**同一条线若已有 ACTIVE 且未跑的棒** ⇒ ⛔ **不再派**(`advance.md` 里有"当前已挂的棒"清单)。
- 需要并行时用**域锁**(域不重叠才并行);机制层必须独占。
- 一棒一线 · 每条线只挂一个 · 排期 = **收口 + 5~8 分钟**。
- 🔴🔴 **术语退役(2026-09-29 按用户意见)**:**不再有"协同监管棒"这个角色**。协同 = **两个动作**:
| 动作 | 谁做 | 判什么 | 成本 |
|---|---|---|---|
| **收尾自判**(棒内) | **刚干完活的会话**(已在跑) | **只判"我这条线"缺口** ⇒ 有则写下一行 `automations` | **零额外会话** |
| **心跳巡检**(全局) | 心跳(每小时 · 宿主排期) | 全局限:V1–V7 是否全过 / 线是否停滞 | 1 会话/小时 |
- 🔴 **单例就去抖,⛔ 不要自造 `mkdir`/flag 协议**:两者都**先抢域锁**(`--domains ai1net-dsh-server/`);
**抢不到 ⇒ 什么都不做**(已有人在推进)⇒ **天然去抖,且无任何"需要记得清理"的东西**(旧的 `.dispatch-claim` 已作废)。
- 📖 **顶层设计与"打转清单"⇒ `交付物/多会话协同-顶层设计-20260929.md`**(加组件前先过它的 §7 判据表)。
### 9.3 心跳(**"监管会话死了"也能续**)
- 🔴 **唯一的心跳 = 循环自动化(由宿主排期)** —— 它**每次开的是新会话**,**与任何一个具体会话无关**。
- 🔴 **监管棒是"无状态可替换角色"**:读 SOP → 读库 → 判 V → 刷看板 → 派活 → 退,**不携带记忆** ⇒ **任何会话死掉都不影响链条**。
- ⇒ **本会话(发起方)关掉也照样推进**:状态在 **DB / 产出文件 / 看板**(都不是会话);推进由**宿主排期**驱动。
- 🔴 **收敛自停**:若看板已标「**目标达成**」⇒ ① ⛔ 不再派新棒 ② **把心跳自动化置为 `PAUSED`**(用 `automation_update` 改自己那条 id)③ 报告里写明「**可结束监管**」。
- ⚠️ 心跳设了 `validUntil` 作**硬终止线**;`advance.md` 会标 `expired` ⇒ 见到就**续期**(新排一条),否则整条链静默断掉。
### 9.5 🔴 12:00 前的**排序原则**(2026-09-29 加 · 保关键路径)
**任何一轮派活前先问:这一步通不通向 V1?** 通不通向"**手机经设备入口看到桌面会话**"?
| 优先级 | 内容 | 说明 |
|---|---|---|
| **P0 关键路径** | `20090` **能通且能常驻** → 设备入口可达 → 手机可见/可发 | 直指 V1/V2 |
| P1 | 让关键路径**不退回去**(与 `keepalive.py` 自愈配合:重复拉起幂等、不叠加多客户端抢 `20090`) | 否则"验证过"≠"可用" |
| **P2(押后)** | UI / 配对卡片 / 文档 / 浏览器级判据(除非它就是关键路径) | ⛔ 12:00 前**不许**占用关键窗口 |
⚠️ **一个必须自觉的陷阱(本日实测)**:某棒结论写「端到端八项判据**两轮起停各一遍全绿**」——
那是**"能跑起来"**的证据,**⛔ 不等于"通路可用/常驻"**(它跑完就关停了,`20090` 随即消失)。
⇒ **判"可用"的唯一判据 = 现在这一刻 `127.0.0.1:20090` 通不通,且能否被自愈维持住。**
### 9.6 🔴 必须区分「**真成果**」与「**接续任务**」(2026-09-29 用户要求)
看任何"进展"时**先分三类**,⛔ 别把后几类当成果:
| 类 | 判据 | 算不算进展 |
|---|---|---|
| **✅ 真成果** | `automation_runs` 里 **`ACCEPTED` 且有结论**,**且最好有可核对产物/读数**(文件 / rc / 端口 / 数据对照) | ✅ **算** |
| **🟡 接续任务** | 只是新增了一条 `automations`(**会话自己排的下一棒**) | ⛔ **不算** —— 它只证明「**有下一步**」,**不证明「这一步干成了」** |
| **🏃 刚开始跑** | 有 run 但 `IN_PROGRESS` / 标题为空 | ⛔ **还不算**(未见结论) |
| **⛔ 哑火** | 到了 `scheduled_at` 却**没产生对应 run** | 🔴 **当异常处置**(链条断了) |
⇒ 看板 / 实时状态 / 汇报里**必须按这几类分开写**。
`thin-consumer.py` 已内建此分级(实时状态里的「🔎 **证据分级**」一行 + 独立段落)。
⚠️ 推论:**"在跑的棒 N 个" 是排期数,⛔ 不是成果数** —— 引用时不许混为一谈。
### 9.7 🩺 机制自检(**空闲时执行** · 2026-09-29 用户要求)
**定期检查「协作机制本身」是否执行正常、是否需要优化** —— 但**只在空闲时**做,⛔ 不与会话协作抢资源。
**空闲判据(同时成立才算空闲)**:① **无锁持有者**(`.locks/` 下无目录)② **无 `IN_PROGRESS`** run。
⇒ **忙 ⇒ 本轮跳过**并记「⏸ 跳过(忙)」,⛔ **不执行任何检查动作**(连报告都不写)。
**体检项(全部只读)**:
| 项 | 判据 | 异常含义 |
|---|---|---|
| **哑火** | ACTIVE 的一次性自动化已过 `scheduled_at` **15 分钟以上**,却**没有对应 run** | 链条断了(没人接) |
| **抢锁失败** | 近 N 条 run 的结论含「抢锁失败」 | 机制摩擦(有会话在持锁)—— ⚠️ 是**摩擦**不是**故障** |
| **并发** | 同时存在**多个** `IN_PROGRESS` | 可能重复派活 / 双写 |
| **关键件齐备** | 计划件 / 看板 / 实时状态 / 本 SOP 是否都在 | 文件被移走 ⇒ 机制失去依据 |
**产出**:`交付物/协作机制-体检报告.md`(**最多每 5 分钟一次**,且仅空闲时)。实时状态里有「🩺 机制自检」一行给用户看。
**由谁执行**:**`thin-consumer.py`**(常驻、只读)—— 它在"没有会话跑"的时候**照样活着**,正好做这件事;
⛔ **不要为此再排会话**(那就又跟协作抢资源了);⛔ 不写任何共享文件(只写体检报告)。
### 9.0 🧩 **唯一常驻程序 = `collabd.py`**(2026-09-29 用户定案:"除了安排任务外,功能都做到单独程序中长期维护优化")
**主会话只做两件**:**判断**(V1–V7 / 缺口)+ **派活**。**其余全部在一个程序里**:
| 程序 | 承担 |
|---|---|
| **`.workbuddy/tools/collabd.py`** | ① 通路自愈(连续 N 次不通才拉客户端·防误杀)② 监控+**证据分级**+推进判定 ③ 机械靶点判定(写 `advance.md`)④ **真空判定**(写 `VACUUM.md`)⑤ 断链/中断告警(`STALL.md`)⑥ **机制体检**(仅空闲)⑦ 会话状态定期检查 ⑧ 实时状态视图 ⑨ 单例守护(`:20099`) |
| ⛔ **它不做的** | **派活/开新会话**(必须由会话做,且只允许白名单两类 —— 见 `CODEBUDDY.md §1.5 F`) |
**用法**:`python collabd.py`(常驻,用**宿主后台机制**启动)|`python collabd.py --once`(跑一轮即退,**钩子调这个**)|`--where`(路径自证)。
**已吸收退役**:`keepalive.py`、`thin-consumer.py`、`advance-watch.py`(三件合并为本件;⛔ 不要再单独启动它们)。
⚠️ 合并时修掉一个潜伏 bug:`sessions` 表**没有 `name` 列**(原 `thin-consumer` 写错、静默返回空)⇒ 正确列 = `id/title/custom_title/status/updated_at/last_activity_at/unread`。
### 9.8 🕳 真空接管(**需求未完成 ∧ 无人执行** ⇒ 主会话接管 · 2026-09-29 用户要求)
**"真空" = 两个条件同时成立**:
1. **需求未完成**(关键路径未通 / V 未全过)
2. **没有会话在执行**(**无锁持有者 ∧ 无 `IN_PROGRESS`**)
⇒ **持续 ≥5 分钟**才算真空(防瞬断误报)⇒ `thin-consumer.py` 写 `tmp/supervise-inbox/VACUUM.md`(恢复即自动删)。
**谁接管 = 主会话(本工作区的「入口推进」)**。它被叫起后(检查点 / 心跳 / 人工),**先看 `VACUUM.md`**:
1. 抢域锁(`--domains ai1net-dsh-server/`)
2. 读 `advance.md` + `VACUUM.md` ⇒ 判 V1–V7 与**关键路径缺口**
3. **按缺口派下一棒**(模板 ⇒ `多会话协同机制-定稿 §4.1`);若最靠前那步**自己就能做** ⇒ **直接自己做**(⛔ 不要为了"派活"而派活)
4. 追加记忆 → 释放锁 → 停
🔴 **怎么落地(⛔ 不靠"加更多会话")**:
- **机械推进** ⇒ 由**常驻程序**做(`keepalive.py` 通路自愈 + `thin-consumer.py` 判定并写 `VACUUM.md`)
- **需要 AI 判断** ⇒ 由**已存在的那一个心跳**(每小时)读 `VACUUM.md` 后接管;⛔ **不要再为"加密"新建检查点**
- **链条自续** ⇒ 靠 §1.5 D⑤ **收尾自判**(零额外会话)
### 9.9 🚫 自动化**配额 + 白名单确认制**(2026-09-29 用户两次点破)
**① 配额**:本线常驻自动化 **≤ 2**。
**② 🔴 白名单(2026-09-29 用户明令)**:**只有两类可不经确认直接建** ——
1. **接续会话**(把某条链/某一线的**下一棒接上**,含 §1.5 D⑤ 收尾自判)
2. **给其他会话安排任务**(派活)
⇒ **其余一切用途**(监管轮/巡检/检查点/体检/观测/清理/日报…)**必须先取得用户确认**,⛔ 不得自行创建。
**执行**:建之前自问这两问;**答不上 ⇒ 报给用户等确认**(⛔ 不许先建后报)。
✅ **删冗余不属"新建"** ⇒ 可直接做(报告里说明删了什么)。
**反面教材(2026-09-29 我犯的)**:为"定期检查"自行加 5 个密集检查点 + 心跳 + 交代轮 ⇒ 用户:「**啥都用自动任务**」。
🔴 **判据**:看见自己"用建自动化来回应需求"时 ⇒ **先走白名单;答不上就报用户**。
### 9.4 🔴 每轮开工先「探守护进程」(自愈 · 2026-09-29 整体检查补)
**每轮(心跳 / 检查点 / 收尾自判)开工第 0 步之后,先探一次守护进程在不在**:
```bash
# 单例端口被占 = keeper 在跑
python -c "import socket;s=socket.socket();
try:
s.bind(('127.0.0.1',20099)); print('KEEPER_DOWN')
except Exception: print('KEEPER_UP')"
```
- **`KEEPER_UP`** ⇒ 什么都不做(监控与通路自愈都在)。
- **`KEEPER_DOWN`** ⇒ **立刻重新起**(用**宿主后台机制**,⛔ `cmd start`/`wmic`/`Start-Process` 均被安全策略拦):
`run_in_background: true` 跑 `E:/ProgramData/AIProject/ai1net-dsh-server/.workbuddy/tools/keepalive.py`
⇒ 它自己会:① 探 `20090`、不通就调桌面线启动器拉起客户端 ② 托管 `thin-consumer.py` ③ 单例绑定 `:20099`。
🔴 **为什么必须有这一步**:keeper / 消费者若因 **WorkBuddy 重启**而消失,**没有任何东西会自己回来** ⇒ 监控与通路自愈同时静默失效。
⇒ 这一步把"守护进程的存活"也纳入了自愈链(**守护者的守护**)。