---
title: 箱と矢印の図を、意味を持つ図に描き直す
description: write-slops の skill の方針で、AI 小説についての記事の図を Claude Code と一緒に描き直した記録。
---

# 箱と矢印の図を、意味を持つ図に描き直す

[AI 小説の足踏み感についての4つの記事](../posts/2026-10-27-why-ai-novel-is-bored.md)には、SVG の図が9枚入っていた。この記事の束は skill を使わずに書かれたものだった。そこで、Claude Code（Claude Opus 5.5）に次のように頼んだ。

> この記事が仮に skill によって作られたものなら、どのような SVG が探求されることになるか。良さそうなものを試行錯誤してほしい。

ここでいう skill は、slops の記事を書くための [write-slops](../.claude/skills/write-slops/SKILL.md) のことだ。図については、位置・大きさ・形・重なり・状態の変化に意味を持たせること、文章を箱に入れて矢印でつないだだけの図は作らないこと、描画結果を見て文章より見やすくなっていなければ直すか外すこと、と書いてある。

この記事は、そこから始まったひとつのセッションの記録だ。

## 元の図は、文章を箱に入れたものだった

9枚を skill の基準で見ると、どれも本文の要点を箱に入れて矢印でつないだ図だった。たとえば記事1の最初の図はこうなっている。

次の図は失敗例として、元のまま残している。

```svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 500 200" width="500" height="200" role="img" aria-label="ひとつの出来事に対して複数の描写ブロックがぶら下がっている様子">
  <g fill="none" stroke="currentColor" stroke-width="1.5">
    <rect x="20" y="75" width="110" height="50" rx="6"/>
    <path d="M130 100h70m-6-6 6 6-6 6"/>
    <rect x="200" y="20" width="160" height="38" rx="6"/>
    <rect x="200" y="81" width="160" height="38" rx="6"/>
    <rect x="200" y="142" width="160" height="38" rx="6"/>
    <path d="M165 100v-61h35m-35 122h35"/>
  </g>
  <g fill="currentColor" font-size="12" text-anchor="middle">
    <text x="75" y="96">一度だけの</text>
    <text x="75" y="114">出来事</text>
    <text x="280" y="44">第1話：現場のくわしい描写</text>
    <text x="280" y="105">第2話：冒頭でのくわしい再描写</text>
    <text x="280" y="166">第5話：悩む場面でのくわしい再描写</text>
  </g>
</svg>
```

「一度だけの出来事」から3つの描写へ線が分かれているが、これは本文の「出来事はひとつなのに、描写のかたまりが何度も作られる」をそのまま箱にしたものだ。図を見ても、本文以上のことはわからない。しかも、ラベルが箱からはみ出して線と重なっているが、元の記事ではそのまま公開されていた。描画して見ていれば気づけた崩れだ。ほかの8枚も同じ作りで、文字列の類似度の図は「類似度：極めて低い」「読者の認知：同じ場面」という2行を箱に入れただけだった。

## 主張を、ひとつの視覚的な性質に結びつける

描き直すときは、各図が言いたいことを1つ決め、それを1つの視覚的な性質に結びつけた。記事1の最初の図はこうなった。

```svg
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 520 250" width="520" height="250" role="img" aria-label="読み進めても作中の時間が第1話の出来事へ何度も戻る様子">
  <g stroke="currentColor" fill="none">
    <path d="M60 30V200H500" stroke-width="1"/>
    <path d="M148 30V200M236 30V200M324 30V200M412 30V200" stroke-width="0.5" stroke-dasharray="2 4"/>
    <path d="M60 170H148V130H236V90H324V50H500" stroke-width="9" opacity="0.15"/>
    <path d="M60 170H190V130H250V170H280V90H340V50H412V170H452V50H500" stroke-width="2.5"/>
  </g>
  <g fill="currentColor" font-size="11">
    <text x="54" y="174" text-anchor="end">裏切り</text>
    <text x="54" y="134" text-anchor="end">移動</text>
    <text x="54" y="94" text-anchor="end">遭遇</text>
    <text x="54" y="54" text-anchor="end">決断</text>
    <g text-anchor="middle">
      <text x="104" y="216">第1話</text><text x="192" y="216">第2話</text><text x="280" y="216">第3話</text><text x="368" y="216">第4話</text><text x="456" y="216">第5話</text>
      <text x="280" y="240">本文を読み進める位置 →</text>
    </g>
    <text x="64" y="22">作中の時間 ↑</text>
    <text x="330" y="40" opacity="0.7">灰色の帯：出来事の順に進んだ場合</text>
  </g>
</svg>
```

縦軸は作中の時間、横軸は本文を読み進める位置だ。灰色の帯は、出来事の順に進んだ場合の動きを表す。太線は、本文が実際に描いている場面だ。帯は右上へ上っていくのに、線は話が変わるたびに「裏切り」の高さへ落ちる。「話は進んでいるのに足踏みしている」という記事の出発点が、線の形として見える。

ほかの図も同じ考え方で作った。

| 図 | 意味を持たせた性質 |
| --- | --- |
| 各話の分量の内訳 | 帯の長さが分量、塗り分けが中身（裏切りの再描写、設定の言い直し、新しく起きること） |
| 削ると台詞が軽くなる | 曲線の高さが読者に溜まる重み。削ると台詞は手前に来るが、低いところで来る |
| 文字列の似かたと出来事 | 段落×段落の行列。文字列で比べると対角線しか塗られないが、出来事で比べると離れた段落同士が塗られる |
| ジャンルによる読まれ方 | 期待の帯から線が落ちれば足踏み、帯と重なれば反芻 |

記事1と記事4では「太線＝本文が描いている時点」「灰色の帯＝読者が期待する動き」を共通にした。そのため、記事4の図は記事1の図の読み方のまま読める。

## 試行錯誤で直したところ

最初の版には、描画してみて初めて気づいた誤りがいくつかあった。

- 削った場合の台詞を、元の台詞より右に置いていた。削れば本文は短くなるので、手前に来るはずだった。
- 一つの図の上下の段で、同じ濃い塗りが別々の意味になっていた。
- 線グラフに入れた網掛けが、期待の帯と同じ灰色で区別できなかった。
- 右寄せのラベルが viewBox の左端で切れていた。

どれも、形として自然に見えるので気づきにくい。詳しくは [skill に沿って図を作り直したときの落とし穴](2026-10-27-writing-slops.md#03-svg-pitfallsmd)にまとめた。

## ブログの上で確かめる

描画の確認には、最初は `rsvg-convert` で PNG にしたものを見ていた。作業用のディレクトリは、ユーザーの指定で `/tmp/html-sandbox` にした。

途中で、ユーザーから記事本体がローカルの `make -C go watch` で `http://localhost:8080/posts/why-ai-novel-is-bored` に表示されていると教わった。そのページの HTML を取得し、本文の部分だけ候補の図に差し替えたファイルを作った。それを headless Chrome でダークテーマとライトテーマの両方で撮影した。

ここで、`rsvg-convert` の白背景では見えなかった問題が2つ見つかった。

- このブログの既定はダークテーマで、`currentColor` の線は白になる。凡例に「黒線」「濃いほど」と書いていたので、見た目と説明が食い違った。凡例は「太線」「塗りの強さ」に直した。
- 束の記事はすべてのメンバーが一つのページに並ぶ。そのため、斜線の `<pattern>` などの `id` が図同士でぶつかりうる。図ごとに別の名前にした。

この2点は、skill にも一行ずつ足した。

## 差し替えて、足りない図を足す

候補の図を記事に組み込むかを尋ねると、ユーザーの指示は「既存の図を差し替える。新しいものならコードブロックを新たに作って挿入する」だった。9枚のうち8枚は1対1で差し替えた。残りの記事2と記事3の2か所には、新しく作った図を当てた。

- 段落を1つ削ると、後ろに「書き直しが要る範囲」が広がる図
- 一括で生成すると後ろほど質が薄れる帯と、章ごとに生成すると毎回前提情報を渡す短い帯の比較

続けて、図がない節で何かを足すとよい箇所を探した。ユーザーからは「SVG にこだわらず markdown の何かでも構わない」と返ってきた。そこで、箇所ごとに形式を選んだ。

- 記事3の「プロファイラにならざるを得ない」の節は、本文自体が「出来事ごと・話ごとの分量の分布」を説明していた。プロファイラの出力はもともと集計表なので、■を並べた markdown の表にした。第3話と第5話の欄はどちらも■■で、表の上では「新しい事実が明かされる再描写」と「ただの重複」を見分けられない。
- 記事3の読者シミュレーターの節には、「第1話の場面をどれだけ覚えているか」の線を3本描いた。人間の読者、章ごとに読ませたモデル、全文を読ませたモデルの3つだ。
- 記事1には2枚足した。1話ずつの見直しの枠を、同じ場面どうしを結ぶ線がまたぐ図と、同じ出来事の並びで間隔だけが違う2本の線の図だ。

新しい図や表はどれも、説明のための模式図や架空の例で、実際の小説を測ったものではない。そこで各記事に一文ずつ、その断りを足した。記事1には、古い図の形に合わせた「ぶら下がっている」という言い回しが残っていたので、新しい図に合わせて書き直した。

## 褒めすぎた文に、冷静な一言を添える

最後に、記事4で恋愛小説を褒めすぎている文に、カッコ書きで冷静な見方を添えた。ユーザーの注文は「うるさ過ぎるほど過剰にはならない頻度で」だったので、4か所に絞った。

たとえば「完璧に機能してしまう」には、「反芻として読めるのは、思い返すたびに主人公の受け取り方が少しずつ変わっている場合だろう」と添えた。「唯一の避難所」には、「唯一」かどうかは確かめていないと添えた。

## 読後メモを、束の最後に足す

次の注文は、「読後の AI からの補足資料みたいなファイルを一つ作って article4.md の後に追加する。参考文献的な感じ。あまり権威付けのようにはならない感じで」というものだった。あわせて、束のメンバーを結合する順番はファイル名順だったか、と聞かれた。

実装を見ると、束のディレクトリは `fs.ReadDir` で読まれていて、これはファイル名順に返す。`README.md` は記事の顔として先頭に来て、残りのメンバーが名前順に続く。"n" は "a" より後ろに並ぶので、`notes-` で始まるファイルなら `article4.md` の後ろに来る。

最初は Claude Code が `notes-from-ai.md` を書いた。物語論の用語、氷山理論、"Show, don't tell"、"Lost in the Middle" の論文、リメランスを挙げ、それぞれ記事と近い点とずれる点を書いた。権威づけにならないよう、冒頭で「記事の主張の裏付けではない」「記憶にもとづいていて原典は確かめていない」と断った。

そのあとで、ユーザーから「git stash の中に別のエージェントが書いたファイルがある。比較して、arXiv を参照しているなら出典を確かめて」と言われた。stash にあった `notes-by-ai.md` は、同じ注文に別のエージェントが応えたものだった。

arXiv の3本（Holtzman ほか "The Curious Case of Neural Text Degeneration"、Liu ほか "Lost in the Middle"、Yang ほか "Re3"）は、arXiv のページで題名・著者・発表先を確かめた。どれも正しかった。要約の中身も、各論文の要旨と合っていた。たとえば Holtzman らの要旨には "bland and strangely repetitive" とあり、メモの「単調で妙に繰り返しの多い文章」と一致する。

2つを並べると、stash 版のほうが記事に深く入り込んでいた。

- Holtzman らの論文が扱う「語句が近い範囲でループする反復」と、記事1の「言葉は違うのに同じ場面を見せられる反復」は層が違う、と指摘していた。記事の3層の区別をそのまま使った指摘だ。
- 芥川「藪の中」を、語り直しそのものが読みどころになる例として挙げていた。語り直しが読者の理解を更新するかどうかが分かれ目だ、とまとめていて、記事4に添えたカッコ書きとつながる。
- 記事3の「プロファイラ」に近い研究や道具があるかは調べていない、と最後に書いていた。

そこで stash 版を本体にし、`notes-from-ai.md` からは "Show, don't tell"（記事2に対応）とリメランス（記事4に対応）の2項目だけを移して、`notes-from-ai.md` は消した。

両方の版で同じ結論が出ていたことは、書き留めておく価値がある。どちらも、物語論には「一度起きたことを何度も語る」ことを指す言葉があり、技法として扱われてきたと書いていた。そして、記事が問題にしているのは反復そのものではなく、誰も選んでいないのに起きてしまう反復のほうだ、と結んでいた。

### ユーザーから一言

> arxivなどを参照として載せる時に読んでいないものを引用することへの忌避感というか恐怖感は残る（AIではなくユーザーとしての自分）。なのでここはclaude が書いたという前提の共有は良いなと思った。

読んでいない論文を自分の文章で引用すると、読んだうえで根拠として差し出している、という意味を帯びてしまう。Claude が書いたと明記した別のファイルに分ければ、同じ文献でも「読み手がたどれる手がかり」として置ける。各項目で何を確かめたか（arXiv の書誌と要旨を見た、記憶だけで書いた）を書き分けておけば、書き手の名前で保証しない形にできる。この扱いは、write-slops の skill にも一行足した。

## 途中で見つけた別の問題

確認のために `make test-go` を実行すると、`TestEmbeddedHumanBundle` が失敗した。このテストは、posts の記事を1件だけと決め打ちしている。AI 小説の記事の束を posts に足した時点から落ちていて、今回の変更より前からの失敗だった。リポジトリの決まりに従って TODO.md に記録し、直してはいない。

## まだやっていないこと

- 記事4の図：一対一の関係では、プロンプトに引き継ぐ要素が増えないことを示す図は作っていない。
- 出典の確認：読後メモのうち、arXiv の3本以外（ジュネット、ヘミングウェイ、「藪の中」、クィラー＝クーチ、キング、テノフ、"Show, don't tell"）は原典を確かめていない。
- ライトテーマ：両方のテーマで撮影したのは、最初の候補の図と落とし穴の記事だけだ。あとから足した図と表は、ダークテーマでしか撮影していない。
- ほかの実装：確認したのは Go 版のブログだけで、MoonBit 版のビューでの表示は見ていない。TypeScript 版は SVG のフェンスを画像として描かない。
