前置:全部前序课程(尤其第 09、11 课) | 预计时长:60 分钟 | 动手环节:必须完成
你将学会
- 贯穿全仓库的设计哲学,以及每条哲学对应的「代码形态 + 门禁证据」;
- verify- 脚本、每文件 100% 覆盖率、六道测试矩阵如何构成质量体系;
- Agent Notes 制度:为什么「理由」需要自己的家;
- 用维护者的视角收束全部课程。
问题引入
前十二课讲「系统如何工作」,最后一课讲「系统如何保持正确」。dsh 跟别的项目最不一样的地方:架构规则大多不靠评审自觉,直接接进了可执行的顶层门禁。读懂这套,你才能跟别人讲清「这些设计凭什么能维持」。
正文
13.1 设计哲学十条:每条都有代码与门禁背书
(完整版见维基 《design-philosophy》,这里把课程里见过的证据串起来)
| # | 哲学 | 你在哪课见过它的代码 | 门禁/机制证据 |
|---|---|---|---|
| 1 | 无特权核心:一切皆插件 | 02(Context 五内建服务也是服务) | 每包必须拥有 ./invariant 运行时契约(verify-package-invariants) |
| 2 | 模型可见 ⟺ 已记录 | 04/05(三层强制) | 运行时逐字节比对 + session 结构不变量 |
| 3 | Capability Seam 三角色 | 08(fs / llm) | docs/capability-seams.md 生成服务图 |
| 4 | 显式 > 隐式 | 08(shell 的 request/spec 拆分) | 评审约定 + 包 README 的 Model Experience 段 |
| 5 | 配置错误大声失败 | 07(坏补丁抛、结算审计) | fail-loud 启动路径 + verify-cordis-config |
| 6 | Fail-closed 安全姿态 | 09(landlock、审批、沙箱) | 无回退构建、确定性拒绝路径 |
| 7 | 类型安全的具体形态 | 全程(strict + branded id + assertNever) | verify-node-next-types、verify-type-equiv |
| 8 | 源码平面 / 产物平面分离 | 07(双编译面) | tsconfig paths 解析到 src 的静态门禁 |
| 9 | 确定性与可回放 | 05/06(重放即真相) | 无 key 快照回放 DSH_SNAPSHOT=replay |
| 10 | 预发布姿态:基础正确性 > 兼容面 | 06(SESSION_FORMAT_VERSION=0 无迁移承诺) | 后端方向感知拒绝旧格式 |
13.2 门禁体系:44 个 verify- 脚本
package.json:72-139 定义 44 个 verify-* 脚本,由 scripts/run-gates.ts 编排进聚合(顶层 check-all 共 55 个 gate)。分类速览:
| 类别 | 数量 | 代表 | 校验什么 |
|---|---|---|---|
| 文档/目录 | 23 | verify-md-wrap、verify-md-links、verify-doc-budgets、verify-export-jsdoc、verify-cordis-config | md 换行/死链、字数上限、JSDoc 完备、cordis.yml 裸插件必须在依赖清单 |
| Agent Note | 3 | verify-agent-note-format 等 | 决策记录格式/分类/归档冻结 |
| 包结构/发布 | 7 | verify-package-invariants | 每包 ./invariant 运行时契约、README 约定 |
| 依赖/编译面 | 6 | verify-runtime-closure、verify-client-domain-graph | 运行时闭包、客户端域依赖图 |
| 应用/客户端 | 4 | verify-application-entrypoints、verify-client-ui-i18n | 应用入口、客户端文案走本地化字典 |
覆盖率门禁是每文件 100%(vitest.config.ts:344-356):thresholds: { perFile: true, statements/branches/functions/lines: 100 },注释「100% or it doesn’t merge」。真不可达的防御分支要写 /* v8 ignore -- <原因> */,不许裸 ignore。注意 test:coverage 才是 CI 门禁,test 不是。
测试六道:unit / e2e(真实 API,无 key 自跳过)/ snapshot(无 key 录制回放,默认道)/ expected / web-perf / web-stress。
门禁哲学一句话(根 AGENTS.md):「Wire mechanically checkable invariants into an executed top-level gate and prove each changed acceptance path rejects an invalid case.」——能脚本化的不变量就接进门禁,且要证明它能拒绝非法输入。
13.3 Agent Notes:理由的家
(制度细节见维基 《agent-notes-system》;第 10 课你已经写过一条)
- 强制触发:每个非平凡变更必须在同一 PR 里附带或更新至少一条 Agent Note;机械/局部编辑豁免。
- 路径编码两个轴:
{proposed|implemented|rejected}/{feature|bug-fix|simplification|architecture|process|testing}/yyyy-mm-dd-topic.md。 implemented/用现在时描述已落地的现实;Alternatives considered必填——「放弃了什么」与「为什么这么做」同等重要。- 取代检查:新笔记要搜索活跃树里覆盖同一决策的旧笔记,完全取代则归档,部分取代则交叉链接;归档即冻结,绝不编辑。
- 在文档分层中的位置:类型定义 →
subsystems/;包契约 → 包 README;步骤 how-to →cookbook/;事故故事 →postmortem/;为什么与放弃什么 → Agent Notes。
13.4 收束:三条主线
把十三课收束成三条主线,向别人讲述时用它们开头:
- 一个运行时公理:模型可见 ⟺ 已记录。日志不是副产品,是系统的第一公民(第 04–06 课)。
- 两个扩展机制:Cordis 事件/服务骨架(怎么挂)与 Capability Seam 三角色(挂什么),组合靠 Profile/Bundle 补丁层(第 02–03、07–08 课)。
- 一条质量路线:fail-loud + fail-closed + 机器可执行门禁 + 决策记录——正确性不是评审出来的,是构造出来的(第 09、11、13 课)。
动手环节
- 跑一个门禁:
pnpm run verify-agent-note-format(对你第 10 课的草稿)与pnpm run verify-md-links,观察门禁的报错形态——它们不是警告,是拒绝。 - 找不变量:任选一个包,读它的
./invariant入口,回答:它断言了什么「被拥有的关系」?(提示:根AGENTS.md——检查权威事件流或可变数据,而不是服务存在性。) - 写收束笔记:为整个毕业项目(第 10 课插件 + 本课学习)补一条
Status: implemented的 Agent Note,Consequences里写清你验证过什么。这就是你从「读者」变「贡献者」的第一个交付物。
自检清单
- 十条哲学里,挑三条说出对应的「代码形态 + 门禁证据」(不许只背名词)。
- 为什么
test:coverage是门禁而test不是?每文件 100% 与全局 100% 的区别是什么? - Agent Note 的哪一段是必填的?归档的笔记为什么不可编辑?
- 「门禁要证明能拒绝非法输入」——用 postmortem 0002 催生的
verify-cordis-config举例说明。
结业
完成本课后,你应该能:给同事做一次 45 分钟的 dsh 架构导览(用第 13.4 的三条主线);独立写出一个装进 profile 的插件(第 10 课);读懂 docs/architecture.md 与维基的全部页面并知道每页在讲哪段代码。下一步建议:挑一个真实需求(新工具、新 LLM 适配器、新 skill provider),从 docs/cookbook/ 对应篇目开始,把本课程的方法循环跑一遍。
延伸阅读
- 维基:《design-philosophy》、《agent-notes-system》、《engineering-gates》
- 仓库:根
AGENTS.md(约定全集)、docs/testing.md、docs/development.md、CONTRIBUTING.md - 返回:课程总览