Files
dsh_ai1net_server/dsh-server-docs/skills/dsh-decision-method/SKILL.md
T
admin bc0dd2c96d docs(dsh-server-docs): mksess 口径校正(DB 直插→PG 直插)+ 技能 dsh-auto-handoff-chain 三处同步建立(序⑰ S1/S2)
- 02-运维手册.md:mksess 命中处补「PG 直插 + 连接串来源」+ D1 勘误指针两行(档案 77 的旧形态说明,正文不改)
- skills/dsh-change-workflow/SKILL.md(146/395/495 三行)、skills/dsh-env-bootstrap/references/常驻规则-快照.md(55 行):同口径校正
- skills/dsh-auto-handoff-chain/:新建文档库副本(SKILL.md v1.3.2 + scripts/chain_report.py),此前该技能三处同步从未建立
- README.md / INDEX.md:登记该技能(技能表 + 「什么时候查什么」+ 技能清单表)

判据:E1 = 0 行、E2 两副本 md5 全同、E3 diff -r = 0 行、E4 登记命中 README 1 / INDEX 2、镜像 47 同值
2026-09-17 17:03:34 +08:00

360 lines
32 KiB
Markdown
Raw 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.
---
name: dsh-decision-method
description: dsh 多租户平台(alotbuy.com)「改造 / 优化功能交互 / UI 界面」的**决策方法论**。当用户提出一个新需求、问「这是不是最优方案 / 还有没有更好的做法」、要在多个方案里选型、要判断某个决策是否该做 / 该不该扩大范围、要**自主给技术实现选取最优解**、或者要复盘「为什么这么定」时使用。⛔ **用户点名「决策方法」/「参考决策方法」/「按你的规划」/「别问我」/「自行决策」/「自主决策」⇒ 必须立即加载本技能,不得凭记忆代替**(机制层由钩子 `dsh-server-docs/scripts/skill-load-guard.py` 强制注入加载提醒;2026-09-16 实证:用户点名后 AI 全程 `Skill` 调用 **0 次**)。核心 = 决策素材库(用户有效决策 **U1-U28** / AI 有效决策 A1-A25 / 反例 X1-X14,**素材源含 180 条用户真实发言**)+ 「如何确认最优解」的十问与判定矩阵 + **技术实现的默认裁决顺序(8 条,AI 自主用、不问用户)** + 决策流程十步 + 交互 UI 改造专项清单 + 决策语言对照表 + **复跑脚本 `extract-user-voice.py`**。**v2.0.0(2026-09-14)结构变更:素材库(U/A/X)已拆到 `references/`,按需读;本文件只留判定核心 + 触发词索引**(索引绑定可识别动作)。**与 dsh-change-workflow 分工:本技能管「怎么想、怎么定」,那个管「怎么落地」。** 与 dsh-feature-first 分工:那个管「谁定什么」,本技能管「怎么定得对」。
version: 2.8.0
updated_at: 2026-09-16
created_from: 本工作区 62 份改造档案 + 5 天工作日志(2026-09-08 ~ 09-12)全量提炼
agent_created: true
---
# dsh-decision-method — 平台改造的思考与决策方法
> **一句话**:把「这个需求该怎么定」从**直觉**变成**可复用的判定**。
> 材料来源 = 本工作区 `dsh-server-docs/04-调整方案/` 62 份档案 + `.workbuddy/memory/` 五天日志里的**真实决策痕迹**(含被驳回的)。
> 每条模式都带**实例出处**,可以回溯核验,不是抽象原则。
---
## 0. 定位:和 `dsh-change-workflow` 的分工
| | 本技能 | `dsh-change-workflow` |
|---|---|---|
| 管什么 | **需求和方案怎么定**(选型 / 收敛 / 判方向 / 拍板) | **定了之后怎么落地**(六阶段 / 红线 / 档案模板) |
| 什么时候用 | 用户刚提需求、问"最优方案"、要在选项间选、要判"该不该做" | 决策已定,开始改码 / 验证 / 归档 |
| 产出 | **选项表 + 决策点 + 判定依据** | 代码改动 + 验证记录 + 档案 |
> 顺序:**先本技能定案 → 再 dsh-change-workflow 执行**。规划会话只做前者,执行会话只做后者(交接载体 = `dsh-server-docs/交接单/`)。
### 0.1 素材来源与复跑方式(**honest provenance,勿含糊**)
| 素材 | 位置 | 说明 |
|---|---|---|
| 改造档案 | `dsh-server-docs/04-调整方案/NN-*.md` | 每份含「触发 / 用户裁定 / 方案对比 / 事故踩坑」——**会话的结论层** |
| 工作日志 | `.workbuddy/memory/YYYY-MM-DD.md` | 五天过程日志,含用户原话引用——**会话的过程层** |
| 现行事实层 | `BRIEF.md` / `INDEX.md` / `README.md` / `06-工作台UI规范.md` / `交接单/README.md` | 约定与红线 |
| **原始会话转录** | `~/.workbuddy/projects/<工作区目录名>/*.jsonl` | **用户真实发言的原始记录**(含被否决、被纠正的内容) |
**复跑命令(只读)**:
```bash
# 抽出本工作区全部历史会话里的「用户真实发言」(2026-09-12 实测 = 180 条,跨 09-08→09-12)
python3 dsh-server-docs/scripts/extract-user-voice.py
# 查某个决策的来龙去脉
python3 dsh-server-docs/scripts/extract-user-voice.py --needle 复用价值
```
> ⚠️ **本方法 v1.0 的素材边界(如实记录)**:首版只从**档案 + 日志**提炼(当时会话检索接口返回 0 命中)。
> 2026-09-12 用上面的提取器回补核对 —— **U1–U12 里 11 条能在原始发言中找到对应原话**(覆盖良好),
> 据此**补上了 U13–U19** 这 7 条只在原始对话里才看得见的模式。**以后迭代本技能,先跑这个脚本。**
---
## 1. 决策素材库 · 用户的有效决策(U1–U28) → **`references/素材库-U-用户决策.md`**
> **已被拆出本文件**(原占全文 55%)。本文件只留「**判决核心 + 指针**」:素材库是**查阅型**(看了更准、不看也不违规),判定核心才是每次都要用的。
> **触发词 → 直接查哪条**(**必须去读**,别凭印象答用户口径):
| 你正在判断什么 | 去查 |
|---|---|
| 「这件事该不该问用户 / 我是不是又在上抛了」 | **U20 · U21 · U22** + 本文件 §4.1 两条总闸 |
| 「要不要自己开发 / 有没有现成的」 | **U23**(官方库优先 + 体检三关) |
| 「多期方案 / 兼容性怎么定」 | **U24** |
| 「要给用户看什么 / UI 怎么排」 | U5 · U7 · U11 + 本文件 §6 |
| 「这个改动会不会让项目变差」 | **U28**(十维净变差即命中 ⇒ **停下复盘**;无正向做法 ⇒ **立即停止**)+ 红线 R11 |
| 「要不要降级/延期/先这样跑」 | **U27**(要的是解决问题,不是将就妥协)+ A6 边界(目标不打折、路径取最小代价)|
| 「方案有风险/问题,能不能先干着看」 | **U26**(先优化到「当下最优解」+ 残余风险写清,再走下一步)|
| 「抢了锁之后怎么收口 / 能不能先放着」 | **U25**(锁的生命周期 = 任务的生命周期;带锁结束不算完成)+ 本文件 §4 判据 |
| 「删 / 留 / 清理 / 收尾怎么定」 | U3 · U6 · U14 |
| 「用户那句话到底是什么意思」 | 读全表(每条 = 原话 + 落地 + 判据) |
---
## 2. 决策素材库 · AI 的有效决策(A1–A22) → **`references/素材库-A-AI推理.md`**
> **已被拆出本文件**。**触发词 → 直接查**:
| 你正在判断什么 | 去查 |
|---|---|
| 「我的证据够不够 / 结论能不能下」 | A1 · A4 · A5 · **A18**(静默失败会伪造结论)· **A19**(验收要含第二环境) |
| 「我凭什么说这是限制 / 做不到」 | **A17**(配置项 / 已抽象层 / 真硬编码,三层取证) |
| 「写状态 / 写支持度 / 交付回执」 | **A15**(三态词表:✅已验证 / ⚠️待开发验证 / ❌已知不支持) |
| 「删除 / 迁移 / 回滚 / 替换」 | A8 · **A16**(伴随物清单)· **A20**(存量烂账选只增不改)· **A22**(先补位再退役) |
| 「我做完了吗 / 能不能宣布完成」 | **A25**(本机改完 ≠ 交付:先画「改动层 → 生效链路」;四条"自我安慰"不算交付)|
| 「我装的门禁/钩子到底管用吗」 | **A24**(拦截面必须覆盖真实行为面 —— 先核账再装)|
| 「判据 / 分类 / 索引怎么设计」 | **A21**(必须报分布、要有区分度) |
| 「失败面 / 报错 / 能力不确定」 | A10 · A11 |
| 「流程走到哪一步了 / 我是不是跳步了」 | **A23**(流程类失效 = 触发词没命中;规则要进常驻层、触发用动作词)+ `dsh-change-workflow` 六阶段 |
| 「拍板前还要问自己什么」 | A2(必含"不做")· A3(决策点)· A6 · A7 · A9 |
---
## 3. 反例库:被驳回 / 被纠正的决策(X1–X13) → **`references/素材库-反例-X.md`**
> **已被拆出本文件**。**每条反例 = 一条避免规则**。**触发词 → 直接查**:
| 你正在判断什么 | 去查 |
|---|---|
| 「我刚被纠正了,同类还有哪些坑」 | X1(批量)· X4(归因)· X9(过度上抛)· X10(答非所问)· X11(越界)· **X12**(把用户材料当权威)· **X13**(把自己的解析失败当成版本差异)· **X14**(一批改造拆成多次中断动作)|
| **「这个库 / 方案成熟、star 高,所以选它」** | **§4.6**(选型判据轴:⛔ 热度≠安全/性能;先立轴再排序;必查默认值 + CVE 历史)|
| 动手前的"别踩"清单 | 读全表 13 条 |
---
## 4. 如何确认最优解(本技能的核心)
### 4.1 判定矩阵:先给方案贴标签
> **⭐ 两条总闸(顺序在前:先问「是不是我的 lane」,再问「要不要停手」)**
> **闸 1 · lane**:这件事**落在谁的 lane**?—— ① **我自己负责的**(我的插件源码/产物、该 profile 的依赖、我自己的临时脚本、我方案内的执行细节)⇒ **自己拍**;② **平台级 / 全局 / 别人 lane 的**(`/var/lib/**`、全局符号链接、别人的 profile、别人的产物)⇒ **只报告、不动手**,**哪怕改它能让自己流程跑通**(2026-09-13 用户原话:「谁让你去改这个的」「不是自己负责的任务相关文件不要去改」→ **X11**)。
> **闸 2 · 门禁**:命中**真门禁**才停等确认 —— 现行只剩两条:① **不可逆破坏性操作**(删数据 / 迁 DB / 清目录)② **边界外**(业务目标与优先级 / 花钱与资源承诺 / 对外承诺与合规 / 需用户提供的凭据 / 无客观优劣的偏好 / 影响面超出本平台)。**其余一律自决**(含部署上线、重启、改配置),事后一句「我选了什么(可推翻)」(**U20 / X9**)。
> ⚠️ 两条闸**对称**:闸 1 治「**越界动手**」,闸 2 治「**过度上抛**」—— 2026-09-13 两类各犯过一次。
| 判定问题 | 若答案是 | 处置 |
|---|---|---|
| 这次是**扩大**还是**收窄**可见面/权限?(R5) | 扩大 | **停手**,出「权限影响评估」四问 + 等确认 |
| | 收窄 | 可直接做,但**遮蔽类必须真启动一次实例验证** |
| 有没有**不扩大也能实现**的方案? | 有 | **必须先提**;提不出才说明为什么没有 |
| 改动**影响多少文件**?(R7) | >10 或有"所有/整个/全库" | 先出**受影响清单** + 等确认;先 1 个对象单点验证 |
| 会不会**中断在线用户**?(R8) | 会 | 先说明影响面 + 取得确认;能避开活跃时段就避开 |
| 会不会**中断在线用户**?(R8)——**按实际影响面判,不按动作名字判** | **不会**(只换包 / 传产物 / 改静态页 / 投放候选池) | **属边界内的「部署与同步」⇒ 做完即上线,不要问**(U20 / X9);先做完,再用一句「我选了什么」交代 |
| 这个改动**失败**会怎样? | 实例起不来 / 全站不可达 / 不可逆 | 必须有回滚点(备份路径 + 恢复命令)**先就位** |
| **删除/迁移**的收益 vs 潜在破坏? | 收益小、破坏大 | **不删**——标注废弃 + 禁再加功能 |
| **这个改动会让项目某一维度净变差吗?**(**R11 · 十维**:目标/方向/架构/功能/性能/安全/交互/UI/便利性/扩展性) | **会** | **立即停下复盘** → 找保住正向收益的做法;**拿不出 ⇒ 立即停止、只报告**(不许"先做着看",见 **U28**) |
| 会不会造出**第二个漂移源**? | 会 | 改成**指针**(单一来源)——清单/待办/部署事实各只有一个权威文件 |
### 4.2 「确认最优解」十问(拍板前逐条答,答不出就是还没想清)
1. **一句话目标**是什么?做完了**没有**(可判定)?
2. 这条结论我**用什么命令/证据**证明?(说不出 = 还在推断,见 A1)
3. 有哪 **≥2 个选项**、以及**"不做"**这一条?(A2)
4. 这个改动是**扩大**还是**收窄**?(U8 / R5)
5. 有没有**更小**的改动达到同样目的?(A6)
6. 会影响**谁**(全部租户 / 单租户 / 仅 admin)?会**断多久**?(R8)
7. **回滚**怎么做?备份在哪?(写得出可执行命令才算数)
8. 造出**第二个真相源**了吗?(单一来源原则)
9. 用户**能不能感知到**(新入口 / 新反馈 / 新文案),还是只有后端变了?(U5)
10. 谁来**验收**?我能不能给一个**第三方可复现**的命令 + 期望输出 + 退出码?
### 4.3 验收口径分级(越靠后越权威)
| 级别 | 手段 | 能证明什么 |
|---|---|---|
| L1 推断 | 读代码 / 读文档 | **什么都不能证明**(只用来生成假设) |
| L2 命令 | `curl` 状态码 / `--dump-config` / 日志 grep | 机制是否被触达(**注意 `--dump-config` 不反映 bundle/patch 层**) |
| L3 对账 | md5 双端 / `docs-sync-check.sh` / 可见面清单 diff / 工具清单前后对比 | 一致性、无回归 |
| L4 端到端 | 铸造临时 session 实跑 → 越界用例(`../../etc/passwd` 应 400) | 安全与功能闭环 |
| L5 用户实测 | 用户浏览器硬刷新 + 体感确认 | **最终验收**(前端渲染、动画、位置类只能到此为止) |
> **做不到就明说**:「未做浏览器渲染验证(本机无 Chromium,装它成本不成比例)→ 待用户硬刷新确认」是**合格交付**;把 L1 说成 L5 才是事故。
### 4.4 技术实现的默认裁决顺序(**AI 自主用,不问用户**)
> 这是「技术实现找最优解」的可执行算法:**按序自答,第一个"是"就是答案**。全部答"否"才说明确实需要新造东西。
> 配套 `dsh-feature-first`:用户在技术层没有判断依据 → 这 8 条**不构成决策点**,不要上抛。
| 序 | 自问 | 若"是" → 选它 |
|---|---|---|
| **1** | 有没有**既有机制 / 扩展点**能复用? | 扩展,**不新建**(U2:不做两套) |
| **2** | 有没有**更小改动**达到同一效果? | 取**最小改动半径**(A6) |
| **3** | 能不能**用配置解决**而不是改代码?(cordis patch / env / bundle 声明) | **配置优先** —— 不改码 = 免 build、免重启 |
| **4** | 能不能**只改一层**?(门户静态页 / 编排器 / profile / bwrap / nginx) | **单层**;绝不"跨层顺手改" |
| **5** | 失败代价**是否对称**? | 不对称 → 选**可回滚、可保留**的那条(删除/迁移类尤其,A8);**删除类先走 A14「删除前三问」** |
| **6** | 结果**能不能被验证**?(命令 / 日志标记 / 端点) | 不可验证 → **顺手加可 grep 的标记或端点**(A5) |
| **7** | 这个改动是**收窄**还是**扩大**可见面 / 权限? | 收窄可直接做;**扩大 → 回 R5 门禁,先取得确认** |
| **8** | 与**官方契约的耦合面**有多大? | 耦合越小越好;**每一处耦合都要写进升级回归清单**(档案 26 六类) |
**三条硬约束**:
1. **第 3 条优先于第 2 条** —— "能配置就不改码":改码要走 build + 重启,而重启**会中断在线用户**(触及 R8);配置改动(尤其静态页)常常即时生效。
2. ⚠️ **2026-09-16 修正**:原表述「任一条与红线冲突 → 红线赢」**过宽**,是会话 `ddea70b7` 上抛的诱因 —— 把"平台级 / 全局 ⇒ 只报告不动手"(R7-边界②)当红线读,于是"红线赢"⇒ **该自己做的事被推给用户**。正确表述:**与「真门禁」冲突 → 门禁赢**(真门禁只有两类 ✓ 见 §4.5);**与表述重叠/打架的规则冲突 → 按 §4.5 裁决顺序**。
3. 🔀 **规则冲突时按 `R8 → §1 边界内自决清单 → 其余红线` 取首个命中项**,⛔ **不许"自行取保守侧"**(详见 §4.5)。
### 4.5 规则冲突裁决顺序 + 上抛前三问(**2026-09-16 加,源自会话 `ddea70b7` 复盘**)
> **案例**:用户要求"完成 guest 迁移",AI 在结尾用「## 四、待你拍板」提了两问(① 106 旧控制面停/留 ② D1–D6 先做哪些)。用户 U6 回:「**D1–D6 先做哪些 按照你的规划执行,中间有问题参考决策方法**」,再两次(U5 / U7)自行给出"删除"的答案。
> **代价**:AI 那两问**都不是真门禁** —— 用户不但没被"省事",还多花一轮把答案喂回来;且 AI 全程 `Skill` 调用 **0 次**(用户点名的方法没被取用)。
**A. 冲突裁决顺序(同一对象被多条规则给出相反结论时)**
| 序 | 取谁 | 命中即停 |
|---|---|---|
| 1 | **R8** | 开发环境服务器 ⇒ **该动就动**,只需动手前一句话说明;⛔ 不必等确认 |
| 2 | **§1 边界内自决清单** | 部署 / 重启 / 改配置 / nginx·nft / drain / 技术选型 / 命名 / 调参 ⇒ **自决** |
| 3 | **其余红线** | R5 权限扩大 / R7 批量写入 / R9 锁 / R10 uid —— **永远是硬约束**,不参与裁决 |
**B. "平台级" ≠ "别人的"**(本次误判根源)
`dshs*`·`dsh-*` 单元、`/var/lib/dshs/**`、nginx·nft、端口,只要在**我们自己的 47 / 106 / 本工作区**上,就是**本平台自己的资源** ⇒ 按 §1 + R8 **直接做**。
R7-边界② 的"只报告不动手"**只针对「别人的 / 归属不明」的对象**。**判据看"归属",不看"是不是平台组件"。**
**C. 上抛前三问 —— 任一条为"是"即自决(不必三问全过)**
| # | 自问 | 结论 |
|---|---|---|
| 1 | 对象是**我们自己的**平台资源吗? | 是 ⇒ **自决** |
| 2 | 我**查证过**关键不确定点吗?(如"还有谁在用 / 有没有访问记录") | 没查 ⇒ **先查**,⛔ 不许把"我不确定"当上抛理由 |
| 3 | 候选按优劣排序后,**第一名是否明显更优**? | 是 ⇒ **自决**(只有"各有优有劣、客观分不出高下"才算真取舍) |
⛔ **同时禁止**:把"我有倾向"降级成"建议 + 待你拍板" —— 有倾向 ⇒ 直接做完,写一句「我选了什么(可推翻)」。
⛔ **冲突 ≠ 门禁**:两条规则打架**不构成**上抛理由。
**产出**:把 1–8 的答案写进档案的「技术选择」段(一行一条,**含被否决的选项与否决理由**)。
→ 这样用户**事后可推翻**、但**事前不被打扰**(对应 `dsh-feature-first` §5 的"默认自主 + 事后可推翻")。
---
### 4.6 技术选型:**先立判据轴,再排序**;⛔ 不许用 star / 年龄 / 生态当选型依据(**2026-09-16 加,源自覆盖网络 relay 选型**)
**反例(我当场犯的)**:把 `frp` 排「首选」,排查依据只有 **~10.6 万 star + 约一月一版 + 生态最好** —— 那是**「省心度」轴**,不是**「安全 / 性能」轴**。用户一句「**项目时间比较久,性能和安全性还真不一定是最好**」直接击穿,复查后**撤销排序**。
复查出的**真实安全面**:`CVE-2026-40910`(认证绕过 + 未授权 DoS,**影响 ≥0.53.0**)|dashboard **默认 `admin:admin` 且口令明文存配置**|**`proxyBindAddr` 默认跟随 `bindAddr`**(官方自己写「**大多数指南遗漏的配置**」—— 不设则代理监听器**绑到公网**)|服务端**默认不强制 TLS**|`auth.token` 是**单一静态共享令牌**、frpc 明文存、`allowPorts` 白名单**默认关**(⇒ 一台客户端失陷可申请**任意**端口)。
⇒ **"项目久"是双刃**:稳定 + 文档好 **vs 漏洞历史长 + 默认值停在历史约定(安全靠运维纪律补)**。
**四条硬规矩**
1. **⛔ 不用「star / fork / 项目年龄 / 发布频率 / 生态」做首轮排序** —— 它们度量的是**热度与省心度**,推不出"在本案里更安全 / 更快"。**只能当同分时的决胜项**,不能当**排序主依据**。
2. **判据轴必须从"本案的真实约束"反推**,并且**每条都要能回答"这条轴上的差异会不会改变本项目的结论?"** —— 不会 ⇒ **该轴不参与选型**。
· 本例立出六条:**① 认证模型(身份 > 每服务密钥 > 共享 token)② 默认拒绝还是默认放行 ③ 能否零新增入站 ④ 单节点失陷的爆炸半径 ⑤ 可观测 ⑥ 生态**。
· 结果:**frp 在 ①②④ 三条里都最差一档**(共享 token / 默认放行 / 可申请任意端口),只在 ⑤⑥ 领先 ⇒ 排序翻转为 **证书身份型(OpenZiti / Nebula)> rathole(Noise_NK 双向认证 + 每服务 token 必填)> frp**。
3. **性能轴先自证"它是不是本案瓶颈"**:本例**第一瓶颈是 presence 不是带宽**、量级是「每 worker 几十个 HTTP 会话」⇒ **吞吐 benchmark 不参与选型**(且多为厂商/二手自测)。**真要测就测链路本身**(RTT / jitter / 带宽)—— **任何 relay 的上限由链路决定,不由实现决定**。
4. **老 / 流行项目必查两张单子**:① **默认值清单**(逐项问"**不设它会怎样**"—— 本例 5 项里任何一项漏设都会**静默**破掉既定安全目标)② **CVE / 安全公告历史**(编号 + 影响版本区间)。**"成熟" ≠ "默认安全"。**
**配套两条(本例同时验证)**
- **"可选性"优先于"选对"**:先把接口抽出来(`Reachability.via` + `Rendezvous` 注册表)⇒ **换实现是 env 级切换** ⇒ 选型**可以推迟**,选错也不致命。**能在不选的情况下保留选择权,就别为"一次选对"付引入成本。**
- **替换 ≠ 无条件升级**:换第三方 = 用**我们不掌控的攻击面**替换**已收窄、且有系统补丁渠道的面**(例:sshd + `restrict,port-forwarding`)。⇒ **没有明确痛点之前,"维持现状"也是合法候选**,别把"换掉旧的"默认当成正向。
**判定触发器**:只要出现「成熟 / 久经考验 / 用得最多 / star 高 / 大家都在用」这类**热度型论据**给排序 ⇒ **立即反问三句**:① 这条论据落在**哪个轴**上?② 这个轴是**本案的瓶颈轴**吗?③ 它的**默认值**与 **CVE 历史**查过没有?
---
## 5. 决策流程十步(新需求到手照这个走)
| 步 | 动作 | 产出 |
|---|---|---|
| 1 | **判类型**:这是「方案请求」还是「任务明确直接执行」? | 方案请求 → 只输出方案,**未经明确授权不改文件** |
| 2 | **开工前置检查**:先看已有技能/资产/记忆,"本机已有的能否满足?" | 决定"扩展还是新建"(→ U2) |
| 3 | **取证**:源码级 / 命令级实证,先拿真实失败请求 | 事实清单(每条带命令 + 期望输出) |
| 4 | **判方向**:扩大 / 收窄 / 中性 | 扩大 → 立即停手出四问 |
| 5 | **出选项表**:≥2 选项 + "不做" + 影响/风险 + 推荐项 | 方案对比表 |
| 6 | **选路径**:优先"最小代价合法路径""能一行代码就不要改平台""删除类判代价对称性" | 推荐方案 + 被否决方案的否决理由 |
| 7 | **列决策点**:已定的标"已定(谁定的/依据)",未定的标"开跑前问用户" | 3–5 个决策点 |
| 8 | **用户拍板** | 决策语言落成文字(见 §7) |
| 9 | **小步落地 + 回滚点就位**(单点验证 → 再推广) | 备份路径 + 恢复命令 |
| 10 | **可复现验收 + 沉淀** | 档案(需求→改动→验证→红线→回滚)+ 红线/技能/记忆三层沉淀 |
> **第 1 步和第 4 步是"停止点"** —— 这两步没结论就不要往下走。
---
## 6. 交互 / UI 改造专项决策清单
> 用户对本项目的界面要求有明确取向,以下是**已验证有效的取向**(源自档案 16/31/36/45/56/57/59/60/61/62 + `06-工作台UI规范`)。
### 6.1 反馈与状态(最高频痛点)
| 场景 | 必须做到 | 实例 |
|---|---|---|
| 有任何等待(实例启动 / 拉目录 / 上传) | **可见进度**,且**导航路径与 XHR 路径都要有** | 档案 59:只有导航有 `wake.html` 动画,XHR 静默 20 秒 → 用户"以为死了" |
| 长耗时 | **3 秒后才亮**覆盖层(短请求不打扰) | 同上:`SLOW_MS = 3000` |
| 状态可缓存 | 页面明示「缓存更新于 X 前(6 小时内直接复用,不联网)」 | 档案 62:功能早已存在**但完全看不出来** |
| 不可编辑 / 只读 | 明示原因,不要"点了没反应" | 档案 36 |
| 失败 | 行内提示(`.toolbar-note` / `.empty`),给出**下一步** | 06 规范 §4.8 |
### 6.2 信息层级与术语
- **首列放用户读得懂的那一列**(说明 > 名称 > 技术标识);技术标识降副行(U7)
- **内部术语不上页面**:「候选池」→「导入到平台」;并显式解释易误解的关系(「**投放 ≠ 生效**」)
- **数值列右对齐 + `tabular-nums`**(否则滚动时数字跳动);超宽字段移出共享网格
- **文件名/标题默认同正文色,hover 才变蓝**(避免整列花掉)
- **图表类改动先看 `06-工作台UI规范`**,冲突时以 `06` 的**实测 Token** 为准
### 6.3 布局与滚动(踩过的坑)
- `main#view` 高度 = `calc(100vh - 55px)`(**55 是实测值**,写 54 会多出 1px 第二层滚动条)
- **"视口自适应高度"必须上下都算** —— 档案 61 第一次修正只算了列表上方 372px,漏了下方 116px(按钮行 50 + card padding 18 + `#view` padding-bottom 48)→ 仍然溢出。正解 `calc(100vh - 520px)`
- `.modal-mask` 是 `display:flex` → **必须显式写** `[hidden] { display: none }`,否则弹窗关不掉
- 同名类二次定义会互相覆盖(`.tab` 有胶囊式与下划线式两套)→ 新页面**另起类名**(如 `.pg-tab`)
### 6.4 危险与不可逆操作
- 确认弹窗 **必须写明后果**(「将重启实例,会话可能中断」)
- 危险按钮用 `--danger` 系;保存/查看类靠**底色深浅**区分(保存=浅灰底深字 `.btn-import`,查看=白底蓝字 `.btn-view`)
- **不静默提升权限**:档位过时只**提示**,不自动改(安全语义变更必须用户知情)→ 档案 45/56
### 6.5 UI 决策的验收口径
- 静态文件(`web/*.html`)改完**立即生效、无需重启**;只有 `src/**` 才 build + restart
- 改完 `node --check` 内联 JS;用**独立 headless Chrome**(`--headless=new` + 独立 profile + CDP)验证,**绝不碰用户日常浏览器**
- **`section` 名是运行时注册的,`curl` 抓不到** → 这类改动只能靠用户硬刷新确认,**如实标注"未做浏览器渲染验证"**
---
## 7. 决策语言对照表(用户怎么说 → 怎么落)
| 用户的话 | 真实含义 | 该怎么落 |
|---|---|---|
| 「按建议处理」 | **只授权那条建议本身** | 不做顺带优化;范围外的发现**先报告**(R7) |
| 「是不是最优方案 / 还有更好的方式吗」 | 要**选项对比 + 依据 + 风险** | 出对比表 + 十问,不要直接开干 |
| 「一次性优化到位」 | 同主题**做透**,别留尾巴 | 一次列全所有子项,附完成清单 |
| 「不需要 / 是不需要的」 | 先**扫引用与依赖**再定范围 | 出"引用实测表",只剔真 0 引用的(U3) |
| 「暂缓 / 还没准备好」 | **parked** | 保留侦察结论 + 列出"需你先办的事",**不再推进,等用户主动提起** |
| 「确认开始执行」 | 决策已定,**可以动刀** | 立即执行;但 R7/R8 门禁仍生效 |
| 「为什么要等我确认才部署呢」 | **部署 / 上线属执行细节** —— 不打断用户的动作不该上抛 | 直接做完上线,让用户**看线上效果**判断需求是否被满足(U20 / X9) |
| 「需要告诉我的是 是否已实现,如果未实现:为什么不能,需要我拍板可以问我」 | 要**结论三件套**,不要过程与自省 | 用 **U21** 四节骨架:判定 → 为什么不行(分层)→ 需你拍板(真需要才写)→ 我接着做(陈述句)|
| 「谁让你去改这个的」 | **越界了** —— 动到了不是我 lane 的东西 | 立即停手 → 能撤就撤(并自证不依赖它)→ 报告;此后动手前先过 **U22 闸 1** |
| 「推送 / 提交」 | 明确授权 git 操作 | 此前一律**不 commit 不 push**;提交也只用定向 `git add` |
| 一行指令(无上下文) | 期望**自主拆解 + 排查到底** | 自己建任务链、自己做根因定位,别逐步问 |
| 「为什么…?」(问现象) | 要**根因链**,不是复述现象 | 先取证(真实请求/日志/实测数),再给"现象→根因→修法"三段 |
| 「有没有越过红线」 | 要**逐条对照全量红线**的结论 | 分"当时成文口径 / 新立口径"两种口径答(A13)|
---
## 8. 决策记录模板(写进档案的固定段落)
```markdown
# <NN>-<标题>(<日期> 落地 / 调研)
- 日期: / - 状态:✅已完成|🔄进行中|⏸暂缓|❌关闭 / - 触发:<用户原话或原始报障>
> **TL;DR**|结论 / 关键 / 状态(紧贴头部,3 行内)
## 背景与动机 # 需求来源、真实失败请求、触发场景
## 用户决策 # 关键分叉 + 选择 + 理由 + 日期(原文引用优先)
## 方案对比 # 表格:方案 / 内容 / 判定 / 理由(含"不做")
## 实现 # 改动文件清单 + commit + 关键片段
## 验证记录 # 命令 + 输出 + 结论;**含失败尝试与假阴性**
## 事故 / 踩坑记录 # 现象 → 根因 → 规避
## 回滚 / 注意 # 回滚命令、副作用、后续待办
```
**三层沉淀(每次决策收口都要做)**:
1. **治本层**:机制与流程固化进 skill,或写进 `04-调整方案/NN-*.md` 改造档案(可复用的留 skill,一次性的归档)
2. **失误层**:教训 append 到 `.workbuddy/memory/YYYY-MM-DD.md`(**append-only**,不改写历史)
3. **记忆层**:长期约定/红线写 `MEMORY.md`(工作区级 + 用户级)
---
## 9. 与其他约束的关系
- **红线优先级高于本技能**:R1 不自动升级 dsh|R2 不改官方主程序与缓存|R3 client bundle 禁 `exports.default`|R4 不用真实账号做登录测试|**R5 权限只准收窄**|**R7 禁未经确认的批量/全仓写入**|**R8 中断在线用户须先知会** —— 任一条命中,**先停手**,本技能的效率论证不构成豁免。
- **执行层**:决策定了之后走 `dsh-change-workflow`(六阶段 + 档案模板 + 并行调度协议)。
- **规划/执行分离**:本技能属**规划侧**;产出交接单(`dsh-server-docs/交接单/`,8 段必填),规划会话**不 ssh、不改码、不重启、不 scp**。
- **单一来源**:清单与状态 = `INDEX.md §二`;待办 = `03-路线图与待办.md`;部署事实 = `DEPLOY-本部署.md`;UI 基线 = `06-工作台UI规范.md`;现行事实 = `BRIEF.md`(首读)。
- **可复跑判定工具**:`docs-audit.py`(歧义/编号/悬空引用,退出码非 0 即需处理)、`docs-sync-check.sh`(双端对账)、`docs-manifest.py`(机读清单)、`handoff-guard.sh`(并发预检,推送前 `PUSH=1`)。
---
## 附:本技能的自检(用完之后问自己)
1. 我有没有**先取证再下结论**?(A1)
2. 我给的方案里有没有**"不做"**这一条?(A2)
3. 未定的决策点,我是**问用户**了还是自己替他定了?(A3)
4. 我的"最优解"能通过 §4.2 十问吗?
5. 我的验收口径是 L1 还是 L5?**有没有把推断说成实测**?
6. 这次操作**会不会命中红线 R5/R7/R8**?
7. 收口时**三层沉淀**做了吗?有没有造出第二个漂移源?
8. 技术实现我是**按 §4.4 的裁决顺序**自己定的吗?还是又把技术选项拿去问用户了?(若问了 → 违反 `dsh-feature-first`)
9. 我这次「停手等确认」,是按**实际影响面**判的吗?还是只看到「部署 / 上线 / 生产」这类**词**就触发了门禁?(X9)
10. 我的答复**第一句**是在答用户问的那件事吗?有没有把「我的失误 / 进度 / 计划」写在前两节?(X10 / U21)
11. 动手前我过「**两条总闸**」了吗?—— ① **这落在谁的 lane**(不是我的 → 只报告,**X11**)② **命中真门禁了吗**(没命中 → 自己拍,别问,**U20 / X9**)
12. 这条回复**能被扫吗**?—— 排版按 `dsh-feature-first §5.4`(首屏 3 行给判定 · 每节 ≤7 行 · 加粗只留关键词 · 表格 ≤5 列 · 一条信息只说一次)