Skip to content

v10.16.0🎉 - #7029

Merged
TinyKitten merged 47 commits into
masterfrom
release/v10.16.0
Sep 23, 2026
Merged

TinyKitten merged 47 commits into
masterfrom
release/v10.16.0

Conversation

@TinyKitten

Copy link
Copy Markdown
Member

概要

v10.16.0 の本番マイナーリリースです。アプリの版数を 10.15.1 から 10.16.0 に上げます。

origin/master からの差分は47コミットです。内訳は次のとおりです。

  • 機能・修正・ドキュメントの PR が28件
  • Canary の版数バンプが16件
  • マージコミットが2件(dev←master の同期 dev<-master #6968 と、その版数の競合解消)
  • この PR の版数バンプが1件

利用者向けの新機能として、Google Analytics for Firebase の再導入、乗り換えが必要な行き先の経路検索、iOS の英語の端末内合成(VITS)、AI 相談の応答内の URL のリンク化が入ります。新機能を含むためマイナーリリースにします。

Important

マージ前に、次の2点が本番に反映されている必要があります。どちらも元の PR に書かれている条件です。

変更の種類

  • バグ修正
  • 新機能
  • リファクタリング
  • ドキュメント
  • CI/CD
  • その他

変更内容

新機能

不具合修正(測位)

不具合修正(その他)

挙動の変更・削除

開発者向けツール(DevOverlay・診断ダンプ・GPX)

リファクタリング・テスト

CI/CD

ドキュメント・エージェント向け手引き

同期マージ

  • dev←master 同期マージの取り込み (dev<-master #6968) と、版数の競合解消

版数更新

v10.16.0 をリリース: npm run version:bump 10.16.0 による版数の更新です。

  • package.json / package-lock.json / app.config.ts: 10.15.1 → 10.16.0
  • iOS: CURRENT_PROJECT_VERSION 2923 → 2924(18か所)、MARKETING_VERSION 10.16.0(4か所)
  • Android :app: versionCode 100000787 → 100000789
  • Wear OS :wearable: versionCode 100000788 → 100000790(:app + 1 を維持)

前回のリリース(v10.15.1)と比べると、iOS のビルド番号は 2907 → 2924、Android :app は 100000755 → 100000789 です。差分は途中の Canary の版数バンプの分です。

テスト

リリースブランチの上でコード品質チェックを実行し、すべて成功しました。自動修正は付けていません。依存は npm ci で package-lock.json どおりに入れています(再ロックなし)。

  • npx biome check ./src: 777 ファイル、指摘なし
  • npm run lint: 指摘なし
  • npm run typecheck: エラーなし
  • npm test: 293 suites / 3262 tests がすべて成功。3回続けて実行し、3回とも成功しました。

含まれる各変更は、dev にマージされる時点でレビューと CI を通っています。

リグレッションリスクと緩和

関連Issue

スクリーンショット(任意)

未添付: dev へマージ済みの変更を master へまとめるリリース PR です。この PR 自体の差分は版数の更新だけで、画面は変わりません。

🤖 Generated with Claude Code

github-actions Bot and others added 30 commits September 12, 2026 20:20
* iOSで変位ゲートにより測位配信が途絶える区間を補完測位で更新し続けるようにする

iOSはtimeIntervalが無視され変位ゲート(distanceFilter=10m)だけが配信を決めるため、
地下鉄のようにGPSを失い測位が同じ座標へ張り付く区間では配信が完全に止まり、位置・
最寄り駅・到着判定・ヘッダーがまとめて凍結する。Androidは変位ゲートが0でtimeInterval
が効くため同じ区間でも10秒ごとに届く。これが「Androidでは地下鉄でも更新されるのに
iPhoneでは更新されない」の原因。

変位ゲートを0へ戻す選択は取らない。iOSでは約1Hz配信となり電池を著しく消費するため
実車検証を経て10mが選ばれている(#6470)。代わりに、継続測位の配信が10秒途絶えたときだけ
getCurrentPositionAsyncで測位を取りに行く補完測位をiOSにだけ追加し、Androidが変位に
依らず確保している更新間隔を下回らないようにする。地上走行中は10mを数秒で超えるため
一度も発火せず、#6470が狙った停車中の取りこぼし対策も維持したまま補える。

取得した測位はhandleTrackingLocationへ通すため、重複排除・精度フィルタ・EMA・速度
フィルタの扱いは継続測位と完全に同じになる。応答が返らない取得でガードが解けず補完が
止まらないよう、間隔3回ぶんを超えた要求は見切る。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sZFS43kKpMv5HjadBkF3x

* 補完測位の取得間隔を実測10秒に直し前景・権限あり・非省電力に限定する

ローカルレビュー(Fable)で見つかった4点への対応。

1. 取得間隔が実測20秒だった。固定間隔のタイマーで点検すると、補完測位が取り込んだ
   測位が途絶タイマーを巻き戻すぶん必ず1回空振りし、実際の取得が閾値の2倍まで開く。
   点検を固定間隔から「最後の配信から途絶時間が経つ時刻」への置き直しへ変更し、
   応答を受け取った時点でも次の点検を張り直す。取得間隔を実物の
   handleTrackingLocationごと測る回帰テストを別ファイルで追加した(固定間隔の実装では
   60秒あたり3回しか取得せず落ちる)。

2. 背景で誤発火していた。expo-locationのタスクは前景でだけ測位を即時報告し、それ以外は
   deferredUpdatesInterval(10秒)ぶん貯めてから報告するため、背景では正常時も配信間隔が
   途絶時間以上になり地上でも発火する。加えて一発取得に使われるCLLocationManagerは
   allowsBackgroundLocationUpdatesを立てないので背景では測位を受け取れない。
   useIsAppActiveで前景に限定する。

3. 前景権限が無い利用者(「許可せずに開始」)で取得の失敗を繰り返していた。effect開始時に
   getForegroundPermissionsAsyncで確認し、未許可なら点検を張らない。effectは前景復帰の
   たびに張り直されるため、あとから許可された場合もそこで拾う。

4. 省電力測位プロファイル中は補完測位を動かさない。このプロファイルはiOSで停車中の
   測位休止(pausesUpdatesAutomatically)を許可しており(#6395)、補完測位はその休止を
   そのまま打ち消すため。電池優先という設定の意図を尊重し、省電力中は凍結を許容する。
   選択肢(受け入れて明記/間隔を伸ばす/無効化)のうち無効化をリポジトリオーナーが選択。

あわせて、抽出したuseLocationProfileの参照安定性(崩れると測位タスクが再レンダーごとに
停止→再開する)と、遅延返答の取り込み・端末省電力モードの分岐にテストを追加した。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sZFS43kKpMv5HjadBkF3x

* 補完測位の初回点検を最後の配信時刻に合わせ時計巻き戻しで点検が飛ぶのを防ぐ

CodeRabbitの指摘への対応。権限確認後の初回スケジュールが常に途絶時間ぶん待っていたため、
既に途絶した状態で前景へ戻ったとき(地下でアプリを開き直した等)に取得までさらに10秒遅れて
いた。待つかどうかの判断をcheckへ一本化し、初回は即座にcheckへ入れる。未配信(0)のときだけ
effect開始時刻を基準にして途絶時間ぶん待ち、起動直後に継続測位と一発取得が二重に走るのを
避ける。

あわせて、経過時間が負になる場合(端末の時計の巻き戻し)を途絶として扱う。残り時間として
使うと巻き戻し幅ぶん点検が先送りされ、補完測位が止まる。handleTrackingLocationが
CLOCK_ROLLBACK_TOLERANCE_MSで同じ事故を防いでいるのと同じ理由。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sZFS43kKpMv5HjadBkF3x

* 経過時間の計測を単調増加時計へ移し端末時計の変更で補完測位が乱れないようにする

CodeRabbitの指摘への対応。補完測位の途絶判定・保留見切りはどちらも「経過時間」の判定
なのに端末の時計(Date.now)で測っていた。時計が巻き戻ると残り時間が巻き戻し幅ぶん伸びて
点検が止まり、進むと保留中の要求を早く見切って重複要求を出す。

src/utils/monotonicNow.ts を追加し、記録側(handleTrackingLocation)と判定側
(useLocationHeartbeat)を同じ時計へ揃える。React Nativeはglobal.performanceを必ず
用意するため、performance.nowを使い、無い環境ではDate.nowへ退避する。

あわせて、記録の公開APIを「時刻」から「経過時間」へ変えた(getLastTrackedLocationAtMs
→ getMsSinceLastTrackedLocation)。時刻を返すと呼び出し側が別の時計と引き算できてしまい、
同じ事故を再発させられるため。未配信はnullで表す。

フォールバックでDate.nowが使われる環境では単調性が保証されないため、負の経過時間を
「基準が信用できない」として扱う既存のガードは残す。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sZFS43kKpMv5HjadBkF3x

* 保留中に経過時間が負になっても補完測位の要求を重ねないようにする

CodeRabbitの指摘への対応。取得の応答を待っている間に経過時間が負になると
(monotonicNowがDate.nowへフォールバックした環境での時計の巻き戻し)、保留の判定から
外れて1件目の応答を待たないまま2件目の要求が走っていた。

負でも「取得中」であることは変わらないので保留として扱う。ただし残り時間をそのまま
使うと見切りが巻き戻し幅ぶん先送りされる(応答が返らない要求で補完測位が止まる)ため、
待ち時間は見切り時間で頭打ちにする。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sZFS43kKpMv5HjadBkF3x

* 補完測位の見切りを時計に依存しないタイマーへ移す

CodeRabbitの指摘への対応。保留の見切りを経過時間の計算で行っていたため、
monotonicNowがDate.nowへフォールバックした環境で時計が巻き戻ったまま応答が返らないと、
経過時間が負のままで見切りが成立せず、補完測位が止まる可能性があった。

要求のたびに見切りタイマー(setTimeout)を張り、応答時とアンマウント時に解除する。
見切り時は要求識別子を進めてから次の点検へ入るので、見切った要求が後から返っても
現役の要求のガードは触られない。保留中の点検は何もしない(次を置くのは応答のfinallyか
見切りタイマー)ため、保留の長さを決めるのは時計ではなくタイマーだけになる。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016sZFS43kKpMv5HjadBkF3x

---------

Co-authored-by: Claude <noreply@anthropic.com>
* オンデバイスTTSの既定音声をVOICEVOXの夜語トバリ「明るい」へ変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tVYs6Yu7jchkzxe6hAG2t

* オンデバイスTTS設計書のスタイルIDフォールバック値を実装に合わせる

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011tVYs6Yu7jchkzxe6hAG2t

* 夜語トバリの商用利用条件の記述から断定を外す

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011dvB4KWYMtpLmZXRGVFE6W

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* iOSでリモートTTSが使えない回の英語をVITS(端末内合成)で読み上げるフォールバックを追加

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ErFSmExdT96Yajwmo961xK

* 読めない語があっても端末内蔵TTSへ倒さず読める部分だけ合成する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ErFSmExdT96Yajwmo961xK

* VITSマニフェストでモデルと辞書の役割を検証する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ErFSmExdT96Yajwmo961xK

* VITSで資産削除後のsetup省略と再生開始前エラーの取りこぼしを修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ErFSmExdT96Yajwmo961xK

* iOSでは端末内蔵TTSを使わず読み上げないようにする

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ErFSmExdT96Yajwmo961xK

* VOICEVOXでも資産削除後にsetupを省略して合成が失敗し続ける問題を修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ErFSmExdT96Yajwmo961xK

* iOSで端末内蔵TTSを使わなくなった点を設計書の各所へ反映

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ErFSmExdT96Yajwmo961xK

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: TinyKitten <32848922+TinyKitten@users.noreply.github.com>
`cumulativeIncreaseRef` は正の増加だけを足し込む一方、
`WRONG_DIRECTION_NOISE_TOLERANCE` (10m) 以内の減少は無視して累積を維持していた。
この非対称性により、静止していてもGPSの揺れだけで累積が単調に伸び、
`WRONG_DIRECTION_MIN_DISTANCE` (300m) に到達しうる (#6967)。

累積を「最接近点 (`nearestDistanceRef`) からの正味距離」で測るよう変更する。
無視した小さな減少も起点の更新を通じて距離へ反映されるため、静止中の揺れでは
正味距離が伸びない。連続カウンタ側のヒステリシス (#5934 の意図) はそのまま残す。


Claude-Session: https://claude.ai/code/session_01W43wAgGXf7Sank3yirTJD2

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: TinyKitten <32848922+TinyKitten@users.noreply.github.com>
* DevOverlayに診断情報をクリップボードへコピーするボタンを追加

地下のワープ調査で必要になる値を、画面から読み上げる代わりに丸ごと持ち出せるようにする。
テレメトリは本番で無効、かつ送っているのはlocationAtom(フィルタ後)だけなので、
生の精度・実効設定を取り出す手段が無かった。

ヘッダーのステータスピル横にCOPYボタンを置き、押すと整形済みJSONをクリップボードへ載せる。
含めるのは、フィルタ前後の測位(座標・精度・速度・タイムスタンプ)、精度履歴、ETAの
フェーズとアンカー、次駅と距離、ビルド情報、そして実効設定(max_permit_accuracy /
eta_assist_enabled / オートモード / テレメトリ / バックグラウンド測位)。設定が分からないと
同じ測位でも挙動を説明できないため、座標と必ずセットで持ち出す。

JSONの組み立てはsrc/utils/devDiagnosticsSnapshot.tsへ純関数として切り出した
(DevOverlay.tsxが既に1100行あるため)。タイムスタンプを持たない測位が届いても
例外を出さないよう、ISO文字列化はnullへ倒す。診断情報の持ち出しで落ちては本末転倒なため。

クリップボードはreact-native coreのClipboardを使う。core から切り出され将来削除が
予告されている非推奨APIだが、expo-clipboardの追加はネイティブモジュールの追加になり
Devクライアントのリビルドとロックファイルの更新を伴うため、まずは依存を増やさない。
呼び出しをsrc/utils/clipboard.tsの1関数へ閉じてあるので、移行時はそこだけ差し替えればよい。

パネルのPanResponderはcaptureを使っていないため子のPressableが先にタッチを取り、
展開/折りたたみのトグルとは競合しない。折りたたみ中は上に載るcollapsedOverlayが
タッチを受けるので押せない。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sfi8S4Yvob2sEzib4VUUBs

* クリップボードをexpo-clipboardへ移し非推奨のreact-native Clipboardをやめる

react-nativeのClipboardはcoreから切り出され「将来のリリースで削除する」と予告されている
非推奨API。現時点のRN 0.86.2では動くが、新規に使い始める先としては選ばない。

expo-clipboard@~57.0.2(expoのbundledNativeModulesがSDK 57に対して示すバージョン)を追加し、
src/utils/clipboard.tsの中だけを差し替える。setStringAsyncはPromise<boolean>を返すため、
copyTextToClipboardも非同期にして載せられたかどうかを返す。DevOverlay側は結果を待ち、
実際に載ったときだけCOPIEDを出す。失敗しているのに成功表示を出すと、貼り付けてみるまで
気付けないため。失敗時はCOPYのまま据え置き、例外はwarnで記録する。

ネイティブモジュールの追加なので、Devクライアントの再ビルドが要る。

ロックファイルはnpm 11で生成し、npm ci --dry-runが通ることを確認した。差分は
expo-clipboardの12行のみで他パッケージへの波及は無い。

CodeRabbitの指摘(#6983)への対応。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sfi8S4Yvob2sEzib4VUUBs

* コピー失敗時にCOPIED表示と解除タイマーを落とす

成功で立てた解除タイマーが生きているあいだに次のコピーが失敗すると、早期returnが
表示とタイマーを残したままにしていた。結果として、最後のコピーが失敗しているのに
前回のタイマーが切れるまでボタンがCOPIEDのままになる。「実際に載ったときだけCOPIEDを
出す」という契約と食い違う。

タイマーの解除を成否の判定より前へ出し、失敗時はsetHasCopied(false)して戻る。
成功直後に失敗させる回帰テストを追加した(修正前は失敗する)。

CodeRabbitの指摘(#6983)への対応。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Sfi8S4Yvob2sEzib4VUUBs

---------

Co-authored-by: Claude <noreply@anthropic.com>
* 公開物に書いてよい根拠を定めるPublishing gateを自動化エージェント向け手引きに追加

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* 公開前チェックリストにPublishing gateの秘匿情報と裏取りの項目を補う

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

---------

Co-authored-by: Claude <noreply@anthropic.com>
* テレメトリを本番でオプトイン可能にする場合のリスク評価をドキュメント化

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* テレメトリ本番オプトインのリスク評価にレビュー指摘を反映

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* コンソールテレメトリの送信先が基盤に存在しない事実をリスク評価へ追記

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* リスク評価の未確定な記述を実装とポリシー原文から確定した内容へ置き換え

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* リスク評価から裏付けの無い記述を外し、ビルド設定から確認できる事実に揃える

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* コンソール経路の記述をルータ定義から言える範囲に限定

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* 公開物に書いてよい根拠を定めるPublishing gateを自動化エージェント向け手引きに追加

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* スロットルが位置送信のみに効くことをリスク評価に明記

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* 公開済みの記述の訂正は自己判断ではなく報告と指示を経る規則へ修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* 公開済みの記述を訂正する際の承認対象をpush以外の公開操作にも広げる

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* 訂正の速さを一律に求める記述を削除

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

* AGENTS.mdの変更を別PRへ分離するためこのブランチから取り除く

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01QzKkzvpiWBmFsBJvBTCc2Q

---------

Co-authored-by: Claude <noreply@anthropic.com>
* 公開物の日本語が翻訳調にならないよう文体の指針を手引きへ追加

PR本文が英語の構文をそのまま日本語へ移した文になっており、内容は正しくても
読み手が中身より文の解きほぐしに時間を取られる、という指摘を受けた。

「翻訳調にしない」とだけ書いても直らないので、症状を手掛かりに直せる形にした。
一文への節の詰め込み・無生物主語・名詞句の積み上げ・接続詞の連発・括弧内の列挙・
文体の揺れの6点を挙げ、実際に書き直したPR #6996 の本文からBefore/Afterを2組引いた。
公開前チェックリストにも1項目足した。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* 多義的な動詞を避ける項目を足し、改善例から「効く」を外す

「効く」で何を指しているのか分からない、という指摘を受けた。読み返すと、狙った効果が
出る・読んだ人の行動が変わる・条件で止まる、という別々のことを同じ語で書いていた。

直前に足した改善例(After側)にも「この変更が効くかどうか」と書いており、曖昧な語を
手本として載せる形になっていたので、何が起きるのかを書く文へ差し替えた。併せて
多義的な動詞を避ける項目を足した。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* 文体の指針が適用される範囲を日本語の公開物に限定する

「公開物は日本語で書く」と書いたため、何語で書くかまで決める指示に読めていた。
この手引き自体の見出しは英語主体で、docs/ にも英語の文書がある(android-build-workflows.md
など)ので、既存の文書を否定する形になっていた。

書きたかったのは文体だけなので、対象を「日本語で書く公開物」に限定し、言語の選択には
触れないことを明記した。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

---------

Co-authored-by: Claude <noreply@anthropic.com>
* 補完測位の稼働状態と要求結果を診断ダンプに追加して地下の無配信の原因を切り分けられるようにする

地下で測位が届かない区間は、locationPipelineStatsのどのカウンタも動かないため、
補完測位が要求を出していないのか、出しても測位が得られていないのかが診断から読めない。
要求を出す側で稼働状態・要求数・成功数・失敗数・見切り数・直近の失敗理由を数え、
DevOverlayのダンプへheartbeatとして載せる。

取得失敗の警告は連続の先頭1回に絞られるためログから件数を追えず、稼働状態は
useLocationHeartbeatの早期returnにしか無いので、いずれも判定したその場で記録する。

判定ロジックには手を入れていない。早期returnは理由を返す述語へ切り出したが条件と
その順序は同じで、権限確認の分割も論理は変えていない。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* 補完測位を一発取得から1件で閉じる購読へ変えて地下でも測位を拾えるようにする

iOSの地下で補完測位が一件も測位を得られていない。expo-locationの実装差が原因と考えられる。

getCurrentPositionAsyncはCLLocationManager.requestLocation()で、Appleの仕様では
「If a location fix cannot be determined in a timely manner, ... reports a error.」と
なっており、fixが取れない地下では毎回エラーで終わる。要求精度は理由ではない(同じ
Discussionに「If obtaining the desired accuracy would take too long, the location manager
delivers a less accurate location value rather than reporting an error.」とある)。
一方watchPositionAsyncが使うstartUpdatingLocationは、expo側がlocationUnknown(code 0)を
明示的に無視して待ち続ける(Providers/LocationsStreamer.swift)。継続測位が地下でも
たまにセル測位を拾えているのはこの粘りによる。

補完測位も同じ経路を使い、測位が1件届いたら購読を閉じる。変位ゲートは0で張る。ここへ
来る時点で継続測位のゲート(10m)に届いていないため、同じゲートを張り直しても届かない。

見切り(LOCATION_HEARTBEAT_MAX_PENDING)では購読を明示的に閉じる。一発取得と違い放置すると
測位が回り続けるため。見切った要求へ後から測位が届く経路は無くなるが、閉じた直後に次の
購読を張るので、測位が出た瞬間はそちらが拾う。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* 補完測位の稼働状態がeffectの終了と張り直しで取り残されないよう修正

CodeRabbitの指摘2件。いずれも状態が実態とずれる欠陥で、修正前は追加した各テストが落ちる
ことを確認した。

1. 非稼働の早期returnがcleanupを返しておらず、止まった理由(power-saving等)を残したまま
   画面を離れていた。いま何が止めているのかと読み違えるので、こちらもnot-mountedへ戻す。
2. 権限確認のcatchがcancelledを見ておらず、張り直し前のeffectの失敗が新しいeffectの
   状態をpermission-deniedで上書きしうる。

併せてDevOverlayのコピー経路にもheartbeatの回帰アサーションを追加した。スナップショット側の
テストは値を直接渡して検証するため、DevOverlayが渡し忘れても落ちない。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* iOSの一時的なinactiveを前景として扱い乗車中に補完測位が畳まれないようにする

#6995 の診断を地下で撮ったダンプで、補完測位が running のまま requested だけが 3 まで
進み、succeeded・failed・abandoned が揃って 0 だった。要求は「取得中は次を出さない」
ガードで1件ずつしか出ないので、ガードが2回解けている。解ける経路は応答(succeeded /
failed)・見切り(abandoned)・effect の張り直しの3つで、前2つが 0 である以上、残るのは
張り直ししかない。

張り直しの引き金は useIsAppActive だった。このフックは 'active' 以外をすべて false に
するため、iOS の 'inactive' でも false になる。'inactive' はコントロールセンターや
App スイッチャーを開いた間に入る状態で、アプリは画面に出たまま、測位も前景と同じように
届く。乗車中に一度それを開くだけで effect が張り直され、進行中の要求は結果を残さずに
捨てられていた。

#6969 が背景で補完測位を止めた理由は2つとも背景そのものの性質で、'inactive' には
当たらない。

- 背景では測位が deferredUpdatesInterval ぶん貯めてから報告されるので、正常時も配信
  間隔が途絶時間以上になり途絶と区別できない
- 補完測位が作る CLLocationManager は allowsBackgroundLocationUpdates を立てないので
  背景では測位を受け取れない

そこで判定を useIsAppForeground へ移し、'inactive' を前景として扱う。背景で止める決定は
そのまま維持する。

併せて、捨てた要求(discarded)と片付けの回数(teardowns)を診断に足す。要求を進行中のまま
捨てるとどの結果カウンタにも現れず、requested だけが進むダンプになる。今回それで
「応答が返っていない」のか「返る前に捨てた」のかの判断に一度失敗しているので、同じ
読み違いが起きないようにする。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* 補完測位のinactiveに関する説明をReact Nativeのドキュメントの記述へ合わせる

'inactive'で入る操作を記憶のまま書いていたので、AppStateのドキュメントが挙げている
ものに直す。あわせて「測位が前景と同じように届く」という裏を取っていない一文を外し、
「まだ背景に入っていないので、背景を理由に止める2つの根拠が当てはまらない」という
コードから辿れる書き方にする。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* 補完測位の張り直しの理由を診断へ残して引き金を推測せずに読めるようにする

片付けの回数(teardowns)だけでは引き金が読めない。前景判定が外れたのか、省電力へ
切り替わったのか、ホストが作り直されただけなのかで、次に直す場所が変わる。数から
引き金を推測すると外すので、理由そのものを残す。

張り直したあとの実行で、前回の依存と突き合わせて差分を組み立てる。片付け側からは
新しい値が見えないため、そこでは作れない。画面を離れたときのアンマウントは次の実行が
無いので、teardowns だけが進んで理由は増えない。

判定の元になる AppState も添える。前景判定が外れたときに 'background' だったのか
'inactive' だったのかで意味が変わる。

例: "foreground: true→false / AppState=background"

直近5件だけ残す。乗車1回ぶんを追うには足り、ダンプも埋まらない。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* コメントの「畳まれる」を何が起きるのかが分かる記述へ置き換える

何が起きるのかを読み手が補う必要がある語だった。実際に起きるのはeffectの張り直しと、
進行中の要求が結果を残さず捨てられること。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

* 失効した補完測位の要求の失敗を数えないようにして二重計上を防ぐ

見切った要求(abandoned)と、画面を離れる・稼働条件から外れるときに捨てた要求
(discarded)は、その時点で1件として数え終えている。購読の登録がそのあとで失敗すると
failed にも乗り、1件の要求が2つのカウンタに現れていた。直近の失敗理由も、待ち手の
いない要求のもので上書きされる。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WHAxmgtPiLPieMwexWw9qH

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: TinyKitten <32848922+TinyKitten@users.noreply.github.com>
TinyKitten and others added 17 commits September 21, 2026 11:29
* フィードバックのトリアージ条件を満たすissueから自動で修正PRを出すワークフローを追加

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* 自動修正できないフィードバックは調査を打ち切って理由をissueへコメントするようにした

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* 自動修正が完了しなかった場合も止まった箇所をissueへコメントしてからジョブを落とすようにした

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* 自動修正まわりのドキュメントとコメントの日本語を翻訳調から書き直した

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* issueへのコメントから内部用語の「判断」を外して読み手に通じる言い方に直した

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* CodeRabbitの指摘に対応してフェンスずれによる個人情報の残留など5件を修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* エージェントに書き込み経路が残ることをdocsへ明記

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* トリアージ条件にP2を足した

P1だけに絞っていたが、2026年1月から9月21日までに立ったP1のBugは8件(duplicateを
除く)しかなく、月1件動くかどうかで仕組みとして仕事をしない。同じ期間のP2のBugは
43件で、足しても月6件弱に収まる。

起動するのは新しくラベルが付いたときなので、既にopenなP2のBug28件が一度に流れる
ことはない。

P2のBugが対象外であることを固定していたテストを、対象になる側へ入れ替えた。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* ディスパッチ用トークンに要る権限の記述を直した

Contents: read-only と Actions: read and write と書いていたが誤り。GitHubの権限表で
POST /repos/{owner}/{repo}/dispatches は Contents の write に挙がっていて、Actionsの
節には出てこない。このままではディスパッチャがAPIで弾かれ、MobileApp側が起動しない。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* トリアージ条件にP3も足した

P3を外す理由として「作るものから決める話になる」と書いていたが、これはカテゴリの
理由で、カテゴリの条件がFeature RequestとImprovementを既に弾いている。P3のBugは
Bugなので、直す場所が決まっている点ではP2のBugと変わらない。件数も2026年で3件、
月0.3件なので費用の理由も立たない。

優先度を3つとも入れたことでこの条件はほぼ素通りになるが、優先度が付く前のissueを
先に渡さないための関門として残す。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* 外部actionをcommit SHAで固定し、月あたりの件数を直した

このジョブはcontents: writeとpull-requests: writeを持ち、secretも渡している。
可変タグのままだと、タグが差し替えられた時点でその内容がここで動く。checkout・
setup-node・claude-code-actionをSHAへ固定した。SHAはgit ls-remoteで確認している。

月6件弱と書いていたが、P1からP3の合計54件を8.6か月で割ると6.25件で、弱ではない。
月6件程度に直した。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

* モデルを選んだ理由を書き、冒頭のコメントをP1のみの説明から直した

Sonnetのままにする。まず費用を見たいため。上げるかどうかは「直せない」と誤って
判断した件数で決める。その経路だけは人のレビューで止まらない。

冒頭のコメントが既定をP1のみと説明したままだった。P2とP3を足したときに見落として
いる。現在の既定と、月あたりの件数に合わせて書き直した。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jUHQb3vwnKPNYL2Cm1mxw

---------

Co-authored-by: Claude <noreply@anthropic.com>
* Firebase Analyticsを再導入してアプリの利用状況を計測できるようにする

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Firebase Analyticsで広告IDを収集しないようにする

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 各ビルドワークフローでFirebaseの設定ファイルをシークレットから復元する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* FirebaseApp.configure()をReact Nativeの起動前に呼ぶ

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* google-services.jsonのシークレットをCanaryとProductionで分ける

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* EAS BuildのAndroidビルドでファイル型環境変数GOOGLE_SERVICES_JSONからgoogle-services.jsonを置く

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* 経路検索の列車種別取得をrouteTypesからconnectedRoutesの直通経路へ切り替え

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 経路検索で乗換が必要な駅も検索結果に出し乗換経路も最初の区間の種別で扱うように変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 行先選択で乗換経路の最初の区間の降車駅へ向かう方面だけを表示するように変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 経路検索で乗換経路を選べるようにし行先選択で探している駅へ向かう方面から乗車を始められるように変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換経路を直通運転と同じく区間の駅をつないだ1本の駅リストとして扱い種別一覧に並べるように変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換駅を次の区間の駅としてつなぎヘッダーに乗換先の路線の直通表示が出るように修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換経路の到着予測を現在乗っている系統の範囲だけで問い合わせるように変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換経路の到着予測とシミュレーションで区間指定legsを渡して経路全体を問い合わせるように変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 行き先検索でfromStationGroupIdを渡す形に戻した

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* legsの乗換駅はAPIが駅グループで引き当てるので駅リストの乗換駅をそのまま渡すように変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換経路をつないだ駅リストでは環状線の区間にいても環状線として扱わないように修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換経路の折り返し後の区間指定と区間の駅取得のエラー表示と乗車路線の選び方を修正しテストを補強

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換経路の区間の駅を探索が選んだ駅グループの並びに沿って拾うように変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* groupIdの無い種別を経路の候補から除きnullの駅識別子を一致判定に使わないように修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* useDestinationSelectionのテストで.env.localの無いCIでも読み込めるようにGraphQLクライアントをモックに差し替え

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換経路のtrainRouteの走行区間を件数の推定でなく駅グループで駅リストと突き合わせるように修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 乗換駅を直通運転の系統と同じく前後の路線の駅として2回並べ種別変更の案内が乗換駅を指すように修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: TinyKitten <32848922+TinyKitten@users.noreply.github.com>
* エージェント向け手引きの重複と一般論を削って要点を半分以下の分量に圧縮

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 手引きのNodeとnpmの版指定の出典とエンドポイントをコミットしない規則の対象を実装に合わせて修正

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 手引きからAPIのホスト名を削り文書内でもエンドポイントのURLを書かない規則に変更

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
* サーバの期限切れをタイムアウトとして扱い行き先相談AIが同じ質問を再送しないようにする

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* 行き先相談AIの設計書でiOSのXHR経路が504をタイムアウトとして扱うことを明記する

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: TinyKitten <32848922+TinyKitten@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@TinyKitten TinyKitten self-assigned this Sep 23, 2026
@coderabbitai

coderabbitai Bot commented Sep 23, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Essentials

Run ID: 51b2d930-0b93-42d3-89eb-7c4981618933

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Warning

Billing warning: we have not been able to collect payment for this subscription for more than 72 hours. Please update the payment method or pay any pending invoices in Billing to avoid service interruption.


Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

抽出したバージョン 10.16.0 は現在のバージョンと同一です。バージョンを上げる必要がある場合はブランチ名を変更してください。

@TinyKitten
TinyKitten merged commit b0f56b8 into master Sep 23, 2026
9 checks passed
@TinyKitten
TinyKitten deleted the release/v10.16.0 branch September 23, 2026 08:59
This was referenced Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants