文档库:目录改为编号制(01-规范/02-架构设计/03-数据库/04-调整方案/
05-交接单/06-ops/07-scripts/08-skills/09-archive),顶层散文件归入 01-规范/;
INDEX.md 与 docs-manifest.json 重刷(档案 146 篇);旧目录名引用全量对齐。
IM 线:src/im/**(SDK / hub / store / presence / ws / gateway-token)、
src/web/routes/im.ts、src/db/plugin-data/**、src/supervisor/plugin-assembly.ts
及对应 test/**。
插件线:poc/{im-agent-bridge,im-connection-gateway,im-conversation-tabs,
business-plugins-im,carbon-mcp-probe}、src/web/routes/{sessions,overlay-device}.ts、
src/net/relay/{device-grant,instance-credential}.ts。
仓库卫生:清出 40 个历史误入库 / 已改名文件(34 个交接单归档 + 6 个旧结构,
本地均有副本);dsh-server-docs/.gitignore 补 tmp/;交接单不入库(政策)。
This commit is contained in:
1 parent
3d8f50e366
commit
e6207aa691
239 files changed
+34477
-14633
No files matched your search
@@ -0,0 +1,165 @@
|
||||
# 素材库 · AI 的有效决策(A1–A22)
|
||||
|
||||
> **归属**:技能 `dsh-decision-method` 的素材库(**按需读**,不是每次都要读)。
|
||||
> **主文件 / 索引 / 判定核心** = `../SKILL.md`(§4 判定核心 · §5 流程 · §7 语言表 · 附 自检)。
|
||||
> **用法**:只在「要判某条是否属于既有口径」或「要引用用户原话」时读本文件;**别整段抄进答复**。
|
||||
> **维护**:条目**只增不改**(编号进位到末尾);用户原话**逐字**引用;每条必须带「实例出处 + 判据」。
|
||||
|
||||
---
|
||||
|
||||
## 2. 决策素材库 · AI 的有效决策(A1–A16)
|
||||
|
||||
> 这些是**被实践证明有效的推理方式**,不是结论。新任务遇到同类岔路时直接套用。
|
||||
|
||||
### A1|取证优先于推断:源码级 / 命令级,禁止只靠文档
|
||||
- **实例**:`--dump-config` 被证伪(它**不反映** bundle/profile patch 层,连已生效的行都不显示)→ 判定口径改为「加载标记 + 浏览器实测」;「手放 node_modules ≠ 安装」(lockfile 才是账本);「空闲回收」**从未生效**(全历史 `idle-reap` 仅 1 次)
|
||||
- **做法** → 结论前先问"这条我能用什么命令证明",写成**命令 + 期望输出**;文档只当线索
|
||||
|
||||
### A2|方案对比表:≥2 选项 + 影响/风险 + 建议,**必须含"不做"**
|
||||
- **实例**:档案 20 方案 A(加固,推荐)/ B(启 enablePatch,不推荐);档案 45 方案 A(会话迁移,不做)/ B(提示,采用);档案 16 §四 folder_plugins(查明后**建议废弃**)
|
||||
- **做法** → 表格四列:方案 / 内容 / 判定 / 理由;**推荐项置首并标注 "(Recommended)"**;给不出"不做"这条路说明分析还没做完
|
||||
|
||||
### A3|决策点显式列出,等用户拍板(不替用户决定)
|
||||
- **实例**:交接单 8 段里第 4 段就是「决策点」——**已定的写"已定(谁定的/依据)",未定的写"开跑前问用户"**
|
||||
- **做法** → 一单最多留 3–5 个决策点,每个给推荐项 + 代价;**未定的决策点不允许执行会话自行拍板**
|
||||
|
||||
### A4|能用 A/B 实测就 A/B,别写"应该会更快"
|
||||
- **实例**:`NODE_COMPILE_CACHE` 冷启动 **5.0s → 4.0s**(实测);反向教训也记:`--max-old-space-size` **不降稳态内存**(优化前后 cgroup 都 ~98 MiB)→ 它买的是**可诊断性**,不是省内存
|
||||
- **做法** → 性能/资源类结论必须给**前后两个数**;说不出第二个数就明说"未实测"
|
||||
|
||||
### A5|把"不可验证"改造成"可验证"
|
||||
- **实例**:给插件加**加载标记** `[workspace-scoped-picker] loaded root=…` → 把升级回归(C4)从"看 UI"变成"看日志";`GET /api/capabilities` 人机同源
|
||||
- **做法** → 一个改动如果只能靠"看起来生效了",就**顺手加一行可 grep 的日志/标记/端点** —— 这是最便宜的可验证性投资
|
||||
|
||||
### A6|选「最小代价的合法路径」,不选「最彻底的」
|
||||
- **实例**:档案 45 —— 根治方案是**改写存量会话的种子事件**(属 R5「扩大」+ 多帧 zstd append-only 日志重写,风险收益不成比例)→ 改选**一句提示文案**;档案 42 —— 想禁 `python3.6` 的"遮蔽"会让实例起不来 → 改选**文档引导**(成本 0、风险 0)
|
||||
- **判据** → 问三句:① 有没有更小的改动达到同样目的?② 这个改动**扩大**了吗?③ 失败时的后果对称吗?
|
||||
- ⚠️ **边界(U27)**:A6 只约束**路径**(实现取最小代价),**不约束目标** —— 不许把"选最小代价"读成"降低目标 / 延期 / 静默兜底"。**目标不打折,路径取最小代价。**
|
||||
|
||||
### A7|能一行代码解决,就不要改平台配置
|
||||
- **实例**:实例内 Python 抓 HTTPS 报 CA 错 → 正解是脚本里 `SSL_CERT_FILE=/etc/pki/tls/certs/ca-bundle.crt`,**不走 R5 注入 env**(因为注入 env = 扩大,而一行代码就够了)
|
||||
- **判据** → 平台级改动(env / 挂载 / nft / 配额)是**最后手段**,不是第一手段
|
||||
|
||||
### A8|遇到"要删/要迁移"先判代价对称性;不对称 → 保留
|
||||
- **实例**:`folder_plugins` / `workspaces` 表**加废弃注释保留**(跨 10 文件 + 含 k8s/PG 未验证路径 → 删除风险不对称);4 份 cold 档案不迁 archive(收益小);技能包裁剪则相反 —— 真 0 引用的才剔
|
||||
- **判据** → 删除的**收益 < 潜在破坏**时,选择"标注废弃 + 禁止再加功能",而不是删
|
||||
|
||||
### A9|明确「不做」并写明「打开条件」
|
||||
- **实例**:白名单源码安装 **不做**(与"平台不执行第三方构建脚本"红线冲突)→ 同时留「打开条件清单」(沙箱构建 / `--ignore-scripts` / 仅 admin / 审计 / 全量扫描);熔断实测、管理类插件化也都明确关闭
|
||||
- **做法** → 「关闭」必须写两句:**为什么不做** + **什么条件下可以重开**;只写"不做"会在下次被重新提起
|
||||
|
||||
### A10|失败面要留证据,不要吞错误
|
||||
- **实例**:插件探活失败**回传 dsh 真实错误**(`duplicate loader entry id` / `ERR_MODULE_NOT_FOUND`),不要泛化成"插件不兼容";坏包隔离并改名标注 `-BAD-missing-index.tgz`
|
||||
- **判据** → 报错信息是 admin 判断根因的**唯一线索**,泛化等于毁掉线索
|
||||
|
||||
### A11|不确定的能力显式抛 `unsupported`,不假装支持
|
||||
- **实例**:`K8sUserFs.readFile` **显式抛 `unsupported`**(sidecar 尚无端点)→ 「属未验证路径,**不假装支持**」
|
||||
- **判据** → 本地验证过的能力才写"支持";没验证的路径要么标注"未验证",要么直接拒绝
|
||||
|
||||
### A12|只读核对也要留痕(不改也要出结论)
|
||||
- **实例**:所有"核查 / 取证 / 评估"类任务都产出档案(编号 + 状态 + 触发 + 结论表),即使**一行代码都没改**
|
||||
- **判据** → 「核查完成」本身就是一个交付物;不落档的结论等于没发生(下次会重复发现)
|
||||
|
||||
### A13|自查要分「当时成文的口径」与「新立的口径」
|
||||
- **实例**:越界自查结论 = 按当时的 R1-R6 **未违反**;按当天新立的 R7/R8 则**5 次实质越界** —— 两种口径都给出,不粉饰
|
||||
- **判据** → 复盘/自查时**说明用的是哪一版标准**,否则结论不可信
|
||||
|
||||
|
||||
### A14|删除 / 移除 / 下线前,先查清楚再动手(用户 2026-09-12 明确)
|
||||
|
||||
- **实例(我的失手)**:我把服务器上两个文件报成"多余、待用户定是否删除",却**没先看它们是什么** —— 一查才发现三件事:
|
||||
① 本机 `07-scripts/` 里**都有**(我只 `ls` 了根目录就说"本机没有")
|
||||
② 服务器那两份**早已被并行会话清掉**(我把一个**已消失**的问题抛给了用户)
|
||||
③ 顺着 `grep -rn` 找到档案 73,一句话就看清用途 —— `lock-guard-hook.py` 是 **PreToolUse 强制钩子**
|
||||
- **删除前三问(没答完就不动)**:
|
||||
1. **它是什么** —— 读内容 / 读关联档案的 TL;DR,**不要凭文件名猜**。
|
||||
2. **被谁引用** —— `grep -rn <名> --include="*.md" --include="*.ts" --include="*.cjs"`;**全库 `find`,不要只看当前目录**。
|
||||
3. **删了影响谁** —— 是否有别的会话 / 服务 / cron 在用;**是不是唯一副本**。
|
||||
- **判据** → **未查明就不动**;查明后确认是"**放错位置的多余副本**"(正本在别处且 md5 一致)才可直接清理。
|
||||
- 与 **A8** 配合:删除是**风险不对称**动作(删错 = 丢失,留着 = 只占空间)→ **默认保留**,除非已查清。
|
||||
|
||||
### A15|写状态必须带「三态 + 级别」,禁止用「支持 / 可用」描述未验证项
|
||||
|
||||
- **实例**:开源文档把未验证的 Kubernetes 模式写成**方案 B** → 用户纠正:「模式 B · Kubernetes **去掉这个,根本没验证**,应该是**待开发验证**」。
|
||||
- **三态词表(强制)**:
|
||||
| 写法 | 什么时候能用 | 必须附 |
|
||||
|---|---|---|
|
||||
| ✅ **已验证** | 有**可复跑**的命令 / 日志 / 截图,且**取数时间**明确 | 命令 + 期望输出(§4.3 L2–L5) |
|
||||
| ⚠️ **待开发验证** | 代码 / 文档存在,但没跑过端到端 | 「未验证」三个字必须出现在**结论句**里 |
|
||||
| ❌ **已知不支持** | 实测证伪 | 失败证据 + 复现条件 |
|
||||
⛔ **禁用词**:「支持 / 可用 / 已实现 / 已落地」**不得**用于 ⚠️ 段;上一轮(档案 76 §10.7)就是**用文件名代替读包**,把「没这能力」说成了结论。
|
||||
- 落地:开源 README / 档案状态 / 能力清单 / 交付回执 **四处统一用这套词**。
|
||||
|
||||
---
|
||||
|
||||
### A16|回滚 / 改名 / 迁移类动作:先列「伴随物清单」,只改主体必留隐患
|
||||
|
||||
- **实例(同日两起)**:① **回滚只回滚了部署、没回滚源码** → 下次重建又把补丁带回来(0.2.19 误带堆限 ⇒ 0.2.20 才真修);② **改 SQLite 库名漏了 `-wal` / `-shm`** → 358 KB WAL 未被 replay、**丢了 2 条会话记录**(归位后 4→6 恢复)。
|
||||
- **伴随物清单(动手前逐项打勾)**:
|
||||
| 动作 | 主体 | **必须一起处理的伴随物** |
|
||||
|---|---|---|
|
||||
| 回滚 | 制品 / 部署 | **源码** + 构建缓存 + lockfile + 实例内已加载的 bundle |
|
||||
| 改名 / 迁移 | 主文件 | **旁路文件**(SQLite `-wal` `-shm`)· 目录 · 符号链接 · 所有引用点(`grep -rn`)· 运行中的进程 / 服务 |
|
||||
| 批量替换 | 命中文件 | 自引用 / 自赋值(`replace_all` 会命中刚插入的定义行)· 行尾风格 · 语法校验(用 build 当校验器) |
|
||||
- **判据** → 凡「一个名字 / 一份数据 / 一段制品」被改或退回,**先写出它的伴随物清单**再动手;**改完必须读回复核**(不靠「应该没问题」)。
|
||||
|
||||
|
||||
### A17|判「这是限制」之前先分层取证:配置项 / 已抽象层 / 真硬编码
|
||||
|
||||
- **实例(用户当场纠正我)**:我把「DB 是单文件 SQLite」列为集群化的限制 → 用户口径「**可以改为连接数据库集群,数据库不是限制**」;实测 `DSHS_DB_URL` 非空即切 PG(`db/index.ts:19`),`db/adapter.ts` 头注释已声明「routes depend only on this abstraction」⇒ **早有抽象,是配置项不是天花板**。
|
||||
- **判据** → 任何「做不到 / 是限制 / 是天花板」的结论,先把它归到三类之一并给出**代码行号或命令**:① 配置项(改 env/参数即可)② 已抽象层(换实现后端)③ 真硬编码(必须改码)。
|
||||
- 反面同时成立:**别把「能配置」当成「已经能用」** —— 同一次实测才发现 `dsh_instances` 归属表**只有 k8s 路径在写**(`LocalSpawner` 根本不收 db)⇒「换库单独做 = 零收益」。
|
||||
|
||||
### A18|静默失败会伪造结论:工具静默 + 降级静默,两头都要防
|
||||
|
||||
- **实例(同日两起,都差点骗了我)**:① `grep -v node_modules` 把**要查的行本身**也滤掉 ⇒ 得出"源仓 0 处"的**假结论**(改用 ripgrep 才看到真相);`rg` 在本机 PATH 不存在 + `2>/dev/null` ⇒ **静默返回空**,看起来像"扫干净了"。② `listCatalogProviders()` 的 readdir 抛错被 catch 吞掉返回 `[]`,注释还把降级写成特性 ⇒ **"没生效"和"没做"不可区分**,缺陷潜伏三轮。
|
||||
- **判据** → **断言"扫干净了 / 没有 / 全绿"之前,先自证工具真的跑了**:跑一次已知命中的探测、看退出码、别用 `2>/dev/null` 掩盖失败;排依赖目录用 `--exclude-dir`/`.gitignore`,**不要用行过滤**。
|
||||
- - ⚠️ **姊妹坑:把失败误读成成功**(2026-09-15 实证)—— 用管道截尾看命令输出时(`| grep` / `| tail`),**失败提示里也含成功关键词** ⇒ 假命中 ⇒ "以为抢到锁了"却在无锁状态改库。
|
||||
✅ **判据**:**先看退出码**(不要接管道),再**复读关键状态文件/OWNER 并断言**;"输出了像成功的话"**不等于**操作成功。
|
||||
|
||||
**降级必须留痕**:静默 catch 至少 `console.warn` 一次,或把「不可读 / 目录为空」**透出到状态端点**(本次已落地:`/api/me/model-providers` 的 `catalog{dir,readable,count}`)。
|
||||
|
||||
### A19|验收判据必须包含「第二环境」——同环境反复通过会掩盖跨环境从未验证
|
||||
|
||||
- **实例**:写死 `/usr/local/lib/node_modules` 在本机(npm 默认 prefix)**恰好是对的** ⇒ 端到端验收"38 家全绿"只证明了"**在这一台机器上**对";换 `/usr/lib` 布局(`install.sh` 部署的机器)则厂家目录读空、兼容性预检**整体失效**、目录选择器 import 即抛 —— 且**全都静默**。同一个未验证假设被**复制了三轮**(picker → plugin-compat → model-catalog)。
|
||||
- **判据** → ① 凡「读**别人**安装位置 / 版本 / 布局」的代码,路径**必须走解析层**,且**至少一条单测用假根**(已落地 `07-scripts/verify-dsh-install.mjs`,15 项断言);② 验收判据**显式包含"非本机布局"**(一句 env 注入即可);③ 前端验收**别用 fixture 桩**掩盖后端不可读(本次就是断言全绿而端点其实是空的)。
|
||||
- **🔑 信号识别**:注释里出现「**本部署事实 / 目前是 / 暂时**」⇒ **当场转成待验证项**(那是作者自己知道这是假设的痕迹)。
|
||||
|
||||
### A20|存量烂账(巨量重复 / 历史遗留):选「只增不改 + 库外视图」,不就地重写
|
||||
|
||||
- **实例**:档案 82 = 2024 行 / 89.1 KB,切 **224 块**后 **重复标题 22 个、冗余块 190 个(≈85%)**;但「八、口径提醒」有**两个内容不同的变体** ⇒ **不是纯复制,盲目去重会丢信息**。
|
||||
- **做法(零改写)**:原文**一字未改** → 文末追加「修正(日期)」小节(实测数据 + 视图路径 + 阅读建议)→ 生成**去重视图**(保留每组信息最全的一份,其余留占位注释)**只写库外** `.workbuddy/cache/dedupe-view/` → manifest 加 `dedupeView` 字段、检索命中时提示"优先读视图"。89.1 KB → 59.0 KB,**零风险**。
|
||||
- **判据** → ① 先做**变体检测(同名 ≠ 同内容)**再决定能不能去重;② **写入权留在原文**(历史冻结),派生物放库外;③ 根治(拆分)与止血(视图)**分开立项**,别用一次大改解决两件事。
|
||||
|
||||
### A21|任何自动判据都要报「分布」;失效就改,别让它假装有区分度
|
||||
|
||||
- **实例**:`tier` 判据原为"被引用次数 ≥8" ⇒ **hot 44/89 ≈ 一半**(等于没筛);改为「**谁在引**」四档(hot = 被 L1/L2 现行层引 ≥3 次)⇒ **hot 7/89(8%)** ✓。⚠️ 我第一版把 **L4 台账类**也算现行层 ⇒ hot 反升到 60,**更糟**(台账会顺带列出几乎所有档案号,**索引式提及 ≠ 要读**)。
|
||||
- **判据** → ① 判据上线时必须报**分布**(各档占比),一眼看出有没有区分度;② **区分"顺带列举"与"真的依赖"**(索引/台账/清单类文件的提及**不算**引用);③ 判据本身要定期体检(老判据会随规模失效)。
|
||||
|
||||
### A22|替换 / 退役类动作的顺序:先补位,再退役
|
||||
|
||||
- **实例**:univer 承担 ① AI 生成 docx/xlsx ② Office 导入导出 ③ `.univer` 协作预览(**独有**)⇒ 要弃用必须**先把 ① 换成 `dsh-office` 并验证**,再停 univer;「**顺序不能倒**」。同理 `@softspark/dsh-file-preview` 的退役**必须等平台升级(阶段 4)之后** —— 现在退 = 生产立刻失去预览。
|
||||
- **判据** → 动「下线 / 替换 / 摘除」之前先写三行:**它现在承担什么**(逐项列)→ **每一项换成什么 + 验证过没有** → **换完之前不许停**。
|
||||
- 与 **A16(伴随物清单)** 互补:A16 管"要一起改什么",本条管"**先做哪一步**"。
|
||||
|
||||
### A23|流程类失效多半不是「忘了」,而是「触发词没命中」
|
||||
|
||||
- **实例(2026-09-14 事故复盘,档案 95)**:改平台代码 / 铺插件 / 重启 `dshs` 时,AI **没把自己这次动作分类成"落地一次改造"** ⇒ 六阶段流程**整条不存在**(阶段 0 前置检查、阶段 2 方案确认、阶段 5 归档全缺)。自审原话:「**本技能就在本机,我一开始没加载;直到用户追问才加载**」。
|
||||
- **根因是结构性的**:流程只写在**按需加载的技能**里,而常驻层 `CODEBUDDY.md §2` 自己就写着「**技能的加载由模型判断相关性,不能保证**」 ⇒ **没加载 = 没有流程**。
|
||||
- **判据** → ① 凡「**动作前必须生效**」的规则,**必须写进常驻层**(项目根 `CODEBUDDY.md` / `MEMORY.md`),技能只放"需要时去拿的方法论";② 常驻层的**触发条件要用「动作词」**("要改平台代码 / 要铺插件 / 要重启服务"),**不要依赖模型自我分类**("我要做一次改造"这种判断本身就会失效);③ 自审时区分**"当时成文口径"与"新立口径"**(A13)—— 本次 95 的自审引的是**过期 R8**(要求"取得确认"),而 R8 已于 09-13 由用户改为"开发环境服务器不必等确认,只需动手前一句话说明"⇒ 两栏都要给,否则违规被高估。
|
||||
|
||||
### A24|拦截面必须覆盖「真实行为面」——装在工具上的闸门,拦不住正文里的行为
|
||||
|
||||
- **实例(2026-09-15 实测)**:昨天给「提问闸门」装了 `PreToolUse` + matcher `^AskUserQuestion$` 的 hook,想治"AI 老让用户确认简单问题"。今天核账:本工作区日志 `tool=AskUserQuestion` 调用数 = **09-12: 43 / 09-13: 3 / 09-14: 0 / 09-15: 0**(`UserQuestion`/`elicitation` 的命中全是 `--tools` 参数与 host capability 字符串,不是调用)⇒ **真实上抛几乎全在正文里,hook 从装好那天起就 0 命中**。
|
||||
- **判据** → 设计任何"拦截 / 校验 / 门禁"之前,先**用日志或计数证明行为发生在哪一面**:
|
||||
① 统计**该面的真实发生率**(不是"应该有");② 若闸门装面上限远低于行为面,**闸门等于装饰**(还制造"已经治好了"的假安全感);
|
||||
③ 正文类行为(无法被工具 hook 拦)只能靠**常驻层的可执行自检动作**(详见 `CODEBUDDY.md §1` "回话前自检")或 **Stop hook 扫最后一条回复**。
|
||||
- **可复跑的核账命令**:`grep -c "tool=AskUserQuestion" <工作区宿主日志>`(宿主日志在 `~/.workbuddy/logs/<日期>/<工作区名>__*.log`,记录 `[ToolManager] execute | tool=X`)。
|
||||
|
||||
### A25|本机改完 ≠ 交付 —— 先画出「改动层 → 生效链路」再宣布完成
|
||||
|
||||
- **实例(同类 3 次,2026-09-13/14/15)**:① 只做到**本地打包、没部署** ⇒ 用户「点开看还是和之前一样」;② 平台登录页/运行时**只改本机、从没部署到服务器** ⇒ 用户看的是旧页面(原话:「**那你看的当然还是旧页面**」)。
|
||||
- **判据** → 宣布完成前逐项答三句:**① 改的是哪一层?② 这一层的生效链路是什么?③ 最后一步走了吗、在「用户可见面」验了吗?**
|
||||
链路清单(缺一步都不算交付)见 `dsh-change-workflow` **阶段 5 §0「交付门禁」**表格:静态页 = scp(含 CDN 缓存坑)|平台 TS = build + restart|插件 = tgz → 候选池 → 实例启用 → **重启实例**|文档库/技能 = scp + 对账|配置 = 改 + reload/restart。
|
||||
- **四条"自我安慰",一条都不算交付**:**本机改完了** · **build 通过了** · **本地打包完成** · **已 commit 了**。
|
||||
- 与 **A19**(验收要含第二环境)互补:**A19 管"在哪个环境验",本条管"链路走没走完"**;与 **U20 / X9** 互补:部署本身**不必问用户**,但**必须做**。
|
||||
@@ -0,0 +1,194 @@
|
||||
# 素材库 · 用户的有效决策(U1–U24)
|
||||
|
||||
> **归属**:技能 `dsh-decision-method` 的素材库(**按需读**,不是每次都要读)。
|
||||
> **主文件 / 索引 / 判定核心** = `../SKILL.md`(§4 判定核心 · §5 流程 · §7 语言表 · 附 自检)。
|
||||
> **用法**:只在「要判某条是否属于既有口径」或「要引用用户原话」时读本文件;**别整段抄进答复**。
|
||||
> **维护**:条目**只增不改**(编号进位到末尾);用户原话**逐字**引用;每条必须带「实例出处 + 判据」。
|
||||
|
||||
---
|
||||
|
||||
## 1. 决策素材库 · 用户的有效决策(U1–U22)
|
||||
|
||||
> 「有效」= 事后被证明正确、且已被落地验证。**这些是用户的稳定偏好,不是一次性指令** —— 新需求来时可以按此预判方向。
|
||||
|
||||
### U1|面向用户的东西只保留「用户视角」,不暴露平台内部
|
||||
- **原话**:「只允许在自己的目录下创建工作区」「**不要给用户看完整路径**」;「用户就只能访问(含读取)dsh 服务用户 id 对应的那个文件夹,**连读都不要读取**」
|
||||
- **落地**:picker 根固定 `<userRoot>/ws`、面包屑显示「我的工作区」、下载走平台代理不暴露宿主路径(档案 17/18/39/56)
|
||||
- **判据** → 任何 UI/接口会暴露**绝对路径、uuid、内部术语、宿主目录名**的,一律收敛;收敛不需确认,扩大才需要(见 R5)
|
||||
|
||||
### U2|不做两套实现,能扩展就不新建
|
||||
- **原话**:T01「实例内我的技能 → **扩展 business-plugins 不用做两套**」(否决了"新建 `@dsh-local/my-skills`")
|
||||
- **判据** → 已有扩展点能承载(哪怕要加一个 section / 一个路由)→ **优先扩展**;新建只在"语义完全不同 + 复用会耦合"时才提
|
||||
|
||||
### U3|删任何东西之前先扫引用("看起来像资料"≠"没被引用")
|
||||
- **原话**:「参考资料是不需要」(针对 MCN 技能包裁剪)
|
||||
- **AI 的正确处置**:扫描后发现三类"像资料"的其实是被引用的**功能件** —— `nuwa-skill-main/` 主体被引为"主方法论"、`references/样例/` 被 `06_生成账号设定卡片.md:67` 写"动手前必须先读" → **保留**;只剔真 0 引用的块;且**剔 `browser-harness/` 目录必须同步改文档**,否则留死引用(档案 T03 §4.1 裁剪表)
|
||||
- **判据** → 删除类需求的**第一步永远是引用扫描**(`grep -rIn` + 排除说明行),产出"引用实测表"再定取舍;**剔除目录 = 必须同改引用它的文档**
|
||||
|
||||
### U4|交付面越少越好(推翻架构洁癖)
|
||||
- **原话**:「**业务技能要打包进插件里一起安装使用,不要分开管理**」(推翻 AI 既有的"技能走平台共享技能层"结论)
|
||||
- **判据** → 用户的心智模型("我装一个插件就全有了")**优先于**架构上的"分层更干净";一个包能解决就别拆成两条投放链路
|
||||
|
||||
### U5|状态变化必须让用户感知到(无反馈 = 缺陷)
|
||||
- **原话**:「点重连成功,但**过程中没有任何加载动画**」;「**AI 生成的文件看不到、下不了**,本机地址浏览器打不开」
|
||||
- **落地**:XHR 挂起 3 秒上覆盖层(档案 59)、右下角「📁 我的文件 / 🧭 能力」、档位提示条(档案 56)
|
||||
- **判据** → 后端正确但用户"看不见 / 点不动 / 不知道在等什么" = **同等优先级的功能缺陷**;凡有等待、有状态、有产出的地方都要有可见反馈
|
||||
|
||||
### U6|同一主题一次性做透
|
||||
- **原话**:「**一次性优化到位**」;「AI 对话记录(sessions)保留时间**可以长些**」
|
||||
- **判据** → 用户讨厌"打补丁式小改";同主题一次列全(如清理策略一次落 5 项);用户给方向性偏好("长些")时**自己定量再回填**,不要反复问
|
||||
|
||||
### U7|信息层级要站在"看得懂"的角度,而不是开发者视角
|
||||
- **原话**:「**导入到候选池是什么意思**」「官方插件优先展示应该是**插件说明或中文名称**,需要**一眼知道这个插件是干什么的**」
|
||||
- **落地**:白名单首列由插件名改**中文说明**(2 行 clamp),技术标识降副行;「候选池」→「导入到平台」;加一句「**投放 ≠ 生效**」的说明(档案 31)
|
||||
- **判据** → 表格/列表首列放**用户能读懂的那一列**;内部术语不得直接上页面
|
||||
|
||||
### U8|权限方向只准收窄,扩大必须先确认
|
||||
- **原话**:(R5 由来)用户明确划定:收窄可直接做,**扩大一律先出「权限影响评估」四问**
|
||||
- **判据** → 任何改动先答「这次是**扩大**还是**收窄**」;命中扩大(新增挂载 / 放开遮蔽 / 暴露平台目录或 env / 放宽 ALLOWED_ENV / 放松 nft / 提档位 / 新增可读写路径 / 让 root 执行链路的对象变用户可控)→ **停手等确认**
|
||||
|
||||
### U9|明确「暂缓」也是决策
|
||||
- **实例**:档案 21 后续(禁 HMR / catch-all vhost)「用户已决定暂缓」;域名切换侦察后用户说"还没准备好" → **parked,不再推进,等用户主动提起**
|
||||
- **判据** → 前置条件在用户侧(备案 / 账号 / 供应商)时,**给出"需你先办的三件事"然后 parked**,不要反复追问或硬推
|
||||
|
||||
### U10|术语统一只改用户可见的那一层
|
||||
- **原话**:「将所有**业务插件**字段改为**功能插件**」→ 后来「将**功能插件**改为**功能管理**」
|
||||
- **AI 的正确收窄**:只改**显示文案/label**(zh+en 同步),**代码标识符、表名、包名、API 路径、文件名一律不动**;同一 locale 里描述"插件这个事物"的句子也**刻意不改**(分区叫「功能管理」,管的对象仍叫「功能插件」)
|
||||
- **判据** → 术语需求 = **label 级改动**;一旦要动标识符就是大范围重命名 → 回到 R7 先出清单
|
||||
|
||||
### U11|用户给的数值即使偏离规范也是硬约束
|
||||
- **原话**:「插件管理的官方插件管理 列表页高度增加 和页面底部间隔 **200PX** 即可」
|
||||
- **落地**:`#view.page-plugins { padding-bottom: 200px }`,**代码注释注明**「`01-规范/06-工作台UI规范` 常规区间是 14~24px,**200px 是用户明确指定的例外**」(档案 61)
|
||||
- **判据** → 用户点名数值 → **照做 + 注释固化来源**,防止日后被"按规范修正"回去;与规范冲突时在注释里写清是例外
|
||||
|
||||
### U12|危险操作要确认弹窗 + 明说后果
|
||||
- **原话/定稿**(档案 16 §2.2):批量启用禁用 → **必须点确认弹窗**,弹窗内写明「**将重启实例,会话可能中断**」
|
||||
- **判据** → 任何会打断用户当前状态的操作(重启实例 / 停会话 / 清数据)→ 前端确认 + 明写后果;后端配合「先备份再执行」
|
||||
|
||||
---
|
||||
|
||||
### U13–U19|2026-09-12 用原始会话转录回补核对后新增
|
||||
|
||||
> 前 12 条来自**档案 + 工作日志**(会话的结构化沉淀)。这 7 条是拿 `07-scripts/extract-user-voice.py` 抽出
|
||||
> **180 条用户真实发言**(跨 09-08→09-12、5 个会话)逐条比对后**补上的漏项**。
|
||||
|
||||
### U13|我报给用户的数字,会被他当作事实基础
|
||||
- **实例**:09-12 00:06 用户直接引用我的读数再追问 ——「当前实况:2 个实例在跑,占用 **212 MiB** 和 **329 MiB**:为什么一个用户要占用这么多内存」
|
||||
- **判据** → **报数必须准确、并带取数时间与口径**;分母/单位错一次就会被当成事实传下去(档案 58 曾把 `systemd` 的**字节**当 KB,读数放大 1024 倍)
|
||||
|
||||
### U14|判断「该不该留」用的判据是「**有没有复用价值**」
|
||||
- **原话**:「是不是搞错了,**AI 生成的代码和脚本等才是需要重点定期清理的**」「这些脚本基本都是根据某个对话任务产生,**没有复用价值**」
|
||||
- **判据** → 取舍类需求**先问"这东西有没有复用价值"**,而不是问"它看起来像什么"(对照 U3:先扫引用)
|
||||
|
||||
### U15|用户会盯**产品级容量约束**(能撑多少人)
|
||||
- **原话**:「这个应该属于**控制用户上限**,不能让 10 个用户注册每个用户体验都差」
|
||||
- **判据** → 用户提需求时**隐含容量期望**;凡涉及常驻资源 / 并发 / 注册量,**主动把容量影响算出来讲清**(引用档案 58 的实测:2 vCPU / 1870 MiB,并发上限 ≈ 3 实例)
|
||||
|
||||
### U16|用户给的「实现建议」是**意图表达**,不是硬要求
|
||||
- **实例**:09-12 09:39 用户提「检测鼠标移动/焦点自动拉起实例」→ 被论证「同时动鼠标会 OOM」后**他接受了否决**,并把话题转到容量上限(U15)
|
||||
- **判据** → 可以(也应该)用更优方案替代,**但必须说明为什么否决**;不要为了"照做"而实现一个坏方案
|
||||
|
||||
### U17|用户会充当**执行手** —— 必须给可直接粘贴的完整命令
|
||||
- **原话**:「还需要建立 ssh 链接 **端口号 32022**」「我的意思有些操作需要 ssh 执行」「**给我个命令去服务器上执行就行**」
|
||||
- **判据** → 凡需要用户动手的(服务器命令 / 浏览器验证 / 关应用再执行),**给一条完整可粘贴的命令 + 期望输出**,不要让用户拼命令;需要他关掉某程序时,要说清"为什么要关"
|
||||
|
||||
### U18|用户会明确「关闭」一条线 —— 关闭后不再推进
|
||||
- **原话**:「**忘记这个项目把**」(否决 my-deepseek-harness 二开路线);「**还没准备好 后面再说**」(域名切换 parked);「**档案 21(卡顿/流式)可以展缓**」
|
||||
- **判据** → 看到这类措辞**立即 parked**:保留已得结论、不再追问、不列入待办;**等用户主动提起**(同 U9,但这条是"用户主动关",U9 是"AI 建议暂缓")
|
||||
|
||||
### U19|用户大量时间花在**平台能力认知**类提问上
|
||||
- **原话**:「dsh 插件开发 不同的插件 代码都是独立的吗」「一个插件的功能都在一个文件夹中吗,是否可以像 SKILL 管理一样做一个插件管理页面」「插件可以热更新 热加载吗」
|
||||
- **判据** → 这类"**是什么 / 能不能**"的往返,**应由「能力清单」类交付物一次性消除**(档案 56 的 `platform-capabilities` 共享技能 + 实例页「能力」面板就是为此而生);**每做一次能力变更,同步更新能力清单**
|
||||
|
||||
### U20|「不打断用户的上线」不要问 —— 部署 / 上线属执行细节(2026-09-13 用户纠正)
|
||||
|
||||
- **原话**:「**为什么要等我确认才部署呢,我看线上效果才知道是否满足需求**」
|
||||
- **背景(真实失手)**:v0.2.8 已打好包,`ensure-biz-plugins.cjs --all` **只换 profile 里的包**(不重启、不停实例、**零中断**),AI 却按 R7「只做被明确要求的事」**停下等确认** ⇒ 用户看不到线上效果,**无法判断需求是否被满足**。
|
||||
- **判据** → **红线的触发按「实际影响面」判,不按「动作名字」判**:
|
||||
- R8 的**唯一**触发条件 = **会中断在线用户**(重启 `dshs` / 停实例 scope / drain / 改实例配额·env / 改 nginx·nft);
|
||||
- **不中断**的上线(传产物到 `/opt/dsh/artifacts`、换 profile 包、改静态页、候选池投放)= 边界内已列的「**部署与同步**」⇒ **做完即上线**,事后一句「我选了什么(可推翻)」交代即可。
|
||||
- **与 R7 的边界**:R7 管的是「**未经确认的批量 / 全仓写入**」和「**范围外的额外改动**」,**不管「该不该上线」**;把 R7 的精神套到上线动作上 = **过度套用**(见 X9)。
|
||||
|
||||
### U21|答复要「结论三件套」:是否已实现 → 为什么不行 → 要拍板什么(2026-09-13 用户纠正)
|
||||
|
||||
- **原话**:「**需要告诉我的是 是否已实现,如果未实现:为什么不能,需要我拍板可以问我**」
|
||||
- **背景(真实失手)**:AI 用「我自己的失误(一并交代)+ 探针怎么被污染 + 版本流水(0.2.19/0.2.20/0.2.23)+ 下一步三步计划」回答了「是否已实现」——用户要的结论**在第 5 段之后**才出现;收尾还问「要我现在接着做,说一声即可」。
|
||||
- **判据** → 回答「是否 / 能不能 / 为什么不行」类提问,**固定四节、顺序不变、没有的节整节删掉**:
|
||||
① **判定**(✅ 已实现 / ⚠️ 部分可用 / ❌ 未实现 + 一句话;用户列了多项就逐项给)
|
||||
② **为什么不行**(按层:已排除的原因 → 当前唯一卡点,最多 3 层)
|
||||
③ **我接着做**(**陈述句**,不是征询句)
|
||||
④ **需要你拍板**(**必须是整条回复的最后一节** —— 它后面不许再有任何节;**真需要才写**,不需要就删掉整节)
|
||||
- **四条铁律**:主位必须是**用户问的那件事**(AI 的进度 / 失误 / 计划不得占前两节)· 结论层**零技术标识** · **禁征询式收尾**(已定的下一步直接做)· **待拍板项置末**。
|
||||
- **修正(2026-09-15 用户明令 · 完整原话)**:「**能根据决策方法 自行决策的就自决策继续处理,不能决策的问题和需确认内容放在回复的最后,按照有序段落展示**」⇒ ③④ **对调**(原为 ③ 拍板 → ④ 接着做),且该节要**逐条编号**(有序段落,不写成散文)。⚠️ 分清三件事:**自决**(能判的别问,直接做完并陈述)· **位置**(不能自决的收到最后一节)· **形态**(陈述句列「选项 + 优缺点 + 我的倾向」,⛔ 不是征询句"要不要我…" / "说一声即可")。
|
||||
- **修正 2(2026-09-15 用户明令)**:「**需要我确认的方案需要说明优点和缺点,现在没法判断,假如只有优点或只有缺点那不需要我判断**」⇒ **上抛前先过「取舍筛」**:候选各写**优点 + 缺点** —— ① 某个**只有优点**(明显更优)或**只有缺点** ⇒ **不需要用户判断**,自己拍掉再陈述;② 只有**各有优有劣、客观标准分不出高下**(真取舍)才上抛;③ 上抛时**必须逐项列出优点与缺点**(只写"可感知差别"**不算** —— 用户原话「现在没法判断」就是这么来的)。落地载体:`dsh-feature-first §5.3 铁律 5 / §5.4 硬约束 8 / 反模式 12`。
|
||||
- **修正 3(2026-09-15 用户明令)**:「**每个需要我决策的问题的潜在解决方案 A B C 也按照段落式排版,别横着排列**」⇒ 候选**竖排成段**(A / B / C **各占一行**),⛔ 不许写成 `A:… · B:…` 一行横排,⛔ 也不许把候选做成**表格的列**(表格是横向对比,与"段落式"正相反)。段内「优点…;缺点…」连写即可,不必每个字段再拆行(否则撞 §5.4 硬约束 3「每节 ≤7 行」)。落地载体:`dsh-feature-first §5.3 铁律 5 ④ / §5.4 硬约束 9 / 反模式 13`。⚠️ 触发它的正是**我自己的实际输出**(把三个候选写成 `A 维持现状 · B 按 50 KB 切分 · C 改成按月分片` 一行并列)。
|
||||
- 落地载体:`dsh-feature-first §5.1–§5.3`(含**可复制骨架**);与 **X10**、**U20 / X9** 同族(都是「别把该自己拍的推回去」)。
|
||||
|
||||
### U22|只碰自己 lane 的东西;平台级 / 全局 / 别人 lane 一律只报告(2026-09-13 用户明令)
|
||||
|
||||
- **原话**:「**谁让你去改这个的**」+「**不是自己负责的任务相关文件不要去改**」
|
||||
- **背景(真实越界)**:为打通自己任务的插件投放(撞 `ERR_PNPM_UNEXPECTED_STORE`),AI **自行创建了 `/var/lib/dshs` 全局符号链接** —— 无人授权,且属**平台级路径**。用户当场追问「谁让你去改这个的」;AI 随即自行撤销并确认实例不依赖它。
|
||||
- **判据** → **动手前先问「这在谁的 lane」**:
|
||||
- **我的 lane(可自己拍)**:① 我负责的插件源码 / 产物 ② 该 profile 的依赖安装 ③ 我自己的临时脚本 ④ 我方案内的执行细节(部署 / 上线 / 重启 / 改配置)
|
||||
- **不是我的 lane(只报告、不动手)**:平台级路径与全局文件(`/var/lib/**`、符号链接、systemd 单元、nginx·nft)· 别人的 profile / 产物 / lane · 与本次任务无关的文件
|
||||
- **与 R7 的关系**:R7 适用于「不是我的 lane」,**不适用**于「我 lane 内的执行细节」—— 两个方向都别套错(对称面见 **U20 / X9**)。
|
||||
- ⚠️ **动机不构成豁免**:「**改它能让我流程跑通**」正是越界的高发动机 ⇒ 越方便越要先问「这是谁的 lane」。
|
||||
|
||||
---
|
||||
|
||||
|
||||
### U23|不要重新开发:先查官方推荐库有没有现成的(2026-09-14 用户口径)
|
||||
|
||||
- **原话**:「**需要查官方推荐库是否有类似插件,是重新开发还是改造**」(背景:univer 太重,要"点对话里的文件在旁边窗口打开")
|
||||
- **结果**:官方推荐库里拿到 **`@softspark/dsh-file-preview` v2.0.0(65 KB tgz)** ⇒ 体积约 univer 的 **1/650**,且未动 univer 一处。
|
||||
- **判据** → 要加任何能力,**顺序固定**:① 本机/项目已有 ② **官方推荐库**(`Awesome-DeepSeek-Harness-Plugins`,源 = cordis.run 索引 331 个)③ npm `keywords:dsh-plugin` ④ 才考虑自研/改造。
|
||||
- **候选体检三关(缺一即否)**:① inject 依赖的**官方包存在吗** ② 有没有**被角色补丁禁**的包(⇒ 静默挂死)③ `peerDependencies` 是否**覆盖我们的 dsh 版本**。反例:`dsh-file-viewer` inject 含本平台不存在的 `dsh-client-runtime` ⇒ 装上即静默挂死。
|
||||
|
||||
### U24|分期方案必须互相兼容(2026-09-14 用户口径)
|
||||
|
||||
- **原话**:「**一/二期方案必须互相兼容**」(集群化改造 Manager/Worker)
|
||||
- **落地原则**:**分期只分「自动化程度与规模」,不分「机制 / 数据结构 / 协议」** —— 机制与结构**一期定死**,二期只加机器 / 加开关 / 加运维。
|
||||
- **可执行判据(7 维度兼容矩阵)**:Manager 数(同代码 1..N,**禁止"必须 2 台"的硬假设**)|Worker 数(一期就走 RemoteSpawner+agent,哪怕 Worker 在本机)|存储(一期就写能力探测 + 按目录分层)|DB(**一期必须 PG**,不能先用 SQLite 顶——租约依赖 PG 原子 `UPDATE…WHERE`)|自动接管(开关默认关,但 **lease+fencing+self-fencing 一期全实现**)|备份(一期就用同一套工具/格式,只调频率)|代理路由(零改动)。
|
||||
- **配套**:新增「**状态三分类**」表(用户数据 / 平台状态 / 机器基线)—— 机器基线(原生运行时、镜像、bwrap 白名单)**不能跟着用户迁移**。
|
||||
|
||||
### U25|锁是独占资源:抢到就必须还 ——「带锁结束」不算完成(2026-09-14 用户明令)
|
||||
|
||||
- **原话**:「抢到的锁一定要**执行完成后解锁**才算任务完成,**禁止抢锁执行一半不解锁就结束任务**」
|
||||
- **为什么是硬规则**:锁的意义就是**同一时刻只允许一个执行会话**(本库多会话并行是常态)⇒ **带锁结束 = 把所有其他会话挡在门外**;而本库**无心跳机制**、别人**没有任何判据**能确认你已停 ⇒ 只能空等,或被人误判"已死"而违规接管(**R9** 禁止)。这正是 R9 存在的原因。
|
||||
- **判据(三条配套)**:
|
||||
① **抢锁前先把收口步骤列出来**(落地 → 校验 → 推送/对账 → 收尾)—— 别做到一半才发现收不完;
|
||||
② **中途必须停**(等用户拍板 / 等外部窗口)⇒ **先释放锁再停**(锁是"正在动手"的凭证,不是"占位符");
|
||||
③ **结束语必须对锁状态负责**:要么写明「已释放」,要么**显式点名**「锁仍在 `<OWNER>`、未释放、原因、下一步」—— 后者**仅限"释放通道不可用"这类极端情形**;⛔ 「忘了 / 做不完就走」一律不允许。
|
||||
- 与 **U22(lane)** 互补:U22 管"**该不该动手**",本条管"**动手后必须收口**"。
|
||||
|
||||
### U26|决策中发现风险/问题 ⇒ **不许带着问题往下走**,先优化到「当前情境下的最优解」(2026-09-14/15 用户明令)
|
||||
|
||||
- **原话**:「**决策中发现方案有风险和问题,需要分析并优化到当前情况和状态下的最优解,然后进行下一步处理**,这个也要加入决策方法」
|
||||
- **为什么是硬规则**:带着已知风险进入下一步 = 把风险**转移给未来**(届时修更贵);而"最优"不是理想方案,是**当下条件(现有资源 / 时间 / 风险面 / 能否验证)下最好的那条**。
|
||||
- **判据(四步,缺一不可)**:
|
||||
① **列出来**:把发现的风险/问题**逐条写成清单**(不许只在脑子里);
|
||||
② **逐条处置**:每条给出**当前情境下可用**的处置 —— 能当场消掉的当场消(改设计/加缓解/降范围),**消不掉的写"残余风险 + 触发条件"**;
|
||||
③ **说清残余**:哪些是"已知但接受"、为什么不接受不行、什么信号出现就必须回头看;
|
||||
④ **然后**才进入下一步 —— 且在交付里把 ①②③ **一并写出来**(这就是 `dsh-feature-first §5.1` 骨架里"为什么不行 / 需要你拍板"两节的原料)。
|
||||
- **配套工具**:能不能消掉要靠 **A24**(先核账真实行为面)· **A18**(静默失败会伪造结论)· **A19**(第二环境)· **A25**(本机改完≠交付)去判;**"改小范围先落地"永远是合法候选**(§4.4 第 2/3 条)。
|
||||
- ⚠️ **反面**:把"有风险"当成"要不要问用户"(**过度上抛**)或者"先干着看"(**风险转移**)—— 两者都不对:**先自己优化到当下最优,再带着残余风险请用户拍板是否接受**。
|
||||
|
||||
### U27|要的是**解决问题**,不是**得过且过、将就妥协**(2026-09-15 用户明令)
|
||||
|
||||
- **原话**:「**项目推进要的是解决问题 不是得过且过,将就妥协**」
|
||||
- **判据** → 面对发现的风险 / 缺陷,**默认目标是"解决"**;下面三种**都不算解决**,一律不许当成交付:
|
||||
① **降级目标**(把"要做到 A"悄悄改成"做到 A′ 也行");
|
||||
② **延期**("下次顺手再说 / 等窗口再补" —— 除非**客观不可逾越**且有证据);
|
||||
③ **静默兜底**("先这样也能跑",而风险与触发条件一个字没写)。
|
||||
- **唯一允许"暂时接受"的情形 = 客观不可逾越**(技术不可行 / 上游未支持 / 需要用户侧凭据或窗口)⇒ 必须写明**三项**:
|
||||
① **卡在哪**(证据)② **当前已做到哪一步** ③ **什么条件一出现就必须回头解决**。
|
||||
- **与 A6 的边界(别读成互相矛盾)**:**A6 管"路径"**(实现取最小代价、不追求最彻底);**U27 管"目标"**(目标不许打折)⇒ 一句话:**目标不打折,路径取最小代价**。
|
||||
- **与 U26 的关系**:U26 要求「发现问题先优化到当下最优解再走下一步」;**U27 补的是"最优解"里不许包含'降低目标'这个选项**。
|
||||
|
||||
### U28|🟢 红线:只做正向迭代 —— 命中「劣化风险」立即停下复盘,无正向做法则立即停止(2026-09-15 用户明令)
|
||||
|
||||
- **原话**:「**要确保所有决策是让项目正向迭代和提升**,如果遇到**纯在项目劣化风险**(目标,方向,架构,功能,性能,安全,交互,UI,便利性,扩展性等)需要**立即停下复盘**,如确实**无正向迭代方法**立即**停止**,**禁止继续执行**」
|
||||
- **判据(每次决策前过一遍十维)**:**目标 / 方向 / 架构 / 功能 / 性能 / 安全 / 交互 / UI / 便利性 / 扩展性** —— 任一维度**净变差**即命中。
|
||||
- **命中后的三步(一步都不许跳)**:① **立即停下**(不许"做完再看")② **复盘**:写清劣化在**哪一维**、**代价量级**(数字 / 证据)③ **找正向做法**(改小范围 / 换实现 / 分阶段)—— **拿不出来 ⇒ 立即停止、只报告,禁止继续执行**。
|
||||
- ⛔ **三种伪装**:把劣化说成"必要代价"/用"后续再优化"掩盖已知劣化/把劣化项藏进交付里不写。
|
||||
- 与 **R5** 互补:R5 只管**权限**(只准收窄);**R11 管全维度净收益**。与 **U27**(不将就妥协)· **A20**(代价不对称就保留)同族。
|
||||
@@ -0,0 +1,34 @@
|
||||
# 反例库 · 被驳回 / 被纠正的决策(X1–X13)
|
||||
|
||||
> **归属**:技能 `dsh-decision-method` 的素材库(**按需读**,不是每次都要读)。
|
||||
> **主文件 / 索引 / 判定核心** = `../SKILL.md`(§4 判定核心 · §5 流程 · §7 语言表 · 附 自检)。
|
||||
> **用法**:只在「要判某条是否属于既有口径」或「要引用用户原话」时读本文件;**别整段抄进答复**。
|
||||
> **维护**:条目**只增不改**(编号进位到末尾);用户原话**逐字**引用;每条必须带「实例出处 + 判据」。
|
||||
|
||||
---
|
||||
|
||||
## 3. 反例库:被驳回 / 被纠正的决策(X1–X11)
|
||||
|
||||
> 每条**反例 = 一条避免规则**。这些是本工作区里真实发生过的失手。
|
||||
|
||||
| # | 反例 | 根因 | 转为规则 |
|
||||
|---|---|---|---|
|
||||
| **X1** | 为"让 scp 文件行尾干净",用脚本把 **147 个文件** CRLF→LF;当期只被要求改一句 UI 字符串 | 把"顺手修"当效率;**没做单点验证就全库推广**;忘了本机镜像不是沙箱 | → **R7**:只做被明确要求的事;>10 文件先出清单;先单点验证;传播前 `git status` 比对待传清单 |
|
||||
| **X2** | 档案 58/59 连续两次重启 `dshs`,**把在线用户踢下线**并引发报障 | 把"改完即验"当完整闭环,漏了"改前先知会" | → **R8**:重启/drain/铺插件/改配额 env → 先说「影响谁、断多久、为何必须现在做」 |
|
||||
| **X3** | 把 mtime 当并发冲突判据 | mtime **分不清是谁改的**;本库长期不提交 → 无冲突检测 | → 冲突判定只认两个硬信号:**别人的占用锁** + **待推送清单里的未声明文件**;mtime 只作提示 |
|
||||
| **X4** | 由"空闲回收没生效"外推出"实例不会中断"(**被用户当面纠正**) | 把"某机制失效"误推成"该类现象不存在" | → 现象归因要**枚举全部可能来源再逐一实测**(中断真凶是服务重启 + 崩溃重启,与回收无关) |
|
||||
| **X5** | 按字面执行"参考资料不需要"去删 | "看起来像资料"与"实际被引用"是两件事 | → 见 **U3**:删除前先扫引用 |
|
||||
| **X6** | 用截断到 200 字符的 `grep` 输出当 `old_string` 去 Edit 长行 → **误删对方记录行首** | 拿不完整内容当精确锚点 | → **长行 Edit 前必须先用 Read 取全文**;共享文件只用 Edit 精确替换(失败即冲突信号),禁整文件 Write |
|
||||
| **X7** | 把用户设备上的"旧会话不好用"当成感受问题,未深挖 | 没做会话级取证 | → 报障第一步**先拿真实失败请求/真实状态**(`journalctl` 精确 URL+method+status),再归因 |
|
||||
| **X8** | "只注入 env 就以为配好了"(bundled 技能层实际未挂载) | 漏了"插件在实例内 `resolve()` + 读盘"这一层 | → 通用判据:**插件在实例内读盘的东西,必须真的出现在命名空间里**;env 只决定"去哪儿找" |
|
||||
| **X9** | **把 R7 按「动作名字」套到部署上** —— v0.2.8 只换 profile 里的包、**零中断**,却停下等确认;用户回「为什么要等我确认才部署呢」 | 红线被当成**关键词匹配**(见「部署 / 上线 / 生产」就触发门禁),没按**实际影响面**判 | → **按影响面判,不按动作名字判**(U20):R8 只认「会中断在线用户」;**不中断的上线 = 执行细节,做完即上线** |
|
||||
| **X10** | **答非所问:拿「我的失误 + 探针踩坑 + 版本流水 + 下一步计划」去答「是否已实现」** | 主位错位 —— 写的是**AI 的进度**,用户问的是**功能的可用性**;收尾「要我接着做,说一声即可」= 又把已定的执行细节上抛 | → 用 **U21 结论三件套**(判定 → 为什么不行 → 要拍板什么 / 我接着做);失误只在 ①改变结论 ②用户问根因 时写(`dsh-feature-first §5.1–5.3`) |
|
||||
| **X11** | **为了让自己的流程走通,自行改了平台级路径**(建 `/var/lib/dshs` 全局符号链接,无人授权)→ 用户追问「谁让你去改这个的」 | **动机取代了边界判断** —— 「改它能让我流程跑通」被当成理由,没问「这落在谁的 lane」 | → **U22 闸 1**:不是我 lane 的(平台级 / 全局 / 别人 lane)**只报告不动手**;越方便越要先问 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
| **X12** | **把用户给的材料当权威照抄**(他们扒的是新版 `0.1.5+` 源码,我们跑的是 `0.1.2-rc.1`) | 没先确认「**这份材料描述的是哪个版本**」 | → 用户给的素材要用**我们的实际版本**核对;本次 4 处纠正:包不存在 / 扩展点不存在 / 装上也静默挂死 / 投放通道不符。⚠️ 与 **U11**(用户给的**数值**是硬约束)区分:**数值口径是约束,事实陈述要核对** |
|
||||
| **X13** | **把自己的解析失败当成"版本差异"**(报「`__DSH_BOOT__` 结构变了」,其实是我的解析正则过时) | 差异归因时**先怀疑版本、没先怀疑自己** | → 报"两版不一样"之前,**必须在两边用同一解析都跑通一次**(或做 A/B 对照);档案 90 已追加更正防误导 |
|
||||
|
||||
| **X14** | **把「一批改造」的中断动作拆成多次执行**(一天连做 5 项改造 ⇒ 铺插件 4 次 + 重启 `dshs` 3 次,每次都让已打开页面手里的 `rev` 过期) | 只有"改一处→验一处"的单点思维,**没有"批处理窗口"概念**(R8 只说"先说明/取得确认",没说"攒批") | → **同一批改动的所有中断动作攒到一个窗口执行**;**窗口内 >1 次重启 = 违规信号**,停下来问"能不能并到一次"。⚠️ 这正是「Failed to load plugins」的直接成因(档案 95) |
|
||||
Reference in new issue
Block a user