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)、记忆修复前备份。
This commit is contained in:
admin committed 2026-09-24 07:51:03 +08:00
commit ce8e6ceed9
396 files changed
+66045

No files matched your search

+513
View File
@@ -0,0 +1,513 @@
# 工作日志 · 2026-09(第 5 片)
> ⚠️ **本目录日志已按【月】分片**(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-12.md
> **上一片**:`2026-09-下3.md` **下一片**:`2026-09-下5.md`
---
## T02 执行完毕(08:26-08:50)
**用户**:「确认开始执行」→ 执行 T02(文档库收尾)。
**任务 A 编号消歧 ✅**
- **脚本正则改了 8 处**(单子列 6 处 —— **漏了 `index_status`/`ref` 的键转换与 `%02d` 格式化**;键改字符串后 `%02d` 会 TypeError,必须同改)
- **闸门验证**(未改名先复跑):audit 唯一差异 = 新号 `37a` 被判悬空(预期);manifest 归一化后 11 条差异**全部更准确**(9 条零填充 `1`→`'01'` + `03` 的 refs 4→2 因单子示例文本被 `int` 误并 + `16` 的 refs 24→25 因去掉 `\b` 修复漏匹配)
- **`git mv` 改名 4 份**(git 识别 R 重命名、历史保留)+ 4 个标题号改写
- **引用修正 28 处 / 14 文件**(单子估 27/13 **偏少**):37a 7 / 37b 1 / 38a 9 / 38b 6 + 53 自身 3 处描述改写 + T02 示例 2 处
**任务 B INDEX 瘦身 ✅**:**28,809 → 7,468 字符**(-74%;后续微调最终 **7,583**);明细表压三列、删"路径/日期/证据"列;§三/§四 精简;§五/§六 保留
**事实校正 8 + 1 处**:L6("服务器唯一源 / 脚本已删除" → 双端模型 + 脚本在用)|L7(本机工作区**写反了**)|L8 更新|§二 重复行合并|缺号 48|§五 HEAD `8355e99`→`ebe8075`|§六 下一号 20→**61**|**另修 README 技能工作副本路径** → **`E:\ProgramData\.workbuddy\skills\`**(`.workbuddy` 已迁 E 盘)
**验收 6/6**:A audit exit 0|B 7,468|C items 78 + `37a/37b/38a/38b` 有 refs/tier|D 裸旧号 **0**|E 双端一致 **108/108**|F T01 仍"待办"
**归档**:T02 → `archive/交接单-已完成/`(用 `mv`,因 `交接单/` 未纳管 git)+ 交接单 README 状态行 + INDEX §四 登记
**⚠️ 协作发现**:**另一会话在活跃工作** —— 08:36 新增 **T03**(`plugin_package` 7 插件整合投放)并更新交接单 README(**它已把 T02 标为"已完成"并留"待归档"待办** → 协作良好);**T01 决策点 1 我 07:16 写的"已定"完整保留**(无冲突)。
## 协作问题:两会话并行写入(08:50-09:10)
**用户问**:「两个会话同时执行造成冲突,如何解决比较好」。
**诊断(实证)**:
- **根因不是"合并难",而是"并行写没有互斥"** —— 现有约定(交接单 README §三 7 条)只覆盖「**同一单子**的冲突域」→ **跨单子仍会撞共享文件**(`INDEX`/`README`/`BRIEF`/`03-路线图`/`交接单 README`/`SKILL.md`)
- **且**:文档库 **HEAD 停在 `43e4ae9`(档案 56)+ 未提交 25 项** → **长期不提交 = 零冲突检测能力**(无法靠 pull/merge 发现撞车)
**今天实际发生**:
| 文件 | 另一会话 | 我 | 结果 |
|---|---|---|---|
| `T01-…md` | 07:22 改 | 07:16 改(决策点)| ✅ 我的保留(**侥幸**)|
| `交接单/README.md` | 08:36 改(登记 T03)| 08:41 改(T02 归档行)| ✅ 双赢(**我读了它的最新版再改**)|
| `T03-…md` | 08:36 新建 | 08:39 scp 同步 | ✅ 无冲突 |
| `INDEX.md` | 未动 | 08:41 **整文件 Write 重写** | ✅ 无冲突 —— **但这是最危险的一步** |
**方案**:
1. **已落地** ✅:`交接单/README.md` §三 新增**第 0 条「先确认没有别的会话在写同一文件」**(4 步:① 查 git 状态 + `docs-sync-check.sh` ② 看 mtime 比自己上次见到的新 = 别人刚动过 → **先读再改** ③ **共享文件只用 Edit 精确替换、禁整文件 Write** ④ **改完立即 commit(本机,不 push)**);已同步双端(md5 一致)
2. **建议分工(单一写者)**:`交接单/*.md` 新单 = 规划会话;`交接单/README.md` 状态表 = 执行会话;`04-调整方案/` + `INDEX` + `BRIEF` + `README` + `skills/` = 执行会话;`03-路线图` = 执行会话(规划会话只读)
3. **建议工具**:**文档库 git 提交常态化**(每次改完 commit、**不 push**)→ 下一方能看到"谁刚改了什么"、冲突可检测;可选给 `docs-sync-check.sh` 加"近 10 分钟改动"提示
4. **今天验证有效的一条**:**共享文件用 Edit(精确 old→new)而非 Write** —— 别人改了同一处时 **Edit 会失败** = **天然的冲突检测**(我今天两次 Edit 失败正是它起作用:一次是我记错内容、一次正是需要先读再改)
**⚠️ 待用户决策**:是否让文档库**开始提交**(现有 25 项未提交);提交边界仍是"未明确要求不 push"。
## 会话收尾盘点(08:49-09:15)
**用户问**:「需要执行的任务完成了吗」。逐项核对本会话全部指令。
**⚠️ 重大发现:另一会话不仅在做 T03,还独立写了一个比我更强的防冲突工具**
- **`scripts/handoff-guard.sh`**(它 08:52 新增,只读 + `--claim/--release`):把"防冲突"从**文字约定**变成**一条命令 + 退出码**——① 占用锁硬判定 ② 越界改动(推送前,防 `git add -A` 带上别人的半成品)③ 热点提示 ④ 双端一致性。**它明确指出「mtime 只作提示、不作判定(分不清谁改的)」** —— 这点比我的方案**更严谨**(我把 mtime 当判据)。
- 它的占位机制:`mkdir 交接单/.doing-<单号>`(mkdir 原子:成功=拿到,`File exists`=别人在做 → 停手),完工 `rmdir`。
- 它 08:52 占过 T03、08:53 释放;`交接单/README.md` 被它连续改三次(08:41→08:45→08:53→最终 11,048 字节)。
- **它保留了我在 08:41 加的「写者协议第 0 条」并整编进它的体系**(grep 命中 1);并把我写的 T02 成果准确登记为「✅ 已完成并归档(2026-09-12,并行执行会话)」,还记了它自己的事故:**"把我已归档移走的 T02 又推回服务器,制造幽灵文件"**。
- **结论:防冲突应以它的 `handoff-guard.sh` 为准,我的文字约定收敛过去**(两套并存反而易混)。
**本会话我的任务盘点(全部完成,除 T01)**:
| 用户要求 | 状态 | 产出 |
|---|---|---|
| 内存为何占这么多 | ✅ | 62 MiB 全员共享 / 私有 106~117 MiB 分解 |
| 内存优化 + 512 能否降 | ✅ | 档案 58(NODE_OPTIONS + 编译缓存 + 384M,已上线)|
| 42 文件删除根因 | ✅ | USN 时间线 + 排除 git/杀软/文件系统 |
| 教训写红线 | ✅ | R7/R8(文档库 README+SKILL、工作区 MEMORY、**用户级 MEMORY**)|
| 越界自查 | ✅ | 5 项越界 + 7 项流程缺失 |
| 官方包核验 | ✅ | 24,923 文件全为 09-08,**零改动** |
| WorkBuddy 迁 E 盘 | ✅ | 脚本 + 用户执行 + 验收零遗漏 |
| 待办盘点 | ✅ | 全景清单(A/B/C/D/E/F 六类)|
| 插件页列表加高 + 200px | ✅ | 已上线;**档案 61 已补**(08:49,2914 字节)|
| A:ensure 脚本姿势对齐 | ✅ | 2 脚本(跑过 skip 验证,未中断用户)|
| B:T02 | ✅ | 消歧 + INDEX 28,809→7,468 + 归档 |
| C:同步缺口 | ✅ | 交接单 + 脚本(双端一致)|
| 冲突解决方案 | ✅ | 写者协议(已被对方整合)+ **采纳其 handoff-guard.sh** |
| **T01**(实例内「我的技能」)| ⏳ **未做** | 决策已定(扩展 business-plugins);**按串行要求等 T03 完成** |
**未提交**(双方均未提交):文档库 25+ 项、代码仓库 11 项。
**最终状态**:`docs-sync-check.sh` → **双端一致 110/110** ✓;`docs-audit.py` 退出码 **0** ✓。
## 提交完成 + 插件目录缓存可见化(09:0x-09:30)
### 提交(用户「确认提交和执行」)
| 仓库 | 提交 | 结果 |
|---|---|---|
| 文档库 | `96f8ef8`(档案 57-61 + T02 + handoff-guard)→ `5d2a5de`(档案 61 二次修正)→ `be42155`(档案 62)→ `b06f7dd`(manifest 刷新)| ✅ 工作树 0 项 |
| 代码仓库 | `3567226`(内存优化/重连动画/分区改名/列表自适应 + 4 新脚本)→ `0e141a4`(目录缓存可见化)| ✅ 工作树 0 项 |
**均只 commit、未 push**(按约定推送需用户明确说)。
**踩坑**:① git 是 Windows 原生的,`git commit -F` 必须给 **Windows 路径**(MSYS `/c/...` 不认);② 代码仓库**没配 git 身份** → 沿用历史提交者 `maogeigei <[email protected]>` 设了**仓库级**配置。
### 档案 61 的两次修正(插件页列表高度)
用户连报两次:①「列表都超出屏幕了」②「还是有页面滚动条,应该只有列表滚动条才对」。
- **根因**:第一版 `clamp(560px, 100vh-260px, 900px)` + **`padding-bottom: 200px`** ⇒ 页面总高 1252px > 视口 900px。
- **第一轮修正**:列表改 `calc(100vh - 420px)`、移除 padding-bottom。**仍然滚动** —— 因为我**只算了列表上方(372px),漏算下方 116px**(按钮行 50 + card padding 18 + **`#view` padding-bottom 48**)。
- **第二轮修正(最终)**:`max-height: calc(100vh - 520px)`(372+116=488,再留 32px 余量)。视口 900 → 列表 380px。
- **教训**:算"视口自适应高度"必须**上下都算**,不能只看列表上方。
### 档案 62:插件目录缓存状态可见化(用户「拉取的官方目录可以缓存,不用每次都拉取,增加一个主动刷新开关」)
**取证结论:功能早已存在,只是完全看不出来** —— `src/web/routes/whitelist.ts` 里已有:
- 磁盘缓存 `<dataRoot>/whitelist-cache/index.json`|**TTL 6 小时**(TTL 内 `getIndex()` 直接返回缓存、**不联网**)|`POST /api/plugins/whitelist/refresh`(强制拉取)|拉取失败降级用旧缓存并标 `stale`|`GET` **已返回 `fetchedAt` + `stale`**。
**前端三处误导**:① 加载提示写「**拉取**官方目录中…(首次约数秒)」② `wlInfo` 只显示 `stale`、**不显示 `fetchedAt`** ③ 按钮叫「刷新清单」看不出是"绕过缓存重拉"。
**改动(仅前端 4 处,13 增 4 删;后端零改动、无需重启)**:
- 按钮「刷新清单」→「**重新拉取目录**」+ title 说明("平时打开本页不会下载,直接读本地缓存")
- 新增 `relTime()`;`wlInfo` 增显「**目录缓存更新于 X 前(6 小时内直接复用,不联网)**」
- 加载文案 → 「加载目录中…(首次会从官方站下载一次,之后读本地缓存)」
- 流程提示明确化
**验证**:门户 `curl` 命中;静态文件即时生效。**已提交 `0e141a4`**。
**待确认**:若还要「自动更新:开/关」toggle(关掉后连 TTL 到期也不联网)→ 需给 `GET` 加 `cacheOnly=1` → **后端改动 + 重启平台(R8 须知会)**,本次未做。
### 协作状态(仍在进行中)
- **另一会话持续活跃**:`交接单/README.md` mtime 到 **09:23:41** 仍在变;它还写了 `scripts/handoff-guard.sh`(并行冲突预检:占用锁/越界改动/热点/双端一致性,**明确"mtime 只作提示不作判定"**,比我的文字约定严谨)。
- **一次虚惊**:收尾三件套报 audit 退出码 1,悬空 `['3','6']` in `交接单/README.md` → 复现时已**命中 0**、重跑 audit **退出码 0** ⇒ 那是**对方改文件过程中的过渡状态**,非我的问题。
- **我的真问题**:刷新了本机 `docs-manifest.json` 却**忘了 scp** → 对账报"内容不一致 1";已补传并提交。
- **最终**:`docs-sync-check.sh` **双端一致 112/112** ✓、`docs-audit.py` 退出码 **0** ✓。
- **防冲突**:后续应以对方的 **`handoff-guard.sh`** 为准(我的文字约定已被其整合)。
## ⚠️ 事故 63:我的"清理残留"断掉了 profile 依赖(09:28-10:00)
**用户报障**(附截图):「设置中功能管理 插件信息需要有限显示插件用途,还有**刚才启用插件失败了,失败了插件状态还是已启用**」。
### 用户的两个需求(均已改,**待实例重启生效**)
1. **列表显示插件用途** —— 改 `poc/business-plugins/lib/client.js` 渲染:名字行下方加 **description 副行**(数据来自 `/api/plugins/mine` 的 `description`,实测有值;缺失则不渲染)。**版本 0.2.2 → 0.2.3**。
2. **失败后状态未回滚(bug)** —— `pollTask` 的**成功分支有 `load()`、失败分支只 `setMsg`** ⇒ 本地 `plugins` 停留在用户勾选后的样子,徽章仍显示「已启用」,与「安装失败」自相矛盾。**修法:失败分支补 `load()` + 文案"(已回滚到改动前的状态)"**。实测 `/api/plugins/mine` 当时返回 `enabled: false` ⇒ **后端回滚是好的,纯粹是前端没刷新**。
### ⭐⭐ 但"安装失败"的真根因是我自己造成的(重要教训)
**故障链**:
1. **档案 60** 我把 ws 里的安装残留 tgz 移入 trash(含 `business-plugins-0.2.2.tgz`、`workspace-scoped-picker-0.1.4.tgz`);
2. 而 profile 的 `dependencies` 正写着 **`file:<ws>/business-plugins-0.2.2.tgz`**、**`file:<ws>/workspace-scoped-picker-0.1.4.tgz`**;
3. ⇒ 此后**任何 `pnpm add` 都在解析阶段 ENOENT 失败**(实测两个用户全中,用户侧就是「安装失败」)。
**这正是档案 57 §五.2 预警过的隐患,我清理时没想到会引爆它。**
**修复(自愈,不是把 tgz 放回 ws)**:给 `ensure-biz-plugins.cjs` 加 **`pruneBrokenFileDeps()`** —— 安装前遍历 `dependencies`,**只删 `file:` 且目标确实不存在**的条目(registry 依赖不动),随后 add 新包会写入正确的新路径。实测两用户各清理 2 个断裂依赖后**安装成功、`ws 保持干净`**。
### ⚠️ 连带发现并修复一个更严重的问题(R5 安全收敛失效)
`prune` 清掉 picker 的 dep 后,**`reconcileBundles` 的过滤规则**(`bundles.filter(b => b.startsWith('@deepseek-ai/') || deps.includes(b))`)把它**从 bundles 里一并剔除** ⇒ **`bundles` 从 5 掉到 4** ⇒ **档案 18 的「目录选择器收敛为仅见自有目录」(R5 安全收敛)失效**。
而 **`ensure-workspace-picker.cjs` 没有 reconcile 逻辑**(且它检测到"已装"就 `continue` 跳过),**补不回来** ⇒ 手工修:直接改 profile 的 `package.json` **补回 dep + bundles**(dep 指向 `<home>/.dsh-stage/…` 而非 `/opt/dsh/artifacts/` —— 后者是 `drwx------ root`,用户读不到,违反档案 52 规范)。
**最终验证**(两用户一致):`dependencies` 3 个包全指向 `.dsh-stage` ✓ | `bundles` 5 项(含 3 个 `@dsh-local`)✓ | `node_modules/@dsh-local` 3 个 ✓ | 属主归用户 ✓。
### 待办(未做)
1. **`workspace-scoped-picker` 脚本同样需要 `pruneBrokenFileDeps` + `reconcileBundles`** —— 否则下次它升级时会重蹈覆辙(本次是手工修的)。
2. **实例重启才生效**(client bundle 在实例启动时打包)—— 两处前端改动待生效;**按 R8 须先知会**。
3. **档案 63 未写**(本次事故 + 两处 UI 修改);**代码未提交**。
**教训**:**移动/清理任何"看似残留"的文件前,必须先确认没有 profile / 配置指向它**(`grep -r "<文件名>" <userRoot>`)。这次是我在档案 60 里"顺手清理"埋的雷。
## T03 开工:前置核查完成(09:49-10:05)
**用户指令**:「确认执行 按照串行顺序」→ 按 README 建议顺序 **T03 → T01 →(容量治理新需求)**,从 T03 起。
**① 状态确认(无冲突)**
- **无锁** ✓;单子状态 `⏳ 待执行(已规划,未开工)` ✓;产物目录**无 `dsh-plugin-mcn-suite`** ✓ → 未动工
- 另一会话近 25 分钟在改 `skills/dsh-decision-method/SKILL.md`(**不是 T03**)✓
- **已用对方工具占锁**:`bash scripts/handoff-guard.sh --claim T03 "exec-session-A(本会话)"` ✓
**② 关键发现:5 个决策点用户已全部拍板**(单子 §四 开头即写明,**不必再问**)
1. `social-workbench` **不进包**(Windows 本地服务 + `127.0.0.1` 被封 → 平台必然不可用)
2. `voxemw-cloud` **进包**(凭据走 env、无硬编码)
3. 入口形态 **A**(保留 `__mcnEntries` 多入口并列)
4. **业务技能随包投放**(用户明确要求「不分开管理」→ 推翻规划会话原"走门户分开投"的建议)
5. 包名 **`dsh-plugin-mcn-suite` v0.3.0**(版本必须每次递增)
**③ 结构与工作量的关键认知(单子 §2.1)**
**7 个包不是平行的,而是「1 个宿主壳 + 6 个功能页」**:`dsh-plugin-mcn` 注册 25+ 条 `/mcn/api/*` 路由、提供 `window.__mcnEntries`(功能页注册表)与 `__mcnNav`(页内路由),其余 6 包全靠往它注册;三个 douyin 包的 host 面只有 9 行空壳。⇒ **拆开"逐个启用"本身违背设计**(缺 mcn 则其余是死链),**整合是回归正确形态**。
**④ §五 平台化 P0 清单(8 项)**:① `homedir()/.dsh` → `$DSH_HOME`(mcn 14 处 + mcn-schedule 3 处)② 技能路径硬编码 → **只报技能名** ③ `spawn("powershell")` = Windows only → Linux 改法 ④ MCP `npx -y myai-mcp` 每次现拉 → 预装 ⑤ `.bak` 剔除 ⑥ 上传扫描 P0 自检 ⑦ **技能原文凭据扫描**(`scripts/mcp-config.json` 实测含 `MYAI_FEISHU_APP_ID=cli_a84d0a47f93e1013` + 私域 URL)⑧ §五#8 层级误判已更正(技能实际有 `subskills/mcn-data-insight/subskills/douyin-top-account/`,规划会话首轮 `-maxdepth 5` 差一层误判"缺失")
**⑤ 第 1 步「前置只读核查」完成** —— 事实清单:
| 项 | 单子预期 | 实测 |
|---|---|---|
| 技能树 `SKILL.md` / 文件数 / 体积 | 36 / 711 / 11 MB | **36 / 711 / 11 MB** ✓ 全对齐 |
| 一级子技能 | 5 个 | browser-harness、mcn-data-insight、mcn-dou-analysis、mcn-script-review、mcn-video-prompt ✓ |
| 门户候选池 | (需下架旧 7 包)| **只有 2 个第三方包**(`@liustack/modlens`、`dsh-univer-office`,均禁用)→ **7 个 MCN 包从未上传,切换成本更低** |
| 平台代码 HEAD | 取当前值 | `0e141a4` |
| `/opt/dsh/artifacts/` | 看命名与 `package/` 前缀 | business-plugins-0.2.3 / portal-entry-0.5.1 / workspace-scoped-picker-0.1.4 ✓ |
| 技能树源位置 | 单子未写明 | **`C:\Users\Administrator\.dsh\skills\mcn-short-video`**(**不在 `plugin_package` 下**;包内 `skills/` 是"要移进去的目标")|
**⚠️ ⑥ 前置核查发现的新风险(单子未提)**:**技能树 `~/.dsh/skills/mcn-short-video` 不在任何 git 仓库内** ⇒ 裁剪与改动**不可追溯、无回滚点** → **动手前必须先备份**。
**⑦ 剩余工作量(诚实评估)**:单子 §六 共 **13 步**,已完成第 1 步;剩余 12 步(建包骨架 → 移植 host 面 9 模块 → 合并 client 面 → P0 适配 8 项 → smoke → 打包 → 扫描 → 上传 → 切换 → 实测验收 → 归档)+ §6.1 技能随包 4 个阶段 + §6.2 两处文档漂移,**属数小时级工程,且含生产切换操作**。
**⭐ 建议**:**T03 交专门会话执行**(本会话已连续数十轮,上下文臃肿;T03 涉及打包/上传/实例切换等生产操作,需要清醒上下文以保证质量)。**锁已占位**,新会话 `bash scripts/handoff-guard.sh` 可直接看到占用状态并续做。
## 新建技能:dsh-decision-method(决策方法论)(09:32-)
**用户要求**:把本工作区所有会话里关于「改造 dsh 服务 / 优化功能交互 / UI 界面」的**用户有效决策 + AI 有效决策 + 如何确认最优解**,整合成一个**思考决策方法**的 skill。
**素材来源(只读)**:`04-调整方案/` 62 份档案(重点读 16/31/45/56 + 各档案头部「触发/用户裁定」)+ 五天工作日志(09-08~09-12)+ `BRIEF.md` / `交接单/README.md` / `06-工作台UI规范.md` / `README.md` / `INDEX.md`。
**注**:`conversation_search` 本次返回 **0 命中**(接口无结果),改走本地档案+日志取证,可靠性更高。
**产出**:`E:\ProgramData\.workbuddy\skills\dsh-decision-method\SKILL.md`(用户级技能,agent_created)。
结构 = 决策素材库(用户有效决策 **U1–U12** / AI 有效决策 **A1–A13** / 反例 **X1–X8**)+ **确认最优解**(判定矩阵 8 问 + 拍板前十问 + 验收口径分级 L1–L5)+ 决策流程十步 + **交互/UI 改造专项清单** + 决策语言对照表 + 决策记录模板 + 三层沉淀。
**与既有技能分工**:本技能管「怎么想、怎么定」,`dsh-change-workflow` 管「怎么落地」;先定案再执行。
**未做**:未 scp、未同步到 `dsh-server-docs/skills/`(技能必须本地加载才有用;入文档库归档需用户明确要求)、未 commit。
## 技能入服务器归档 + 加载确认(09:40-09:55)
**用户要求**:「同步到服务器,并且加载到 workbuddy skills目录中」。
### A. workbuddy 技能目录(本就在位,已核)
- 位置 = 用户级 `E:\ProgramData\.workbuddy\skills\dsh-decision-method\SKILL.md` —— **该目录即 WorkBuddy 扫描的技能目录**(与 `dsh-change-workflow` 同级)。28,029 B / 327 行 / UTF-8,frontmatter `name` 与目录名一致。
- ⚠️ **新技能不会在本会话的可用技能列表出现**(该列表在会话启动时构建)→ **需新开会话才会被识别**。
- 工作区级 `.workbuddy/skills/` **不存在**(工作区 `.workbuddy/` 下只有 `memory/`)→ 按默认只放用户级。
### B. 服务器归档(已完成,逐文件 md5 双端一致)
- 新增归档副本 `dsh-server-docs/skills/dsh-decision-method/SKILL.md`(与工作副本同 md5 `ee1861bb…`)
- scp → `/opt/dsh/docs/skills/dsh-decision-method/SKILL.md`,目录 **700** / 文件 **600**(对齐 `dsh-change-workflow` 的 drwx------ / -rw-------)
- 同批推送:`INDEX.md`(§二 加技能行)、`README.md`(模块一览加技能行)、`docs-manifest.json`(复跑刷新,83 条目)
- **对账 113/113 一致**(唯一"仅本地"= 并行会话刚占用的锁 `交接单/.doing-T03/OWNER`,非我的文件;**未用 `--push` 整批,逐文件 scp 避开幽灵文件**)
- **未 git commit / push**(用户未要求;红线)
### C. 途中修掉自己引入的一个悬空引用(重要)
- 首跑 `docs-audit.py` **退出码 1**:`skills/dsh-decision-method/SKILL.md 引用了不存在的档案号 ['2']`
- 根因:审计正则 `档案\s*(\d{1,2}[a-z]?)` 的 **`\s*` 会跨行** —— 我写的 `…固化进 skill 或档案` 行尾的"档案" + 换行后的列表项 `2.` 被读成裸号 `2`
- 修法:改写为 `…固化进 skill,或写进 \`04-调整方案/NN-*.md\` 改造档案(可复用的留 skill,一次性的归档)`(行尾不再紧邻数字);**两份副本同步改**
- 结果:`docs-audit.py` **退出码 0、结论「无 P0 级问题」**
- 📌 **沉淀:这是文档库已记坑(`档案`+字符类)的变体 —— 凡「档案」后换行紧跟有序列表数字都会误报。写文档时不要让「档案」落在行尾。**
### D. 发现但未处理(按 R7 先报告、后动手)
1. **`scripts/docs-manifest.py` 打印阶段崩溃**:`TypeError: %d format: a real number is required, not str`(第 100 行 `'%d' % i['num']`)—— T02 把 `num` 键改成字符串(支持 `37a`)时**漏改这一处**。JSON 在打印前已写出(条目 83、可解析),故不阻断收尾;**一行修复(`%d` → `%s`)即可,未擅自动手**。
2. **`INDEX.md` 头部「最后核对」数字已过期**:`md 78 份`(实测 **83**)、`档案已至 60`(实测 **62**)、代码 HEAD `ebe8075`(代码仓库今晨已到 `0e141a4`)。与本次改动无关,**未一并改**(避免混入无关修正)。
3. 服务器 `skills/dsh-change-workflow/` 下有一份本地没有的 `SKILL.md.bak-20260911-2055`(备份残留,对账不计)。
## 用户「确认无误后处理」→ 两项修正已落地(10:04-10:10)
**用户指令**:「确认无误后处理」(授权我上一轮报告的两项)。**先核实事实再动手**,结果**推翻了我自己上一轮的一个判断**。
### 核实(不凭记忆)
| 待改项 | 我上轮的说法 | **实测** | 结论 |
|---|---|---|---|
| md 份数 | 78 → 83 | `find` 计数 = **83** | ✅ 应改 |
| 档案已至 | 60 → 62 | `04-调整方案/*.md` = 64 文件(含 README)、最大编号 = **62** | ✅ 应改 |
| 代码 HEAD | 「今晨已到 `0e141a4`」→ 想改成它 | **服务器 `/opt/dshs` HEAD 就是 `ebe8075`**(权威值,未变);`0e141a4` 是**本机镜像**的 HEAD | ❌ **我错了 → 不改**(INDEX 原本就对) |
**代码仓库真实状态(重要,此前未记)**:本机镜像 `D:\github\dsh_shenxian` = `0e141a4`,**包含**服务器 HEAD `ebe8075` → 即 `3567226`/`0e141a4` 两个提交**只在本机、服务器还没落**;服务器工作树有 **7 M + 4 ??** 未提交(`portal.html`/`orchestrator.ts`/`proxy.ts`/`poc/*`/`ensure-*.cjs`)。→ **代码侧存在"本机领先、服务器未落"的落差**,属既有状态,本次未动。
### 已改(两处,均为最小改动)
1. **`scripts/docs-manifest.py` 第 100/103 行**:`%-3d` → `%-3s`(`num` 现为字符串,支持 `37a`;T02 漏改的就是这两处)。**行尾保持 LF(0 CRLF / 104 行)**。
- 验证:脚本**完整跑通、退出码 0**,hot 30 / warm 29 / cold 4 全部正常打印(`档案 38a` 正确显示)。
2. **`INDEX.md` 头部「最后核对」**:`md 78 份` → **83**;`档案已至 60` → **62**;`代码 HEAD ebe8075` **保持不变**(已核实为服务器权威值)。
### 验证与同步
- `docs-audit.py` → **退出码 0、结论「无 P0 级问题」**
- `docs-manifest.json` 内容**未变**(md5 仍 `10c3b9c4…`)→ 无需重推
- scp 推送 `scripts/docs-manifest.py`(755) + `INDEX.md`(600);**md5 双端逐文件一致**(`c1bf95be…` / `c124285c…`)
- 双端对账:**一致 113 / 内容不一致 0 / 仅服务器 0**(唯一"仅本地"= 并行会话的锁 `交接单/.doing-T03/OWNER`)
- **未 git commit**(用户未要求)
### 顺带发现(按 R7 只报告、未动手)
- `docs-sync-check.sh` **会把占用锁目录 `交接单/.doing-<单号>/OWNER` 算进"仅本地"** → 只要有会话持有锁,对账就恒报「存在差异 ❌」,容易被误读成"有文件没推"。建议把 `交接单/.doing-*` 加入排除(与 `handoff-guard.sh` 的【2】已有的 `grep -v` 一致)。**一行改动,未做。**
## 复盘「用户时间被技术问题吃掉」+ 新建 `dsh-feature-first`(11:16-11:35)
**用户原话**:「复盘工作空间内所有会话,感觉现在大多数时间都在沟通技术问题,我想把精力放到平台功能如何搭建上,AI 根据平台功能需求自己思考和解决技术相关问题 如何才能实现」。
### 复盘(取证,非估算)
对含「触发」字段的 **42 份**档案按来源分类(命令:`grep -Hn "触发" 04-调整方案/*.md`):
| 类别 | 份数 | 占比 |
|---|---|---|
| 用户的功能/交互需求(用户主场) | 15 | 36% |
| **技术类**(用户被拉进技术判断 / AI 技术排查) | 17 | **40%** |
| **用户报障**(用户只能看到现象,被迫当测试) | 10 | **24%** |
⇒ **技术 + 报障 = 64%**。
**五个根因**:① 技术问题被"决策化"上抛(用户没有判断依据只能点头);② 需求缺"规格层"(用户说现象 → AI 直接跳技术方案,中间规格没沉淀);③ 报障驱动(输入大量来自"坏了");④ 没有"技术默认值"= 没有 AI 自主决策的授权边界,每次重新分析重新上抛;⑤ 交付用技术语言(commit/文件/md5),用户只能靠技术语言参与验收。
### 落地:新技能 `dsh-feature-first`(功能优先协作协议)
核心 = **把"事前请示"改成"默认自主 + 事后可推翻"**。六块内容:
1. 用户输入收窄为**功能卡 4 问**(谁用 / 在哪用 / 做什么 / 怎样算成功)
2. **AI 自主决策 9 类白名单(永不问)**:技术选型 / 实现路径 / 命名结构 / 性能调参 / 部署同步 / 排查方法 / 版本依赖 / 兼容降级 / 文档技术内容。口诀 =「用户能否从功能视角判断这个选项的好坏」——不能就是 AI 的活
3. **只上抛 2 类**:功能语义分叉(选项间有用户能感知的差别)+ 红线门禁(R5 扩大 / R7 批量 / R8 中断)
4. **上抛语言转换表(强制)**:禁止出现包名/环境变量/路径/commit/API 路径,必须改写成"你能感知的差别"
5. **报障闭环前置五条**:错误给人话 + 等待有反馈 + 状态可自查 + 能自愈不报错 + 缓存状态可见。口诀 =「用户遇到这个情况会不会只能来问我」
6. **交付回执格式**:做了什么(功能)→ 你现在能看到什么 → **不用你决策的技术选择(已定,可推翻)** → 技术附录折叠
**双位置**:工作副本 `E:\ProgramData\.workbuddy\skills\dsh-feature-first\SKILL.md`(md5 `65e7531a…`)+ 归档副本 `dsh-server-docs/skills/dsh-feature-first/` → scp 到 `/opt/dsh/docs/skills/dsh-feature-first/`(700/600 ✅)。INDEX §二 + README 模块一览各加一行(**只放指针,不复制全文**)。
### 顺带校准:INDEX 头部「最后核对」绝对值已改成不易腐写法
- 实测:同日 83(10:04)→ 85(11:16)→ 87(11:22)**三次作废**(并行会话持续新增档案)
- 处置:**不再写死篇数/档案号**,改为「以 `python3 scripts/docs-manifest.py` 复跑为准」+ 代码 HEAD 给出取数命令(保留最后核对值 `ebe8075`);附一句实测证据说明为什么
- 理由:写一个明知数十分钟后就错的值,比不写更糟
### 本轮验证与同步
- `docs-manifest.py` **exit 0**;5 个文件 scp 后 **md5 逐文件双端一致**(SKILL.md / INDEX.md / README.md / docs-manifest.json / scripts/docs-manifest.py)
- 双端对账:**一致 114 / 内容不一致 0 / 仅服务器 0**;「仅本地 4」= **并行会话的 3 个新档案(64/65/66)+ 其占用锁**,非我的文件,不代推
- **未 git commit**(用户未要求)
### 发现(按 R7 只报告)
- ⚠️ **`docs-audit.py` 退出码 1,但不归属我**:`04-调整方案/64-接入AnySearch搜索provider.md 引用了不存在的档案号 ['63']` —— 并行会话跳号(62 → 64/65/66),64 里引用了不存在的 63。属其在建文件,**未替其修改**。
- 代码仓库落差(前一轮已记):本机镜像 `0e141a4` 领先服务器 `ebe8075` 两个提交未落。
## 让规则「默认生效」+ 补齐技术实现裁决顺序(11:45-12:05)
**用户两问**:① 能不能形成一套决策方法,后续技术实现让 AI 按方法找最优决策?② 如何让 workbuddy 的项目任务执行会话**默认**执行这套规则,**需要开启定时任务跟进吗**?
### 关键发现(真因):工作区 MEMORY.md 超限被截断
- 实测 `D:\AI技能\aliyun-dsh-server\.workbuddy\memory\MEMORY.md` = **10,242 字符 / 16,893 字节**
- **本次会话注入给我的内容只到 ~7,960 字符处被切断**(截断点正好落在「并发冲突防治」第二条 bullet)→ **R7/R8 红线、技能资产、实例机制全都没送达会话**
- ⇒ **"规则没有默认生效"的真因不是载体错,而是载体撑爆了**
**处置**:先备份 `MEMORY.md.bak-20260912-consolidate`(16,893 B)→ 重写为 **4,548 字符 / 7,939 字节**(原 44%,占推测上限 57%,有余量)。
新结构 = ①**默认工作规则(最前,含功能卡输入协议 + R1-R8 全量)** ②技能资产 ③仓库与推送约束 ④**现行事实→查单一来源(不再复制细节)** ⑤长期操作坑 6 条 ⑥实例关键机制 3 条。
> 被移出的细节全部**本来就有单一来源**(`BRIEF.md` / `INDEX.md` / `DEPLOY-本部署.md` / `06-工作台UI规范.md` / 各档案),故无信息丢失。
### 机制认知(回答"如何默认生效 / 要不要定时任务")
| 载体 | 是否自动注入 | 可靠性 | 用途 |
|---|---|---|---|
| **工作区 `.workbuddy/memory/MEMORY.md`** | ✅ 每会话注入 | **最高(但有长度上限)** | 默认规则、红线、约定 |
| `SOUL.md` / `USER.md`(用户级) | ✅ 每会话注入 | 高 | 全局姿势与用户偏好 |
| **技能**(用户级/项目级) | ❌ 模型按 description 判断触发 | 中(**是"按需",不是"默认"**) | 领域方法论 |
| `settings.json` | — | — | 已有 `sandbox.extraAllowWrite` / `enabledPlugins` / `claw`;**本项目未配 hooks** |
**结论:不需要定时任务** —— 定时任务解决"到点无人值守跑",解决不了"每次会话默认遵守"。默认生效靠**注入型载体**(MEMORY.md + SOUL.md),故本轮做的是 MEMORY.md 瘦身。
### 补齐:`dsh-decision-method` v1.0.0 → v1.1.0
新增 **§4.4 技术实现的默认裁决顺序(AI 自主用、不问用户)** —— 8 条按序自答的算法:
`① 既有机制能复用吗 → ② 有更小改动吗 → ③ 能用配置解决吗 → ④ 只改一层吗 → ⑤ 失败代价对称吗 → ⑥ 可验证吗 → ⑦ 是收窄还是扩大 → ⑧ 官方契约耦合面多大`
**两条硬约束**:③ 优先于 ②(能配置就不改码,改码要 build+重启会触 R8);任一条与红线冲突 → 红线赢。产出 = 写进档案「技术选择」段(含被否决选项与否决理由)→ 用户**事后可推翻、事前不被打扰**。自检清单加第 8 问。
同步:两份副本 md5 一致 `c5b3938e…`,已 scp 服务器(`/opt/dsh/docs/skills/dsh-decision-method/SKILL.md`),**双端一致**。
### 未做 / 待用户定
- **定时任务**:提议一个真正适合定时的用途(**每日/每周巡检**:双端文档对账 + `docs-audit.py` + 未释放的 `交接单/.doing-*` 占用锁 + 待办漂移)——今日已多次被这些坑到。**等用户点头再建**。
- 技能仍放**用户级**(`E:\ProgramData\.workbuddy\skills\`),未建项目级 `{workspace}/.workbuddy/skills/`(可选:让本项目的技能只在本项目可见)。
- 未 commit(用户未要求)。
## 「提问闸门」:在 AI 问用户之前强制先自判(11:54-12:10)
**用户原话**:「有没有办法 AI 问我决策时,能先根据方法自动判断,如果没办法判断我再决策」。
→ 要的不是"写进文档",而是**在提问动作发生的那一刻被拦住**。
### 机制:`PreToolUse` hook + matcher `^AskUserQuestion$`
**取证来源(权威)**:WorkBuddy 本地自带 CodeBuddy 官方 hooks 文档 `cli/dist/web-ui/docs/cn/cli/hooks.md`(27+ 事件,Beta);并用 grep 确认本机 CLI 构建**确实实现了** `PreToolUse` / `allowUntrustedFrontmatterHooks`。
**关键点**:`PreToolUse` 支持按**工具名**做 matcher,而 AI 向用户提问用的就是 **`AskUserQuestion`** 工具 → 可以精准拦在"问出去之前"。
- 事件触发:工具参数已生成、工具调用被处理**之前**
- hook `type: "prompt"` = 交给 lite 小模型做语义判断,返回 `{"ok": true|false, "reason": ...}`
- `ok:false` → **阻止该工具调用**,`reason` 传给 Agent(我)→ 我读到"这属于你自己该定的"就改为自判
### 已配置(`E:\ProgramData\.workbuddy\settings.json`)
```json
"hooks": { "PreToolUse": [ { "matcher": "^AskUserQuestion$",
"hooks": [ { "type": "prompt", "timeout": 30, "prompt": "<三分类判据>" } ] } ] }
```
prompt 让 lite 模型把提问分三类:**A 功能语义分叉**(选项间有用户能感知的差别)/ **B 红线门禁**(扩大权限·中断在线用户·批量>10 文件)→ 放行;**C 技术项**(选型/路径/命名/调参/部署/排查/版本/兼容/文档技术细节;**特征=出现包名·环境变量·路径·commit·端口·内存数值·代码标识符**)→ 拦截并给出 8 条裁决顺序要我自答;**无法确定 → 放行**(宁可问、不卡死)。
理由文本里内嵌了 8 条,**不依赖技能被加载**(换成别的项目也成立)。
- 备份:`settings.json.bak-20260912-hooks`(2172 B);改后 4049 B,`json.load` 通过,顶层键 = sandbox / claw / enabledPlugins / **hooks** / autoLaunchDesired
- 配置目录依据:CLI 含 `WORKBUDDY_CONFIG_DIR`(判定链 `WORKBUDDY_CONFIG_DIR ?? CODEBUDDY_CONFIG_DIR ?? ~/.workbuddy`)→ 即现有那个 settings.json
### ⚠️ 未验证 / 前提(必须如实说)
1. **是否真的生效未验证** —— hooks 是"**启动时快照**",且官方文档写明「外部修改 hooks 不会立即生效,需在 `/hooks` 面板审核后才应用」。**需重启 WorkBuddy(或新会话)+ 在 `/hooks` 看是否已注册**。
2. **语义判定无法离线自测** —— 判定由 lite 模型执行;我做过一次关键词自测但**结果无意义(判定逻辑太糙)**,不作数。
3. **作用域是用户级**(所有项目都会拦)。若在非 dsh 项目误拦,理由文本仍能指导自判,影响可控;如需只对本项目生效,改用 `<项目根>/.workbuddy/settings.json`(**该路径是否被 WorkBuddy 读取未验证**)。
4. **关闭方式**:删掉 `settings.json` 的 `hooks` 键,或直接还原 `settings.json.bak-20260912-hooks`。
### 兜底(今天即生效,不依赖重启)
工作区 `MEMORY.md §一.1` 增加 **⛔ 提问闸门(硬要求)** 一条:调用 `AskUserQuestion` 前先按 `dsh-decision-method §4.4` 自答,能定就不问。注入型载体**无需重启**,与 hook 互为保险。
## 边界落定:「方法管不到的还是要问」+ 方法演进不再上抛(11:58-12:10)
**用户原话**:「有超过现有决策方法边界的事情,还是需要问的,以后决策方法的问题就不需要再问了。」
**我读了两件事,都落成文字**(若读错请纠正):① **边界内 → 自决;边界外 → 必须问**;② **方法本身的修订也不再上抛**(发现缺口直接改、改完报一句)。
### 写进 `dsh-feature-first` v1.0.0 → v1.1.0
- **§3 标题**:「只准上抛的 2 类」→ **3 类**(新增 (c) 超出方法边界)
- **新增 §3.4「超出决策方法边界的事 —— 必须问」8 类**:① 业务目标与优先级(做不做/先做哪个)② 花钱与资源承诺 ③ 对外承诺与合规(备案/资质/合同)④ 需用户提供的账号凭据或审批 ⑤ 无客观优劣的体验偏好(审美/文案/默认值)⑥ 影响面超出本平台 ⑦ 红线门禁(R5/R7/R8)⑧ 方法确实判不准。
**统一判据 = 「有没有客观可判的优劣」:有 → 方法能判,自决;没有 → 用户的取向,必须问。**
⚠️ 并写明这条是 §2(9 类自决白名单)的**例外出口**,也是闸门 fail-open 的依据。
- **新增 §3.5「方法本身的演进 —— 不再上抛」**:边界内的一切判断不问;**方法修订也不问**(直接改 + 记录);**唯一例外** = 修订会**扩大 AI 自主权或收窄用户门禁** → 属边界外第 7 类,必须问。
- description 同步重写(含"边界定义"与"方法演进"两项);三处副本 md5 一致 `e25f7505…`,已 scp 服务器。
### 闸门判据同步升级(否则会误拦该问的事)
`settings.json` 的 hook prompt 从三分类 → **四分类**(783 字符):
- **A 功能语义分叉 / B 红线门禁 / D 超出方法边界 → 放行**(D 的八项已内嵌)
- **C 技术项 → 拦截**(特征:出现包名·环境变量·路径·commit·端口·内存数值·代码标识符)
- 末句加固统一判据:「**有没有客观可判的优劣?有 → C 类自己定;没有 → 用户的取向,放行去问。**」
- 被拦时的 reason 末尾改为「若你确认这属于 **A/B/D** 类,说明理由后重新提问一次」(原为 A/B)
### 核验
- `settings.json` **JSON 解析 ✓**、四分类特征串全部命中、4420 字节(原 2172;备份 `settings.json.bak-20260912-hooks`)
- `MEMORY.md` **5,246 字符 / 9,386 字节 = 推测注入上限的 66%**(仍有余量,但要留意继续增长)
- 技能三处(工作副本 / 归档副本 / 服务器)md5 一致
### 仍未变的前提
hook **是否真生效仍需重启 WorkBuddy + 在 `/hooks` 面板确认**(启动时快照 + 外部修改需审核)。在此之前,靠 `MEMORY.md` 的硬要求兜底。
## 核实「是否整理了所有历史会话」→ 结论:首版没有,已回补(12:00-12:25)
**用户要求**:「确认是整理了所有历史会话记录 沉淀的可复用决策方法」——要求核实,不能靠记忆答。
### 核查过程(真找到了会话记录在哪)
| 项 | 结果 |
|---|---|
| 会话记录位置 | `E:\ProgramData\.workbuddy\projects\d-AI技能-aliyun-dsh-server\`(**工作区 cwd 决定目录名**) |
| 会话文件 | **5 个** `.jsonl`(+ 各 1 个 `.file-rollback.ndjson` + `.meta.json`) |
| 规模 | **44 MB / ≈8,900 行** |
| 时间跨度 | 主线 `b2817961` = **09-08 20:38 → 09-12 10:11**(5,802 行 / 31 MB);其余 4 个为 09-11~09-12 |
| 行结构 | `{"type":"message","role":"user","content":[{"type":"input_text","text":...}]}`;另有 `reasoning`(1165) / `function_call`(1491) / `file_result` / `file-history-snapshot` |
| **用户真实发言** | **180 条**(剥掉 `<system-reminder>` 前言后)—— 主线 135 / 其余 45 |
### 诚实结论(**对用户不利的那一半也要说**)
- ❌ **首版 v1.0 没有读原始转录** —— 当时 `conversation_search` 两次返回 0 命中,素材只来自**62 份档案 + 五天工作日志**(即会话的"结论层 + 过程层"沉淀)。
- ✅ **但覆盖良好**:逐条比对后,**U1–U12 里 11 条能在原始发言中找到对应原话**(例:U1←msg63/67/71、U2←msg119、U5←msg99/106、U6←msg85、U8←msg40、U9←msg53、U10←msg102/107、U11←msg116)。→ 说明"档案+日志"这套沉淀**确实抓到了主要决策**。
- ⚠️ **确实漏了 7 条**(只在原始对话里看得见,档案/日志没显式记为"决策模式")→ 已补为 **U13–U19**:
- **U13** 我报的数字会被用户当事实基础(msg「当前实况:…212 MiB 和 329 MiB:为什么…」;档案 58 曾把字节当 KB)
- **U14** 「该不该留」的判据是**有没有复用价值**(「这些脚本基本都是根据某个对话任务产生,没有复用价值」)
- **U15** 用户盯**产品级容量约束**(「应该属于控制用户上限,不能让 10 个用户注册每个用户体验都差」)
- **U16** 用户给的"实现建议"是**意图**不是硬要求(鼠标移动→拉起实例,被论证 OOM 后接受否决)
- **U17** 用户当**执行手** → 必须给可直接粘贴的完整命令(「给我个命令去服务器上执行就行」)
- **U18** 用户会**主动关闭**一条线(「忘记这个项目把」「还没准备好 后面再说」)
- **U19** 能力认知类提问占大量往返 → 靠「能力清单」交付物消除
### 沉淀的可复用件
**`dsh-server-docs/scripts/extract-user-voice.py`**(只读,可复跑):抽出工作区**全部历史会话**的用户真实发言。
- 自动定位项目目录(**实测规则:盘符小写 + 分隔符换 `-`**,如 `D:\AI技能\aliyun-dsh-server` → `d-AI技能-aliyun-dsh-server`;**支持从子目录向上回溯 + 归一化模糊兜底**——首版按当前 cwd 推导失败过两次)
- 必须剥 `<system-reminder>` 前言才是用户原话;`--full` 全文 / `--needle 关键词` 查某个决策的来龙去脉
- ⚠️ **别把输出重定向进文档库目录**(会被 `docs-sync-check` 计成"仅本地")
### 结果
- `dsh-decision-method` **v1.1.0 → v1.2.0**:新增 **§0.1 素材来源与复跑方式(honest provenance)**、§1 扩到 **U1–U19**、description 更新
- 三处(工作副本 / 归档副本 / 服务器)md5 一致 `8b33d103…`;新脚本已 scp(755)
- `docs-audit.py` 退出码 1 **仍只来自并行会话的 `档案 64 → 63` 悬空引用**;**我的文件 0 引入**
## 诊断「为什么还在让我确认技术问题」(14:40-15:05)
**用户报**:「为什么和AI对话 还是在让我确认技术问题,你做的设置没有用呢」→ 要求看工作区「任务执行2」的最新对话。
### 定位「任务执行2」
从 `workbuddy.db` 的 `sessions` 表(`title` / `custom_title`)查到映射:
| 会话 | 名称 | 创建 | 最后活动 | 备注 |
|---|---|---|---|---|
| `6cd67b31` | **决策方法** | 09-12 09:32 | 14:42 | **本会话** |
| `4f40f882` | **任务执行2** | 09-12 **10:13** | 14:39 | ← 用户要看的 |
| `a0b34e9f` | 任务执行3 | 09-12 10:10 | 13:26 | anysearch 接入 |
| `ca58e09f` | 方案规划 | 09-11 23:52 | 13:25 | |
| `b2817961` | 任务执行 | 09-08 20:38 | 10:16 | 主线 |
### 诊断结论(两层,第一层是我的错,第二层更关键)
**① hook 确实没在那些会话生效** —— `settings.json`(含 hook)写入时间 **11:58**,而「任务执行2」**10:13 就创建了** → 会话的 hooks 是**启动时快照**,早于配置的会话**根本没有这道闸门**。我在上一轮说过"需重启/新会话",但**把宝押在 hook 上、没同时铺好注入型通道**,这是我的判断失误。
**② 但即使闸门生效,6 次上抛里也只有 1 次该被拦** —— 逐条核对「任务执行2」的 6 次 `AskUserQuestion`:
| 时间 | 问的什么 | 判定 |
|---|---|---|
| 10:34 | 21 处 Windows 指引怎么处理 | ❌ 纯技术项(该自己定) |
| 10:21 | 行尾 CRLF 怎么处理 | ✅ 该问(R7 批量换行符) |
| 11:16 + 11:42 | 验收用哪个实例/账号 | ✅ 该问,❌ **连问两次** |
| 13:32 | admin 崩溃怎么修 | ✅ 该问(R8),❌ 选项混了三种**技术路径** |
| 14:39 | 选 A/B 方案 **+** 要不要重启 | ✅ 红线该问,❌ 技术方案不该问 |
⇒ **"设置没用"的真正形态不是"问得太多",而是「把该问的红线问题和不该问的技术方案捆成一个提问」** —— 用户被迫先读懂两套技术方案,才能回答那个"要不要重启服务"。**体感就是"又在让我确认技术问题"。**
### 修正(三处)
1. **`dsh-feature-first` v1.1.0 → v1.2.0**:新增 **§3.6 拆包上抛** —— ① 红线问题**剥出来单独问**,只问"要不要现在动生产 / 影响谁 / 断多久 / 能否避开";② **技术形态自己定**,作为已定项陈述("我按 B 做…已定,可推翻");③ 一轮最多一个问题、**不许连问两次**。附该会话 6 次上抛的逐条判定 + 正确写法示例。三处 md5 一致 `c735b608…`。
2. **用户级 `~/.workbuddy/MEMORY.md`(第一次改这里)**:加上跨项目规则「不要拿技术项来问用户」+「只问两类」+「⛔ 不许捆包」+ 判据一句话。**这是每会话必注入的通道,新会话在任何项目都生效**(hook 之外最可靠)。体积 3,496 字符 / 7,020 字节。
3. **给用户一段可粘贴的会话内规则**(见交付回复)—— 因为**已开的会话收不到任何注入**,只能靠用户把这段话贴进去即时生效。
### 待用户定(我没替他决定)
「任务执行2」14:39 那个提问仍悬着:**admin 实例因 anysearch 插件不兼容崩溃熔断 → 要不要现在重启 `dshs`**(R8,影响当前在线用户)。属红线问题,**必须用户点头**,我不代答。