コンテンツにスキップ

rulec の診断

rulec が出しうるコードの全部について、いつ出るかと、どう直すかを書いています。コードと JSON の形は安定 API で、変わるのは文面の改善だけです。一件だけ読むときは rulec explain E101 を使ってください。

コード 種別 見出し
E001 error 文字列が閉じていません
E002 error 読めない文字があります
E003 error ファイルが rule の行で始まっていません
E004 error 行の先頭に語がありません
E005 error この位置に書けない語です
E006 error 宣言に = がありません
E007 error そういう方式はありません
E008 error 空のセルがあります
E009 error 宣言の名前が予約語と衝突しています
E010 error .. を使った範囲記法は書けません
E011 error 公開される名前に ASCII の別名がありません
E012 error 宣言されていない名前です
E013 error 取込先がありません
E014 error 出力のセルに式は書けません
E015 error result が書けるのは最初の出力だけです
E016 error result は一つしか書けません
E017 error constraint の形が違います
E018 error constraint は入力どうしの関係です
E019 error 例が、生成コードが入口で受け付けない入力です
E020 error elements の宣言が正しくありません
E021 error fold の書き方が正しくありません
E022 error 要素がゼロ件のときの答えが宣言されていません
E023 error 最後まで見終えたときの答えが宣言されていません
E024 error 行き先の無い判定があります
E025 error 例に並びの列がありません
E026 error sequence の書き方が正しくありません
E027 error 例が指す並びがありません
E028 error count の書き方が正しくありません
E029 error この列は数えられません
E030 error count に範囲が要ります
E031 error 一つの項目が、二つの並びの要素を読んでいます
E032 error 取り込んだ列挙と宣言がずれています
E033 error 外から来た列挙の値に、行も default もありません
E034 error 同じ名前が二度あります
E035 error overrides の指す先がありません
E036 error overrides の相手が同じ出力を定めていません
E037 error 引用した箇所のハッシュが固定されていません
E038 error 引用した箇所が変わっています
E039 error 出典のコピーがありません
E040 error 固定した元のファイルが、書いてあるハッシュと違います
E041 error 準用の読み替えが元の規則と合いません
E042 error 読み替えの型が合いません
E043 error 渡す値が元の規則の範囲か制約に収まりません
E044 error その規則は準用できません
E045 error 出力を共有する表に、出力の列が二つ以上あります
E046 error clause の形が読めません
E047 error 宣言の後ろに余分な語があります
E049 error 桁区切りのカンマは書けません
E048 error この型には足し算も掛け算もありません
E050 error machine の節の形が違います
E051 error carry か over が宣言と噛み合いません
E052 error ステートマシンに書いた状態が噛み合いません
E053 error once の行が宣言と噛み合いません
E054 error 並びを畳む規則は、ステートマシンの一歩になれません
E055 error scenario の形が違います
E056 error held の行が宣言と噛み合いません
E057 error 宣言に型がありません
E058 error 宣言の行を読めません
E059 error 式を読めません
E060 error 刻みが正の値ではありません
E061 error 範囲が空です
E062 error ありえない日付です
E063 error セルを読めません
E064 error 行が見出しと合いません
E065 error range from koyomi の形か置き場所が違います
E066 error enums のファイルの形と、そこから読む import enum の形が違います
E069 error 順序つきの列挙と比べるセル、または表示名の形が違います
E071 error 前提のつながりの形が違います
E072 error 持ち越す値の書き方が違います
E075 error 列挙の値でも、名前でもある語です
E101 error 完全性の欠落: どの行にも当てはまらない入力があります
E102 error どの入力にも当てはまらない行があります
E103 error 単位の混同: 型の違う値を混ぜています
E104 error 数値の出力に丸めの宣言がありません
E105 error 行の重なり: 同じ入力が二つ以上の行に当てはまります
E106 error 出力のリテラルが丸めの刻みに載っていません
E107 error 例の期待値と一致しません
E108 error 中間値が int64 に収まることを証明できません
E109 error 検査の予算を超えたので、完全性を証明できませんでした
E110 error 検査できない型の列があります
E111 error 例に出力の列がありません
E112 error 導出の範囲が、実際に到達しうる値を含んでいません
E113 error 真偽定義の条件が、書ける二つの形のどちらでもありません
E114 error 値が宣言した刻みに載っていません
E115 error 割る数が正の定数ではありません
E116 error 行の金額が、引いた出典のコピーに無いか、別の見出しの下にあります
E117 error 配分の前提が揃っていません
E118 error 呼び出しの形が違います
E120 error from が入力の型と合いません
E121 error from のパスが契約にありません
E119 error 行の境界が、引いた出典のコピーと反対側です
W122 warning その shape を使っている入力がありません
E122 error 契約が通す値を、規則が受け付けません
W123 warning 行が、契約の通さない値でしか当たりません
E123 error 契約が、規則の constraint を破る組み合わせを通します
W124 warning 行が、契約の通さない組み合わせでしか当たりません
E124 error 終わりの状態から出る遷移があります
E125 error 着いたら終われない状態があります
E126 error never の主張が破れています
E127 error once の主張が破れています
E128 error ステートマシンの主張を検査できませんでした
E129 error この rulec は koyomi のファイルを読めません
E130 error koyomi の日付がとる日を読めません
E132 error 割る数が 0 になりえます
E139 error isqrt の引数が負になりえます
E140 error 出力の範囲が、出力のとる値を含んでいません
E134 error 持ち越す数が範囲を出る呼び出しがあります
E135 error always の主張が破れています
E136 error 前提が循環しています
E137 error start からたどり着けない値があります
E138 error ordered by の順で、前提が値より後に来ます
W125 warning どの手順でも着かない状態があります
W126 warning 案件が着ける状態からは使われない遷移があります
W127 warning ステートマシンの主張を決めきれませんでした
W128 warning 行に当たる入力を見つけられず、当たらないことも示せませんでした
W130 warning ほかの前提からたどれる前提があります
W105 warning 要確認の隠れ: 先の行が後の行の一部を隠しています
W110 warning 重なりのない first です
W111 warning 使われていない宣言があります
W116 warning どの例も使っていない sequence です
W119 warning ハッシュを書いた箇所が引用されていません
W120 warning 出典のコピーにある値を、どの行も使っていません
W118 warning 準用した表の行が、この規則ではどれも当たりません
W117 warning 効かない例外です
W121 warning 生成先の言語で、識別子がぶつかるか使えません
W115 warning どの要素もこの判定にはなりません
W114 warning 未確認の重なり: 両方に当てはまる入力が有り得ます
W901 warning 鍵がファイルに書かれています
E074 error from sum・from max・from min か elements … from の形が違います
E070 error 乱数の入力か確率の主張の形が違います
E073 error 重みで選ぶ畳み込みの形が違います
E133 error 確率の主張が成り立ちません
W129 warning 確率の主張を予算の中で決められませんでした
W131 warning 確率の関数は、呼ぶたびに規則を何度も評価します
E067 error 寄与の形が違います
E068 error 開いた値の形が違います
E131 error 合わせた値が、宣言した範囲を出ます
W132 warning 開いた値の項が、合わせた値を変えません

E001

error — 文字列が閉じていません

いつ出るか。 " で開いた文字列が、その行のうちに閉じていないとき。セルの中にも description にも改行は書けません。

直し方。 その行のうちに " を閉じてください。長い説明は一行に収めるか、# のコメントに移してください。

最小の再現:

rule t(t) v1
description "unterminated

関係するコード: E002

E002

error — 読めない文字があります

いつ出るか。 名前の位置に、文字でも _ でもない文字(記号や制御文字)があるとき。括弧に入れた別名が名前になっていないとき(六十(60))も同じです。打ち間違いが黙って名前になったり、別名が黙って消えたりするのを防ぐための検査です。

直し方。 その文字を消してください。名前は文字か _ で始まります(@x(x) なら x(x)、六十(60) なら 六十(size_60))。

最小の再現:

rule t(t) v1

inputs
  %x(x) : bool

関係するコード: E001, E009

E003

error — ファイルが rule の行で始まっていません

いつ出るか。 一つの .rule は一つの規則で、先頭行が規則名と版です。空行とコメントより前に他の宣言があるとき、または rule の行に名前が無いとき。名前の無い rule の行は、いままで何も言われずに、中身の無い規則として検査を通っていました。

直し方。 先頭に rule 規則名(alias) v1 の一行を足してください。

最小の再現:

inputs
  x(x) : bool

関係するコード: E004, E011

E004

error — 行の先頭に語がありません

いつ出るか。 表でもコメントでも空行でもない行が、記号で始まっているとき。この構文は行指向なので、行の先頭の語が何の宣言かを決めます。

直し方。 行頭に宣言の語を書いてください(description / import / enum / group / inputs / elements / outputs / derive / define / constraint / table / fold / count / sum / max / min / sequence / result / examples / policy / overrides / clause / source / apply / shape / machine / scenario / prerequisites / chances / open)。表の行なら | で始めてください。

最小の再現:

rule t(t) v1

= 1

関係するコード: E003, E005

E005

error — この位置に書けない語です

いつ出るか。 行頭の語が語彙にないとき。語彙には同義の綴りがなく、英語の一種類だけです。

直し方。 description / import / enum / group / inputs / elements / outputs / derive / define / constraint / table / fold / count / sum / max / min / sequence / result / examples / policy / overrides / clause / source / apply / shape / machine / scenario / prerequisites / chances / open のどれかに直してください。業務の語を書けるのは、名前とセルの中だけです。

最小の再現:

rule t(t) v1

foo bar

関係するコード: E004, E009

E006

error — 宣言に = がありません

いつ出るか。 enum group derive define result の行に、名前と中身を分ける = が無いとき。

直し方。 = を入れてください。例: enum k(k) = a(a) | b(b)。

最小の再現:

rule t(t) v1

enum k(k) a(a) | b(b)

関係するコード: E005

E007

error — そういう方式はありません

いつ出るか。 policy の後ろが unique と first 以外のとき。DMN の Any / Priority / Collect は採っていません。

直し方。 policy unique(重なりはすべてエラー)か policy first(先に書いた行が勝つ)に直してください。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool

outputs
  r(r) : bool

table j(j)
policy any
| x | -> r(r) : bool |
| - | true           |

関係するコード: W110, E105, W105

E008

error — 空のセルがあります

いつ出るか。 表のセルが空白だけのとき。空欄は書き忘れと区別がつかないので構文エラーにしています。

直し方。 どの値でもよいなら - と書いてください。値を書き忘れていたなら、その値を書いてください。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool

outputs
  r(r) : bool

table j(j)
policy unique
| x | -> r(r) : bool |
|   | true           |

関係するコード: E101

E009

error — 宣言の名前が予約語と衝突しています

いつ出るか。 宣言した名前(や別名)が語彙の語と同じとき。行指向のパーサーがその行をセクションの始まりと読んで、宣言を黙って捨てる事故を防ぐための検査です。列挙の値は行の頭に来ないので、列挙の値で出るのは、値の位置で別の意味に読まれる 11 語(not none true false starts_with default after empty exhausted by with)のときだけです。

直し方。 名前を変えてください(enum range(kind) なら enum 範囲区分(range_kind))。予約語は src/kw.rs の表ひとつで決まっています。

最小の再現:

rule t(t) v1

enum range(kind) = a(a) | b(b)

関係するコード: E005, E011

E010

error — .. を使った範囲記法は書けません

いつ出るか。 セルに 0g..1000g のような .. があるとき。「1000g まで」が両端を含むのか含まないのかが、書いてある字から読めないためです。

直し方。 比較演算子で書き直してください。0g..1000g は <=1000g か <1000g のどちらかです。両端を決めたいなら >=0g <=1000g と並べて書いてください。

最小の再現:

rule t(t) v1

inputs
  w(w) : mass[g]  range >=0g <=10kg

outputs
  r(r) : bool

table j(j)
policy unique
| w         | -> r(r) : bool |
| 0g..1000g | true           |
| >1000g    | false          |

関係するコード: E105, E101

E011

error — 公開される名前に ASCII の別名がありません

いつ出るか。 規則名・入力・出力・並び・要素のフィールドに、ASCII でない名前が付いていて括弧の中の別名も無いとき。別名は生成コードの公開名になります(漢字は大文字を持てず、Go の公開識別子になれません。.proto のフィールドの名前は ASCII だけです)。並びは呼ぶ側が渡す入力で、要素のフィールドは呼ぶ側が埋めるので、入力と同じく公開されます。名前がもとから ASCII なら、それ自身が公開名になるので別名は要りません。

直し方。 括弧で別名を足してください(重量 : bool なら 重量(weight) : bool)。導出・定義・グループ・表の別名は任意で、書けば生成コードがその名前を使い、書かなければ宣言した名前をそのまま使います。

最小の再現:

rule t(t) v1

inputs
  重量 : bool

outputs
  r(r) : bool

table j(j)
policy unique
| 重量 | -> r(r) : bool |
| -    | true           |

別名の無い並び:

rule 明細の合計(lines_total) v1

elements 明細
  金額(amount) : money[USD]  range >=0USD <=100USD

outputs
  合計(total) : money[USD]  round down(1USD)

sum 支払い(spent) over 明細 of 金額  range >=0USD <=1000USD

define 合計 : money[USD] = 支払い

関係するコード: E009, E012

E012

error — 宣言されていない名前です

いつ出るか。 表の列や式が、どこにも宣言されていない名前を指しているとき。前に宣言していない名前は使えないので、名前はそれを使う行より上で宣言する必要があります。セルやグループに書いた値がどの列挙の値でもないときにも出ます。組み込みの区分(std/us/states など)を取り込んでいれば、注に、似た綴りの値か、その語を値に持つ別の国の名前空間が出ます。取り込んだ二つの国が同じ綴りの値を持つとき(WA はワシントン州と西オーストラリア州の符号です)は、その綴りをそのまま書いても出ます。none はこれに当たりません。optional の列では値の無いことで、optional でない列では E103 です。

直し方。 綴りを宣言に合わせるか、その入力・導出・定義を上に宣言してください。二つの国が共有する綴りなら、値の名前(Washington か Western_Australia)で書いてください。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool

outputs
  r(r) : bool

table j(j)
policy unique
| y | -> r(r) : bool |
| - | true           |

関係するコード: E011, E013

E013

error — 取込先がありません

いつ出るか。 import の先が無いとき。取込先は三つあります。組み込みの名前空間(十三か国の一段目の区分。std/us/states、std/gb/nations、std/cn/provinces、std/tw/divisions、std/kr/provinces、std/in/states、std/fr/regions、std/es/communities、std/it/regions、std/de/states、std/au/states、std/br/states、std/jp/prefectures。日本の都道府県は std/都道府県 でも取り込めて、そのときは値を日本語で書きます)、.proto の列挙(import proto "<ファイル>" <列挙> -> <この規則の列挙>)、JSON Schema の列挙(import jsonschema "<ファイル>" "<ポインタ>" -> <この規則の列挙>、OpenAPI も同じ)です。あとの二つは、ファイルを読めないとき、その列挙がファイルに無いとき、行の形が違うときに出ます。rulec は YAML を読まないので、JSON にしたものを指してください。一つの国の区分を二つの名前で取り込んだとき(std/都道府県 と std/jp/prefectures)にも出ます。

直し方。 名前空間の綴りを直すか(似た綴りがあれば注に出ます)、その列挙を enum でこのファイルに書いてください。ファイルから取り込むなら、パスは規則ファイルのある場所からの相対パスで書いてください。JSON Schema のポインタは #/components/schemas/<名前> の形です。ポインタが届かなかったときは、注に、届いたところにある鍵が並びます。

最小の再現:

rule t(t) v1

import std/都道府

関係するコード: E012, E032

E014

error — 出力のセルに式は書けません

いつ出るか。 表の -> から右のセルに語が二つ以上あるとき。書けるのは値一つか名前一つだけです。残りを読み飛ばして最初の語だけを採ると、かけ算が黙って消えた生成コードができてしまいます。

直し方。 計算に名前を付けて define の行へ出し、表にはその名前だけを書いてください(| - | 率割引 |)。表に書くのは分岐だけです。

最小の再現:

rule t(t) v1

inputs
  p(p) : money[円, incl_tax]  range >=0円 <=1万円
  r(r) : rate[step 1%]  range >=0% <=100%

outputs
  o(o) : money[円, incl_tax]  round down(1円)

table j(j)
policy first
| r    | -> o(o) : money[円, incl_tax] |
| <=5% | 0円                           |
| -    | p × r                         |

関係するコード: E008, E012

E015

error — result が書けるのは最初の出力だけです

いつ出るか。 result が二つ目以降の出力を指したとき。result は最初の出力を組み立てるための書き方で、評価器も生成コードもそこにしか当てません。書いた名前が効かないまま通っていたので、number が money の枠に入っても E103 が出ませんでした。

直し方。 その出力と同じ名前の define を書いてください(define 付与点(pts) : number = 基本点 × 倍率)。出力の値は宣言の順に、同じ名前の define から取られます。result で組み立てたいなら、その出力を outputs の先頭へ移してください。

最小の再現:

rule t(t) v1

inputs
  p(p) : money[円, incl_tax]  range >=0円 <=1万円

outputs
  a(a) : money[円, incl_tax]  round down(1円)
  b(b) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| p | -> a(a) : money[円, incl_tax] |
| - | 100円                         |

result b = p

関係するコード: E016, E103

E016

error — result は一つしか書けません

いつ出るか。 一つのファイルに result の行が二本以上あるとき。組み立てられるのは最初の出力だけなので、二本目は一本目を置き換えるだけになります。以前はそれが黙って起きていました。

直し方。 一本だけ残してください。ほかの出力の値は、その出力と同じ名前の define から取られます。

最小の再現:

rule t(t) v1

inputs
  p(p) : money[円, incl_tax]  range >=0円 <=1万円

outputs
  a(a) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| p | -> a(a) : money[円, incl_tax] |
| - | 100円                         |

result a = p
result a = p + 100円

関係するコード: E015

E017

error — constraint の形が違います

いつ出るか。 constraint の行が「入力 比較 入力」になっていないとき。比較が無い、片側が名前一つでも名前を + で足した和でもない、両側とも和になっている、のどれかです。

直し方。 constraint <入力> <= <入力> の形にしてください。比較は <= < >= > の四つです。片側だけは入力を足した和にできます(constraint 値引き + ポイント <= 小計)。係数と定数は書けません。A = B を言いたいなら、A <= B と A >= B の二行に分けてください。

最小の再現:

rule t(t) v1

inputs
  a(a) : number  range >=0 <=10
  b(b) : number  range >=0 <=10

constraint a

outputs
  r(r) : bool

table j(j)
policy unique
| a | -> r(r) : bool |
| - | true           |

関係するコード: E018

E018

error — constraint は入力どうしの関係です

いつ出るか。 constraint の片側が入力でないか、順序の無い型のとき。制約は「呼び出し側が渡す値の組み合わせのうち、どれが起きるか」を言うものなので、両側とも inputs の名前で、型は金額・数量・率・number・日付のどれかでなければなりません。和の側の名前も、一つずつ同じです。

直し方。 両側を inputs の名前にしてください。導出や定義は入力から計算されるので、関係は元の入力どうしで書いてください。列挙や真偽に大小はありません。

最小の再現:

rule t(t) v1

inputs
  a(a) : number  range >=0 <=10

constraint a <= r

outputs
  r(r) : bool

table j(j)
policy unique
| a | -> r(r) : bool |
| - | true           |

関係するコード: E017, W111

E019

error — 例が、生成コードが入口で受け付けない入力です

いつ出るか。 例の入力が constraint を満たしていないとき、または入力(並びの要素のフィールドを含む)の値が宣言した範囲の外にあるとき。制約は「この組み合わせは起きない」という宣言で、範囲は「この外の値は来ない」という宣言です。完全性の検査はそれを信じて、そこには行を要求していません。生成コードもその入力を入口で受け付けません。そのため、規則はその入力の答えを決めていません。範囲の外の例と、二つの日付のあいだの constraint を破る例は、いままで検査を通り、その例から作ったベクタは、生成コードでエラーになっていました。

直し方。 例の値を直してください。その値や組み合わせが本当に来るなら、範囲を広げるか、制約を消してください。

最小の再現:

rule t(t) v1

inputs
  a(a) : number  range >=0 <=10
  b(b) : number  range >=0 <=10

constraint a <= b

outputs
  r(r) : bool

table j(j)
policy unique
| a | b | -> r(r) : bool |
| - | - | true           |

examples
| a | b | -> r |
| 5 | 1 | true |

関係するコード: E017, E018, E101

E020

error — elements の宣言が正しくありません

いつ出るか。 elements に名前が無いとき、または宣言した並びをどの行もたどらないとき。並びは、count・sum・max・min・fold のどれかが over で指して、はじめて規則の値になります。たどらない並びのフィールドを読む項目は、どの要素の値を読むのかが決まりません。規則は並びをいくつでもたどれます(elements は何本でも書けます)。

直し方。 elements 運賃行(fee_rows) の形で名前を書き、続く行に一要素ぶんのフィールドを inputs と同じように書いてください。並びが要るなら、たどる行を足してください。要らないなら、その elements を消してください。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=0 <=10

elements xs(xs)
  k(k) : number  range >=0 <=10

outputs
  r(r) : bool

table j(j)
policy unique
| n | -> r(r) : bool |
| - | true           |

関係するコード: E028, E021, E031

E021

error — fold の書き方が正しくありません

いつ出るか。 fold <判定の列> over <並びの名前> [-> <名前> [: <型>]] になっていないか、判定の行き先が next stop stop with <値> take_unique <値> take_first <値> keep_max <値> by <鍵> take_weighted <値> by <重み> のどれでもないか、畳もうとしている列が列挙でないとき。答えの名前が、入力、要素のフィールド、たどる並び、上で宣言した値と同じとき、出力でない名前に型が無いとき、出力の名前に出力と違う型を書いたとき、畳み込みとほかの項目が同じ名前を決めるときも、これです。畳み込みの値が、その値を決める時点に無い値を読むときもこれです。empty と exhausted の値は要素を見ていないところで決まるので、要素の値を読めません。どの値も、この畳み込みの答えから計算する値を読めません(要素の判定がその答えを読むと、答えを出す前に答えが要ります)。held は最後まで見終えたときの値なので、exhausted の値にだけ書けます。

直し方。 見出しと行き先を上の形に直してください。take とだけ書くことはできません。一件だけ採るのか、最初の一件を採るのかは、書く人が選ぶことだからです。要素の値を答えにするなら、take_unique・take_first・keep_max で採ってから、exhausted -> held で返してください。後ろの項目が答えを読むなら -> <名前> で名前を付けます。自分の答えを読む判定は、別の畳み込みにすれば二回目の歩きで読めます。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=0 <=10

elements xs(xs)
  k(k) : number  range >=0 <=10

outputs
  r(r) : bool

table j(j)
policy unique
| n | -> r(r) : bool |
| - | true           |

fold r
  empty -> false

関係するコード: E020, E022, E023, E024

E022

error — 要素がゼロ件のときの答えが宣言されていません

いつ出るか。 fold に empty -> <値> が無いとき、max・min に empty <値> が無いとき。空の並びは必ず来ます。手で書いたループがいちばんよく見落とすのがこの場合で、たいていは最初の要素をそのまま読もうとして、実行時に落ちます。max・min では、where に当てはまる要素が一つも無いときも、この値が答えです。

直し方。 empty -> <値>(max・min では empty <値>)を足してください。何を返すかは業務の判断で、rulec が決められることではありません。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)

elements xs(xs)
  k(k) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| k     | -> d(d) : v |
| <=5円 | a           |
| >5円  | b           |

fold d over xs
  a -> next
  b -> take_first k
  exhausted -> held

max に empty が無い:

rule t(t) v1

elements xs(xs)
  k(k) : number  range >=0 <=10

outputs
  r(r) : number  round down(1)

max r over xs of k

関係するコード: E023, E024

E023

error — 最後まで見終えたときの答えが宣言されていません

いつ出るか。 fold に exhausted -> <値> が無いとき。どの要素も打ち切らずに並びが尽きた場合の答えです。保持していた暫定の値をそのまま返すつもりでも、書くまでは決まっていません。

直し方。 exhausted -> <値> を足してください。保持しているものを返すなら exhausted -> held です。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)

elements xs(xs)
  k(k) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| k     | -> d(d) : v |
| <=5円 | a           |
| >5円  | b           |

fold d over xs
  a -> next
  b -> take_first k
  empty -> 0円

関係するコード: E022, E024

E024

error — 行き先の無い判定があります

いつ出るか。 表が出しうる判定のどれかに、fold の行き先が無いとき。その判定の要素が来たら、次にどうするかが決まっていません。表の完全性と同じ検査を、畳み込みの側に当てたものです。

直し方。 行き先を足すか、表がその値を出さないようにしてください。逆に、どの要素もたどり着けない判定に行き先があるときは、W115 が出ます。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)

elements xs(xs)
  k(k) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| k     | -> d(d) : v |
| <=5円 | a           |
| >5円  | b           |

fold d over xs
  a -> next
  empty -> 0円
  exhausted -> held

関係するコード: E022, E023, W115

E025

error — 例に並びの列がありません

いつ出るか。 並びをたどる規則に examples があるのに、elements の名前の列が見出しに無いとき。どの並びをたどるかが決まっていない例は、答えの決まっていない例です。

直し方。 sequence <名前> で並びを書き、例の見出しに並びの列を足して、その名前をセルに書いてください。行がゼロ本の sequence は、要素ゼロ件の例になります。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)

elements xs(xs)
  k(k) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| k     | -> d(d) : v |
| <=5円 | a           |
| >5円  | b           |

fold d over xs
  a -> next
  b -> take_first k
  empty -> 0円
  exhausted -> held

examples
| -> r |
| 0円  |

関係するコード: E026, E027

E026

error — sequence の書き方が正しくありません

いつ出るか。 sequence のフィールドが elements のフィールドとそろっていないとき。余分なフィールドがある、フィールドが足りない、見出しに同じフィールドの列が二つある、-> がある、たどる並びそのものが無い、同じ名前が二つある、セルが値でない(範囲や - が書いてある)、のどれかです。

直し方。 elements のフィールドをそのまま見出しにして、一行に一件ぶんの値を書いてください。これは表ではなく、実際に渡す値の並びです。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)

elements xs(xs)
  k(k) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| k     | -> d(d) : v |
| <=5円 | a           |
| >5円  | b           |

fold d over xs
  a -> next
  b -> take_first k
  empty -> 0円
  exhausted -> held

sequence s(s)
| m   |
| 3円 |

関係するコード: E025, E020

E027

error — 例が指す並びがありません

いつ出るか。 例の並びの列に書かれた名前の sequence が無いとき、またはその列に名前でないもの(数や範囲)が書かれているとき。

直し方。 その名前で sequence を書くか、セルを、書いてある sequence の名前に直してください。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)

elements xs(xs)
  k(k) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| k     | -> d(d) : v |
| <=5円 | a           |
| >5円  | b           |

fold d over xs
  a -> next
  b -> take_first k
  empty -> 0円
  exhausted -> held

examples
| xs   | -> r |
| nope | 0円  |

関係するコード: E025, E026

E028

error — count の書き方が正しくありません

いつ出るか。 count <名前>(<別名>) over <並びの名前> where <列> = <値> になっていないとき。over が無い、where が無い、指した並びが elements で宣言されていない、= の右に値が無い。sum <名前>(<別名>) over <並びの名前> of <列>、max・min の <名前>(<別名>) over <並びの名前> of <列> [where <列> [= <値>]] empty <値> の形でないときも、これです。

直し方。 上の形に直してください。= <値> は、真偽の列を数えるときだけ省けます。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=0 <=10

elements xs(xs)
  b(b) : bool

outputs
  r(r) : bool

count h(h) where b  range >=0 <=10

table j(j)
policy unique
| n | -> r(r) : bool |
| - | true           |

関係するコード: E029, E030, E020

E029

error — この列は数えられません

いつ出るか。 where が指す列が、要素ごとに決まる値でないとき(入力や導出は一件の呼び出しに一つしかないので、数えても 0 か 1 です)。値が有限の集合でないとき。書いた値がその列挙にないとき。列挙の列なのに = <値> が無いとき。sum・max・min の of が指す列も同じで、over が指すのと別の並びの値のとき、sum の列が数でないとき、max・min の列が数・日付・順序つきの列挙のどれでもないときにも出ます(max・min では題が「この列はまとめられません」になります)。

直し方。 要素のフィールドか、要素ごとの表が出した列を指してください。判定を表に書けば、その分類そのものも完全性の検査に掛かります。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=0 <=10
  ok(ok) : bool

elements xs(xs)
  b(b) : bool

outputs
  r(r) : bool

count h(h) over xs where ok  range >=0 <=10

table j(j)
policy unique
| h | -> r(r) : bool |
| - | true           |

関係するコード: E028, E012

E030

error — count に範囲が要ります

いつ出るか。 count の行に range >=0 <=<上限> が無いか、上限が無いか、下限が負のとき。範囲には二つの意味があります。数えた結果を列に使ったときに完全性の検査が調べる値の全体と、並びの長さの上限です。

直し方。 range >=0 <=100 の形で書いてください。生成コードは、この上限より長い並びを入口で受け付けません。数値の入力と同じで、宣言の外は黙って通しません。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=0 <=10

elements xs(xs)
  b(b) : bool

outputs
  r(r) : bool

count h(h) over xs where b

table j(j)
policy unique
| h | -> r(r) : bool |
| - | true           |

関係するコード: E028, E112

E031

error — 一つの項目が、二つの並びの要素を読んでいます

いつ出るか。 一つの項目(表・節・導出・定義・畳み込み)が、二つの並びの要素の値を読むとき。要素の値は、その並びをたどっているあいだにしかありません。二つの並びの要素を一緒に読むには、片方の並びの要素ごとに、もう片方を最初からたどることになります(並びの中で並びをたどる)。そうすると歩きの数が並びの長さにつれて増え、検査が終わりません。出力が要素ごとの値のときも、これです。たどり終えたあとには、一つの値に決まりません。規則の項目は、要素によらない項目と要素ごとの項目に分かれ、要素ごとの項目は、読む集計の答えが決まったあとの歩きで計算されます(集計の答えを読む要素ごとの項目は二回目の歩きに入ります)。

直し方。 片方の並びを count・sum・max・min・fold で一つの値にしてから、もう片方の項目で読んでください。その項目は、その値が決まったあとの二回目の歩きで計算されます。要素ごとの値を出力にするなら、集計で並び全体の一つの値にしてから出力にしてください。

最小の再現:

rule t(t) v1

elements xs(xs)
  a(a) : number  range >=0 <=10

elements ys(ys)
  b(b) : number  range >=0 <=10

outputs
  r(r) : number  round down(1)
  s(s) : number  round down(1)

define both(both) : number = a + b

sum r over xs of both  range >=0 <=1000

sum s over ys of b  range >=0 <=1000

要素ごとの値の出力:

rule 大きな部品(big_parts) v1

elements 部品(parts)
  単価(price) : number  range >=0 <=100

outputs
  合計(total) : number  round down(1)
  大きい(big) : bool

table 大きさ(big_of)
policy unique
| 単価 | -> 大きい : bool |
| >=50 | true             |
| <50  | false            |

sum 合計 over 部品 of 単価  range >=0 <=10000

関係するコード: E021, E029, E020

E032

error — 取り込んだ列挙と宣言がずれています

いつ出るか。 import proto や import jsonschema が指す列挙の値と、この規則の enum の値(別名があれば別名)がそろっていないとき。片方にしか無い値は、どちらの側のものも名前で出ます。値が増えるのはたいてい proto の側で、それは規則の外での変更が、互換な変更として通ってしまったものです。

直し方。 増えた値をこの規則の enum に足してください。値の名前に別名を付けて書く列挙なら、名前は自分で決めてください。消えた値なら、この規則からも消してください。値を足すと、次はその値に行が要るかを E033 が問います。

最小の再現:

rule t(t) v1

import proto "tier.proto" Tier -> v
enum v(v) = one(one)

inputs
  x(x) : v

outputs
  r(r) : bool

table j(j)
policy unique
| x   | -> r(r) : bool |
| one | true           |

隣に置く tier.proto:

syntax = "proto3";

enum Tier {
  TIER_UNSPECIFIED = 0;
  TIER_ONE = 1;
  TIER_TWO = 2;
}

関係するコード: E013, E033, E101

E033

error — 外から来た列挙の値に、行も default もありません

いつ出るか。 取り込んだ列挙の値が、どの行にも現れず、default も付いていないとき。寄与が extend で足した値が、表のどの行にも名前で書かれず、- の行、その値を外さない not: の行、その値まで覆うようになった比べるセルの行に黙って落ちるときも同じです(行ごとに言います)。自分で書いた値なら書き忘れの警告(W111)で済みますが、契約や寄与から来た値の場合は外の変更がまだ誰にも読まれていないことを示すので、rulec はエラーにして止めます。既定の行がある表では完全性の検査が通ってしまい、新しい値には既定の行の答えが黙って当たります。

直し方。 その値の行を表に足すか、値の宣言に default を付けてください。寄与が足した値なら、開いた表に寄与が行を足すか、extend の行に default を付けてください。default は「既定の行に落ちるのが意図です」という宣言で、誰かがその値の扱いを決めたことを示します。

最小の再現:

rule t(t) v1

import proto "tier.proto" Tier -> v
enum v(v) = one(one) | two(two)

inputs
  x(x) : v

outputs
  r(r) : bool

table j(j)
policy first
| x   | -> r(r) : bool |
| one | true           |
| -   | false          |

隣に置く tier.proto:

syntax = "proto3";

enum Tier {
  TIER_UNSPECIFIED = 0;
  TIER_ONE = 1;
  TIER_TWO = 2;
}

寄与が足した値(extend):

contribution c(c) v1
to "base.rule" signature:69e01897ab91b191

extend kind with z

隣に置く base.rule:

rule base(base) v1

enum kind(kind) = a(a) | b(b)  open

inputs
  k(k) : kind

outputs
  fee(fee) : number  round down(1)

table t(t)
policy first
| k | -> fee : number |
| a | 1               |
| - | 2               |

関係するコード: E032, W111, E101, E067

E034

error — 同じ名前が二度あります

いつ出るか。 一つのファイルが同じ種類の名前を二度書いたとき、二つ目のところで出ます。種類は、値(入力、たどる並びとその要素のフィールド、出力、derive・define・count・sum・max・min・open と、表や節が決める出力の列)、表と節、列挙、一つの列挙の値、グループと一つのグループに書いた値、shape、出典、準用、前提のつながり、一つの表の行ラベル、表と例の見出しの列です。出力はそれを決めるものと同じ名前で、一つの名前をいくつかの表や節で決めることもできます。値のそれ以外の重なりは、入力と同じ名前の出力も含めて、一つの名前に二つの値があることになるので止まります。列挙の値と同じ名前のグループも、一つの語に二つの読み方があるので止まります。一つの並びの二つの名前が生成するコードで同じ識別子になるとき(一方の別名が、他方の別名か名前と同じ)、一つの名前に二つの別名を書いたとき、enums のファイルで列挙の名前がほかの列挙の別名と同じとき(import enum は名前でも別名でも列挙を探します)にも出ます。二つの名前の識別子が違っても、それを書くどの言語でも同じに綴るときにも出ます。二つの列挙の型と一つの列挙の二つの値(どちらも PascalCase で書きます)、二つの前提のつながりの関数(snake_case)、並びが二つ以上ある規則の要素の型、呼ぶ側のオブジェクトから入力を読む関数の引数として並ぶ shape と入力や並びです。いくつかの言語だけが同じに綴るものは W121 です。import enum で読んだ列挙と一緒に来たグループはこの規則の名前やほかの import enum が読んだものと、寄与が足す入力は足す先の規則の名前と比べます。畳み込みの答えの名前は E021、準用の出力に付けた名前は E041 で止まります。

直し方。 どちらかを消すか、名前を変えてください(行ラベルと見出しの列も同じです)。同じ識別子になる二つの名前は、どちらかに別の別名を付けてください。import enum で読んだ列挙なら、-> <別の名前> で読めます。

最小の再現:

rule 重さの判定(weight_check) v1

inputs
  重さ(weight) : number  range >=0 <=9
  重さ(weight) : number  range >=0 <=99

outputs
  重い(heavy) : bool

table 判定(decide)
policy unique
| 重さ | -> 重い |
| <=5  | false   |
| >5   | true    |

一つの列挙に同じ値が二つ:

rule 送料無料(free_shipping) v1

enum 会員区分(member_kind) = 一般(basic) | ゴールド(gold) | 一般(basic)

inputs
  会員(member) : 会員区分

outputs
  無料(free) : bool

table 判定(decide)
policy unique
| 会員     | -> 無料 |
| 一般     | false   |
| ゴールド | true    |

同じ識別子になる二つの名前:

rule 大きさの判定(size_check) v1

inputs
  重さ(weight) : number  range >=0 <=9
  長さ(weight) : number  range >=0 <=9

outputs
  大きい(large) : bool

table 判定(decide)
policy first
| 重さ | 長さ | -> 大きい |
| >5   | -    | true      |
| -    | >5   | true      |
| -    | -    | false     |

表の見出しに同じ列が二つ:

rule 重さの判定(weight_check) v1

inputs
  重さ(weight) : number  range >=0 <=9

outputs
  重い(heavy) : bool

table 判定(decide)
policy first
| 重さ | 重さ | -> 重い |
| <=5  | >5   | true    |
| -    | -    | false   |

型の名前が一つになる二つの列挙:

rule 段階ごとの料金(tier_fee) v1

enum 会員の段階(tier_level) = 一般(basic) | ゴールド(gold)
enum 地域の段階(tierLevel) = 近い(low) | 遠い(high)

inputs
  会員(member) : 会員の段階
  地域(band)   : 地域の段階

outputs
  料金(fee) : money[USD]  round down(1USD)

table 会員ごとの料金(fee_by_member)
policy unique
| 会員     | 地域 | -> 料金 |
| 一般     | -    | 1USD    |
| ゴールド | 近い | 2USD    |
| ゴールド | 遠い | 3USD    |

一つの表の二つの行に同じラベル:

rule t(t) v1

inputs
  a(a) : bool

outputs
  x(x) : bool

table 表(t1)
   | a     | -> x  |
r1 | true  | true  |
r1 | false | false |

関係するコード: E009, E035, E021, E041, E075, W121

E035

error — overrides の指す先がありません

いつ出るか。 overrides が指す表が無いか、この表より後ろで宣言されているか、表:行ラベル の行にそのラベルが無いとき。行の書き方が読めないときも同じです。例外は本文の後に書くので、指す先はいつも上にあります。

直し方。 上で宣言した表か、その行(行の先頭にラベルを書き、表:ラベル で指す)を指定してください。優先する側を後に書いてください。

最小の再現:

rule t(t) v1

inputs
  a(a) : bool

outputs
  x(x) : bool

table 表(t1)
overrides 無い表
| a     | -> x  |
| true  | true  |
| false | false |

関係するコード: E034, E036

E036

error — overrides の相手が同じ出力を定めていません

いつ出るか。 overrides の指す表が、この表とは別の出力を定めているとき。優先の順序は、同じ出力を定める定義のあいだにだけあります。

直し方。 同じ出力を定める表を指すか、この表の出力列をその相手と揃えてください。

最小の再現:

rule t(t) v1

inputs
  a(a) : bool

outputs
  x(x) : bool
  y(y) : bool

table 甲(ko)
| a | -> x |
| - | true |

table 乙(otsu)
overrides 甲
| a | -> y |
| - | true |

関係するコード: E035, E045

E037

error — 引用した箇所のハッシュが固定されていません

いつ出るか。 @出典 第91条 のように引用した箇所に、source の行の下の 第91条 sha256:… というハッシュの行が無いとき。file の出典なら、その行に sha256:… が無いとき。法令を箇所無しで @法 とだけ引用したとき、箇所の書き方や、引用・宣言の形が読めないときも同じです(隣に置いたファイルは @郵便 と丸ごと引用できます)。文書から引けるのは表なので、引用箇所は 表3(文書の中で三つめの表)か table3 と書いてください。それ以外の書き方は読めません。語として読めない箇所は " で囲んでください(@osha "§1910.157")。ハッシュが無いと、取り直したコピーの中身が変わっていても、check は何も言えません。

直し方。 原文を読んで、転記した行が正しいことを確かめたら、fix.text の行を貼るか rulec source pin <file.rule> を実行して、いまのコピーのハッシュを書き込んでください。

最小の再現:

rule t(t) v1

source 法 = law "000AC0000000001" asof 2026-04-01

inputs
  a(a) : bool

outputs
  x(x) : bool

table 表(t1)  @法 第1条
| a | -> x |
| - | true |

隣に置く sources/law/000AC0000000001@2026-04-01/MainProvision-Article_1.xml:

<Article Num="1"><ArticleTitle>第一条</ArticleTitle><Paragraph Num="1"><ParagraphNum/><ParagraphSentence><Sentence>甲は、乙とする。</Sentence></ParagraphSentence></Paragraph></Article>

関係するコード: E038, E039, W119

E038

error — 引用した箇所が変わっています

いつ出るか。 規則に書いてあるハッシュと、規則の隣にあるコピーのハッシュが違うとき。コピーを取り直した PR で出ます。注に、その箇所を引用している表・節・行が出るので、読み直すのはそこだけで済みます。

直し方。 コピーの差分を読み、転記した行がまだ正しければ fix.text のとおりハッシュの行を書き換えてください(rulec source pin でも書けます)。行が変わるなら、先に行を直してください。

最小の再現:

rule t(t) v1

source 法 = law "000AC0000000001" asof 2026-04-01
  第1条 sha256:0000000000000000

inputs
  a(a) : bool

outputs
  x(x) : bool

table 表(t1)  @法 第1条
| a | -> x |
| - | true |

隣に置く sources/law/000AC0000000001@2026-04-01/MainProvision-Article_1.xml:

<Article Num="1"><ArticleTitle>第一条</ArticleTitle><Paragraph Num="1"><ParagraphNum/><ParagraphSentence><Sentence>甲は、乙とする。</Sentence></ParagraphSentence></Paragraph></Article>

関係するコード: E037, E039

E039

error — 出典のコピーがありません

いつ出るか。 引用した箇所のコピーが規則の隣に無いとき(法令なら sources/law/<法令ID>@<日付>/<要素>.xml、文書の表なら文書の隣の 料金表.md.fragments/表3.tsv)、または file の出典そのものが読めないとき。check は通信をせず、文書の中身も見ないので、コピーが無ければ照合できません。

直し方。 rulec source fetch <file.rule> を実行してください。政府の法令データベース(e-Gov 法令検索)から引用箇所を取り、文書からは引いた表を取り出して、規則の隣に保存します。コピーは git に入れてください。

最小の再現:

rule t(t) v1

source 法 = law "000AC0000000001" asof 2026-04-01

inputs
  a(a) : bool

outputs
  x(x) : bool

table 表(t1)  @法 第2条
| a | -> x |
| - | true |

関係するコード: E037, E038

E040

error — 固定した元のファイルが、書いてあるハッシュと違います

いつ出るか。 apply の見出しに固定が無いとき、または書いてある固定と、いま隣にある元の規則が違うとき。固定は meaning:…(元の規則の行と宣言から、コメント、description、出典の引用を除いたもの)で、前に書いた sha256:…(ファイルのバイト列)もそのまま読みます。元の規則の行が改正されれば、それを準用するこの規則の答えも変わっています。寄与のファイルの to と after の signature:… が無いとき、合わないときも同じです。こちらは足す先の形(名前、入力と出力、開いた値と開いた出力、開いた列挙と塊、寄与が読む名前の宣言)で、元の行やコメントを直しても落ちず、形が変わると、何が変わったかを言います(リポジトリの履歴に固定したときの版があれば)。固定を書いておかないと、その変化を誰も承認しないまま通ってしまいます。

直し方。 rulec diff <古い版> <新しい版> でこの規則の答えが何件いくら動くかを見て、それでよければ、見出しを fix.text のとおり書き換えるか rulec source pin <file.rule> を実行して固定を書き直してください。寄与なら、寄与を新しい形で読み直してから、rulec source pin <寄与のファイル> で signature: を書き直してください。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=1 <=10

outputs
  y(y) : number  round down(1)

apply 呼(c) = "呼び先.rule"
  a = n
  x -> y

隣に置く 呼び先.rule:

rule 呼び先(callee) v1

inputs
  a(a) : number  range >=1 <=10

outputs
  x(x) : number  round down(1)

table 表(t)
policy unique
   | a   | -> x |
小 | <=5 | 1    |
大 | >5  | 2    |

寄与の signature: が足す先の形と違う:

contribution c(c) v1
to "base.rule" signature:0123456789abcdef

extend kind with z

隣に置く base.rule:

rule base(base) v1

enum kind(kind) = a(a) | b(b)  open

inputs
  k(k) : kind

outputs
  fee(fee) : number  round down(1)

table t(t)
policy first
| k | -> fee : number |
| a | 1               |
| - | 2               |

関係するコード: E037, E038, E044, E067

E041

error — 準用の読み替えが元の規則と合いません

いつ出るか。 元の規則の入力に、読み替えの無いものか、二度読み替えたものがあるとき、元の規則に無い入力や出力を書いたとき、元の規則の出力に付けた名前がこの規則に既にあるとき、一つの出力に名前を二度付けたとき、apply の下の行の形が読めないとき。読み替えは元の規則の入力を一つ残らず書くものなので、一つでも足りなければ、読み替えを書いていないのと同じです。

直し方。 元の規則の入力を一つずつ <元の規則の入力> = <この規則の値> で読み替え、出力は <元の規則の出力> -> <名前> で名前を付けてください。元の規則の入力と出力の名前は、診断の注に並びます。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=1 <=10

outputs
  y(y) : number  round down(1)

apply 呼(c) = "呼び先.rule" sha256:369102b8f803dc28
  b = n
  x -> y

隣に置く 呼び先.rule:

rule 呼び先(callee) v1

inputs
  a(a) : number  range >=1 <=10

outputs
  x(x) : number  round down(1)

table 表(t)
policy unique
   | a   | -> x |
小 | <=5 | 1    |
大 | >5  | 2    |

関係するコード: E040, E042, E043

E042

error — 読み替えの型が合いません

いつ出るか。 読み替えた値の型が、元の規則の入力の型と違うとき(単位・税区分・列挙と数)。列挙どうしでは、この規則の列挙の値にあたる元の規則の値が無いとき(同じ綴りの値はそのまま対応します)、with にどちらにも無い値を書いたとき、リテラルが元の規則の型の値でないときも同じです。with none -> <値> は、この規則の値に値の無いことがあり、元の規則の入力が値の無いことを受け付けないときだけ書けます。ほかで書くと、このエラーです。

直し方。 型を合わせてください。列挙は <入力> = <値> with <この規則の値> -> <元の規則の値>, … の形で、この規則の列挙の値を全部対応づけてください。法令の「『退職』とあるのは『任期の終了』と読み替える」を、そのまま書く形です。with none は、値の無いことがあるときだけ書いてください。元の規則が値の無いことを受け付けるなら、with から外して、そのまま渡してください。

最小の再現:

rule t(t) v1

enum 種別(kind) = 甲(a) | 乙(b) | 丙(c)

inputs
  k(k) : 種別

outputs
  y(y) : number  round down(1)

apply 呼(c) = "区分の呼び先.rule" sha256:2e6f2e04c21cdbb3
  a = k
  x -> y

隣に置く 区分の呼び先.rule:

rule 区分の呼び先(enum_callee) v1

enum 区分(kind) = 甲(a) | 乙(b)

inputs
  a(a) : 区分

outputs
  x(x) : number  round down(1)

table 表(t)
policy unique
| a  | -> x |
| 甲 | 1    |
| 乙 | 2    |

関係するコード: E041, E043

E043

error — 渡す値が元の規則の範囲か制約に収まりません

いつ出るか。 読み替えた値の取りうる範囲が、元の規則の入力の range からはみ出すとき(注に、はみ出す値の例が一つ出ます)、または元の規則の constraint がこの規則の宣言から導けないとき。順のある列挙の入力の range(range >=basic <=gold)では、渡す値が取りうる列挙の値を with で元の規則の値に読み替えて、範囲に入らない値があるときです。取りうる値は、入力ならその範囲(範囲が無ければ列挙の全部)、リテラルならその値、表の出力なら行が書く値(名前を書く行は、その名前が取りうる値)、二つの値の max と min なら、二つが取りうる値のうち答えになりうるもの(max は二つの一番前の値の後のほうより前にならず、min は二つの一番後の値の前のほうより後にならない)です。fold の答えなどほかの式で決まる値は、check がその値を求めないので列挙の全部とし、範囲の外の値があれば、渡す値の取りうる値が分からないと言います。元の規則の完全性はその範囲と制約の上でしか証明されていないので、外の値には定義がありません。値の無いことがある値(T? の入力や要素のフィールド、none を書く行のある表の出力、それらを指すだけの定義)を、? の無い元の規則の入力やフィールドに渡すときにも出ます。元の規則の表には、値が無いときの答えがありません。with none -> <値> で値の無いことを元の規則の値に読み替えていれば出ません。fix.text は付けません。元の規則に行を足すのは、別の承認の話だからです。

直し方。 この規則の入力の範囲を元の規則の範囲まで狭めるか、はみ出す部分をこの規則の節で定めてください。どちらにするかは業務の判断です。列挙なら、この規則の入力に同じ range を書くか(順のある列挙のとき)、範囲の中の値だけを書く表で値を決めて渡すか、with で範囲の中の値に読み替えてください。制約なら、同じ関係を constraint で宣言してください。値の無いことなら、with none -> <値> で元の規則の値に読み替えるか(列挙のとき)、値がいつもあるならこの規則の名前を ? の無い型にするか、none にも答える表をこの規則に書いて値を決めて渡してください。数や要素のフィールドで値の無いことがあるなら、元の規則が値の無いことを受け付ける変更になります。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=0 <=10

outputs
  y(y) : number  round down(1)

apply 呼(c) = "呼び先.rule" sha256:369102b8f803dc28
  a = n
  x -> y

隣に置く 呼び先.rule:

rule 呼び先(callee) v1

inputs
  a(a) : number  range >=1 <=10

outputs
  x(x) : number  round down(1)

table 表(t)
policy unique
   | a   | -> x |
小 | <=5 | 1    |
大 | >5  | 2    |

順のある列挙の入力の範囲:

rule t(t) v1

enum tier = basic < silver < gold < platinum

inputs
  k(k) : tier

outputs
  y(y) : number  round down(1)

apply call(c) = "tier_callee.rule" meaning:137f2373042d3154
  campaign = k
  x -> y

隣に置く tier_callee.rule:

rule tier_callee(tier_callee) v1

enum tier = basic < silver < gold < platinum

inputs
  campaign(campaign) : tier  range >=basic <=gold

outputs
  x(x) : number  round down(1)

table t(t)
policy unique
| campaign | -> x |
| basic    | 1    |
| >=silver | 2    |

値の無いことがある値:

rule t(t) v1

enum tier = basic < silver < gold < platinum

inputs
  m(m) : tier?

outputs
  y(y) : number  round down(1)

apply a(a) = "absent_callee.rule" meaning:38fa5f7ac6342966
  t = m
  x -> y

隣に置く absent_callee.rule:

rule absent_callee(absent_callee) v1

enum tier = basic < silver < gold < platinum

inputs
  t(t) : tier

outputs
  x(x) : number  round down(1)

table t1(t1)
policy unique
| t        | -> x |
| basic    | 1    |
| >=silver | 2    |

関係するコード: E041, E042, E101

E044

error — その規則は準用できません

いつ出るか。 元の規則が読めないとき、元の規則が check を通らないとき(注に、出たコードが並びます)、準用が輪になっているとき(ある規則を準用する規則を、その規則が、直接かほかの規則を通して準用している。輪の全部のファイルを挙げます)。通らない規則を準用しても、通らない規則になるだけで、自分を通して自分を読む規則は答えが決まりません。準用している規則の準用、並びをたどる規則の準用、元の規則の列挙を出す表の準用はできます。元の規則の出力が、値の無いことのある数(money[円]? など)のときにも出ます。準用した出力は、元の規則の丸めを掛けた定義になり、値の無いことのある値には丸めを掛けられないからです。値の無いことのある列挙・真偽・日付・文字列の出力は準用でき、値の無いことをそのまま渡します。

直し方。 先に元の規則を直してください。輪なら、どこか一つの apply を外してください。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=1 <=10

outputs
  y(y) : number  round down(1)

apply 呼(c) = "壊れた呼び先.rule" sha256:c4f9eba5b2949205
  a = n
  x -> y

隣に置く 壊れた呼び先.rule:

rule 壊れた呼び先(broken) v1

inputs
  a(a) : number  range >=1 <=10

outputs
  x(x) : number  round down(1)

table 表(t)
policy unique
| a   | -> x |
| <=5 | 1    |

準用の輪:

rule t(t) v1

inputs
  n(n) : number  range >=1 <=10

outputs
  y(y) : number  round down(1)

apply o(o) = "other.rule"
  a = n
  x -> y

隣に置く other.rule:

rule other(other) v1

inputs
  a(a) : number  range >=1 <=10

outputs
  x(x) : number  round down(1)

apply back(back) = "explain.rule"
  n = a
  y -> x

関係するコード: E040, E041

E045

error — 出力を共有する表に、出力の列が二つ以上あります

いつ出るか。 ある出力を二つ以上の表が定めていて(または overrides で結ばれていて)、そのうちの表に出力の列が二つ以上あるとき。行が二つの出力の定義を束ねていると、一方だけが上書きされたときにもう一方の値の出どころが決まらず、生成コードでは同じ行の条件を二度書くことになります。

直し方。 二つ目の出力を、別の表に分けてください。

最小の再現:

rule t(t) v1

inputs
  a(a) : bool

outputs
  x(x) : bool
  y(y) : bool

table 甲(ko)
| a | -> x | y    |
| - | true | true |

table 乙(otsu)
overrides 甲
| a    | -> x  |
| true | false |

関係するコード: E036, E105

E046

error — clause の形が読めません

いつ出るか。 clause の見出しに名前か -> か出力が無いとき、when か then の行が無いか二度あるとき、when の条件が <列> <セル> and … の形でないとき(列が無い、同じ列が二度ある、条件が無い)。節は一行の表なので、条件と値が一つずつ要ります。

直し方。 clause <名前>(<別名>) -> <出力> の下に when <列> <セル> and …(条件が無ければ when always)と then <値> を一行ずつ書いてください。優先する相手があれば overrides <相手> を足してください。

最小の再現:

rule t(t) v1

inputs
  a(a) : bool

outputs
  x(x) : bool

clause 例外(exception) -> x
  then true

関係するコード: E008, E035, E045

E047

error — 宣言の後ろに余分な語があります

いつ出るか。 宣言の行に、その行が読まない語が残っているとき。行ごとに読む語は決まっていて、入力の行は range・contract_only・random、要素のフィールドの行は range と contract_only、出力の行は range と round、derive の行と count・sum・max・min の行は range だけです。shape の行と、入力の from のパスの後ろ(where・empty のほか)には何も置けません。rulec のパーサーは行から欲しい語を探して残りを読み飛ばすので、こうした語はいままで黙って捨てられていました。範囲の後ろに書いた税区分(range >=0円 <=10000円 incl_tax)も、単位が単位として読めずに余った分も、derive の round も、from の後ろの range も、どれも通っていました。範囲は完全性の検査が調べる値の全体で、生成コードの入口のガードでもあるので、境界が一つ落ちると、片側が欠けた範囲のまま「完全」と答えることになります。

直し方。 その語を消すか、宣言の一部として正しい形に直してください。税区分や刻みは型の括弧の中に(money[円, incl_tax]、rate[step 0.1%])、範囲は range >=<値> <=<値>、丸めは round <向き>(<刻み>) の形で書いてください。入力の範囲と印は from の前に書きます。導出の値を丸めるなら、式の中で down(<式>, 1円) のように丸めます。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円, incl_tax]  range >=0円 <=10000円 incl_tax

outputs
  x(x) : bool

table 表(t1)
policy unique
| a | -> x |
| - | true |

関係するコード: E011, E103, E104

E049

error — 桁区切りのカンマは書けません

いつ出るか。 数を 1,000 や 1,949,000円 のように、1〜3 桁のあとに , と 3 桁の組を続けて書いたとき。, はセルの中で集合の要素を区切る記号なので、そのままでは二つ以上の値に読まれます。いままでは黙ってそう読んでいて、数の列の <=1,000 は <=1 として検査を通り、金額の列では 1 に単位が無いという的外れな E103 で止まっていました。文書の数字をそのまま転記すると、このエラーが出ます。

直し方。 カンマを外して 1000 と書いてください。桁を区切りたいときは 1_000 と書けます。fix.text には、書き直したリテラルが入っています。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円]  range >=0円 <=5000円

outputs
  x(x) : bool

table 表(t1)
policy unique
| a         | -> x  |
| <=1,000円 | true  |
| >1,000円  | false |

関係するコード: E014, E103

E048

error — この型には足し算も掛け算もありません

いつ出るか。 順序はあるが演算の無い型を、+ - × ÷ のどれかに使ったとき。date、temperature[℃]・temperature[℉]、sound[dB] の三つがそれです。℃ は 0 が「無い」を意味しない目盛りなので 気温 × 2 に意味が無く、dB は対数なので二つ足しても音が二つ分にはならず、日付は暦日なので引き算の結果を入れる型がありません。どれも規則の中では閾値としてしか現れないので、比較と range だけを残して演算を落としています。

直し方。 閾値として比べるか、range に書いてください。差や倍率そのものが業務ルールなら、計算した結果を入力として受け取るか、表で引いてください。二つの日付のあいだの日数は、呼び出し側で数えて number か duration として渡してください。

最小の再現:

rule t(t) v1

inputs
  甲(a) : temperature[℃]  range >=0℃ <=40℃
  乙(b) : temperature[℃]  range >=0℃ <=40℃

outputs
  x(x) : bool

derive 差(gap) : temperature[℃] = 甲 - 乙  range >=-40℃ <=40℃

table 表(t1)
policy unique
| 差 | -> x |
| -  | true |

関係するコード: E103, E112, E115

E050

error — machine の節の形が違います

いつ出るか。 machine の見出しに名前か over <表> が無いとき、carry か initial の行が無いとき、状態の initial の行が二行あるとき、machine の中に carry・held・initial・final・never・once・always のほかの行があるとき、規則に machine が二つあるとき。

直し方。 形は machine <名前>(<ascii>) over <表> と、その下の carry <入力> -> <出力> と initial <状態>(どちらも必須)、final <状態>, …、never <状態>, … after <状態>, …、once <出力> <セル>(どれも任意)です。ほかの値も一緒に持ち越すなら、carry の行と initial <入力> <値> の行を足してください(E072)。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |

machine k(k) over m
  carry   st -> nx

関係するコード: E051, E052, E053

E051

error — carry か over が宣言と噛み合いません

いつ出るか。 carry の左が入力でないとき、右が出力でないとき、最初の carry の二つが同じ列挙でないとき、二行目からの carry の二つが同じ型でないとき、over の表が無いとき、その表が持ち越す出力を決めていないとき。状態が有限個の値の列挙なので、呼び出しの並びについての主張を確かめられます。

直し方。 状態の入力と状態の出力を同じ列挙で宣言して carry <入力> -> <出力> と書き、over には、持ち越す出力を出力の列に持つ表の名前を書いてください。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |

machine k(k) over m
  carry   zz -> nx
  initial a

関係するコード: E050, E052

E052

error — ステートマシンに書いた状態が噛み合いません

いつ出るか。 initial・final・never の行に、持ち越す状態の列挙に無い値があるとき。または never の両側に同じ状態があるとき。その主張は、その状態に留まる最初の呼び出しで破れるので、意味のある主張になりません。

直し方。 列挙の値の綴りで書いてください。never の両側には、別の状態を書いてください。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |

machine k(k) over m
  carry   st -> nx
  initial a
  final   d

関係するコード: E050, E126

E053

error — once の行が宣言と噛み合いません

いつ出るか。 once の出力が宣言されていないとき、持ち越す状態か持ち越すほかの値の出力であるとき、セルが - のとき。持ち越す値は、それを保つ呼び出しのたびに同じ値を返すので、once で数えると、保つだけで主張が破れます。セルは出力の型に照らして、表のセルと同じ検査を受けます(E103 など)。

直し方。 once <出力> <セル> の出力には、持ち越す状態ではない出力を書いてください(once 返金額 >0円)。状態について言うなら never … after … を使ってください。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |

machine k(k) over m
  carry   st -> nx
  initial a
  once    nx c

関係するコード: E127, E103

E054

error — 並びを畳む規則は、ステートマシンの一歩になれません

いつ出るか。 fold のある規則に machine を書いたとき。答えが並び全体で決まるので、入力を決まった数の列の区画に分けられず、一回の呼び出しの行き先を数え上げられません。diff が同じ規則を受け付けないのと同じ理由です。

直し方。 並びは呼び出す側で読み、見つけたもの(件数や合計)を入力として渡してください。count と sum で数える規則は、ステートマシンの一歩になれます。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)
enum s(s) = p(p) | q(q)

inputs
  st(st) : s

elements xs(xs)
  w(w) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)
  nx(nx) : s

table j(j)
policy unique
| w     | -> d(d) : v |
| <=5円 | a           |
| >5円  | b           |

table m(m)
policy unique
| st | -> nx(nx) : s |
| p  | q             |
| q  | q             |

fold d over xs
  a -> next
  b -> take_first w
  empty -> 0円
  exhausted -> held

machine k(k) over m
  carry   st -> nx
  initial p

関係するコード: E050, E028

E055

error — scenario の形が違います

いつ出るか。 machine の無い規則に scenario を書いたとき、名前が無いか二つが同じ名前のとき、行が無いとき、見出しに同じ列が二つあるとき、持ち越す入力(状態とほかの持ち越す値)の列があるとき、ほかの入力の列が足りないとき。一行目の呼び出しは initial の値から、二行目からは一つ前の呼び出しが返した値から始まるので、持ち越す入力には列がありません。

直し方。 scenario <名前>(<ascii>) の直下に表を書いてください。見出しは、持ち越す入力のほかのすべての入力、->、すべての出力です。持ち越す状態が無いなら、一行ずつの examples で書けます。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool

outputs
  r(r) : bool

table j(j)
policy unique
| x     | -> r(r) : bool |
| true  | false          |
| false | true           |

scenario s(s)
| x    | -> r  |
| true | false |

関係するコード: E107, E111, E050

E056

error — held の行が宣言と噛み合いません

いつ出るか。 held に、入力でない名前か、持ち越す入力(状態とほかの持ち越す値)か、同じ名前を二度書いたとき。held は、一つの案件が最初の呼び出しから最後の呼び出しまで同じ値で渡す入力を言います(注文の金額、申し込んだ人の区分)。書いておくと、検査は、そういう入力を呼び出しごとに変えた並びを、主張が破れる例として挙げなくなります。

直し方。 入力の名前を書いてください。持ち越す入力は呼び出しのたびに一つ前の答えで入れ替わるので、held にはなりません。

最小の再現:

rule t(t) v1

enum s(s) = p(p) | q(q)

inputs
  st(st) : s
  x(x)   : bool

outputs
  nx(nx) : s
  r(r)   : bool

table m(m)
policy unique
| st | x     | -> nx(nx) : s | r(r) : bool |
| p  | true  | q             | true        |
| p  | false | p             | false       |
| q  | -     | q             | false       |

machine k(k) over m
  carry   st -> nx
  held    r
  initial p
  final   q

関係するコード: E050, E051, W126

E057

error — 宣言に型がありません

いつ出るか。 inputs・outputs・elements の行、または define・derive の行に、名前だけがあって型が無いとき。この行は、いままで黙って捨てられていました。規則は書いた人の思うより入力が一つ少ないまま検査を通り、例やベクタがその名前を渡すと、知らない名前としてエラーになっていました。

直し方。 <名前>(<別名>) : <型> の形で型を書いてください(: money[円, incl_tax]、: 都道府県、: bool)。数の型なら range も要ります。

最小の再現:

rule t(t) v1

inputs
  a(a) : bool
  b(b)

outputs
  r(r) : bool

table j(j)
policy unique
| a     | -> r(r) : bool |
| true  | false          |
| false | true           |

関係するコード: E011, E047, E012

E058

error — 宣言の行を読めません

いつ出るか。 define・derive・result・enum・group・table のような宣言の語で始まる行を、その宣言として読めないとき。名前が無い、= の前に余分な語がある、などです。こういう行は、いままで何も言われずに捨てられていました。derive の行は捨てられもせず、検査が終わらなくなっていました。

直し方。 診断の注記にある形に書き直してください(define 大口(bulk) : bool = 注文金額 >= 3万円)。どの宣言の形も docs/reference.md にあります。

最小の再現:

rule t(t) v1

inputs
  a(a) : bool

outputs
  r(r) : bool

derive

table j(j)
policy unique
| a     | -> r(r) : bool |
| true  | false          |
| false | true           |

関係するコード: E006, E057, E059, E005

E059

error — 式を読めません

いつ出るか。 = などの右に書いた式を、最後の語まで読めないとき。演算子の右が空(x +)、( が閉じていない、値が二つ演算子なしで並んでいる(金額 税)、符号が数にくっついている(金額 -100円)、などです。いままでは読めたところまでを式にして、残りを黙って捨てていました。金額 税 は 金額 と読まれて検査を通り、x + は宣言ごと消えていました。

直し方。 抜けている演算子や括弧を補ってください。引くときは 金額 - 100円 のように、記号の後ろを空けてください。記号と数字がくっついていると、負の数として読まれます。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円]  range >=0円 <=100円
  b(b) : money[円]  range >=0円 <=100円

outputs
  o(o) : money[円]  round down(1円)

define s(s) : money[円] = a b

result o = s

関係するコード: E058, E118, E115

E060

error — 刻みが正の値ではありません

いつ出るか。 型の刻み(rate[step 0%])、出力の丸めの刻み(round up(0円))、式の中の丸めの刻み(down(x, 0円))が 0 か負の数のとき。刻み 0 の丸めは検査を通り、生成コードの中で 0 で割って、実行時に止まっていました(Python なら ZeroDivisionError)。刻み 0 の型は、黙って刻み 1 として読まれていました。

直し方。 0 より大きい刻みを書いてください(round up(1円)、rate[step 0.1%])。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円]  range >=0円 <=100円

outputs
  o(o) : money[円]  round up(0円)

result o = a

関係するコード: E104, E114, E106

E061

error — 範囲が空です

いつ出るか。 range に入る値が一つも無いとき。下の端が上の端を超えている(range >=10円 <=0円)か、両端が同じ値で片方が > か < のときです。こういう範囲は、いままで何も言われずに通っていました。完全性の証明は何も無い集合について「漏れなし」と答え、生成コードの入口はどの呼び出しも受け付けていませんでした。

直し方。 書き間違えた端を直してください(range >=0円 <=10円)。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円]  range >=10円 <=0円

outputs
  o(o) : money[円]  round down(1円)

result o = a

関係するコード: E112, E103, E060

E062

error — ありえない日付です

いつ出るか。 日付の形(2026-04-01)をしているのに、月が 1〜12 の外か、日がその月の日数を超えるとき(2026-02-30、2026-01-99)。こういう日付は、いままで形だけを見て読まれていました。検査器は日の通し番号として数え(1 月 99 日は 4 月 9 日)、生成した Python は実行時に止まり、JavaScript の Date は黙って次の月へ繰り越すので、言語ごとに答えが割れていました。

直し方。 ある日付に直してください。月末を言いたいなら、その月の最後の日を書いてください(2026-02-28)。

最小の再現:

rule t(t) v1

inputs
  d(d) : date  range >=2026-01-01 <=2026-12-31

outputs
  r(r) : bool

table j(j)
policy unique
| d            | -> r(r) : bool |
| <=2026-02-30 | true           |
| >2026-02-30  | false          |

関係するコード: E002, E103

E063

error — セルを読めません

いつ出るか。 表・例・並びのセルに、セルとして読めない語があるとき。比較の後ろの余分な語(<=0円 + false)、値の後ろの語(false 0円)、値でない語(+)、見出しの列に名前が無い、などです。いままでは読めたところまでをセルにして、残りを捨てていました。読めないセルは丸ごと捨てていたので、後ろのセルが一つずつ左の列へずれていました。

直し方。 セルに書けるのは、値一つ、-、none、比較、カンマで区切った値の集合、not: と集合、starts_with と文字列です。一つの列に二つの条件を書くなら、比較を並べてください(>=1 <10)。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円]  range >=0円 <=1000円

outputs
  r(r) : bool

table j(j)
policy unique
| a             | -> r(r) : bool |
| <=100円 + 1円 | true           |
| >100円        | false          |

関係するコード: E008, E010, E014, E064

E064

error — 行が見出しと合いません

いつ出るか。 表・並び・手順の例・例の行のセルの数が、見出しの列の数と違うとき。または、最後の | の後ろに語があるとき(行を閉じる | の書き忘れ)。いままでは、閉じていない行の最後のセルが黙って捨てられ、セルの数の合わない行もそのまま読まれていました。参照評価器と生成コードがその行を別々に読み、答えが割れていました。例の表では、見出しに出力の列が無いか行の期待値が足りなければ E111 が、並びの列が無ければ E025 が先に出て、どの列かを言います。

直し方。 一つの列に一つのセルを書き、行を | で閉じてください。どの値でもよい列には - を書いてください。

最小の再現:

rule t(t) v1

inputs
  a(a) : bool

outputs
  r(r) : bool

table j(j)
policy unique
| a     | -> r(r) : bool |
| true  |
| false | true           |

関係するコード: E063, E008, E111

E065

error — range from koyomi の形か置き場所が違います

いつ出るか。 range from の後ろが koyomi "<ファイル>" date <日付の名前> の形になっていないとき、日付でない入力に書いたとき、出力・導出・並びの要素に書いたとき。koyomi の日付がとりうる日は、呼び出し側が渡す日付の範囲にだけなります。

直し方。 日付の入力に range from koyomi "<ファイル>" date <日付の名前> と書いてください。ファイルは、規則のディレクトリからの相対パスです。

最小の再現:

rule t(t) v1

inputs
  d(d) : date  range from koyomi "terms.cal"

outputs
  r(r) : bool

table j(j)
policy unique
| d | -> r(r) : bool |
| - | true           |

関係するコード: E129, E130

E066

error — enums のファイルの形と、そこから読む import enum の形が違います

いつ出るか。 見出しが enums のファイルに、description・import・enum・group・prerequisites 以外の行(表、入力、出力、定義、import enum など)を書いたとき。import enum <列挙> from "<ファイル>" が読むファイルが enums のファイルでないとき、または check を通らないとき。enums のファイルは規則どうしが分け合う列挙を置く場所で、何も決めず、規則の関数も生成しません。

直し方。 表や入力は、その列挙を import enum … from で読む規則の側に書いてください。読む先のファイルは enums <名前> v<版> で始め、check を通るように直してください。

最小の再現:

enums 区分(kinds) v1

enum 区分(kind) = 冷蔵(chilled) | 常温(ambient)

table 送料(fee)
policy unique
| 区分 | -> 送料 : number |
| -    | 1                |

関係するコード: E013, E034

E069

error — 順序つきの列挙と比べるセル、または表示名の形が違います

いつ出るか。 値を | で区切った(順序の無い)列挙の列に <v や >=v のような比べるセルを書いたとき、そういう列挙の二つの値を < などで比べたとき、max・min に渡したとき、入力に範囲を書いたとき。一つの列挙の値の区切りに < と | を混ぜたとき。範囲に入る値が一つも無いとき、要素のフィールドの列挙に範囲を書いたとき、列挙の列の max・min の行に範囲を書いたとき。値の表示名が空か制御文字を含むとき、同じ列挙の二つの値の表示名が同じとき。値を < で区切った列挙は、書いた順が値の順序になり、比べるセルは、比べた値より前(後)の値の集合として読まれます。

直し方。 宣言の順が意味を持つなら、値を < で区切ってください(enum 段階 = 一般 < シルバー < ゴールド)。持たないなら、値か集合で書いてください。区切りは < か | のどちらかにそろえ、表示名は空でない、ほかの値と違う名前にしてください。

最小の再現:

rule 会員送料(member_fee) v1

enum 段階(tier) = 一般(basic) | シルバー(silver) | ゴールド(gold)

inputs
  会員(member) : 段階

outputs
  送料(fee) : money[円]  round down(1円)

table 送料表(fees)
policy unique
| 会員       | -> 送料 |
| >=シルバー | 0円     |
| 一般       | 500円   |

関係するコード: E012, E103

E071

error — 前提のつながりの形が違います

いつ出るか。 prerequisites の塊で、over の後が列挙でないとき、列挙の値でない名前を書いたとき、一つの値を二か所に書いたとき(start と自分の行、二つの行、一つの行の中で二度)、start の行にも自分の行にも無い値があるとき、start の行が無いとき、行の形が読めないとき。ordered by が名前を挙げた表が無いとき、塊より下にあるとき、その列挙の列一つを条件にし、値ごとに順序のある列挙か number の値を一つ書く表でないとき、enums のファイルに ordered by を書いたとき。どの値も、何も要らない(start)か、要るものを書いた自分の行を持つか、手に入らない値(requires nothing "<理由>")なので、値を足して前提を書き忘れると、ここで止まります。

直し方。 値ごとに一か所だけ書いてください。何も要らない値は start に、要るものがある値は <値> requires <前提>, … の行に、手に入らない値は <値> requires nothing "<理由>" に書きます。ordered by の表は塊より上に置き、列挙の列一つを条件にして、順序のある列挙か number の値を行ごとにそのまま書いてください。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b) | c(c)

inputs
  x(x) : k

outputs
  r(r) : bool

table j(j)
policy unique
| x | -> r(r) : bool |
| - | true           |

prerequisites p(p) over k
  start a
  b     requires a

関係するコード: E136, E137, E138

E072

error — 持ち越す値の書き方が違います

いつ出るか。 二行目からの carry が、範囲に両端の無い数か、日付・文字列・省略できる値を持ち越すとき、同じ値を二度持ち越すとき、持ち越す値に initial <入力> <値> の行が無いか二行あるとき、その値が型や範囲に合わないとき、initial <入力> <値> が状態や持ち越さない入力を書いたとき、always の行の形が違うとき、always が持ち越す値でない名前か状態そのものを書いたとき。持ち越す数に範囲の両端があるので、案件がとりうる値は有限個になり、呼び出しの並びについての主張を確かめられます。

直し方。 持ち越す数には range >=0 <=7 のように両端のある範囲を書き、どの持ち越す値にも initial <入力> <値> で始まりの値を書いてください。always には、二行目からの carry の左の入力とセルを and でつないで書き、成り立つ状態を when の後に書きます(always 残り日数 >=1 <=7 when 猶予中)。状態について言うことは never と final で書きます。

最小の再現:

rule t(t) v1

enum s(s) = run(run) | done(done)

inputs
  st(st) : s
  n(n)   : number  range >=0 <=3

outputs
  nx(nx) : s
  nn(nn) : number  round down(1)

define more(more) : number = n + 1

table m(m)
policy first
| st  | n  | -> nx(nx) : s | nn(nn) : number |
| run | <3 | run           | more            |
| -   | -  | done          | n               |

machine k(k) over m
  carry   st -> nx
  carry   n -> nn
  initial run

関係するコード: E050, E051, E135

E075

error — 列挙の値でも、名前でもある語です

いつ出るか。 表の出力のセルか fold の答えに書いた語が、その列(答え)の列挙の値で、同じ列挙を型にもつ入力・出力・要素のフィールド・導出・定義・表の出力の名前でもあるとき。値としても名前としても読めるので、どちらの意味か決まりません。名前の型が別の型なら、語はその列の値として読みます(数の出力 gold があっても、列挙の列に書いた gold は列挙の値です)。例と手順の例の期待値のセルは値しか書けないので、いつも値として読みます。

直し方。 列挙の値か名前のどちらかを、別の名前に変えてください。

最小の再現:

rule 段階の引き継ぎ(carry_stage) v1

enum 段階(stage) = 新規(fresh) | 前回(previous) | 終了(done)

inputs
  前回(previous) : 段階
  閉じる(close) : bool

outputs
  次の段階(next_stage) : 段階

table 決め方(decide)
policy unique
| 閉じる | -> 次の段階 : 段階 |
| true   | 終了               |
| false  | 前回               |

関係するコード: E103, E012

E101

error — 完全性の欠落: どの行にも当てはまらない入力があります

いつ出るか。 行を全部合わせても、宣言した範囲の入力を覆いきれていないとき。完全性は宣言で外せず、常に必須です。当てはまらない入力の具体例が必ず付きます。列が規則の計算する値(導出、define、上の表の出力)なら、例はその値で書かれ、その値を作る入力も、参照の評価器で確かめられたときは付きます。その入力は、導出が足し算・引き算・定数倍だけなら式から求め、ほかの列(min や丸めを使う導出、define、上の表の出力)では、入力の組み合わせが 16,384 通りまでなら全部を確かめて探します。導出の値は、セルを書く単位より細かい刻みをとることがあり(amount * 10% は 0.1 刻み)、その刻みで調べます。どの入力も届かない値には、行を求めません。導出と、数を計算する define の列では、その列が実際に取りうる値の外に、行を求めません(取りうる値は、式を入力の範囲と上流の表が出す値で計算したもので、導出では constraint も読みます)。上流の表が出す値の列では、上流の表がその値を出す行の条件と合わせて、ほかの列が取りえない値に、行を求めません。一つの比べ方でできた真偽の define の列では、入力の範囲でいつも同じ値をとるなら、もう一方の値に行を求めません(作成日 <= 2027-03-31 で、作成日がその日までしかとらないなら、false に行を求めません)。optional の入力(T?)では、値が無いことも入力の一つで、その行を求めます。数・日付・真偽の optional の入力では、値があるときの宣言した範囲の全部にも行を求めます。上の表が決める optional の列では、上の表が none を書く行か、値の無いことのある名前を渡す行があれば、値の無いことにも行を求めます。

直し方。 それを起こす入力に当てはまる行を足してください。列挙の値が増えたのが原因なら、その値の行か、全部を受ける - の行を足してください。値に専用の行が要らないなら、列挙の宣言に default を付けてください。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b) | c(c)

inputs
  x(x) : k

outputs
  r(r) : bool

table j(j)
policy unique
| x | -> r(r) : bool |
| a | true           |
| b | false          |

関係するコード: E102, E105, W111

E102

error — どの入力にも当てはまらない行があります

いつ出るか。 どの入力もその行に当てはまらないとき。形は三つあり、診断の文が原因を書き分けます。一つ目は、先行する行(overrides で優先する行も含む)にすべて覆われている行です。二つ目は、上流の表が決して出さない値を指している行です。三つ目は、導出か、数を計算する define の列に、その列が実際に取りうる値の外だけを求めている行です(取りうる値の中の部分を、先行する行が先に取っている場合も含みます)。上流の表が出す値と導出の両方を列に持つ表で、上流の表がその値を出すときには導出が取りえない値を求めている行と、一つの比べ方でできた真偽の define が、入力の範囲ではとらない値を求めている行も、この形です。取りうる値は、式を入力の範囲と上流の表が出す値で計算したもので(導出では constraint も読みます)、導出に書いた range ではありません。

直し方。 その行が新しい仕様なら、覆っている行より上へ移してください。不要なら削除してください。上流が出さない値を指しているなら、上流の表にその値を出す行を足すか、この行を消してください。導出や define が取りえない値を求めているなら、条件をその取りうる値の中に書き直すか、この行を削除してください。導出の range を広げても、取りうる値は変わりません。真偽の define がとらない値を求めているなら、この行の条件を、その define がいつもとる値に書き直すか、この行を削除してください。

最小の再現:

rule t(t) v1

inputs
  w(w) : mass[g]  range >=0g <=10kg

outputs
  r(r) : bool

table j(j)
policy first
| w       | -> r(r) : bool |
| -       | true           |
| <=1000g | false          |

三つ目の形(導出の取りうる値の外にある行)の最小の再現:

rule t(t) v1

inputs
  額(a)   : money[円, incl_tax]  range >=1円 <=100円
  上限(l) : money[円, incl_tax]  range >=0円 <=100円

outputs
  r(r) : bool

derive 超過(x) : money[円, incl_tax] = 額 - 上限  range >=-1000円 <=1000円

table j(j)
policy unique
| 超過         | -> r(r) : bool |
| <=0円        | false          |
| >0円 <=100円 | true           |
| >100円       | true           |

三つ目の形(define の取りうる値の外にある行)の最小の再現:

rule t(t) v1

inputs
  点(p) : number  range >=0 <=200

outputs
  r(r) : bool

define 割合(s) : rate = 点 / 200

table j(j)
policy unique
| 割合         | -> r(r) : bool |
| <50%         | false          |
| >=50% <=100% | true           |
| >100%        | true           |

三つ目の形(上流の表がその値を出すときには、導出が取りえない値を求める行)の最小の再現:

rule t(t) v1

enum 大きさ(z) = 少額(small) | 多額(large)

inputs
  額(a)   : money[円, incl_tax]  range >=1円 <=100円
  上限(l) : money[円, incl_tax]  range >=0円 <=100円

outputs
  r(r) : bool

derive 超過(x) : money[円, incl_tax] = 額 - 上限  range >=-100円 <=100円

table k(k)
policy unique
| 額     | -> 区分(c) : 大きさ |
| <=50円 | 少額                |
| >50円  | 多額                |

table j(j)
policy unique
| 区分 | 超過   | -> r(r) : bool |
| 少額 | <=50円 | false          |
| 少額 | >50円  | true           |
| 多額 | -      | true           |

三つ目の形(真偽の define が入力の範囲ではとらない値を求める行)の最小の再現:

rule t(t) v1

inputs
  作成日(d) : date  range >=2024-04-01 <=2026-12-31

outputs
  r(r) : bool

define 期間内(p) : bool = 作成日 <= 2027-03-31

table j(j)
policy unique
| 期間内 | -> r(r) : bool |
| true   | true           |
| false  | false          |

関係するコード: E101, W105, W110, E112

E103

error — 単位の混同: 型の違う値を混ぜています

いつ出るか。 式やセルで、単位・通貨・税区分の違う値を足したり比べたりしているとき。money[円, incl_tax] と money[円, excl_tax] も別物です。型の刻みが読めないとき(rate[step 1g])と、率の入力に刻みが無いときにも出ます。どちらも、実行時に受け渡す整数が何を単位に数えているのかが決まりません。お金の型の税区分に incl_tax と excl_tax のほかの語を書いたとき(money[円, foo])にも出ます。列の列挙に無い値やグループをセルに書いたときにも出ます。出力のセルに書いたときと、グループが二つの列挙の値を混ぜているときも同じです。式の中の数が、書いた単位の値にならないときにも出ます。単位の無い小数(amount * 0.4。単位の無い数は整数の number です)と、金額や量の端数(0.5円)です。表・節・例の見出しに、その名前がもう持っている型と違う型を書いたときにも出ます。出力の名前なら出力の宣言の型、上の表や節が決める名前ならその型です。optional でない列(規則の出力、表が決める列、例の期待値)に none を書いたときと、値の無いことのある名前を書いたときにも出ます。値の無いことのある名前を式の中で使ったとき(quoted * 2)にも出ます。そういう値は、表のセルで確かめるか、optional の列にそのまま渡すことしかできません。

直し方。 混ぜている片方を表に移してください。「重量に応じた加算料金」なら table 重量加算 | 重量 | -> 加算額 : money[円, incl_tax] | の形です。税の変換も、式ではなく表として書いてください。刻みなら、型と同じ単位で書いてください(率の入力は rate[step 1%] や rate[step 0.1%])。税区分は、税込なら incl_tax、税抜なら excl_tax と書いてください。率は % で書いてください(0.4 は 40%。fix.text がこの形を出します)。見出しの型が名前の型と違うなら、どちらが正しいかを決めて直してください。見出しの型は消してもかまいません。消せば、名前の型で読みます。値の無いことを答える列なら、その型を T? にしてください(規則の出力なら outputs の宣言、表が決める列なら見出しの型です)。そうでなければ、none の代わりに値を書いてください。

最小の再現:

rule t(t) v1

inputs
  w(w) : mass[g]  range >=0g <=10kg
  p(p) : money[円, incl_tax]  range >=0円 <=1万円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| w | -> r(r) : money[円, incl_tax] |
| - | 100円                         |

result r = p + w

出力と違う型を書いた、表の見出し:

rule t(t) v1

inputs
  w(w) : mass[g]  range >=0g <=10kg

outputs
  r(r) : money[円, excl_tax]  round down(1円)

table j(j)
policy unique
| w | -> r(r) : money[円, incl_tax] |
| - | 100円                         |

optional でない出力に書いた none:

rule t(t) v1

inputs
  x(x) : bool

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| x     | -> r(r) : money[円, incl_tax] |
| true  | 100円                         |
| false | none                          |

関係するコード: E108, E112

E104

error — 数値の出力に丸めの宣言がありません

いつ出るか。 数量・金額・率の出力に round が無いとき。optional の出力(money[円]? など)も同じです。端数がどう決まるかを宣言しないと、生成コードが黙って決めてしまいます。式が端数を生む場合は、丸め方で答えがどれだけ動くかが、診断に数字で出ます。

直し方。 出力の宣言に丸めを書いてください。例: round up(10円)。向きは五種(up down half_up half_down half_even)で、負の側まで固定されています。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool

outputs
  r(r) : money[円, incl_tax]

table j(j)
policy unique
| x     | -> r(r) : money[円, incl_tax] |
| true  | 100円                         |
| false | 200円                         |

関係するコード: E106, E103

E105

error — 行の重なり: 同じ入力が二つ以上の行に当てはまります

いつ出るか。 policy unique の表で、両方に当てはまる入力を実際に構成できたとき。構成できなかった重なりは W114 に落ちます。上の表が同時には出さない値の組でしか重ならない対と、どの入力も届かない点(define の取りうる値の外、真偽の define がとらない値、上の表がその値を出す行の条件と導出の組み合わせ)でしか重ならない対は、重なりとして報告しません(完全性の検査と E102 が、そういう点に行を求めず、そこだけを求める行をどの入力にも当てはまらない行とするのと同じ読み方です)。optional の列では、比べ方、リテラル、値の集合は値があるときだけに当てはまり、- と not: は値が無いことにも当てはまります。だから none の行は、- の行とも not: 5 の行とも、値の無い入力で重なります。

直し方。 出力が違うなら、どちらが正しいか決めて行を直してください。順序に意味を持たせたいなら policy first を宣言してください。出力まで同じなら、片方を削ってください。同じ出力を定める二つの表や節が重なるときは、勝つほうに overrides <相手> を書いてください。表なら policy の次の行に、節なら節の下の行に書きます。二つが同じ答えを返していても、重なりは許しません。今日同じ答えでも、明日の編集で片方だけが変わるからです。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b)

inputs
  x(x) : k
  y(y) : bool

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| x | y     | -> r(r) : money[円, incl_tax] |
| a | -     | 100円                         |
| - | true  | 200円                         |
| b | false | 300円                         |

関係するコード: W105, W114, E102

E106

error — 出力のリテラルが丸めの刻みに載っていません

いつ出るか。 出力セルに書かれたリテラルが、宣言した丸めの刻みの倍数でないとき。round up(10円) の表に 1451円 があるような、桁の打ち間違いをここで落とします。

直し方。 リテラルを刻みに載せてください(1451円 は 1450円 か 1460円)。その値が本当に正しいなら、丸めの刻みのほうを直してください。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool

outputs
  r(r) : money[円, incl_tax]  round up(10円)

table j(j)
policy unique
| x     | -> r(r) : money[円, incl_tax] |
| true  | 1451円                        |
| false | 1000円                        |

関係するコード: E104

E107

error — 例の期待値と一致しません

いつ出るか。 examples の行を参照評価器で走らせた結果が、書かれた期待値と違うとき。どの表のどの行に当てはまったかが付きます。examples は実行される仕様です。optional の出力の期待値の none は、値の無いことを期待します。

直し方。 表が正しいなら期待値を直してください。期待値のほうが正しいなら、当てはまった行を直してください。どちらを直すかは、出典(規約、Excel、いま動いている実装)が決めます。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| x     | -> r(r) : money[円, incl_tax] |
| true  | 100円                         |
| false | 200円                         |

examples
| x    | -> r  |
| true | 200円 |

関係するコード: E111, E105

E108

error — 中間値が int64 に収まることを証明できません

いつ出るか。 宣言した範囲と刻みから計算した「実際に取りうる値」が、int64 を超えるとき。率の刻みが 1% なら格納される整数は 100 倍になります。乱数の入力(random)の点を掛け合わせた数が 2^62 を越えるときもこれです。確率は点を数えて出し、数えた通りの数はどの言語でも int64 で持ちます。

直し方。 入力の範囲を狭めるか、途中に丸めを一つ入れてください。どこで丸めるかは答えを変える業務の判断なので、rulec は決めません。乱数の入力の点が多すぎるなら、その範囲を狭めてください。

最小の再現:

rule t(t) v1

inputs
  p(p) : money[円, incl_tax]  range >=0円 <=100000000000000000円
  q(q) : rate[step 1%]  range >=0% <=100%

outputs
  r(r) : money[円, incl_tax]  round down(1円)

define off(off) : money[円, incl_tax] = p × q

table j(j)
policy unique
| off | -> r(r) : money[円, incl_tax] |
| -   | 0円                           |

乱数の入力の点:

rule t(t) v1

inputs
  a(a) : number  range >=0 <=9999999999  random
  b(b) : number  range >=0 <=9999999999  random

outputs
  r(r) : bool

table j(j)
policy unique
| a   | b | -> r(r) : bool |
| <5  | - | true           |
| >=5 | - | false          |

関係するコード: E112, E103

E109

error — 検査の予算を超えたので、完全性を証明できませんでした

いつ出るか。 領域検査が訪れたノード数が --budget を超えたとき。証明できなかったことを緑にはしないので、警告ではなくエラーです。

直し方。 表を分けて列の数を減らすか、--budget を上げてください(rulec check にも ritsu check にもあります)。列の積が効くので、一つの表に列を積むより、表を一列につないでいくほうが安く済みます。

最小の再現(--budget 1 で):

rule t(t) v1

enum k(k) = a(a) | b(b) | c(c)

inputs
  x(x) : k

outputs
  r(r) : bool

table j(j)
policy unique
| x | -> r(r) : bool |
| a | true           |
| b | false          |
| c | true           |

関係するコード: E101, W114

E110

error — 検査できない型の列があります

いつ出るか。 その列の型を、区画の計算ができる形に落とせないとき。これが出たら rulec 自身のバグです。 表の検査が黙って素通りするのを防ぐための内部の検査で、日付と optional で二度起きた同じ種類の事故を、まとめて塞いだものです。

直し方。 その列を、いま検査できる型(真偽・列挙・数量・金額・率・日付・optional)に直してください。そのうえで報告してください。黙って素通りするより止まるほうが正しい、という判断でこの検査を置いています。

最小の再現:

rule t(t) v1

inputs
  s(s) : string?

outputs
  r(r) : bool

table j(j)
policy unique
| s               | -> r(r) : bool |
| starts_with "a" | true           |

関係するコード: E101, E105

E111

error — 例に出力の列がありません

いつ出るか。 examples が、宣言した出力の一部しか書いていないとき。実装どうしの照合は、生成物が揃って同じ誤りを持つと緑のままなので、それを破れるのは人の書いた期待値だけです。実際に複数出力の丸めが、どの言語でも揃って抜けたことがあります。

直し方。 欠けている出力の列を examples に足してください。出力が二つ以上あるときは、二列目以降に -> を書いても書かなくても構いません。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool

outputs
  ok(ok) : bool
  fee(fee) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| x     | -> ok(ok) : bool | fee(fee) : money[円, incl_tax] |
| true  | true             | 100円                          |
| false | false            | 0円                            |

examples
| x    | -> ok |
| true | true  |

関係するコード: E107

E112

error — 導出の範囲が、実際に到達しうる値を含んでいません

いつ出るか。 入力の範囲から計算した「実際に取りうる値」が、導出に宣言した range からはみ出すとき。範囲が狭いと、完全性検査が実際に起きる値を見ないまま「完全」と答えます。max・min に書いた range が、列の範囲と empty の値を含まないときも、これです。答えはそのどちらかの値だからです。

直し方。 文面が示す範囲まで range を広げてください(range >=-110万円 <=100万円 の形で書いてあります)。起こりえない分まで広げても、検査がそこを自分で外すので害はありません。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円, incl_tax]  range >=0円 <=100万円
  b(b) : money[円, incl_tax]  range >=0円 <=100万円

outputs
  r(r) : bool

derive gap(gap) : money[円, incl_tax] = a - b  range >=0円 <=100万円

table j(j)
policy unique
| gap   | -> r(r) : bool |
| <=0円 | false          |
| >0円  | true           |

関係するコード: E108, E101

E113

error — 真偽定義の条件が、書ける二つの形のどちらでもありません

いつ出るか。 define … : bool の条件が、「入力か導出の値ひとつを定数と比べる」形でも、「引き算で差を取れない型どうしの比較」(日付どうしなど)でもないとき。数値どうしを直接比べたときがこれに当たります。

直し方。 差を導出として宣言してから定数と比べてください。define bigger : bool = a >= b は derive gap(gap) : money[円, incl_tax] = a - b range … を足して | gap | >=0円 | と書き換えられます。そのほうが厳密に解析できます。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円, incl_tax]  range >=0円 <=100万円
  b(b) : money[円, incl_tax]  range >=0円 <=100万円

outputs
  r(r) : bool

define bigger(bigger) : bool = a >= b

table j(j)
policy unique
| bigger | -> r(r) : bool |
| true   | true           |
| false  | false          |

関係するコード: E112, E103

E114

error — 値が宣言した刻みに載っていません

いつ出るか。 rate[step 1%] の列に 0.5% のように、宣言した刻みの整数倍でない値が書かれたとき。実行時の値はその刻みの整数一本なので、この値には表し方がありません。率の出力の丸めの刻みが、出力の宣言した刻みの整数倍でないとき(rate[step 1%] に round down(0.5%))も同じです。答えは丸めの刻みに載り、呼び出し側へは宣言した刻みの整数で渡すので、表せない答えが出ます。

直し方。 刻みに載る値に直すか、型の刻みを細かくしてください(rate[step 0.1%])。黙って近い刻みに寄せると、表で読める境界と生成コードの境界が食い違います。丸めの刻みなら、刻みを丸めに合わせるか、丸めの刻みを刻みの整数倍にしてください。

最小の再現:

rule t(t) v1

inputs
  r(r) : rate[step 1%]  range >=0% <=100%

outputs
  o(o) : bool

table j(j)
policy first
| r      | -> o(o) : bool |
| <=0.5% | true           |
| -      | false          |

関係するコード: E103, E106

E115

error — 割る数が正の定数ではありません

いつ出るか。 ÷ の右が、正の整数の定数でも、同じ単位の正の金額・数量の定数でもないとき。変数、0、負の数、小数がこれに当たります。ただし、丸めの関数の引数のいちばん外側の割り算は、値で割れます(half_up(合計 / 件数, 1円)。割る数が 0 にならないことは E132 が確かめます)。mod(x, n) の割る数 n も、正の整数の定数でなければこれです。

直し方。 値で割るなら、割り算を丸めの関数の中に入れて、刻みと丸め方を書いてください(half_up(合計 / 件数, 1円))。割る数が業務のデータで率として渡せるなら、率の入力にするか、定数を引く表として書いてください。刻みが静的に決まらないと生成コードは言語の除算に頼ることになり、Python は −∞ 方向、Go は 0 方向に丸めて答えが食い違います。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=0 <=100
  d(d) : number  range >=1 <=100

outputs
  o(o) : bool

define r(r) : number = n ÷ d

table j(j)
policy first
| r | -> o(o) : bool |
| - | true           |

関係するコード: E103, E108

E116

error — 行の金額が、引いた出典のコピーに無いか、別の見出しの下にあります

いつ出るか。 行の出力の値が、その行(またはその表)が @出典 表1 で引いている出典のコピーのどこにも出てこないとき。行のセルの語(関東)と一字一句同じ見出しがコピーにあれば、その見出しの行と列の中だけを探します。隣の行の金額はコピーのどこかにはあるので、表全体を探したのでは取り違えを見逃すからです。比べるのは金額だけです。閾値は転記するときに書き換わります(1,949,000円まで は <=1949000円 になる)が、金額は書き換わらないからです。rulec は、コピーの 5/1,000 や 1,000分の5 を 0.5% と読みます。コピーは rulec source fetch が文書から取り出して保存したもので、check が見るのはそのコピーであって文書そのものではありません。

直し方。 出典のコピーを読み直して金額を直してください。別の見出しの下にあると言われたら、行を取り違えています。一桁の打ち間違いなら、たいてい同時に W120 が出て、どの値が使われずに残っているかを言います。値が別のところ(後の通知、正誤表、人の回答)から来たのなら、この行の引用を外し、どこから来たかを行末のコメントに書いてください。rulec doc がそのコメントを、規則を読む人に見せます。

最小の再現:

rule t(t) v1

source 料金表 = file "料金表.md" sha256:75465b330d123ab8
  表1 sha256:0a95cedbd7311274

inputs
  a(a) : bool

outputs
  x(x) : money[円]  round down(1円)

table 表(t1)  @料金表 表1
policy unique
| a     | -> x  |
| true  | 990円 |
| false | 890円 |

隣に置く 料金表.md:

# 料金表

| あて先 | 運賃 |
|---|---|
| 近畿 | 990円 |
| 関東 | 880円 |

隣に置く 料金表.md.fragments/表1.tsv:

あて先 運賃
近畿  990円
関東  880円

関係するコード: W120, E038, E107

E117

error — 配分の前提が揃っていません

いつ出るか。 allocate(配る額, 累計, 全体) の三つが配分の形になっていないとき。三つとも範囲を宣言した名前で、配る額と累計は負になれず、全体は正で、累計が全体を超えないと constraint が言っていなければなりません。

直し方。 足りないものを書いてください。constraint 累計 <= 全体 がないと、配る分が配る額を超えることがあり、明細の合計が総額に一致しません。負の値が混じると、下へ丸めるのか 0 の方向へ丸めるのかで、言語ごとに答えが割れます。

最小の再現:

rule t(t) v1

inputs
  値引き(off) : money[円]  range >=0円 <=1000円
  ここまで(upto) : money[円]  range >=0円 <=1000円
  合計(base) : money[円]  range >=1円 <=1000円

outputs
  o(o) : money[円]  round down(1円)

derive 配分(share) : money[円] = allocate(値引き, ここまで, 合計)  range >=0円 <=1000円

result o = 配分

関係するコード: E115, E108

E118

error — 呼び出しの形が違います

いつ出るか。 無い関数を呼んでいるか、引数の数が合わないとき。書けるのは min(a, b) max(a, b) allocate(配る額, 累計, 全体) mod(x, n) isqrt(x) と丸めの五つ(down(x, 1円) など)だけです。丸めの刻みが定数でないときも、これです。

直し方。 綴りと引数の数を確かめてください。引数が多ければ余りは黙って捨てられ、少なければ答えが決まりません。どちらも以前の版では検査を素通りしていて、ジェネレーターで初めて止まっていました。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=0 <=100
  d(d) : number  range >=1 <=100

outputs
  o(o) : number  round down(1)

define r(r) : number = min(n, d, n)

result o = r

関係するコード: E103, E115

E120

error — from が入力の型と合いません

いつ出るか。 from の返すものが、それを受ける入力の型と合わないとき。any と all は bool を、count は number を、sum は数(number・お金・量・率)を、max と min は数か日付を返します。パスの先にあるものの型が入力と合わないとき(契約が文字列と言っているフィールドを number の入力で受けるなど)と、any・all・count・sum・max・min が並びでないものを歩こうとしているとき、where の値がフィールドの型と合わないときにも出ます。of が読む要素のフィールドの型が入力と合わないとき(sum は整数を足し、小数は足せません)、契約から取る並びが配列でないとき、並びの要素のフィールドの型が合わないときも同じです。契約が決めるのは値の運ばれ方なので、列挙も日付も文字列で、金額と数量は宣言した単位の整数で届きます。

直し方。 型のほうか from のほうを直してください。件数が欲しいなら number の入力に範囲を付けて受け、当てはまるかどうかが欲しいなら bool で受けてください。値そのものが欲しいなら from <shape の名前>.<フィールド> と書いてください。where の値に単位は書けません。契約の値には単位が無いので、書けば目盛りの違う数どうしを黙って比べることになるからです。

最小の再現:

rule t(t) v1

shape order(order) = jsonschema "order.json" "#/$defs/Order"

inputs
  a(a) : bool  from count order.lines

outputs
  x(x) : bool

table 表(t1)
policy unique
| a | -> x |
| - | true |

隣に置く order.json:

{"$defs":{"Order":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string"}}}}}}}}

関係するコード: E121, W122, E103

E121

error — from のパスが契約にありません

いつ出るか。 from のパスが、宣言した shape の契約の中に見つからないとき。パスの最初の語が shape の名前でないとき、途中のフィールドが無いとき、where や of の見るフィールドが要素に無いときです。elements … from の並びのパスと、その要素のフィールドのパス(order.lines[].qty のように、要素の中を [] の後ろに示します)も同じです。注に、パスがどこまで届いたかと、そこにあったフィールドの名前が出ます。パスが並び(JSON Schema の array、.proto の repeated のフィールド)の先へ続くときも、このエラーです。パスが読むのは一つの値で、要素はそれぞれ自分の値を持つので、入力がどの要素のものを受け取るかが決まりません。注は、パスが通る並びを全部挙げます。契約は .proto でも JSON Schema でもよく、import proto と同じく毎回の check で読まれ、固定は付きません。

直し方。 綴りを直すか、契約のほうが動いたのならパスを書き直してください。このエラーはそのためにあります。 契約がフィールドの名前を変えたとき、手書きのつなぎのコードなら実行するまで気づきませんが、rulec は生成の前に止まります。パスが並びを通るときは、並びを読む書き方にしてください。要素のフィールドを調べる from any <並び> where <フィールド> = <値>(all、count も)、数を足し合わせたり比べたりする sum・max・min、要素を一つずつたどる elements <名前> from <並び> です。並びに要素がいつも一つなら、契約のほうで、それを一つのオブジェクト(repeated でないフィールド)にしてください。

最小の再現:

rule t(t) v1

shape order(order) = jsonschema "order.json" "#/$defs/Order"

inputs
  a(a) : bool  from order.nope

outputs
  x(x) : bool

table 表(t1)
policy unique
| a | -> x |
| - | true |

隣に置く order.json:

{"$defs":{"Order":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string"}}}}}}}}

並びの先へ続くパス:

rule t(t) v1

shape order(order) = jsonschema "order.json" "#/$defs/Order"

inputs
  a(a) : string  from order.lines.category

outputs
  x(x) : bool

table t1(t1)
policy unique
| a | -> x |
| - | true |

隣に置く order.json:

{"$defs":{"Order":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string"}}}}}}}}

関係するコード: E120, W122, E032

E119

error — 行の境界が、引いた出典のコピーと反対側です

いつ出るか。 引用のある行の閾値が、境界の値をコピーと反対の側に入れているとき。閾値は転記するときに書き換わる(1,949,000円まで は <=1949000円 になる)ので文字としては比べられず、比べているのは境界の値がどちらに入るかだけです。コピーの「60cm以下」と「60cmを超え」はどちらも 60cm を小さいほうに入れ、<=60cm と >60cm も同じことを言います。コピーに境界の語が無いとき(18 to 20、60〜80)、語が数と別の列にあるとき(保険料額表の「円以上/円未満」)、同じ数をコピーが両側に置いているときは、何も言いません。

直し方。 出典のコピーを読み直して直してください。fix.text は、このセルの境界の側だけを入れ替えた形です。比べる向きは表の形で決まり、コピーが決めることではないので、fix.text は < と <= の入れ替えしか書きません。一つの境界を誤って転記すると、それを分け合う二つの行の両方にこのエラーが出ます。境界が別のところ(後の通知、本文の但し書き)から来たのなら、この行の引用を外し、どこから来たかを行末のコメントに書いてください。

最小の再現:

rule t(t) v1

source 寸法表 = file "寸法表.md" sha256:a19333e262c10371
  表1 sha256:a5c05813ad703b8e

inputs
  a(a) : length[cm]  range >=1cm <=80cm

outputs
  x(x) : money[円]  round up(10円)

table 表(t1)  @寸法表 表1
policy unique
| a             | -> x   |
| <60cm         | 1410円 |
| >=60cm <=80cm | 1710円 |

隣に置く 寸法表.md:

# 寸法表

| サイズ | 運賃 |
|---|---|
| 60cmまで | 1410円 |
| 60cmを超え80cm以下 | 1710円 |

隣に置く 寸法表.md.fragments/表1.tsv:

サイズ 運賃
60cmまで  1410円
60cmを超え80cm以下   1710円

関係するコード: E116, W120, E105

W122

warning — その shape を使っている入力がありません

いつ出るか。 shape を宣言しているのに、from <その名前>.… と書いた入力も並びも一つも無いとき。契約は読まれますが、何も確かめていません。

直し方。 使うか、消してください。読まれているだけの契約は、次に読む人に「ここは契約に縛られている」と思わせます。縛られているのは from を書いた入力だけです。

最小の再現:

rule t(t) v1

shape order(order) = jsonschema "order.json" "#/$defs/Order"

inputs
  a(a) : bool

outputs
  x(x) : bool

table 表(t1)
policy unique
| a | -> x |
| - | true |

隣に置く order.json:

{"$defs":{"Order":{"type":"object","properties":{"lines":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string"}}}}}}}}

関係するコード: E121, W111

E122

error — 契約が通す値を、規則が受け付けません

いつ出るか。 from で読む値について、契約の検証は通すのに、入力の宣言が受け付けない値があるとき。比べるのは、数の範囲(Protovalidate の gte・lte など、JSON Schema の minimum・maximum)、並びの件数(min_items・max_items、minItems・maxItems)、列挙の値(string.in、enum。順のある列挙の入力に range を書いていれば、範囲に入る値と比べます)、JSON Schema の required です。from sum は、要素のフィールドの値の範囲と要素の数から決まる合計の届く先を、from max・from min はフィールドの値を比べます。elements … from で契約から取る並びは、要素のフィールドを入力と同じに比べ、並びの件数を count の上限と、要素の値の合計を sum の上限と比べます。proto3 で注釈の無い数のフィールドは、入れ忘れると 0 として届くので、0 を受け付けない入力はここで止まります。required の無いメッセージのフィールドと optional のフィールドは省略でき、そのとき中の値は規則を通らずに既定値(0、""、0 件)として届きます。.proto の文字列から読む日付は、"" を通すかどうかを見ます。フィールドをまたぐ条件(CEL の式、oneof、JSON Schema の allOf・anyOf・oneOf・not・if)が一つのフィールドの幅を狭めていれば、それも読みます。JSON Schema の型に null があるのに、入力が省略できないときにも出ます。読めない規則(剰余や文字列の関数を使う CEL など)は、無いものとして扱います。契約を実際より広く読むので、要らないところで出ることはあっても、見逃すことはありません。

直し方。 どちらを直すかは、人が決めることです。その値が来ないはずなら、契約を狭めてください。fix.text が、契約に書く注釈そのものです(narrow_contract)。来るのなら、規則の範囲を広げるか列挙に値を足して、その値の答えを決めてください。where で絞った件数の下限のように契約に書けない前提もあり、そのときは fix.kind が none です。読む値が無いことがあるなら、入力を T? にしてください。値が無いとき、規則はそれを none として読みます。

最小の再現:

rule t(t) v1

shape order(order) = jsonschema "order.json" "#/$defs/Order"

inputs
  a(a) : number  range >=0 <=5  from count order.lines

outputs
  x(x) : bool

table 表(t1)
policy unique
| a | -> x |
| - | true |

隣に置く order.json:

{"$defs":{"Order":{"type":"object","properties":{"lines":{"type":"array","maxItems":10,"items":{"type":"object"}}},"required":["lines"]}}}

関係するコード: W123, E123, E121, E032

W123

warning — 行が、契約の通さない値でしか当たりません

いつ出るか。 行のセルが from で読む入力を試していて、そのセルが受け付ける値を、契約の検証が一つも通さないとき。契約を通ったものしか来ないので、その行に当たるリクエストやメッセージはありません。比べるのは入力そのものの列だけで、そこから導いた値の列は見ません。

直し方。 契約がこの先も広がらないなら、行を消して、入力の範囲を契約に合わせてください。広がる予定があって残しているのなら、そのままで構いません。CI の check --diff-base は、新しく生じたものだけを報告します。

最小の再現:

rule t(t) v1

shape order(order) = jsonschema "order.json" "#/$defs/Order"

inputs
  a(a) : number  range >=0 <=20  from count order.lines

outputs
  x(x) : bool

table 表(t1)
policy unique
| a    | -> x  |
| <=10 | true  |
| >10  | false |

隣に置く order.json:

{"$defs":{"Order":{"type":"object","properties":{"lines":{"type":"array","maxItems":10,"items":{"type":"object"}}},"required":["lines"]}}}

関係するコード: E122, W124, E102, W111

E123

error — 契約が、規則の constraint を破る組み合わせを通します

いつ出るか。 constraint の両側が、同じ shape から from で読む入力で、契約の検証を通るリクエストのなかに、両方の値が入力の範囲に入っているのに constraint を満たさないものがあるとき。契約がフィールドのあいだに置く条件(.proto のメッセージの CEL、oneof、JSON Schema の組み合わせ)を読んだうえで、それでも破る組み合わせが残るかを確かめ、見つかれば、その値を例に出します。読めない規則は無いものとして扱うので、見逃すことはありません。

直し方。 どちらを直すかは、人が決めることです。その組み合わせが来ないはずなら、契約で約束してください。.proto なら、fix.text がメッセージに書く (buf.validate.message).cel です(narrow_contract)。JSON Schema には二つのフィールドの値を比べる書き方がないので、fix.kind は none です。来るのなら、constraint を外して、その組み合わせのときの答えを表で決めてください。

最小の再現:

rule t(t) v1

shape 見積(q) = proto "quote.proto" shop.v1.Quote

inputs
  最小(min_g) : mass[g]  range >=1g <=30kg  from 見積.min_g
  最大(max_g) : mass[g]  range >=1g <=30kg  from 見積.max_g

constraint 最小 <= 最大

outputs
  x(x) : bool

table 表(t1)
policy unique
| 最小 | -> x |
| -    | true |

隣に置く quote.proto:

syntax = "proto3";
package shop.v1;

message Quote {
  option (buf.validate.message).cel = {id: "express_cap", expression: "!this.express || this.weight_g <= 5000"};
  int64 min_g = 1 [(buf.validate.field).int64 = {gte: 1, lte: 30000}];
  int64 max_g = 2 [(buf.validate.field).int64 = {gte: 1, lte: 30000}];
  int64 weight_g = 3 [(buf.validate.field).int64 = {gte: 1, lte: 30000}];
  bool express = 4;
}

関係するコード: E122, W124, E018

W124

warning — 行が、契約の通さない組み合わせでしか当たりません

いつ出るか。 行のセルが、同じ shape から from で読む二つ以上の入力を試していて、セルを一つずつ見れば契約の通す値なのに、契約がフィールドのあいだに置く条件のもとでは、その組み合わせが一つも通らないとき。たとえば CEL の this.min <= this.max のもとで「最小が 20kg を超え、最大が 10kg 以下」を求める行や、一つの oneof の二つのメンバーをどちらも 0 でないとする行です。ほかの列のセルは見ないので、当たると言いすぎることはあっても、当たらないと言いすぎることはありません。

直し方。 契約がこの先も変わらないなら、行を消してください。変わる予定があって残しているのなら、そのままで構いません。CI の check --diff-base は、新しく生じたものだけを報告します。

最小の再現:

rule t(t) v1

shape 見積(q) = proto "quote.proto" shop.v1.Quote

inputs
  重さ(weight) : mass[g]  range >=1g <=30kg  from 見積.weight_g
  急ぎ(express) : bool  from 見積.express

outputs
  料金(fee) : money[円]  round up(10円)

table 料金表(fees)
policy first
| 急ぎ  | 重さ | -> 料金 |
| true  | >5kg | 3000円  |
| true  | -    | 1500円  |
| false | -    | 800円   |

隣に置く quote.proto:

syntax = "proto3";
package shop.v1;

message Quote {
  option (buf.validate.message).cel = {id: "express_cap", expression: "!this.express || this.weight_g <= 5000"};
  int64 min_g = 1 [(buf.validate.field).int64 = {gte: 1, lte: 30000}];
  int64 max_g = 2 [(buf.validate.field).int64 = {gte: 1, lte: 30000}];
  int64 weight_g = 3 [(buf.validate.field).int64 = {gte: 1, lte: 30000}];
  bool express = 4;
}

関係するコード: W123, E123, E102

E124

error — 終わりの状態から出る遷移があります

いつ出るか。 final に書いた状態から、別の状態へ移る呼び出しがあるとき。終わったはずの案件がまた動くことになります。その状態に着くまでの最短の呼び出しと、出ていく一回が witness.trace に付きます。

直し方。 その行で状態を留めるか、その状態を final から外してください。どちらが正しいかは業務の判断です。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |

machine k(k) over m
  carry   st -> nx
  initial a
  final   b, c

関係するコード: E125, E126

E125

error — 着いたら終われない状態があります

いつ出るか。 initial から着ける状態のうち、終わりの状態でなく、そこからどの終わりの状態にも着けないものがあるとき。ワークフローネットの健全性でいう「必ず終われる」が破れている形です。そこに着くまでの最短の呼び出しが付きます。持ち越す数が範囲を出て、次の呼び出しを受けられなくなった案件は、E134 で言います。

直し方。 終わりの状態へ移る行を足すか、そこで終わるのが正しいなら、その状態を final に加えてください。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c) | d(d)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | d             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |
| d  | -   | d             |

machine k(k) over m
  carry   st -> nx
  initial a
  final   c

関係するコード: E124, W125, E134

E126

error — never の主張が破れています

いつ出るか。 never A after B について、initial から B を通ったあとで A に着く呼び出しの並びがあるとき。いちばん短いものが付き、そのどの呼び出しも、規則が受け付けて答えを返す入力です。

直し方。 行き先を決める行を直すか、主張が業務として誤りなら never の行を消してください。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |

machine k(k) over m
  carry   st -> nx
  initial a
  final   c
  never   c after b

関係するコード: E052, E124

E127

error — once の主張が破れています

いつ出るか。 once <出力> <セル> について、一件の案件の中で、出力がセルに当てはまる呼び出しが二回ある並びがあるとき。二重の返金、二重の付与の形です。いちばん短いものが付きます。

直し方。 二回目に至る並びを断つ行を足すか(返金を済ませた状態から前へ戻らない、など)、宣言が誤りなら once の行を消してください。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s
  f(f) : bool

table m(m)
policy unique
| st | ev  | -> nx(nx) : s | f(f) : bool |
| a  | fwd | b             | false       |
| a  | rev | a             | false       |
| b  | fwd | c             | false       |
| b  | rev | a             | true        |
| c  | -   | c             | false       |

machine k(k) over m
  carry   st -> nx
  initial a
  final   c
  once    f true

関係するコード: E053, E126

E128

error — ステートマシンの主張を検査できませんでした

いつ出るか。 入力の区画の数が予算(--budget を 50 で割った数)を超えたとき、または規則の答えが決まった数の列で区切れないとき。証明できなかった主張を緑にはしないので、警告ではなくエラーです。

直し方。 --budget を上げるか(rulec check にも ritsu check にもあります)、遷移を決める表の列を減らしてください。列の積が効くので、表を一列につないでいくほうが安く済みます。

最小の再現(--budget 100 で):

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |

machine k(k) over m
  carry   st -> nx
  initial a
  final   c

関係するコード: E109, W127

E129

error — この rulec は koyomi のファイルを読めません

いつ出るか。 範囲を koyomi の日付からとる規則(range from koyomi)を、koyomi をつないでいない rulec で確かめたとき。rulec のクレートのバイナリがそうです。範囲全体で確かめ直すことはせず、確かめられなかったとして終了コード 2 で終わります。

直し方。 ritsu rulec check <ファイル> か ritsu check <ディレクトリ> で走らせてください。どちらも、koyomi から日の集合を受け取ります。

最小の再現:

rule t(t) v1

inputs
  d(d) : date  range from koyomi "terms.cal" date payment

outputs
  r(r) : bool

table j(j)
policy unique
| d | -> r(r) : bool |
| - | true           |

隣に置く terms.cal:

dates terms v1

inputs
  received : date  range >=2026-01-01 <=2026-12-20

date closing = received
  close day 20

date payment = closing
  day 10 of month +1

関係するコード: E065, E130

E130

error — koyomi の日付がとる日を読めません

いつ出るか。 range from koyomi が指す日付の日を、koyomi が答えないとき。ファイルが無い、koyomi の検査を通らない、その名前の日付が無い、入力の組み合わせが koyomi の確かめる数を超える、途中で計算が止まる入力がある、とる日が一つも無い、のどれかです。注には koyomi のメッセージが出ます。範囲全体で確かめ直すことはしません。

直し方。 koyomi のファイルを ritsu koyomi check で通るように直し、日付の名前を合わせてください。

最小の再現:

rule t(t) v1

inputs
  d(d) : date  range from koyomi "terms.cal" date due

outputs
  r(r) : bool

table j(j)
policy unique
| d | -> r(r) : bool |
| - | true           |

隣に置く terms.cal:

dates terms v1

inputs
  received : date  range >=2026-01-01 <=2026-12-20

date closing = received
  close day 20

date payment = closing
  day 10 of month +1

関係するコード: E065, E129

E132

error — 割る数が 0 になりえます

いつ出るか。 丸めの関数の引数が値で割る割り算(half_up(合計 / 件数, 1円))で、割る数のとりうる範囲が 0 を含むとき。範囲は、入力の範囲、導出と define の範囲、上の表が書く値から区間で求めます。行が自分の表の列をそのまま書くときは、その行のセルがその列に通す値だけを数えます(| >=1 | 件数 | は 1 以上の件数だけを書きます)。constraint は読みません。範囲の決まらない値を読む割る数も、0 にならないとは言えないので、これに当たります。注には、割る数を 0 にする入力が見つかればそれが出ます。

直し方。 割る数の範囲を 0 を含まないように狭めるか(range >=1)、max(件数, 1) のように 1 以上にしてから割るか、0 のときに別の値を選ぶ表(| 0 | 1 | と | >=1 | 件数 | の二行)を置いて、その表の出力で割ってください。constraint a < b のもとで b - a で割るときも、max(b - a, 1) と書きます(その制約のもとでは同じ値です)。0 のときに何を答えるかは業務の決めなので、rulec は決めません。

最小の再現:

rule 平均単価(average_price) v1

inputs
  合計(total) : money[円]  range >=0円 <=10000円
  件数(units) : number  range >=0 <=100

outputs
  平均(average) : money[円]  round half_up(1円)

define 単価(per_unit) : money[円] = half_up(合計 / 件数, 1円)

result 平均 = 単価

関係するコード: E115, E108, E019

E139

error — isqrt の引数が負になりえます

いつ出るか。 isqrt(x) の x のとりうる範囲が負の値を含むとき。範囲は E132 と同じく区間で求め、範囲の決まらない値を読む引数もこれに当たります。負の数に平方根は無く、生成コードはその呼び出しで答えを持ちません。注には、引数を負にする入力が見つかればそれが出ます。

直し方。 引数の範囲が 0 以上になるように入力の範囲を狭めるか、isqrt(max(x, 0)) のように 0 以上にしてから渡してください。冪の切り捨ては掛け算で書きます(isqrt(n * n * n) が n の 1.5 乗の切り捨て)。

最小の再現:

rule 平方根(root_of_gap) v1

inputs
  差(gap) : number  range >=-10 <=100

outputs
  根(root) : number  round down(1)

define 整数の根(whole_root) : number = isqrt(差)

result 根 = 整数の根

関係するコード: E108, E103

E140

error — 出力の範囲が、出力のとる値を含んでいません

いつ出るか。 出力の行に書いた range が、その出力のとりうる値を含まないとき。とりうる値は、出力を決めるもの(表の行のセルの値と式、同じ名前の define、result の式)が入力の範囲と constraint のもとでとる値を、丸めの刻みへ外向きに広げたものです。rulec がその値を求められないとき(範囲の無い入力を読む、数でない出力)も、書いた範囲を確かめられないので、これです。出力の範囲は、ほかの言語(kaname、dandori など)が規則の答えを読む範囲なので、狭いと、そこで行う範囲の検査が、規則が実際に返す値を見落とします。

直し方。 範囲を、文面の示すとりうる値まで広げてください(fix.text に range >=0円 <=1000円 の形で入っています)。確かめられないときは、出力が読む入力に範囲を書くか、出力の範囲を外してください。範囲を書かない出力にも、rulec が求めた範囲が付き、ほかの言語はそれを読みます。

最小の再現:

rule 手数料(fee) v1

inputs
  金額(amount) : money[円]  range >=0円 <=10_000円

outputs
  手数料(fee) : money[円]  round down(1円)  range >=0円 <=500円

result 手数料 = 金額 × 10%

確かめられない範囲:

rule 手数料(fee) v1

inputs
  金額(amount) : money[円]

outputs
  手数料(fee) : money[円]  round down(1円)  range >=0円 <=500円

result 手数料 = 金額 × 10%

関係するコード: E112, E061, E103

E134

error — 持ち越す数が範囲を出る呼び出しがあります

いつ出るか。 initial から着ける状態からの呼び出しで、持ち越す数の次の値が、その入力の範囲の外になるとき。次の呼び出しにその値を渡せないので、案件はそこから先へ進めません。いちばん短い呼び出しの並びが witness.trace に付きます。着けない状態からの呼び出しでだけ範囲を出る行は、W126 で言います。

直し方。 次の値を決める行を直す(上限で止める、別の状態へ移す)か、その値が業務として起きるなら、入力の範囲を広げてください。

最小の再現:

rule t(t) v1

enum s(s) = run(run) | done(done)

inputs
  st(st)       : s
  again(again) : bool
  n(n)         : number  range >=0 <=3

outputs
  nx(nx) : s
  nn(nn) : number  round down(1)

define more(more) : number = n + 1

table m(m)
policy first
| st   | again | n   | -> nx(nx) : s | nn(nn) : number |
| run  | true  | <=2 | run           | more            |
| run  | true  | -   | done          | more            |
| run  | -     | -   | done          | n               |
| done | -     | -   | done          | n               |

machine k(k) over m
  carry   st -> nx
  carry   n -> nn
  initial run
  initial n 0

関係するコード: E072, E135, W126

E135

error — always の主張が破れています

いつ出るか。 always の行が言う状態(when の後に書いた状態、書いていなければどの状態でも)に、持ち越す値がセルに当てはまらないまま着く呼び出しの並びがあるとき。いちばん短いものが付き、そのどの呼び出しも、規則が受け付けて答えを返す入力です。持ち越す数が範囲を出たところは E134 が言い、ここでは見ません。

直し方。 行き先や次の値を決める行を直すか、主張が業務として誤りなら always の行を直してください。

最小の再現:

rule t(t) v1

enum s(s) = run(run) | done(done)

inputs
  st(st) : s
  n(n)   : number  range >=0 <=3

outputs
  nx(nx) : s
  nn(nn) : number  round down(1)

define more(more) : number = n + 1

table m(m)
policy first
| st  | n  | -> nx(nx) : s | nn(nn) : number |
| run | <3 | run           | more            |
| -   | -  | done          | n               |

machine k(k) over m
  carry   st -> nx
  carry   n -> nn
  initial run
  initial n 0
  always  n <=2 when run

関係するコード: E072, E126, E134

E136

error — 前提が循環しています

いつ出るか。 値から要るものへ、そのまた要るものへとたどると、元の値に戻るとき。or の中の値もたどります。互いにたどれる値の組ごとに一つ出て、組の最初の値から戻るまでの輪を一つと、組の値を挙げます。輪の上の値は、どれもほかの値を先に持っていないと手に入らないので、輪のどこからも始められません。or の別の値から輪に入れる場合も、前提の読み違いのもとなので、エラーにします。

直し方。 輪のどこかの前提を外してください。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b) | c(c)

inputs
  x(x) : k

outputs
  r(r) : bool

table j(j)
policy unique
| x | -> r(r) : bool |
| - | true           |

prerequisites p(p) over k
  start a
  b     requires c
  c     requires b

関係するコード: E071, E137

E137

error — start からたどり着けない値があります

いつ出るか。 start の値から始めて、要るもののどのグループにも持っている値がある値を足していっても、足されない値があるとき。循環が無ければ、足されないのは手に入らない値(requires nothing)を待つ値で、手に入らない値だけのグループを持つ値ごとに一つ出ます。その値を待つほかの値は注記に挙げます。循環は E136 が言い、ここでは見ません。手に入らないと書いた値そのものは言いません。

直し方。 手に入らない前提を外すか、その値も手に入らないなら <値> requires nothing "<理由>" と書いてください。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b) | c(c)

inputs
  x(x) : k

outputs
  r(r) : bool

table j(j)
policy unique
| x | -> r(r) : bool |
| - | true           |

prerequisites p(p) over k
  start a
  b     requires c
  c     requires nothing "retired"

関係するコード: E071, E136

E138

error — ordered by の順で、前提が値より後に来ます

いつ出るか。 ordered by が名前を挙げた表で、値の答えが、その値に要るもの(or の中の値も)の答えより前にあるとき。手に入らない値への前提と、循環の上の前提は、E137 と E136 が言うので、ここでは見ません。

直し方。 表の答えか、前提のどちらかを直してください。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b) | c(c)
enum s(s) = one(one) < two(two)

inputs
  x(x) : k

outputs
  r(r) : s

table j(j)
policy unique
| x    | -> r(r) : s |
| a, c | one         |
| b    | two         |

prerequisites p(p) over k
  start a
  b     requires a
  c     requires b
  ordered by j

関係するコード: E071, E136

W125

warning — どの手順でも着かない状態があります

いつ出るか。 持ち越す状態の列挙に、initial から始まる呼び出しの並びでは着かない値があるとき。

直し方。 その状態へ移る遷移を足すか、要らなければ列挙から消してください。ほかの版から移ってくる案件のために残しているのなら、このままで構いません(移行は diff が見ます)。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c) | d(d)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |
| d  | -   | d             |

machine k(k) over m
  carry   st -> nx
  initial a
  final   c

関係するコード: W126, E125

W126

warning — 案件が着ける状態からは使われない遷移があります

いつ出るか。 遷移を決める表の行が、initial から着けない状態のときにしか当てはまらないとき。W125 と一緒に出ます。状態には着けても、その行が要る held の入力の値や、持ち越す値(carry の二行目から)では着かないときも、この警告です(持ち越す数が範囲を出る行が、着けない値のときにしか当たらない場合もここに入ります)。

直し方。 着けない状態へ移る遷移を足すか、行を消してください。

最小の再現:

rule t(t) v1

enum s(s) = a(a) | b(b) | c(c) | d(d)
enum e(e) = fwd(fwd) | rev(rev)

inputs
  st(st) : s
  ev(ev) : e

outputs
  nx(nx) : s

table m(m)
policy unique
| st | ev  | -> nx(nx) : s |
| a  | fwd | b             |
| a  | rev | a             |
| b  | fwd | c             |
| b  | rev | a             |
| c  | -   | c             |
| d  | -   | d             |

machine k(k) over m
  carry   st -> nx
  initial a
  final   c

関係するコード: W125, E102

W127

warning — ステートマシンの主張を決めきれませんでした

いつ出るか。 主張が、答えを出す入力を作れず、起こらないとも示せなかった区画に左右されるとき。導出どうしが入力を共有していて、解が有理数にしか無い形がここに残ります(W114 と同じ場所です)。数を持ち越す機械(carry の二行目から)では、ほかに三つあります。数の値を一つずつ調べると予算を超えるので区間にまとめて調べ、区間の上で破れる並びを、本当に起きる呼び出しでは作り直せなかったとき。区間にまとめたので、どの状態からも終わりに着けるかを確かめていないとき。持ち越す数の次の値が区画の中でほかの入力とともに動き、あいだの値を一つずつは試していないとき。決めきれなかったことを、成り立つとは言いません。

直し方。 その区画に当たる入力が本当に無いなら、条件を整数で書き直してください(倍 >= 5円 を a >= 3円 にする、など)。あるなら、その入力を例か手順の例に書いてください。区間にまとめたためなら、--budget を上げるか持ち越す数の範囲を狭めると、値を一つずつ調べて決めます。

最小の再現:

rule t(t) v1

enum s(s) = p(p) | q(q)

inputs
  st(st) : s
  a(a) : money[円]  range >=0円 <=10万円

outputs
  nx(nx) : s

derive 倍(d) : money[円] = a + a  range >=0円 <=20万円

define 上(up) : bool = 倍 >= 5円
define 下(dn) : bool = 倍 <= 5円

table m(m)
policy first
| st | 上   | 下   | -> nx(nx) : s |
| p  | true | true | q             |
| -  | -    | -    | st            |

machine k(k) over m
  carry   st -> nx
  initial p

関係するコード: W114, E128

W128

warning — 行に当たる入力を見つけられず、当たらないことも示せませんでした

いつ出るか。 計算した列(導出、define)にセルを書いた行で、その行に当たる入力が、規則の例にも、ベクタを作るときの探し方でも、入力の候補の値の組み合わせ(4,096 通りまで)にも、その行を除いたときに完全性の検査が見つける穴を作る入力にも見つからず、どの入力も当たらないことも示せなかったとき。そういう行の点は入力ではなく、そこに届く入力があるかは式どうしの関係で決まります(整数でしか届かない、整数では届かない、など)。届くと決まっていない行を、黙って通しません。入力と列挙だけの行は、点がそのまま入力なので、この探しはしません。

直し方。 その行に当たる入力が本当にあるか、式と行の条件を見比べてください。あるなら、その入力を例に書くと、この警告は消えます。無いなら、行を削除してください。削除して完全性の欠落(E101)が出るなら、その組み合わせが起きないことも rulec は示せていないので、行は残してかまいません。

最小の再現:

rule 平方の区分(square_band) v1

inputs
  辺(side) : number  range >=0 <=10

outputs
  区分(band) : number  round down(1)

define 面積 : number = 辺 * 辺

table 区分表(band_of)
policy first
| 面積 | -> 区分 : number |
| 2    | 1                |
| -    | 2                |

関係するコード: E101, E102, W114, W127

W130

warning — ほかの前提からたどれる前提があります

いつ出るか。 値の前提の一つが、同じ値のほかの前提が要るもの(そのまた要るものも)の中にあるとき。書いても書かなくても、その値を取れるときは同じです。or の中の値は、どちらの側でも見ません。

直し方。 その前提を消してください。前提を直すときに書き直す所が一つ減ります。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b) | c(c)

inputs
  x(x) : k

outputs
  r(r) : bool

table j(j)
policy unique
| x | -> r(r) : bool |
| - | true           |

prerequisites p(p) over k
  start a
  b     requires a
  c     requires b, a

関係するコード: E136

W105

warning — 要確認の隠れ: 先の行が後の行の一部を隠しています

いつ出るか。 policy first の表で、一部だけ重なっていて出力が違う行の対があるとき。階段状の隠れと、答えが同じ隠れは件数の注記に畳まれ、ここに一覧されるのは要確認の対だけです。重なりがどの入力も届かない点だけにあるときは、E105 と同じく報告しません。

直し方。 意図どおりならこのままで構いません(CI の check --diff-base は新たに生じた対だけを報告します)。後の行を優先したいなら、その行を先の行より上へ移してください。すべての対を見るには --show-shadow を付けてください。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b)

inputs
  x(x) : k
  y(y) : bool

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy first
| x | y    | -> r(r) : money[円, incl_tax] |
| a | -    | 100円                         |
| - | true | 200円                         |
| - | -    | 300円                         |

関係するコード: E105, W110, E102

W110

warning — 重なりのない first です

いつ出るか。 policy first なのに、どの二行も重ならないとき。順序に意味が無いので、unique のほうが強い保証になります。

直し方。 policy unique に変えてください。並べ替えても意味が変わらないことが、以後の検査で守られます。

最小の再現:

rule t(t) v1

enum k(k) = a(a) | b(b)

inputs
  x(x) : k

outputs
  r(r) : bool

table j(j)
policy first
| x | -> r(r) : bool |
| a | true           |
| b | false          |

関係するコード: W105, E105

W111

warning — 使われていない宣言があります

いつ出るか。 入力・導出・グループ・列挙の値が、どの表のどのセルにも現れないとき。書き忘れのしるしであることも、意図した契約であることもあります。import で持ち込んだ型の値は対象外です。順のある列挙の値のうち、その列挙を型に持つ名前がどれも入力で、どの入力の range もその値を外しているものも対象外です。その値を持ってくる呼び出しは無いからです。入力をそのまま渡すセル(| false | requested |)が答える値も、その列挙をどの表も列で確かめていなければ対象外です。その値の行を持てる表が無いからです。

直し方。 入力が範囲の入口検査としてだけ効いているなら、宣言に contract_only を付けて黙らせてください。列挙の値が既定行に落ちるのが正しいなら、値の宣言に default を付けてください。どちらでもないなら、その列を表に足すか、宣言を消してください。

最小の再現:

rule t(t) v1

inputs
  x(x) : bool
  w(w) : mass[g]  range >=0g <=10kg

outputs
  r(r) : bool

table j(j)
policy unique
| x     | -> r(r) : bool |
| true  | true           |
| false | false          |

関係するコード: E101, E012

W116

warning — どの例も使っていない sequence です

いつ出るか。 sequence を書いたのに、どの例もその名前を書いていないとき。並びは、例が使ったときにだけ走るので、走っていない並びです。

直し方。 その並びをたどる例を足すか、並びのほうを消してください。書いたのに使っていないのは、たいてい例を書き忘れた跡です。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)

elements xs(xs)
  k(k) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| k     | -> d(d) : v |
| <=5円 | a           |
| >5円  | b           |

fold d over xs
  a -> next
  b -> take_first k
  empty -> 0円
  exhausted -> held

sequence s(s)
| k   |
| 3円 |

関係するコード: E027, W111

W119

warning — ハッシュを書いた箇所が引用されていません

いつ出るか。 source の下にハッシュの行があるのに、その箇所を引用する @ が規則のどこにも無いとき。引用を消したあとの残りです。

直し方。 その行を消してください。rulec source pin でも消せます。

最小の再現:

rule t(t) v1

source 法 = law "000AC0000000001" asof 2026-04-01
  第1条 sha256:ce31217424a10206
  第2条 sha256:0000000000000000

inputs
  a(a) : bool

outputs
  x(x) : bool

table 表(t1)  @法 第1条
| a | -> x |
| - | true |

隣に置く sources/law/000AC0000000001@2026-04-01/MainProvision-Article_1.xml:

<Article Num="1"><ArticleTitle>第一条</ArticleTitle><Paragraph Num="1"><ParagraphNum/><ParagraphSentence><Sentence>甲は、乙とする。</Sentence></ParagraphSentence></Paragraph></Article>

関係するコード: E037

W120

warning — 出典のコピーにある値を、どの行も使っていません

いつ出るか。 表が @出典 表1 で丸ごと引いている出典のコピーに、数だけでできたセルがあって、その値をどの行も使っていないとき。行を一本落としても、完全性の検査には出ません。落ちた行の入力は、残った行のどれかに当てはまってしまうからです。数だけのセルしか見ないので、2026年4月1日改定 のような文は金額として数えません。<=3kg の一行でコピーの 1kg・2kg・3kg をまとめて転記した場合も出ません。

直し方。 出典のコピーと見比べて、落とした行がないか確かめてください。改定で行が増えたのなら、その行をここに転記してください。引用した表のうち一部だけを転記したのなら(発地ごとの運賃表から、一つの発地だけを転記したときなど)、引用を table の行から、転記した行それぞれの末尾へ移してください。行の引用は「この行はここから来た」としか言わないので、転記していない残りの行は問われなくなります。金額の突き合わせ(E116)は残ります。

最小の再現:

rule t(t) v1

source 料金表 = file "料金表.md" sha256:75465b330d123ab8
  表1 sha256:0a95cedbd7311274

inputs
  a(a) : bool

outputs
  x(x) : money[円]  round down(1円)

table 表(t1)  @料金表 表1
policy unique
| a | -> x  |
| - | 990円 |

隣に置く 料金表.md:

# 料金表

| あて先 | 運賃 |
|---|---|
| 近畿 | 990円 |
| 関東 | 880円 |

隣に置く 料金表.md.fragments/表1.tsv:

あて先 運賃
近畿  990円
関東  880円

関係するコード: E116, W119

W118

warning — 準用した表の行が、この規則ではどれも当たりません

いつ出るか。 準用した表か節の全行が、この規則では当たらないとき。読み替えた値がその表の条件に届かないか、この規則のほかの定義(overrides 準用名:表 で優先する節など)が全部先に取っています。一部の行が当たらないだけなら何も言いません。元の規則の表はこの規則より広い範囲に書かれているのが普通で、そうした行は doc が「この準用では当たらない行」として挙げます。

直し方。 その表がこの準用に要らないなら except <表> で外してください。要るはずなら、読み替えか with の値の対応を見直してください。

最小の再現:

rule t(t) v1

inputs
  n(n) : number  range >=1 <=10

outputs
  y(y) : number  round down(1)

apply 呼(c) = "呼び先.rule" sha256:369102b8f803dc28
  a = n
  x -> y

clause 特例(special) -> 呼:x
  when always
  then 3
  overrides 呼:表

隣に置く 呼び先.rule:

rule 呼び先(callee) v1

inputs
  a(a) : number  range >=1 <=10

outputs
  x(x) : number  round down(1)

table 表(t)
policy unique
   | a   | -> x |
小 | <=5 | 1    |
大 | >5  | 2    |

関係するコード: E102, W117

W117

warning — 効かない例外です

いつ出るか。 overrides で優先すると書いた相手の行と、この表の行が一つも交わらないとき。優先は、両方に当てはまる入力があるときにどちらが勝つかを決めるものなので、交わらなければ何も決めていません。たいていは、ただし書が本文の一部を切り出す形に転記されていない、という転記の誤りです。

直し方。 原文と見比べて、この表の行の条件か相手の行の条件を直してください。本当に交わらないなら、overrides の行を消してください。

最小の再現:

rule t(t) v1

inputs
  a(a) : bool

outputs
  x(x) : bool

table 甲(ko)
   | a     | -> x  |
r1 | true  | true  |
r2 | false | false |

table 乙(otsu)
overrides 甲:r1, 甲:r2
| a    | -> x  |
| true | false |

関係するコード: E035, E105

W121

warning — 生成先の言語で、識別子がぶつかるか使えません

いつ出るか。 ASCII の別名が、生成先のどれかの予約語か、その言語がすでに使っている名前と同じとき。別名はそのまま関数・引数・型・メンバの名前になります。規則の別名は、モジュールやパッケージの名前にもなります。そこで標準ライブラリと同じ名前だと、生成したモジュールがぶつかります。また、規則と、規則が宣言する列挙の型の名前が同じになるとき。Go は規則の関数と列挙の型を一つのパッケージに並べ、Java は列挙を規則のクラスの中に置くので、どちらもコンパイルできません(enums のファイルから読む列挙は、そのファイルのパッケージやクラスの名前で書くので、ぶつかりません)。別名の無い名前が予約語のときも出ます。そのときは生成コードがどの言語でも名前の後ろに _ を付けて書き(class_)、それがこの規則のほかの名前の識別子でもあれば、さらに番号を付けます(class_2)。書いた二つの名前の識別子(別名、無ければ名前)が違っても、どれかの生成先の綴りで一つになるときにも出ます。綴りは、値を書く lowerCamelCase、構造体のフィールドの PascalCase、.proto のフィールドの JSON の名前、列挙の値の大文字、予約語や言語が使う変数の名前に付ける _、大文字と小文字を区別しない列の名前(SQLite)、名前の先頭の 63 バイト(PostgreSQL)です。識別子をその生成先が使えないときも出ます。大文字で始まる名前を定数として読む言語、_ で始まるフィールドを受け付けない NamedTuple、63 バイトより長い列の名前を切る PostgreSQL、_ だけの名前を変数にもフィールドにもできない言語、列の名前に true と false を付けない SQLite、ASCII でない名前を取らない .proto です。書いた名前が、生成したコードが自分で使う名前と同じになるときにも出ます。当てはまった行と答えと要素の型、誤りの型、丸めなどの補助関数、局所変数、組み込みの名前、.proto のメッセージとフィールド(DecideResponse の trace)、列挙の値の <型>_UNSPECIFIED、Connect のサービスが読み込む名前、言語のコマンドが取ってあるパッケージの名前、プログラムが始まるファイルの名前です。どの生成先でそうなるかは、警告の注記が言います。どの言語でも一つに綴る二つの名前(二つの列挙の型など)は、E034 で止まります。

直し方。 予約語なら、その言語の生成コードはコンパイルが通りません(type を入力の別名にすると Rust が落ちます)。すでにある名前なら、規則の関数や列挙の型がそれを隠します(sum を規則の別名にすると Python の組み込みが隠れます)。モジュールの名前なら、time を規則の別名にすると、生成した time のモジュールが標準ライブラリの time とぶつかります。どの生成先でどうぶつかるかは、警告の注記に出ます。引数やローカル変数の名前は、その本体の外までは隠しません。そのため、引数やローカル変数の名前でこの警告が出るのは、予約語のときだけです。二つの名前がある生成先で一つの識別子になるなら、その生成先を使うときは、どちらかに別名を付けてください。生成先が使えない識別子や、生成したコードが自分で使う名前なら、使える別名を付けてください(大文字で始まらない、_ で始まらない、63 バイト以下の、生成したコードが使わない別名)。使わない生成先なら、このままで構いません。

最小の再現:

rule t(t) v1

inputs
  種別(type) : number  range >=0 <=10

outputs
  o(o) : number  round down(1)

table j(j)
policy first
| 種別 | -> o(o) : number |
| >=5  | 1                |
| -    | 0                |

Swift と Java が同じに綴る二つの名前:

rule 定額の送料(flat_fee) v1

inputs
  数量(qty) : number  range >=0 <=10

outputs
  送料(fee) : money[USD]  round down(1USD)

define 基本料金(base_fee) : money[USD] = 3USD
define 追加料金(baseFee) : money[USD] = 2USD

table 数量ごとの送料(fee_by_qty)
policy unique
| 数量 | -> 送料  |
| <=5  | 基本料金 |
| >5   | 追加料金 |

SQLite が一つの列として読む二つの名前:

rule 少額の送料(small_fee) v1

inputs
  数量(qty) : number  range >=0 <=10

outputs
  送料(fee) : money[USD]  round down(1USD)

define 基本料金(afee) : money[USD] = 3USD
define 追加料金(aFee) : money[USD] = 2USD

table 数量ごとの送料(fee_by_qty)
policy unique
| 数量 | -> 送料  |
| <=5  | 基本料金 |
| >5   | 追加料金 |

PostgreSQL が一つの名前に切る二つの長い名前:

rule 春の送料(spring_fee) v1

inputs
  数量(qty) : number  range >=0 <=10

outputs
  送料(fee) : money[USD]  round down(1USD)

define 春のキャンペーンが始まる前に受けた少ない注文の送料その一 : money[USD] = 3USD
define 春のキャンペーンが始まる前に受けた少ない注文の送料その二 : money[USD] = 2USD

table 数量ごとの送料(fee_by_qty)
policy unique
| 数量 | -> 送料                                                  |
| <=5  | 春のキャンペーンが始まる前に受けた少ない注文の送料その一 |
| >5   | 春のキャンペーンが始まる前に受けた少ない注文の送料その二 |

Ruby が定数として読む名前:

rule 基本の送料(base_fee) v1

inputs
  数量(qty) : number  range >=0 <=10

outputs
  送料(fee) : money[USD]  round down(1USD)

define 基本料金(Base) : money[USD] = 3USD

table 数量ごとの送料(fee_by_qty)
policy unique
| 数量 | -> 送料  |
| <=5  | 基本料金 |
| >5   | 2USD     |

生成したコードが自分で使う名前:

rule 送料と記録(fee_and_trace) v1

inputs
  数量(qty) : number  range >=0 <=10

outputs
  送料(fee)   : money[USD]  round down(1USD)
  記録(trace) : number  round down(1)

table 数量ごとの送料(fee_by_qty)
policy unique
| 数量 | -> 送料 | 記録 |
| <=5  | 3USD    | 1    |
| >5   | 2USD    | 2    |

_ だけの名前:

rule 下線の手数料(underscore_fee) v1

inputs
  数量(qty) : number  range >=0 <=10

outputs
  手数料(fee) : money[USD]  round down(1USD)

define _ : money[USD] = 3USD

table 数量ごとの手数料(fee_by_qty)
policy unique
| 数量 | -> 手数料 |
| <=5  | _         |
| >5   | 2USD      |

関係するコード: E009, E011, E034

W115

warning — どの要素もこの判定にはなりません

いつ出るか。 fold にその判定の行き先があるのに、表のどの行もその判定を出さないとき。E024 の裏返しで、こちらは穴ではなく、どの要素も届かない行き先です。たいていは書き間違いではなく、表のほうが変わった跡です。

直し方。 表の行を見直すか、その行き先を消してください。どちらが正しいかは表のほうを読まないと決まりません。

最小の再現:

rule t(t) v1

enum v(v) = a(a) | b(b)

elements xs(xs)
  k(k) : money[円, incl_tax]  range >=0円 <=10円

outputs
  r(r) : money[円, incl_tax]  round down(1円)

table j(j)
policy unique
| k | -> d(d) : v |
| - | a           |

fold d over xs
  a -> take_first k
  b -> next
  empty -> 0円
  exhausted -> held

関係するコード: E024

W114

warning — 未確認の重なり: 両方に当てはまる入力が有り得ます

いつ出るか。 policy unique の表で二行が重なりうるが、それを実際に起こす入力を構成できず、実現不能の証明もできなかったとき。導出が入力を共有する形と、真偽の define の中の閾値は、消去が決めるようになったのでここには落ちてきません。残るのは、消去が有理数の上で解いているために決まらない形です。下の最小の再現の 倍 は必ず偶数なので 5円 ちょうどにはなりませんが、有理数には 2.5円 があります。不等式の数が上限(400 本)を超えた場合と、単位をまたぐ場合も同じです。どれも「証明できなかった」という意味で、「起こりうる」という意味ではありません。上流の表がその値を出す行の条件と導出の組み合わせでしか重ならない対は、検査がその組み合わせを読んで重なりから外すので、ここには来ません。

直し方。 その条件を同時に満たす入力が存在するなら、行を直してください(出力が違うので、当てはまれば矛盾です)。存在しないなら、このままで構いません。生成コードには、万一その条件に当てはまる入力が来たとき黙って先の行を選ばずエラーを返すガードが入ります。

最小の再現:

rule t(t) v1

inputs
  a(a) : money[円]  range >=0円 <=10万円

outputs
  r(r) : bool

derive 倍(d) : money[円] = a + a  range >=0円 <=20万円

define 上(up) : bool = 倍 >= 5円
define 下(dn) : bool = 倍 <= 5円

table j(j)
policy unique
| 上    | 下    | -> r(r) : bool |
| true  | -     | true           |
| -     | true  | false          |
| false | false | false          |

関係するコード: E105, W105, E109

W901

warning — 鍵がファイルに書かれています

いつ出るか。 規則のどこか(文字列でもコメントでも)に、鍵の形の値があるとき。調べる鍵は、AWS のアクセスキー ID、GitHub・Slack・Stripe・OpenAI・Anthropic・Google の鍵やトークン、Slack の Incoming Webhook の URL、PEM の秘密鍵で、どれもプロバイダーが接頭辞や形を決めているものです。ritsu のどの言語も同じ決まりで調べます。診断には鍵の種類と、接頭辞と、長さだけを出し、鍵そのものも、その行も出しません。

直し方。 鍵はコードが動くところ(環境変数、プラットフォームの接続やシークレットの置き場)に置き、そこから読んでください。本物の鍵なら、まずプロバイダーで無効にしてください。ファイルから消しても、リポジトリの履歴には残ります。テスト用の値なら、同じ行のコメントに ritsu: test secret と書いてください。

最小の再現:

rule 席数(seats) v1
# 数を読んだときの Google Sheets の API キー: AIzaSyD-ritsu-fake-key-for-tests-000000

enum 種類(kind) = 講習(workshop) | 講演(talk)

inputs
  催しの種類(event_kind) : 種類

outputs
  席(needed) : number  round down(1)

table 選ぶ(pick)
policy unique
| 催しの種類 | -> 席 : number |
| 講習       | 30             |
| 講演       | 80             |

E074

error — from sum・from max・from min か elements … from の形が違います

いつ出るか。 from sum|max|min に of <要素のフィールド> が無いとき、from max・from min に empty <値> が無いとき、empty の値が入力の型の値でないか、入力の範囲の外にあるとき、of や empty をそれを取らない from に書いたとき(empty が要るのは max と min だけです。合計なら 0、件数なら 0 件に決まっています)。また、elements <名前> の後ろに from <shape の名前>.<並び> 以外のものを書いたとき、契約から取る並びのフィールドに from が無いとき、契約から取らない並びのフィールドに from があるとき、要素のフィールドの from が要素の中のパスでないとき。

直し方。 形を直してください。from max 注文.lines of amount empty 0円 のように書きます。empty は見る要素が一つも無いときの入力の値で、何にするかは業務の判断です。並びを契約から取るなら elements 明細 from 注文.lines と書き、フィールドごとに、要素の中のどこから読むかを from qty のように書いてください。並びを呼び出し側が組み立てて渡すなら、フィールドの from を消してください。

最小の再現:

rule t(t) v1

shape 注文(order) = jsonschema "order.json" "#/$defs/Order"

inputs
  最高額(top) : money[円]  range >=0円 <=1000円  from max 注文.lines of amount

outputs
  x(x) : bool

table 表(t1)
policy unique
| 最高額 | -> x |
| -      | true |

隣に置く order.json:

{"$defs":{"Order":{"type":"object","required":["lines"],"properties":{"lines":{"type":"array","maxItems":10,"items":{"type":"object","required":["amount"],"properties":{"amount":{"type":"integer","minimum":0,"maximum":1000}}}}}}}}

関係するコード: E120, E121, E122, E022

E070

error — 乱数の入力か確率の主張の形が違います

いつ出るか。 random を付けた入力が引けないとき。引けないのは、範囲の両端の無い数、値の無いことがある入力(?)、日付と文字列、from で呼ぶ側のオブジェクトから取り出す入力(from sum などで取り出す値も、呼ぶ側の値で、引いた値ではありません。random を from の前に書いても後ろに書いても同じです)、machine が持ち越す入力です。random を出力か要素のフィールドに書いたとき。chances の形が違うとき:chances の行に何かが続く、下に表が無い、見出しに -> が無い、最後の列が chance でない、出力の列が無い、行が無い。乱数でない入力に列の無いものがある、左に乱数の入力や入力でない名前を書いた、右に出力でない名前を書いた、並びをたどる規則で並びの列に sequence の名前でないものを書いた、確率のセルが 0 から 1 の有理数・率・その比べとして読めないとき。乱数の入力が無いのに chances があるときもこれです。

直し方。 引く数には range >=0 <=13 のように両端のある範囲を書き、数か列挙か真偽を引いてください。chances の見出しは、乱数でない入力の全部の列、->、主張に要る出力の列、最後に chance です。どの値でもよい列には - を書き、確率は 5/14、35%、<=1/100 のように書きます。

最小の再現:

rule t(t) v1

inputs
  roll(roll) : number  random

outputs
  r(r) : bool

table j(j)
policy unique
| roll | -> r(r) : bool |
| <5   | true           |
| >=5  | false          |

関係するコード: E073, E133, E108

E073

error — 重みで選ぶ畳み込みの形が違います

いつ出るか。 take_weighted に by が無いとき、draw の行が二つあるとき、take_weighted の無い畳み込みに draw の行があるとき。重みで選ぶ畳み込みが一つの規則に二つあるとき、その腕に next と take_weighted のほかの腕があるとき、重みが number でないか負になりうるとき、draw の行が無いとき、draw が指す値が、random を付けて範囲が 0 から始まる number の入力でないとき。

直し方。 腕 take_weighted <値> by <重み> と、行 draw -> <乱数の入力> を一行書き、指す入力は range >=0 <=<上限> の random な number にしてください。重みは 0 以上の整数です。選ぶのが二回要るなら、規則を二つに分けます。

最小の再現:

rule t(t) v1

enum v(v) = skip(skip) | pick(pick)

elements os(os)
  ix(ix) : number  range >=1 <=9
  ok(ok) : bool
  w(w)   : number  range >=0 <=10

inputs
  roll(roll) : number  range >=0 <=99  random

outputs
  p(p) : number  round down(1)

table j(j)
policy unique
| ok    | -> v(v) : v |
| true  | pick        |
| false | skip        |

fold v over os
  skip      -> next
  pick      -> take_weighted ix by w
  empty     -> 0
  exhausted -> held

関係するコード: E021, E070

E133

error — 確率の主張が成り立ちません

いつ出るか。 chances の行の確率が、行の入力のセルに当てはまる乱数でない入力のある組み合わせで、乱数の入力を一様に引いたときの確率と違うとき(比べる形なら、それを満たさないとき)。その組み合わせと、そこでの確率が付きます。確率は、乱数の入力の点を数えた正確な有理数です。

直し方。 表が正しいなら主張を直してください。主張のほうが業務として正しいなら、表の行を直してください。

最小の再現:

rule t(t) v1

inputs
  roll(roll) : number  range >=0 <=9  random

outputs
  r(r) : bool

table j(j)
policy unique
| roll | -> r(r) : bool |
| <3   | true           |
| >=3  | false          |

chances
| -> r | chance |
| true | 1/3    |

関係するコード: E070, W129, E107

W129

warning — 確率の主張を予算の中で決められませんでした

いつ出るか。 答えが乱数の入力の式で区分の中で変わるところや、乱数の入力とほかの入力を一緒に読むところで、点を一つずつ評価する数が、主張一つの予算(--budget の 50 分の 1、既定で 100 万点)を越えるとき。並びが読めないとき、規則が矛盾する点があるときも、決めずにこれを出します。決められない主張は、成り立つとも成り立たないとも言いません。

直し方。 行の乱数でない入力のセルを狭めるか、--budget を上げてください。

最小の再現:

rule t(t) v1

inputs
  roll(roll) : number  range >=0 <=999  random
  a(a)       : number  range >=0 <=9999

outputs
  r(r) : bool

derive d(d) : number = roll - a  range >=-9999 <=999

table j(j)
policy unique
| d   | -> r(r) : bool |
| <0  | true           |
| >=0 | false          |

chances
| a | -> r | chance |
| - | true | >=0    |

関係するコード: E133, E109

W131

warning — 確率の関数は、呼ぶたびに規則を何度も評価します

いつ出るか。 乱数の入力の点を掛け合わせた数が 100 万を越え、生成する確率の関数が、呼ぶたびにその数だけ規則を評価するとき。重みで選ぶ規則で乱数の入力を draw の行だけが読むときは、関数が重みから数えるので出ません。

直し方。 頻繁に呼ぶなら、乱数の入力の範囲を狭めてください。重みで選ぶ規則なら、乱数の入力を draw の行だけが読むようにしてください。

最小の再現:

rule t(t) v1

inputs
  a(a) : number  range >=0 <=999  random
  b(b) : number  range >=0 <=9999  random

outputs
  r(r) : bool

table j(j)
policy unique
| a     | b | -> r(r) : bool |
| <500  | - | true           |
| >=500 | - | false          |

関係するコード: W129, E108

E067

error — 寄与の形が違います

いつ出るか。 見出しが contribution のファイルが、寄与として読めないとき。to の行が無い、二行ある、足す先が読めないか check を通らない。open の付いていない列挙に extend で値を足す、足す先の列挙が別の enums のファイルのもの、ある値を二度足す、順序のある列挙に after の無い値を足す。into の先が開いた値でない、項がどこにも宣言されていないか開いた値より下で決まる。open の付いていない出力を決める表や節を足す、開いた出力を決める表や節が、その出力の最後の定義より下の名前を読む。open の付いていない前提の塊に行を足す、元の値の行を足す。after の輪、二つの寄与が同じ名前、寄与に書けない行(出力、result、apply、機械、たどる並び、列挙、取り込み、出典、契約、制約、確率の主張)、乱数にした入力。

直し方。 寄与が足せるのは、足す先が open で開いた場所だけです。開いていなければ、足す先の作り手に開いてもらうか、apply で読んで自分の規則を書いてください。注に、どこに足せるかが出ます。

最小の再現:

contribution c(c) v1
to "base.rule" signature:9e889c8a59016488

extend kind with z

隣に置く base.rule:

rule base(base) v1

enum kind(kind) = a(a) | b(b)

inputs
  k(k) : kind

outputs
  fee(fee) : number  round down(1)

table t(t)
policy unique
| k | -> fee : number |
| a | 1               |
| b | 2               |

関係するコード: E068, E040, E033, E131

E068

error — 開いた値の形が違います

いつ出るか。 open の行に合わせ方(combine sum・product・max・min)が無いとき、範囲が無いとき、max と min に empty が無いとき、型が合わせ方に合わないとき(足すのは数・お金・量・率、掛けるのは数と率、max と min はそれに温度と音量)、オプショナルにしたとき、項が値の刻みより細かい刻みのとき。範囲は、寄与を全部合わせても値がその外に出ないという約束で、下の表はこの範囲の全体で検査されます。

直し方。 open <名前> : <型> combine sum|product|max|min [empty <値>] range >=… <=… の形にしてください。empty は、項が無いときの答えで、max ならいちばん小さい答え(min ならいちばん大きい答え)として合わさります。細かい項は、値の刻みに丸めてから足してください。

最小の再現:

rule t(t) v1

inputs
  member(member) : bool

outputs
  bonus(bonus) : rate[step 1%]  round down(1%)

table p(p)
policy unique
| member | -> from_member : rate[step 1%] |
| true   | 10%                            |
| false  | 0%                             |

open bonus : rate[step 1%]  combine sum
  from_member

関係するコード: E067, E131

E131

error — 合わせた値が、宣言した範囲を出ます

いつ出るか。 開いた値の項(規則の項と、寄与が足した項)を合わせ方どおりに合わせた値の区間が、open の行の範囲を出るとき。注に、項ごとの区間と、どの寄与の項かと、範囲の外にする入力の例が出ます。範囲は、どの寄与が来ても値がその外に出ないという約束で、下の表はこの範囲の全体で検査されているので、範囲を出た値には、検査されていない答えが返ります。

直し方。 範囲を広げるか(下の表は、広げた範囲で検査し直されます)、寄与が足す項を狭めてください。どちらにするかは業務の判断なので、fix.text はありません。

最小の再現:

contribution c(c) v1
to "base.rule" signature:b10f6ca4271b3f2f

inputs
  promo(promo) : bool

table q(q)
policy unique
| promo | -> from_promo : rate[step 1%] |
| true  | 15%                           |
| false | 0%                            |

into bonus
  from_promo

隣に置く base.rule:

rule base(base) v1

inputs
  member(member) : bool

outputs
  bonus(bonus) : rate[step 1%]  round down(1%)

table p(p)
policy unique
| member | -> from_member : rate[step 1%] |
| true   | 10%                            |
| false  | 0%                             |

open bonus : rate[step 1%]  combine sum  range >=0% <=20%
  from_member

関係するコード: E068, E112, E067

W132

warning — 開いた値の項が、合わせた値を変えません

いつ出るか。 開いた値の項が、どの値を取っても合わせた値を変えられないとき。max で項の値が全部 empty の値以下のとき、min で全部 empty の値以上のとき、sum でいつも 0 のとき、product でいつも 1 のとき。max と min の empty は、項が無いときだけの値ではなく、いつも合わせに加わる出発の値なので、上限を max で書くと、項は黙って効かなくなります。寄与が足した項でも、この規則の項でも言います。

直し方。 max の項が上限を決めるなら、合わせ方を min にしてください(min の項が下限を決めるなら max に)。empty を越える(min なら下回る)ことがある項なら、その値を書いてください。要らない項なら外してください。

最小の再現:

rule t(t) v1

inputs
  plan(plan) : bool

outputs
  limit(limit) : number  round down(1)

table cap_of(cap_of)
policy unique
| plan  | -> plan_cap : number |
| true  | 40                   |
| false | 60                   |

open cap : number  combine max  empty 100  range >=0 <=100
  plan_cap

define limit : number = cap

関係するコード: E068, E131