# Dsh Development Practices

> 在已有工作流里做非平凡改动时，补上 Harness 验证过的工程纪律：先搞清事实、记好长期决定、按表面拿证据、如实收尾。可叠加在任何计划/编码/审查流程上

- Skill: `czm15053/dsh-development-practices` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add czm15053/dsh-development-practices`
- Raw SKILL.md: https://api.skillmd.com/api/skills/czm15053/dsh-development-practices/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: czm15053 (https://skillmd.com/u/czm15053)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/czm15053/dsh-development-practices

---


# DSH 开发实践

> 从 DeepSeek Harness 提炼、可搬到任何仓库的做法。宿主负责拆任务、排计划、管 Todo；本 Skill 只补判断和证据。不引入第二套任务库或会话状态。

## 定位

这不是"从零搭项目"的工作流，也不是要替代已有的计划/编码/审查流程。它的定位是**叠加层**：当改的是行为、架构、契约、流程或落盘格式这类以后会有人回头审视的决定时，帮你把 Harness 用血换来的四件事补上——事实有没有摸清、长期决定有没有留痕、证据有没有按表面拿全、收尾有没有如实说清。

只改格式/无歧义命名/错别字标 `not applicable`，走宿主常规检查。不确定就按非平凡处理。

## 0. 先探测，再落地

别一上来就建一套目录。先看宿主有什么就用什么：

1. 有 `AGENTS.md`/`CLAUDE.md`/贡献指南就读它，没有也不为此新建一套规范。
2. 有 `docs/adr/`、`docs/decisions/`、Issue 模板等决策记录就沿用，把语义映射到本 Skill 的 lifecycle/class 即可。
3. 没有决策记录再建最小 Note 树：**轻量项目只建 `.agents/notes/implemented/<class>/`**，用到 `proposed`/`rejected`/`archived` 再建；已有空目录可直接删掉。团队长期仓库再建全套。

## 1. 动手前先把事实搞清

不为此新建状态文件，记在宿主当前上下文里：

1. 找到项目根，把根和受影响目录的规则读一遍。
2. 看一眼工作区，把无关改动标出来——不覆盖、不重置、不算到这次任务里。
3. 找到真正会用到这次改动的地方：源码/构建/测试/生成物/线上入口，只看声明不够要找到消费方。
4. 翻已有长期决定（ADR/Note/Issue），先看在用的再看归档。
5. 列出会影响哪些可观察表面（见 §5），每个表面怎么验。

记下：已确认的事实、还没验证的假设、会动到哪些文件和表面、无关改动、需要人来拍板的问题。

> 需求有分歧或多个合理方案时，先把每个分支问清楚再写代码。追问本身不产代码——有追问/访谈类 Skill 就调它，没有就用同样提问把分支覆盖到再进 §2。

## 2. 先分类，再定边界

**分类**（只决定要留什么证据，不额外加阶段）：局部/机械 · 行为变更 · 跨表面变更 · 高风险（安全/丢数据/兼容/并发/不可逆）。

**定边界**——优先复用已有扩展点和靠谱依赖，别为了"像个架构"硬抽象：

- 默认值放在显式的解析/归一化那一步，别藏在执行函数里的 `?? default`。
- 会随环境变的东西做成可校验的配置项，别写死成常量或散落在多处。
- 能独立判断的非法配置在加载时就报错，其他错误在最早能定位的地方报，别静默跳过或吞掉未知的分支（封闭联合用 `assertNever`，开放联合走有文档的默认分支）。
- 在解析、文件、持久化、外部 JSON、进程/Worker、网络这些边界上校验不可信数据；同进程内已定类型的数据不用重复设防。
- 管好所有权和生命周期：注册/释放、取消、清理、错误传播要成对；别引入两套事实源或宽泛兼容层却证明不了现有边界兜不住。
- 别把某一个实现的枚举升为全局标准——能力由提供方声明，核心只透传；协议归提供方管、由提供方自愈，消费方别去硬改提示符或协议细节。
- 评估依赖时看净删除、健康度、边界贴合度：能真删掉实现+测试+文档才值得引入，手写协议/解析/重试之类优先看现成包。

> 做并发/清理/子进程改动时，必读 `references/defensive-checklist.md` 的完整清单。

## 3. 长期决定怎么记

这是最值得搬走的部分。每个非平凡改动在同一 PR 里新增或更新至少一条 Note，纯机械可不写；已有覆盖就更新，别重复新建；不要把一条 Note 改写成另一个决定。

- **放哪**：`{lifecycle}/{class}/yyyy-mm-dd-topic.md`，有既定目录就映射语义。lifecycle `proposed(可选)→implemented→rejected(能防重犯才留)→archived(冻结)`；class `feature/bug-fix/simplification/architecture/process/testing`（封闭集，新增需改门禁）。
- **写成什么样**：`# Agent Note: <标题>` + `Status: <状态 — 一句话>` + `Problem` + `Proposal|Decision` + 按需的 bespoke 技术节 + 必写的 `Alternatives considered`（每个真考虑过的备选及为什么没选，不写就重审）+ `Acceptance criteria|Consequences|Risks`。`implemented` 用现在时，归档加 `Archived: YYYY-MM-DD` 后冻结。
- **新建/更新/归档**：先搜现有归属；决定没变只事实/验证变了就更新；只有新增长期决定/防重犯否决/可复用复盘才新建；完全取代才归档，部分取代两份都留并互链。

小项目允许"一话题一份 `implemented`"，提案讨论写在 PR 描述或 `Alternatives considered` 里。

## 4. 带着证据做

做最小自洽改动，在行为真正被消费的地方测。测试写外部可观察行为和边界，别复述实现。

- 异步不是同步：别把 `running`/`idle` 当单条消息的结果；清理要等到静止（先关监听再杀进程、等子进程退出）；回调异常由调度器兜住；正交结果（超时/退出码/信号）分开报。
- 涉及部分视图编辑（如配置页只拿到脱敏快照）走"算 diff 发 ops + 带版本号防覆盖"，别用全量 `replace` 把看不见的字段洗掉。
- 公开或模型可见行为变了，同步更新契约、快照或 SDK 投影；持久化格式变了要处理旧数据的降级而非硬报错。
- 别用 normalizer 盖失败、别放宽校验、别用 mock 代替真实集成；在消费方的真实入口上验（走发布形态的 Loader/bin/worker，而非手搭的 `ctx.plugin(...)`）。
- 同一子任务内别反复刷同一句进度，阶段变了或有新证据再更新。

> 完整实现自检见 `references/defensive-checklist.md`。

## 5. 按表面拿证据

**源码和产物分开验**——源码过了不代表产物过了，一个投影过了不代表兄弟也过了。只挑相关表面做最小够用集：

| 表面 | 怎么验 |
| --- | --- |
| 纯规则/转换 | 聚焦单测，含非法与边界 |
| 包/API 行为 | 包测试 + 真实消费方或组合入口 |
| CLI/配置 | 源码/配置启动与失败路径 |
| 浏览器/UI | 把应用跑起来，走一遍代表性交互，看桌面/移动布局 |
| 生成输出 | 从权威来源重生成并 diff |
| 快照/转录/模型可见输出 | 无密钥回放或项目认可的快照（**拍模型实际看到的**，不是日志本身） |
| 构建/发布产物 | 干净构建 + 用真实产物起一次/冒烟 |
| 持久化/协议/线数据 | 往返、迁移/版本、非法数据拒绝 |
| 安全/并发/清理 | 明确的拒绝、取消、释放与失败路径 |

再补两条 Harness 最近用血换来的：

- **数据和元数据一起裁**：截断丢掉工具调用时，其对应的签名/回放元数据也要一起丢，否则持久化后下一轮直接卡死；读到旧脏数据要降级而非硬报错。
- **一条证据链**：浏览器/UI 证据要来自同一次真实运行的同一服务和同一会话，别把多轮截图拼成一张图；录屏/GIF 要可追溯到同一 commit。

本地只跑相关表面，覆盖率/快照/构建等门禁和 CI 各管各的，报清楚实际跑了哪些命令及结果就行，不用每次全量。详表与坑位见 `references/evidence-by-surface.md`。

## 6. 审查与收尾

**收尾前自问**：

- 和需求/非目标对得上？每处改动都有验收或写清为何没法测？
- 契约/文档/生成物/快照/兄弟消费方同步了？有无重复/第二事实源/隐藏默认值/陈旧兼容/说不清的不对称？
- 错误会响亮失败、清理成对？注释直接完整无过程泄露？
- 要删东西先证明有消费方、行为等价、净删除量；没明确理由别在功能改动里顺手重构无关代码。

自检不过再按需读 `references/review-checklist.md` 的必拦项与人工必查。

**文档与注释**：说人话、点名谁做了什么、在什么条件下会怎样；别把推理过程泄露进注释。一个事实只在一处讲透，其他地方链过去。自检见 `references/prose-checklist.md`。

**简化机会**：收尾或重构时扫一遍重复/过度设计/可删的兼容层，见 `references/simplification-checklist.md`。

**如实收尾**：同步文档/契约/生成物/Note，跑宿主最终机械检查。报告分开写：实际跑了什么及结果 / 刻意没跑什么及原因 / 已验证行为 / 已知限制与剩余风险 / 有意没动的文件。没证据别声称验过浏览器/集成/覆盖率/发布。

## 停止条件

需求或验收实质冲突、长期决定归属不清、涉数据/安全/协议/兼容/不可逆但无策略、找不到入口或证据、无关改动无法安全归属、方案要并行事实源或宽泛兼容却无证据、测试与实现打架且推不出预期——先停下找人确认，别编计划或谎报成功。

## 集成约定

可叠加在任何流程上，和宿主显式规则冲突时听宿主的。必须保住四条：动手前摸清事实与现行决定；实现是最小且有依据的长期正确改动；证据盖住每个受影响表面且源码/产物分开；最终报告分清事实/未做/风险且 Note 与文档已同步。

## References

按需加载，不必每次全读：

- `references/defensive-checklist.md` — 定边界与实现时的防御自检（展开版）
- `references/evidence-by-surface.md` — 表面对照表与两条易踩坑（展开版）
- `references/review-checklist.md` — 审查必拦项与人工必查（展开版）
- `references/prose-checklist.md` — 文档与注释自检（展开版）
- `references/simplification-checklist.md` — 简化机会自检（展开版）

