- 变更规模:新增 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/ 知识文件,按口径入库)
9.2 KiB
9.2 KiB
唤醒 · 双排期实现方式 + 状态→动作表(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 节奏章待更正)