Files
workbuddy_skills/session-mechanism/references/99-速查清单.md
T
admin 19101acd65 init: workbuddy_skills 重建,仅收录 session-mechanism
- 按用户指示清空原有 25 技能内容,只提交 session-mechanism(57 文件)
- 附 .gitignore(产物 + 本机凭据)
- 令牌明文已脱敏(历史 .neodata_token 与 pitfalls 引用均不入库)
- 本提交为孤儿提交(父提交为空),历史自此重新开始
2026-10-05 14:13:24 +08:00

9.6 KiB
Raw Blame History

速查清单 · 常见坑一句话版

📌 来路:原嵌在 pitfalls.md 的 P0-2 条里(占那条 79% 的篇幅 ⇒ 把一个条目撑成 11.6 KB)。 2026-10-04 拆出:⛔ 内容逐字保留(一字未改),只是搬家。 什么时候用:已知坑名、想快速确认「这个形状是不是老坑」⇒ 先扫这份; 要根因与实证 ⇒ 去 pitfalls.md 查对应编号。 📌 注意:这��条只给「现象 / 根因 / 修法」三行,⛔ 不含证据; 别拿它当结论 —— 当年 P0-2 里的旧结论就因为"只有弱相关性"被作废过。

P0 ⛔ 子进程不加 CREATE_NO_WINDOW ⇒ 桌面反复闪黑窗(用户:"一会弹出来一会弹出来的,影响我操作电脑")

  • 现象:守护/常驻程序跑起来后,桌面每隔 10~30 秒闪一个控制台窗口。
  • 根因:程序里有 subprocess.run(["netstat", "-ano"], stdout=PIPE, …)(认网关端口用)—— netstat 是控制台程序,不带 creationflags=0x08000000 就会新建一个控制台窗口;而该函数每轮都被调(常驻程序 ~10 s/投递 ~30 s)⇒ 桌面反复闪。
  • 修法:✅ 所有 subprocess 调用一律带 creationflags=0x08000000(CREATE_NO_WINDOW)。 ⛔ 只重定向 stdout/stderr 是没用的 —— 窗口照样会建。
  • 验收:桌面从"反复闪"变为"零窗口";功能侧用"能否照常认出网关端口"核对(日志/wakeups.jsonl 仍有记录)。
  • 🔑 推广:任何长期循环里的外部命令调用,先过一遍"它会不会开窗"。

本档给现象 / 根因 / 修法。架构层判据 ⇒ references/architecture.md;原技能存档 ⇒ references/collab-detail.md §6。

P1 ⛔ 用「会话后台任务」跑常驻 ⇒ 宿主"卡死"

  • 现象:用户说"卡住了/发消息不恢复";会话永不回 idle。
  • 根因:会话后台任务每轮输出都会唤醒宿主会话。
  • 修法:🔴 首选=根本不要常驻 —— 由宿主钩子按需唤起一次性进程(见 P0-3)。 ⛔ 旧建议"用 run_in_background 起常驻"是错的:那正是 P0-2(任务记在该会话名下 ⇒ 该会话卡输出)。 真需要常驻时,只能会话之外起(启动文件夹/独立窗口),并接受它拿不到口令 ⇒ 只能落盘、不能投递。
  • ⚠️ cmd start / wmic process call create / PowerShell Start-Process 常被安全策略拦 ⇒ ⛔ 别在"独立起进程"上耗时间。

P2 ⛔ 自愈没有去抖 ⇒ 反复杀掉正在服务的好实例("自愈比故障更伤")

  • 现象:监控到的端口反复通/断;日志里"launching → 又被杀"循环。
  • 根因:启动器常有幂等闸("进程活着但端口不通 ⇒ 杀掉旧的再拉一份");若守护进程每次探测失败就触发,就变成抖动,把可能正在服务的好实例打死。
  • 修法:连续 N 次(≥3)失败才动手 + 冷却(数百秒) + 探测用socket 连一下(⛔ 别发真请求)。

P3 ⛔ 粗粒度域锁 ⇒ 自造串行瓶颈,整轮白开

  • 现象:别的会话抢锁失败 ⇒ 什么都不做就退出(纯浪费的会话)。
  • 根因:把整个工作区声明成一个域 ⇒ 所有写操作串行。
  • 修法:按节点涉及的文件/子目录声明域;不重叠即可并行。机制层才独占。

P4 ⛔ fail-open 掩盖字段名错误 ⇒ 视图静默为空

  • 现象:rc=0、日志无异常,但某个区块一直是空的。
  • 根因:异常被 except: pass 吞掉;查询写错列名(真实例:给 sessions 查了不存在的 name 列)。
  • 修法:① 必须核对输出非空(⛔ 不能只看退出码)② 关键查询先 pragma table_info(<表>) 核对列名 ③ 定期 diff 视图一眼。

P5 ⛔ 把"接续任务"当成果 ⇒ 被"空转链条"骗

  • 现象:看起来一直在推进("下一棒已派"),实际总工期不动。
  • 根因:排期 ≠ 成果。
  • 修法:证据分级(真成果/接续任务/刚开跑/哑火);"在跑的棒 N 个"是排期数,⛔ 不是成果数。

P6 ⛔ 用"加自动化"回应一切需求 ⇒ 会话洪泛

  • 现象:一个需求挂上 7 个自动化,其中 5 个同用途。
  • 修法:白名单+确认制(只有"接续会话/派活"可免确认)+ 配额 ≤2。建前自问:非得开新会话吗?已有的能不能覆盖?

P7 ⚠️ 一次性自动化跑完 status 仍为 ACTIVE ⇒ 统计虚高

  • 现象:数"在挂的棒"= 6,实际只有 2 个真在等。
  • 修法:一律用 next_run_at > now 过滤;⛔ 不看 status 单独判断。清理僵尸旧件(已跑完的 once)。

P8 ⛔ 诊断数据不落盘/不落库 ⇒ 只能靠"自述"

  • 根因:把"谁干完了、结论是什么"寄托在文件扫描/人报告上。
  • 修法:读宿主已落的运行记录(automation_runs.thread_title 等)⇒ 0 token、不轮询。
  • ⚠️ 但要核对该列是否真有内容(IN_PROGRESS 时标题可能为空 ⇒ 判"在跑"看 status)。

P9 ⛔ 校验"可用"时只看"能跑起来"

  • 现象:结论写"八项判据起停各一遍全绿",但端口此刻并不通。
  • 判据:"能跑起来" ≠ "可用"。可用 = 现在这一刻服务可达,且能被维持住。

P10 ⚠️ 长前台命令被沙箱杀,连带杀掉先前后台起的进程

  • 现象:命令无输出、Exit -1;随后发现后台进程也没了。
  • 修法:单条前台命令控制在 ~90 秒内;长活拆短步或走异步。

P12 ⛔ 反复重启常驻程序 ⇒ 把主会话自己弄卡(最容易被忽视的一条)

  • 现象:每次进入"改常驻程序"的阶段,主会话就变卡、被反复打断(用户原话:"为什么每次一改到这里就把自己的会话弄卡")。
  • 根因(两条叠加 + 一条次因):
    1. 🔴 用会话后台任务起常驻 ⇒ 该进程成为本会话的附带物;每次 kill / launch 都产生一条 failed 任务通知 ⇒ 每次都打断会话。实测:一个阶段里重启 7~8 次 ⇒ 7~8 次打断。
    2. 🔴 同一会话里做了 500+ 次工具调用 + 反复读写长文件 ⇒ 上下文极大 ⇒ 每轮推理显著变慢。
    3. ⚠️ 注入钩子每轮往上下文加 ~1KB(应压在几百字符)。
  • 修法:
    1. 攒批重启:代码改动攒到一次再重启(≈3 处以上/或等功能自测全过)。⛔ 不要"改一行重启一次"。
    2. 优先热加载:把规则/配置/任务图/队列做成程序每轮读文件 ⇒ 改这些根本不用重启。
    3. 长任务换会话:一个会话不要既"建系统"又"跑长验收" ⇒ 到阈值就交棒接续(这正是本机制存在的意义)。
    4. 注入瘦身:additionalContext 压到几百字符。
    5. 🔴 改成"拉取模型"(最根治):程序只写队列/文件,⛔ 不调用会话、不通知、不起后台任务;会话在"用户发话 / 棒收尾 / 需要时"三个时机主动拉队首 ⇒ 没有"推"就没有打断。详见 references/collab-detail.md §1.3。

🔑 一句话:"改代码 → 重启常驻 → 产生失败通知 → 打断自己"这个循环,是主会话变卡的机制性原因,而不是外部故障。 ⇒ "拉"取代"推",是这个问题的根治解。

  • 现象:SyntaxError: unterminated string literal。
  • 根因:在双引号字符串里写了 ASCII 双引号。
  • 修法:文案里的引号一律用 「」;改完 ast.parse 校验(比 py_compile 报错更清楚)。

P13 ⛔ 常驻"活不长" ∧ 钩子指向无唤醒码的旧副本 ⇒ 机制静默停摆(最阴的一条:没人会发现)

  • 现象:唤醒回路代码写完、也实测到 1 次真投递,但此后再也不投。查下去:常驻进程已消失、单例端口 Connection refused、日志停在某一刻;而"唯一会自动跑"的钩子那条路,跑的是另一份旧的精简副本(没有队列闸门、没有唤醒码)⇒ 整个机械层静默停摆,且没有任何告警——因为告警也是那个程序发的。
  • 根因:① 从会话里起的常驻会随其宿主会话结束被回收(实测:13:09 起的 pid,13:12 之后再无一轮);② 同目录另存过一份旧副本且钩子指向它 ⇒ "代码在 A、钩子在 B" ⇒ 接了线等于没接;③ 认口取"uptime 最大"的口,而那个口可能没有活会话 ⇒ 有活会话也照样落 no-live-session 跳过。
  • 修法:
    1. 🔴 "能自动跑起来"的路只有一条 = 钩子(每个会话收尾跑一轮、零 token、不占会话)⇒ 把机制的关键环节挂在这条路上,⛔ 别押在"常驻一直活着"上。
    2. 钩子必须指向最新那份(含队列/唤醒);同目录⛔ 不要留旧副本,或让旧副本显式转调新版(fail-open + 静默 + 超时,⛔ 不改自己原有行为)。
    3. 认口=「第一个带活会话的口」,⛔ 不是 uptime 最大者(实测两者常不同)—— 同 cwd 多实例时,这条正是投得出去 / 投不出去的分水岭。
    4. 判"接线成立"看产物:每轮覆写的视图/队列/状态文件 mtime 是否跟着"会话收尾"推进 —— 比读代码可靠得多(本节即靠这一条定位的)。