Whiteboard で Claude に描かせたコード解説の図から、関数名 load_atom のリンクをクリックしました。開いたのは、その関数の定義ではなく、関数の途中にある splitn(...) の行でした。

Whiteboard とは、Claude Code や Codex などのコーディングエージェントにシーケンス図や call stack をキャンバスへ描かせ、図の各要素から該当するコード行へ飛べるようにする、オープンソース(MIT ライセンス)のデスクトップアプリです。 開発しているのは YC W26 のチームで(リポジトリは devdotfast/whiteboard)、Show HN で公開されたのは 2026-09-24 です。

Hacker News のスレッドで紹介用の図の正確さを問われた作者は、 Real diagrams are all linked to code, so hallucinations don’t really happen in practice(実際の図はすべてコードに紐付いているので、でたらめは現実にはまず起きない)と答えています1。では、違う場所に飛んだのはツールの不具合なのか、AI のでたらめなのか。

結論から書くと、どちらでもありませんでした。図の中のコードへの参照(延べ 30 件、重複を除いて 22 の行範囲)を Claude に照合させると、誤ったものは 1 件もありませんでした。違う場所に飛ぶように見えた原因は、ジャンプの不具合でも参照の誤りでもなく、リンクの ラベル の付け方でした。以下では、その切り分けの手順と、ラベルをどう書けばよいかを示します。

Geoffrey Litt は Working with AI, it's easy for the loop to run faster than the speed of human understanding.(AI と作業していると、ループが人間の理解の速さを追い越しやすい)と書いています2。AI に図を描かせる道具は、この「理解が追いつかない」問題への答えの一つとして出てきたものです。では、その図を読むときには何を確かめればよいのでしょうか。

検証環境と範囲

  • ツール: Whiteboard v0.1.3(macOS 版。v0.1.3 の公開は 2026-09-26)3
  • 題材: 私が作って公開している Tauri 製アプリ clara の、コミット 421cc57 時点の 全体解説 を 1 枚。差分の無いリポジトリだったため、Whiteboard 本来の用途である差分レビューではありません
  • 図の作成: 図を作ったのは Claude(Claude Code)です。Whiteboard に付属する CLI(whiteboard api)だけで描かせ、Claude Code 用のプラグインは入れていません
  • 範囲外: 意味 diff(AST を使った差分の要約)と判断ログは、差分が無いため一度も動かしていません
  • 実施日: 2026-09-28〜29

用語を2つ決めておきます。「参照」は図や本文に埋め込んだコードへのリンク1本、「行範囲」は(ファイル, 開始行, 終了行)の組です。また、参照先が書いた側の意図と違うことを「誤り」、読む側がクリックして「違う場所だ」と感じることを「ずれ」と呼び、この2語を区別して使います。

Whiteboard の図はどこでコードとつながっているか

Whiteboard の図には、コードとつながる部品が4種類あります。本文中のリンク、シーケンス図のステップ、call stack のフレーム、code peek(コード片の埋め込み)です。このうち、コードへの参照を必ず求めるのは2種類だけです。

部品コードへの参照根拠(Whiteboard のツール定義・執筆指示の原文)
本文中のリンク任意(書式の指定のみ)Link repository code as [label](review-source:head/src/file.ts#L10-L24)
シーケンス図のステップ任意(参照・説明・コード片のどれか1つ)each needs exactly one of source, explanation, or code
call stack のフレーム必須Each frame requires source
code peek必須スキーマで source が必須

参照を持たせるかどうかは部品によって違い、参照の 中身(何行目を指すか、何というラベルを付けるか)は、図を描くエージェントが指定する値で決まります。Whiteboard がエージェントに渡す執筆指示は verified line numbers(確認済みの行番号)を使うよう求めていますが、ラベルの書き方には触れていません。

実装側も見ました(2026-09-29 時点の main ブランチ。v0.1.3 との差分は見ていません)。参照を解析するテスト source-links.test.ts が検査しているのは書式で、行番号が 0 のもの、範囲が逆順のもの、行指定を欠くもの、head / base 以外を指すものなどを弾きます。同じテストには、ラベルだけが違う2本のリンクを同じ参照として扱うケースがあります4。ラベルは参照の一部として扱われていない わけです。ただしこれはテスト・ツール定義・執筆指示から読み取れることで、Whiteboard が公式にそう明記しているわけではありません。

私は Whiteboard を、AI と協業して成果物を作る道具だと受け取っています。正しさを握っているのは AI です。どこへ飛ぶかも AI が指定する値次第で、図とコードが機械的に接続されているわけではありません。

違う場所に飛んだように見えた3本のリンク

ずれて見えたのは、Claude が描いた解説図の「読んでいて気になった点」の節と、「Implementation:コードの読み順」の節にあるリンクです。名前にして2つ(load_atom と lib.rs)、リンクにして3本です(load_atom が2本)。

図の本文には、たとえば次の文がありました。

[load_atom] は splitn(3, "---") で frontmatter を切り出す。YAML の値(タイトル等)に --- が入ると、パースに失敗する。

この [load_atom] の部分がリンクです。3本のリンクは、図に書き込まれた Markdown のリンク記法としては次のとおりです。

[load_atom](review-source:head/src-tauri/src/commands.rs#L125-L128)
[load_atom](review-source:head/src-tauri/src/commands.rs#L122-L122)
[lib.rs](review-source:head/src-tauri/src/lib.rs#L14-L24)

それぞれの飛び先の1行目は、clara のコミット 421cc57 では次の内容です。

リンクのラベル飛び先飛び先の1行目
load_atomcommands.rs 125 行目let parts: Vec<&str> = content.splitn(3, "---").collect();
load_atomcommands.rs 122 行目if file_name.starts_with(&id) && file_name.ends_with(".md") {
lib.rslib.rs 14 行目.invoke_handler(tauri::generate_handler![

関数 load_atom そのものは、commands.rs の 111 行目から始まります。

画面では、load_atom をクリックしたのに、表示されたのはその文の続きで説明している splitn や starts_with の方でした。lib.rs をクリックしたときも、表示されたのは generate_handler! の部分でした。

このとき私は、保存されたデータは正しいのに、表示の段階でジャンプがずれているのだろうと考えました。

ジャンプの不具合ではなかった──2段階の切り分け

切り分けは2段階で行いました。

(1) 全参照の照合。図の中のコードへの参照は延べ 30 件(本文中のリンク 10、call stack のフレーム 10、シーケンス図のステップ 9、code peek 1)で、重複を除くと 22 の行範囲になります。Claude に、22 の行範囲それぞれについて開始行と終了行をソースから表示させ、意図した関数・ブロックの始まりと終わりに一致するかを判定させました。結果は 22 件すべて一致です。

この方法には限界が3つあります。見たのは開始行と終了行で、範囲の中身全体は比べていません。照合したのは図を描いたのと同じ Claude Code の会話の中で、意図を別に記録しておいたわけではなく、描いた本人が照合の時点で判定した自己照合です。そして、ここでの「一致」は Claude が意図した箇所と の一致で、ラベルから読む側が想像する箇所との一致ではありません。AI に確かめさせるときは意見を言わせるより元のデータに戻らせる、という考え方はAI レビューの使いどころを書いた記事でも扱いましたが、元のデータに戻らせても、照合の基準が「書いた側の意図」である限り、読む側のずれは測れません。

(2) 確認用の図。Claude に、4種類の部品(本文中のリンク、シーケンス図のステップ、call stack のフレーム、code peek)を1つずつ入れた確認用の図を作らせました。各参照の横には、正しい飛び先(ファイル・行・その行の中身)を書き添えさせています。私が画面で順にクリックすると、4種類とも正しい場所に飛びました。

ジャンプの仕組みにも、参照の行番号にも問題はありませんでした。違う場所に見えたのは、前の節の3本のリンクの ラベル のせいです。「表示の段階でずれる」という最初の読みは、この切り分けで撤回しました。

「誤り」と「ずれ」の違い

原因は、リンクの向け方と読み方の食い違いです。Claude は、リンクを「その文で言っている箇所」に向けました。「load_atom は splitn(3, "---") で frontmatter を切り出す」という文の load_atom を、splitn の行にリンクしたわけです。一方、読む側の私は、クリックした名前(関数名・ファイル名)の定義や先頭に飛ぶと思っていました。クリックした名前を探してしまうので、ずれているように感じたのです。

作者の主張は「誤り」については当たっていました。ずれは別の種類の問題です。

誤りずれ
何が起きているか参照先が、書いた側の意図と違う参照先は意図どおりだが、ラベルが別のものを名指ししている
今回の件数0 件(22 の行範囲を照合)3 本(読む側が気づいたもの)
行番号の確認で見つかるか見つかる見つからない
Whiteboard が入力時に止めるか書式の誤り(行番号が 0、範囲が逆順など)は止めるテストとツール定義の範囲では、ラベルは検査の対象外

「3 本」は私が画面で気づいたものの数で、全 30 参照を「ずれ」の観点で数え直したものではありません。

ずれは、行番号をいくら確かめても見つかりません。「紐付いているので、でたらめは起きない」は、この試用の範囲では当たっていました。Claude の自己照合で見るかぎり、意図と違う行を指す参照はゼロです。そのうえで、でたらめとは別の種類のずれが残りました。

「コードに紐付けさせる」仕組みは正しく働いていました。延べ 30 件の参照(22 の行範囲)は全部、書いた側の意図どおりの行を指していました。それでも読む側にはずれて見えたので、紐付けの強制が守っているのは「図の正しさ」ではなく「行番号の正しさ」だと私は受け取っています。

リンクのラベルの書き方:飛び先そのものを名指しする

リンクのラベルは、読む側がクリックする前に「どこへ飛ぶか」を予告するものです。だから、書いた側の文脈ではなく、飛び先そのものの名前にするべきだと考えます。

Web アクセシビリティの基準 WCAG 2.2 にも、リンクの文言からリンクの目的が分かるようにする達成基準(2.4.4 Link Purpose (In Context)、2.4.9 Link Purpose (Link Only))があり、その解説文書は provide link text that identifies the purpose of the link(リンクの目的が分かるリンクテキストにする)ことを勧めています5。コードへのリンクを想定した基準ではありませんが、考え方は同じです。

先の文を書き換えると、次のようになります。図に書き込むリンク記法の変更前と変更後です。

<!-- 変更前: ラベルが「文の主語」を指している -->
[load_atom](review-source:head/src-tauri/src/commands.rs#L125-L128) は `splitn(3, "---")` で frontmatter を切り出す。

<!-- 変更後: ラベルが飛び先そのものを指している -->
`load_atom` は [`splitn(3, "---")` の行](review-source:head/src-tauri/src/commands.rs#L125-L128) で frontmatter を切り出す。

逆に、load_atom というラベルのまま関数そのものへ飛ばしたいなら、範囲を関数の定義(111 行目から)に直します。ラベルと範囲のどちらかを、もう一方に合わせればよいのです。

AI に図を描かせるときは、エージェントへの指示に次の1行を足すことを提案します。

コードへのリンクのラベルには、飛び先の行そのものを表す語句を使う。関数名やファイル名をラベルにするのは、その関数の定義全体やファイル全体へ飛ばすときだけにする。

ラベルを直した版で「ずれ」の感覚が消えるかは、まだ試していません。上の指示はずれの原因に対応させた提案で、効果を測ったものではありません。入力に制約はあっても、うまい図を作るには何度か実行して調整する必要がありそうだ、というのが1回の試用での印象です。

よくある質問(FAQ)

Q. Whiteboard の図から違う場所に飛ぶのは、不具合ですか?

A. 確かめた範囲では、登録した行どおりに飛んでいました。参照(延べ 30 件、22 の行範囲)はすべて、図を描いた Claude の意図どおりの行を指していました。違う場所に見えたのは、関数名やファイル名をラベルにしたリンクが、その関数の定義ではなく、文で説明している別の行を指していたためです。

Q. コードに紐付いた図なら、AI が描いたものでも信用してよいですか?

A. 行番号が正しいことと、図が読む人に正しく伝わることは別です。Whiteboard が入力の時点で止めることを確かめられたのは参照の書式の誤りで、行番号が意図どおりか、ラベルが飛び先を名指ししているかは、図を描くエージェントに任されています(2026-09-29 時点のコードとツール定義から読み取れる範囲)。

Q. AI に図を描かせるとき、リンクのずれを防ぐにはどうすればよいですか?

A. ラベルを飛び先の行そのものを表す語句にするよう、指示に1行足します。関数名やファイル名をラベルにするのは、関数全体やファイル全体へ飛ばすときだけにします。ただし、この指示で効果が出るかはまだ測っていません。

まとめ

  • Whiteboard で Claude に描かせた図では、延べ 30 件の参照(22 の行範囲)がすべて意図どおりの行を指していた。それでも、ラベルが飛び先を名指ししていない 3 本は、読む側には違う場所に飛ぶように見えた
  • 参照が正しいかは行番号で決まり、読む人に正しく伝わるかはラベルで決まる。行番号の確認では、ラベルのずれは見つからない
  • Whiteboard が入力時に止めることを確かめられたのは参照の書式の誤りで、行番号とラベルの中身は図を描くエージェントが決めている
  • リンクのラベルは、飛び先そのものを名指しする語句にする。関数名やファイル名をラベルにするなら、範囲を関数全体・ファイル全体にする

図に多少のずれがあったとしても、コードの理解には役に立ちます。トークンは使いますが、図を描かせるためのプロンプトを自分で考えるよりは良いものができたと思っています。

AI エージェントに生成させたコード・説明・図を、チームのレビュー工程にどう組み込むか。確認の観点の設計からご相談に乗ります。お気軽に コンタクトフォーム からご連絡ください。

Footnotes

  1. sidharthkmenon のコメント(Show HN: Whiteboard (YC W26) – An open-source IDE for thoughtful software design) Hacker News、2026-09-24(UTC)。Show HN の投稿者である sidharthkmenon が、紹介用 GIF の図の正確さを指摘した 8organicbits のコメントに返答したもの。引用した1文は同コメントの第2段落。 ↩

  2. Understanding is the new bottleneck Geoffrey Litt、2026-07-02。講演の書き起こし。引用した1文は「A quiz is a speed regulator.」の段落にある。 ↩

  3. Release v0.1.3 devdotfast/whiteboard、GitHub、2026-09-26T03:13:47Z 公開(リリース名は「Review Desktop 0.1.3」)。 ↩

  4. packages/review/src/review-api/source-links.test.ts devdotfast/whiteboard、コミット 3a52207(2026-09-29 に参照した main)。ラベルだけが違うリンク([new label])を既存の参照と同じ id として扱うテストは L33〜35、書式の誤った参照先を弾くテスト(rejects malformed source destinations)は L38〜47。 ↩

  5. Understanding Success Criterion 2.4.4: Link Purpose (In Context) W3C、WCAG 2.2 Understanding Docs。provide link text that identifies the purpose of the link は Intent 節にある。 ↩