Files
dsh_ai1net_server/交付物/唤醒机制-现行工作机制与能否运行判定-20261002.md
T
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

18 KiB
Raw Blame History

唤醒机制 · 现行工作机制说明 +「能否正常运行」判定

日期:2026-10-02(07:0x 取证) 触发:用户两条指令 —— ①「把唤醒框图的线 连接到 协作程序上,然后分析 唤醒 后台任务机制是否可以正常运行」②「详细说明当前唤醒的具体工作机制」 取数方式:只读宿主机库(sqlite3 file:...?mode=ro)+ 工作区台账/日志文件。⛔ 未写库、⛔ 未拷库文件、⛔ 未起任何进程。


§0 一句话结论

唤醒机制「能准时醒、能走完流程、但送不出去」——而且送不出去的时候,它一声不响。

环节 判定 一句话
① 时钟(排期) ✅ 正常 宿主每小时真触发、真开一条新会话,连续 8 轮有记录
② 执行(会话内三步) ✅ 正常(有 1 次例外) 让位检查通过、三条判据都取到真读数、跑了一次 --tick;⚠️ 近期 8 跳里 1 跳被中断
③ 送达(--tick 投递) ❌ 结构性不达 投了,但被自己的去抖 same-item 挡掉;且不写日志、不喊用户 ⇒ 静默空转

⇒ 「是否可以正常运行」的答案是:排期与执行这两段可以,整条链路不行 —— 卡在最后一段,而且是无声地卡。


§1 现行机制 · 六个环节(每环都附一手证据)

环节 1 · 时钟 = 宿主的一条每小时排期(⛔ 不是常驻进程、⛔ 不是网关注册的定时任务)

项 实测值
排期名 [唤醒]-会话协作自检-脉冲
id 7fe0fe82…
类型 recurring / FREQ=HOURLY;INTERVAL=1 / status=ACTIVE
下次到点 automations.next_run_at = 10-02 07:10:34(⇒ 这一项读得到,见 §4 的看板假话②)
工作目录 E:/ProgramData/AIProject/ai1net-dsh-server(正斜杠形态)

复跑:sqlite3 file:E:/ProgramData/.workbuddy/workbuddy.db?mode=ro "select id,name,rrule,next_run_at,status from automations where name like '%唤醒%'"

⚠️ 同线的两条旧排期仍是 PAUSED:[协作]-唤醒机制-唤醒轮A/B(caca9a89 / 16bec5ce)⇒ 在册但不生效,⛔ 别把它们当成"还有两条钟"。

环节 2 · 触发 = 每跳开一条新会话(⛔ 不是"复用同一条")

automation_runs 逐跳有记录;sessions 里同标题会话每小时新增一条、id 各不相同:

建(开新会话) 完 会话 id
10-02 06:08:00 06:10:34 a5af050c
10-02 05:06:24 05:07:34 01d55d84
10-02 03:55:52 05:09:09 f9ad6a46
10-02 02:47:55 02:55:41 cf2f3fe5
10-02 01:34:04 01:47:23 1495f547
10-02 00:25:36 00:33:50 945bb847

⚠️ 点火时刻是漂的(01:34 / 02:47 / 03:55 / 05:06 / 06:08)—— 不是固定 :xx,迟到量 4~47 分钟。 ⇒ 所以任何"唤醒准点就会推"的假设都不成立;靠它报时不可行。

环节 3 · 会话内三步(这是"机制本体")

从最近一跳(06:08,会话 a5af050c)自己的自述逐字取:

  1. 第 0 步 · 让位检查 —— 「本工作区除本会话外没有正在执行的 [唤醒] 会话(两道判据都指向本会话)⇒ 本轮照常执行」。
  2. 取三条判据(真读数):
    • ① 除本会话外正在执行的会话 = 0;
    • ② queue.json 有待处理项 —— head=S9 / pending=1 / doing 空 / gate=free;
    • ③ goal.json.acceptance_state 仍有非 pass 项 —— 只剩 V2-主会话可响应=待重验。
  3. 跑一次 collabd.py --tick(="推一次投递轮")。

环节 4 · 投递 = 「唤醒只负责跑一次 tick,推给谁由协作程序决定」

  • 唤醒会话不直接找跟进会话;投递目标 target=follow 由协作程序判。
  • 最近一次成功投递:10-02 04:06:52 → 19e6e204([跟进] 会话),http=200,hash 512943bd519bbf1d。
  • ⚠️ 此后再无成功投递(台账 wakeups.jsonl 最后一条就是它)。

环节 5 · 三条兜底出口(推不成时写文件)

文件 什么时候写 现状
NEED-USER.md 需用户介入 mtime 10-02 05:01(停在 05:01 那一版)
READY.md 「可派未派(浪费)」 mtime 10-02 06:54,内容=派 S9
STALL.md 有会话在跑但长时间无成果 06:06:31 生成

🔴 但是:--tick 被去抖挡掉时,这三份一份都不写(下详 §3-①)。

环节 6 · 它与另外两台"钟"的分工

角色 谁在驱动 出口
唤醒(本文件) 宿主排期,每小时,开新会话 跑一次 --tick
跟进 宿主排期,每小时,开新会话(055ffdd1,next 10-02 07:34:23) 收队列上报、判"该不该派活"
钩子(补充) 宿主在 PreToolUse ^Bash$ / UserPromptSubmit 时机起短命子进程 事件驱动地补一次 --tick

⇒ 三者的唯一"推"出口都是协作程序;⛔ 唤醒不叫主会话(主会话只由用户触发)。


§2 「能否正常运行」的判定 —— 三段分开答

✅ 段一:能点火

  • automation_runs 里连续 8 跳有记录,result_success=1;会话按预期被创建。
  • ⚠️ 例外 1 次:05:06 那一跳被中断 —— 该跳的 thread_title 原文是 Automation prompt interrupted: unknown_i… ⇒ 那一小时的唤醒没跑完。 ⇒ 结论:"每小时必醒"成立,但"每小时必跑完"不成立(近期 8 跳 1 次中断)。

✅ 段二:能执行(会话内三步照跑)

06:08 那跳把三步全做完了,并且自己写出了体检:闸门在册、各闸门日志末行是 06:08、看板进程在跑。⇒ 会话内部的流程是好的。

❌ 段三:送不出去(这是"整条链路不行"的地方)

真因不是"没人投",而是投了、被自己的去抖静默挡掉。三重叠加:

① 去抖 same-item 无时限(直接原因)

  • 机制自己的状态文件 tmp/supervise-inbox/collabd-state.json 里: "wake_info": { "skipped": "same-item" }(mtime 07:01,最新一跳)。
  • 含义:队首这条内容的 hash 与上一次已投递的完全相同 ⇒ 判定"重复"、跳过。
  • 🔴 它没有时限:只要内容不变就永远不再投。实测后果 —— 队首从 04:06:52 起约 2 小时没出过件。
  • 🔴 而且它静默:生产日志 _collabd.log 的最后一行停在 05:01:23,NEED-USER.md 也停在 05:01 ⇒ 被挡掉的每一轮,日志、喊话都不写(="卡住但一声不响")。

② target-busy 判据(已登记、未修)

  • _session_status() 只回 sessions.status 小写串;"活"与"忙"是同一根字符串 working ⇒ 有活跟进会话时也会被判"忙"而延后(S9 待修)。
  • 旁证:日志里 04:06 那两行 忙判据读不到(19e6e204)⇒ 按**没在跑**处理 —— 它是靠"读不到"才绕过去投成的。

③ 常驻投递缺席(放大静默窗口)

  • 全机进程扫描:没有任何 collabd.py --supervise(只剩看板 board.py --serve 8788)。
  • ⇒ 本该由常驻投递承担的高频投递没了,唯一投递源只剩"每小时唤醒会话 + 宿主钩子"; 一旦上面 ①/② 命中,没有人补投,静默窗口就是一小时起。

④ 顺带发现:看板服务此刻也已停

  • 06:08 那跳的自述里还写着「看板进程 board.py --serve 8788 在跑」; 07:0x 实测:netstat 里 8788 无监听,tasklist 里 一个 python.exe 都没有(curl 回 HTTP 000)。
  • ⇒ 投递与看板"两个常驻"现在都不在 —— 它们起在会话里 ⇒ 会话一结束就被带走(=S8 记过的那个根因)。

附带旁证(同样指向"读数曾经过期"): · 生产 _collabd.log 尾部还留着 10-01 14:09–15:07 一串 fatal 'gbk' codec can't encode '\u26d4' —— 即"编码未声明 ⇒ GBK ⇒ 整轮 fatal"那类故障的历史痕迹。 · 弃用的 wake-pulse.sh 仍在盘上(.workbuddy/collab/)。


§3 本轮"顺带"修掉的(都是同一个病:看板在说假话)

# 位置 原来写什么 实测是什么
① board_ext.py 唤醒格 tip 「唤醒已从『排期开新会话』改成『脉冲复用同一条会话』」 反的 —— 排期每小时开一条新会话
② board_ext.py 唤醒格 tip 「『下次几点到点』⛔ 读不到 —— 脉冲是会话自己起的后台任务」 两半都错 —— 是宿主排期;next_run_at 读得到(10-02 07:10:34)
③ board_ext.py WAKEUP_KINDS 用 上报·唤醒/监督程序·心跳 当"唤醒痕迹" 两类 kind 都已退役(最后一条 09-30T10:44:43)⇒ 照它读会得出「两天没响过」的假结论;现役真读数在会话表
④ board_ext.py 唤醒格数据 死字段 "edge": "唤醒"(注释"箭头指主会话") 零消费方(board.html 已改成固定文案)⇒ "在册 ≠ 生效"的坑,已删
⑤ board_ext.py(技能侧模板) 改名替换过头留下的乱码 4 处((原来叫"唤醒")、("唤醒" not in nm) and ("唤醒" not in nm) 等) 已逐处订正
⑥ references/architecture.md 「常驻投递进程…它同时提供唤醒时钟」/「唤醒不是一个定时自动化…不引入任何周期性排期」 🔴 这两句是口径(定案),不是错的 —— 我 07:0x 一度把它们当"与现状相反"给废掉了,同日已回改(见 §7)

§7 🔴 同日自我更正:我把「口径」当「实测」废掉了(2026-10-02 07:2x)

起因:用户问「为什么唤醒会话还是定时任务呢,不应该是一个会话靠自己的后台任务定时唤醒吗」⇒ 回查口径原文,发现我上一轮的"订正"订错了。

定案口径(⛔ 一直没变,多处同款):

出处 原文
architecture.md §0 ⛔ 已废弃:「用自动任务当闹钟」 —— 2026-10-01 用户明确废弃(原话:「定时任务的方案已经废弃了」)
architecture.md §4.0/§4.1 两节整节作废 ⇒ 「时钟由常驻投递提供」
architecture.md §5-1/deploy.md §5/collabd.py 用法头 常驻投递(collabd.py --supervise)= 投递本体 + 唤醒时钟;⛔ 不用自动任务、⛔ 不靠宿主排期
architecture.md §8 「—— 它同时就是唤醒时钟」

⇒ 正确记法:口径不动;现状是偏差 ——「唤醒时钟缺位,由一条已作废的旧路代偿」。 我错在:把"现状与口径不符"读成了"口径已被推翻",于是把两处口径当实测给订正掉了。⇒ 已回改(原文保留,另加「实测偏差」行,并写明⛔ 不许据此改口径)。

现场读数(07:10 那一跳,正在跑):[唤醒] 会话 477ab6ca 建 07:10:53、status=working;台账最后一条仍停在 04:06:52;去抖仍 same-item ⇒ 每小时开一条新会话、每次都投不出去,此刻就摆在眼前。

⚠️ 另有一条同样被误会的禁区:用户问的「一个会话靠自己的后台任务定时唤醒」—— 这条路是 2026-10-01 明令禁止的(architecture.md §4.0 末:「⛔ 禁止(原「第四种」,仍然禁):把长跑服务放进会话后台任务」,理由=每轮输出唤醒宿主 ⇒ 会话永不空闲 ⇒ 用户看到"卡死",历史复现 6 次)。⇒ 它不是备选方案,⛔ 别照它照做。

🔴 订正③值得单独记一笔:它意味着看板原样会告诉用户"唤醒两天没响过",而事实是它每小时都在响 —— 又一处「在册 ≠ 生效」的镜像(这回是"在册的是旧的")。


§8 相关引用的全量清扫(2026-10-02 07:2x · 对应「修复错误概念时要排查相关引用」)

缘起:用户原话「修复错误概念的时候 要排查相关引用 确保更新完全」—— 同日的「口径 vs 实测」自我更正(§7)若不把引用一起改,下一个人读到的仍是旧概念。

做法:全量枚举 ⇒ 逐处只加标注、⛔ 不删原字(保留取证)⇒ 复核(判定窗口=该行或其后 3 行内是否带标注)。

落点 处数 说明
architecture.md 10 §3 投递/派活行、§5-1 时钟行、§4 ④时钟行、§7.3 标题、排期名前缀 + 本轮 §4.1 的标题/红字「⇒ 🔴 结论」/「旧『代价』已被 ④ 补上」段/红字「⇒ 🔴 立场」
collab-detail.md 8 :95/:235/:404/:425/:512/:513/:778/:891
collab.md / SKILL.md 3 措辞「唤醒轮排期名」⇒「自动唤醒任务的排期名」(旧措辞会被读成"唤醒本该用排期")
board_ext.py 3 死函数 _triggers_gw 的旧名「心跳」;运行期文案「在等脉冲到点」⇒「现状由排期代偿到点叫醒;⚠️ 定案是常驻投递直接叫醒」
MEMORY-全文-20261001.md 2 条 整条改写(见下)
MEMORY.md 1 补入「🔴🔴 唤醒时钟=这个常驻进程本身」

🔴 最重的一处(差一点漏掉):状态层 ⇒ 全文 的指针目标 MEMORY-全文-20261001.md:35,原文整条与定案相反 —— 「监管+投递都=钩子事件驱动」/「⛔ 不常驻(常驻天生拿不到口令)」/「两个拨钟方:① 钩子 ② 自动任务」/「⚠️ 常驻走不通」。 ⇒ 已整条改写为定案口径 + 附「2026-10-02 订正记录(三项全错)」;同文件 :34 两处同步订正。 ⇒ 教训(新):查残留 ⛔ 不能只查"正文" —— 指针目标(⇒ 全文/⇒ 细则)必须一起查,它们在读者眼里就是正文。

复核结论("确保更新完全"的证据):技能库 md 侧疑似残留 30 → 13;13 条逐条判过 = 全部是正确口径/历史引用/用户原话(如 :546/:548「常驻投递=唤醒时钟」正是定案、pitfalls.md:363「不建当闹钟的自动任务」正是修法)⇒ 无遗留。 已退役技能名(workbuddy-session-forensics/multi-session-collab):活引用零(命中全在 归档/技能-退役-20261001/、带日期接续包、归档/配置与备份/)。

回归:install.py --manifest = 35 份 / 语法失败 0;--verify = 全绿(PASS 45 / FAIL 0);两份 board_ext.py md5 一致(技能侧为源、cp 到工作区实跑份)。 改前备份:tmp/bak-wake-sweep-20261002/(4 份 md 改前原样)。

⚠️ 顺带发现(既存,非本轮引入):MEMORY.md 8039 字符(自设上限 7,650)/MEMORY-全文-20261001.md 10,453(上限 7,800)—— 两者改前即已超,建议专做一次压缩(涉及信息取舍,⛔ 不顺手做)。

§4 缺口 / 待决(⛔ 我没有擅自改)

级别 缺口 影响 建议
P1 去抖 same-item 无时限 队首一旦投出过一次、内容不变 ⇒ 永不再投(实测停摆 ≈2h) 并入 S9(同方向:投递判据);至少加时限/退避
P1 去抖跳过时不写日志、不写 NEED-USER.md 卡住但一声不响 ⇒ 只能靠人凑巧看见 静默跳过也必须留痕(已有 skipped.jsonl 那套写法可循)
P1 常驻投递缺席(--supervise 全机无进程) 投递没有主时钟 ⇒ 静默窗口一小时起 S8(载体)待决,⛔ 受"⛔ 不在会话里挂常驻后台任务"约束
P2 看板服务同样已停(8788 无监听、无 python.exe) 用户看不到看板;且它是"读数打架"的又一例(06:08 报在跑、07:0x 已无) 与 S8 同根因(起在会话里 ⇒ 会话结束被带走),一并治
P2 target-busy 判据把"活"与"忙"判成同一个值 有活跟进会话也会被判忙 S9
P2 唤醒格还没读排期表的 next_run_at 看板给不出"下次几点醒" 已登记,未实现(本轮只订正文案)
P2 同线的 唤醒轮A/B 两条 PAUSED 排期仍在册 容易被误读成"还有两条钟" 收敛清单
P3 _triggers_gw() 无调用方(历史件) 改它不会有任何效果 已加"无调用方"护栏注释

§5 我没做的(如实)

  • ⛔ 未起常驻投递、⛔ 未派新会话、⛔ 未改 S9/S8/S5 任何一件的代码(都属机制层,且本轮执行锁由本会话持有,应由下一棒在抢到锁后做)。
  • ⛔ 未删任何排期、未动线上任何文件(除本文档与 §3 列的订正处+看板技能文件)。
  • ⛔ 未对 _collabd.log 的历史 fatal 做清理(那是取证痕迹)。

§6 复跑(全部只读)

PY=E:/ProgramData/.workbuddy/binaries/python/versions/3.13.12/python.exe
# ① 排期与运行记录(⛔ 别 SELECT *:automation_runs 有大字段会淹输出)
$PY tmp/_q_wake3.py
# ② 唤醒/跟进是不是各开新会话
$PY tmp/_q_wake4.py
# ③ 唤醒最近一跳的自述(机制自己写的账)
$PY tmp/_q_wake5.py
# ④ 去抖现状
$PY -c "import json,io;print(json.load(io.open('tmp/supervise-inbox/collabd-state.json',encoding='utf-8'))['wake_info'])"
# ⑤ 生产日志尾
tail -6 .workbuddy/collab/logs/_collabd.log