ios-chaos-monkey について
ios-chaos-monkeyは、iOSおよびSwift開発者向けのクラッシュ調査ガイドです。並行処理、メモリ、永続化などの実行時リスクを優先度順に扱い、修正前にテストでクラッシュを再現する手順を採用しています。
主な機能
- 01優先度付きのクラッシュリスク規則
- 02並行処理とデータ競合の確認
- 03メモリとデッドロックの指針
- 04非同期タスクとキャンセルの確認
- 05永続化とファイルI/Oのリスク
- 06テストでクラッシュを再現する手順
活用シーン
- 01Swiftの並行処理におけるデータ競合の監査
- 02非同期コードのキャンセルやContinuation漏れの確認
- 03永続化とファイルI/Oの障害リスクのテスト
- 04修正前に失敗するクラッシュテストを作成
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ pproenca/ dot-skills --skill ios-chaos-monkeyインストール後、Claude Code で/ios-chaos-monkeyを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
metadata.jsonassets/templates/_template.mdreferences/_sections.mdasync-actor-hop-starvation.mdasync-continuation-leak.mdasync-detached-task-leak.mdasync-missing-cancellation.mdasync-task-group-error.mdasync-unsafe-sendable.mddead-actor-reentrancy.mddead-mainactor-blocking.mddead-queue-hierarchy.mddead-recursive-lock.mddead-semaphore-in-async.mddead-sync-on-main.mdexhaust-file-descriptor-leak.mdexhaust-memory-warning-ignored.mdexhaust-thread-explosion.mdexhaust-unbounded-task-spawn.mdexhaust-urlsession-leak.mdio-concurrent-file-write.mdio-coredata-cross-thread.mdio-filemanager-race.mdio-keychain-thread-safety.mdio-plist-concurrent-mutation.mdio-swiftdata-background.mdmem-async-task-self-capture.mdmem-closure-retain-cycle.mdmem-combine-sink-retain.mdmem-delegate-strong-reference.md詳細
iOS Chaos Monkey — クラッシュハンターのベストプラクティス
iOS および Swift アプリケーション向けの、敵対的なクラッシュハンティングガイドです。8 つのカテゴリにわたる 47 のルールを、クラッシュの深刻度順に優先付けしています。各ルールは TDD に従います。危険なコード、バグを実証する失敗テスト、そしてテストを通過させる修正の順に扱います。
Clinic Architecture Contract (iOS 26 / Swift 6.2)
このスキルのすべてのガイダンスは、Clinic のモジュラー MVVM-C アーキテクチャを前提としています。
- フィーチャーモジュールがインポートできるのは
DomainとDesignSystemのみです(Dataや兄弟フィーチャーはインポートしません) - App ターゲットが集約地点となり、
DependencyContainer、具象コーディネーター、Route Shell の配線を所有します Domainは純粋な Swift を維持し、モデルに加えて、リポジトリ、*Coordinating、ErrorRouting、AppErrorの契約を定義しますDataは SwiftData/ネットワーク/同期/リトライ/バックグラウンド I/O を所有し、Domain プロトコルを実装します- 読み取り/書き込みフローでは、デフォルトで stale-while-revalidate による読み取りと、キューに入れた楽観的な書き込みを使用します
- ViewModel はリポジトリプロトコルを直接呼び出します(デフォルトのユースケース/インタラクターレイヤーはありません)
適用する場面
次のような場合に、これらのガイドラインを参照してください。
- Swift のデータ競合、デッドロック、並行処理によるクラッシュを調査するとき
- 保持サイクルや解放済みメモリへのアクセスがないか、メモリ管理を監査するとき
- キャンセルや継続のリークがないか、async/await コードをレビューするとき
- ファイル I/O や CoreData/SwiftData の永続化レイヤーにストレステストを実施するとき
- 修正を実装する前に、クラッシュを証明するテストを作成するとき
優先度別のルールカテゴリ
| 優先度 | カテゴリ | 影響度 | プレフィックス |
|---|---|---|---|
| 1 | データ競合とスレッドセーフティ | CRITICAL | race- |
| 2 | メモリ破損とリーク | CRITICAL | mem- |
| 3 | デッドロックとスレッド枯渇 | HIGH | dead- |
| 4 | Async/Await と構造化並行処理 | HIGH | async- |
| 5 | ファイル I/O と永続化の破損 | MEDIUM-HIGH | io- |
| 6 | コレクションと状態の変更 | MEDIUM | mut- |
| 7 | リソース枯渇 | MEDIUM | exhaust- |
| 8 | Objective-C 相互運用の落とし穴 | LOW-MEDIUM | objc- |
クイックリファレンス
1. データ競合とスレッドセーフティ(CRITICAL)
race-dictionary-concurrent-write- Dictionary の並行変更により EXC_BAD_ACCESS でクラッシュしますrace-array-concurrent-append- Array への並行追加によって内部バッファが破損しますrace-property-access- スレッド間でプロパティの読み書きが同期されていませんrace-lazy-initialization- 並行処理中に遅延プロパティが二重に初期化されますrace-singleton-initialization- 非アトミックなシングルトンが、構築途中の状態を公開しますrace-bool-flag- 非アトミックな Bool フラグによって、確認してから実行するまでの間に競合が発生しますrace-closure-capture-mutation- クロージャがスレッド間で可変参照をキャプチャしますrace-delegate-nilification- コールバックの実行中にデリゲートが nil に設定されます
2. メモリ破損とリーク(CRITICAL)
mem-closure-retain-cycle- エスケープクロージャで強参照によって self を捕捉すると、保持サイクルが発生しますmem-timer-retain-cycle- Timer がターゲットを保持するため、検出困難な保持サイクルが発生しますmem-delegate-strong-reference- delegate への強参照によって解放が妨げられますmem-unowned-crash- 所有者の解放後に unowned 参照へアクセスするとクラッシュしますmem-notification-observer-leak- 削除が必要になった後も NotificationCenter のオブザーバーがクロージャを保持しますmem-combine-sink-retain- キャンセラブルを保存せずに Combine の sink が self を保持しますmem-async-task-self-capture- Task が self を捕捉し、想定されたスコープを超えてライフタイムを延長します
3. デッドロックとスレッド枯渇(HIGH)
dead-sync-on-main- メインスレッドから DispatchQueue.main.sync を呼び出すと、即座にデッドロックしますdead-recursive-lock- 同じシリアルキューでロックを再帰的に取得しますdead-actor-reentrancy- Actor の再入によって予期しない処理の割り込みが発生しますdead-semaphore-in-async- 非同期コンテキスト内で Semaphore.wait() を呼び出すと、スレッドプールがデッドロックしますdead-queue-hierarchy- Dispatch キューのターゲット階層の逆転によってデッドロックが発生しますdead-mainactor-blocking- 重い同期処理によって MainActor がブロックされます
4. Async/Await と構造化並行性(HIGH)
async-missing-cancellation- Task.isCancelled の確認がないため、画面遷移後もリソースが無駄に消費されますasync-detached-task-leak- キャンセルハンドルのないデタッチされたタスクによって処理がリークしますasync-task-group-error- TaskGroup が子タスクのエラーを黙って破棄しますasync-continuation-leak- CheckedContinuation が一度も再開されず、待機中のタスクがリークしますasync-actor-hop-starvation- ホットループ内で MainActor へのホップが過剰に発生すると、UI 更新が滞りますasync-unsafe-sendable- @unchecked Sendable によってデータ競合がコンパイラから隠されます
5. ファイル I/O と永続化データの破損(MEDIUM-HIGH)
io-concurrent-file-write- 調整せずにファイルへ同時に書き込むと、データが破損しますio-coredata-cross-thread- CoreData の NSManagedObject に誤ったスレッドからアクセスしますio-swiftdata-background- SwiftData のモデルに誤った ModelContext からアクセスしますio-plist-concurrent-mutation- UserDefaults の同時読み書きによって古い値が返されますio-filemanager-race- FileManager で存在確認をしてから使用する処理は TOCTOU 競合ですio-keychain-thread-safety- 複数のスレッドから Keychain にアクセスすると、予期しないエラーが返されます
6. コレクションと状態の変更(中)
mut-enumerate-and-mutate- 列挙中にコレクションを変更すると、実行時にクラッシュしますmut-kvo-dealloc-crash- 解放前にKVOオブザーバーを削除しないと、クラッシュしますmut-index-out-of-bounds- 境界チェックなしで配列インデックスにアクセスすると、クラッシュしますmut-force-unwrap- 本番環境でオプショナルを強制アンラップすると、値がnilの場合にクラッシュしますmut-enum-future-cases- 網羅性のないswitch文は、不明なenumケースでクラッシュします
7. リソースの枯渇(中)
exhaust-unbounded-task-spawn- ループ内でタスクを無制限に生成すると、メモリが枯渇しますexhaust-thread-explosion- GCDは、並行負荷がかかると無制限にスレッドを生成しますexhaust-urlsession-leak- URLSessionを無効化しないと、デリゲートと接続がリークしますexhaust-file-descriptor-leak- ファイルハンドルを閉じないと、ファイルディスクリプターがリークしますexhaust-memory-warning-ignored- メモリ不足の警告を無視すると、Jetsamによる強制終了が発生します
8. Objective-C相互運用の落とし穴(低〜中)
objc-unrecognized-selector-@objcアノテーションがないと、認識されないセレクターでクラッシュしますobjc-nsnull-in-json- デコードされたJSONコレクション内のNSNullにアクセスすると、クラッシュしますobjc-bridge-type-mismatch- Swift/ObjCブリッジの型が一致しないと、実行時にクラッシュしますobjc-dynamic-dispatch-dynamicキーワードがないと、メソッドスウィズリングが機能しません
使い方
詳しい説明とコード例については、各リファレンスファイルをお読みください。
リファレンスファイル
| ファイル | 説明 |
|---|---|
| references/_sections.md | カテゴリーの定義と順序 |
| assets/templates/_template.md | 新しいルール用のテンプレート |
| metadata.json | バージョンとリファレンス情報 |
コメント
Markdown 対応