言ったことを残す
AI に「受注照会の画面を作って。探すのは受注番号と顧客名で、承認ボタンを押したら選んだ行をまとめて確定にする」と頼めば、定義は出てくる。出てきた定義は動く。動くから気づけないのが問題で、あとから3つ困る。
| 困ること | いま何が起きているか |
|---|---|
| 言ったのに入っていない | 頼んだ絞り込みが1つ落ちている。画面は出るので、使う日まで分からない |
| 言っていないのに入っている | 頼んでいない列やボタンが増えている。AI に書かせると必ず出る |
| 未定のはずが決まっている | 「却下の理由は未定」と言ったのに、選択肢が3つ書かれている |
設計書をコードから生成しても、これは消えない
hatake は定義から人の言葉を出せる(explain)。これは生成物なので古くならない設計書で、値打ちはある。それでも上の3つは消えない ── 言ったことが定義に書いていないから。意図・理由・決めた人・決まっていないことは、どこにも残っていない。
だから残すのは1枚だけ。言ったことを機械可読な形で置く。
意図の1枚
定義の隣に <画面id>.intent.yaml を置く。
intent_version: "1.0"
page: order_search
asked: # 人が言ったこと(原文のまま)
- id: R1
text: 受注を受注番号・顧客名・受注日の範囲で探せる
covers: [filter:orderNo, filter:customer, filter:orderDate]
by: 田中
at: "2026-09-08"
- id: R2
text: 承認ボタンを押したら approveOrders を呼んで、選んだ行をまとめて確定にする
covers: [action:approve]
decisions: # 業務の決めごと(理由つき)
- id: D1
text: 出荷済の受注は直せない
why: 倉庫の締めが先に走るため
covers: [field:status]
undecided: # 決まっていないこと
- id: U1
text: 却下の理由の選択肢は未定
covers: [field:rejectReason]
acceptance: # 終わりの判定
- validate --warn-as-error
- run --scenario order.scenario.jsontext は要約しない。 人が言ったまま置く ── 要約した時点で読んだ側の解釈が混ざり、それが言った言ってないの正体だから。
covers が肝。 「その要求が定義のどこに落ちたか」を指す。ここがあるから機械が突き合わせられる。
「決まっていない」を空欄と区別して持つ。 空欄は「まだ聞いていない」と「聞いたけど未定」を区別できない。undecided に書いてあれば、あとで誰かが決めたときに機械が気づける。
突き合わせる
npx -p @hatake-fw/api hatake trace order_search.yamlorder_search: 要求 6 件 / 定義の相手 12 件
言ったのに入っていない(1 件):
・R3「却下の理由を選べる」が指している field:rejectReason は定義にありません=言ったのに入っていない、か、名前が違います。
未定なのに決まっている(1 件):
・U1「却下の理由の選択肢は未定」は未定のはずですが、定義には field:rejectReason が在ります=誰かが決めています。
由来の無い定義(2 件):
・column:memo は、どの要求からも来ていません。
・action:export は、どの要求からも来ていません。
終わりの判定:
・validate --warn-as-error
・run --scenario order.scenario.json一番効くのは由来の無い定義。頼んでいない列やボタンが増えているのは、レビューで一番見つけにくい(動くので)。
| 言うこと | 落とすか |
|---|---|
| 言ったのに入っていない(指す相手が定義に無い) | 落とす(確かに食い違っている) |
| 未定なのに決まっている | 落とす |
| 由来の無い定義 | 言うだけ |
| どこに落ちたか書いていない要求・人が見ていない下書き | 言うだけ |
落とすのを2つに絞ったのは、途中から始められるようにするため。 既にある定義に意図を後から書き始めると、最初は全部が「由来の無い定義」になる。そこで落とす道具は、1日で使われなくなる。全部を落としたいときは --require-intent(CI に置くときはこちら)。
最初の1枚は、指示文から起こせる
意図の器は在っても、書き始めるのが手間では続かない。指示文はもう在るので、そこは機械にやらせる。
npx -p @hatake-fw/api hatake intent --draft --from 指示.md --definition order_search.yaml \
--out order_search.intent.yaml1行が1件になる。やることはそれだけ ── まとめない・言い換えない・順番を変えない。
| 機械が決めること | 決めないこと |
|---|---|
| 行を件に開く(箇条書きは1行1件、散文は句点で分ける) | 何を言ったのか(text はその行のまま) |
| 分類(見出しと合図の言葉だけで決める) | 見出しが無ければ全部 asked(推し量らない) |
covers(業務の言葉が一致した所だけ) | 一致しなければ空。人が書く |
AI への頼み方のテンプレで書いてあると、そのまま分かれる。
## 画面でやること
- 探す: 受注番号・顧客名 → covers: [filter:orderNo, filter:customer]
- 見る: 受注番号・顧客名・金額 → covers: [column:orderNo, column:customer, column:amount]
## 決まっていないこと
- 却下の理由の選択肢は未定 → undecided へ「受注番号」は絞り込みにも列にも在る。探す: / 見る: の書き出しで種類が決まるので、1件が両方を指さずに済む(推し量りではなく、テンプレが決めている字を読んでいる)。
起こしたものは全部 source: ai-draft。
- id: R2
text: "押す: 承認(選んだ行をまとめて)"
covers: [action:approve]
source: ai-draftAI がこう読んだという下書きで、人が見て confirmed: true にするまで未確認のまま。trace はそれを「人が見ていない下書き」として挙げる ── 読まずに使うと、AI の解釈が人の言葉として固まってしまうので。
一緒に「人がやること」も返る。
・5 件を起こしました。**どれも AI が読んだ下書き**です(人が読んで confirmed: true にしてください)。
・R1「受注を探せる画面を作って。」は、定義のどこに落ちるか分かりませんでした(covers が空)。
・誰が言ったか(by)といつ言ったか(at)は指示文からは分かりません。
・action:detail は、どの要求とも言葉が一致しませんでした(頼まれていないか、言い方が違うだけです)。要求を定義から生成してはいけない。 入力は指示文だけ ── 定義から起こせば必ず一致するので、突き合わせが何も言わなくなる。ここは規則として決めてある。
MCP を繋いでいれば hatake_intent がそのまま渡る(instruction に指示文、source に定義)。定義を書く前に呼び、書いたあともう一度呼ぶのが使い方 ── 2回目で covers が当たり、勝手に足したものが出る。
レビューに出すのは1枚
突き合わせの結果は読めるようになったが、人に渡す紙にはなっていなかった。レビューに出すのは1枚がいいので、1枚に刷る。
npx -p @hatake-fw/api hatake design order_search.yaml --intent order_search.intent.yaml \
--out 設計書.md並ぶのはこの順。
| 節 | どこから来るか |
|---|---|
| 言ったこと(要求) | 意図の1枚(人が書く)+ trace の食い違い |
| 読み返し | explain(定義から生成) |
| 決まっていないこと | ask(定義に書けない問い)+ 意図の undecided |
| 書き足したほうがいい所 | advise |
| 終わりの判定 | 意図の acceptance |
| この紙が見ていないもの | 毎回同じ(サーバの中身・画面の見た目・業務として正しいか) |
手で書く欄は1つも無い。 人が書くのは意図の1枚と案件の前書きだけで、この紙は刷り直す ── 手で書く欄を1つ作ると、そこだけが古くなって嘘をつく。刷った日付も入れない(同じ入力なら1バイトも変わらないので、差分がそのまま「何が変わったか」になる)。
渡していない紙の節は消さない。 --intent を渡さなければ「渡されていません」と書く。空の節にすると、読んだ人は「要求が無い案件」「未決は無い」と読むので。意図は画面1枚ごとの紙なので、app: の定義では --page <id> でどの画面かを決める(決めていなければ、決まっていないとそう書く)。
終了コードは動かない。合否は validate(事実)と trace(食い違い)の担当で、この紙はレビューに出すためのもの。
言わないこと
trace が言うのは対応の有無だけ。「意図どおりか」は言わない ── それは定義を読み返して(explain)人が決めること。機械が「意図どおりです」と言い出したら、その時点でこの仕組みは嘘をつく側に回る。
言った言ってないが完全に消えるわけでもない。text は人の言葉なので、解釈の幅は残る。消えるのは「入っていない/勝手に入っている」で、そこは機械が確実に言える。
頼むときの型と同じもの
AI への頼み方の「埋めるだけのテンプレ」は、そのままこの1枚の入力になる。テンプレの「やること・画面でやること・業務の決めごと・決まっていないこと・終わりの判定」が、asked / decisions / undecided / acceptance に順に落ちる。頼み方を決めておくと、設計書が副産物になる。