Back to skills
SKILL.md
Omd Contract
ASecurity把审议结论结晶成正式契约文档落盘 docs/plan/,当 /omd-execute 的执行契约。承接 /omd-grill 的决策记录表,写给没有对话上下文的执行器看。含 crystallize/crystals 职能。Trigger:/omd-contract、定契约、写成执行契约、写成 SDD、SDD、结晶、方案定了记下来、列结晶。
- 40 stars
- 0 votes
- 0 copies
- 6 views
- Added September 3, 2026
Security analysis
100/100npx -y skills add AbyssCN/oh-my-dag --skill omd-contract --agent claude-codeAre you the author of Omd Contract?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/abysscn-omd-contract)---
name: omd-contract
description: 把审议结论结晶成正式契约文档落盘 docs/plan/,当 /omd-execute 的执行契约。承接 /omd-grill 的决策记录表,写给没有对话上下文的执行器看。含 crystallize/crystals 职能。Trigger:/omd-contract、定契约、写成执行契约、写成 SDD、SDD、结晶、方案定了记下来、列结晶。
---
# /omd-contract — 审议结晶成执行契约
审议(`/omd-grill`、pathfinder 裁决)收敛后,把结论写成结构化 SDD 落盘——它是 `/omd-execute` 的执行契约,写给**没有对话上下文的执行器**,不是给人读的散文。
## 承接 /omd-grill 的决策记录表
| # | 决策 | 定论 | 落点(/omd-note · pathfinder 票 · SDD 章节) | 证据 |
|---|------|------|--------------------------------------------|------|
落点标「SDD 章节」的行 → 进「决策」与「契约」段;标 `/omd-note` 的留台账;标 pathfinder 票的附票 id 进「未决」段。「待 owner / 待实测」项原样进「未决」,不写成结论。
## 落盘
路径:`docs/plan/YYYY-MM-DD-<slug>.md`。每段可被无上下文执行器独立消费:
```markdown
# <标题>
## 目标 (Destination) 一句话讲清做成什么样
## 决策 (Decisions) D-1..D-N:每条已定型裁决 + 一句为什么 + 证据
## 契约 (Contracts) 不变量 + GWT 验收点——/omd-execute 逐条判 pass/fail 的依据
## 分解 (Breakdown) 依赖图 + 并行波形(写法见下)
## 非目标 (Non-goals) 明确不做什么
## 未决 (Open) 未裁的问题;附 pathfinder 票 id;待实测的标「待实测」
```
GWT 验收点越可证伪,验收越不含糊;一个模糊验收点 = 执行器和你各自解读的裂缝。
## 分解段 —— 默认并行,串行必须给理由
- 只写**真实依赖边**,每条带理由:「B 依赖 A 因 <B 消费 A 的产物 X>」——且 **X 必须出现在 A 的写集清单里**(机器可锚)。写不出被消费产物的边,删——那是顺序偏好,不是依赖。
- **接口依赖就地消解**:B 只需要 A 的类型/签名/schema 而非实装 → 把该接口**冻进本 SDD**(契约段),边删掉,两片并行。接口从此是契约的一部分:A 的实装必须符合它,偏离 = 回流改契约,不是恢复边。(实例:内环 v2 切片 2 只消费切片 1 的 `SddSlice` 结构——冻进 SDD 即可并行,当时没冻,白等一层。)
- **定稿前过一遍并行性审问**:串行率(关键路径长 ÷ 切片数,编译器 `parallelismReadout` 同口径)= 1 的链,逐边重跑上面两问再定稿;审完仍是真串行就如实保留——读数只点名,不否决诚实的线性分解。
- 切片表:| 切片 | 写集 | 依赖(带理由) | verify |。写集两两不相交 = 可并行的机器判据。
- **verify 列必须是可跑命令串**(如 `bun test src/x.test.ts`),不是验收点引用——G 点引用的家在契约段。编译器(sdd-compile)按首词白名单拒不可跑的 verify;写引用 = 这份 SDD 吃不到直通 v2,回落 conductor 铺图税(owner 2026-08-11 裁:直通就是为了消铺图税与墙钟)。全量回归命令不进 verify 列(它只属终局 accept,D-4)。
- 收尾写并行波形一行,conductor 照铺:`并行波形:{1,3,5} → {2} → {4}`。全串行波形须给整体理由,默认视为写错。
- 优先序(哪片价值高)写波形注释或 Open 段,不进依赖边。
### ⚠ 分解表的四条机器硬要求(写错 = 点火当场拒 / 静默回落,而它只在点火那一刻才响)
真源 `src/harness/goal/sdd-direct.ts` + `sdd-compile.ts`。2026-08-18 量过全量语料:
**149 份 plan 文档、52 份有分解段,只有 14 份吃得下 `sddPath` 直通** —— 而直通是夜批的默认路径。
73% 的失败**全部**来自下面四条,一条都没写进过本模板:
1. **切片列必须裸数字开头** —— `| 1 span 计算 …`。写 `S1` / `**S1 …**` / `Phase` 一律拒
(`sdd-direct.ts` 的 `/^(\d+)/`;编号是波形/依赖引用它的唯一方式)。
2. **波形行独占一行** —— `WAVE_LINE` 锚行首。写成「写集两两不相交 ✓。并行波形:…」会被
**静默忽略**(不报错,图退回按依赖边排;2026-08-18 实测)。
3. **写集只收相对路径,且不许留空** —— 写「无」/「dispatch」这类词会被拒;空写集直接拒
(写集是并行安全的机器判据)。
4. **verify 列要过 #251 判据自证的三条 lint** —— 真源
`src/harness/goal/ignition-criteria-check.ts`,点火期接线在 `goal.ts:1153`。
**这是六道点火闸里唯一没有 `force` 出口的一道**:给了出口就等于放虚判据进图,
而虚判据让整跑判不出真假(实账 run `85a18995` 零改动 4 分钟假 done;
`bca0a0c7` 的 `bun test` 多 filter 静默忽略缺失,二次假 done)。三条逐条写:
| lint | 判据 | 怎么写才过 |
|---|---|---|
| `missing-path` | verify 里「含 `/` 且以 `.ts/.tsx/.js/.json/.md` 结尾」的 token,盘上不在、也不在本片写集 | 引用的路径**要么盘上真有,要么写进本片写集**。绝对路径(`/` 开头)不收,那是机内路径 |
| `mixed-first-segment` | 本片写集含**新建文件**时,verify 的**首段**(第一个 `&&` 之前)引用了本片写集之外的 token | 首段只许引用本片写集内的东西 —— 否则首段能在**不动本片文件**的情况下退 0,这片是空的 |
| `pre-green` | 本片写集含新建文件 ∧ verify 在实装前就退 0 | 换一条实装前**必然红**的命令。本片没有新建文件时这条不查(改既有文件,改前改后都可能绿) |
⚠ `pre-green` 那条还有第二重代价:**读到绿 = RED 前提不成立 → 整图回落 v1 conductor 铺图**,
而点火回执那句「SDD 直通」只讲契约段、**不报执行段已回落** —— 唯一线索是节点名从
`s1-red/s1/s1-green` 变成 `execute::<hash>`。既有测试要跟着改,写进**写集**,别写进 verify。
⚠ **两句听起来矛盾的话,分清楚**(2026-08-23 我把它们混了,代价见下):
- 「**不要求实装前天然红**」管的是**契约措辞** —— 别写条款逼执行体去**制造** RED
(`159ea49` 删掉 RED 节点之后);
- 而**引擎的 O-6 探针照样要求 verify 命令在实装前是红的**,平铺图才编得出来。
**前者不豁免后者。**
⚠ **本片是「修改一个既有绿测试」时怎么写 verify**:它实装前当然是绿的 ⇒ 必然回落。
换一条**实装前必然红**的命令,例如
`ugrep -q '<实装后才会出现的串>' <目标文件>`(改前 0 命中 ⇒ 非零退出)。
⚠ **回落的代价读得出来**:2026-08-23 实测,同一片活
回落成 14 节点 conductor 图跑了 **44m37s**,而当晚同规模平铺图是 **11–28 分钟**
—— **约一倍墙钟**。回执不报回落,`dag_status` 的节点名才报。
## 结晶后立刻验证 —— 不验不算结晶
写完**当场**跑一次,编译不过就地重写。**别等点火才发现**(2026-08-23 一晚 15 片实测:
所有「契约编译通过、跑起来必挂」的错法,都是在这一步能机械判死的)。
```bash
bun -e '
const { parseBreakdown, loadSddContract } = await import("./src/harness/goal/sdd-direct.ts");
const { compileBreakdown } = await import("./src/harness/goal/sdd-compile.ts");
const p = "docs/plan/<刚写的>.md";
loadSddContract(p); // 契约段 + 分解段齐不齐
const b = parseBreakdown(await Bun.file(p).text());
console.log("writeSet:", JSON.stringify(b.slices.map((s) => s.writeSet)));
console.log("falsify:", JSON.stringify(b.falsify)); // ← 逐条核对是不是你写的那一行
console.log("nodes:", Object.keys(compileBreakdown(b, { acceptCommand: "bun test" }).nodes).join(" "));
'
```
**逐条核对(每条都花过一整轮)**:
| 看什么 | 判据 |
|---|---|
| `falsify` 解出来的 `oldText` | 与你写的**逐字相同**。含 `\|`(TS 的 `\|\|`)会被 markdown 切列 ⇒ 截成半句 ⇒ 跑起来 `matches=0` |
| 写集碰 `src/` 任何文件 | **多半要把 `docs/architecture/seams.md` 也放进写集**,见下面那条 ⚠ |
| 命令首词 | **不许 `npx`** —— 执行体沙箱里退出 **127**;用 `./node_modules/.bin/<bin>` |
| `nodes` 清单 | 与你预期的节点数一致;`sN-falsify-*` 该在的在、不该在的没有 |
⚠ 上面前三条今天已由编译器**硬拒**(`sdd-direct` / `sdd-compile`),
所以这一步跑不过 = 契约真有问题,**不是工具挑剔**。
### ⚠ seam 漂移闸的规则比「改了 types.ts 才要重跑」宽得多
`docs/architecture/seams.md` 记的**不只是字段**,还有**每个字段的「提及文件清单与计数」**
(`| \`verifier\` | … | \`src/harness/verifier.ts\`<br>… (61 文件) |`)。
⇒ **任何 `src/` 改动只要改变了某个 seam 字段的提及文件数,`seams.md` 就过期,漂移闸就红** ——
**包括只在一句注释里写下那个字段名。**
2026-08-23 现场:一片完全不碰 `dag/types.ts` 的改动,因为执行体在两个源文件的注释里
写了 `verifier` 这个词,计数 61→63,整跑判 `failed`。而我在契约里明写过
「已查证:不碰 seam 漂移闸,不用跑 `gen-seam-catalog.ts`」——
**我验的是「`ShellRun` 在不在目录里」,断言的却是「不碰漂移闸」。验了一条,断言了一片。**
**⇒ 两条照做**:
① 只要写集里有 `src/**`,就把 `docs/architecture/seams.md` **一并放进写集**,
并在契约里写「实装完跑一次 `bun run scripts/gen-seam-catalog.ts`」;
② 真要断言「本片不碰漂移闸」,**唯一算数的证据是跑一遍生成器看 diff 是不是空**,
不是 grep 一个类型名。
### 还有一条,抓的是**另一半**
```bash
bun run plan-doc-check --ignite <文档> # 文档形态闸 + 点火预演 (2026-09-04 起)
```
它查两批错:
**① 文档形态**(不带开关也跑):切片列编号是不是裸数字、波形行有没有独占一行、
有没有未决段,以及**不变量与 GWT 配没配上**。
**② 点火预演**(`--ignite` 才跑):把 `solve --sddPath` 点火期那几道闸**提前搬到结晶期**,
判定复用点火期的同一份实现(抄一份必漂,而漂的后果正是「结晶期说过了、点火期照样拒」):
| 预演段 | 对应点火闸 | 抓什么 |
|---|---|---|
| D3 干跑 | `dryRunSddIgnition` | 平铺图编译得出来吗(表坏 / verify 列全空 / 写集相交 / 依赖悬空) |
| 坐标校验 | `checkCoords`(#241) | 反引号里编造的路径、行号、符号 |
| 判据自证 | `checkIgnitionCriteria`(#251) | 上面第 4 条那三条 lint —— **逐片实跑 verify**,所以这段最慢 |
⚠ **`--ignite` 默认关,别去掉这个开关。** 实测:仓里 293 份计划文档、149 份有分解段,
打开后 **116/149 判红** —— 那些绝大多数是历史文档,活早干完了、永远不会再点火。
默认开会把这条本来干净的闸变成噪声,而假 blocker 的代价是有人把整条闸关掉。
**该带开关的场合只有一个:刚结晶完、马上要点火的那份。**
**这一条与上面那条 `bun -e` 抓的不是同一批错,都要跑。**
`bun -e` 让你**逐条看**解出来的 falsify 与节点清单(眼睛核对);
`--ignite` 让机器**替你判死**。不验的代价是一次夜批空跑。
⚠ **两次实测都靠它拦下**:第一次是 `S1` 切片列(点火当场拒),第二次是波形行被静默丢掉。
### ⚠ INV / GWT 必须写成它读得懂的形状,否则它数出 0 条(而它是对的)
真源 `src/harness/plan/plan-doc-score.ts:242-245`:
| 它认什么 | 正则要求 | 写成这样才算数 |
|---|---|---|
| 不变量 | `INV_RE` —— 列表项 + **粗体** + `INV-` | `- **INV-1 短输出零回归**:…` |
| GWT | `GIVEN_RE` —— 字面 `Given`(可带 `*`)+ 同项里有 `Then` | `- **GWT-1** *Given* … *When* … *Then* …` |
| 配对 | GWT 嵌在 INV 下当子项,**或**正文里点名 `(INV-1)` | 两种都行,挑一种 |
⚠ **别写 `- INV-1 …`(不加粗)或 `**G** … **W** … **T**` 简写** ——
2026-08-23 实测:本仓多份既有契约用的正是这两种,于是 `plan-doc-check` 判
「契约段在,但一条不变量、一条 GWT 都没有」**blocker**。
那不是误报,是**它看不见**。同一份内容换成上表的形状后立刻
「不变量配 GWT 率 7/7 · GWT 可判定率 7/7 · PASS」。
**Then 里写机器判得了的东西**(`.includes('…')` / 具体数字 / 文件路径),
写「合理」「符合预期」会被单独点名。
⚠ **有一条 `major` 躲不掉**:新建文件必然被 `breakdown-path-missing` 点名
(`plan-doc-gaps.ts:207`,纯按 `!fileExists` 报;它的修法文案让你写「新建」,
但**检测器里没有一处读这两个字**)。`major` 不拦人(要 `--strict` 才拦),照点火。
### ⚠ 登记面与坐标:两件写契约时要先想到的事
⚠ **2026-09-04 起,这两件都能离线跑到了** —— `plan-doc-check --ignite` 的点火预演覆盖坐标闸,
登记面则由**拒改扩**(见下),不再需要你手工补。本节留的是**为什么**,不是操作步骤。
#### 闸 A —— 登记面:写集碰了 trigger,伴生件自动进写集(不再需要你手补)
真源 `src/harness/goal/sdd-compile.ts` 的 `REGISTRATION_FACES` + `expandRegistrationFaces`
(#243 / #254)。下表是**全集**,盘上恰 5 条 trigger。
⚠ **2026-09-04 由拒改扩:缺伴生件不再拒点火,编译器自动把它们扩进那一片的写集 + 记账。**
改的理由:这张表是硬编码的,**表永远落后于仓** —— 表外长出新绊线时,闸只会误缩边界
(实账 #254:B1 run `8888b93b` 的新闸 `[fuse-paralysis]` 因表外无权改 `gate-registry`
而 accept 判红,owner 手补表 13→14 行才过)。一道只会误缩边界的闸不该 fail-closed。
⇒ **你仍然该在契约里主动写上伴生件**:自动扩容会在派工文本里标成「已授权你改,但**不要求**改」,
而**该不该改是语义判断,编译器判不了**(见本节末尾那两种情形)。写上去,执行体才知道你的意思。
| 写集里出现 | 并集必须也有 |
|---|---|
| `src/harness/dag/types.ts` | `docs/architecture/seams.md` · `src/harness/dag/seam-catalog.test.ts` |
| `src/harness/conductor-plan.ts` | `src/harness/schema-field-registry.ts` · `src/harness/schema-field-registry.test.ts` · `docs/plan/2026-07-30-schema-field-registry.md` |
| `src/harness/schema-field-registry.ts` | 上面那份人读表 · 它自己的 test |
| `src/harness/dag/engine.ts` | `src/harness/gates/gate-registry.ts` · `src/harness/gates/gate-registry.test.ts` |
| `src/harness/goal/run-goal.ts` | 同上两件 |
**语义是「有权改」,不是「必须改」** —— 治的是修复轮想动绊线却被写集闸判无权
(S1 run `e63f47ea`;#254 的 B1 run `8888b93b` 因无权改 `gate-registry` 而 accept 红)。
所以伴生件放进写集之后**允许一个字都不动**。
⇒ **两种情形要在契约里分开写明**,否则执行体判不了该不该动它们:
① 必改(例:往 `dag/types.ts` 的 kind 词表加一格 ⇒ 接缝对账必红);
② 预期零改动(例:只改 `conductor-plan.ts` 里的 prompt 教法、不动 zod 值域)——
这时要补一句「真要改它们说明越界动了 schema 字段,停手报 finding 升 owner」。
上面「seam 漂移闸」那一节讲的是同一件事的 `types.ts` 那一行,但它只覆盖一个 trigger;
本表是全集,以本表为准。
#### 闸 B —— 坐标机械校验(#241):反引号里的路径与符号会被逐个去盘上核
真源 `src/harness/goal/coord-check.ts`。病根是实账 run `0f67293b`:派工文本写了一个
编造的符号名,执行体照抄进 `rg -e ...`,无匹配退 1,`&&` 链首败,下游 7 节点全 skipped,一整跑白烧。
**它只验三种形状(白名单制),其余反引号内容一律不验:**
| 形状 | 判据 | 写法 |
|---|---|---|
| `` `path:line` `` | 文件存在且行号 ≤ 总行数 | 同句写「新建」可豁免 |
| 裸路径(含 `/` + `ts/tsx/js/json/md`) | 文件存在 | 同句写「新建」可豁免 |
| **同句共现**的「反引号标识符 + 反引号路径」 | 标识符在该文件 `grep -F` 必须命中 | 见下 |
第三条是最容易误伤自己的一条,**它管的是「同一句里」**:
- 契约本身要论证「`budgetBasis` 在 `src/harness/plan-critic.ts` 里一次都不出现」——
这句话写在同一句里就会被判成编造坐标。**把结论与坐标拆到两句**。
- commit sha 别与文件路径同句(`fe7a5c7f` 被当成标识符去文件里找)。
- 标识符规则是 `^[A-Za-z_$][A-Za-z0-9_$]{2,}$`,所以中文、标点、单字符、数字开头的都不命中,
不用为它们担心。
- 命中行号偏差**不管** —— 它治的是「编造」,不是「过时」。
⇒ **写完自查一遍**(或者直接 `plan-doc-check --ignite` 让机器查):每个反引号里的路径,盘上有吗?没有的话同句写了「新建」吗?
每一处「符号 + 路径」同句,那个符号真在那个文件里吗?
### falsify 表的锚点两条硬规矩(拿不准就别写表)
① 锚点必须是「**实装写完之后一定长这样**」的一行 ——
拿不准(数组还是 Set、一行还是多行、字段顺序)⇒ **别写进表**;
② 锚点必须**改了真会变行为** —— 改完测试照样绿的锚点是**哑弹**,
那种 falsify 节点**必然判失败**,白挂一个节点。
两条有一条不满足,就把判别力交给**手做**那一跳(验收里写清「改什么 → 哪条必红 → 还原复绿」)。
## 纪律
- 只写已定型的决策;未决进 Open 段(或 `map_add` 开票)。
- **验收分两栏**:判据(必须能区分做完/没做)与护栏(防回归、本来就该绿)。
把护栏当判据写会被判据自证闸判 `[vacuous]` —— 它在活还没干之前就已经满足。
- **⚠ 钉性质,别钉行号。** 写「只改被本片必然打断的整串字面量,别的断言不动」,
**不要**写「只能改第 58 行」。
2026-08-23 实测:我写了「只能更新第 58 行 `VERDICT_MSG`,其余断言一个字不动」,
而那个文件里有**两处**带前缀的整串字面量(`:58` 与 `:185`),两处都被本片必然打断。
执行体改的正是这两行 —— **最小正确改动,而我的条款禁止了它**,verifier 两轮都判未过。
⇒ **点名行号 = 我在替实装做一个我没查全的假设。**
(同族:「一行的改动要有一行的爆炸半径」—— 爆炸半径该约束**碰哪些代码路径**,不是行数。)
- **⚠ 写每一条护栏之前问一遍:本片的改动会不会让这条断言改变?**
会 → **它不是护栏,是写集的一部分**,连同「断言该改成什么」一起写进契约。
(2026-08-23 实测:片 3k 把「正文改成头+尾」列为判据,又把一条拿
「有 100 个连续字符」当「预算仍生效」代理的既有断言列为护栏 ——
那个代理只在头截断时代成立,新判据**必然**让它红。写集还钉死两个文件
⇒ **执行体两边都满足不了,没有合法解**,整跑判 failed 而实装是对的。)
⇒ **代理断言是重灾区**:一条测试断言的**字面**常常不是它想量的那件事。
本片会改掉那个「字面」时,它就得跟着改。
- **每条验收出口前问两遍**:这条能不能验?**执行体有没有能力遵守它?**
(实测写过的做不到条款:`npx tsc`、「全量 0 fail」在执行体沙箱里、
「`s1-green` 不许被合并」——那是引擎的优化,执行体控制不了。)
- 无证据的决策行,先补证据或降级进 Open,不进 Contracts。
- 写完提示 owner:确认后 `/omd-execute` 执行。
- 看已有结晶 → `ls docs/plan/*.md` 按时间列出。
## 边界
- 审议在 `/omd-grill`(问透之前不结晶);轻量决策/引用 → `/omd-note`;执行 → `/omd-execute`,本 skill 不碰实现。
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.