# 「上下文到量 ⇒ 开接续会话」机制 · 为什么没运行 + 强化 > 时间: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` 补回一条: ```json { "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`): ```json {"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 ```