Skip to content
Back to skills

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
ai-agentsgoshellbashnode

Security analysis

A100/100

Scanned September 20, 2026

npx -y skills add AbyssCN/oh-my-dag --skill omd-contract --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Omd Contract?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Omd Contract
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/abysscn-omd-contract/badge)](https://www.skillsdirectory.com/skills/abysscn-omd-contract)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
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

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.