- 变更规模:新增 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/ 知识文件,按口径入库)
10 KiB
「上下文到量 ⇒ 开接续会话」机制 · 为什么没运行 + 强化
时间:2026-09-30 18:27–18:45(本机)|会话:
6ecf6d98用户原话:「那个上下文到达一定量 就开接续会话的机制 没运行,强化一下」 产出:本文件 + 改settings.json(补钩子)+ 改state.py(加闸门自检)
0. 一句话结论
机制一行代码都没坏 —— 是它的「触发源」被人整段删掉了。
stop-dialog-guard.py(唯一负责「到量就提醒收口」的钩子)挂在 UserPromptSubmit 事件上;
2026-09-26 21:17 那次改 settings.json 把整个 hooks 段清空了,之后三天只补回了两个别的钩子,
它再也没被注册回去 ⇒ 从 09-26 19:19 起静默失效 4 天,直到今天你发现。
已修:钩子已补回 + 实测注入正确;并给 state.py(开工第 0 步)加了 【闸门】自检,让它不可能再静默失效。
1. 根因(全部为实物证据,非推断)
| # | 证据 | 读数 |
|---|---|---|
| 1 | 备份文件 settings.json.bak-decision-20260927-233116 |
mtime = 2026-09-26 21:17,hooks 段 = 空 ⇒ 那一刻被整段清掉 |
| 2 | 钩子日志 .workbuddy/stop-dialog-guard.log |
最后一条 = 2026-09-26 19:19:29(09-26 21:17 之后再无任何记录) |
| 3 | 对照工作区 ai1net-dsh-desktop 同名日志 |
最后一条 = 2026-09-26 17:01:10(同一时段一起停) |
| 4 | 本工作区日志事件分布 | UserPromptSubmit × 115 / Stop × 0 ⇒ 这个钩子修好后要挂 UserPromptSubmit,Stop 在本机从未被调用过 |
| 5 | 另外三个闸门的日志 | skill-load-guard.log 停在 09-26 19:19|bash-guard.log 停在 09-26 19:22|lock-hook.log 停在 09-28 10:47 ⇒ 四个闸门一起停 |
| 6 | 水位档位文件 .workbuddy/.budget-alert-level |
仍是 b303ef70…\t2(09-26 那次报的第二级)⇒ 之后没人再写过 |
结论:不是脚本坏了、不是水位算错了 —— 只是没挂上去。
2. 为什么整整 4 天没人发现(三道自检全瞎)
| 自检 | 本该发现 | 为什么没发现 |
|---|---|---|
guard 自带的 path_health()(钩子路径体检) |
钩子指向的文件/配置异常 | 🔴 它读配置用的是 WORKBUDDY_CONFIG_DIR / ~/.workbuddy,本机真实配置根是 CODEBUDDY_CONFIG_DIR = E:\ProgramData\.workbuddy ⇒ 读的是不存在的文件 ⇒ 异常被吞 ⇒ 恒返回空、永远静默 |
state.py 开机快照 |
—— | ❌ 根本没有"钩子注册"这一节(它只管锁 / git / 入口 / 收口) |
| 「日志里有行数」 | —— | ⚠️ 没人在意;且它静默之后连行都不写了,越静默越像"没事" |
⇒ 这是典型的 fail-silent:机制死了,但所有会说话的东西一起死了。
3. 已落地的修复与强化
3.1 修(把触发源接回去)
E:/ProgramData/.workbuddy/settings.json 的 hooks.UserPromptSubmit 补回一条:
{ "hooks": [ { "type": "command", "timeout": 10,
"command": "\"…python.exe\" \"D:/github/dsh_shenxian/dsh-server-docs/07-scripts/stop-dialog-guard.py\"" } ] }
- ⛔ 未加
-E(guard 的 docstring 明写:-E会屏蔽PYTHONUTF8⇒ 含中文的载荷解码即炸,09-15 实测让它"看起来从没被调用"一整天)。 - 已备份原文件:
settings.json.bak-restoreGuard-20260930-183244。 - 模式闸刀
.workbuddy/stop-guard-mode=inject本来就在(✅ 无需改)。 - 急停闸刀
.workbuddy/stop-guard.disabled不存在(✅ 没被误关)。
3.2 强化(让它不可能再静默失效)
state.py 新增 §5.5 【闸门】自检(开工第 0 步就会跑,1 次调用):
[闸门] ✅ 关键闸门在册 | PreToolUse×2 SessionEnd×2 SessionStart×1 UserPromptSubmit×3
- 关键闸门清单(当前只有一条):
stop-dialog-guard.py必须挂在UserPromptSubmit—— 缺失就显红并打印「该机制现在不会运行」。 - 顺带做 路径自检:把
settings.json里每个钩子指向的.py逐个exists—— 补掉了 guard 那个读错目录的洞。 - 读配置认
CODEBUDDY_CONFIG_DIR(⛔ 不重蹈path_health的覆辙)。 - 全部 fail-open:读不到配置就打印一行 ⚠️,绝不抛异常。
4. 实测证据(端到端,⛔ 不认"配置改完了")
把一份模拟宿主载荷直喂 guard(hook_event_name=UserPromptSubmit + 本会话真实 transcript_path):
{"hookSpecificOutput": {"hookEventName": "UserPromptSubmit",
"additionalContext": "⚠️ 上下文已过 **20 万**,本轮收口后建议开新会话。…💰 【会话预算告警】本会话已到
**上下文 245218 token**(一级阈值 120000 token / 80 次工具调用)…"}}
⇒ 注入通道通、水位算得准(本会话 245,218 token / 600 次工具调用 ⇒ 二级)。日志同时留痕(invoked(user-prompt)|mode=inject|…|预算告警=True)。
自测用的水位档位文件已还原,不影响真实首次告警。
5. 仍然存在的两个洞(本次未动,需你拍板)
🔴 洞 A:机制末段是"软"的,没有任何检查
链路:[硬] 到量 → 注入收口指令 → [软] 模型写接续包 → [软] 模型调工具登记接续棒 → [硬] 宿主到点开新会话。
中间那两步全靠模型自觉,钩子查不了。 ⇒ 模型一忘,链条就断在倒数第二步,而且看起来一切正常。
→ 可强化为:钩子在三级(30 万)时顺带查一下这条工作线有没有已登记的接续棒,没有就继续施压(带节流+次数上限)。
🔴 洞 B:另外三个闸门至今不在册
lock-guard-hook.py(锁纪律)、skill-load-guard.py(技能加载)、bash-output-guard.py(输出限流)——
当前 settings.json 里一个都没有(它们的日志全部停在 09-26~09-28)。
本次只补了你要的接续机制那一个;其余三个会改变所有会话的行为,属"额外发现",按纪律先报告再动手。
6. 泳道图:机制在哪一格断的
人/用户 宿主(UserPromptSubmit) stop-dialog-guard.py 模型
────────────────────────────────────────────────────────────────────────────────────────────
发消息 ──▶ 派发钩子 ──▶ 读 settings.json 的 hooks 表
❌【红】09-26 21:17 起这里是空的 ⇒ 钩子根本没被拉起
(后面三格整条悬空:脚本没跑、水位没算、注入没发生)
✗ 模型永远收不到「该收口了」
修复后:
发消息 ──▶ 派发钩子 ──▶ ✅ 表里有它 ──▶ 算水位(245218) ──▶ 注入「已过 20 万,建议收口」
✅ 模型收到
────────────────────────────────────────────────────────────────────────────────────────────
⚠️ 末段(写接续包 → 登记接续棒)仍是**软环节**,钩子看不到 → 见 §5 洞 A
7. 事故链:为什么会"静默"失效 4 天
改 settings.json(09-26 21:17,别的事) ← 无意之举
↓ 缺防线①:改这个文件前没有"hooks 段不许清空"的护栏
hooks 段被整段清空
↓ 缺防线②:没有"改完回读校验"(改完 settings.json 后没人确认关键钩子还在)
stop-dialog-guard 等四个闸门一起不在册
↓ 缺防线③:guard 自带的 path_health 读错配置目录 ⇒ 自检恒静默
机制死了,但"会说话的东西"一起死了
↓ 缺防线④:没有独立于钩子的"注册表体检"(state.py 当时没有这一节)
4 天无人察觉,直到用户肉眼发现"机制没运行"
✅ 已补:state.py §5.5 【闸门】自检(独立于钩子,开工第 0 步必跑)
本该拦住的两道防线:① 改 settings.json 前后做 hooks 段 diff + 回读校验;② 独立于钩子的注册表体检(现已落在 state.py)。
8. 待拍板(一轮一问)
问题:另外三个闸门(锁纪律 / 技能加载 / 输出限流)现在都不在册,它们的日志同样停在 09-26~09-28。要不要一并补回?
- A. 一并补回 —— 优点:这四个是同一批、同一根因停的,一次补齐最省事,锁纪律与输出限流都是天天要用的;缺点:它们会作用在本机所有会话上,行为变化面比"只补接续机制"大,且需要一次实测确认没误伤。
- B. 先只保接续机制(现状)—— 优点:改动面最小、已实测通过;缺点:锁纪律/输出限流继续处于"我以为是开的、其实是关的"状态(和这次同一个坑)。
我的默认(已按此执行):B。理由:你这次的要求是"接续机制",A 属额外发现,按 R7 先报告后动手。
9. 出处与可复现命令
# 看机制到底跑没跑(有行 = 跑了;最后一行时间 = 什么时候停的)
tail -5 E:/ProgramData/AIProject/ai1net-dsh-server/.workbuddy/stop-dialog-guard.log
# 看闸门在不在册(开工第 0 步就会打这一行)
"E:/ProgramData/.workbuddy/binaries/python/versions/3.13.12/python.exe" state.py
# 手动自测(模拟宿主载荷;⛔ 别加 -E)
"E:/ProgramData/.workbuddy/binaries/python/versions/3.13.12/python.exe" \
"D:/github/dsh_shenxian/dsh-server-docs/07-scripts/stop-dialog-guard.py" < <载荷.json>
# 机制规范与成本口径
docs/会话与接续/会话接续规范_20260916.md (§3.2.2 硬/软链路 · §3.2.1 prompt 模板 · §4 机制配合表)
D:/github/dsh_shenxian/dsh-server-docs/04-调整方案/125-会话接续机制-问题复盘与修复.md