Files
dsh_ai1net_server/交付物/唤醒-上报即唤醒与门控归属-20260930.md
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

7.6 KiB
Raw Permalink Blame History

唤醒 · 「上报给主会话」到底是不是唤醒 + 门控该归谁(2026-09-30)

起因(用户原话):「会话协作项目中有任何会话在执行时,唤醒定时任务跳过处理(应该是通过 hook),无任何协作队列无任务,且无任何会话执行时,检查目标状态(完成:同时暂停,阻碍:反馈给协作程序 同时暂停,未完成:反馈给协作程序),这样等队列信息上报给主会话时 是不是就唤醒了」 判据:文中每条都标了源码位置(~/.workbuddy/skills/multi-session-collab/scripts/collabd.py)。


0. 结论(三行)

  1. 是 —— 但前提是主会话此刻活着。因为在这套机制里,「上报」不是写文件,是投递;投递落地 ⇒ 主会话多跑一轮 ⇒ 这就是唤醒。
  2. 主会话已退出 ⇒ 投不出去 ⇒ 不会唤醒。那一格只能由唤醒轮(自动任务起新会话)覆盖。
  3. 你这条规则里,"有会话在执行就跳过""无队列才查目标""目标三态判定"大半已经是现成实现(协作程序 supervise() / _deliver_str);真正缺的是两格:「完成/阻碍 ⇒ 自动暂停」 与 「有队列但无会话执行 ⇒ 派棒」。

1. 把「上报」拆成三段 —— 只有第二段会唤醒

# 段 具体动作 会不会唤醒谁
① 内容 写 tasks.json(队列本体)、TO_MAIN.md(投影)、blocked.json、NEED-USER.md ❌ 一个人都叫不起来(纯落盘)
② 投递 钩子 → POST /api/v1/sessions/<主会话>/reply {text}(collabd.py:1058) ✅ 这才是唤醒:主会话多跑一轮
③ 起会话 自动任务(唤醒轮) ✅ 主会话不在时的唯一通道

判据:supervise() 先写 TO_MAIN.md(collabd.py:1770),紧接着才 _deliver_str(txt, "上报·单条", st)(collabd.py:1777)。 ⇒ 只做了 ① 没做 ②,等于没上报。 你问的"上报时是不是就唤醒了",答案取决于走没走 ②。


2. 你的表述 vs 现有实现(逐格对照)

你的表述 现有实现(位置) 状态
有会话在执行 ⇒ 跳过 _session_status(目标)=="working" ⇒ target-busy 延后(collabd.py:1050) ✅ 已有
队列无任务 tasks.json 四态 pending/running/done/blocked,唯一权威(collabd.py:852) ✅ 已有
无任何会话执行 宿主库 sessions.status='working'(_main_state collabd.py:1616;reconcile collabd.py:1644) ✅ 已有
检查目标状态 goals_open():台账非 done ∪ 任务图非 done ∪ goal.json.acceptance_state 任一非 pass(collabd.py:1403,三路取并集) ✅ 判据已有
完成 ⇒ 同时暂停 A、B 现有只有「任务图全 done ⇒ skipped=all-done 不再投递」(collabd.py:754)——它⛔不会去暂停自动任务 🔴 缺
阻碍 ⇒ 反馈协作程序 + 暂停 task_report(state="blocked", reason=…)/need_user()(collabd.py:878/728) ⚠️ 接口有;⛔ 见 §3-②
未完成 ⇒ 反馈协作程序 goals_open()==True ⇒ 写差距;现有只在"有活可派/僵住"时才报(collabd.py:786-798) ⚠️ 部分
有队列任务 且 无会话执行 —— 🔴 你的规则没定义这一格 —— 而这正是最该动的那一格(有活没人干)

3. 落地必须先知道的三个硬约束(源码级)

  1. reply 只认 live ⇒ 主会话退出后投不出去;程序此时拒绝盲投(不投给任意会话),只按工作区解析,解析不出就 need_user("找不到主会话…")(collabd.py:1038-1049)。 ⇒ "上报即唤醒"对已退出的主会话结构性不成立,且程序的处置是喊人,不是自己想办法。
  2. 队列只有「投递方」才配改(mutate,collabd.py:1690-1696):--tick(宿主钩子)是唯一推进方;--once/常驻只做投影。⛔ 唤醒轮不许手改 tasks.json,要用 task_report 口径上报,否则会重演「把待反馈项消费掉却不投递」的静默丢件。
  3. "跳过"是零 token 的:投递前的否决(same-item 内容哈希去重 / too-soon 最小间隔 300s / target-busy)都在钩子进程内完成,不碰会话、不烧 token(collabd.py:960-967)。⚠️ 但钩子拦不住自动任务起会话——automation 无条件触发,所以唤醒轮"起来后发现有人在跑就立刻退"仍靠域锁。

4. 完整闭环:两半合起来才闭合

主会话此刻 谁把它叫起来 延迟 成本
活着 · 空闲 钩子投递(reply) 秒级~分钟 到投递前零 token
活着 · 执行中 不打扰(target-busy 延后,等它空闲) 等它空 —
已退出(worker 已回收) 唤醒轮(自动任务起新会话) ≤30 分钟 一个新会话

⇒ 所以「等队列信息上报给主会话时就醒了」——对"活着"那行成立,对"已退出"那行不成立;后者靠唤醒轮。

⚠️ 代价(源码里写着的一句话,必须知道):collabd.py:857-860 注释——

「每次投递都会唤起主会话跑一轮 ⇒ 用户发消息撞 busy ⇒ 体感"卡"」 ⇒ "上报即唤醒"=会占用主会话 ⇒ 必须节流。现有的四道节流:单条+握手(一次只反馈一条,等它执行完才发下一条)/内容哈希去重/最小间隔 300s/真停滞门槛 15 分钟(HEARTBEAT_MIN_IDLE,有进展一条都不发)。⛔ 落地时不许把这四道拆掉。


5. 落地:要补的两格(其余照抄现成)

唤醒轮起来 → ① 抢域锁(抢不到 = 有人在推进 ⇒ 立即结束,零成本跳过)
           → ② 读队列 tmp/supervise-inbox/tasks.json
           → ③ 读会话:宿主库 sessions.status='working'(cwd=本工作区,排除自己)
           → ④ 读目标:tasks.json 非 done ∪ taskgraph.json 非 done ∪ goal.json.acceptance_state 任一非 pass
格 条件 动作
A 有队列任务(pending/running)且 无会话执行 派一棒(起一个会话去干)← 🔴 你原规则缺的这格
B 无队列 且 无会话执行 · 目标未完成 把差距写进 tmp/supervise-inbox/(⛔ 不手改 tasks.json)
C 无队列 且 无会话执行 · 目标有阻碍 写清"要用户做什么" + A、B 两条排期一起置 PAUSED
D 无队列 且 无会话执行 · 目标已完成 A、B 两条排期一起置 PAUSED ← 🔴 现成实现没有这一格
E 判不准 按 B 处理(宁可空转一轮,⛔ 不许造活)

A/B 排期 id(自我暂停时用;⛔ 只改 status,不动 rrule):

  • 唤醒轮 A caca9a89-fa82-48e1-a55c-7e0f3a06bd48 | 唤醒轮 B 16bec5ce-98c0-470c-afa9-6f5a06218068

6. 一句话速记

上报(写文件)≠ 唤醒;投递(钩子把文字推进活着的会话)才=唤醒。 主会话活着 ⇒ 秒级唤醒(但要节流,否则把它顶"卡");主会话退出 ⇒ 钩子也没了,只剩唤醒轮起新会话(≤30 分钟)。 判据一句:"有会话在执行就跳过"= sessions.status=='working' 或 域锁被占。


附:图

见同目录 唤醒-上报即唤醒与门控归属-20260930-图.html(① 三段拆解图:标出哪一段才唤醒;② 门控矩阵图:标红两格缺失)。