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

11 KiB
Raw Permalink Blame History

接续包 · 唤醒机制探索(2026-09-30 18:55 立)

🔴 状态块(2026-09-30 19:5x 加 · 由接续棒 a202550c 回填): §1 第 3 棒(worker 退出后能否被外部叫起)已作答 ⇒ 判定:🔴 不能(叫醒旧会话)/能(无人值守地新起一个会话)。 定稿 ⇒ 交付物/唤醒-无人值守可行性-20260930.md(判定+泳道图+事故链图)+ 同名 -图.html;冲突以定稿为准。 三条硬结论(一句话各一):① 网关口长在 worker 进程里 ⇒ worker 退出端口就消失;② POST /api/v1/runs 不选会话(id 只当消息 id,路由先取宿主自己的 primarySession)⇒ 对别的活网关投递只会落到投递方自己的会话;③ 宿主不自愈(activated 条目意外退出只写 warn),唯一有效的复活动因在桌面端 pipe 上 ⇒ 外部接不上。 🔴 连带影响:§3 的"三选项"要重读 —— 方案 ③(idle 钩子→runs)不具备无人值守所需稳定性(worker 典型寿命仅 30 s–6 min,实测),已降级为可选兜底;主干改为 A 自动化派棒。 ⛔ §2 #3c 要更新:worker 自行退出不是偶发,是常态(三天计数 40 / 55 / 28)。 ⚠️ 唯一能改判定的未知量:code=1 静默退出是"回合结束被主动回收"还是"崩溃"(未做,留下一棒)。

工作线:机制线 · 唤醒机制探索 上一棒:会话 6ecf6d98(标题 [主控]-[机制线]-接续:查「唤醒」为什么断) ✅ 上一棒已完成:一次性自动化 8d046fb3-be7e-410c-8ae6-239113e780a9(19:00 起,会话 706d2476)   ⇒ 结论:idle 钩子"成立",全天唯一一次真触发 18:55:00.210;并修正了本包 §2 #2 的旧结论。产出 交付物/唤醒-idle钩子坐实-20260930.md。 🔴 下一棒已登记:一次性自动化 b68e2b24-0964-400c-b7d8-be097211d23d   名称:主控 · 唤醒机制线 · 棒:worker 退出后能否被外部叫起(无人值守决定性一问)|排期:2026-09-30 19:33|cwd:E:/ProgramData/AIProject/ai1net-dsh-server   (id 取自工具返回值,⛔ 手写 id 一律无效) 本包位置:E:/ProgramData/AIProject/ai1net-dsh-server/接续包_唤醒机制探索_20260930.md


⚠️ 状态块(2026-09-30 19:1x 加 · 由接续棒 706d2476 回填)

本包 §1 目标已达成 ✅ —— 结论:idle 钩子「成立」,已端到端坐实(18:55:00.210 宿主真实 spawn)。 定稿 ⇒ 交付物/唤醒-idle钩子坐实-20260930.md(含泳道图+事故链图)。冲突以定稿为准。

⛔ 本包 §2 有两行已被推翻,别再沿用:

§2 条目 处置
#1「idle 钩子至今 0 次真实触发」 更新:17:51–18:54 期间仍成立;18:55:00 起 = 1 次真实触发
#2「项目级配置对已运行会话不生效」 ⛔ 判错,撤销。真因=hasLiveBackgroundTask() 被一个 12:17:45 起、18:38:13 才死的后台任务压了 6h20m(闸门不过只重装表、零日志)。项目级钩子对已跑会话确实生效(本会话 12:00 起跑、钩子 17:51 才挂,仍触发成功)
#2 附带的两个"空闲窗"(17:52→17:55 / 18:50→18:52) ⛔ 都不成立:前者该会话全程在跑工具;后者到期时刻状态=tool_executing

🔑 "空闲"的正确判据(⛔ 不是"没收到用户消息 60 s"):状态机 idle + 该会话无 pending/running 后台任务,且计时器每次 addHistory 都重置(回合进行中永不计时)。

🔴 #2 的这条错如果没被拦下,会让后续棒去改全局配置(一个既非必要、又属"改全局"的动作)—— 这正是本状态块存在的意义。

🔴 下一棒已换:一次性自动化 98fb060b-81e2-4daf-ba1f-d0e522246e80(主控 · 唤醒机制线 · 复现验证棒,排期 2026-09-30 19:15,cwds 正斜杠)。 其唯一目标=验证 §9 那条可复现预测(session_id=706d2476 的探针行是否在"+60 秒"出现)。§3 的"唤醒落地三选项"仍待用户拍板。

§1 本包唯一目标的演进(两棒已了,第三棒在跑)

✅ 第 2 棒(已完成,19:00):idle 钩子成立

全天唯一一次宿主真触发在 18:55:00.210(宿主日志 [HookExecutor] spawn,可复核)。两道隐形闸门: ① 状态机必须 idle(每次 addHistory 都重置 60 s 计时器)② 该会话无 pending/running 后台任务(hasLiveBackgroundTask())。 闸门不过 ⇒ 只重装表、零日志 —— 这就是它之前"看起来从没工作过"的真因(被一个 12:17 起的僵尸后台任务压了 6h20m)。 判据只认端到端:探针 tmp/_idle_hook_probe.jsonl 出现宿主新增行(⛔ 手工自测那行不算),且落在真实 >60 s 空闲窗内。

🔴 第 3 棒(已登记,19:33):worker 退出后能否被外部叫起(无人值守决定性一问)

  • 要答:worker 退出(今天实测到 activated prewarm entry exited unexpectedly (code=1) 一波 3 个)后 —— 网关口还在不在?POST /api/v1/runs 是排队、报错、还是真把它拉起来跑一轮?若拉不起来,是否只剩"每次唤醒都新起会话"?
  • 为什么决定性:idle 钩子路线的前提是"会话活着且空闲";外部定时器→runs 路线若拉不活,则"无人值守"的成本前提被推翻。

§2 已经定死的结论(⛔ 别再重做取证)

# 结论 级别
1 ✅ idle 钩子成立(已坐实,含唯一一次真触发 18:55:00.210)—— "至今 0 次真实触发" 已作废 实测(第 2 棒)
2 🔴 项目级配置对已运行会话不生效 判错,已推翻:配置生效正常,是被两道隐形闸门压的(状态机非 idle/有活的后台任务)。真因=一个 12:17 起的僵尸后台任务压了 6h20m 实测(第 2 棒修正)
3 钩子热生效(改完 settings.json 不重启宿主,下一次调用就生效) 实测
3b idle 钩子的两道闸门:① 状态机 = idle(每次 addHistory 重置 60 s)② 无 pending/running 后台任务;不过闸 ⇒ 只重装表、零日志 源码 + 实测
3c ⚠️ 宿主 worker 会自行退出:19:09–19:11 一波 3 个会话 activated prewarm entry exited unexpectedly (code=1) ⇒ 计时器随之消失 实测(第 2 棒附带)
3d 取证四件套(判"机制为何不触发"必须齐):[addHistory] COMPLETED|[SessionRunStateMachine] transition|[BashTool] background task …|[HookExecutor] spawn,再加会话进程存活;缺一件都⛔ 不许下"机制不成立" 实测
4 5 分钟级自动化做不到(源码级:parseRRule 的 FREQ 是硬白名单 HOURLY/DAILY/WEEKLY/MONTHLY/YEARLY) 源码级
5 网关 scheduled-tasks 在桌面端是死能力(宿主硬编码 CODEBUDDY_DISABLE_CRON=1) 源码级
6 POST /api/v1/runs 投递成立:会话忙时排队、空闲即交付 ⇒ 外部程序可以叫醒会话,不需人切窗口 实测(17:49 投、17:55 真到)
7 POST /sessions/{id}/reply 只认 live;非 live ⇒ parkInQueue(4.5 h 无反应) 实测判负
8 /jobs/{id}/reply 写 inbox,worker 从不 drain 实测判负
9 stop→reply(pending)→respawn:pending/respawn/unshift 都成,worker 卡 resuming… 实测判负
10 唤醒 =「任务完成」事件,与 stdout 无关;后台任务静默安全、300 s 不被回收 实测
11 ⛔ 常驻循环 + 周期 echo 当不了脉冲(永不完成 ⇒ 永不唤醒) 实测
12 交接唯一触发条件 = 「登记为 main 的那条在不在活会话集合里」;在 ⇒ 钉死,不在 ⇒ 换 实测

§3 未决 / 待用户拍板

  1. 🔴 唤醒落地三选项(上一棒已问,用户未答):
    • ① 只留探针(上一棒的倾向)
    • ② 外部定时器 → 网关 runs(唯一能 5 分钟且 0 新会话,需单独评审)
    • ③ idle 钩子 → runs 自己(闭环但最坏 1440 轮/天,且要先解决"装哪里")
  2. idle 探针装哪里:项目级不生效 ⇒ 候选是改挂全局 E:\ProgramData\.workbuddy\settings.json 的 Notification。 ⚠️ 属"改全局配置",动手前必须先问用户(本棒边界已写死)。
  3. resolve_main 的前缀判据缺陷 A/B(机制层,须独占锁、单独一棒):
    • A|前缀判据不认方括号(代码 startswith("主控") 而实际标题常是 [主控]-…)
    • B|「登记还活着」短路压过显式前缀(正确优先级应为 显式前缀 > 登记 > 最近活动)
  4. stop-collab.py::_gw_port() 会把 20090(设备接入垫片)误认成网关(真网关 56975)。

§4 当前状态与命令

  • 协作机制现指向休眠中的主会话 67dfd365 ⇒ 投递会「拒投(loud)」。⛔ 别动它、别改它标题。 本棒新会话标题以 主控 开头 ⇒ 它一跑起来 resolve_main() 会自动切到它(走 prefix:主控)。 ⚠️ 一次性自动化起的会话跑完即 completed:它作为 main 只在运行期间有效;要长期接管须在桌面上打开它。
  • 四条闸门已全部补回且当天有真实调用(收口 / 技能 / 限流 / 锁)。state.py 的 [闸门] 段一行看全。
  • 开工三件套:
    python E:\ProgramData\AIProject\ai1net-dsh-server\state.py
    bash "D:/github/dsh_shenxian/dsh-server-docs/07-scripts/handoff-guard.sh" --claim-exec "<会话名>"
    bash "D:/github/dsh_shenxian/dsh-server-docs/07-scripts/handoff-guard.sh" --release-exec "<会话名>"
    

§5 出处(按需读,别整读)

  • 交付物/查唤醒为什么断-结论-20260930.md | 交付物/唤醒的解决方式-官方文档核对与方案分析-20260930.md(§11="5 分钟做不到"的源码依据)
  • 交付物/唤醒-本机网关直连测试-20260930.md | 交付物/唤醒-会话自建后台任务方案评估-20260930.md
  • 交付物/唤醒-idle钩子破解-20260930.md | 交付物/唤醒交接-机制能否跟着换主会话-20260930.md | 交付物/补回三个闸门-20260930.md
  • 历史全文:.workbuddy/memory/2026-09-30.md(同日多棒都在里面,按小节标题找)|自动化记忆:.workbuddy/memory/automations/fb113c35-2cbe-45f0-afb3-4dbf0b1b4ea6/memory.md
  • 探针脚本:.workbuddy/tools/idle-hook-probe.py|探针数据:tmp/_idle_hook_probe.jsonl|项目级配置:.codebuddy/settings.json