Files
dsh_ai1net_server/交付物/接续机制未运行的根因与强化-20260930.md
admin c1b5e4d966 chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 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/ 知识文件,按口径入库)
2026-10-10 23:13:22 +08:00

173 lines
10 KiB
Markdown
Raw Permalink 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.
# 「上下文到量 ⇒ 开接续会话」机制 · 为什么没运行 + 强化
> 时间: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
```