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

111 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 速查清单 · 常见坑一句话版
> 📌 **来路**:原嵌在 `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 是否跟着"会话收尾"推进** —— 比读代码可靠得多(本节即靠这一条定位的)。