check と validate の違い
koyu は「正しさ」を二つに割っている。
| 構成の診断 | 建築の判定 | |
|---|---|---|
| コマンド | koyu check | koyu validate |
| 返す型 | Diagnostic { code, severity } | Finding { rule, level } |
| 識別子 | BND04 SUF01 — 3 字 + 2 桁 | envelope.gap access.unreachable — 章.規則 |
| 重さ | error / warning | violation / caution |
| 数 | 65 コード | 15 規則 |
| 版 | 凍る | 凍らない。増える |
| 言うこと | 書かれたものがデータとして矛盾していない | 建築として妥当である (らしい) |
綴りが違うのは事故を防ぐためである。ENV01 と envelope.gap を取り違える読み手はいない。
型からして別である
--json を付けると、二つが同じ形をしていないことがそのまま見える。
npx tsx src/cli.ts check b1.muro --json
[
{
"code": "BND04",
"severity": "error",
"message": "The spaces do not touch, so no boundary can be derived: /L1/a | /L1/b",
"line": 6,
"file": "b1.muro",
"path": [
"/L1/a",
"/L1/b"
]
}
]
npx tsx src/cli.ts validate gap.muro --json
[
{
"rule": "envelope.gap",
"level": "caution",
"message": "Perimeter not faced by any envelope: /L1/b — S 3600mm / E 4000mm / N 3600mm (11200mm over 3 run(s)). Write a boundary to the exterior",
"line": 6,
"file": "gap.muro",
"path": [
"/L1/b"
]
}
]
混ぜられないことがこの型の仕事である。下流の道具が二つを同じ配列に流し込むには、まず型を潰す必要がある。潰したことは、その時点で見える。
分ける理由 — 求められる品質が違う
判定は、何が正しいかがまだ定まっていない領域である。採光の有効係数をどう扱うか、階段の窮屈さをどこで切るか、避難の経路をどう数えるか — どれも管轄と時代と建物用途で変わる。定まらないうちに凍結すれば、誤りを凍結することになる。
一方、構成の診断は定まっている。パスが一意か。参照先が存在するか。二つの領域が重なっていないか。これらは「読解の一部」であって、意見の余地が無い。
だから扱いを変える。
| 構成の診断 | 建築の判定 | |
|---|---|---|
| 足すときの値段 | 高い — 解析・合成・機械形式・仕様・文書を同時に触る | 安い — 台帳に一行と、頁に一節 |
| 間違えたときの値段 | 極めて高い — 凍った面に誤りが残る | 安い — 書き直せる |
| 精度 | 完全でなければならない | 粗くてよい |
| 捨てられるか | 捨てられない | 捨ててよい |
汚くてよい条件は一つ。判定の結果が、原本の保証と混同されないこと。その条件を、綴りと型と出力の文言が三重に守っている。
Validation — 2 violations / 0 cautions
✔ Nothing caught by validation (this is a judgement, not a guarantee about the composition)
判定が緑でも、それは判定が緑なだけである。
判定が粗くてよいことの実例
envelope.gap は外皮の穴を報告する規則である。判定の母集団は外部への境界を一本でも書いたレベルだけである。
外皮をまだ模型にしていない階を「穴が開いている」とは言わない。「書き始めたなら閉じきる」という整合の要求であって、完全性の要求ではない。
これは正確な規則ではない。基本計画の途中で外皮を一階分だけ書いた模型は、他の階について何も言われない。それでよい — 粗さを直す値段が安いからこの粗さで出せる。core にこの規則があったら、この粗さでは出せなかった。
数を返すのは core、線を引くのは判定
集計とグラフの問いは core が持つ。ただし合否を言わない。
| 問い | core が返すもの | 判定が言うこと |
|---|---|---|
| 採光 | 床面積と有効窓面積 | 1/7 を満たすか (daylight.ratio) |
| 敷地 | 敷地面積・接道長・建築面積・延べ面積とその商 | 2m の接道 (site.frontage)・はみ出し (site.escape) |
| 縦動線 | 段数・蹴上・踏面・勾配 | 窮屈さ (stair.proportion)・勾配 (run.slope) |
| 外皮 | 何にも面していない外周の線分 | それが穴か (envelope.gap) |
| 動線 | 最少扉数の経路と通行可能性 | 外部へ出られるか (access.unreachable ほか) |
| 柱と開口 | 通り芯から立つ柱と線分上の開口 | 重なっているか (column.blocksdoor) |
閾値は建築の側にある。1/7 も 2m も 240mm も、原本の構成が満たすべき不変量ではない。数を返すところまでが core で、数に線を引くのが判定である。
この線引きがあるので、別の管轄の判定を足すことは core を一行も触らずにできる。規則を台帳に足し、頁を一つ書けば終わりで、言語の版は動かない。
判定は増える面である
15 規則は完成形ではない。防火区画、日影、斜線、動線の距離、バリアフリー、設備の成立 — 判定として書けることは山ほど残っている。
それらは全部この面に足される。足しても .muro の意味は変わらず、既存のファイルは読めたまま、正準 JSON は同じバイト列を出す。
言語に足すことは高く、判定に足すことは安い。この非対称を作るためにこそ、二つを分けてある。
この先
- 言語・判定・描画の分離 — この分割の全体像
- 診断 — koyu check — 65 コード
- 判定 — koyu validate — 15 規則
- 約束の範囲