朝、コーヒーを淹れながら Crashlytics のダッシュボードを開くのが、ここ数年の習慣になっています。前夜に上がった新しいクラッシュが赤い数字で並んでいると、まだ眠い頭でも一気に目が覚めます。2014年から個人でアプリを作り続けて、いま運用している壁紙アプリは4本、累計のダウンロードは5,000万に届きました。数が増えるほど、自分一人で全部のクラッシュを追うのは現実的ではなくなってきます。
Antigravity を使い始めてから、この「朝のクラッシュ確認」の中身が少しずつ変わってきました。スタックトレースをそのまま渡して原因を絞ってもらうようになって3週間ほど経ちます。任せられる部分と、最後まで自分で握っておくべき判断がだいぶ見えてきたので、実際の作業の流れに沿って残しておきます。
なぜスタックトレースを AI に渡そうと思ったか
きっかけは単純で、似たようなクラッシュに何度も同じ調べ方をしている自分に気づいたからでした。Crashlytics の画面でスタックトレースを開き、どのフレームが自分のコードか目で追い、該当箇所をエディタで開いて前後を読む。この一連の動きは、慣れているぶん退屈で、しかも数が多いと後回しにしがちです。
宮大工だった祖父たちは、木の節やねじれを一本ずつ手で確かめてから鉋をかけていました。手を動かして確かめること自体が一つの信心だ、という感覚が私のなかには残っています。クラッシュを一件ずつ潰す作業も本来そういうものだと思うのですが、退屈さに負けて雑になる瞬間がある。その雑になる部分こそ、AI に下調べを任せて、自分は判断に集中したいと考えました。
実際にやっている渡し方
私のやり方はとても素朴です。Crashlytics でクラッシュを開き、スタックトレースと、影響を受けたデバイス・OS バージョン・発生回数をコピーします。そのまま Antigravity のエージェントに貼り付けて、リポジトリを開いた状態で次のように頼みます。
このクラッシュのスタックトレースを渡します。
- 該当しそうな自分のコードのフレームを特定してください
- なぜこのクラッシュが起きるのか、考えられる原因を複数挙げてください
- まだ修正は書かないでください。原因の仮説だけ先に見せてください
[ここにスタックトレースを貼る]最後の一行が肝心でした。最初の頃は「直して」とまで一気に頼んでいたのですが、原因の見立てが浅いまま修正コードが出てきて、結局自分で読み直す羽目になりました。仮説を先に出させて、私が納得してから修正に進む。この二段構えにしてから、手戻りがはっきり減りました。
たとえば、ある壁紙アプリで配列の範囲外アクセスが出たときは、Antigravity が三つの原因候補を挙げてきました。
// クラッシュしていた箇所
let item = wallpapers[selectedIndex]
// Antigravity が挙げた仮説
// 1. リフレッシュ中に wallpapers が空配列に置き換わり、古い selectedIndex が残った
// 2. フィルタ適用後に配列が縮んだのに selectedIndex を更新していない
// 3. ページング読み込みの途中で削除イベントが入った実際の原因は2番目でした。フィルタ機能を後から足したときの考慮漏れです。仮説の出し方が具体的だったおかげで、自分のコードのどこを見ればいいかすぐ分かりました。
ぶつかった壁
最初に困ったのは、難読化されたスタックトレースをそのまま渡しても、AI も私も読めないことでした。Swift のリリースビルドはシンボルが落ちているので、dSYM を使って復元(symbolicate)しておかないと、フレームがただのアドレスの羅列になります。ここは Crashlytics 側で自動シンボル化が効いていれば問題ありませんが、dSYM のアップロードが漏れていたバージョンのクラッシュは、人間が読める情報がほとんどありませんでした。Antigravity に渡す前に、まず自分のビルド設定を整える必要があったわけです。
もう一つは、AI が「直しすぎる」傾向です。範囲外アクセスを防ぐために、頼んでいないのに配列アクセスを全部ガード節で包む書き換えを提案してくることがありました。安全側に倒すのは悪いことではないのですが、根本原因(selectedIndex の更新漏れ)を直さずに症状だけ抑える修正は、後で別の不具合を呼びます。「症状を隠す修正ではなく、原因を直す最小の変更にしてください」と毎回添えるようにしています。
三つ目は再現性です。Crashlytics の回数が多くても、自分の手元で再現できないクラッシュは確認が難しい。Antigravity に「このクラッシュを再現する最小のテストケースを書けますか」と頼むと、状態を組み立てるテストを書いてくれることがあり、これが再現の足がかりになりました。直す前にまず赤いテストを作る、という順序を踏めるようになったのは収穫でした。
3週間でできた線引き
任せていいと感じたのは、スタックトレースから自分のコードのフレームを絞る作業、原因の仮説を複数出す作業、再現テストの叩き台を書く作業の三つです。どれも「下調べ」にあたる部分で、ここを速くしてもらえるだけで朝の確認がずいぶん楽になりました。
一方で、どの仮説を採用するか、その修正を本当に入れていいか、リリースに含めるかどうかの判断は、最後まで自分で握っています。アプリの履歴や、ユーザーがどう使っているかの肌感覚は、まだ言葉にしきれていない部分が多く、そこは渡しきれません。4本のアプリはそれぞれ事情が違っていて、同じクラッシュでも優先度が変わります。その重み付けは、12年運用してきた自分の感覚に頼るほうが今のところ確かです。
数字でいうと、この3週間で扱った新規クラッシュは4本合わせて30件ほどでした。そのうち、原因の仮説がそのまま当たって短時間で直せたのは半分強。残りは仮説が外れたり、再現できずに保留にしたりしたものです。打率としては完璧にはほど遠いのですが、当たった半分のぶん、朝に費やしていた下調べの時間は確実に減りました。外れたときも、仮説を読んで「いや、それは違う」と判断する過程で、自分の頭の中が整理されていく感覚があります。AI の見立てを叩き台にして自分の考えを進める、という使い方が私には合っていました。
これから試したいこと
次に整えたいのは、Crashlytics からスタックトレースを取り出してエージェントに渡すまでの手作業を減らすことです。いまは画面からコピーしていますが、影響度の高いクラッシュだけを毎朝まとめて拾ってくる仕組みにできれば、判断により多くの時間を回せます。ただ、ここで一気に自動化を進めすぎると、自分がクラッシュの全体像を肌で感じる機会を失う気もしていて、どこまで自動化するかは慎重に決めたいと考えています。
クラッシュを一件ずつ丁寧に潰していく作業は、地味でも個人開発の土台です。AI に下調べを任せられるようになったぶん、空いた時間で原因の手前にある設計の癖まで見直せるようになりました。同じように少人数でアプリを運用している方の参考になれば嬉しいです。