壊れて見えた投稿ヒートマップと、別マシンに置き去りだった10コミット
壊れて見えた投稿ヒートマップと、別マシンに置き去りだった10コミット
本番のトップページを開いたまま、直近1年の投稿ヒートマップが壊れているようだから直してほしい、と Claude Code に投げた。 GitHub の草に相当するやつだ。 数えるのは記事側と日記側の両方の合計でいい、とだけ付け足した。 自分しか見ないページなので、注文はそのくらいの雑さでちょうどいい。
壊れていません、という答えが返ってくるとは思っていなかった。
草は何本出ていたか
本番の描画を確認させたら、草はふつうに出ていて1658本と表示されていた。 直近1年の md ファイルは1729件ある。 数としては妥当だ。
それでも2025年の8月から11月あたりが薄いのが引っかかった。 月ごとの実データと突き合わせさせたところ、8月と9月が空白なのは記事が0本だからだった。 10月が34本、12月が212本、直近の7月が375本。 グラフの濃淡はそのまま実数をなぞっている。
途中で MCP 側のブラウザが不整合になって止まった。 about:blank だけを抱えた自動操作用の Chrome が残ったままプロファイルを掴んでいた。 自分が普段使っている Chrome とは別プロセスなので、その残骸だけ落として繋ぎ直させた。
ローカルの空白
そもそも「壊れている」と判断した理由は、手元でも草が見えていなかったからだ。
こちらは dev サーバーが落ちていた。 起動させたら本番と同じ1658本が出た。 待ち時間には草グラフのユニットテストも確認させている。
合計に記事と日記の両方が入っているかどうかは、内訳を出させて確かめた。 指定した仕様どおりに数えられていた。
これで終わるはずだった。
カードが1枚しかない
ローカルの画面を眺め直して、別のことに気づいた。 記事(アーティクル)と日記(ダイアリー)は分けたはずなのに、カードが記事のぶんしか出ていない。 なぜこの差がローカルで生まれるのかが分からなかった。
調べさせたら、ローカルが origin/master より10コミット遅れていた。 差はローカルで生まれたのではない。 記事と日記を分離した作業がまだこの端末に来ていないだけだった。
そこで思い出した。 あのマージはこの Mac でやっていない。 Windows のノートPCをもう1台持っていて、あちらで PR をマージしたのだった。
だとすると、もう一つ確かめたいことが出てくる。 Cloudflare に上がっているのは、間違いなく master なのか。
本番に上がっているのはどのツリーか
master ではなかった。
deploy:cloudflare は、ローカルでビルドして wrangler pages deploy dist を直接叩く形になっている。
GitHub Actions は3本あるが、どれもサイト本体を push で自動デプロイするものではない。
本番に反映されるのは、デプロイを実行した端末の作業ツリーそのものだ。
今回は Windows 側が PR #71 をマージしたあとにデプロイしたので、本番だけが先に新しくなっていた。 手元の Mac には、その10コミットがまだ届いていない。 本番のほうが進んでいる状態を「本番が壊れている」と読み違えていたわけだ。
取り込みで衝突した1207行
同じ時刻に、別のセッションで日記生成のコマンドを回していた。 記事を書いている最中に足元のリポジトリを動かせば、そちらを巻き込みかねない。 安全側でやってほしい、と条件を付けた。
その心配は要らない、という説明が返ってきた。 pull はこの Mac の中だけで完結して、リモートにも Windows 側にも影響しない。 分岐もしていない(ahead 0 / behind 10)ので、素直な fast-forward で入る。
手順としては、svgManifest を書き換え続ける dev サーバーを先に止め、編集中のファイルをスクラッチパッドへ退避してから stash させた。 取り込み自体はそのまま通った。
引っかかったのは stash を戻したあとだ。
svgManifest.json だけがぶつかって、衝突マーカーが1207個入った状態になった。
JSON としては壊れているので、dev もビルドも通らない。
ただしこれは apps/web/scripts/generate-svg-manifest.mjs が吐く生成物だった。
作り直せば済む。
再生成させたら1207エントリで JSON も妥当な形に戻った。
そのあとに、全1207行が差分になっているのが気になった。 Mac と Windows で生成結果が変わるなら、この先も毎回ぶつかることになる。 中身を見させたら、差分の正体は全部 mtime だった。 チェックアウトし直したぶん更新時刻がずれただけで、中身は同一だ。
取り込み後のローカルは、本番と同じ「記事」「デイリーブログ(開発日記)」の2枚構成になった。
新設された /diary を含めて、全ページが200を返している。
タイムライン画像と統計チェーン
同じ日の朝には、Mac で初めて日記生成のコマンドを通していた。
日記本体はできあがってブラウザ確認まで終わっていたが、そのあとのデータチェーンとコミットが残っていた。 これは途中で止まっているのかと聞いたら、そのとおりだと返ってきた。
そこで2つ決めた。 タイムライン画像は1行直して通し、コミットまで持っていく。 統計まわりのチェーンはこの日はスキップする。
タイムライン画像のほうは、Playwright 同梱の chromium が428K しかなく壊れていた。 ダウンロードがハングしたまま止まっている。 入れ直させても同じ428K で再びハングした。 同梱ブラウザは諦めさせて、システムの Chrome を使う形に1行で切り替えさせた。 PNG が出て、朝と夜に作業が固まっているのが一目で見えた。
1行で通るものは通してコミットまで持っていく。 詰まったチェーンはその日のうちに切る。 Mac へ移したばかりの環境では、この2つの決めごとが一番きれいに収まった。
できなかったこと
一日の終わりに、結局できなかったことは何かと聞いた。
返ってきたのは4つ。 メールの送信そのもの、PDF の添付、2つのアカウントへのアクセス、そして Mac のスリープ設定の変更。 どれも権限や接続の制約によるもので、作業の失敗ではない。
メールについては、繋がっている Gmail のコネクタに送信ツールが存在しない。 検索も下書きの作成も更新もラベル操作もできるのに、送信ボタンに相当するものだけがない。 だから下書きまでを作らせて、最後は自分で押すことになる。
できたことより、この一覧のほうが翌日の役に立つ。
残ったもの
壊れていると思って調べさせたのに、ヒートマップの側に壊れたところは一つもなかった。
見つかったのは、落ちていた dev サーバーと、取り込んでいない10コミットと、「master がそのまま本番になっている」という自分の思い込みの3つだ。 最後のひとつが一番厄介で、端末を2台使い分けている限りは今後も同じ勘違いをする。 デプロイした端末の作業ツリーが本番になる、という事実のほうを覚えておくしかない。