247 lines
19 KiB
Markdown
247 lines
19 KiB
Markdown
# 唤醒 · 「会话空闲 ⇒ 宿主 spawn idle 钩子」坐实(2026-09-30 19:0x)
|
||||
|
|
|
|||
|
|
> 状态:**成立 ✅ 端到端坐实**(拿到全天唯一一次真触发)
|
|||
|
|
> 线:机制线 · 唤醒机制探索 | 域:`ai1net-dsh-server/` | 会话:`706d2476`(19:00 起的接续会话)
|
|||
|
|
> 上游:`接续包_唤醒机制探索_20260930.md`(本棒执行其 §1 唯一目标)
|
|||
|
|
> 🔴 本文**修正**上一棒两条结论(见 §6)——不修正会把假事实带给后续所有棒。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 0. 一句话结论
|
|||
|
|
|
|||
|
|
**成立。**「会话空闲满 60 秒 ⇒ 宿主自己去 spawn `Notification` 钩子(`idle_prompt`)」今天 **18:55:00.210 拿到全天唯一一次真触发**,判据端到端达成。
|
|||
|
|
|
|||
|
|
但"空闲"不是"没收到用户消息 60 秒",而是**两道隐形闸门同时满足**:
|
|||
|
|
|
|||
|
|
1. 会话状态机 = `idle`(**每次 `addHistory` 都重置 60 s 计时器** ⇒ 回合进行中永不计时)
|
|||
|
|
2. 该会话**没有 pending/running 的后台任务**(`hasLiveBackgroundTask()`)
|
|||
|
|
|
|||
|
|
🔴 **第 2 条把我们瞒了 6 小时 20 分**:一个 12:17:45 起的后台任务一直没退出,把 idle 钩子全程压死,且**闸门拦下是"正常返回"、宿主一个字节都不记** ⇒ 现场看起来就是"什么都没发生"。上一棒据此误判成"项目级配置对已运行会话不生效"。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. 判据与达成(本棒验收)
|
|||
|
|
|
|||
|
|
| 判据 | 要求 | 实测 | 判定 |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| 探针出现**宿主新增**行 | 非手工自测 | `tmp/_idle_hook_probe.jsonl` 第 2 行:`ts=2026-09-30 18:55:00`、`session_id=6ecf6d98-…`、`transcript_path` 指向真实会话、`pid/ppid` 真实 | ✅ |
|
|||
|
|
| 时间戳落在**真实 >60 s 空闲窗**内 | — | 该会话 `AGENT_ENDED→idle` @18:54:00,**至今未再 resume**(窗口 6 分钟以上) | ✅ |
|
|||
|
|
| 该行**不是手工写** | 排除自测 | ① 该会话 transcript **最后一条 = 18:54:00 的助手收官消息**,其后**零工具调用**(不可能手工喂 stdin)② 该行 env 里**没有** `CODEBUDDY_TOOL_CALL_ID`(17:51:51 那行手工自测**有**)⇒ 不是工具调用起的 | ✅ |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 2. 证据链(5 条独立互证,任一条单独都指同一结论)
|
|||
|
|
|
|||
|
|
| # | 证据 | 原文 / 读数 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 1 | **宿主 spawn 记录(决定性)** | `E:/ProgramData/.workbuddy/logs/2026-09-30/ai1net-dsh-server__e476dc05d23a01f725b368d606f4ff0f.log:146869`:`[2026/9/30 18:55:00.210] [HookExecutor] spawn pid=54964 shell=…bash.exe timeout=8000ms cmd="…python.exe" "…/.workbuddy/tools/idle-hook-probe.py"` —— **全天 999 条 `HookExecutor spawn` 里含本探针的只有这 1 条** |
|
|||
|
|
| 2 | **探针落行** | 第 2 行 `ts=18:55:00`,`gateway_password_present=true`、`session_id=6ecf6d98-1308-4218-8111-50a71fcb7201` |
|
|||
|
|
| 3 | **60.0 s 精确对齐** | 该会话最后一条 `[addHistory] COMPLETED` = **18:54:00.193** ⇒ 计时器装于此刻 ⇒ 到期 **18:55:00.19**,与宿主 spawn(.210)/探针落行(18:55:00)**同一秒**。源码:`resetIdleTimer` 里 `setTimeout(…, 6e4)` 收在 `addHistory` 末尾 |
|
|||
|
|
| 4 | **不是手工/不是别的会话** | 见 §1 第 3 行;且只有 hook 执行器会带着**真实 transcript_path** 与 session_id、又不带 `TOOL_CALL_ID` |
|
|||
|
|
| 5 | **真空闲窗** | `[SessionRunStateMachine]` 该会话最后迁移 = `AGENT_ENDED | from=model_done | to=idle`,此后无任何迁移 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 3. 机制全貌(源码 + 实测校正)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
addHistory(任何历史写入) ──► resetIdleTimer(session) // 每次都重装
|
|||
|
|
│
|
|||
|
|
▼ setTimeout(60 000)
|
|||
|
|
┌───────────────────────────────┐
|
|||
|
|
│ !stateMachine.isIdle(session) │──是──► 重装表,再等 60 s(⛔ 无日志)
|
|||
|
|
│ OR │
|
|||
|
|
│ hasLiveBackgroundTask() │
|
|||
|
|
└───────────────┬───────────────┘
|
|||
|
|
│ 否(两道闸门同时通过)
|
|||
|
|
▼
|
|||
|
|
sessionHookManager.executeNotificationHooks(session,
|
|||
|
|
"CodeBuddy is waiting for your input", IDLE_PROMPT)
|
|||
|
|
▼
|
|||
|
|
宿主 [HookExecutor] spawn(bash + 用户钩子命令)
|
|||
|
|
⚠️ timeout=8000ms | 钩子自带 CODEBUDDY_GATEWAY_PASSWORD
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
要点(全部实测/源码可查):
|
|||
|
|
|
|||
|
|
- **计时器装点 = 每次 `addHistory` 完成**(不只是回合结束)⇒ **回合进行中永不"空闲计时"**;这也解释了"长回合中间没有 idle 钩子"。
|
|||
|
|
- **闸门不通过 ⇒ 只是重装表**,不报错、不写日志 ⇒ **失败完全静默**(这是本次最大的坑)。
|
|||
|
|
- 钩子是**宿主子进程**:自带网关口令(探针实测 `gateway_password_present=true`)、**不占会话、0 token**。
|
|||
|
|
- **已运行会话同样生效**:本会话 12:00 起跑、钩子 17:51 才写进项目级 `.codebuddy/settings.json`,仍然生效 ⇒ **项目级钩子配置对已在跑的会话有效("热生效"成立)**。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 4. 泳道图(角色 × 阶段)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
│ ①回合进行中 ②回合结束 ③静默 60s ④闸门判定 ⑤spawn ⑥落地
|
|||
|
|
──────────────┼────────────────────────────────────────────────────────────────────────────────────────────────────
|
|||
|
|
用户 │ 发消息 ──┐ (离开/不发言) (不在场)
|
|||
|
|
│ │
|
|||
|
|
会话状态机 │ model_streaming AGENT_ENDED→idle idle 保持不变 idle ✔ — —
|
|||
|
|
│ tool_executing
|
|||
|
|
│ (每次工具/流式都 addHistory)
|
|||
|
|
宿主计时器 │ 装表→被重置 装表 @18:54:00.19 ──60s──► 到期判定 调用 HookExecutor
|
|||
|
|
(resetIdleTimer)│(永远等不到 60s) T=18:55:00.19 ┌──────────────┐
|
|||
|
|
│ │ isIdle → 真 │
|
|||
|
|
│ │ ⛔ hasLive- │◄── 6h20m 内这里恒为「真」
|
|||
|
|
│ │ Background- │ ⇒ 重装表、静默
|
|||
|
|
│ │ Task()→问题 │
|
|||
|
|
│ └──────┬───────┘
|
|||
|
|
钩子执行器 │ — — — — │ 18:55:00.210 spawn
|
|||
|
|
(HookExecutor)│ ▼
|
|||
|
|
探针脚本 │ — — — — 写 tmp/_idle_hook_probe.jsonl
|
|||
|
|
│ ts=18:55:00 ✅
|
|||
|
|
网关 │ — — — — (下一步才用:POST /api/v1/runs 投递)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**红格位置**:第 ④ 列「闸门判定」——`hasLiveBackgroundTask()` 恒为真,把后续 ⑤⑥ 全部截断。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 5. 事故链图(这次实际怎么坏 + 缺席的防线)
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
12:17:45 collabd 类后台任务(taskId=NDucGY)被起 → 【status=running】
|
|||
|
|
│
|
|||
|
|
│ ⚠️ 它一直没退出:宿主日志到 18:38:13 才 finalize(failed, elapsed=22 827 768 ms = 6h20m19s)
|
|||
|
|
▼
|
|||
|
|
17:51:30 探针钩子写进项目级 .codebuddy/settings.json(配置本身没问题)
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
17:56:15 回合结束 → 装表
|
|||
|
|
17:57:15 ◄── 到期:state=idle ✔ / hasLiveBackgroundTask=true ✘ ⇒ 重装表 ⋯⋯ 静默
|
|||
|
|
18:16:52 回合结束 → 装表
|
|||
|
|
18:17:52 ◄── 同上,被压 ⋯⋯ 静默
|
|||
|
|
18:23:22 回合结束 → 装表
|
|||
|
|
18:24:22 ◄── 同上,被压 ⋯⋯ 静默
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
18:38:13 僵尸后台任务终于 failed ⇒ 闸门 2 放开
|
|||
|
|
│
|
|||
|
|
18:54:00 该会话最后一次 addHistory → 装表
|
|||
|
|
18:55:00 ◄── 到期:idle ✔ + 无活后台任务 ✔ ⇒ ★ 宿主 spawn ⇒ 探针落行 ★
|
|||
|
|
│
|
|||
|
|
▼
|
|||
|
|
(真因被完全掩盖,因为全程 0 条日志)
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 哪几道防线缺席(关键)
|
|||
|
|
|
|||
|
|
| # | 缺席的防线 | 后果 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| ① | **"钩子被闸门拦下"无日志**:宿主只在 `executeNotificationHooks` **抛异常**时 `logger.warn`;闸门不过 = **正常重装表** ⇒ 完全静默 | 现场唯一可见物 = "什么都没发生",把"被压制"误读成"机制不生效" |
|
|||
|
|
| ② | **探针只记"来了",不记"没来"** ⇒ 探针无法自证被压制 | 探针全部命中 0 次时无法区分"没触发"与"被压制" |
|
|||
|
|
| ③ | **事后取证视角错**:只查了 git 时间线/源码/配置,**没查 `[BashTool] background task` 生命周期**(真因所在) | 得到一个自洽但**错误**的结论(且它被写成"已定死、别再重做取证") |
|
|||
|
|
| ④ | **"空闲窗"判据本身错**:上一棒用"没收到用户消息 60 秒"当空闲窗;正确判据是"状态机 idle + 无活后台任务" | 把 17:52–17:55(其实**全程在跑工具**)、18:50–18:52(到期时刻 state=`tool_executing`)都当成了"空闲窗" |
|
|||
|
|
|
|||
|
|
⇒ 教训(治本):**凡"钩子/定时器类机制应当发生却没发生",必须同时取证三件:① 该机制的 spawn/执行日志 ② 它的前置闸门状态 ③ 会压制它的"长活对象"(后台任务/队列/锁)清单**。缺任一件都不许下"机制不成立"的结论。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 6. 修正上一棒的结论(⛔ 别再把旧的带下去)
|
|||
|
|
|
|||
|
|
| 上一棒「已定死」 | 本棒实测 | 处置 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| ②「**项目级配置对已运行会话不生效**」(实测) | **判错**。配置生效正常;被 `hasLiveBackgroundTask()` 压了 6h20m。本会话 12:00 起跑、配置 17:51 才挂,仍然生效 ⇒ 项目级钩子对已跑会话**确实生效** | 撤销,改写为"闸门压制" |
|
|||
|
|
| ②附带的两个"空闲窗"(17:52→17:55 / 18:50→18:52) | **两个都不成立**:17:46:43→17:56:15 该会话连续在跑工具(无 ≥55 s 的 addHistory 空档);18:51:39 到期时刻状态 = `tool_executing` | 撤销 |
|
|||
|
|
| ①「idle 钩子至今 0 次真实触发」 | 17:51–18:54 期间**仍然**成立(0 次,因闸门);但 **18:55:00 起不成立** ⇒ 现在 = **1 次真实触发** | 更新计数 |
|
|||
|
|
| ③「钩子热生效」(据此把 ② 判成"真结论") | 结论对,**但推理没错、结论没错而事实错**:热生效成立,只是被闸门掩盖 | 保留 |
|
|||
|
|
| ④–⑫ 其余各条 | 本棒未复核,⛔ 不作废但也不再当"支撑 ②"的依据 | 保留 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. 最小可行路径(成立 ⇒ 怎么用起来)与其代价
|
|||
|
|
|
|||
|
|
**落地形态(用现成触发源,0 新会话)**
|
|||
|
|
|
|||
|
|
1. 项目级 `.codebuddy/settings.json` 已有 `Notification` + matcher `^idle_prompt$`(现挂的是探针脚本)。
|
|||
|
|
2. 把探针脚本升级为**仲裁投递器**(同一个脚本、同一处挂点):
|
|||
|
|
- 读 `CODEBUDDY_GATEWAY_PASSWORD`(实测可得)→ 发现本机网关端口 → `POST /api/v1/runs` 投一条消息给**目标会话**。
|
|||
|
|
- **投给协调会话,⛔ 绝不投给自己**(投自己会自激:干活→空闲→唤醒自己→…)。
|
|||
|
|
- 加**最小间隔节流**(如 ≥10 min)+**有活才投**(先读工作区状态,没待办就不投)。
|
|||
|
|
3. 触发链:`会话空闲满 60 s → 宿主 spawn 钩子 → 钩子投递 → 目标会话被唤醒`;投递成立已实测(会话忙时排队、空闲即交付)。
|
|||
|
|
|
|||
|
|
**代价(老实讲)**
|
|||
|
|
|
|||
|
|
| 项 | 量级 |
|
|||
|
|
|---|---|
|
|||
|
|
| 钩子侧成本 | **0 token、不占会话**(宿主子进程,timeout 8 s) |
|
|||
|
|
| 投递侧成本 | 每命中一次 = 唤醒目标会话跑一轮 ⇒ **真的烧 token**(必须靠节流+"有活才投"压住) |
|
|||
|
|
| 最坏情况 | 若投给自己/无节流 ⇒ **最坏 1440 轮/天** |
|
|||
|
|
| 已知失效模式 | **任何 pending/running 的后台任务会静默压制它**(今天实测 6h20m)⇒ 必须配自检(如让投递器记"上次成功时间",超时即告警;或借 `Stop` 钩子(**每个回合结束必触发、不受闸门压制**)做交叉校验) |
|
|||
|
|
| 装哪里 | 项目级已可用(对已跑会话也生效);要覆盖"所有工作区"须挂**全局**配置 ⇒ **属"改全局",须先问用户** |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 8. 待用户拍板(一轮一问 · 唤醒落地三选项仍未定)
|
|||
|
|
|
|||
|
|
**问题**:唤醒这条链,落地选哪一条?
|
|||
|
|
|
|||
|
|
**为什么问你**:三条路的差别不在技术优劣,而在「**要不要长期占一个常驻东西**」和「**能不能接受它自己把会话叫起来烧 token**」——这属于资源承诺与取向,不是我能替你定的。
|
|||
|
|
|
|||
|
|
**① 只保留探针(现状,不动)**
|
|||
|
|
- 优点:零风险、零成本、零维护;机制结论已经拿到,随时可升级。
|
|||
|
|
- 缺点:唤醒能力等于没有;链条仍然是靠"排自动化"这一条腿走路。
|
|||
|
|
|
|||
|
|
**② 外部定时器 → 网关 `runs`(唯一能做 5 分钟级)**
|
|||
|
|
- 优点:与钩子解耦、不依赖空闲闸门、可 5 分钟级;0 新会话。
|
|||
|
|
- 缺点:要**长期养一个常驻进程**(本项目一向慎入:独立进程**读不到宿主口令**,需要人工给凭据并处理"端口每次重启都变");多一个要运维的活物。
|
|||
|
|
|
|||
|
|
**③ idle 钩子 → 网关 `runs` 闭环**
|
|||
|
|
- 优点:**用现成触发源**(今天已端到端验证触发成立)、钩子侧 0 token 0 会话、天然"只在不忙时"触发。
|
|||
|
|
- 缺点:最坏 1440 轮/天(必须节流);**会被活的后台任务静默压制**(今天 6h20m),要先补齐自检;要覆盖全部工作区得动全局配置(须你同意)。
|
|||
|
|
|
|||
|
|
**倾向**:**③**(唯一"用现成触发源"的方案,且今天已把触发这一环坐实);落地时**必须**同时上"节流 + 有活才投 + 投给协调会话而非自己"三条护栏。若你要更稳,我建议 ③ 先只接**一条线**试跑一天,再决定要不要扩到全部工作区。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 9. 复现预测(留给下一棒的判定点)
|
|||
|
|
|
|||
|
|
本棒是**单次观测**,为把它从"1 次"变成"可复现",留一条**可falsify的预测**:
|
|||
|
|
|
|||
|
|
> 本会话(`706d2476`)**本轮 done 后**,若不再有活动且**无活的后台任务**,
|
|||
|
|
> 应在**我最后一条 `addHistory` 完成时刻 + 60 s** 出现一行
|
|||
|
|
> `session_id=706d2476-93fb-439a-9742-22e009915331` 的探针记录。
|
|||
|
|
|
|||
|
|
- 出现 ⇒ 机制**可复现**(且证明"新会话天然生效")。
|
|||
|
|
- 不出现 ⇒ 先查本会话有没有活的后台任务(`[BashTool] background task` 生命周期),再谈机制。
|
|||
|
|
|
|||
|
|
### 9.1 复现验证结果(2026-09-30 19:2x 追加 · **复现验证棒**)
|
|||
|
|
|
|||
|
|
**判定:❌ 未出现。** `tmp/_idle_hook_probe.jsonl` 至今仍是 **2 行**(`PROBE-TEST-0001`、`6ecf6d98-…`),**没有** `706d2476-…` 行。
|
|||
|
|
⇒ §9 的预测**既未被证实、也未被证伪**:预测的前提("收官后不再活动、静置 >60 s")在 `706d2476` 上**根本没发生**。
|
|||
|
|
|
|||
|
|
**第一步先排除"被压制"(prompt 要求)—— 结论:不是被压制。**
|
|||
|
|
|
|||
|
|
| 检查项 | 实测读数 | 结论 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 19:00 后 `[BashTool] background task` 四类事件(created / completed / failed / killed) | **0 条**(全文件最后一条 = 18:38:13 `NDucGY` failed,elapsed 22 827 768 ms) | ⛔ **无活的后台任务** ⇒ 不是第二道闸门压的 |
|
|||
|
|
| 全天含探针的 `[HookExecutor] spawn` | **1 条**:`18:55:00.210`(§2 证据①不变) | 19:00 后宿主**从未** spawn 过 idle 钩子 |
|
|||
|
|
| 预测时刻(= 末条 `[addHistory] COMPLETED` **19:06:25.337** + 60 s = **19:07:25**)该会话状态 | 该 addHistory 后 **0.4 s** 即 `MODEL_REQUEST_STARTED`(19:06:25.755)→ `MODEL_STREAM_STARTED`(19:06:27.976)→ 持续流式(19:06:48.075 累计 1 556 287 B),全程 `busy=true` | 第一道闸门 `!stateMachine.isIdle` **不通过** ⇒ 只重装表(静默) |
|
|||
|
|
| 该会话最终去向 | `[CliPrewarmPool] activated prewarm entry **exited unexpectedly** (id=wb-pool-1790765516875-2537cd, **pid=47188**, sessionId=706d2476-…, **code=1**, signal=none)` @ **19:09:16.570** | 🔴 **承载它的 CLI worker 猝死** ⇒ 宿主计时器随之消失 |
|
|||
|
|
|
|||
|
|
**真因(一句话)**:`706d2476` 这一棒**一路忙到进程退出**(一直在流式生成、`busy=true`),**从未出现 60 s 空闲窗**;19:09:16 承载它的 worker 又以 `code=1` 退出 ⇒ 会话此后**零活动**(其会话日志冻结在 19:09:17、工作区日志冻结在 19:06:48、主线日志最后一行就是这次退出)⇒ **没有活着的宿主计时器**,自然不会有 idle 钩子。
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
时点 │ 19:06:25.337 19:06:25.8~19:06:48 19:07:25(预测点) 19:09:16.570 19:2x(本棒)
|
|||
|
|
─────┼────────────────────────────────────────────────────────────────────────────────────────────────
|
|||
|
|
事件 │ addHistory COMPLETED ─► 请求/流式中(busy) ─► ✗ 本应 spawn 探针 ─► worker exited code=1 ─► 仍无探针行
|
|||
|
|
│ ▲计时器装点 ▲闸门①不过(忙) ▲▓▓ 空的这格=本棒的靶子 ▲计时器随进程消失
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
**顺带登记(⛔ 不属本棒判据,仅记录)**:19:09–19:11 出现**一波 3 个会话**的 `activated prewarm entry exited unexpectedly (code=1)` —— `706d2476` @19:09:16.570、`12732a10` @19:10:27.935、`ac8de40d` @19:10:59.886,三者的会话日志**都在各自退出时刻冻结**。疑似宿主侧 worker 回收/重启波;它**会连带灭掉 idle 计时器**,后续真要用 idle 钩子做唤醒,需先弄清这一波。
|
|||
|
|
|
|||
|
|
**⇒ 对链的结论**:机制**仍然成立**(§0–§3 的 18:55 端到端证据链未被动摇),但**"可复现"这一环今天没能补上** —— ⛔ 不是"机制不可复现",是**这次的样本自己死在半路**。要补这一棒,须挑一个**能正常收官并静置 >60 s** 的会话,⛔ 不要再用长回合/带后台任务的会话当靶子。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 10. 出处(按需读)
|
|||
|
|
|
|||
|
|
- 宿主 spawn 记录:`E:/ProgramData/.workbuddy/logs/2026-09-30/ai1net-dsh-server__e476dc05d23a01f725b368d606f4ff0f.log:146869`
|
|||
|
|
- 后台任务生命周期(真因):同文件 `[BashTool] background task created|failed|finalized`(`NDucGY`:12:17:45 建、18:38:13 收、elapsed 22 827 768 ms)
|
|||
|
|
- 状态机:同文件 `[SessionRunStateMachine] transition | sessionId=6ecf6d98-…`
|
|||
|
|
- 计时器装点:同文件 `[addHistory] COMPLETED`(末条 18:54:00.193)
|
|||
|
|
- 探针:`tmp/_idle_hook_probe.jsonl` | 脚本:`.workbuddy/tools/idle-hook-probe.py` | 挂点:`.codebuddy/settings.json`
|
|||
|
|
- 取证工具:`tmp/wb-phone/asar-peek.mjs`(`find` / `slice`)+ `reflow.mjs`
|
|||
|
|
- 上游:`交付物/唤醒-idle钩子破解-20260930.md`、`交付物/查唤醒为什么断-结论-20260930.md`、`接续包_唤醒机制探索_20260930.md`
|