Files
admin c1b5e4d966 chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次)
- .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…),
  目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪
- .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/)
- .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*)
- .gitignore 补:备份件(*.bak-*)
- 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
2026-10-10 23:13:22 +08:00

336 lines
25 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 协同监管棒 · 作业规程(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 重启**而消失,**没有任何东西会自己回来** ⇒ 监控与通路自愈同时静默失效。
⇒ 这一步把"守护进程的存活"也纳入了自愈链(**守护者的守护**)。