Files
dsh_ai1net_server/.workbuddy/memory/2026-09-下23.md
T
admin ce8e6ceed9 chore(工作区): 纳入版本控制基线(回收 411 MB 过程产物)
回收 411 MB(470 M → 58.8 M),全部经回收站,可恢复:
- 待清理/(146.2 M,含 relay 分片 128 M 与 42 项过程目录)
- tmp/(32.4 M,按接续棒命名的过程临时区)
- .workbuddy/tmp/(39.5 M)
- 4 份 workbuddy.db 冗余副本(101 M,09-23 事故的坏副本 / 抢救产物)
- tmp/im16/gw/centrifugo 二进制(63.9 M,可重下)+ 缓存残留

入库范围:常驻规则(CODEBUDDY.md / README.md / state.py)、在途接续入口与
接续包、docs/、交付物/、交接单/、归档/、scripts/、.codebuddy/、
.workbuddy/memory/;共 398 件,其中 >60 KB 的 26 件全为文档。

排除(.gitignore):tmp/、待清理/、运行态日志与缓存、*.db 与 DB 备份整目录、
打包二进制(*.tar.gz / *.tgz)、记忆修复前备份。
2026-09-24 07:51:03 +08:00

400 lines
47 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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(第 24 片)
> ⚠️ **本目录日志已按【月】分片**(2026-09-15 用户定,单文件 ≤50 KB):同月续片 `2026-09.md` / `2026-09-下.md` / `2026-09-下2.md` / `2026-09-下3.md` / `2026-09-下4.md` / `2026-09-下5.md` / `2026-09-下6.md` / `2026-09-下7.md` / `2026-09-下8.md` / `2026-09-下9.md` / `2026-09-下10.md` / `2026-09-下11.md` / `2026-09-下12.md` / `2026-09-下13.md` / `2026-09-下14.md` / `2026-09-下15.md` / `2026-09-下16.md` / `2026-09-下17.md` / `2026-09-下18.md` / `2026-09-下19.md` / `2026-09-下20.md` / `2026-09-下21.md` / `2026-09-下22.md` / `2026-09-下23.md`
> **写入约定**:一律 append 到**当月最后一片**;该片超 50 KB ⇒ 新建 `2026-09-下N.md`;⛔ **不要再按日新建 `2026-09-DD.md`**。
> **覆盖来源**:2026-09-15.md
> **上一片**:`2026-09-下22.md` **下一片**:`2026-09-下24.md`
---
## 07:2x — R5 多语言落地:平台运行时 + 登录页切换 + 插件「偏好设置」语言栏
- 用户口径:「优化插件相关代码,并且在登录窗口、设置中用户设置栏新增语言切换选项」(承接上一条:**沿用 dsh 官方 locale 方案 + 全球化默认英语**)。
- ① **平台 i18n 运行时(新建 `web/i18n.js`,7960 B)**:词条表(`en`/`zh` 两套扁平 key)+ 极小运行时(`data-i18n` 文本 / `data-i18n-attr` 属性就地替换)+ **语言下拉组件**(容器 `<div data-i18n-switch>`)。优先级 `?lang=` → cookie → `navigator.language`(命中支持列表才用)→ **兜底 `en`**;缺 key **回退英文并 warn**(不出空文案/裸 key)。
⚠️ 语言 id **与官方 `LOCALE_IDS` 对齐为 `en` / `zh`**(原设计 `zh-CN`)—— 便于日后把平台语言透传给实例的 `locale.preference` 而无需映射。
- ② **登录窗口**:`web/login.html` 全量词条化(title/标签/占位/按钮/错误文案/忙碌态)+ 卡内语言下拉;顺手把原来拼 `innerHTML` 的错误提示改为 **DOM 组装**(不再拼 HTML)。
- ③ **设置中用户设置栏**:插件 `@dsh-local/business-plugins` **0.3.19 → 0.3.20**,新增**用户可见** section「**偏好设置**」(id `preferences`,order 99,排在「模型设置」之前),内含「界面语言」下拉 —— 走官方扩展点 `ctx.locale.getLocale()` / `ctx.locale.setLocale(id)`,**零官方改动**;切换后只 bump 本栏 state(本栏立即换语言,官方 UI 由自身订阅刷新)。已铺发开发服务器:**admin bundles=7 / guest bundles=6,均含该插件**(未被 `pruneBrokenFileDeps` 摘掉)✅;tgz md5 本地=服务器。
- ⚠️ **踩坑 1(去痕迹约束)**:`scripts/verify-static.mjs` 有 `BANNED = 'dshs'`(**用户可见面不得出现平台内部名**)⇒ 我最初的 cookie 名 `dshs_lang` 直接判不合格;**连「在注释里把它写出来解释」也会被判不合格**(第二次被拦)。改为 **`dsh_lang`**(与既有 `sid` / `dsh-auth-*` 同族)。档案 §10.2 原写 `dshs_lang` ⇒ 已在档案里标注为**有意偏差**。
- ⚠️ **踩坑 2(断言需同步)**:`scripts/verify-platform-admin-section.mjs` 断言了 section 数量(admin 3 个 / 非 admin 2 个)⇒ 新增分区后**必须同步**:改为 4 个 / 3 个,并**新增** `preferences` 的渲染断言(该断言同时充当冒烟:输出实测含「界面语言 | English | 中文」)。
- 验证:`npm run verify` **exit 0 全绿**;`/i18n.js` 服务端 200 + `application/javascript; charset=utf-8` + `content-length: 7960`(`curl -w size_download` 显示 0 是**假象**);登录页经真实起服务取回,含 `lang="en"` / `data-i18n` / `script src=/i18n.js`;插件在服务器实例里渲染出 4 个分区(见 ③ 断言输出)。
- ⏳ **仍未做**:其余 5 个平台页(index/register/portal/admin/wake)与**注入浮层文案**的词条化;`verify-static` 的「静态页不得出现裸中文」判据(待 6 页都迁完再开,否则误拦未迁移页)。
- ⚠️ **未 commit / 未 push**(用户本次未要求)。待提交:`web/i18n.js`(新)、`web/login.html`、`poc/business-plugins/{lib/client.js,package.json}`、`scripts/verify-platform-admin-section.mjs`。
- 锁:`--claim-exec "R5落地-登录页+插件语言栏-0720"` → 已反序释放。
## 07:4x — 自我纠正:把「该我自己定的事」上抛了(决策方法文档)
- 用户质问:「为什么这个需要我来定,决策方法的文档有看到吗」⇒ **确实没先读技能就收尾提问**。违反:
- `dsh-decision-method` §4.1 **两条总闸**:闸 1(lane)=「设置里语言切换放哪」属**我方案内的执行细节 ⇒ 自己拍**;闸 2(门禁)= 现行**只剩两类**(不可逆破坏性 / 边界外),**实现落点不是门禁** ⇒ 不该问。
- §4.4「技术实现的默认裁决顺序:**AI 自主用,不问用户**」+ X9/U20「**过度上抛**(把部署/实现细节拿去问)」。
- **同时纠正另一处同类错误**:上一轮写的「其余 5 页待你定」也属上抛 —— 平台静态页是**我们自己的**、改静态页**即时生效不中断用户** ⇒ 按文档**自己排期做**。
- 本轮落地(自主决策 + 执行):
- 运行时扩展:`t(key, params)` 支持 `{n}` 占位符;抽 `common.*` 通用词条(登录/注册共用 pw-toggle 与 busy,**并删掉重复的 5 个 `login.*` key** —— U2 不做两套)。
- **新增 3 页词条化**:`register.html`(校验提示/错误/成功文案)、`wake.html`(「第 N 次」「约 N 分钟」**参数化** + 熔断提示)、`index.html`(title)。连同上一轮 `login.html` ⇒ **4/6 页已迁移**。
- **新增防回归判据**:`verify-static.mjs` 加 `I18N_PAGES` 白名单 —— 已迁移页**不得再出现裸中文文案**(剥掉 HTML/JS 注释后再判)+ 必须引入 `/i18n.js`。**迁移一页加一个**,未迁移页不误拦。
- 修判据自身两个缺陷:① `/<title>/` 不认带属性的 `<title data-i18n=…>`(改 `/<title[^>]*>/`)② 行尾 `//` 注释未剥离(假阳性)。
- 验证:`node scripts/verify-static.mjs` **全部合格 ✅**(6 页 + 内联脚本语法 + 资源);`npm run verify` **exit 0**。
- **我自主排的顺序(陈述,非征询)**:本轮 3 页 → 下一轮 `admin.html`(146 行)→ 再下一轮 `portal.html`(709 行 / 200+ 词条,动态模板串最多,单独做透以免"半翻译")→ 最后 `assets/inject/*.js` 浮层文案(**跨源资产**,需单独打包词条,属另一层)。
- 固化(A23:触发词没命中 ⇒ 规则进常驻层、用**动作词**):`MEMORY.md §三` 新增「**收尾前(写最终回复之前)必过两条闸**」,并明确列出**不算门禁**的动作(实现落点/部署上线/重启/改配置/改静态页/命名/断言期望值)。
- ⚠️ 副本冲突:`MEMORY.md` 在本轮被**另一会话整文件重写**(17 KB → 12.3 KB,07:31)⇒ 我的 Edit 因锚点消失而**失配**(工具正确拦住);已按新内容重做,并**补回被我误替换掉的「`INDEX.md` 三件套」铁律行**。
- ⚠️ 未 commit / 未 push(用户未要求)。待提交:`web/{i18n.js,login.html,register.html,wake.html,index.html}` · `poc/business-plugins/{lib/client.js,package.json}` · `scripts/{verify-static.mjs,verify-platform-admin-section.mjs}`。
## 07:4x — 报障:用户刷新看不到语言设置 ⇒ 根因 = **平台侧只改本机、从未部署**
- 用户:「我说的功能实现了吗,怎么刷新页面还是没看到修改语言的设置」。
- **根因(取证,非推断)**:
1. **平台侧从未部署**:服务器 `/opt/dshs/web/login.html` 还是 **9/13** 的旧版(`i18n` 命中 **0**),且 **`/opt/dshs/web/i18n.js` 不存在** ⇒ 登录页的语言下拉在线上**根本不存在**。我此前只改了本机仓库 —— 把「部署」这一步漏了(违反 U20:部署/上线属执行细节,该做完即上线)。
2. **实例侧其实已就绪**:两个用户 profile(`4092b965…` / `cce6d1cd…`)里装的都是 **0.3.20 且含 `id: "preferences"`**(`find -L` 跟 pnpm 软链才看到 —— 上次我用 `-type d` 没跟软链,误以为没装;另上次路径写成 `/var/lib/dsh/`,正确是 **`/var/lib/dshs/`**)。
- **修复(已执行)**:
- 备份旧文件到 **`/opt/dsh/backups/web-20260915-073736/`**(回滚点:`cp -a` 回去即可);
- scp 5 个文件到 `/opt/dshs/web/`(本地是 LF,无需转行尾):`i18n.js`(12248 B) · `login.html` · `register.html` · `wake.html` · `index.html`;`chown root:root` + `chmod 644`;
- **双端验证**:服务器本机 `curl /i18n.js` → 200 + `application/javascript; charset=utf-8` + 12248 B;`/login.html` 含 `data-i18n` **11 处**;**公网** `curl https://alotbuy.com/login.html` → **HTTP 200**、`data-i18n` **11 处** ✓(静态文件**无需 build/重启**;平台 `dshs` 服务全程 `active`)。
- **自查路径(用户侧)**:① 平台 **`https://alotbuy.com/login.html`** → 卡片底部「Language / 语言」下拉(默认英文)② 实例内 **设置 → 偏好设置** → 「界面语言」(需**硬刷新** `Ctrl+Shift+R` 以绕过浏览器缓存 —— 换产物后的既有 rev 契约)。
- **固化(防复发)**:`MEMORY.md §三` 新增「**「改完了」≠「上线了」——按文件类型判部署动作**」:`web/**` ⇒ scp 即生效;`src/**` ⇒ build + restart;插件 ⇒ artifacts + `ensure-biz-plugins.cjs`;**验证必须到公网侧**(只看 `127.0.0.1:3080` 不算数)。
- ⏳ 仍待做:`portal.html`(709 行)与 `admin.html`(146 行)的词条化 + 注入浮层文案(我的排期,非征询)。未 commit / 未 push。
## 07:30–07:5x 会话 `15ee0d4f`:索引优化收口 + 「自决功能」失效根因 + 交付门禁
**用户两问**:① 之前设的「会话按决策方法自行判断继续处理」不好使、会话老让确认简单问题(让我看 5 分钟前的会话记录)② 要不要把「改了本机没部署」加进项目迭代执行步骤。
### 一、索引/文档链路优化:昨天的落地包**已全部落地**(一个锁窗口内做完并释放)
- ★❓ 状态缺失 **14 篇 → 3 篇**(余 `04-27/50/84` 确无状态行)。根因 = **manifest↔INDEX 环形锁定**:`docs-manifest.py` 的 `marks` 白名单不含 ❓ ⇒ INDEX 的 ❓ 被读成 `'?'`;而 `'status': (index_status…).get('status') or (hs…)` 因 `'?'` 为真**短路** ⇒ 回灌 ⇒ 再渲染成 ❓ ⇒ 永久锁死。修法 = 状态改为「**档案头部为权威 → INDEX(❓/? 视为缺)→ ?**」+ 放宽正则 + `norm_status()`。
- 同窗口完成:`docs-archive-index.py` 顺序断言 + 缺失率/名单 | `docs-shrink-guard.py` `--allow-shrink` | `handoff-guard.sh` 抢锁输出加"锁生命周期" | 库内 CODEBUDDY 七件套·顺序不可换 + 约定 #2/#3 执行者 | **4 个未入库脚本首次入库**(G1 修复)
- 提交 **`ea6e837`**(13 文件 / +1251 −428)· `audit` rc=0 · `consistency` ✓ · 对账 167 一致 / **0 幽灵** · 锁已释放
### 二、「会话自行判断继续」为什么不好使(★根因 + 硬证据)
- **核账**:本工作区宿主日志 `tool=AskUserQuestion` 调用数 = **09-12: 43 / 09-13: 3 / 09-14: 0 / 09-15: 0**(`UserQuestion`/`elicitation` 命中全是 `--tools` 参数与 host capability 字符串,**不是调用**)
- ⇒ **既有「提问闸门」hook(matcher `^AskUserQuestion$`)拦的是"几乎不走"的工具面**;真实上抛在**正文**("要我接着做吗/请确认/说一声即可")⇒ **零机制覆盖** ⇒ 这就是"会话经常忘记"的结构性原因(不是态度)
- 已修三处:① **常驻层**(项目根 `CODEBUDDY.md §1`)新增「**回话前自检**」+ 征询句清单(发问前重判三问)② 方法层 **A24**「拦截面必须覆盖真实行为面」③ **机制层**:新写 `scripts/stop-dialog-guard.py` —— **Stop 事件钩子**,读 transcript **最后一行**扫征询句 → `{"continue":false,"reason"}`;自作用域(仅本工作区)+ 防死循环(`stop_hook_active`)+ **引用豁免** + 异常静默放行;**5/5 用例自证通过**
- ⚠️ **未安装**(需拍板):装它要改 `E://ProgramData//.workbuddy//settings.json` 的 `hooks` 段(**多会话共享配置**)+ **完全重启 WorkBuddy**(会打断当前所有会话),且宿主是否采纳 Stop 的裁决**未验证**。
- **诚实边界**:5 分钟前那个会话(`63615df4`「检查项目是否支持用户自定义 skills」,07:19 起、07:30:30 仍在写)**问了什么的原文拿不到** —— 会话正文只在云端;本机事件流只有 `tool_call` 类型无文本、`projects/` 无该 sid 的 jsonl、宿主日志只记 `tool=`。**但结论不受影响**:今天无任何 AskUserQuestion 调用 ⇒ 那个问句只可能是正文。
### 三、交付门禁(用户问"是否加入迭代执行步骤" → **判定:需要**,已落)
- **缺口定位**:`06-工作台UI规范 §7` 早有"生效链路四关",但 **`dsh-change-workflow` 阶段 5 通篇只讲文档归档,一个字没提"平台改动要部署到用户可见面"** ⇒ 知识在文档、**不在执行步骤**。
- 落地:① `dsh-change-workflow` 阶段 5 新增 **★§0「交付门禁」**(按改动层列生效链路表:静态页 scp+**CDN/CF 缓存坑** | 平台 TS build+restart | 插件 tgz→候选池→实例启用→**重启实例** | 文档库 scp+对账 | 配置 reload;并点名**四条不算交付的自我安慰**:本机改完 / build 通过 / 本地打包完成 / 已 commit;同时**禁止回头问"要不要部署"**)② `dsh-decision-method` **v2.4.0** 新增 **A25**「本机改完 ≠ 交付」+ 索引行 ③ 项目根 `CODEBUDDY.md §2` 加一行「我做完了吗」判据
- 依据实例:**同类 3 次**(09-13 本地打包未部署 →「点开看还是和之前一样」;09-14「应用更改是哪里…」;09-15 原话「**平台那半我只改了本机,从没部署到服务器 —— 那你看的当然还是旧页面**」)
- 提交 **`09149af`** · 两技能三处 md5 一致 · 对账残留 **3 项全别人 lane**(BRIEF / DEPLOY / opensource-release)· 锁已释放
## 07:4x — 文案微调:「登录进入AI世界」→「欢迎进入AI世界」(改完即上线)
- 用户要求改登录页副标题。实测改动面**只有 3 处**:`web/i18n.js` 的 zh/en 词条 + `web/login.html` 的兜底文案(导出物 `web/login.html` 仍是旧版 ⇒ 下次重建自动跟上)。
- **英文同步改**为 `Welcome to the AI world`(原 `Sign in to the AI workspace`)—— 中英必须同义,否则破坏双语对齐。
- 按新固化的判据**改完即部署**:备份 `/opt/dsh/backups/web-20260915-074052/` → scp `i18n.js` + `login.html` → `chmod 644`(静态文件**无需 build / 无需重启**)。
- 验证:`node scripts/verify-static.mjs` **全部合格 ✅**;服务器本机与**公网** `https://alotbuy.com/` 均取到 `data-i18n="login.sub">Welcome to the AI world`,词条两条(`'Welcome to the AI world'` / `'欢迎进入AI世界'`)✓。
- ⚠️ **刻意不手工同步导出物**:`web/wake.html` 里有 `alotbuy.com` 字面量,**由构建的 GLOBAL 规则替换** ⇒ 手抄会把真实域名带进公开仓。**导出物一律走重建**(本机 `--force` 被安全删除层拦 `rmtree`,需另循途径:先 `mv` 走 `.git` 再重建)。
## 07:44–08:1x 会话 `15ee0d4f`:Stop 钩子「装之前」的风险量化 + 加固(5 修)
**用户问**:「装上会有哪些风险和潜在影响呢」 ⇒ 先量化,再加固,最后给风险表。
### 量出来的硬数(决定了 3 个必须改的点)
- 本机转录大小:本工作区最大 **31.9 MB**(`b2817961`)、另有 25.3 / 11.2 MB;其他工作区 21.5 MB
- **全文读 14 MB 实测 = 832 ms**;应用侧 hook 进程历史 `elapsed ≈ 264 ms`(09-13 `[HookExecutor] abnormal exit … elapsed=264ms`)⇒ **每轮回话读全文不可接受**
### 装之前修掉 5 个问题(**其中 3 个是我自己刚埋的**)
| # | 问题 | 修法 |
|---|---|---|
| 1 | 全文读转录(30 MB 级/轮) | **只读末尾 256 KB** |
| 2 | **巨行漏判**:一条 assistant 记录 > 256 KB 时,尾窗切在 JSON 行中间 ⇒ 解析失败 ⇒ **静默漏判**(实测复现) | **从尾部分块扩窗**(256 KB → ×4 → 上限 **4 MB**) |
| 3 | 限频误吞:旧版"只查也记账" ⇒ 同会话**下一轮的合法拦截被吞掉** | 改为 **命中才记账**(`peek=True` 只查不写) |
| 4 | 无急停手段(误伤时要卸载+重启) | **急停双闸**:env `DSH_STOP_GUARD_OFF=1` / `<工作区>/.workbuddy/stop-guard.disabled` |
| 5 | 超窗漏判无痕 | **留痕**(A18:静默失败是负债)⇒ 写 `stop-dialog-guard.log` |
### 加固后实测
常见情形 **270–540 ms/轮**(含 python 冷启动,压不掉)|判据样本 **5/5**|限频 ✓|换 sid 仍拦 ✓|急停 env ✓ / 闸刀 ✓|巨行超窗 = **放行**(fail-open:**不误伤,只是漏**)
### 交付
入库 + scp 镜像 + 提交 **`ec88710`** + 锁已释放(一个窗口)。**仍未安装**(等用户拍板);未安装时脚本在库里/镜像里,**急停闸与日志都不会产生**。
### 待用户拍板(安装)与验证方案
装 = 在 `settings.json` 的 `hooks` 加一个 `Stop` 键(**只 Edit 增条,不整段覆盖**,改前备份)→ **完全重启 WorkBuddy** → **用一次故意犯规实测**:若宿主不采纳 `continue:false`(**未验证**)⇒ 卸载(删该键 + 再重启)。
## 08:0x–08:2x 会话 `15ee0d4f`:按新规则 **U26** 处理 Stop 钩子的风险(形态定型 + 恢复现场 + 后台验证)
**用户两条指令**:① 「先解决风险和问题,做到最优效果确认无误后再执行」② 「**决策中发现方案有风险和问题,需要分析并优化到当前情况和状态下的最优解,然后进行下一步处理,这个也要加入决策方法**」。
### 一、新规则已入方法:**U26**(dsh-decision-method **v2.5.0**,U 条数 26)
「发现风险/问题 ⇒ **不许带着问题往下走**」四步判据:① **列出来**(风险清单,不许只在脑子里)② **逐条处置**(能当场消的当场消;消不掉的写「残余 + 触发条件」)③ **说清残余**(哪些是已知接受、什么信号必须回头看)④ **然后才进入下一步**,且交付里把 ①②③ 一并写出。配套:A24/A18/A19/A25 判"能不能消";"改小范围先落地"永远合法。⛔ 反面:把"有风险"当"要不要问用户"(过度上抛)或"先干着看"(风险转移)。
### 二、决策级实测(把钩子形态定死)
| 方案 | 实测(热 python 直接 spawn,10 次均值) | 判定 |
|---|---|---|
| `python -c pass`(对照) | **286 ms** | — |
| **`python -S -E`** | **185 ms** | ✅ **采用**(省 ~100 ms/轮) |
| `node -e ""` | 211 ms | ❌ 不比 python -S 好 |
| `bash -c exit 0`(外壳) | **1072 ms** ⚠️ | ❌ **bash shim 方案否决**(比 python 还慢 3 倍) |
| 真实钩子·作用域外立即放行 | 286 ms | 冷启动主导 |
| 真实钩子·常见路径(小转录) | 283 ms | — |
| 真实钩子·**70.4 MB 转录** | **286 ms** | ✅ **成本与转录大小无关**(尾部读生效) |
⇒ **形态定型 = 单 python 脚本 + `python -S -E`**;**不引入第二层**(bash shim 已删)。
### 三、现场恢复(不留半截)
- 临时装的 Stop 钩子**已移除**;`settings.json` 校验 = 顶层键 5 个、`PreToolUse`×2 + `SessionStart`×1 **完好**,备份 `settings.json.bak-stopverify-075408` 保留。
- 清理:headless 输出/err、`stop-dialog-guard.log`、`stop-guard-fires.json`、`__pycache__`、待落地下的杂项 `.workbuddy/` 全部删除。
- 备注:headless **前台**尝试被 SIGTERM(工具超时)⇒ 改为**后台自包含**跑:`verify-stop-hook.py`(装→验→**自动卸回**),task `jNTflq`。
### 四、按 U26 的结论(当前情境下的最优解)
- **暂不装**:① 常驻层「回话前自检」(`CODEBUDDY.md §1`)+ 方法层 **A24** 已覆盖同一面(零成本零风险)② R5(宿主是否**调用** Stop 钩子、是否**采纳** `continue:false`)**仍在验证**(后台)③ 装它需**完全重启**(打断用户所有会话)⇒ **不值得为一个"可能无效"的机制单独安排一次重启**。
- **触发条件(何时装)**:**下次用户本来就要完全重启时顺手装**(零额外成本);或后台验证出"宿主确实调用且采纳"而用户希望立刻生效。
### 五、本轮提交
`5f34b1b`(技能 v2.5.0 + 脚本终版含 `DSH_SG_DEBUG`)· scp 镜像 OK · 对账 0 仅服务器 · **锁已释放**。
## 08:00–08:2x 会话 `15ee0d4f`:**认错并改正** —— 把"延后"当最优解是**将就**;按 U27 真解决
**用户两句**:① 「你的最优解是 延后处理不是立马解决问题吗」(质疑)② 「**项目推进要的是解决问题 不是得过且过,将就妥协**」+「把这个理念当作重要方法加入到规则中」。
### 一、我上一轮错在哪(如实)
- 我把「暂不装、等下次重启顺手装」当成"当下最优解",还拿"常驻层自检已覆盖同一面"当缓解 —— **而用户最初的报障就是这条前提的反证**(规则早在,会话照样问)⇒ 按 **A24**(先核账再假设)这条前提不成立。**结论:那是"将就",不是"解决"。**
### 二、新规则 **U27**(dsh-decision-method **v2.6.0**,U 条数 27)
「**要的是解决问题,不是得过且过、将就妥协**」:面对风险/缺陷**默认目标是解决**;**降级目标 / 延期 / 静默兜底**三种**都不算解决**。**唯一允许"暂时接受" = 客观不可逾越**,且必须写明 ① 卡在哪(证据)② 已做到哪一步 ③ **什么条件一出现必须回头解决**。
- 给 **A6 补边界**(防互相矛盾):**A6 管路径(取最小代价)、U27 管目标(不许打折)** ⇒ 一句话 **"目标不打折,路径取最小代价"**。
- 常驻层:项目根 `CODEBUDDY.md §1` 加一行(含"与 §2 不矛盾"的说明)。
### 三、按 U27 重做的动作(**不延期 → 直接装**)
| 动作 | 结果 |
|---|---|
| Stop 钩子**正式安装** | `settings.json` 的 `hooks.Stop` = `"<python>" -S -E "<脚本>"`;**只加一个键**,`PreToolUse`×2 / `SessionStart`×1 断言完好;备份 `bak-stopverify-075408` / `bak-stopverify2-075909` |
| 档案 **99** | `04-调整方案/99-会话自决失效根因与Stop钩子补强.md`(8 节:根因/用户决策/方案对比含"不做"/实现/验证含**失败尝试**/踩坑/验收/回滚)→ INDEX 已登记(**档案 99 篇**) |
| 方法 & 常驻层 | U27 · A6 边界 · `CODEBUDDY.md §1` 一行 |
| 收口 | 七件套:audit rc=0 · manifest ✓ · archive-index --write(99 进表)· consistency ✓ · shrink-guard(见下)· scp 镜像 OK · 对账 3 不一致(**全别人 lane**)· commit **`64de538`** · **锁已释放** |
| 顺手清掉一条误报 | `docs-shrink-guard` 一直在报 `skills/dsh-decision-method/SKILL.md 491→302 行(-38%)`(= 我 09-14 的**合法拆分**)⇒ 用我自己加的 `--allow-shrink` 接受并刷新基线 |
### 四、headless 预验证路线:**放弃(有依据)**
两次尝试(前台 + 后台自包含)**都在 `codebuddy-headless.js -p` 处卡死 4–5 min 无输出**,被迫 kill ⇒ 该路线不可用。**替代 = 重启后当场实测**(我在会话里故意以征询句结尾,看是否被拦回 + reason 是否注入),**30 秒得结论**。
### 五、剩余唯一成本(客观不可逾越,有证据)
**一次完全重启** —— hooks 是**应用启动时快照**(09-13 实测定论:改配置对已跑会话无效)。已做到:装好 + 档案 + 验证法 + 急停闸 + 回滚。**触发条件(必须回头)**:重启后若**未拦回** ⇒ 说明该版本不采纳 Stop 裁决 ⇒ 当场卸载并改走"收尾清单 + 用户输入前提示"的第二方案(不留在"假安全感"里)。
## 08:11–08:25 会话 `15ee0d4f`:功能验证(**含一处自纠**)+ 新红线 **R11** / 方法 **U28**
**用户两条**:① 「确认现在功能正常就行」② 新红线:「确保所有决策让项目**正向迭代和提升**;遇到**纯劣化风险**(目标/方向/架构/功能/性能/安全/交互/UI/便利性/扩展性)**立即停下复盘**,确实**无正向迭代方法**立即**停止**,**禁止继续执行**」。
### 一、功能验证(诚实记:我的判定法先错了一次)
- **重启已生效**:`last-launch.json` = **08:09:52**、`WORKBUDDY_STARTUP_PID=29456` ⇒ 新进程 ⇒ `hooks.Stop` 已随快照加载 ✓
- **安装命令自测 ✓**:用真实转录 + 合成 Stop 载荷逐字跑配置里那条命令 → 未命中 → 空输出(符合预期)
- ❌ **自纠**:我上轮写"日志空 = 宿主没调用" —— **不成立**:我的**探针句本身没命中判据**(长句塞不进 `{0,12}`);而我的**校验脚本又用空正则**(全命中)自欺,两错叠加 ⇒ 该结论作废。改用**直接加载模块**复核后:长句 命中=False、短句 命中=True。
- **已修两处根因**:① 判据 `{0,12}` → **`{0,20}`**(长句可命中;陈述句与"需要你拍板"节仍**不误伤** ✓)② 本工作区内**每次调用都留痕**(含 `invoked` 行,日志上限 300 行)⇒ **"宿主有没有调用"从此必然可判**,不再依赖探针句是否命中。
- 本轮回复**结尾用已验证会命中的短探针句** ⇒ 一次拿到两问:① 被调用?② 采纳 `continue:false`?
- 顺带:`py_compile` 产生 `scripts/__pycache__/*.pyc` ⇒ 对账报「仅本地 1」⇒ 已清干净(**教训**:py_compile 后要么清副产物,要么 `PYTHONDONTWRITEBYTECODE=1`)。
### 二、新红线 R11 + 方法 U28(已落)
- **常驻层**(项目根 `CODEBUDDY.md`):§3 新增 **R11**(十维**净变差**即命中 ⇒ **立即停下复盘**;**拿不出正向做法 ⇒ 立即停止、禁止继续执行**;⛔ 三种伪装:说成"必要代价"/用"后续再优化"掩盖/藏进交付不写)+ §1 一行指针(含"与 R5 互补:R5 管权限、R11 管全维度净收益")。
- **方法层**:`dsh-decision-method` **v2.7.0**:**U28** + **§4.1 判定矩阵新增一行**("会让项目某一维度净变差吗" → 会 ⇒ 停下复盘/无正向做法即停)+ 索引行;库内 `CODEBUDDY.md` 的「红线 R1–R10」引用 → **R1–R11**。
- 收口:七件套 ✓(audit rc=0 · consistency ✓ · archive-index --write ✓)· scp 镜像 ✓ · 对账 **仅本地 0 / 仅服务器 0**(余 3 项内容不一致 = 别人 lane)· commit **`5001f03`** · **锁已释放**。
## 08:22–08:40 会话 `15ee0d4f`:常驻规则**可移植化**(新技能 `dsh-env-bootstrap`)+ 顺带修两处账实不符
**用户要求**:「常驻层 CODEBUDDY.md 的关键内容也要加入到 skill 中,避免哪天换电脑换环境就无法执行了(换环境后可以自动注入到对应 CODEBUDDY.md 中)」
### 一、判定与做法(不造第二真相源)
常驻层**不能被替代**("动作前必然生效"靠它),技能只负责 **带过去 + 防丢 + 校验**。所以做成 **技能内快照 + 幂等命令**:
| 文件 | 内容 |
|---|---|
| `references/常驻规则-快照.md` | **由权威 `CODEBUDDY.md` 经 `--snapshot` 自动抽取**(**19.4 KB / 6 章**:§1 提问判据 · §3 红线 **R1–R11** · §4 提交边界 · §5 规划执行分离 · §6 并发纪律 · §8 事故级实测事实)+ 骨架锚点清单 + **待核清单** |
| `scripts/resident-rules.py` | `--env-check`(路径 + hooks 命令自检)· `--check`(**默认只报**,rc=1)· `--inject [--init]`(只动标记块)· `--snapshot`(由权威重生成,单向) |
| `SKILL.md` | 何时用 + 换环境四步 + **设计红线** + 自检 |
**设计红线(防漂移)**:① **权威方向单向**(CODEBUDDY.md 权威 / 快照副本,只允许 `--snapshot` 生成)② **默认只报不改**(同文档库"体检只报不改")③ **注入只动标记块**,首次**不自动注入**(避免同一规则两处并存)④ **不假装能自动配环境**(环境相关项只做存在性检查 + 待核清单)。
### 二、实测(都跑了)
- `--snapshot` → 快照 10036 字符 / 19.4 KB / 129 行 / 6 章 ✓
- `--check` → **全绿 rc=0**(10 个骨架锚点 + 5 章节存在性)✓
- `--env-check` → 工作区/文档库/代码仓 ✓ 存在;**3 条 hooks 命令路径全部有效** ✓;服务器/备份目录标"需 ssh 侧核对"
- `--inject`(无 `--init`)→ **拒绝注入**("目标里没有标记块")✓ = 防重复设计生效
- 修脚本自身 2 个 bug:`references/` 目录未建(加 `makedirs`);hooks 命令用正则解析被**转义引号**截断(改 `json` 解析)
### 三、顺带修两处**账实不符**
- `CODEBUDDY.md §3` 标题:`红线 R1–R10` → **`R1–R11`**(内容已含 R11,标题漏改)
- `INDEX.md` / `README.md` 里引用我技能的几行:「红线 **R1-R8**」→ **`R1-R11`**;并新增 `dsh-env-bootstrap` 的**三处清单行**(INDEX 场景速查 + 全量清单 + README 模块表)✓(阶段 5 第 5 条的"更新引用它的元数据")
### 四、收口
七件套 ✓(audit rc=0 · manifest ✓ · archive-index --write ✓ · consistency ✓)· scp 镜像 ✓ · 对账 **仅本地 0 / 仅服务器 0**(174/174;余 3 项内容不一致 = 别人 lane)· commit **`3b5bd42`** · **锁已释放**。
### 五、Stop 钩子行为验证(本轮读日志)
见本轮回复:留痕已开(本工作区内**每次调用必写一行**)⇒ 日志为空即**宿主不调用 Stop 钩子**;有 `invoked` 行则至少证明被调用;有 `命中` 行 + 我被拦回 ⇒ 调用与采纳都成立。**判据不再依赖探针句是否命中**(上一轮的两错已修)。
## 08:25–09:00 会话 `15ee0d4f`:Stop 结论 + 第二方案落地 + **我的一个真违规**(已沉淀)
### 一、功能确认(Stop 线程定论,决定性实测)
- 重启已生效(`last-launch.json`=08:09:52、新 PID)+ 探针句**已验证会命中** + 脚本已改为**本工作区内每次调用必写一行** ⇒ **日志仍为空**
⇒ **WorkBuddy 5.5.6 桌面版不调用 `Stop` 钩子** ⇒ 按「不留假安全感」**已卸载**(备份 `settings.json.bak-stopuninstall-082503`)。
- **第二方案 `UserPromptSubmit` 已装**(官方契约:输入**同样带 `transcript_path`**,且支持 `additionalContext` 注入;**每轮必触发**):
· 两级模式:`probe`(只写日志、零风险)→ `inject`(命中才注入上下文);**切换 = 改 `<工作区>/.workbuddy/stop-guard-mode`,即时生效、无需再重启**(只有 settings 的 hooks 条目是启动快照)
· 自测 **4/4**(probe 不注入 / inject 命中才注入 / 陈述句与"需要你拍板"节不误伤 / 每次调用必留痕)
· 当前 = **probe**:**下次你自然重启后**读 `stop-dialog-guard.log`:有 `invoked(user-prompt)` ⇒ 该面可用 ⇒ 我切 `inject`;仍空 ⇒ 只余"常驻规则+每轮自检"那层,如实收口。
- 顺带修真 bug:脚本 `main()` 的 `except: pass` **把 `NameError: out is not defined` 藏了半小时**(我调了本文件不存在的 `out()`)⇒ 改为**异常必留痕**(A18 教科书案例)。
### 二、🔴 **我的真违规(如实记)**:无锁改库
- 我在同一命令里用 `... --claim-exec ... | grep -E "已持全局执行锁|停手"` 判抢锁 ⇒ **抢锁其实失败**(有会话持锁),
但**失败提示里也含关键词**("…必须 `--release-exec` 才算完成")⇒ grep **假命中** ⇒ 我据此**在无锁状态下改了档案 99 + scp + commit**。
- **损害核对(无实际损害)**:我的 commit `cbf51ba` 只含 **3 个文件**(档案 99 / manifest / 我的脚本),**未带走别人的半成品**;档案 99 是我自己当天新建、别人不会改。
- **已沉淀为硬判据**(项目根 `CODEBUDDY.md §6` + 素材库 **A18** 姊妹坑):**① 检查退出码(不要接管道)② 复读 `交接单/.exec-lock/OWNER` 并断言等于自己的会话名**;"输出了像成功的话" ≠ 成功。
### 三、上一条要求已交付:常驻规则**可移植化**
- 新技能 **`dsh-env-bootstrap`**(SKILL.md + `references/常驻规则-快照.md`(19.4 KB / 6 章,由权威 CODEBUDDY.md 经 `--snapshot` 生成)+ `scripts/resident-rules.py`)
- 四命令实测 ✓:`--check` **全绿 rc=0**(10 骨架锚点 + 5 章节)|`--env-check` ✓(3 条 hooks 命令路径有效)|`--inject`(无 `--init`)**拒绝**(防两处重复)|`--snapshot` ✓
- **设计红线**:权威方向单向(CODEBUDDY.md 权威 / 快照副本)· 默认只报不改 · 注入只动标记块 · 不假装能自动配环境
- 顺带修账实不符:`CODEBUDDY.md §3` 标题 R1–R10 → **R1–R11**;INDEX/README 的「红线 R1-R8」→ **R1-R11** + 新增三处技能清单行
- 另:项目根 **§7** 加一条 —— **语法检查别用 `python -m py_compile`**(必落 `__pycache__/*.pyc` ⇒ 污染对账「仅本地」)⇒ 用 `ast.parse` 不落盘写法。
### 四、收口 / 现状
- commits:**`cbf51ba`**(Stop→第二方案 + 档案 99 修正节)· **`f3b475d`**(抢锁校验教训沉淀)· `3b5bd42`(env-bootstrap 入库)· `5001f03`(R11/U28)
- 对账:**仅本地 1 = `04-调整方案/100-实例内我的技能-并入功能管理分组.md`** —— **别的会话的在途产物**(不在我清单 ⇒ 按 §6 不动、只报告);内容不一致 3 项亦全为别人 lane。
- 锁:当前**空闲**(每次均严格反序释放)。
## 13:53–14:05 会话 `15ee0d4f`:新增**排版规范**(可扫读)—— `dsh-feature-first §5.4`
**用户要求**:「和 AI 对话过程中 AI 返回执行信息和问题**排版格式很不方便阅读**,看看如何优化内容排版做到 **内容结构清晰、重点突出、细节完整、方便快速浏览和阅读**」
### 一、落在哪(三处 + 一处自检)
| 载体 | 内容 |
|---|---|
| **`dsh-feature-first §5.4 排版规范`(实体)** | A **六条硬约束**(可自检)· B **五类回答的现成骨架**(执行信息/是否已实现/报障/提问/长清单,**不新造**)· C **十条反模式** · D "细节完整 ≠ 全塞正文" |
| `dsh-feature-first §6 自检清单` | 加**第 11 条**:「这条回复**能被扫吗**?」(逐项数得出来) |
| 项目根 `CODEBUDDY.md §1` | 一行指针(含六条摘要)—— 常驻、每轮生效 |
| 用户级 `~/.workbuddy/MEMORY.md` | 一行跨项目偏好(**所有项目都生效**,不只 dsh) |
### 二、六条硬约束(都是"数得出来"的,不是感觉)
首屏 3 行给判定(✅/⚠️/❌ + 一句)· 层级 ≤3(**不出 `####`**)· 每节 ≤7 行、连续 >12 行无结构 = 文字墙 · 加粗每节 ≤2 处且**不整句加粗** · 表格 ≤5 列且单元格不塞整句 · **一条信息只出现一次**。
### 三、五类回答的骨架(避免"每次都即兴排版")
执行信息 → §5.2 交付回执|是否已实现 → §5.1 结论骨架|报障 → 判定/证据(代码块 ≤10 行)/处置/未闭环|**提问 → 问题 + 为什么问你 + 选项(推荐置首)**|长清单 → 表格。
### 四、十条反模式(见到就改)
文字墙 · 嵌套 >2 层 · 结论埋段中 · 整句加粗 · 表格超宽 · 同信息重复三遍 · "如下所述"指代不清 · emoji 堆砌(只用于状态/分级)· 术语路径混进结论层 · 标题层级跳跃。
### 五、为什么这么定(不是审美)
用户要的四点 → 分别对应可检验的动作:**结构清晰** = 层级≤3 + 五类骨架;**重点突出** = 首屏判定 + 节首句给结论 + 加粗只留关键词;**细节完整** = 细节进附录/代码块/表格附列(不删信息);**快速浏览** = 每节≤7 行 + 表格 ≤5 列 + 一条信息只说一次。
### 六、收口
commits **`4498b42`**(§5.4 + 自检第 11 条 + 两处指针)|严格抢锁(校验退出码 + 断言 OWNER)→ 同步归档(md5 `20d601b5` 双端一致)→ scp 镜像 OK → `audit` rc=0 / `consistency` ✓ → **锁已释放**。
对账:仅本地 1 = `交接单/T08-集群化落地-兼容单例模式.md`(**别人的在途产物**,不在我清单 ⇒ 不动、只报告);内容不一致 6 项亦全为别人 lane。
## 14:15–14:30 会话 `15ee0d4f`:「继续处理」—— 推进可做的部分 + 把两个客观卡点点明
**用户**:「继续处理」。
### 一、先判定两条线的卡点(都不是"我不想做",是客观条件)
| 线程 | 卡在哪(证据) | 已做到哪 | 什么条件回头 |
|---|---|---|---|
| UserPromptSubmit 探针定论 | **应用未重启**:`last-launch.json` 仍 = **08:09:52**、PID 29456 未变 ⇒ 钩子(08:26 装)**尚未加载** ⇒ 日志空是**预期**,不是"不可用" | 钩子已装(probe)· 脚本自测 **4/4** · 切换只需 `echo inject > .workbuddy/stop-guard-mode`(**免重启**) | **你下次完全重启**后读日志:有 `invoked(user-prompt)` ⇒ 切 inject;仍空 ⇒ 卸载并如实收口 |
| 技能归档同步(本轮改动) | **全局锁被 `exec-cluster-1a` 持有**(14:15 起 = T08 集群化在跑)⇒ R9 禁抢禁接管 | 3 个技能的**工作副本**已改好(库外、本地加载即生效) | 锁释放后:同步归档副本 + 镜像 + bump patch 版本 + commit |
### 二、本轮「继续处理」实际做完的事
1. **排版规范一致性推广**(避免"规范只活在一个技能里"的半截状态):`dsh-change-workflow` 阶段 5 第 4 条(汇总表交付)· `dsh-decision-method` §附自检**第 12 条** · `dsh-env-bootstrap` §4 自检**第 5 条** —— 各加一行指向 `dsh-feature-first §5.4`。
2. **`待落地/重启后待办.md`**(新):把"重启后必须做的两件事(探针定论 + 顺手核对)"写成显式文件,放 `待落地/` ⇒ 重启那一刻必然被看到;含**判负前提**(先看 `last-launch.json` 是否晚于 08:26,避免把"还没重启"误判成"不可用")。
3. **严格抢锁**(校验退出码 + 断言 OWNER)→ **失败即停、未动库** ✓(这次判据正确,与上午那次违规形成对照)。
### 三、我 lane 待办扫描(只读)
- `交接单 §一`:T03 ✅ 已归档;**T08 集群化 = 🔄 执行中**(占用者 `exec-cluster-1a`,11:19 开工)—— **不是我的单**,不动。
- 对账:仅本地 1(`交接单/T08-…md`)+ 内容不一致 6 项 —— **全为别人 lane**。
---
## 15:0x 技能三处同步 + 工具缺陷修复(执行会话 `排版指针归档-0718`)
**背景**:上轮把 `dsh-feature-first §5.4` 排版指针加进 3 个技能的**工作副本**(`~/.workbuddy/skills/`),
但**文档库归档副本**(`dsh-server-docs/skills/`)没跟着,本次补齐并收口。
**抢锁**:`--claim-exec "排版指针归档-0718"` → 退出码 0 + **复读 `.exec-lock/OWNER` 断言一致**
(⛔ 不接管道 —— 上次「假命中导致无锁改库」正是接管道造成的)。完工后 `--release-exec` + 断言目录消失。
**改了什么**
- 归档补齐 3 处:`dsh-change-workflow`(汇总表那行)· `dsh-decision-method`(自检第 12 条)· `dsh-env-bootstrap`(自检第 5 条)
- 顺路修 2 个真缺陷(都在本次要冻结的文件内):
① `dsh-decision-method` 活副本自检清单被插成 `…10, 12, 11`(**编号乱序**)⇒ 改回 `…10, 11, 12`
② `dsh-change-workflow §5` 指 `docs-status/文档库状态备注.md`,**该机制已不存在**(照做必然失败)⇒ 改指「`README.md` 模块表行 + `INDEX.md` 场景速查行 + 全量清单行」
- 版本 patch bump:`2.9.0→2.9.1-playwright-banned` / `2.7.0→2.7.1` / `1.0.0→1.0.1`;三者 `updated_at → 2026-09-15`
- `README.md` 模块表:3 行版本号校正(原 v2.8.0/v1.0.0/v1.0.0)+ decision-method 素材库计数 `U1-U12/A1-A13/X1-X8 → U1-U28/A1-A25/X1-X14`(已拆 `references/`)
- 修 `handoff-guard.sh` **两处「双引号内未转义反引号」**(L45 / L127):被 shell 当命令替换执行 ⇒
印刷出来变成「必须 才算完成;」+ 每次抢锁往 stderr 抛 `command not found`。**恰坏在「教锁纪律」那句话上**,命令名消失 ⇒ 读的人无从照做
**新技术判据(已写进 MEMORY §三)**
- ⚠️ **判行尾只能信字节级**:`grep -c $'\r$'` 在本机把**纯 LF** 文件误报成"全部带 CR"(本轮先据此得出错结论,
被 Python `b.count(b'\r')` 推翻)。实测分布:**BRIEF / README / `skills/**` / `.workbuddy/memory/**` = 纯 LF**;
**`INDEX.md` = 历史遗留混合**(裸 CR ~472 + 裸 LF ~102 + `\r\n` 双 CR ~120)⇒ 动它按字节处理
- 技能归档**验收四件**:① 两副本 md5 一致 ② 镜像 md5 一致 ③ `README.md` 模块表 / `INDEX.md` 登记行跟着改 ④ 七件套
**验收(全部实测)**
- 8 个文件(3 SKILL + 3 references + 1 script + README)两副本 md5 **全一致**,行尾保持纯 LF
- 镜像就位后 md5 一致;权限 **600 / 700 root:root** —— ⚠️ **README 服务器现状即 600(规范文字写 644)
⇒ 按 R5「权限只准收窄」未放大**;原件已备份 `/opt/dsh/backups/docs-skills/`(TS `20260915_145751` / `_145933`)
- 七件套:`manifest` / `archive-index`(**只读模式**,自报「表内容与 INDEX.md 一致」)/ `audit` / `consistency` /
`shrink-guard` / `search` 全绿(退出码 0)
- `docs-sync-check`:本次 5 个文件**已离开差异表**(一致 165 → 169);剩余 ❌ **全是别人的在途**
**提交**:`391495a`(4 文件)+ `82d3e49`(脚本修复)—— **只 add 自己改的 5 个文件**;**未 push**(§4 提交边界)
**没动(别人的 lane ⇒ 只报告)**:`INDEX.md`(T01 在改)· `BRIEF.md` / `DEPLOY-本部署.md` / `交接单/README.md`(T08)·
`skills/dsh-opensource-release/SKILL.md`(导出会话)· `docs-manifest.json` · `04-100` · `交接单/T08-*`
**顺带办完**:工作区 `MEMORY.md` **15.5 KB → 12.0 KB(12,271 B)** —— 注入超限被截断 ⇒ 整编:
合并重复条目、§四 与 PLAYBOOK 去重(章节标题一一对应)、状态更新为「T08 在途」、新增行尾判据。
原名备份 = `.workbuddy/tmp/MEMORY.md.bak-pre-shrink-20260915`(回滚 = cp 回去)。关键项抽查**零丢失**。
**未决 / 下轮**
1. `README.md` 技能表**第 4 行** `dsh-feature-first` 仍写 `v1.0.0`(实际 **1.4.0**)—— 不在本次范围,未动
2. `INDEX.md` line 151 的 `U1-U12 / A1-A13 / X1-X8` 计数陈旧(同因,**未动**,避免与 T01 会话撞同一文件)
3. `UserPromptSubmit` 探针定论仍**待完全重启**后读 `.workbuddy/stop-dialog-guard.log`(有日志 → 切 `inject`)
4. 本次脚本与备份在 `.workbuddy/tmp/`:`sync-skill-archive-20260915.py`、`bak-skill-sync-20260915/`
---
## 16:40–16:53 新增交互规则「待确认 / 待决策内容放最后 + 有序段落」;并沉淀「跨载体扫描」
**用户原话(两段,第二段补全)**
1. 「**ai会话 要把需要我确认或决策的内容放在 最后,别隐藏在回复内容中间**」
2. 「**是能根据决策方法 自行决策的就自决策继续处理,不能决策的问题和需确认内容放在回复的最后,按照有序段落展示**」
**关键发现:钩子文案与新规则直接对撞**
`scripts/stop-dialog-guard.py` 的 `REASON` / `CONTEXT` 原写「…**不要在结尾甩问题**」——
会被读成把「**位置**」也一并否掉,与用户要求**正相反**。
裁决:**用户管位置(放最后),钩子管形态(禁征询句)** ⇒ 二者不冲突,但文案必须改写。
(`user_prompt_mode` 里 `tail = tail_lines(text, 1)` ⇒ 钩子只看**最后一行**,故"末节用陈述句列选项"不会触发 `RE_BAN`。)
**一条规则 → 6 个载体全改(只改一处 ⇒ 其余立刻自相矛盾)**
| 载体 | 改了什么 |
|---|---|
| `dsh-feature-first` 1.4.0→**1.5.0** | §5.1 骨架 ③④ **对调**(拍板项 = 末节)+ 骨架改**逐条编号**;§5.3 三条→**四条铁律**(新增铁律 4;铁律 3 标注"禁的是**形态**");§5.4 硬约束 六条→**七条** + 骨架表同步 + 反模式 十条→**十一条**;§6 自检加第 12 条 |
| `scripts/stop-dialog-guard.py` | `REASON` / `CONTEXT`:「不要在结尾甩问题」→「放到**最后一节**、且**逐条编号**」 |
| 项目根 `CODEBUDDY.md §1` | 📌 口径改写(自决/位置/有序段落/陈述句四件事)+ 排版指针行同步 |
| 用户级 `~/.workbuddy/MEMORY.md` | 跨项目指针同步 |
| `dsh-decision-method` 2.7.1→**2.7.2** | `references/素材库-U-用户决策.md` U21:③④ 对调 + 追加「修正(2026-09-15)」 |
| `dsh-env-bootstrap` 1.0.1→**1.0.2** | `references/常驻规则-快照.md` **重生成**(`--snapshot`;权威方向单向,勿手改),`--check` RC=0 |
| `README.md` | 模块表 4 行版本号(含 feature-first 那行**此前的陈旧 v1.0.0 → v1.5.0**,本次因改动它而校正) |
**顺带修的真实缺陷(同类复发)**:`dsh-feature-first §6` 自检清单**编号乱序**(原 `11` 排在 `10` 前面)——
与上轮 `dsh-decision-method` 那处**一模一样**,都是"插入新条时插错位"。
**治本沉淀**:`dsh-change-workflow §5` 新增「**改跨载体规则时必做全载体扫描**」(2.9.1→**2.9.2**):
6 类载体清单(技能正文 / 项目根常驻层 / 用户级记忆 / **钩子文案** / **生成物勿手改** / 登记行)+
判据「改完再 grep,命中应**只在已改处**」+ 点名「**钩子文案最关键**(每轮都在教训 AI 该怎么做,
与规则打架危害最大)」+ 收口四件。
**验收(全部实测)**
- 四个技能共 **9 个文件**两副本 md5 **全一致**,行尾纯 LF(CR=0)
- 镜像:本轮共推 **9 件**(两批 TS `20260915_164907` / `20260915_165149`),就位后 md5 与本机一致;
权限 **600 root:root**(按现状,**R5 未放大**);原件全部备份 `/opt/dsh/backups/docs-skills/`
- 七件套(两轮各跑一次)**全绿**;`resident-rules.py --check` ✅ 关键规则齐备;`stop-dialog-guard.py` ast 语法通过
- `grep -rn "有序段落"` 回扫 ⇒ **只命中已改处**(无遗留矛盾表述)
- `docs-sync-check`:我的文件全在差异表外;剩余 ❌ 全为别人的在途
**提交**:`f975aad`(7 文件)+ `b0fd279`(2 文件);均**未 push**(§4 提交边界)
**锁**:两次 `--claim-exec` 都按硬判据校验(不接管道查退出码 + 复读 OWNER 断言),两次均 `--release-exec` + 断言目录消失
**未纳入(别人的在途,只报告不动)**:`INDEX.md` / `BRIEF.md` / `docs-manifest.json` /
`交接单/README.md` / `DEPLOY-本部署.md` / `skills/dsh-opensource-release/SKILL.md` / `04-100` / `交接单/T08`
**仍待办**:`UserPromptSubmit` 探针定论 —— 需**完全重启**后读 `.workbuddy/stop-dialog-guard.log`;
有日志 ⇒ `echo inject > .workbuddy/stop-guard-mode` 切 inject 模式(此后钩子会真的注入自检上下文)。