退避ジョブがJSONを残し、自動追従を止めていた
今回やったこと
画像の原本を定期退避するジョブに、JSONの付属ファイル(サイドカー)をリポジトリへ回収する役割が加わった。ところが回収後も元のチェックアウトにJSONを未追跡ファイルとして残していたため、次の自動更新が止まることがあった。回収処理の最後に、リモート側へ同じ内容が入ったと確認できたファイルだけを片付ける仕組みが追加された。
この記録では、画像とJSONを同じ「rawファイル」として一括処理しない理由と、消してよい条件をどう限定したかを整理する。対象の実装は scripts/raw_masters_push_drip.sh と scripts/lib/sidecar_sweep.sh、説明資料は docs/shared_article_asset_manual.md にある。
画像とJSONでは、正本の置き場所が違う
raw/ には画像とJSONが並ぶことがある。しかし、同じフォルダにあることは同じ保存方針を意味しない。画像原本は生成した機械にだけ存在する状態を前提にし、R2へ退避する。Gitに入れるのは画像そのものではなく、所在を示す索引である。一方、prompts.json と sources.json は後続の画像処理が読む入力契約なので、リポジトリで追跡する。
| raw内のファイル | 正本 | ドリップ処理の扱い |
|---|---|---|
画像(例: featured.png) | R2 | R2へ退避し、索引を更新。画像はGitに入れない |
prompts.json / sources.json | Git | ファイルの中身を回収し、変更としてPRに載せる |
この区別を誤ると、JSONが別の機械へ届かず処理の入力が欠ける。逆に、画像までGitへ入れると、原本の所在をR2へ集約する設計から外れる。ファイルの拡張子だけではなく、後続工程が何を読み、どこを正本にするかで扱いを決める必要がある。
回収後に残ったファイルが、次の更新を塞ぐ
従来の回収は、未追跡のJSONを使い捨てworktreeへコピーしてPRにする一方、元のチェックアウトにも同じJSONを残していた。PRがマージされると、リモートではそのパスが追跡済みになる。ローカルには同じパスの未追跡ファイルが残るため、次の git merge --ff-only は「未追跡ファイルを上書きする」と判断して止まる。
実装コメントには、2026年9月29日の回収で3件がマージされた後、同日のauto-pull(回収から約16分後)で3件とも同一blobとして退避処理に入った記録がある。ファイルの内容が失われたわけではない。しかし、回収が成功するたびに自動更新側が一度余分な退避・照合・破棄を行う状態だった。後始末を別の工程へ押しつけるより、回収した側が安全に片付けられる条件を明文化する方が筋が通る。
削除条件を「同じ内容がリモートにある」に絞る
追加された sidecar_sweep.sh は、未追跡の raw/prompts.json と raw/sources.json だけを列挙する。PRを作ったことやコミットしたことは、元ファイルを消す根拠にしない。PRがマージされなければリモートに内容がないからだ。処理は更新済みの origin/main を見て、同じパスのGit blobとローカルファイルから計算したblobが一致した場合だけ削除する。
未追跡のJSONを回収
→ PRとして送る
→ origin/mainを更新
→ 同じパスのblobを比較
一致: ローカル原本を片付ける
未マージ・内容違い: 原本を残して次回に再確認
中身が1バイトでも違えば、機械はどちらが新しいかを決めない。変更後の原本を残し、次回の回収へ渡す。シンボリックリンクも通常ファイルと同じ比較にしない。Gitが保持するリンク先文字列と、リンク先ファイルの内容を取り違えないためである。画像ファイルはこの掃除の対象外であり、R2退避の方針を維持する。
片付け前にfetchできなかった場合も削除しない。参照が古ければ、マージ済みの内容をまだ確認できない可能性がある。後続の同期処理で追跡ファイルとして戻る経路を残すことで、ローカルから消した直後に内容が永久に失われる事態を避ける。
やってみて分かったこと
「回収したから元を消す」という順番では、PRがマージされなかったときに原本を失う。「安全のため元を残す」だけでは、マージ後の自動更新を何度も塞ぐ。必要なのは削除を避けることではなく、削除を許す証拠を内容単位で確認することだった。
画像とサイドカーで正本を分け、JSONはマージ後の同一blob確認を出口にする。この形なら、未マージや更新競合では原本を残し、確認できた分だけ次の自動更新に道を譲れる。バックアップや同期の処理では、コピーの成功だけでなく、コピー元をいつ片付けるかまで一つの手順として設計する必要がある。
更新履歴
- 2026-10-09: 初稿。