- 变更规模:新增 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.5 KiB
9.5 KiB
唤醒机制 · 角色与情况全表(2026-09-30 20:3x)
线:机制线 · 唤醒机制 | 域:
ai1net-dsh-server/上位:~/.workbuddy/skills/multi-session-collab/references/architecture.md(五主体唯一权威)|本文件是它在「唤醒」这一块的展开 兄弟件:交付物/唤醒-双排期实现方式与状态动作表-20260930.md(配方+状态表)|交付物/唤醒-无人值守可行性-20260930.md(为什么叫不醒旧会话)
0. 结论:唤醒轮不是新角色,是「主会话」的定时、不可接续实例
架构里只有 5 个主体。唤醒轮不增加第 6 个主体 —— 它扮演的就是「主会话」:
- 与用户那个主会话职责完全相同(判断 + 派活);
- 唯一区别:它不可接续(用户回不到它;它跑完即死)。
🔴 一条分界线(本文件最重要的一句):
派活(写排期、开会话)只属于「会话」 —— 也就是主会话和唤醒轮。 协作程序(
collabd)与投递:⛔ 永不派活、永不开会话(architecture §1 硬边界)。 ⇒ 把唤醒轮误当成"协作程序的一部分"就会得出"它不许派活"的错误结论 —— 它是会话,可以派活。
1. 角色卡(谁是谁)
| 角色 | 是不是会话 | 只做什么 | ⛔ 不做什么 |
|---|---|---|---|
| 用户 | — | 看一个看板;拍边界外的板(授权/放行/花钱/对外承诺) | ⛔ 不管过程、⛔ 不必催进度 |
| 主会话(可接续) | ✅ 是,用户对接的那个 | 判断 + 派活 + 接口令(启停唤醒轮)+ 向用户报告 | ⛔ 不做机械判定;⛔ 不搬砖(除非最靠前那步自己就能做) |
| 唤醒轮(A/B 两条定时排期起的) | ✅ 是,临时且不可接续 | 抢锁 → 按【状态表】只做 ①接棒 / ②报告并停 / ③退出 / ④按③ | ⛔ 不造活、⛔ 不巡检体检、⛔ 不启自己、⛔ 不接管别人的锁、⛔ 不拍边界外的板 |
| 协作会话(每棒 worker) | ✅ 是 | 一棒一线、一次一件;做完即上报 | ⛔ 不跨线;⛔ 不夹带;⛔ 不常驻 |
协作程序(collabd) |
❌ 否,程序 | 台账/判定/告警/看板/单例 | 🔴 ⛔ 不派活(不写排期、不开会话) |
| 投递 | ❌ 否,程序/钩子 | 逐条读队列 ⇒ 有变化就告诉主会话;机械判定 | ⛔ 不开会话、⛔ 不派活、⛔ 口令不落盘 |
| 宿主(WorkBuddy 本体) | ❌ 地基 | 提供四样:状态/调度(唯一能开新会话的通道)/事件(钩子)/互斥(域锁) | ⛔ 不是"主体",⛔ 不参与判断 |
1.1 🔴 「可接续 / 不可接续」决定了能动多大的手
| 主会话(可接续) | 唤醒轮(不可接续) | |
|---|---|---|
| 能否被用户中途插话 | ✅ 能(用户就在里面) | ❌ 不能(用户不知道它存在) |
| 允许做的判断 | 全部,含无客观优劣的偏好 | 只允许"机械可判"的:有客观可判的优劣 ⇒ 自决;没有 ⇒ 必须走 ② |
| 典型可自决 | 选型、路径、命名、调参、部署、排查方法 | ①接棒(下一步已定死)/③退出 |
| 典型必须停下 | —— | 要不要改方向、要不要花钱、要不要对外承诺、要用户凭据 |
| 产出去向 | 直接回给用户 | 写台账/看板 + 一条报告(用户下次回主会话才看到) |
⇒ 判据一句话:这个判断有客观可判的优劣吗? 有 ⇒ 唤醒轮自己拍;没有 ⇒ ② 停下、报告。
2. 【核心】完整情况表(情形 → 各角色各干什么)
A. 目标生命周期层(🔴 用户 09-30 定:唤醒轮从属于目标)
| 情形 | 主会话(可接续) | 唤醒轮(A/B) | 协作程序 / 投递 |
|---|---|---|---|
| A1 下达「执行 XXX 目标」 | 接口令:定目标 + 启动唤醒轮(A 即刻启用 + 排 +30 分钟启 B) | 尚未醒 | 记台账 |
| A2 目标在途·有缺口 | 判断缺口、派关键那棒 | 每 30 分钟醒一次 ⇒ 抢锁 → ①写一行排期接棒 | 投递把变化告诉主会话 |
| A3 目标在途·暂时无缺口(等外部/等数据) | 说明在等什么 | ③ 一句话退出(⛔ 不造活) | 保持台账 |
| A4 卡在需要用户 | 把"要你做什么"报告到用户面前 | ② 不派棒+报告+把 A/B 一起暂停 | 落 NEED-USER.md |
| A5 目标完成(验收全过) | 收口:宣布完成,暂停 A/B | 若它先发现 ⇒ ③ 收口 + 暂停 A/B | 台账置已完成 |
| A6 目标作废/换目标 | 换 goal.json,删旧目标的两条排期,按新目标重开一对 |
—— | 台账清旧目标 |
| A7 用户放行/继续 | 重新下「执行 XXX 目标」口令 ⇒ 重新启用 + 校准相位 | 保持 PAUSED 直到被启用(⛔ 不许自启) | 台账恢复 |
| A8 用户另开新目标(旧目标还在途) | 🔴 先处理旧目标(收口或显式挂起)⇒ 再开新的;⛔ 不许两对唤醒轮同时跑同一项目 | —— | 台账两条并行(须显式) |
B. 唤醒轮运行时层(抢锁前后)
| 情形 | 主会话 | 唤醒轮 | 备注 |
|---|---|---|---|
| B1 抢到锁 + ①有缺口 | —— | 写一行排期(新棒 id 只从工具返回值取)⇒ 释放锁 ⇒ 回一句 | 一次只派一棒 |
| B2 抢到锁 + ②卡在用户 | 用户回话时直接接手 | ⛔ 不派棒;写清"要你做什么";A、B 一起 PAUSED;释放锁 | 派了=空转链条 |
| B3 抢到锁 + ③无缺口 | —— | 一句话结束;确认无在途目标 ⇒ A、B 一起 PAUSED | 空转是正常出口,不丢人 |
| B4 抢到锁 + ④判不准 | —— | 按 ③ 处理 | 宁可空转,⛔ 不许造活 |
| B5 抢不到锁 | —— | 立即结束(有人正在推进=天然去抖) | ⛔ 不等待/不接管/不删别人的锁(R9) |
| B6 上一棒的产物没验收/棒死掉了 | 验收并判缺口 | 若"验收这一步"已定死判据 ⇒ 可直接派复验棒(属①);否则 ⇒ ②/③ | 判据看"下一步是否已定死" |
| B7 两条撞在同一分钟 | —— | 一条抢到、另一条 B5 退出 | 相位漂移的表现,按 §3 校准 |
C. 机制健康层
| 情形 | 主会话 | 唤醒轮 | 怎么办 |
|---|---|---|---|
| C1 相位漂移(两条不再差 ≈30 分钟) | 重做启用(全停 → A 即刻 → B 隔 30 分钟) | 无感 | 查 automation_update mode=list 的 nextRunAt |
| C2 宿主重启 | 复查两条状态 | 排期表由宿主持久化,重启后仍按 next_run_at 跑 |
⚠️ 已知 004f6bc2 的 next_run_at 曾停在过去 ⇒ 重启后必查一次 |
| C3 排期被误删 | 按 §配方重建一对 | —— | ⚠️ 删除是软删:status 仍是 ACTIVE、只有 deleted_at 有值 ⇒ 判"还在不在跑"看 deleted_at |
| C4 钩子不 spawn | 查宿主日志 [HookExecutor] spawn |
不受影响(唤醒轮走排期,不走钩子) | —— |
| C5 唤醒轮自己起不来(会话创建失败) | 查 automation_runs 有无 ACCEPTED 行 |
—— | 排期本身还在,下个整点半再试 |
| C6 真·全员静止(没人在) | —— | 这正是唤醒轮存在的意义:它自己就是一个新会话,不依赖任何"活着的会话" | 这就是唯一能破静默的东西 |
D. 异常与红线层(⛔ 一律先停手)
| 情形 | 主会话 | 唤醒轮 |
|---|---|---|
| D1 锁持有者疑似已死/卡住 | 报告用户,处置权只属用户 | ⛔ 绝对禁止删锁/接管(R9)=唯一合规是停手+报告 |
| D2 发现别人正在改的文件 | 归属不明 ⇒ 只报告、不动手 | 同上(R7-边界) |
| D3 需要用户凭据/审批 | 向用户要 | ② 停下报告(⛔ 不许自己找) |
| D4 需要重启宿主/改全局配置 | 先问用户 | ⛔ 硬禁止,直接 ② |
| D5 发现是对外动作(发布/承诺) | 当轮问用户 | ⛔ 禁止(上一轮同意不算数) |
3. 口径(启停 · 相位 · 锁)
| 项 | 口径 |
|---|---|
| 启动 | A 即刻 ACTIVE + 排一条 +30 分钟的一次性排期去启用 B(用完即废)⇒ 两条相位差 ≈30 分钟 |
| 停止 | A、B 一起 PAUSED(唤醒轮判到 ②/③ 自己停;完成/作废由收口会话停) |
| 重启 | 只有「执行 XXX 目标」口令能启;⛔ 唤醒轮不许自启 |
| 相位 | = 建立/启用那一刻;PAUSED 时为空;⛔ 分钟写不进规则(BYMINUTE 被忽略) |
| 互斥 | 两条抢同一把域锁(--domains <项目>/);⛔ 抢不到就退,⛔ 不接管 |
| 粒度 | 30 分钟(宿主只认 HOURLY/DAILY/WEEKLY/MONTHLY/YEARLY) |
4. 一句速记
用户拍边界外的板|主会话(含唤醒轮这个实例)判断+派活|协作会话干活+上报|协作程序管台账|投递管通知 —— 唤醒轮只是"被定时叫起来的主会话",跑完就死、不许自启、不许造活。
5. 遗留
- 🔴
multi-session-collab/references/architecture.md§4 仍写「⛔ 不引入任何周期排期」(旧定案)⇒ 与本文件冲突,待更正。§1 五主体表也宜加一句"唤醒轮=主会话的定时实例"。 - 其他项目尚未复制配方(用户说的是"后续每个项目")⇒ 照 §配方 三步抄。