| id | async-correctness |
| name | Async Correctness 非同期処理の正しさ検証 |
| version | 0.1.0 |
| description | await 漏れ・floating promise・並行競合など、非同期処理の correctness バグを検出する。並列化の効率提案(SIMPLIFY Efficiency)や配線断点(e2e-wiring)ではなく、「await を忘れて結果・順序・エラー伝播が壊れる」実装バグに限定する |
| category | midstream |
| phase | ["midstream"] |
| applyTo | ["src/**/*.{ts,tsx,js,jsx,mjs}"] |
| tags | ["async","await","promise","race-condition","correctness","midstream"] |
| severity | major |
| inputContext | ["diff","fullFile"] |
| outputKind | ["findings","questions"] |
| modelHint | high-accuracy |
| dependencies | ["code_search"] |
Pattern declaration
Primary pattern: Reviewer
Secondary patterns: Inversion
Why: 非同期 correctness はチェックリスト型評価が主だが、async/await/Promise を含まない差分では実行を止めるゲートが必要
Goal / 目的
- 差分に含まれる非同期処理の correctness バグ(await 漏れ・floating promise・並行競合)が本番で「たまにしか再現しない不具合」になるのを防ぐ。
- 「動いているように見えるが順序・エラー伝播が壊れている」実装を、差分の段階で検出する。
Non-goals / 扱わないこと
- 宣言した処理の経路が末端まで配線されているかの確認(
e2e-wiring の役割。本スキルは配線済みの非同期コードの実行の正しさを見る)。
- 逐次 await の並列化提案(SIMPLIFY 観点 Efficiency の役割。本スキルは「速くできる」ではなく「壊れている」だけを指摘する)。
- テストコード内の un-awaited assertion(
vitest-mock-isolation の役割)。
- null / undefined の伝播(
typescript-nullcheck / nullability-contract の役割)。
- 設計判断そのものの論理検証(
logic-torturing の役割)。
Pre-execution Gate / 実行前ゲート
このスキルは以下の条件がすべて満たされない限りNO_REVIEWを返す。
ゲート不成立時の出力: NO_REVIEW: async-correctness — 非同期処理を含む変更が検出されない
False-positive guards / 抑制条件
- 意図的な fire-and-forget(
void asyncFn() 明示、またはコメント・命名で意図が明確なもの)は指摘しない。ただしエラーハンドリングが皆無なら questions として確認する。
@typescript-eslint/no-floating-promises が有効なリポジトリでは、当該ルールが決定論で検出する単純な floating promise の severity を minor に落とす。順序・競合の問題はこの限りでない。
- フレームワークが await を要求しない規約(イベントハンドラ・ライフサイクルフック等)に従う呼び出しは指摘しない。
- 共有状態への並行アクセスは、差分内のコードだけで競合が確定する場合のみ findings とする。差分外の呼び出し文脈に依存する場合は questions に落とす。
抑制時の出力: 該当する指摘を出力しない(黙る)。
Rule / ルール
- await 漏れ: Promise を返す呼び出しの結果を await / then せずに値として使用していないか(
if (asyncCheck()) は常に truthy、const x = asyncGet() の x は Promise)。
- floating promise: 結果もエラーも処理されない Promise が放置されていないか(unhandled rejection でプロセス・リクエストが不安定になる)。
- エラー伝播の断絶:
try ブロック内で await せずに Promise を return し、catch が効かない構造になっていないか。
- 並行競合: 同一リソースへの check-then-act(TOCTOU)、 内での同一状態への書き込み、ループ内の共有変数への非同期書き込みがないか。