151 lines
9.2 KiB
Markdown
151 lines
9.2 KiB
Markdown
# 唤醒 · 双排期实现方式 + 状态→动作表(2026-09-30 20:2x)
|
||||
|
|
|
|||
|
|
> 线:机制线 · 唤醒机制 | 域:`ai1net-dsh-server/`
|
|||
|
|
> 上游:`交付物/唤醒-无人值守可行性-20260930.md`(判定「叫醒旧会话无路」)
|
|||
|
|
> 配图:`交付物/唤醒-双排期实现方式与状态动作表-20260930-图.html`
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 0. 一句话
|
|||
|
|
|
|||
|
|
**唤醒 = 到点由宿主起一个「新会话」,它第 0 步跑状态、抢域锁,然后按【状态表】决定干什么。**
|
|||
|
|
每个项目挂 **2 条每小时排期、相位错开 30 分钟** ⇒ 实际每 30 分钟有一次唤醒;**互斥靠同一条域锁**(抢不到就退),所以两条不会重复干活。
|
|||
|
|
🔴 **这对排期不是常驻的** —— 它**从属于「目标」**:下口令启动,目标完成或有阻碍时一起暂停(§4)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 四条硬事实(本机实测,⛔ 别重做)
|
|||
|
|
|
|||
|
|
| # | 事实 | 证据 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 1 | **相位 = 建立/启用那一刻** | `20:03:42` 建 ⇒ 下次 `21:03:42`;改 `rrule` 后 `20:04:03` ⇒ 下次 `21:04:03` |
|
|||
|
|
| 2 | **只改提示词不重算相位** | 改完提示词后 `nextRunAt` 与改前**逐毫秒相同**(`…458318`) |
|
|||
|
|
| 3 | **暂停时相位被清空** | `PAUSED` 的行 `next_run_at` = NULL(对照 `1eaf45c3`)⇒ 重新启用时**又会按"启用那一刻"重算** ⇒ **两条必须错开启用 30 分钟** |
|
|||
|
|
| 4 | **分钟写不死**:`BYMINUTE` 被接受但**被忽略**;`BYHOUR` **列表**被直接拒绝("must be an integer") | 建 `FREQ=HOURLY;INTERVAL=1;BYMINUTE=30` ⇒ 仍按建立时刻触发 |
|
|||
|
|
|
|||
|
|
⇒ **"错开半小时"只能靠"两条相隔 30 分钟落地"得到,写不进规则里。**
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 落地配方
|
|||
|
|
|
|||
|
|
### 2.1 建立(一次性,每个项目建一次)
|
|||
|
|
|
|||
|
|
| 步 | 动作 | 备注 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 1 | 建**唤醒轮 A、B**:`FREQ=HOURLY;INTERVAL=1`,`cwds` = 该项目(**逐字同形**:正斜杠),`status` 先给 **PAUSED** | 两条的提示词里写死**同一把域锁**+状态表(见 §5) |
|
|||
|
|
| 2 | 把两条的 **id 写进彼此的提示词**(自我暂停要用) | 本项目 id 见下表 |
|
|||
|
|
|
|||
|
|
**本项目已建立**:
|
|||
|
|
|
|||
|
|
| 角色 | automation id | 当前 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 唤醒轮 A | `caca9a89-fa82-48e1-a55c-7e0f3a06bd48` | **PAUSED**(已建好,待口令启用) |
|
|||
|
|
| 唤醒轮 B | `16bec5ce-98c0-470c-afa9-6f5a06218068` | **PAUSED**(同上) |
|
|||
|
|
|
|||
|
|
### 2.2 🔴 启动(每次下达「执行 XXX 目标」时,三件事一起做)
|
|||
|
|
|
|||
|
|
| 步 | 动作 | 为什么 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 1 | 把 **A 置 `ACTIVE`** | 它的相位 = 此刻 |
|
|||
|
|
| 2 | 排**一条一次性排期**(+30 分钟)去把 **B 置 `ACTIVE`** | 这样 B 的相位 = A+30 分钟;**这就是"错开半小时"的唯一手段** |
|
|||
|
|
| 3 | 用 `mode=list` **核对**两条 `nextRunAt` 相差 ≈30 分钟 | 不对 ⇒ 重复第 1、2 步(先暂停 A 再启用) |
|
|||
|
|
|
|||
|
|
⚠️ 那条 +30 分钟的启动棒是**一次性、用完即废**,⛔ 不要长期留着。
|
|||
|
|
|
|||
|
|
### 2.3 停止(目标完成 或 有阻碍)
|
|||
|
|
|
|||
|
|
把 **A、B 一起置 `PAUSED`**。两种触发都成立:
|
|||
|
|
- **AI 自动**:唤醒轮自己判到"② 卡在用户"或"③ 目标已收口" ⇒ 它自己把两条暂停(§3);
|
|||
|
|
- **人/主会话**:目标验收全过或决定作废 ⇒ 由收口的那个会话暂停。
|
|||
|
|
|
|||
|
|
⛔ **唤醒轮不许把自己从 PAUSED 启回来** —— 只有「执行 XXX 目标」这道口令能启。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 🔴【核心】状态 → 动作表
|
|||
|
|
|
|||
|
|
唤醒轮抢到锁之后,**只认这四种状态**;判不准一律按 ③ 处理。
|
|||
|
|
|
|||
|
|
| # | 状态 | 判据(怎么认) | 该干什么 | ⛔ 不许 |
|
|||
|
|
|---|---|---|---|---|
|
|||
|
|
| **①** | **有缺口** | 链断了/有**明确且已定死**的下一步(不是"应该再研究研究") | 写**一行**排期把下一棒接上(新棒 id **只从工具返回值取**)⇒ 回一句结论、结束 | 不许一次派多棒;不许派"再调研一下" |
|
|||
|
|
| **②** | **卡在需要用户** | 缺凭据/缺真机/缺审批/有 `NEED-USER.md` 或 blocked 项 | ⛔ **不派棒**(派了=空转链条);把"要用户做什么"写成**可执行一句话**(要哪台机器、要哪句授权)报出来;**然后把 A、B 一起置 `PAUSED`**,结束 | 不许"受阻就硬派别的棒" |
|
|||
|
|
| **③** | **无缺口/目标已收口** | 队列空/没有客观可判的下一步 | 一句话说明"无缺口",结束。**若确认"当前没有任何在途目标" ⇒ 把 A、B 一起置 `PAUSED`** | ⛔ 不造活;⛔ 不做巡检/体检/日报 |
|
|||
|
|
| **④** | **判不准** | —— | 按 ③ 处理(宁可空转一轮) | 不许"先干点什么看看" |
|
|||
|
|
|
|||
|
|
**另外两条前置状态(抢锁之前就决定):**
|
|||
|
|
|
|||
|
|
| 状态 | 判据 | 动作 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| **锁被占** | 抢域锁失败 | **立即结束**(有人正在推进)⛔ 不等待、⛔ 不接管、⛔ 不删别人的锁(R9) |
|
|||
|
|
| **相位漂移** | 两条 `nextRunAt` 不再相差 ≈30 分钟,或停在过去 | 按 §2.2 重做启用;⚠️ 已见过 `004f6bc2` 的 `next_run_at` 停在 09-28 23:19 ⇒ **漂移真会发生** |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 目标生命周期 × 唤醒轮(🔴 2026-09-30 20:2x 用户定:「由执行 XXX 目标的口令同时启动,完成或有阻碍时同时暂停」)
|
|||
|
|
|
|||
|
|
| 目标处于 | 唤醒轮 A/B | 谁执行 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| **下达「执行 XXX 目标」** | 一起**启动**(A 即刻 + 排一条 +30 分钟启 B ⇒ 相位错开 30 分钟) | 接口令的会话 |
|
|||
|
|
| **在途(有缺口)** | 保持 ACTIVE;每 30 分钟一次唤醒,按 ① 接棒 | 唤醒轮自己 |
|
|||
|
|
| **有阻碍(卡在用户)** | **一起暂停** + 报告"需要用户做什么" | **唤醒轮自己**(不必等人) |
|
|||
|
|
| **完成(验收全过)/作废** | **一起暂停**(作废则 `delete` 两条) | 收口会话 |
|
|||
|
|
| **用户放行/继续** | 重新下"执行 XXX 目标"口令 ⇒ 重新启用并校准相位 | 接口令的会话 |
|
|||
|
|
|
|||
|
|
⇒ **净效果**:只有"目标真的在途"时才烧唤醒轮;收口或受阻即刻停 ⇒ 空转轮总量可控(§6)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 唤醒轮提示词(模板,已写进 A/B 两条)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
你是本工作区(<WS>)的唤醒轮 <A|B>。本轮只做一件事,做完即停。
|
|||
|
|
🔴 唤醒 = 起一个「新会话」(⛔ 不是叫醒旧会话 —— 旧会话的网关口随进程消失)
|
|||
|
|
🔴 本排期从属于「目标」:只有"正在执行某个目标"期间才该 ACTIVE;完成或有阻碍 ⇒ 一起停
|
|||
|
|
|
|||
|
|
第 0 步(必做,先跑再说话)
|
|||
|
|
1. 跑状态:<PY> <WS>/state.py
|
|||
|
|
2. 抢域锁:handoff-guard.sh --claim-exec "唤醒轮<A|B>" --domains <项目>/
|
|||
|
|
抢不到 ⇒ 立刻结束(天然去抖)。⛔ 不等待、⛔ 不接管、⛔ 不删别人的锁
|
|||
|
|
|
|||
|
|
抢到锁之后:按【状态表】动作
|
|||
|
|
①有缺口→写一行排期接棒(id 只取返回值) ②卡在用户→⛔不派棒,只报告,然后把 A/B 一起置 PAUSED
|
|||
|
|
③无缺口/已收口→⛔不造活,一句话结束;确认无在途目标则把 A/B 一起置 PAUSED ④判不准→按③
|
|||
|
|
|
|||
|
|
本对排期 id(自我暂停用;⛔ 只改 status,不动 rrule):A=<id_a> B=<id_b>
|
|||
|
|
重启规则:只有「执行 XXX 目标」口令能启用,⛔ 自己不许把自己启回来
|
|||
|
|
|
|||
|
|
硬约束:⛔ 不重启宿主/服务|⛔ 不改全局 settings.json|⛔ 不起常驻长跑任务
|
|||
|
|
|⛔ 不 kill 任何会话|⛔ 不投递消息给用户其它会话|收尾必须 --release-exec
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 代价(如实登记,⛔ 不粉饰)
|
|||
|
|
|
|||
|
|
| 项 | 数 |
|
|||
|
|
|---|---|
|
|||
|
|
| **在途期间**频率 | 每项目 **2 次/小时** ⇒ 48 次/天 |
|
|||
|
|
| **收口/受阻后** | **0 次**(一起暂停)⇒ 这是本方案相对"常驻排期"的关键优势 |
|
|||
|
|
| 每次唤醒成本 | 一轮完整会话(哪怕③空转出口也要"跑状态+抢锁+回一句") |
|
|||
|
|
| 粒度下限 | **30 分钟**(宿主只认 HOURLY/DAILY/WEEKLY/MONTHLY/YEARLY,5 分钟级做不到) |
|
|||
|
|
| 与旧文档的冲突 | `~/.workbuddy/skills/multi-session-collab/references/architecture.md` §4 现写着「**⛔ 不引入任何周期排期**」(依据用户 09-30 原话「又给我整到自动任务去了」)。**本方案是用户 09-30 20:02 后的新指令,取代那一条** ⇒ 该文件 §4 需更正,⛔ 不改则文档与实现打架 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 校准与撤销
|
|||
|
|
|
|||
|
|
- **查相位**:`automation_update mode=list` 读两条 `nextRunAt`(应相差 ≈30 分钟;PAUSED 时为空,属正常)。
|
|||
|
|
- **校准**:按 §2.2 重做启用(先全暂停,再 A 即刻、B 隔 30 分钟);或对某一条 `delete` + `create` 重建。
|
|||
|
|
- **撤销**:`mode=delete` 删两条 ⇒ 回到"只有收尾自判"的旧形态。⛔ 删锁/接管仍禁止(R9)。
|
|||
|
|
⚠️ **删除是软删**:行仍留在 `automations` 表里、`status` 仍是 `ACTIVE`,只是写了 `deleted_at`(调度器按它排除)⇒ **判断"是否还在跑"要看 `deleted_at IS NULL`,⛔ 别只看 `status`**。
|
|||
|
|
- ⚠️ **别用 SQL 直接改 `automations` 表**(宿主持有;一律走 automation_update)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 出处
|
|||
|
|
|
|||
|
|
- 判定上游:`交付物/唤醒-无人值守可行性-20260930.md`(§3 源码判据 / §6 worker 存活时长 / §7 替代路径)
|
|||
|
|
- 宿主表(只读):`E:/ProgramData/.workbuddy/workbuddy.db` → `automations`(`next_run_at`/`status`)/`automation_runs`(实际触发时刻)
|
|||
|
|
- 技能:`~/.workbuddy/skills/multi-session-collab/`(§4 节奏章待更正)
|