agile-tdd について
agile-tddは、ソフトウェア開発エージェント向けにRed-Green-Refactorとテスト選択を案内するテスト駆動開発のワークフロー技能です。オプションのフックテンプレートで、対応テストのないソースファイルへの書き込みを警告または阻止できます。
主な機能
- 01Red-Green-Refactorサイクルの案内
- 02振る舞いに応じた単体・統合・E2Eテストの選択
- 03テストの命名規則と配置の定義
- 04カバレッジ目標とアンチパターンの提示
- 05対応テストを確認する任意のフック
- 06warnまたはblockの実行モード
活用シーン
- 01新機能のTDD計画
- 02既存モジュールへのテスト追加
- 03適切なテスト層の選択
- 04テストファイルのプロジェクトガードレール設定
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ djalmajr/ skills --skill agile-tddインストール後、Claude Code で/agile-tddを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
templates/agents-block.md.tmplopencode-plugin.js.tmpltdd-guardrails.yml.tmpltemplates/hooks/tdd-announce.sh.tmpltdd-pre-write.sh.tmpltdd-session-audit.sh.tmpltemplates/lib/audit-helpers.sh.tmpltemplates/project-types/README.mdtemplates/project-types/desktop/README.mdtemplates/project-types/mobile/README.mdtemplates/project-types/pwa/README.mdtemplates/project-types/tauri/agents-block.partial.mdaudit.partial.shdetect.shguardrails.partial.ymlREADME.mdtemplates/project-types/tauri/hooks/tdd-record-mcp.sh.tmpl詳細
TDD(テスト駆動開発)
Red-Green-Refactor サイクルと、実践的なテスト戦略をガイドします。「テストを書く。多すぎず、主にインテグレーションテストを。」
スラッシュコマンド経由で受け取る初期コンテキスト:$ARGUMENTS
$ARGUMENTS に値が入っている場合(例:モジュール名、機能の説明)は、出発点として使用してください。
空の場合は、何をテストするのか尋ねてください。
言語
成果物とテストの説明は、ユーザーの言語で記述してください。判断に迷う場合は、確認してください。テストコード自体(関数名、アサーション)は英語のままにしてください。
プロジェクトルート
このスキルでは、エージェントの現在の作業ディレクトリではなく、プロジェクトルート(作業対象のリポジトリ)からの相対パスに成果物を書き込みます。
- プロジェクト内から呼び出された場合は、このスキルに記載された相対パスを使用してください。
- 別のディレクトリ(例:隣接するリポジトリ、またはプロジェクトが別の場所にある場合)から呼び出された場合は、すべての成果物のパスの前に
<project-root>/を付けてください。 - プロジェクトルートが曖昧な場合は、書き込む前にハーネスの質問ツールでユーザーに確認してください。
プロンプト
CLAUDE.md / AGENTS.md に記載されたプロジェクト全体の規約(「Skill Prompting Conventions」)に従ってください。以下の判断が必要な場面では、ハーネスの構造化質問ツール(Claude Code の AskUserQuestion、Codex の ask_user_question、OpenCode の question)を使用してください。
| 判断事項 | 構造化質問を使う理由 | 推奨される選択肢 |
|---|---|---|
| 適用モード(インストール時) | 元に戻しにくいポリシー上の選択 | 警告 · ブロック · 現状維持 |
| テスト戦略(曖昧な場合) | ファイル配置に影響する | sibling · sibling_dir · tests_root |
| 特定のパスを除外する | ガードレール設定を編集する | はい · いいえ · 後で確認 |
自由形式のプロンプト(構造化質問ツールなし):
- テストの説明
- 除外する理由
一時停止なしモード:ユーザーがスキル実行中の確認を明示的に無効にしている場合は、すべての構造化プロンプトを「未解決の質問」(または同等の項目)に記載し、処理を止めずに続行してください。
使用する場面
- TDD で新機能を開始するとき
- 既存のコードにテストを追加するとき
- モジュールのテストカバレッジを確立するとき
- 単体テスト、インテグレーションテスト、E2E テストのどれが必要か不明なとき
使用しない場面
- テストに価値がない簡単なプロトタイプの場合 —
/agile-protoを使用してください - 使い捨てのスクリプト
- ドキュメントのみの変更
TDD サイクル
- Red -- 期待する動作を説明する、失敗するテストを書く
- Green -- テストを通すために必要最小限のコードを書く
- Refactor -- 動作を変えずに構造を改善する
- 繰り返す
各ステップを明示してください。Red を飛ばしてはいけません -- まずテストが失敗する必要があります。
テストピラミッド(実践的な指針)
| 層 | 目標 | 焦点 |
|---|---|---|
| 単体 | 60% | 純粋関数、変換処理、ユーティリティ |
| インテグレーション | 30% | サービス、DB とのやり取り、API ルート |
| E2E | 10% | 重要なユーザーフロー |
全体のカバレッジ目標:75% 以上。
フロントエンドの作業では、これらの割合をノルマではなく、リスクを判断するための指針として扱ってください。ユーザーの操作、バリデーション、ローカル状態、API コントラクト、権限、オフライン時の動作/同期、重要なフローを検証するインテグレーションテストを優先してください。静的なテキストがあること、ボタンが描画されたこと、デザインシステムのコンポーネントの実装詳細だけを検証するテストは避けてください。
プロジェクトでビジネスルールをplanning/<initiative>/business/*.mdに管理している場合は、そのルール ID を使って、どの項目をテストすべきか判断してください。重要なルールに関わる動作をテストで証明し、ルールの文面をそのまま繰り返すだけにならないようにしてください。
ファイル構成
- 単体テスト: ソースファイルと同じ場所(
foo.tsの隣にfoo.test.ts) - インテグレーション/E2E:
tests/配下にintegration/、e2e/、helpers/、fixtures/、mocks/ - 命名:
.test.ts(単体/インテグレーション)、.e2e.test.ts(E2E) .spec.tsは使用禁止
ルール
- AAA パターン(Arrange / Act / Assert)
- テストごとに1つの概念を扱う
- 文として読める、説明的な名前を付ける
- ハードコードしたデータより、常にファクトリー(例:
faker)を使用する beforeEachでテストを分離する — テスト間で状態を共有しない- 実装の詳細ではなく、動作をテストする
アンチパターン(避けてください)
- 相互依存するテスト(テスト A の実行前にテスト B の実行が必要)
- 根拠のない
sleep(ms)— 適切な待機処理を使用してください - プライベートメソッドのテスト — パブリック API 経由でテストしてください
- テスト内の
console.log— 適切なアサーションを使用してください - 実行順序に依存するテスト
- 自分が所有するコードのモック化(外部依存関係をモック化し、自分のコードはモック化しないでください)
カバレッジ目標(細分化)
| 領域 | 目標 |
|---|---|
| トランスフォーマー/純粋関数 | 90% 以上 |
| ユーティリティ | 85% 以上 |
| サービス | 80% 以上 |
| ルート/ハンドラー | 70% 以上 |
コマンド(Bun)
bun test
bun test --watch
bun test --coverage
bun test --filter "name"
bun test src/dir/
必要に応じて、他のランタイム(vitest、jest)に合わせて調整してください。コマンドを提案する前に、package.json または設定ファイルからプロジェクトのテストランナーを検出してください。
プロセス
1. テスト対象を把握する
コードを調べ、次の点を把握します。
- どのモジュールまたは機能にテストが必要か
- 重要な動作は何か
- すでにテストでカバーされている内容(既存のテストを確認してください)
- この変更が満たす必要のあるビジネスルール ID、受け入れ基準、またはプロトタイプのフロー
フロントエンドの作業では、Red を開始する前に、実際に存在するすべてのプロトタイプソースを見つけてください。プロジェクトには、Agile-Proto のブラウザープロトタイプ、デザインツールの Agile-Design プロトタイプ、両方、またはいずれもない場合があります。プロトタイプの根拠は、コンポーネントの選定に役立ち、観察可能な動作を明確にしますが、実装の許可を与えたり取り消したりするものではありません。
Agile-Proto ソース
planning/*/proto/ や {app}/client-proto/ など、プロジェクトで定められた場所にあるブラウザープロトタイプを見つけてください。安定したシーン ID/ルートを読み、実際の htm-ui/<module>.js インポートを調べてください。これらのインポートは、コンポーネントを直接示す根拠です。
htm-ui/button.jsは、保守されている HTM UI Button モジュールに対応します。- プロトタイプ固有の構成ファイルは構成であり、プリミティブのカタログをコピーしたものではありません。
- 保守されているインポートを伴わないカスタムマークアップは、未解決のマッピングに関する警告であり、作業を中断する理由ではありません。
プロトタイプで観察できる動作とルートフローを、インタラクションの根拠として使用してください。プロトタイプ専用のマークアップを機械的にコピーするのではなく、対象アプリにインストールされたコンポーネントシステムとリポジトリの規約から、本番相当の要素を確認してください。
Agile-Design ソース
planning/<initiative>/design/README.md(プロトタイプのインデックス)と、そこに要約されている関連ノートを読んでください。画面 ID と状態 ID、トリガー、アクションの遷移先、表示上のルールは、テストの動作根拠になります。デザインファイル自体は視覚的な参照に限られます。デザインとコードを結び付けるコンポーネントマッピングは存在しないため、コンポーネントの選定には、対象アプリにインストールされたコンポーネントシステムと /design-workflow を使用します。
両方のソースがある場合
対象ストーリーまたは画面について、次の手順でソースマップを作成してください。
- 安定した planning/story/requirement ID と画面/シーンの目的を照合します。
- Agile-Design のノートを、状態、遷移、表示上のルールに使用します。
- ブラウザー上の動作と HTM UI の識別には、Agile-Proto のインポートと実行時のインタラクションを使用します。
- いずれかのソースが既存の本番コンポーネントに対応する場合は、インストール済みの本番コンポーネントを優先します。
- ソース間に食い違いがある場合は、警告を出し、対象の受け入れ基準と現在のプロダクトコードに最も近いソースを選びます。食い違いによってユーザーに見える動作またはスコープが大きく変わる場合に限り、ユーザーに確認してください。
プロトタイプが存在しない、不完全、古い、または複数の形式で存在するという理由だけで、実装を拒否してはいけません。AI は利用可能なすべての手掛かりを使い、役立つ場合は確信度を示し、最も根拠のあるコンポーネントを選んで作業を進めてください。
TDD では、引き続き観察可能な動作を基準にします。デザインシステムコンポーネントの内部マークアップではなく、画面フロー、バリデーション、権限、状態変更、統合コントラクトをテストしてください。
2. 適切なテストの種類を選ぶ
テストピラミッドを目安にします。
- 副作用のない純粋関数ですか? ユニットテストを行います。
- DB や外部 API と通信するサービスですか? 統合テストを行います。
- 複数のシステムにまたがる重要なユーザーフローですか? E2E テストを行います。
- バリデーション、API コントラクト、権限、楽観的更新、オフライン/同期状態を伴うフロントエンドの動作ですか? 統合テストを行います。
- 静的なコピー、単純なレンダリング、ルールのない視覚的な詳細だけですか? 既知のリグレッションを防ぐ場合を除き、通常はテスト不要です。
ローカルファーストの製品では、コマンドのバリデーション、楽観的状態、オフラインキューの永続化、調整、競合処理、権限、監査イベントを対象とするテストを優先します。
3. TDD サイクルを実行する
各動作について、次の手順を実施します。
- 失敗するテストを書く(Red)
- 最小限のコードを実装する(Green)
- 必要に応じてリファクタリングする
- テストが引き続き成功することを確認する
この対応付けが今後の改善に役立つ場合は、テストの説明または関連するストーリーの成果物に、ビジネスルール ID または受け入れ基準を記録します。
4. カバレッジを確認する
カバレッジを測定し、目標と照らし合わせて確認します。まず重要な領域の不足を解消します。
連携
- 機能の実装中:
/agile-storyのチェックリストに沿って作業します - 実装後:
/agile-refinementでテストの品質をレビューします - クローズ前:テストが
/agile-statusの検証(クローズモード)に含まれていることを確認します - TDD ワークフローで繰り返し摩擦が生じる場合、不足しているガイダンス、弱いテンプレート、または不明確な検証があれば、影響を受けるスキル/テンプレート、根拠、提案する変更、検証成果物を記した簡潔なスキルフィードバックメモを作成します。
- TDD の摩擦が繰り返し発生し、スキル/テンプレートの変更が必要と思われる場合は、プロセスライブラリを編集する前に、人間によるレビュー用の提案書を作成します。
適用(任意、プロジェクトごとにオプトイン)
助言としてのガイダンスに加え、このスキルには TDD ルールをプロジェクトレベルのガードレールにするフックテンプレートが付属しています。プロジェクトで有効にすると、エージェントがこのスキルの呼び出しを忘れても、すべての実装セッションでファイル書き込み時にチェックが行われます。
適用される内容
Write|Edit|MultiEditに対する PreToolUse — 対象ファイルが.tdd-guardrails.ymlのsource_pathsに一致し、対応するテストが存在しない場合、フックは警告を表示する(mode: warn)か、ツールの呼び出しをブロックします(mode: block)。- Stop フック — セッション終了時に git diff をスキャンし、対応するテストなしで変更されたソースファイルを報告します。
- SessionStart フック — 「TDD 適用中」と通知し、エージェントにルールが有効であることを知らせます。
フックテンプレートは skills/agile-tdd/templates/hooks/*.sh.tmpl にあり、設定スキーマは skills/agile-tdd/templates/tdd-guardrails.yml.tmpl にあります。
設定(.tdd-guardrails.yml)
| キー | 意味 |
|---|---|
enabled | 全体の有効/無効 |
mode | warn(stderr のみ)または block(PreToolUse が呼び出しを拒否) |
source_paths | 対応するテストを必須とする glob パターン |
test_strategy | sibling(foo.ts → foo.test.ts)、sibling_dir(__tests__/foo.test.ts)、または tests_root(<app>/tests/integration/foo.test.ts) |
exemptions | テストなしでも許可される glob パターン(エントリーポイント、生成ファイル、UI プリミティブ) |
パターンの仕様: フックスクリプトでは、拡張 globstar ではなく bash case の glob パターンを使用します。bash case のパターンでは、* は / を含む任意の文字列に一致し、** はありません。そのため、apps/*/src/*.ts は apps/server/src/handler.ts と apps/server/src/auth/handler.ts の両方に一致します。source_paths または exemptions では ** を使用しないでください。
適用上の注意点
フックが確認するのはファイルペアの存在だけです。以下は検証できず、検証することもできません。
- テストがソースより先に書かれたこと(Red を Green より先に実行する順序は確認しません)。
- テストが実際にソースを実行すること(意味上の一致は確認しません)。
- テストが現時点で成功すること(テストは実行しません)。
意味のある規律(テストごとに動作を 1 つにする、ハードコードされたデータよりファクトリーを使う、説明的な名前を付ける、AAA)は、引き続きエージェントが担います。フックはガードレールであり、保証ではありません。
手動インストール(tdd-init スクリプトができるまで)
ハーネスごとに仕組みが異なります。Claude Code と Codex はシェルフックを直接実行しますが、OpenCode は同じシェルスクリプトを呼び出す JS プラグインを実行します。
-
templates/tdd-guardrails.yml.tmplを<project-root>/.tdd-guardrails.ymlにコピーし、リポジトリの構成に合わせてsource_pathsとexemptionsを編集します。続いて、プロジェクトタイプ検出ツールを実行し、
project_typesを設定します。for type in .claude/skills/agile-tdd/templates/project-types/*/; do name="$(basename "$type")" [ -f "$type/detect.sh" ] || continue bash "$type/detect.sh" "$PWD" && echo "detected: $name" done検出されたタイプごとに、その
guardrails.partial.ymlを新しく作成した.tdd-guardrails.ymlに追記します(ブロックがすでに存在する場合はマージします)。また、タイプのスラッグをproject_typesリストに追加します。 -
フックのテンプレートをコピーします。
templates/hooks/から<project-root>/.claude/hooks/、<project-root>/.codex/hooks/、および<project-root>/.opencode/hooks/にコピーします(OpenCode プラグインはnode:child_process.spawnを介して同じスクリプトを実行します)。.tmpl接尾辞を削除し、chmod +xを実行します。共通ヘルパーもコピーします。
templates/lib/audit-helpers.sh.tmpl → .claude/hooks/lib/audit-helpers.shさらに、プロジェクトタイプのディレクトリもコピーします。
templates/project-types/ → .claude/hooks/project-types/セッション監査スクリプトは両方の場所を検索します。Codex/OpenCode では、
.codex/hooks/と.opencode/hooks/にも同じものを配置してください。 -
各ハーネスの設定にフックを登録します。
- Claude Code(
.claude/settings.json):Write|Edit|MultiEditに一致するPreToolUseエントリを追加し、$CLAUDE_PROJECT_DIR/.claude/hooks/tdd-pre-write.shを呼び出します。tdd-session-audit.shを呼び出すStopエントリと、tdd-announce.shを呼び出すSessionStartエントリも追加します。既存のフックとマージし、置き換えないでください。 - Codex(
.codex/hooks.json):apply_patch|Edit|Write|MultiEditに一致するPreToolUse、Stop、およびSessionStartのエントリを追加します。コマンド形式にはbash "$(git rev-parse --show-toplevel)/.codex/hooks/<script>.sh"を使用してください(Codex のパターン)。それぞれにstatusMessageフィールドを含めます。 - OpenCode:
templates/opencode-plugin.js.tmplを<project-root>/.opencode/plugins/tdd-guardrails.jsにコピーします。このプラグインはtool.execute.before(PreToolUse相当)、session.created(SessionStart相当)、およびsession.idle(Stopに最も近いイベント。監査シェルは tmp 状態ファイルにより冪等なので、複数回実行しても安全です)を購読します。プラグインはnode:child_process.spawnを介して同じ.opencode/hooks/tdd-*.shスクリプトを起動します。OpenCode はシェルスクリプトを直接実行しません。エントリーポイントはプラグインです。
- Claude Code(
-
templates/agents-block.md.tmplの内容をAGENTS.mdとCLAUDE.mdに追記し、プロジェクトで TDD が適用されていることをエージェントに伝えます。検出されたプロジェクトタイプごとに、その
templates/project-types/<type>/agents-block.partial.mdも同じファイルに追記します(再インストール時にその場で更新できるよう、/ :endマーカーを保持してください)。 -
.claude/settings.jsonにタイプ固有のマッチャーを登録します。tauriの場合:mcp__tauri__webview_screenshot|mcp__tauri__webview_execute_js|mcp__tauri__webview_dom_snapshot|mcp__tauri__manage_windowに一致するPostToolUseエントリを追加し、$CLAUDE_PROJECT_DIR/.claude/hooks/tdd-record-mcp.shを呼び出します。
Codex の同等の設定は
.codex/hooks.jsonに記述します。OpenCode では、ツール名でフィルターしたtool.execute.afterを購読し、node:child_process.spawnを介して同じシェルスクリプトを起動します。
フックはガードレールであり、保証ではありません。確認するのはファイルのペアが存在するかどうかであり、テストの品質ではありません(1 テストにつき 1 つの振る舞いにする、ハードコードしたデータよりファクトリーを使う、といった)意味面での規律は、引き続きエージェントが担います。
ハーネス互換性マトリックス
| ハーネス | エントリーポイント | 書き込み前イベント | 停止相当 | セッション開始 |
|---|---|---|---|---|
| Claude Code | .claude/settings.json フック | PreToolUse(マッチャー Write|Edit|MultiEdit) | Stop | SessionStart |
| Codex | .codex/hooks.json フック | PreToolUse(マッチャー apply_patch|Edit|Write|MultiEdit) | Stop | SessionStart |
| OpenCode | .opencode/plugins/tdd-guardrails.js JS プラグイン | tool.execute.before | session.idle(利用可能な中で最も近いイベント。監査は冪等) | session.created |
意図的に回避する場合
- 1 つのパスだけの場合:
.tdd-guardrails.yml → exemptionsに追加します。 - 1 回のセッションだけの場合:一時的に
enabled: falseに設定し(コミット前に元に戻します)。 - フックを黙らせるためだけにテストファイルを削除してはいけません。目的に反します。
プロジェクトタイプのテンプレート
基本のコンパニオンテストルールに加えて、agile-tdd は templates/project-types/<type>/ にプロジェクトタイプ別のテンプレートを用意しています。各テンプレートを有効にすると、Stop フックはコンパニオンテストに加え、プロジェクト固有の証拠もチェックします。セッション監査スクリプトは、基本チェックにアクティブなタイプごとのフラグメントを組み合わせます。モードはタイプごとに独立しているため、TDD を warn にしながら、より厳格なタイプを block にできます。
利用可能なタイプ
| タイプ | 検出条件 | 適用内容(コンパニオンテストに加えて) |
|---|---|---|
tauri | src-tauri/Cargo.toml(単一リポジトリまたはモノレポ) | cargo check が最新であること + bun run typecheck が最新であること + 影響を受ける各アプリで、最後の編集後に mcp__tauri__webview_screenshot が 1 回以上実行されていること |
pwa | (計画中)manifest.webmanifest + サービスワーカー | サービスワーカーの再ビルド + オフラインのスモークテスト |
mobile | (計画中)app.json(Expo)/ Podfile / android/build.gradle | プラットフォームのビルドが成功すること + シミュレーターのスクリーンショット |
desktop | (計画中)electron/forge の設定 | electron-builder の検証 + ウィンドウのスクリーンショット |
アクティブなタイプは .tdd-guardrails.yml → project_types に記載されます。インストール時に、各 templates/project-types/<type>/detect.sh がリポジトリに対して実行されます。成功したタイプは、guardrails.partial.yml ブロックとともに設定に追加されます。
タイプの構成
タイプは次の要素を含むフォルダーです。
detect.sh— タイプがリポジトリに適用される場合に 0 を返します。guardrails.partial.yml—.tdd-guardrails.ymlに追加されるブロックです。agents-block.partial.md— マーカーの間にあるCLAUDE.md/AGENTS.mdに追加されるセクションです。audit.partial.sh—tdd-session-audit.shによって読み込まれます。テキスト形式の違反内容を返すcheck_<type>_evidence "$ROOT"をエクスポートします。フレームワークがブロックと警告のどちらにするか判断できるよう、<TYPE>_MODE(大文字)を設定します。hooks/*.sh.tmpl— タイプが登録する追加フック(PostToolUse の証拠記録など。任意)です。README.md— タイプについての説明です。
フレームワークは、yml の解析、glob マッチング、アプリルートの検出、最新状態のチェックに templates/lib/audit-helpers.sh のヘルパーを呼び出します。新しいタイプを追加するために、フレームワークのスクリプトを変更する必要はありません。
タイプのインストール
基本の agile-tdd インストールは、すでに上記の「手動インストール」の手順に従っています。検出されたタイプごとに、次の手順を実行します。
templates/project-types/<type>/guardrails.partial.ymlを.tdd-guardrails.ymlに追加します(ブロックがすでに存在する場合はマージします)。agents-block.partial.mdをマーカーのペアの間にあるCLAUDE.md/AGENTS.mdに追加します。hooks/*.sh.tmplを.claude/hooks/、.codex/hooks/、.opencode/hooks/にコピーし、.tmplの接尾辞を削除してchmod +xを実行します。- 各ハーネス設定にタイプのマッチャーを追加します。
- Claude Code(
.claude/settings.json→PostToolUse):タイプの PostToolUse フック用のマッチャーエントリーを追加します。tauriの場合:mcp__tauri__webview_screenshot|mcp__tauri__webview_execute_js|mcp__tauri__webview_dom_snapshot|mcp__tauri__manage_windowを$CLAUDE_PROJECT_DIR/.claude/hooks/tdd-record-mcp.shで呼び出します。 - Codex(
.codex/hooks.json):同じマッチャーパターンを使います。コマンドはbash "$(git rev-parse --show-toplevel)/.codex/hooks/tdd-record-mcp.sh"を使います。 - OpenCode:
.opencode/plugins/tdd-guardrails.jsを拡張し、ツール名でフィルターしてtool.execute.afterを購読するようにします。同じシェルスクリプトをnode:child_process.spawnで起動します。
- Claude Code(
.tdd-guardrails.ymlのproject_typesにタイプのスラッグ(例:tauri)を追加します。セッション監査は実行時にこのリストを読み込みます。
Tauri MCP の検証(プロジェクトタイプ)
実際の Tauri のデバッグ/テストセッションからまとめたノウハウです。Tauri が検出されたリポジトリで src-tauri/src/** または src/{routes,components,hooks}/** を変更する前に読んでください。
ツールボックス(標準参照)
mcp__tauri__driver_session(start)— 必ず最初に呼び出します。以降の WebView ツールはアクティブなセッションを前提とします。mcp__tauri__webview_screenshot— 「画面を開いた」ことを示す標準シグナルです。windowId="main"を渡します(Tauri アプリでは通常、mainとtray-panelがあります)。mcp__tauri__webview_execute_js— JS エグゼキューターのタイムアウト(約数秒)を超える呼び出しでは、window.__TAURI_INTERNALS__.invoke(cmd, args).then(r => window.__last = r)を使って fire-and-forget で実行します。awaitする代わりに、 DB またはスクリーンショットをポーリングします。mcp__tauri__webview_interact/webview_find_element/webview_dom_snapshot内の refs — これらはwindow.__MCP__.resolveRefに依存しており、開発サーバーの HMR リロード後は undefined になります。webview_execute_js経由でdocument.querySelector(...).click()を使うことを推奨します。
再ビルドの流れ
- Rust の変更 →
touch src-tauri/src/<file.rs>を実行すると、tauri-devが 再ビルドされます(cargo の mtime ウォッチャーによるものです)。 - MCP 呼び出しを再実行する前に、開発プロセスの出力で
FinishedとMCP Bridge plugin initializedが表示されるのを確認します。HMR が対象とするのは フロントエンドのみです。 - Claude Code では、次のフィルターを指定して
Monitorを使うことを推奨します。tail -f tauri.log | grep --line-buffered -E "Finished|error\\[|MCP Bridge plugin initialized"。
検証パターン
- DB の直接読み取り — 状態のアサーションには
invoke()より低コストです。sqlite3 <workspace>/<app>.db "SELECT ..."。 - GPU オフロードの確認 —
ps -p $(pgrep -x <app-name>) -o pcpu,etime。 Metal/CUDA を使用するアプリでは、GPU が処理中の CPU 使用率は低く(5~15%)なります。CPU のみのフォールバックでは 200~400%になります。 - 視覚的な確認 —
webview_execute_js経由でlocation.assign('/route/...')を実行し、約 500 ミリ秒待ってからwebview_screenshotを実行します。
既知の注意点(プロジェクト横断のパターン)
各プロジェクトでは、独自の修正リストをリポジトリ内に保持しています(例:LLM
wiki パターンに従うプロジェクトでは wiki/technical/tauri-gotchas.md)。以下はパターンを説明するもので、実際のファイルパスはプロジェクトによって異なります。
-
whisper-rs 0.14.x の
set_abort_callback_safeにおける型の混同 — v0.14.4 では、トランポリンは元のクロージャー型でインスタンス化されますが、user_dataは実際にはBox<dyn FnMut() -> bool>として書き込まれます。コールバックが誤った メモリレイアウトを逆参照し、誤った bool 値を返すため、whisper は 0~5%でエラー-6を出して中断します。回避策:保存された型と一致する手書きのトランポリンを使い、unsafe版のset_abort_callbackとset_abort_callback_user_dataを使用します。unsafe extern "C" fn abort_trampoline(ud: *mut std::ffi::c_void) -> bool { let f = &mut *(ud as *mut Box<dyn FnMut() -> bool>); f() } let closure: Box<dyn FnMut() -> bool> = Box::new({ let cancel = cancel.clone(); move || cancel.load(Ordering::Relaxed) }); let ud = Box::into_raw(Box::new(closure)) as *mut std::ffi::c_void; unsafe { params.set_abort_callback(Some(abort_trampoline)); params.set_abort_callback_user_data(ud); } -
バイナリーの強制終了後にバックグラウンドジョブが
runningのまま停止する — 実行中に終了した tokio タスク(cargo の再起動、アプリのクラッシュ)は、DB の行を終端状態に更新しません。プールのオープン時に照合処理を追加します。// db::open_pool, after schema migration sqlx::query( "UPDATE jobs SET status='cancelled', error_message=COALESCE(error_message,'interrupted by app restart'), finished_at=? WHERE status IN ('running','pending')" ).bind(now_iso()).execute(&pool).await?; -
openをデータ状態と連動させるモーダルライブラリー(例:Base UI Dialog、一部の Radix パターン)—openが false に切り替わるのと同じレンダーでデータの prop がnullになると、閉じるアニメーションが終わる前にモーダルがアンマウントされます。document.body上で pointer-events が捕捉されたままになり、ページをクリックできなくなります。open(ブール値)をデータから切り離したうえで、データのクリアをsetTimeout(..., 200)で遅延させます(または、ライブラリーが提供している場合はonCloseCompleteコールバックを使います)。 -
既存のテーブルでは
CREATE TABLE IF NOT EXISTSは何もしません — 既存のワークスペース/DBには、スキーマファイルに追加された新しい列が反映されません。症状:アップグレード後に実行時のno such columnエラーが発生します。修正方法:ドリフトごとに明示的なALTER TABLE … ADD COLUMN IF NOT EXISTSを実行するか、 DB に本番データがない場合は、削除して再初期化します。 -
hound::WavReaderがデコードできるのは WAV のみです —.mp3/.mp4/.m4a/.webmの場合は、Whisper に渡す前に ffmpeg を通してf32le @ 16 kHz monoに変換します。// ffmpeg -hide_banner -loglevel error -nostdin -i <input> // -ac 1 -ar 16000 -f f32le - let mut child = Command::new(ffmpeg) .args(["-hide_banner","-loglevel","error","-nostdin","-i"]) .arg(input) .args(["-ac","1","-ar","16000","-f","f32le","-"]) .stdout(Stdio::piped()).spawn()?; // read stdout, reinterpret bytes as &[f32]
Definition of Done(Tauri)
affected_paths に触れる変更ごとに、影響を受けるすべてのアプリで(モノレポの場合はアプリごとに)次を満たします。
cargo check --manifest-path <app>/src-tauri/Cargo.toml --libが成功していること。bun run typecheck(またはtsc --noEmit)が成功していること。<app>/src-tauri/src/**で最後にtouchを実行した後、tauri-devにFinishedと表示されていること。- 対応するテストが存在すること(該当する場合は基本の TDD ルールに従います)。
<app>/{src-tauri,src}/**の最後の編集後に、1 回以上mcp__tauri__webview_screenshotを呼び出していること。- 操作後の状態を確認していること:DB クエリ、DOM スナップショット、またはスクリーンショットで確認できる証拠。
tdd-session-audit.sh の Stop フックは、tauri テンプレートを介して(1)、(2)、(5)を自動的に確認します。(3)、(4)、(6)はエージェントの責任です。
フローとの関係
flowchart LR
A["/agile-story"] --> B[TDD cycle]
B --> C[Red: failing test]
C --> D[Green: minimum code]
D --> E[Refactor]
E --> F{More?}
F -->|Yes| C
F -->|No| G["/agile-refinement"]
このスキルは実行中に動作します。構築する内容を定義する /agile-story と連携し、結果を検証する /agile-refinement に情報を渡します。オプションの強制機能がインストールされている場合、このルールは Write/Edit/MultiEdit ツールの呼び出しごとにも自動的に適用されます。