既存ユーザーを守る仕組みを入れて、六日と経たずにその仕組みが尽きた — タヌビのキツネ解放
線を引き上げると、越えていた人の足元も動きます。2026年7月25日、キツネの解放条件を1500から2500に上げました。この記事の数字は当時のもので、今はもっと高い値です。
記録日: 2026-07-25
最終更新日: 2026-08-21
最後の一人を「特別な最後」にしたかった 💭
キツネはタヌビで最後に解放される英雄です。
最後の一人なら、たどり着いた時の重みがもう少しあってほしいと思いました。
それで解放条件を1500から2500へ引き上げることにしました。
足し算としては簡単な変更です。定数を一つ書き換えるだけ。
ただ、この変更には受け手が二種類いました。
線を動かすと、すでに越えた人の足元も動く ⚠️
これから遊ぶ人にとっては、条件が少し遠くなるだけです。
問題はもう一方でした。累計1500から2499の区間にいる人たちです。
その人たちはすでにキツネを持っています。条件を満たしたからです。
定数だけ書き換えると、次に開いたときキツネにまた鍵がかかります。
自分のコミットにはこう書きました。リテンションの裏切りだと。
機能の調整のつもりが、既存プレイヤーには回帰として届きます。 😖

一度開いたものは取り上げない 🔒
そこで解放判定を、点数だけで決めるのをやめました。
恒久解放のリストを進捗データに持たせ、点数の条件かリストのどちらかで開くようにしました。
旧条件の値も定数として残しました。1500という数字を捨てずに置いておく必要があったからです。
起動時に、旧条件をすでに満たしていたキャラクターをそのリストへ一度だけ吸収します。
次の目標表示も直しました。すでに持っているキャラは次の目標として出てきません。
解放はローカルのメタ情報です。シードも判定もランキングも動かしていません。

一度だけ、を保証するフラグ 🏷️
吸収は何度も走ってはいけません。走るたびに条件が緩む挙動になってしまいます。
そこで移行済みフラグを一つ持たせました。
フラグが立っていなければ吸収し、立てる。立っていれば何もしない。
読み込みと吸収と保存を一つの関数にまとめ、何度呼んでも結果が変わらないようにしました。
入口は三か所あります。ハブ、ゲーム、図鑑です。どこから入っても一度で済みます。
呼び出し箇所は八か所を更新しました。
境界をテストで固定した ✅
無損失は主張ではなく、証明にしたいところでした。
ちょうど1500の既存ユーザーは吸収されて恒久的に維持される。
同じ1500でも新規なら、まだ鍵がかかったまま。2500が必要です。
1499は吸収されない。境界の一つ手前で線が引かれていることを固定しました。
再実行しても結果は同じ。累計が変わっても再吸収は起きない。
保存後に読み直しても維持され、そのあと累計がゼロになっても消えない。
進捗バーの割合が範囲外に飛ばないことまで見ました。
そして六日と経たず、線をもう一度動かした 📈
7月25日に2500へ上げました。
7月31日、WS20で5500へ再度引き上げています。
間隔は五日と二十三時間ほど。六日にも届きません。
このとき、あの守る仕組みはもう使われませんでした。
一度だけを保証したフラグが、最初の引き上げですでに立っていたからです。
安全にした性質が、そのまま一回性にもなっていた 🙃
フラグは吸収の暴発を防ぐために入れました。その役割は果たしています。
ただ、そのフラグはグローバルに一度きりでした。
つまり「この移行を済ませたか」ではなく「移行というものを済ませたか」を持っていたのです。
二度目の引き上げに対する保護は、自動では効きません。
この限界はコードのコメントに書いてあります。
バージョンを持つフラグへの作り直しは、別作業として提案が残っている状態です。
まだ直っていません。 🙇

おわりに 🏁
既存ユーザーを守る仕組みを作ったこと自体は正しかったと思っています。
学んだのは、その仕組み自体もバージョンを持つべきだったということです。
一度きりで十分だと決めた時点で、二度目の変更を想定から外していました。
線を動かす予定が一度しかない機能は、たぶんそんなに多くありません。
守る側の装置こそ、繰り返しを前提に設計する。次はそこから始めます! 🛡️