Files
dsh_ai1net_server/.workbuddy/memory/2026-09-下23.md
T

399 lines
47 KiB
Markdown
Raw Normal View History

# 工作日志 · 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 模式(此后钩子会真的注入自检上下文)。