開発blog-platform

何を作ったか

毎日同じ時刻に太陽を撮り続けて1年分を重ねると、太陽は空に「8の字」を描く。アナレンマと呼ばれる現象だ。地球の公転軌道が楕円であることと、地軸が23.4度傾いていること。この2つが原因らしい、と聞いてもピンとこなかったので、Vueページとして触れるシミュレーターを Claude Code に実装させた。

最終的に行き着いたのは「傾き ON/OFF × 楕円 ON/OFF」のトグルで、4つのプリセットを切り替えながら太陽の軌跡がどう壊れて8の字に組み上がるかを観察できる画面だ。

実装は /blog/analemma-claude に置いた。

既に同名ファイルが居た

着手しようとしたら、apps/web/app/utils/analemma.ts が既にコミットされていた。記憶を遡ると、過去セッションで Codex に同じテーマを投げていたらしい。Codex 版が analemma.ts / analemma-simulator.vue を握っていて、こちらも同じ場所に書き込むと採用判断が混ざる。

そこでファイル名を分けることにした。

  • app/utils/analemma-claude.ts(純粋関数)
  • app/pages/blog/analemma-claude.vue(画面)
  • tests/analemma-claude.test.ts(テスト)

Codex の成果物には一切手を入れず、-claude 接尾辞で完全に独立させる。後で見比べて、よい方を残せばいい。

テスト先行 → 均時差の符号が逆

純粋関数を utils/analemma-claude.ts に切り出してから、Claude Code にテストを先に書かせた。1回目の実行で、均時差(equation of time)の符号が標準的な天文公式と逆になっていることが落ちたテストから判明した。Wikipedia の式に置き換えて再実行、20件全パス。

これは画面を見る前に純粋関数だけで弾けた。SVG を描き始めてからこのバグを踏んでいたら、太陽がずっと変な方向に飛んでいって原因の切り分けに時間を吸われていたと思う。

画面が出てから2つ目のバグ

pnpm dev を 3001 で起動してブラウザを開いたら、観測者ビューでアナレンマが画面外に飛んでいた。原因は2つ。

  1. 方位角の式が北基準になっていて、南基準に直すと符号が反転する
  2. 横軸スケールが小さすぎて、8の字の左右の振れが1ピクセル未満に潰れていた

方位角のテストを追加して23件パスにし、SVG の横軸ピクセル幅を上げて再描画したら、8の字が画面の真ん中で綺麗に閉じた。手が止まった。動くものになった瞬間だった。

「なぜ8の字なのか」が分からない問題

完成スクショを送ったら、ユーザーから次のフィードバックが返ってきた。

地上のカメラはいい、俯瞰カメラもいいとして、結局なんで八の字を描いているのかが、この2つではわからない。傾きがないパターンと正円だったパターンがオンオフになっていれば、太陽がどう見えるかパラメータで調整できるようにしてもらえませんかね。

これは刺さった。「8の字」は2つの効果(傾き+楕円)の合成だから、片方ずつ消してみないと寄与が分離できない。実装を Claude Code に投げ直す。

純粋関数のシグネチャに CelestialOptions を追加して、axialTilt(地軸傾斜)と eccentricity(離心率)をオプション引数として受け取れるようにした。デフォルトは地球の実値(23.44度、0.0167)。テストにパラメータ化のケースを5件足して、30件全パス。

Vue 側も「傾きスライダー」「離心率スライダー」「4プリセット切り替えボタン」を追加した。同時に、サイドバーの目次が3ビューを圧迫していたのを削除して、横並びのまま全部見えるレイアウトに改修した。

4プリセットの結果

プリセット切り替えで実際に見えた挙動を表にした。

プリセット傾き楕円観測者ビューの太陽解釈
AOFFOFF1点に潰れる同じ時刻なら毎日同じ位置(当たり前)
BONOFF縦の直線赤緯が動くので南北だけ往復、東西は不動
COFFON横の振動軌道速度が変わるので東西だけ振れる
DONON8の字縦の往復 × 横の振動が合成されて8の字

A→B→C→D の順でトグルすると、潰れた点が縦線になり、横線が独立に重なり、最後に2つが直交して8の字が組み上がる。「なぜ8の字なのか」が画面に出た。当初の「説明しなきゃ伝わらない」状態から、画面を触ればわかる状態に切り替わった。

Codex 版との回転方向違い

並走している Codex 版(/blog/analemma-simulator)と見比べたら、太陽の回転方向が逆になっていた。Codex 版は時計回り、Claude Code 版は反時計回り。ユーザーから「これ何が違うんですか?」と聞かれた。

原因候補を3つに絞った段階で記事を書いている。

  • 観測者の半球(北半球 vs 南半球)の違いで上下のループの大小は反転するが、回転方向そのものが逆になるかは別問題
  • 時計回りの定義(観測者から見て?真上から見て?)が片方で逆になっている可能性
  • 方位角を東基準で測るか西基準で測るかの差

ここはまだ詰めきれていない。明日、両実装の方位角・赤緯の符号を並べて表にして、どこで反転が起きているかを特定する。AI が書いた天文公式を AI に並べて差分を取る、という構図になる。

振り返り

純粋関数 → テスト → SVG という順番を Claude Code に最初に宣言させたのが効いた。均時差の符号バグは画面を出す前にテストで弾けたし、方位角の符号バグはスクショで違和感を拾ってからテストを追加して固定できた。「画面の違和感を人間が拾い、修正と回帰テストは AI が書く」役割分担が一番回る。

Codex 版とファイル名を分けて並走させた判断もよかった。一方の実装に引っ張られず、最後に2つを並べて比較できる。回転方向の違いも、片方に統一せず両方残したまま差分を取れる状態にできた。AI に同じテーマを2回投げて結果を比較する、という使い方が今後も増えそうだ。

明日やること

  • Codex 版と Claude Code 版で方位角・赤緯・時角の符号を一覧表にして、回転方向反転の原因を1行で書けるようにする
  • プリセット切り替え時にスライダーの値が更新されないバグがないか、各プリセットで axialTilteccentricity の表示値を目視確認する
  • 赤緯と均時差の値を画面下部に数値で出して、スライダーを動かしたときに何が変化しているかを文字でも追えるようにする