- 变更规模:新增 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/ 知识文件,按口径入库)
11 KiB
唤醒 · 本机 gateway 直连测试(纯本机 · 无代理 · 无垫片)
任务(用户原话):「先用 gateway 那条线测试,但是不用走代理什么的 都在本机环境处理即可,也就是把唤醒做成程序调用本机 workbuddy gateway,就用当前会话测试」 附带口径(用户补充):「会话自己创建的后台任务是可以触发给自己发消息的……后台任务监控程序安装,装好后会话继续处理,这条线是可以的」 日期 2026-09-30 12:5x | 执行者:接续-唤醒方案分析-20260930
§0 三句话结论
- 这条线通了:程序 →
127.0.0.1:59486(本机 WorkBuddy gateway)→POST /api/v1/sessions/6ecf6d98…/reply⇒ HTTP 200{"data":{"delivered":true}},⛔ 未经过覆盖网络 443、⛔ 未经过垫片 20090、⛔ 未经过任何代理。 - 但「投递成功」≠「立刻唤醒」:目标当时
writerOccupied=True(本轮正在跑)⇒ 消息入队、等空闲边界才被消费。这是本次唯一新口径。 - 用户补充的那条线是对的,而且它与本测试互补:会话后台任务能继承网关口令(它跑在 WorkBuddy 进程树内)⇒ 它是「零新会话 + 能每 5 分钟 + 拿得到凭据」的唯一载体。⚠️ 代价见 §5。
§1 交付物:wake-session.py
路径:$WS/.workbuddy/collab/wake-session.py(零第三方依赖,只用标准库)
python wake-session.py --list # 列出本机所有网关及其 live 会话
python wake-session.py --session current --dry-run # 只做发现+前置判定,不投递
python wake-session.py --session current --text "…" # 真投递(默认目标=当前会话)
python wake-session.py --port 59486 --session current --text "…" # 应急:跳过发现
| 设计点 | 落地 |
|---|---|
| 凭据 | 只从环境变量 CODEBUDDY_GATEWAY_PASSWORD 读;⛔ 命令行明文、⛔ 落盘、⛔ 回显(T3) |
| 端口 | 每次现查;fail-closed:查不到 ⇒ 具名错误码 no-live-match,⛔ 绝不沿用上次端口 |
| 目标闸门 | 只投给 live 且 live.sessionId == 目标 的会话 ⇒ 否则 rc=2 拒绝(T2) |
| 超时 | 读 ≤5 s、写 ≤10 s(T5);单次投递、不重试(T4) |
| 副作用 | 本程序不监听任何端口;⛔ 不改配置 / 插件 / 令牌 / 进程(T3/T7) |
| 退出码 | 0 成功 | 1 参数错 | 2 前置不满足 | 3 发现失败 | 4 投递失败 |
§2 读数(2026-09-30 12:49–12:56)
§2.1 「服务本会话的那个网关」怎么定 —— 三判据 + 一条匹配
--list 实测:
| 网关 | pid | live 会话 | writerOccupied | 备注 |
|---|---|---|---|---|
127.0.0.1:55283 |
56072 | 11a263a2… |
True | 另一个会话的宿主 |
127.0.0.1:56975 |
50716 | fe146dd9… |
True | 另一个会话的宿主 |
127.0.0.1:59486 |
52460 | 6ecf6d98… |
True | ← 本会话所在 |
三判据(全部不带凭据):
① GET / 含 CodeBuddy Gateway / CodeBuddy Remote Control;
② GET /api/v1/health ⇒ 401 AUTH_REQUIRED;
③ 能应答 /api/v1/sessions/live。
再按 live.sessionId == 目标 精确匹配 ⇒ 唯一命中才动手(多命中 ⇒ rc=3 拒绝)。
🔴 本次踩到并修掉的坑(值得记住):判指纹必须不带凭据。
带 x-access-token 时 /api/v1/health 会从 401 变 200 ⇒ 判据全线落空(首版就因此全灭)。
⚠️ 而这一条恰好也是「真网关 vs 垫片 20090」的唯一分水岭:垫片会把根页原样转出去(标记同样命中),但它自己不做鉴权 ⇒ health=200 ⇒ 被正确排除。
§2.2 投递读数
| 项 | 值 |
|---|---|
| 目标 | 6ecf6d98-1308-4218-8111-50a71fcb7201(本会话) |
| 时刻 | 12:55:11 |
| 网关应答 | HTTP 200 {"data":{"delivered":true}} |
sessions.updated_at |
12:49:20 → 12:55:31(投递后被推进) |
sessions.unread |
0(live 会话本就不计未读) |
| 转录落库 | ⛔ 尚未:projects/…/6ecf6d98….jsonl 里没有对应的 user 消息(user-like=0) |
§2.3 证据分级(⛔ 不把"ack"说成"闭环")
| 级别 | 内容 |
|---|---|
| 硬(已取得) | 网关自认 delivered:true + 会话行 updated_at 在投递后被推进 20 s |
| 待闭环 | 那条注入消息作为一条用户消息出现 —— 目标当时正忙,会排在空闲边界;它自己现身即闭环。⛔ 若始终不出现 ⇒ 说明 reply 对 busy 会话只入队不落地,需另找触发点(这是本测试留下的唯一未决项) |
§3 链路图(本次实测)
┌──────────────────────── 全程本机回环,⛔ 无 443 / 无垫片 / 无代理 ────────────────────────┐
│ │
│ wake-session.py │
│ │ ① netstat -ano → 回环监听口 │
│ │ ② 逐口三判据指纹(不带凭据)→ 命中 3 个真网关,排除垫片 20090 │
│ │ ③ GET /api/v1/sessions/live(带 x-access-token)→ 取 live.sessionId │
│ │ ④ 精确匹配目标 6ecf6d98 ←─ **本会话** │
│ ▼ │
│ 127.0.0.1:59486 WorkBuddy gateway ──► POST /api/v1/sessions/6ecf6d98…/reply │
│ │ │ │
│ │ └──► 200 {"delivered":true} │
│ ▼ │
│ sessions 行 updated_at 被推进(12:49:20 → 12:55:31) │
│ │ │
│ ▼ │
│ ⚠️ writerOccupied=True ⇒ **入队**,等**空闲边界**被消费 ⇒ 本轮结束后作为一条用户消息现身 │
└──────────────────────────────────────────────────────────────────────────────────────────┘
§4 与「会话后台任务」那条线的关系(用户补充口径)
用户说对了,机制层面完全成立,且与本次测试互补:
| 问题 | 答案 |
|---|---|
| 会话自己起的后台任务能给自己发消息吗? | 能 —— 它的输出作为事件回流到宿主会话 ⇒ 就是「监控安装、装完会话继续处理」的那个现象 |
| 那它为什么被列进禁令(T1)? | 因为非静默的输出会反复唤醒宿主 ⇒ 会话永不空闲;本轮又取到一条硬证据(见下) |
| 它对「5 分钟唤醒」意味着什么? | 🔑 它是本机唯一同时满足「零新会话 + 能拿口令 + 能任意周期」的载体 —— 会话后台任务跑在 WorkBuddy 进程树内 ⇒ 自动继承 CODEBUDDY_GATEWAY_PASSWORD;而独立进程(计划任务)拿不到口令,⛔ 不能用网关派活 |
§4.1 🔴 本轮新取到的一条硬证据(与本会话直接相关)
| 读数 | 值 |
|---|---|
logs/2026-09-30/sdk/conversations/6ecf6d98-….log |
10,485,723 B ≈ 10 MiB + 1 KB |
| 该文件 mtime | 12:26(此后不再增长) |
⇒ 本会话的诊断日志已经顶到 ~10 MiB 那个阈值,与既有结论一致(超限 ⇒ 宿主 diagnostic-log 丢弃 ⇒ 界面不再显示、看着像卡)。
⇒ 因此:会话后台任务当唤醒源,必须「完全静默」(stdout 全重定向到文件),否则就是把这个阈值当加速器在踩。
§5 「5 分钟唤醒」的结论因此要改(相较 2026-09-30 上午的判定)
| 档 | 载体 | 粒度 | 新会话 | 凭据 | 判定 |
|---|---|---|---|---|---|
| A | 1 小时自动化(FREQ=HOURLY;INTERVAL=1) |
1 h | 24/天 | 有 | ✅ 现成 |
| B | 本机 gateway 直连(本次成果)+ 一个完全静默的周期进程 | 5 分钟可做 | 0 | 需要进程在 WorkBuddy 进程树内 | ✅ 可达 5 分钟、零新会话;载体=会话后台任务(静默循环)或任何能继承口令的常驻进程 |
| C | 外部定时器 → 覆盖网络 443 → 垫片 20090 | 5 分钟 | 0 | 不需要本机口令 | ✅ 可行,但绕远(本机测试已证明不需要走那条) |
🔴 与 T1 的冲突必须明说:T1 写的是「⛔ 垫片/桥不得放进会话后台任务」。
它的本意是「别让输出回流把宿主拖死」。B 档若走「会话后台任务 + 完全静默 + 只调 reply」,满足本意、违反字面 ⇒ 要采纳必须先由用户明确覆盖 T1,或把 T1 的措辞改成「非静默的长跑不得放进会话后台任务」。
⛔ 本棒未擅自建任何常驻、⛔ 未创建任何自动化。
§6 边界与残留
- ⛔ 未走覆盖网络 443、⛔ 未动垫片 20090、⛔ 未动看板 8788、⛔ 未动中继客户端。
- ⛔ 未改 WorkBuddy 配置 / 插件 / 令牌;⛔ 未 kill/restart 任何 WorkBuddy 进程(T3/T7 逐条自查通过)。
- ⛔ 口令未落盘、未回显;本文件与脚本内无任何凭据字面。
- ⛔ 未创建自动化、⛔ 未建常驻进程(均需用户拍板)。
- 本棒临时取证件(
tmp/_wk_probe.py、tmp/_wk_verify.py)已逐个删除,tmp/无残留。 - 域锁:
接续-唤醒方案分析-20260930(ai1net-dsh-server/),收尾释放。
§7 索引
| 件 | 路径 |
|---|---|
| 投递器 | $WS/.workbuddy/collab/wake-session.py |
| 本文件 | $WS/交付物/唤醒-本机网关直连测试-20260930.md |
| 上一棒(方案分析 + §11 五分钟判定) | $WS/交付物/唤醒的解决方式-官方文档核对与方案分析-20260930.md |
| 架构约束(T1–T7 / V7 验收) | $WS/交付物/手机App经覆盖网络操作WorkBuddy-架构定稿v3-20260929.md §0.5 |