debug-app について
debug-appは、モバイルアプリ開発者向けのデバッグスキルです。プロジェクト内のMetroログを監視して実行時・バンドルエラーを調べ、影響箇所の編集や起動診断を行います。
主な機能
- 01プロジェクト内のMetroログ監視
- 02実行時・バンドルエラーの検出
- 03該当ファイルの自律的な編集
- 04症状に基づくデータ経路の追跡
- 05起動診断と状態確認
- 06監視のみのモード
活用シーン
- 01アプリ起動やデバイス表示の失敗調査
- 02画面の空白やリスト欠落の診断
- 03新たに記録されたMetroエラーの監視
- 04プロジェクトを変更せずに問題を調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ microsoft/ power-platform-skills --skill debug-appインストール後、Claude Code で/debug-appを入力して読み込まれたか確認します。
同梱ファイルreferences/startup-diagnostics.md
詳細
翻訳後に原文が更新されています。最新の内容は原文をご確認ください。
プラグインの確認:
node "${PLUGIN_ROOT}/scripts/check-version.js"を実行します。メッセージが出力された場合は、続行する前にユーザーに表示してください。
📋 共通の手順:shared-instructions.md — 最初にお読みください。
アプリのデバッグ — 監視と修正
metro.config.js が書き込むプロジェクトローカルの .powernative/metro-logs/ ファイルを通じて実行中のアプリを監視し、実行時エラーとバンドルエラーを検出して、影響を受けるファイルを編集することで自律的に修正します(修正が Dataverse スキーマや認証登録などのドメインに属する場合は、適切なスキルに振り分けます)。サイレントな失敗の場合は、データパスの境界に一時的な console.log ステートメントを挿入し、新たに追記されたログのバイトのみを読み取り、根本原因を修正した後にトレースを削除します。上流の app-debugger.agent.md パターンをもとにしており、フォアグラウンドループ、上限付きポーリング、クリーンチェック/タイムアウトによる終了の設定、監視のみのオプションに対応しています。
**開発クライアントの制限事項:**スタンドアロンの開発クライアントは、アプリ/ランタイムのログ、React エラー、ホスト診断、Metro バンドラーの出力を Metro 経由で送信します。テンプレートの
metro.config.jsは、Metro のターミナル出力と HTTP バンドルエラーを.powernative/metro-logs/に書き込みます。別のデバイスログソースはありません。ホスト診断には、[AuthProvider] MSAL init failed:、[bridge] fetch THREW for、[bridge] HTTP <status> for、[addAadAppToConnectionAcl] failed HTTP <status> for connection、[useConnectionRefs] could not verify connection ACLs; treating existing connections as setup-required、[PAHost][ErrorBoundary] Unhandled JS error:などの文字列が含まれます。
サブコマンド($ARGUMENTS から解析)
| 形式 | 動作 |
|---|---|
/debug-app(引数なし) | デフォルト — プロジェクトログ主導モード。 フェーズ 0 を実行し、有効なプロジェクトローカルの Metro セッションを検出します。稼働中のセッションが 1 つの場合は自動的に選択し、複数ある場合は選択を求めてから、選択したログを監視します。ホストターミナル ID は不要です。 |
/debug-app "<症状のテキスト>" | 症状主導モード(ユーザーに見える問題がある場合に推奨)。"todos not appearing on home screen"、"login button does nothing"、"list empty after refresh" などの自由記述による症状を指定します。フェーズ 0 → フェーズ 0.5(症状を解析 → ユーザーに再現/画面遷移を依頼 → ターミナルトレースから可能性の高いデータパスをたどる)を実行してから、監視ループに入ります。通常のログポーリングでは見逃すサイレントな失敗(空のリスト、空白画面、握りつぶされたエラー)を検出します。 |
/debug-app status | すべてのプロジェクトローカルの Metro ログを検出し、有効な各セッションのプロジェクト、プラットフォーム、PID、ポート、開始時刻、ログパスを出力します。保存済みカーソルが参照するセッションがあればそれを示し、その後、修正内容と未解決のエラーを出力します。選択を求めたり、ループに入ったりしてはいけません。 |
/debug-app stop | フォアグラウンドのデバッグループのみを停止し、.powernative/debug-app/ の状態を保持します。Metro は停止しません。npm run dev プロセスはユーザーが管理します。 |
/debug-app version | ${PLUGIN_ROOT}/.plugin/plugin.json から、インストール済みの mobile-app プラグイン名とバージョンを出力して終了します。 |
監視オプション
オプションは、デフォルトのコマンド、症状、または status の後に指定できます。
| オプション | 意味 | デフォルト |
|---|---|---|
--working-dir <path> | package.json と metro.config.js を含むアプリのルートです。相対パスは、現在のシェルディレクトリを基準に解決されます。 | 現在のシェルディレクトリ |
--port <1-65535> | このポートの有効な Metro セッションのみを監視します。 | 任意のポート |
--platform <ios|android> | 最近のログでこのプラットフォームが特定されたセッションのみを対象とします。 | 任意のプラットフォーム |
--cycles <1-50> | クリーンな観測間隔がこの回数連続した後に終了します。 | 3 |
--timeout <duration> | 監視時間の最大値です。s、m、または h を使用して、30s~60m を指定します。 | 5m |
--no-fix | 監視のみのモードです。分類と報告を行いますが、プロジェクトのソースや設定の編集、トレースの挿入、依存関係のインストール、ファイルの再生成、変更を伴う引き継ぎの呼び出しは行いません。デバッグカーソル/監査/ヘルス状態は引き続き更新されます。 | 修正有効 |
例:
/debug-app --port 8082 --platform ios
/debug-app "orders screen is empty" --cycles 10 --timeout 15m
/debug-app --no-fix --timeout 30m
/debug-app status --platform android
/debug-app status --working-dir ../my-mobile-app
引数の解析:
- 引用符で囲まれたテキストは1つの症状値として解析し、認識されたフラグは場所を問わず解析します。
- 最初に現れる予約語トークン(
status、stop、help、--help、-h、version、--version)でサブコマンドを選択します。stop、ヘルプ、バージョンでは監視オプションを指定できません。statusでは--working-dir、--port、--platformのみ指定できます。ループに入らないため、症状、--cycles、--timeout、--no-fixは拒否します。 - 認識されたオプションとその値を取り除いた後、残った予約語以外のテキストは症状となり、症状モードが有効になります。
- 不明なフラグ、重複したフラグ、値の不足、無効な数値、サポートされていないプラットフォーム、または自由入力の症状が複数ある場合は拒否します。有効な形式を表示して、監視せずに終了します。
platformは小文字に正規化します。timeoutはtimeoutSecondsに変換し、30 <= timeoutSeconds <= 3600を必須とします。監視とstatusでは、--working-dirまたは現在のシェルディレクトリからworkingDirを絶対パスとして解決します。親ディレクトリは検索しません。そのルートにpackage.jsonとmetro.config.jsがあることを必須とします。ない場合は無効なパスを表示し、プロジェクトの状態を読み書きする前に停止します。検証後、workingDirへ一度だけcdし、結果の絶対パス$PWDで値をリセットします。以下のすべての相対プロジェクトパスとコマンドは、このディレクトリから実行します。- 初期化します:
workingDir=<absolute app root> portFilter=<number|none> platformFilter=<ios|android|none> targetCleanCycles=<number, default 3> timeoutSeconds=<number, default 300> noFix=<true|false, default false> monitorStartedAt=<current ISO timestamp>
help/--help/-h の場合は、サブコマンドの表と監視オプションの表を表示して終了します。
早期リターンするサブコマンド:
stop:このフォアグラウンドループが会話を所有している間に受信した場合、Phase 0.5.5 を使って挿入済みのトレースをクリーンアップし、次の安全なタイミングで終了します。単独のstop呼び出しでは、アクティブなループがないことを報告します。Metro を停止したり、.powernative/debug-app/の状態を削除したりしないでください。version/--version:${PLUGIN_ROOT}/.plugin/plugin.jsonを読み取り、<name> <version>を表示して、プロジェクトを解決したり状態を書き込んだりせずに終了します。マニフェストがない、または不正な形式の場合は、プラグインのバージョンを取得できないことを報告して終了します。status:workingDirを検証し、以下の status 分岐を通じて Phase 0.0 の検出のみを実行します。プロジェクトの事前チェック、状態ファイルの作成、セッションの確認、ベースラインの初期化、監視ループへの移行は行いません。
ヒント —「少し試してからデバッグ」: Metro は、チャット/エディターを再起動しても、最近のアプリ出力を .powernative/metro-logs/ に保持します。何かおかしなことが起きたら、そのままアプリを使い続けてから、/debug-app または /debug-app "<what you saw>" を実行してください。最初のサイクルでは、保持されている最新のログ範囲を読み取ります。以降のサイクルでは、保存済みカーソル以降に追加されたバイトのみを読み取ります。
Core Principles
- フォアグラウンドでの自律ループ — 起動すると、このスキルは
targetCleanCycles回連続で問題のないポーリングが行われてアプリの正常性が確認される、timeoutSecondsが経過する、ユーザーがstopと入力する、またはエスカレーションルールが適用されるまで、会話を占有します。他のスキルを同時に実行しないでください — ループの後ろにキューイングされます。 - 監視のみの場合、プロジェクトは変更しません —
--no-fixを指定した場合、プロジェクトのソースや設定の編集、診断ログの挿入、パッケージのインストール、スキーマの再生成、アカウントの切り替え、変更を加えるスキルの実行は行わないでください。.powernative/debug-app/のカーソル/監査/ヘルス状態の更新、エラーの分類、実施するはずだった修正や引き継ぎの提示は続けてください。 - アプリの読み込み後に実行 — Metro は
npm run devで起動し、シミュレーターまたはデバイスでアプリを開いておく必要があります。フェーズ 0 で.powernativeのログが存在することを確認し、アプリが検出されない場合はスキルを正常に停止します。 - ネイティブ専用の実行ターゲット — アプリはデバイスまたはシミュレーター上のネイティブ開発クライアントに読み込まれている必要があります。そのネイティブセッションでは、
.powernative/metro-logs/が唯一の正式なログソースです。 - Web または Metro への直接プローブは禁止 — 実行時診断に React Native Web、ブラウザー自動化、
curl、fetch、WebFetch、または Metro/localhost エンドポイントへの直接リクエストを使用しないでください。.powernativeのログとソースファイルのみを読み取ってください。 - 画面ごとの検証は禁止 — ルートを巡回したり、すべての画面を検証したりしないでください。症状モードでは、ユーザーが報告したワークフローと、診断に必要なターミナル/ソースの証拠だけに注目してください。
- 修正は一度に 1 つ — 次の問題に取りかかる前に、1 つの問題を完全に解決してください(状況把握 → 修正 → 型チェック → リロード → 再ポーリング)。まとめて処理しないでください。
- 作業ディレクトリの状態 — デバッグ監査状態は
.powernative/debug-app/に保存されます。ファイルはfixes.md、unresolved.md、injected-logs.md、health.json、metro-cursor.jsonです。Metro のログは、すでに Git の追跡対象外になっている.powernative/metro-logs/に保存されます。どちらもチャットやエディターを再起動しても維持され、特定のエージェントホストにはひも付きません。 - 多層防御による秘匿化 — Metro ロガーは
.powernativeに書き込む前に、認証情報のような行を削除します。ただし、/debug-app側でも、.powernative/debug-app/に値を永続化する前に、個別に最小化とサニタイズを行う必要があります。生のレスポンス本文、レコードオブジェクト、トークン、ヘッダー、トレースのペイロード、絶対パス形式のホームディレクトリパスを、デバッガーの状態にコピーしないでください。 - ログの識別子はポートです — 開発サーバーのポート番号は、QR コードにエンコードされ、デバイスが接続し、このスキルが検証する番号です。稼働状況はソケットプローブで確認します(ログの PID がそのポートを引き続き保持しているか)。ターミナルのスクロールバックは使用しません。
port-takenのステータスは、ログが停止済みのセッションに属することを示すため、診断してはいけません。 - 過去の問題は修正しない — ログは過去の記録であるため、ログ内のエラーは現在の問題を証明するものではありません。ベースライン期間に見つかったエラーは、コードを編集する前にフェーズ 0.2.1 の後続確認を通過する必要があります。すでに解決済みのエラーを追って動作中のコードを編集するのは、何も報告しないより悪い結果です。
- ファーストパーティのネイティブパッケージは変更不可の境界です —
node_modules/@microsoft/power-apps-native-*内のフレームは証拠ではありますが、パッケージが原因であることの証明ではありません。まず、アプリの入力が無効でないか、構成がサポートされているか、パッケージのドキュメントに記載された API の使い方が正しいかを確認してください。インストール済みの@microsoft/power-apps-native-*パッケージ内部の不具合であることが証拠によって確認されたら、顧客プロジェクト側の回避策を適用しないでください。node_modules/の編集、patch-packageパッチや postinstall による書き換えの作成、パッケージソースの同梱やフォーク、Metro/Babel/TypeScript のエイリアスによるパッケージのリダイレクト、依存関係の git、tarball、ローカルフォークへの置き換えは禁止です。サニタイズしたパッケージ不具合レポートを記録し、ユーザーを/report-issueに案内してください。 - ホストのターミナル API は任意の場合のみ使用可能 — 現在のホストが Metro のターミナル出力をすでに提供している場合は、低遅延の補助情報として参照してもかまいません。ターミナル ID をユーザーに尋ねたり、保存したりしないでください。また、正式な
.powernativeログのカーソルも進めずに、ホストの出力だけから診断しないでください。 - コンテキストを優先した診断 —
memory-bank.mdがある場合は読み取ってください。環境、Dataverse、コネクターのコンテキストを把握するにはpower.config.jsonを読み取ってください。失敗が計画された画面、データモデル、コネクター、オフラインプロファイル、ネイティブ機能に関係する場合に限り、native-app-plan.mdを参照してください。無関係な構文/実行時エラーのために解析しないでください。 - 参照情報を確認する順序 — Dataverse/Power Platform のエラーの場合は、まず skills/add-dataverse/references/dataverse-reference.md を読み取り、生成されたサービス/モデルとプロジェクトのコンテキストを確認してください。その後も動作が不明な場合は、
mcp__plugin_mobile-app_microsoft-learn__microsoft_docs_searchを呼び出してください。Expo/Expo Router/React Native のエラーの場合は、まずインストール済みのバージョンとプロジェクトコードを確認し、その後、公式ドキュメントhttps://docs.expo.dev/を対象にWebFetchを使用してください。次にパッケージのドキュメントを確認し、一般的な Web 検索は最後の手段としてのみ使用してください。
ワークフロー — タスクリストを最初に作成
モニターループに入る前にタスクリストを作成し、最新の状態に保ってください。
- [ ] Discover valid `.powernative` Metro sessions and select one when needed
- [ ] Capture baseline log state from the selected session and save its byte cursor
- [ ] (Symptom mode only) Phase 0.5: parse symptom → ask user to navigate → inject console.logs → read new log bytes → walk data path → clean up logs
- [ ] Monitoring cycle 1: collect → classify → fix if needed
- [ ] Monitoring cycle 2: collect → classify → fix if needed
- [ ] Monitoring cycle 3: collect → classify → fix if needed
(add cycles as needed; after <targetCleanCycles> consecutive clean cycles, use the resolved/flagged/pending symptom outcome)
- [ ] Fix: <error summary> → <inline edit | skill route> (one task per error found)
次のサイクルを始める前に、各サイクルを完了(問題なし、または修正済み)としてマークしてください。
フェーズ 0 — 起動チェック
ループに入る前に、以下を実行してください。
0.preflight プロジェクトのコンテキストを確認する
ログを診断する前に、共通の指示に従ってください。
このワークフローでは、引数の解析で取得した workingDir を <working_dir> として使用してください。これはすでにアプリのルートとして検証済みです。後続フェーズから再導出したり、気付かないうちに別のプロジェクトに切り替えたりしないでください。
<working_dir>/memory-bank.mdが存在する場合は、その「プロジェクトの事実」「Power Platform のコンテキスト」「データモデル」「コネクタ」「画面」「ネイティブ機能」「ビルド履歴」を読み取ってください。/debug-appからメモリーバンクを作成しないでください。存在しなくても問題ありません。<working_dir>/power.config.jsonが存在する場合は読み取ってください。environmentId、databaseReferences、connectionReferencesを取得します。環境の情報源にはpower.config.jsonを優先してください。- 指定された症状または分類されたエラーが、計画された画面、Dataverse のエンティティ/列、コネクタ、オフライン動作、ナビゲーション契約、またはネイティブ機能に関係する場合に限り、
<working_dir>/native-app-plan.mdを読み取ってください。この計画は意図された設計として扱い、実際のスキーマやランタイム状態の証拠とはみなさないでください。 - 影響を受けるデータパスで使用される場合に限り、
src/generated/services/、src/generated/models/、src/generated/connectorSchemas.tsを調査してください。生成ファイルは編集しないでください。
フェーズ 0.1 で fixes.md を作成した後、簡潔なコンテキスト行を追記してください。
[<HH:MM:SS>] Context — memory-bank=<present|absent> native-plan=<present|absent|not-needed> environment=<environmentId|none> dataverse-tables=<N> connectors=<N>
通常のバンドル、React、またはローカル JavaScript のエラーでは、環境を特定したり、Dataverse を呼び出したりしないでください。現在の症状/エラーが Dataverse または Power Platform 関連の場合は、引き継ぎの前に D2 の読み取り専用 Dataverse 診断手順を実施してください。
0.0 プロジェクト内の Metro セッションを検出して選択する
引数の解析で取得した、検証済みの <working_dir> を使用してください。該当するログをすべて新しい順に列挙します。
LOG_DIR='<working_dir>/.powernative/metro-logs'
ls -t "$LOG_DIR"/metro-*-pid-*-port-*.log 2>/dev/null
候補ごとに、以下を解析してください。
metro-<timestamp>-pid-<pid>-port-<port>.logからpidとportを取得します。- ファイル名のタイムスタンプから
startedAtを取得します。 power.config.json.appDisplayNameからprojectを取得し、存在しない場合は<working_dir>のベース名を使用します。- 最新 64 KiB のみを走査し、最も新しい
iOS ... Bundled/iOS BundlingまたはAndroid ... Bundled/Android Bundlingの行からplatformを取得します。どちらも見つからない場合はunknownを使用します。
記録された PID をすべて、クロスプラットフォーム対応の Node プローブで確認してください。process.kill(pid, 0) が成功すれば稼働中とみなし、EPERM も稼働中、それ以外のエラーは停止中として扱います。port が数値の場合は、macOS/Linux では利用可能であれば lsof -nP -iTCP:<port> -sTCP:LISTEN -t、Git Bash/Windows では netstat.exe -ano -p tcp を使用してポートの所有者を確認します。lsof のない Linux では、利用可能であれば ss -ltnp を使用します。候補が有効/稼働中とみなされるのは、PID が稼働中であり、かつ記録されたポートを所有している場合、port=unknown の場合、または利用可能なポート所有者プローブがない場合に限ります。プローブが実行され、別の PID が報告された場合は、プローブが利用できないのではなく矛盾として扱います。ターミナル ID を保存したり、ターミナル出力に依存したりしないでください。
選択ルール:
- 選択前に、有効/稼働中の候補に
portFilterとplatformFilterを適用してください。有効なセッションが該当しない場合は、フィルターと利用可能な有効セッションを表示して停止してください。プラットフォームフィルターに該当する候補がunknownの場合は推測せず、--portを使用するか--platformを省略するようユーザーに伝えてください。 - 有効なセッションが 1 つ — 自動的に選択します。
- 有効なセッションが複数 — セッションごとに、以下の正確な形式で選択肢を表示し、どれを監視するか尋ねてください。
<project> — <platform> — port <port> — pid <pid> — started <startedAt>AskUserQuestionを使用してください。選択肢を内部的に識別する際は、ポートだけではなく、完全なlogPath+pid+portを使用してください。metro-cursor.jsonが有効なセッションのいずれかを指している場合、そのセッションをデフォルトの選択肢にしますが、必ずユーザーに確認してください。稼働中のセッションが複数ある場合、新しいセッションを暗黙に選択しないでください。 - 有効なセッションがない — 以下の失敗時の分岐を適用してください。古いログや矛盾するログはレポートの根拠として使用し、選択可能な候補にはしないでください。
statusブランチ — 選択前に終了: フィルタリングと稼働確認の後、.powernative/debug-app/metro-cursor.jsonが空でない有効な JSON であり、文字列のlogPath、数値のpid、および数値またはunknownのportを含む場合に限り読み取ります。カーソルが存在しない、空である、形式が不正である、または形状が無効である場合は、存在しないものとして扱い、警告を表示します。statusからカーソルを上書きしてはいけません。有効なセッションをすべて通常のセッション表示形式で新しい順に表示し、有効なカーソルとlogPath+pid+portが一致する場合に限り[saved]を付けます。その後、fixes.mdとunresolved.mdから空でない行を最大 20 行ずつ表示します。表示するテキストは、先に永続化用の秘匿化処理を通してください。古い候補や矛盾する候補の件数は表示しますが、そのログ内容をもとに診断してはいけません。その後、終了します。有効なセッションがない場合は、その結果と該当するログなし/古いログの理由を表示して終了します。
監視モードでのみ、上記のルールに従ってセッションを選択します。選択後、選ばれた候補から LOG_PATH、pid、port、project、platform、startedAt を設定します。この選択は、現在の監視実行中は固定されます。
ログがない場合は、失敗時の分岐を選ぶ前に metro.config.js を調べ、<working_dir> からロギングモジュールを解決します。
- 現在のファクトリー形式: 設定で
@microsoft/power-apps-native-host/config/metroConfigのcreatePowerAppsMetroConfigを使用しており、プロジェクトにインストールされた依存関係からその正確なサブパスを解決できます。ファクトリーが内部でプロジェクトローカルのロギングを設定します。 - レガシーな直接指定形式: 設定で
@microsoft/power-apps-native-host/metro-loggerを直接インポートしており、プロジェクトにインストールされた依存関係からその正確なサブパスを解決できます。 - 利用不可: どちらの設定済みサブパスも解決できない、参照されている形式が存在しない、または
package.jsonに@microsoft/power-apps-native-hostがない場合です。依存関係のバージョン文字列だけでは、設定されたエクスポートが存在する証明にはなりません。
次のように分岐します。
| 状態 | 意味 | 対応 |
|---|---|---|
| 有効なログがちょうど 1 つあり、PID が稼働中で、ポートが不明またはポートプローブを利用できない | そのログを選択します。project、platform、startedAt、port、pid、logPath を取得して続行します。 | |
| 有効なログがちょうど 1 つあり、PID が記録されたポートを引き続き所有している | そのログを選択します。project、platform、startedAt、port、pid、logPath を取得して続行します。 | |
| 有効なログが複数ある | 有効なセッションをすべて表示し、どのセッションを監視するかユーザーに尋ねます。新しさだけを基準に選択してはいけません。 | |
| ログはあるが、PID が終了しており、別のプロセスが記録されたポートを所有している | このログをもとに診断してはいけません。ポートを保持している PID をユーザーに伝え、npm run dev を再起動するよう依頼します。 | |
| ログはあるが、PID とポートが矛盾している | デバイスが誤ったサーバーと通信している可能性があります。古い Metro プロセスを停止し、npm run dev を再実行するようユーザーに依頼します。 | |
| ログがなく、ロギング形式を利用できない | このプロジェクトはプロジェクトローカルの Metro ロギング導入以前のものか、依存関係が不完全です。停止し、設定形式、依存関係の宣言、または解決可能なエクスポートのうち、不足しているものを報告します。再起動ループに入ったり、/debug-app からユーザー所有の設定を編集したりしてはいけません。ユーザーはまず、現在のテンプレートの Metro 設定とホスト依存関係を採用する必要があります。 | |
| ログがなく、現在のファクトリー形式またはレガシーな直接指定のロギング形式を解決できる | ホストの出力に [powernative] Metro logging instrumentation failed が含まれている場合は、そのフェーズとプロジェクト相対のログパスを報告します。ホストは意図的にフェイルオープンするため、ファイルがなくても Metro は稼働し続けることがあります。それ以外の場合は、Metro が実行されていないか、.powernative ログがまだ出力されていないことを伝えます。npm run dev を実行し、ネイティブアプリを開いてから /debug-app を再実行するよう依頼します。 |
PID/ポートの確認により、古いログをもとにした診断を防げます。ログファイルは Metro プロセスの終了後も残ることがあるため、ログがテスト対象のアプリに対応しなくなったことを明らかにできるのは、ソケットプローブだけです。明示的に選択してもらうことで、同じプロジェクト内のあるポートの有効なセッションを、別の有効なセッションと取り違えることを防げます。
.powernative ログが存在しないものの、ホストが実行中の Metro ターミナルを公開している場合、その出力から何が実行中かを把握できることがあります。ただし、ターミナル ID を尋ねたり保存したりせず、そのターミナルに対して継続的なモニターループを開始しないでください。Metro の設定でログを作成できるよう、npm run dev で再起動するようユーザーに依頼してください。
安定したソースを fixes.md に記録します。
[<HH:MM:SS>] Log source — <project> <platform> — <logPath> (pid <pid>, port <port>, started <startedAt>)
0.1 状態ディレクトリを確保する
mkdir -p .powernative/debug-app
touch .powernative/debug-app/fixes.md
touch .powernative/debug-app/unresolved.md
touch .powernative/debug-app/injected-logs.md
touch .powernative/debug-app/health.json
touch .powernative/debug-app/metro-cursor.json
rm -f .powernative/debug-app/symptom-state # per-session — Phase 0.5 rewrites it if symptom mode is active
fixes.md が空の場合は、セッションヘッダーを書き込みます:
# Debug session — <date>
実効的な呼び出し設定を追記します:
[<HH:MM:SS>] Monitor config — port=<any|port> platform=<any|ios|android> clean-cycles=<targetCleanCycles> timeout=<timeoutSeconds>s no-fix=<true|false>
0.1.1 ヘルス状態を初期化する
生のログ内容を含めずに .powernative/debug-app/health.json を書き込みます:
{
"bundle": { "status": "unknown", "summary": "No evidence yet" },
"runtime": { "status": "unknown", "summary": "No evidence yet" },
"authentication": { "status": "unknown", "summary": "No evidence yet" },
"dataverse": { "status": "unknown", "summary": "No evidence yet" },
"connector": { "status": "unknown", "summary": "No evidence yet" },
"offline": { "status": "unknown", "summary": "No evidence yet" },
"navigation": { "status": "unknown", "summary": "No evidence yet" },
"nativeCapability": { "status": "unknown", "summary": "No evidence yet" },
"updatedAt": "<ISO timestamp>"
}
許可されるステータスは healthy、degraded、failed、unknown、not-configured です。シグナルを分類するたびに、影響を受けるドメインのみを更新します:
| シグナル | ヘルス状態の更新 |
|---|---|
| 最新のバンドルエラー後にネイティブバンドルが成功 | bundle=healthy |
| バンドル/変換/インポートの失敗 | bundle=failed |
| 捕捉されていない JS/React エラー | runtime=failed;修復後のワークフローで新しい出力が正常になったら healthy に設定 |
| 認証の成功/失敗に関するホスト診断 | `authentication=healthy |
| 対象の操作に対する Dataverse の 2xx/エラー | `dataverse=healthy |
| コネクターの解決/呼び出しの成功または失敗 | `connector=healthy |
| オフラインプロファイルがない | offline=not-configured;オフラインの有効化/同期に関する警告または失敗 → `degraded |
| 確認済みのルート/ナビゲーションエラー | navigation=failed;修復後にルートを確認できたら healthy |
| ネイティブラッパーの成功、権限拒否、モジュール不足、またはネイティブの失敗 | `nativeCapability=healthy |
証拠がない場合は unknown のままにします。観測していないドメインを healthy にしてはいけません。
0.1.2 永続化前の秘匿情報除去ゲート
診断テキストを fixes.md または unresolved.md に追記する前、あるいはヘルス状態の summary を保存する前に、秘匿情報を除去します:
- プロジェクトパスを
<working_dir>からの相対パスに変換します。その他の絶対ホームディレクトリパスは[REDACTED_PATH]に置き換えます。 - 認証/Cookie/シークレットのヘッダー全体(
Authorization、Proxy-Authorization、Cookie、Set-Cookie、x-api-key、api-key、client-secret、およびトークンヘッダー)を[REDACTED_HEADER]に置き換えます。 - Bearer 値、JWT に類似した 3 セグメントの値、SAS/クエリのシークレット(
sig、se、sp、sv、code、token、access_token、refresh_token、id_token、client_secret)、パスワード、API キーを[REDACTED_SECRET]に置き換えます。 - メールアドレスは
[REDACTED_EMAIL]に、GUID/レコード識別子は、機密情報ではないローカル PID/ポートを除き、[REDACTED_ID]に置き換えます。 - Dataverse/コネクターのレスポンス本文や、任意の
[TRACE]オブジェクト値は決して永続化しないでください。ステータス、ソース/設定のテーブル名または列名、件数、エラーコード、および長さを制限したエラーメッセージのみを永続化します。 - 除去済みの結果をもう一度スキャンします。機密情報のパターンが残っている場合は、代わりに
[REDACTION_BLOCKED: diagnostic omitted]を永続化します。
書き込む前に、候補となる診断情報ごとに同梱の検証ツールを実行します:
printf '%s' "$DIAGNOSTIC_SUMMARY" | node \
"${PLUGIN_ROOT}/scripts/redact-debug-diagnostic.js" \
--working-dir '<working_dir>'
検証ツールの標準出力のみを永続化します。まず最小限のフィールドから DIAGNOSTIC_SUMMARY を作成してください。Metro のウィンドウ全体やレスポンス本文を渡し、秘匿情報除去によって安全にすることに頼らないでください。
metro-cursor.json の logPath は <working_dir> からの相対パスで保存し、読み込む際は <working_dir> を基準に解決します。このゲートは必須です。.powernative のログがすでに秘匿情報除去済みであっても省略できません。
0.2 Metro がバンドル済みで、アプリが実行中であることを確認する
テレメトリのチェックポイント:validate_metro_session
範囲を限定したベースラインウィンドウを読み取り、実際のバイトカーソルを返します:
node - "$LOG_PATH" 262144 <<'NODE'
const fs = require('node:fs');
const [file, maxText] = process.argv.slice(2);
const maxBytes = Number(maxText);
const size = fs.statSync(file).size;
const start = Math.max(0, size - maxBytes);
const fd = fs.openSync(file, 'r');
const buffer = Buffer.alloc(size - start);
const bytesRead = fs.readSync(fd, buffer, 0, buffer.length, start);
fs.closeSync(fd);
process.stdout.write(JSON.stringify({
cursor: start,
nextCursor: start + bytesRead,
truncated: start > 0,
output: buffer.subarray(0, bytesRead).toString('utf8')
}, null, 2));
NODE
ロガーは最初に port-unknown を書き込み、そのファイルを数値のポート名にアトミックに変更する場合があります。ベースラインの読み取りで ENOENT が発生した場合は、失敗を報告する前に一度だけ再検出してください。同じファイル名のタイムスタンプと PID が存在し、現在のポートが数値になっている場合は、LOG_PATH と port をそのファイルに更新し、範囲を限定した読み取りを一度だけ再試行してください。両方の名前を別々のセッションとして処理してはいけません。
output、cursor、nextCursor、truncated を解析し、Phase 0.0 で解決した pid、port、logPath を使用します。output をスキャンします:
- 最も新しいエラークラスの行が
SyntaxError、Unable to resolve module、transform failed、またはerror: Bundling failedの場合 → バンドルが壊れています。Step B の「インポート/バンドル」の重大なエラーとして扱い、直ちに Step D に進みます。バンドルが正常になるまで、定常状態のループに入ってはいけません。 outputにBundling complete/iOS Bundled/Android Bundledが含まれ、その後にエラークラスの行がない場合 → Metro は正常です。続行します。outputに Metro のバナー(Metro waiting on、Logs for your project、または› Metro:)が含まれているものの、ネイティブのBundled/bundling行がまだない場合 → Metro は起動していますが、ネイティブクライアントが接続していません。ユーザーに次のように伝えます:Metro は実行中ですが、アプリはまだ接続されていません。 デバイスまたはシミュレーターでアプリを開いてから、
/debug-appを再実行してください。 ここで停止します。- 選択した PID/ポートのセッションが有効なまま、ロガーの起動行しか含まれていない場合 → Metro から十分な状態情報がまだ出力されていません。ネイティブ URL が表示されるまで待ってから
/debug-appを再実行するようユーザーに伝え、準備が整っていると推測してはいけません。
truncated: true の場合、ベースラインの対象は直近の 256 KiB のみです。以前の履歴が省略されたことを記録し、セッション履歴全体を確認したと主張してはいけません。
カーソルを初期化する前に、この最初のウィンドウに含まれる分類可能なエントリーをすべて Step B に渡してください。JS ランタイムエラー、React の警告、ネットワーク/API の失敗、ネイティブエラー、ホストの診断情報が含まれます。バンドルエラーではないからといって、以前のエラーを飛ばしてはいけません。これにより、症状がすでに発生した後でも「試してからデバッグする」という約束を守れます。
0.2.1 上書き解決 — ログですでに解決済みと示されているエラーを再修正しない
ベースラインウィンドウは履歴であり、現在の状態ではありません。すでに修正済みのエラー、ユーザーが自分で解決したエラー、一時的に発生したエラーが含まれていることがあります。それらを修正するのは何もしないより悪い結果になります。存在しなくなった症状を追って動作中のコードを変更することになり、エラーを再現できないため「修正」を検証できないからです。
そのため、ベースラインウィンドウのみ(後続のポーリングを除く)で見つかったすべてのエラーは、上書き解決の有無を確認するまで未確認として扱います。エラー行からウィンドウの末尾まで先を確認します。
| エラーの種類 | 後続の行に次の内容が示されている場合は上書き解決済み |
|---|---|
| インポート/バンドル | Bundling complete、iOS Bundled、または Android Bundled |
| ネットワーク/API | 以前失敗したものと同じルート/リソースへの 2xx |
| JS ランタイム/React | その後にアプリが再読み込みされた、またはバンドルに成功しており、その後エラーが再発していない |
ホスト診断([AuthProvider]、[bridge]、…) | 同じサブシステムからの後続の成功(例:acquireTokenSilent failed の後にトークンが取得された) |
そのうえで、次のように対応します。
- 上書き解決済み → 修正しないでください。記録して次に進みます。
[<HH:MM:SS>] Observed (already resolved, not fixed) — <error summary> — superseded by <evidence line> - 上書き解決されていない → エラーは現在も発生しています。ステップ D に沿って通常どおり修正します。
- 曖昧(上書き解決を示す明確な証拠がない) → まだコードを編集しないでください。ユーザーにまだ発生しているか確認するか、次のポーリングで再発するまで待ちます。カーソルが進んだ後に再発したエラーは、現在も発生していることが確認済みです。
これはベースラインウィンドウにのみ適用されます。後続の tail --cursor ポーリングに現れるものは、定義上、新しい出力であり、上書き解決の確認は不要です。
症状モードでは、このルールより症状が優先されます。 ユーザーが症状を提示した場合、それは問題が現在も発生していることを示す直接的な証拠です。そのため、後続の行が上書き解決を示しているように見えても、対応するベースラインエラーは現在も発生しているものとして扱います。
0.3 ベースラインを記録する
テレメトリチェックポイント:capture_runtime_baseline
フェーズ 0.2 の出力を使用します。最後にバンドルされたネイティブプラットフォーム(iOS/Android)と、最近のランタイムログ行を確認します。fixes.md に追記します。
[<HH:MM:SS>] Baseline — last Metro activity: <1-line summary of most recent lines>
0.4 永続的なバイトカーソルを初期化する
構造化 JSON を使用して .powernative/debug-app/metro-cursor.json に書き込みます。
{
"logPath": ".powernative/metro-logs/metro-<timestamp>-pid-12345-port-8081.log",
"pid": 12345,
"port": 8081,
"project": "My Mobile App",
"platform": "ios",
"startedAt": "2026-08-27T12:41:32.050Z",
"monitorStartedAt": "<ISO timestamp>",
"monitorConfig": {
"port": null,
"platform": null,
"targetCleanCycles": 3,
"timeoutSeconds": 300,
"noFix": false
},
"cursor": 12345,
"updatedAt": "<ISO timestamp>"
}
フェーズ 0.0 の値を使用して、プロジェクト相対の logPath と、pid、port、project、platform、startedAt を設定します。現在の呼び出しの値を使用して monitorStartedAt と monitorConfig を設定し、フェーズ 0.2 の nextCursor を cursor に設定します。ファイルにアクセスする前に、logPath を <working_dir> を基準として解決します。新しい呼び出しでは、以前の監視設定と開始時刻を必ず置き換えます。後続の呼び出しでは、次のようにします。
-
既存のカーソルは、空ではない有効な JSON で、期待されるフィールド型を備えている場合にのみ解析します。ファイルが存在しない、空、形式が不正、または構造が無効な場合は、保存済みカーソルがないものとして扱い、サニタイズしたリセット警告を
fixes.mdに追記して、選択したセッションの上限付きベースラインから初期化します。以前のデバッグ状態が不完全であることだけを理由に起動を失敗させないでください。 -
logPath、pid、portが同一で、プロセスが引き続きそのポートを使用している場合 → 保存済みカーソルを再利用し、古いエラーを再処理しないようにします。 -
有効なセッションが複数ある場合 → 監視するセッションをユーザーに確認します。保存済みセッションが引き続き有効な場合は、それをデフォルトとして選択します。
-
別のセッションが明示的に選択された場合、または保存済みセッションが無効になった場合 → 古いカーソルを破棄し、選択したセッションの最新ログウィンドウから初期化します。
-
ステップ A から
rotationLost: trueが返された場合 → 返されたリセットカーソルを受け入れ、ファイルの縮小/置換をfixes.mdに記録します。
Phase 0.5 — 症状に応じたセットアップ($ARGUMENTS が症状を表す文字列の場合のみ)
症状が指定されていない場合は、このフェーズ全体をスキップします。標準のログポーリングループは、目に見えるエラーの検出には優れていますが、目に見えないエラーは検出できません。たとえば、コネクターが追加されていないためリストが空になる、useFocusEffect が設定されていないため画面が真っ白になる、カラム名がモデルと一致しないため行が空になる、といったケースです。Phase 0.5 でこのギャップを埋めます。
--no-fix の動作: 症状を解析し、ユーザーに再現を依頼しますが、[INJECTED-TRACE] ログの注入やファイルの編集は行いません。新しい Metro 出力のみを読み取ります。症状が目に見えず、分類可能な出力もない場合は、symptom-state に pending を書き込み、unresolved.md に watch-only: traces not injected を追記してから、標準ループに進みます。
0.5.1 症状を解析する
ユーザーのテキストから、次の3つのシグナルを抽出します。
| シグナル | 導出方法 |
|---|---|
| 影響を受ける画面 | app/ 内のルートファイル名とキーワードを照合します(例:"todos" → app/(tabs)/todos.tsx、app/todos/index.tsx、app/(tabs)/index.tsx)。Glob を使って app/**/*.tsx を列挙し、最も近い部分一致を選びます。複数ある場合は、一度だけ質問します。 |
| 影響を受けるエンティティ/サービス | 同じキーワードを src/generated/services/*Service.ts および src/generated/models/*Model.ts と照合します(例:"todos" → TodosService、Todo モデル)。Glob を使います。 |
| 症状の種類 | テキストを次のいずれかに分類します:empty-list、blank-screen、wrong-data、unresponsive-control、stale-data、wrong-navigation、crash、pdf-viewer、pdf-report、pen-input、geolocation、dataverse-upload。「PDF が開かない/PDF のプレビューに失敗する」のデフォルトは pdf-viewer です。「レポート PDF が生成されない/レポートの印刷に失敗する」のデフォルトは pdf-report です。「署名/ペン/インクに失敗する」のデフォルトは pen-input です。「位置情報が追跡されない/GPS が更新されない/バックグラウンドの位置情報が停止した/ブレッドクラムに抜けがある/ルートが一定しない」のデフォルトは geolocation です。「署名/レポートは保存されたが見つからない」、または「位置情報の行が Dataverse に届かない」のデフォルトは dataverse-upload です。「表示されない/何も表示されない/ここに何もない/見つからない」のデフォルトは empty-list です。「読み込まれない/フリーズする/スピナーが回り続ける」のデフォルトは blank-screen です。 |
fixes.md に追記します:
[<HH:MM:SS>] Symptom — class=<class> screen=<path> entity=<service>
画面/エンティティが一致しない場合は、screen=unknown/entity=unknown のまま処理を進めます。Phase 0.5 では引き続き診断ログを注入し、症状のテキストから最も可能性の高いデータパスを選んでターミナルを読み取ります。
0.5.2 ユーザーに影響を受ける画面への移動を依頼する
dev-player にはナビゲーション用の自動化 API がありません。ユーザーに次のように依頼します:
"デバイス/シミュレーターで
<screen>画面を開き、準備ができたらreadyと返信してください。"
ユーザーが確認するまで待ってから、次に進みます。
0.5.3 診断用の console.log ステートメントを挿入してターミナルを確認する
疑わしいデータパスの境界に対象を絞った console.log ステートメントを挿入し、Metro のターミナルで何が起きているかを確認します。
挿入箇所 — 症状の種類を網羅する最小限の箇所を選びます:
| 症状の種類 | 挿入箇所 |
|---|---|
empty-list | (a)データ取得フックのエントリーポイント。生レスポンスの件数を [TRACE items] として記録します。(b)画面コンポーネント。リストの描画前に items 配列の件数を [TRACE render] として記録します |
blank-screen | 画面コンポーネントのエントリーポイント。必須の認証/データの props が存在するかどうかを示すブール値または件数のみを、タイムスタンプとともに [TRACE mount] として記録します |
wrong-data / stale-data | 生成されたサービスを呼び出すフック(src/generated/ 内ではありません)。許可リストにある要約を [TRACE service-response] として記録します。要約には、結果の件数、エラーの有無、範囲を制限したエラーコード/ステータス、および期待するフィールドの有無を示すブール値を含めます |
unresponsive-control | イベントハンドラー(onPress、onSubmit など)。非同期処理の前に [TRACE handler-called] として記録します |
crash | 挿入はスキップし、モニターループ(ステップ A)に進みます。クラッシュスタックはターミナルに表示されます |
console.log の挿入パターン — 挿入するすべての行は、必ず次の形式にします:
console.log('[TRACE <tag>]', <value>); // [INJECTED-TRACE]
<tag>— この箇所に付ける短く一意なラベル(例:items、render、service-response)// [INJECTED-TRACE]の末尾コメントを同じ行に付けます。これは削除時に grep で検索するキーです- プリミティブ値、または件数、ブール値、範囲を制限したエラー/ステータスコード、設定されたテーブル名/列名のみを含む新規作成の許可リスト内要約だけを記録します。
JSON.stringifyは、その要約に対してのみ使用できます - 生のレコード、レスポンス本文、任意のオブジェクト、フィールド値、ユーザー入力テキスト、認証/データ props の値、識別子、URL、ヘッダー、認証情報は決して記録しないでください。ホストのロガーは認証情報らしき行を削除しますが、任意のアプリデータに機密情報が含まれないことまでは確認できません
src/generated/内には決して挿入しないでください。そこにあるコードを呼び出すフック/画面に挿入します
すべての挿入箇所を .powernative/debug-app/injected-logs.md に記録します:
[<HH:MM:SS>] Injected [INJECTED-TRACE] at <file>:<line> — tag=<tag>
続いて、ユーザーに次のように伝えます:
「診断用の console.log ステートメントを追加しました。Fast Refresh によって自動的に反映されるはずです。
<screen>に移動し、症状が発生する操作(例:リストをスクロールする、ボタンをタップする)を行ってください。アプリが更新されない場合は、ネイティブの dev-client メニューから再読み込みしてください。完了したらdoneと返信してください。」
ユーザーの返信を待ってから、ステップ A の tail --cursor の手順を実行し、nextCursor を保存して、返された output から [TRACE の行を絞り込みます。
0.5.4 ターミナル出力からデータ経路をたどる
[TRACE 行を使って、次の経路をたどります。
-
画面 TSX(
app/<route>.tsx)useListData(...)/use*Data(...)の呼び出しを探します。- サービス呼び出しのオプションを確認します。余分な
top: 0、厳しすぎるfilter、クリアされない入力にバインドされたsearch: query、存在しない列に対するorderByは、いずれもエラーを出さずに行数を 0 件にすることがあります。 - データ取得後にクライアント側の
.filter(...)がないか確認します。
-
データフック(
src/hooks/useListData.tsまたは同種のファイル)- **重要:**テンプレートのフックには、モックへのフォールバック経路が 2 つあります。
- エラー経路:サービスが
{ error }を返す → フックがモックに置き換え、setErrorを呼び出す場合もあります。画面がerrorを無視している場合は、表面化しません。 - 空の結果経路:サービスが
{ data: [] }(エラーなし)を返す → フックが黙ってモックに置き換えます。[TRACE]ログがなければ、必ず見えません。
- エラー経路:サービスが
- 検出方法:画面ファイル内で
MOCK_のインポートをGrepします。見つかった場合は、モックデータが組み込まれています。 useFocusEffectが使われていることを確認します(useEffectではありません)。useEffectは戻る操作で再実行されません。
- **重要:**テンプレートのフックには、モックへのフォールバック経路が 2 つあります。
-
生成されたサービス(
src/generated/services/<Name>Service.ts)- TODO スタブ、またはファイルが見つからない場合は、
/add-connectorまたは/add-dataverseに案内します。src/generated/は編集しないでください。 - ファイルが存在し、
[TRACE service-response]の概要にエラーが表示される場合は、範囲を限定したステータス/エラーコードを使います。401/403 は認証の問題、404 はリソース名の誤りです。メッセージの内容を把握するには、別途出力されるサニタイズ済みのホスト診断情報を使います。生のエラートレースは追加しないでください。
- TODO スタブ、またはファイルが見つからない場合は、
-
生成されたモデル(
src/generated/models/<Name>Model.ts)- フィールド名が画面で参照しているものと一致することを確認します。
item.titleとcr3e9_titleが一致しないと、行が空白になります。
- フィールド名が画面で参照しているものと一致することを確認します。
-
power.config.jsondatasources配列に、問題が疑われるエンティティ/コネクタが含まれていることを確認します。含まれていない場合、そのデータソースに対してpa app add data-sourceが実行されていません。
-
認証状態(
src/playerConfig.ts、app.config.js、auth.config.json、useAuth()フック)- サービスからの 401 は
{ error }としてラップされます。[TRACE service-response]の概要には、エラーオブジェクトやメッセージを保存せずにステータスが表示されます。 - OAuth ディープリンクの受け渡し:
app.config.jsのexpo.schemeがsrc/playerConfig.tsのconnectorOAuthRedirectUriと一致すること、さらに同じリダイレクト URI がauth.config.jsonと Entra ID の登録に含まれていることを確認します。アプリ登録がない場合は、Power Apps Wrap ページの/set-app-registration-nativeにユーザーを案内します。
- サービスからの 401 は
[TRACE の出力を分類します。
| 出力 | 意味 | 次の手順 |
|---|---|---|
[TRACE items] 0 または [] — エラーフィールドなし | サービスが空の結果を返しました — フィルター/クエリ、またはデータが投入されていないことを確認します | クエリを修正します。レコードがない場合は、サンプルデータを投入します |
[TRACE items] undefined | フックが応答を受け取っていません — サービススタブまたはデータソースの不足が考えられます | /add-connector または /add-dataverse に案内します |
[TRACE service-response] にエラーステータス/コードが表示される | サービスで例外が発生しました — 401/403 は認証、404 はリソース名の誤りです | 認証設定を修正するか、pa app add data-source を再実行します |
[TRACE render] の N > 0 だが、リストが空に見える | モデルと画面のフィールド名が一致していません | 画面のフィールド参照をモデルに合わせて修正します |
[TRACE handler-called] が一度も表示されない | onPress が設定されていないか、コンポーネントがマウントされていません | TSX を確認し、イベントのバインドを修正します |
[TRACE 行が一切ない | Metro が古いバンドルをキャッシュしている可能性があります | Metro を停止し、npm run dev -- --clear を再実行してから、ネイティブアプリを再読み込みするようユーザーに依頼します |
結果を .powernative/debug-app/symptom-state に記録します(1 行で resolved、flagged、または pending)。
- 修正方法が明確で、ローカルで対応できる → Step D3 + D4(型チェック + 再読み込み + 再ポーリング)で適用します。修正後、画面を再度操作してターミナルを確認するようユーザーに依頼します。
[TRACE items]行に N > 0 と表示されたら、resolvedと記録します。 - 修正に別のスキルが必要 → ユーザーに伝え、
unresolved.mdに記録します。flaggedと記録します。 - 原因が明らかでない → 構造化したメモを
unresolved.mdに記録します。pendingと記録し、監視ループに入ります。
0.5.5 注入された console.log 文をクリーンアップする
根本原因を特定して修正を適用した後(またはフェーズ 0.5 が終了した後)、注入されたログをすべて削除します。
find app src -type f \( -name '*.js' -o -name '*.jsx' -o -name '*.ts' -o -name '*.tsx' \) \
! -path 'src/generated/*' -exec grep -nH 'INJECTED-TRACE' {} +
該当するファイルごとに、console.log(...); // [INJECTED-TRACE] の行を削除します。次のコマンドで確認します。
find app src -type f \( -name '*.js' -o -name '*.jsx' -o -name '*.ts' -o -name '*.tsx' \) \
! -path 'src/generated/*' -exec grep -nH 'INJECTED-TRACE' {} + # must print zero matches
追跡ファイルをクリアします。
echo '' > .powernative/debug-app/injected-logs.md
クリーンアップ後に npm run type-check を一度実行します。
厳守事項: コード内に
[INJECTED-TRACE]の行を残さないでください。症状がpendingまたはflaggedの場合でも、セッションを完了とする前にクリーンアップしてください。
0.5.6 標準のモニターループに戻る
フェーズ 0.5 が完了したら、モニターループ(ステップ A)に進みます。正常なサイクルは通常どおりカウントしますが、終了方法はステップ C で単一行の symptom-state に基づいて選択します。resolved の場合は正常終了できますが、flagged と pending の場合は targetCleanCycles 経過後に正常終了以外の方法で終了します。症状が flagged または pending の場合、正常終了の結果を報告してはいけません。
モニターループ
targetCleanCycles 回連続で正常なサイクルが完了するまで、timeoutSeconds が経過するまで、ユーザーが stop と入力するまで、またはエスカレーションルールが発動するまで繰り返します。
各ログ収集サイクルの前と、修正の検証直後に、現在時刻を monitorStartedAt と比較します。経過時間が timeoutSeconds 以上になった場合:
- 終了前に
[INJECTED-TRACE]の行をすべてクリーンアップします。 - 経過時間、サイクル数、正常回数、アクティブなセッション ID、未解決の問題数を
fixes.mdに追記します。 - Metro を停止せずに終了します。
⚠ Monitoring timeout reached after <duration>. Session: <project> — <platform> — port <port> — pid <pid> Clean checks: <clean>/<targetCleanCycles> Details: .powernative/debug-app/fixes.md
ステップ A — ログを収集する
テレメトリチェックポイント:collect_runtime_logs
.powernative/debug-app/metro-cursor.json を読み込み、フェーズ 0.0 の検証ロジックを使用して、稼働中のすべての .powernative セッションを再検出します。
- 保存された
logPath、pid、portが引き続き有効な場合は、新しい有効なセッションが出現していても、そのセッションの監視を続けます。現在の実行を中断したり、別のポートに切り替えたりしないでください。 - 保存されたセッションが無効で、有効なセッションがちょうど 1 つ残っている場合は、そのセッションを選択し、新しいベースラインを取得するためにフェーズ 0.2 に戻ります。
- 保存されたセッションが無効で、有効なセッションが複数残っている場合は、セッションの選択肢を表示して監視するセッションを尋ね、その後フェーズ 0.2 に戻ります。
- 有効なセッションが残っていない場合は、古いログを読み込まず、該当するフェーズ 0.0 のエラーで停止します。
それ以外の場合は、固定されたセッションから新たに追記されたバイトを収集します。待機中のバイトがない場合、このフォアグラウンドコレクターはログディレクトリを監視し、そのファイルに変更があるか、5 秒間の監視間隔が完了するまで待機します。
node - "$LOG_PATH" <saved-cursor> 262144 5000 <<'NODE'
const fs = require('node:fs');
const path = require('node:path');
const [file, cursorText, maxText, observationText] = process.argv.slice(2);
const cursor = Number(cursorText);
const maxBytes = Number(maxText);
const observationMs = Number(observationText);
const observedAt = Date.now();
let watcher;
let timer;
let finished = false;
function snapshot(observation) {
try {
const size = fs.statSync(file).size;
const start = Number.isInteger(cursor) && cursor >= 0 && cursor <= size ? cursor : 0;
const fd = fs.openSync(file, 'r');
const buffer = Buffer.alloc(Math.min(maxBytes, Math.max(0, size - start)));
let bytesRead;
try {
bytesRead = fs.readSync(fd, buffer, 0, buffer.length, start);
} finally {
fs.closeSync(fd);
}
return {
cursor: start,
nextCursor: start + bytesRead,
rotationLost: start !== cursor,
truncated: start + bytesRead < size,
fileMissing: false,
readError: null,
observation,
observedMs: Date.now() - observedAt,
output: buffer.subarray(0, bytesRead).toString('utf8'),
};
} catch (error) {
return {
cursor,
nextCursor: cursor,
rotationLost: false,
truncated: false,
fileMissing: error && error.code === 'ENOENT',
readError: error && typeof error.code === 'string' ? error.code : 'UNKNOWN',
observation,
observedMs: Date.now() - observedAt,
output: '',
};
}
}
function finish(observation) {
if (finished) return;
finished = true;
if (watcher) watcher.close();
if (timer) clearTimeout(timer);
process.stdout.write(JSON.stringify(snapshot(observation), null, 2));
}
const initial = snapshot('initial');
if (initial.readError || initial.rotationLost || initial.truncated || initial.output) {
process.stdout.write(JSON.stringify(initial, null, 2));
} else {
try {
watcher = fs.watch(path.dirname(file), (_event, changedFile) => {
if (!changedFile || String(changedFile) === path.basename(file)) finish('change');
});
watcher.on('error', () => finish('watch-error'));
timer = setTimeout(() => finish('interval'), observationMs);
} catch {
finish('watch-error');
}
}
NODE
このサイクルでは、返された output のみを使用します。fileMissing: true はロガーが port-unknown の名前を変更した可能性を示すため、カーソルを進めずにセッションを再検出します。その他の null ではない readError、または observation: watch-error は正常なサイクルではありません。エラーコードを制限付きで報告し、高頻度のポーリングをせずに停止します。それ以外の場合は、output が空の場合やエラーを含む場合でも、現在の logPath、pid、port、nextCursor、新しい updatedAt を metro-cursor.json に直ちに保存します。これにより、中断後の重複処理を防ぎ、ファイルの安全な置き換えに対応できます。
readError が null、observation: interval、observedMs >= 5000 であり、output が空、または分類可能なエラーを含まない場合に限り、正常なサイクルとしてカウントします。情報出力を伴う早期の change 観測は、まだ完全な正常監視間隔ではありません。内容を処理し、次の収集サイクルを開始します。ログファイルが変更された場合、PID/ポートのチェック結果に矛盾がある場合、またはファイルの縮小やローテーションによってカーソルがリセットされた場合は、そのサイクルを正常としてカウントしないでください。
truncated: true の場合、その結果をクリーンとして決してカウントしないでください。空でない出力を処理し、その後、同じサイクル内で返されたカーソルから最大 3 回の追加テール呼び出しを発行します。rotationLost: true の場合、fixes.md に明示的なローテーション警告を記録し、クリーンカウンターをインクリメントする前に、新たな完全な観測間隔を必須とします。4 チャンク後もデータが切り詰められたままである場合、バックログ警告を記録し、無制限のコンテキストを消費するのではなく、次のサイクルに継続します。
新しい出力では、分類可能なシグナルとして表面化し、一致する health.json ドメインを更新します:
- ランタイムの
ERROR/WARN/LOGプレフィックス [PAHost]、[bridge]、[AuthProvider]、[AuthContext]、[useConnectionRefs]、[useConnectionSetup]、[addAadAppToConnectionAcl]、[PAHost][ErrorBoundary]などのプレフィックスを持つホスト診断行- スタックフレーム(
at <fn> (<file>:<line>:<col>)) - バンドルクラスのエラー(
Unable to resolve module、SyntaxError、transform failed) — Step B「Import / Bundle」Critical として再分類し、Step D を経由してルーティングします - Metro のリクエストログからの HTTP メソッド + ステータス(例:
"GET /index.bundle?platform=ios&dev=true ..." 500 -) —.bundle上の非 200 はバンドル/トランスフォームの失敗です;connector / Dataverse ホスト上の非 2xx は Step B「Network / API」に供給されます Bundling complete/iOS Bundled/Android Bundledを含む行は情報提供です — デバッグボリュームでfixes.mdにログ記録しますが、問題として分類しないでください- 注入されたトレースステートメントからの
[TRACEプレフィックス付きの行 — エラーとしてではなく、症状ウォーク(Phase 0.5.4)の下で分類します
ホスト診断行の解釈ルール:
- 次のような出力されたホスト文字列に一致する行のみを、分類可能なシグナルとして扱います:
[AuthProvider] MSAL init failed:[AuthProvider] Intune enrollment failed:[AuthContext] acquireTokenSilent failed for scopes:[AuthProvider] Intune unenroll failed:[bridge] unhandled plugin call[bridge] fetch THREW for[bridge] HTTP <status> for[addAadAppToConnectionAcl] failed HTTP <status> for connection[addAadAppToConnectionAcl] error:[useConnectionRefs] could not verify connection ACLs; treating existing connections as setup-required[useConnectionRefs] Failed to load connections:[useConnectionSetup] could not grant connection ACL: missing Power Apps token or user OID[PAHost] getConnectorToken: acquireToken threw for apiId="...":[PAHost] getConnectorToken: acquireToken returned null for apiId="..."[PAHost] getDataverseToken: acquireToken threw for orgUrl="...":[PAHost] getDataverseToken: acquireToken returned null for orgUrl="..."[PAHost][ErrorBoundary] Unhandled JS error:[PAHost][ErrorBoundary] Error stack:[PAHost][ErrorBoundary] Component stack:
- ブリッジのセットアップ/レディ、トークン取得の開始/成功、ブリッジ登録、接続セットアップ画面の表示など、ライフサイクル/ステータスのみの行は情報提供として扱います。
ステップ B — 新しい各ログエントリーを分類する
テレメトリのチェックポイント:classify_runtime_failures
8 カテゴリーの表を適用します。一意のスタックトレース/エラーメッセージごとに 1 件の問題として扱います。
| 優先度 | パターン | カテゴリー |
|---|---|---|
| Critical | 捕捉されていない例外、未処理の Promise 拒否、アプリのクラッシュ | JS Runtime |
| Critical | Unable to resolve module、Cannot find module | Import / Bundle |
| Critical | SyntaxError、Unexpected token、transform failed(Metro のターミナルに表示される複数行ブロック。プライマリモードのみ) | Import / Bundle |
| Critical | Cannot read properties of undefined、is not a function | JS Runtime |
| High | pdfViewer または penInput ラッパーからの NATIVE_MODULE_MISSING | Native |
| High | geolocation ラッパーからの NATIVE_MODULE_MISSING、PERMISSION_DENIED、または TRACKING_FAILED | Native |
| High | pdfViewer からの INVALID_URL、または content://、blob:、http:// の PDF ビューアー入力に言及するログ | JS Runtime |
| High | PDF/ペンラッパーからの VIEWER_FAILED または CAPTURE_FAILED | Native |
| High | ERROR レベルのランタイムログ | JS Runtime |
| High | ログに表示された HTTP 4xx/5xx | Network / API |
| High | ネイティブモジュールまたはブリッジのエラー | Native |
| Medium | React の Warning: コンポーネントエラー | React |
| Low | 既知のノイズではない WARN レベルのログ | General |
複数行のバンドル/変換ブロックの解析(プライマリモード): Metro はこれらをバナー(例:error: Bundling failed、iOS Bundling failed)として出力し、その後にインデントされたブロックが続きます。ランタイムのスタックとは異なり、ファイル:行番号はブロックの最初のバナー以外の行にあり、<absolute or relative path>:<line>:<col> の形式です。通常、at <fn> のスタックフレームはありません。認識すべき例:
iOS Bundling failed 412ms
SyntaxError: /Users/.../app/(tabs)/todos.tsx: Unexpected token (47:12)
45 | return (
46 | <YStack>
> 47 | <Text>{title</Text>
| ^
48 | </YStack>
49 | );
app/(tabs)/todos.tsx:47:12 を修正箇所とします。以下の D3.1 のレシピはこの形式に対応しています。
既知のノイズとなる行は無視します:
- Metro の
Require cycle:警告 - 関連するクラッシュを伴わない
VirtualizedList: You have a large list… - Expo SDK の情報バナー(
Starting Metro…、Connecting to…) - シリアライズできないパラメーターに関する React Navigation の開発時警告(クラッシュに関連する場合を除く)
- 画面の状態が変わらず、エラーも表示されない場合の、ペン入力からの
USER_CANCELLED - 失敗を示す情報のないホストのライフサイクル/情報行。例:
[bridge] setupNativeHost: bridge ready、[PAHost] bridge registered、[PAHost] render: waiting for connection resolution (spinner)
ステップ C — 問題が見つからない場合
テレメトリチェックポイント:confirm_runtime_health
連続クリーンサイクル数を増やします。
targetCleanCyclesで終了する前に、症状ガードを確認してください。 .powernative/debug-app/symptom-stateを読み取り、以下の該当する終了パスを選択します。(このセッションで症状駆動モードを使用していない場合は、Phase 0.1で起動時にファイルがクリアされているため、「ファイルが存在しない」分岐が実行されます。)
クリーン、フラグ付き、保留、タイムアウト、反復上限、エスカレーションのいずれかで終了する前に、health.jsonからこのサニタイズ済みヘルステーブルを出力してください。
Health
Bundle <status> <summary>
Runtime <status> <summary>
Authentication <status> <summary>
Dataverse <status> <summary>
Connector <status> <summary>
Offline <status> <summary>
Navigation <status> <summary>
Native capability <status> <summary>
証拠が確認されていない場合はunknownを維持し、設定が存在しないことを明確に検出した場合に限りnot-configuredを使用します。すべてのサマリーに永続化のためのレダクションゲートを適用してください。ログのクリーンな期間があっても、すべての不明なドメインが健全であるとは限りません。
**resolved**またはファイルが存在しない場合(このセッションで症状モードを使用していない場合):
✓ App is running cleanly — no errors detected across <targetCleanCycles> consecutive log checks.
Symptom verification: <PASS | n/a — no symptom provided>.
Session summary written to .powernative/debug-app/fixes.md.
To resume monitoring, run /debug-app again.
flagged(Phase 0.5で、別のスキルが必要な実際の問題が見つかった場合):
⚠ Logs are clean BUT the symptom isn't fixed — it requires another skill.
Symptom: <class> on <screen>
Next step: <skill route recorded in unresolved.md by Phase 0.5> (e.g., run /add-connector)
Details: .powernative/debug-app/unresolved.md
Re-run /debug-app "<symptom>" after taking that step to verify the fix.
緑色の✓は出力しないでください。アプリのログは技術的にはクリーンですが、ユーザーから見える問題は解決しておらず、再実行する前にユーザーの対応が必要です。
pending(targetCleanCycles分のクリーンなログサイクル後も、まだ有効な場合):
Phase 0.5の連鎖調査結果をunresolved.mdに追記してから、次を出力します。
"⚠
<screen>上の症状<class>は、クリーンなログサイクルが<targetCleanCycles>回続いた後も有効です。ランタイムは静かですが、ユーザーから見える問題は解決していません。データパスのエラーが握りつぶされている可能性があります。連鎖調査については.powernative/debug-app/unresolved.mdを参照してください。推奨される次のステップ:<調査結果に基づく提案>。"
ループを終了します。自動的に再開しないでください。
反復上限(両モードに適用): クリーンサイクル数やタイムアウトとは別に、ループは合計50サイクルで終了します。fixes.mdの先頭にcycle: <N>を記録し、サイクルごとに増やしてください。上限に達した場合は、次を出力して終了します。
"⚠ ループが反復上限(50サイクル)に達しました。症状が断続的に発生しているか、リロードのたびに修正が後退している可能性があります。サイクルごとのログについては
.powernative/debug-app/fixes.mdを参照してください。推奨される次のステップ:直近3件の修正を確認して循環する後退がないか調べるか、より具体的な症状を指定して再実行してください。"
カウンターがtargetCleanCycles未満で、上限にも達していない場合は、ステップAに戻ります。フォアグラウンドのファイルウォッチャーが観察間隔を確保するため、シェルのsleep、ホスト固有の待機コマンド、または頻繁なポーリングループを追加しないでください。
ステップ D — 問題が見つかった場合
テレメトリチェックポイント:repair_and_verify_runtime_issue
連続クリーンカウンターを0にリセットします。問題ごとに、次へ進む前に以下の手順を1つずつ実施します。
D0. 監視のみの分岐(--no-fix)
noFix=trueの場合、変更を伴うD1~D4には進まないでください。
- カテゴリー、最小限のサニタイズ済みエラーサマリー、確認できる場合はプロジェクト相対パスでのユーザーコード上の最上位フレーム、および使用するはずだった修正手順または引き継ぎ内容を記録します。書き込む前に永続化のためのレダクションゲートを適用してください。
- 次を追記します。
[<HH:MM:SS>] Observed (no-fix) — <category> — <file:line|no user frame> — <summary> Would do: <inline fix recipe | skill handoff | manual native action> - プロジェクトのソースや設定を編集したり、トレースを挿入したり、型チェック、リロード、インストール、再生成、アカウント切り替え、または別のスキルの呼び出しを行ったりしないでください。
.powernative/debug-app/のカーソル、監査、ヘルスファイルの更新は許可されています。 - 次の問題に進み、その後ステップAに戻ります。クリーン目標、タイムアウト、停止、または反復上限に達するまで、新しい出力の監視を続けます。
D1. コンテキストを収集する
現在のステップ A の output ブロックを使用します。ログに次のいずれが表示されているか確認します。
- 完全なスタックトレースを伴うクラッシュ(アプリがクラッシュしています)
- React のエラーバウンダリメッセージ(コンポーネントで例外が発生しています)
- ネットワークエラーまたは HTTP ステータス(API/コネクタの障害)
- エラーのない空のレスポンス(サイレント障害です。[INJECTED-TRACE] の
console.logの挿入を検討してください。パターンについては Phase 0.5.3 を参照してください)
JS Runtime/React のエラーでは、ターミナルのスタックトレースがコンテキストそのものです。最上位のユーザーコードのフレームを読み、ファイルを特定します。
クラッシュまたはターミナル出力のない空白画面の場合は、ユーザーに次のように尋ねます。
「画面には何か表示されていますか?エラーバウンダリ、真っ白な画面、読み込み中のスピナーなどです。表示されているエラーテキストがあれば、コピーして送ってください。」
D2. 根本原因の分析
関連するソースファイルを読みます。次の点を特定します。
- エラーの原因となっている正確なファイルと行番号。ランタイムエラー(JS Runtime、React、Network/API)の場合は、スタックトレース内で最も上にあるユーザーコードのフレームを選びます(
node_modules/とsrc/generated/は除外します)。バンドル/変換エラー(Import / Bundle カテゴリ、primary モード)の場合は、Metro エラーブロックのバナーではない最初の行にあるファイルと行番号を使用します。Step B の解析に関する注記を参照してください。 - 修正がデータレイヤー、UI レイヤー、ルーティング、スキーマのどれに影響するか。
- 修正によってほかの画面でリグレッションが発生する可能性があるか。
Dataverse / Power Platform の診断手順(引き継ぎ前):
- skills/add-dataverse/references/dataverse-reference.md を読みます。
memory-bank.mdと、該当するnative-app-plan.mdのセクションがある場合はそれも使用します。 power.config.jsonを読み、ほかの情報源を参照する前にenvironmentIdを取得します。関連する生成済みのサービス/モデルとconnectorSchemas.tsを確認します。- 環境を読み取り専用で解決します。
解決に失敗した場合は、node "${PLUGIN_ROOT}/scripts/resolve-environment.js" "<environmentId-or-url>"$PA auth status --jsonを実行します。ユーザーの確認なしに、アカウントを切り替えたり、ログアウトしたり、/debug-appからログイン画面を開いたりしないでください。 - 環境の解決に成功し、実環境の証拠が必要な場合は、以下を介した読み取り専用の
GETリクエストのみを使用します。
認証/テナントの識別が問題となっている場合は、まずnode "${PLUGIN_ROOT}/scripts/dataverse-request.js" <envUrl> GET <apiPath> \ --tenant-id '<resolved-tenant-id>'WhoAmIを実行します。テーブル名と列名の確認には、範囲を限定したメタデータ/エンティティの読み取りを使用します。/debug-appから作成、更新、削除、公開、シード、過剰なリクエスト、または意図的な認証情報の無効化を行わないでください。 - アプリのランタイムデータの修正では、生成済みの
<Table>Service呼び出しを引き続き使用する必要があります。これを Dataverse への直接のfetch/axios呼び出しに置き換えないでください。 - OData の構文、ルックアップの動作、選択肢/仮想/ファイル/画像フィールド、認証、スロットリング、またはエラーの形式に不確かな点が残る場合は、修正を決める前に、正確なエラー/トークンを使って Microsoft Learn を検索します。
この手順を実施して、テーブル/列/サービス/スキーマの成果物が欠落しているか、互換性がないことが確認された場合に限り、D3 で /add-dataverse に誘導します。
Expo / Expo Router / React Native の診断手順:
- 該当する場合に限り、引用されているアプリファイルと、
package.json、app.json/app.config.js、ルートレイアウトを読みます。 - インストールされているパッケージの型定義や README を、正確なバージョンに合わせて優先的に確認します。
- 動作に不確かな点が残る場合は、公式ドキュメント
https://docs.expo.dev/に対して対象を絞ったWebFetchを使用します(ルーティングには Expo Router のページ、ネイティブモジュールには SDK のページを参照)。Expo/React Native の動作について Microsoft Learn を検索しないでください。
ファーストパーティのネイティブパッケージの所有権判定ゲート:
失敗したスタック、モジュール、またはエクスポートに、名前が @microsoft/power-apps-native-* に一致するインストール済みパッケージが含まれる場合は、D3 の前にこの判定ゲートを適用します。
node_modules/のフレームは手掛かりとしてのみ扱います。アプリの呼び出し箇所、インストール済みパッケージの公開型定義/README/エクスポート、宣言されたバージョンとロックファイルで解決されたバージョンを確認します。アプリが、サポートされている入力と設定で、文書化された API を使用していることを確認します。- 呼び出し元、入力、またはサポートされている設定を修正することで契約違反が解決する場合は、顧客コードの問題として分類します。その場合は通常の D3 のルートに進みます。
- サポートされているアプリ呼び出しが有効であり、パッケージ内部の実装、公開が告知されているエクスポートの欠落/不具合、またはパッケージ内部のインポートが原因で失敗している場合に限り、パッケージ側の問題として分類します。どちらに問題があるか判断できない場合は、いずれにもパッチを適用せず、不確実性を記録してエスカレーションします。
- パッケージ側の不具合が確認された場合は、その問題に対する自動修正の試行を停止します。補償のためにアプリのソース、設定、依存関係の解決、またはインストール済みパッケージの内容を変更しないでください。記録するのは、パッケージ名、宣言された/解決されたバージョン、プラットフォーム、最小限の再現手順、期待される動作と実際の動作、および秘匿化された範囲限定のスタック/エラーの概要のみです。その後、ユーザーを
/report-issueに誘導します。既知の公式公開修正または文書化された回避策がある場合は伝えますが、/debug-appから適用しないでください。
D3. 修正を適用する
Import / Bundle カテゴリのエラーの場合は、まず D3.1 に進んでください — これらには特定のレシピがあり、以下の汎用ルーティングテーブルよりも優先されます。それ以外のすべて(JS Runtime、Network/API、React など)については、ルーティングテーブルを使用してください:
| エラーの発生箇所 / カテゴリ | 対応 |
|---|---|
app/ の画面ファイル、_layout.tsx、ルートセグメント | Edit ツールによるインライン編集 |
src/components/ | Edit ツールによるインライン編集 |
src/hooks/、src/services/ | Edit ツールによるインライン編集 |
src/generated/ | 編集しないでください。 サービス/モデルの修復は、CLI リフレッシュを使用して所有元のデータソーススキルに引き継いでください。npm run generate-schemas はランタイムコネクタマップを再生成するだけです。意図的に廃止されたソースを再度追加しないでください。 |
| Dataverse スキーマ(列/テーブルの欠落) | まず D2 の読み取り専用 Dataverse 診断シーケンスを実行してください。ライブメタデータ/生成された成果物でスキーマまたはサービスが欠落していることが確認された場合は、/add-dataverse に引き継いでください。/debug-app から Dataverse を変更したり、生成されたファイルを編集したりしないでください。 |
Auth / MSAL(AADSTS65001、AADSTS50011) | 引き継ぎ: /set-app-registration-native を介してユーザーを Power Apps Wrap ページに誘導してください。登録を自動編集しないでください。 |
| 接続 / コネクタ参照の欠落 | 引き継ぎ: ユーザーを /list-connections または /add-connector に誘導してください。 |
@microsoft/power-apps-native-* 内で確認された不具合 | 顧客プロジェクトでは修正しないでください。 以下のパッケージ不具合レポートを出力し、/report-issue に誘導してください。このルートは、ネイティブ、Import/Bundle、および未認識エラーのレシピよりも優先されます。 |
ネイティブモジュール、app.config.js、app.plugin.js、Podfile、build.gradle | ユーザーに通知してください。 ネイティブ設定を自動編集しないでください — エラー + 推奨アクションを出力し、次の問題にスキップしてください。 |
| 未認識のエラーパターン | ベストエフォートの自律修正 — 以下 D3.2 を参照してください。スキルは停止する代わりに、単一の名前付き仮説を試みます。既存の 2 回試行エスカレーションルールがセーフティネットです。 |
PDF/ペン/ジオロケーション固有のルーティング:
- PDF ビューア入力の
INVALID_URLは、インラインの画面/ラッパー修正です。ビューア 0.2.9+ でhttps://および空でないfile://入力を許可してください。ネイティブビューアパスでcontent://、blob:、またはhttp://のサポートを追加しないでください。 - 生成された PDF のローカル
file://URI は、ネイティブ PDF ビューア 0.2.9+ で開くことができます。 - PDF ビューアまたはペン入力の
NATIVE_MODULE_MISSINGは、ネイティブ拡張機能が実行中のビルドに含まれていないことを意味します。デバッグからパッケージをインストールしたり、ネイティブ設定を編集したりしないでください。/add-native pdf-viewerまたは/add-native pen-inputに誘導してラッパー/パッケージの状態を確認し、パッケージがアプリビルドに含まれていない場合はネイティブのリビルド/テンプレート更新が必要であることをユーザーに伝えてください。 geolocationについては、実際の失敗の次元をデバッグしてください:トラッキングを開始できるか(startTracking、権限、ネイティブモジュール)、行が Dataverse に到達しているか(デフォルトのmsdyn_locationrecordsが存在するか、ネイティブアップロード/認証エラー、JS アップロードパスがないか)、および動作がユーザーの期待と一致するか(バックグラウンド、再起動後の永続性、ブレッドクラム/ルートの継続性)。表示される画面の処理はインラインで修正してください。ネイティブモジュール/テーブルが欠落している場合は、使用をブロックし、/add-dataverseではなく関連するジオロケーションセットアップパスに誘導してください。- ペン入力からの
USER_CANCELLEDは、画面がそれをエラーとしてレンダリングしない限りバグではありません。キャンセルを失敗として表示する画面はインラインで修正してください。 - Dataverse 成果物の書き込みは、スキーマ/サービスがすでに存在する場合に限り、ローカルアプリの修正です。File/Image 列が欠落している場合は、
/add-dataverseに誘導してください。
インライン編集では、変更を最小限かつ外科的に保ってください。周囲のコードをリファクタリングしたり、シンボル名を変更したり、コンポーネントのコントラクトを変更したりしないでください。
確認されたファーストパーティのネイティブパッケージ不具合については、成功した修正エントリを追加しないでください。このレポートを永続化のリダクションゲートに通し、.powernative/debug-app/unresolved.md に追加し、注入されたトレースをクリーンアップし、/report-issue を実行できるようにループを停止してください:
Confirmed first-party native package defect — no customer-project workaround applied
Package: <@microsoft/power-apps-native-*>
Declared/resolved version: <declared> / <resolved>
Platform: <ios|android>
Reproduction: <minimal sanitized steps>
Expected: <bounded behavior>
Actual: <bounded error/status>
Ownership evidence: <why the documented caller contract is satisfied and the failure is package-internal>
Next step: /report-issue "<package>: <sanitized summary>"
.powernative/debug-app/fixes.md に追加してください:
[<HH:MM:SS>] <category> — <file>:<line> — <one-line description of fix>
D3.1 バンドル/変換エラーの修正レシピ(インポート/バンドルカテゴリー)
これらのレシピは、ステップBで「インポート/バンドル」に分類されたエラーに適用されます。永続化された .powernative Metro ログから読み取ります。各レシピには具体的な方針があります。前提条件が一致する場合は記載されたアクションを実行し、一致しない場合は次のレシピに進みます。
レシピを適用する前に、引用元またはインポーター、あるいは失敗した内部インポートが node_modules/@microsoft/power-apps-native-* 配下にある場合は、ファーストパーティのネイティブパッケージ所有権ゲートを実行します。パッケージ所有の不具合であることが確認された場合は /report-issue に誘導します。リゾルバーエイリアス、ソースのコピー、パッチ、postinstall による書き換え、依存関係の置き換えで修正してはいけません。
| エラーパターン | 前提条件 | アクション |
|---|---|---|
SyntaxError: <file>:<line>:<col> in app/, src/components/, src/hooks/, src/services/ | 指摘された行が編集可能なユーザーコード内にある(src/generated/ 内ではない、node_modules/ 内ではない) | 指摘された行の前後(±10 行)を Read し、構文上の問題(閉じられていない JSX タグ、閉じ波括弧または閉じ括弧の不足、余分なカンマ、import の from の不足、閉じられていない文字列、文の間のセミコロン不足)を特定して、最小限の Edit を 1 回適用します。周囲のコードのフォーマットを変更しないでください。 |
SyntaxError in src/generated/ | 指摘されたファイルが src/generated/ 内にある | 編集しないでください。 connectorSchemas.ts の場合は、ランタイムマップを再生成します。サービス/モデルの場合は、既存の登録を確認し、対象を絞った CLI 更新と検証のための承認済みスコープ、絶対パスのアプリルートとともに、--refresh --data-source-name "<registered-name>" を指定して /add-connector または /add-dataverse に引き継ぎます。まず承認済みプランを確認してください。削除されたソースの場合は、再登録ではなく /edit-app を通じて利用側をクリーンアップする必要があります。登録が見つからない、または曖昧な場合は更新を中止し、追加に切り替えないでください。 |
<importer> からの Unable to resolve module <name> | <name> が . または .. で始まる(相対 import) | import 元のディレクトリで、拡張子(.ts、.tsx、.js、.jsx、.json)を問わず、<name> に一致するファイルを Glob で検索します。別の拡張子で見つかった場合 → 拡張子を省略するか、実際の拡張子に import を修正します。スペルミスを含む名前(Levenshtein ≤ 2)で見つかった場合 → スペルミスを修正します。見つからない場合 → ファイルが実際に存在しません。作成するか、import を削除するかをユーザーに確認します。 |
Unable to resolve module <name> | <name> がパッケージ名であり、package.json の dependencies/devDependencies に存在しない | shared/references/javascript-dependency-planning.md に従い、パッケージ名ではなく内容に基づいて公開パッケージを分類します。ネイティブバインディングがあり、テンプレートに存在しない場合は、テンプレート/ランタイムの更新が必要であることを報告します。純粋な JavaScript であると確認できた場合は、正確なバージョンについて同意を求め、npm install --save-exact でインストールし、検証してから再試行します。同意なしにインストールしないでください。 |
Unable to resolve module <name> | <name> が package.json に存在するが、それでもバンドルに失敗する | キャッシュが原因と考えられます。Metro を停止し、npm run dev -- --clear を再実行してから再読み込みするようユーザーに依頼します。所有していないプロセスを終了してはいけません。 |
babel プラグインを参照する transform failed(例:[BABEL] ... unknown plugin "react-native-reanimated/plugin") | エラーが babel.config.js を参照している | 引き継ぎます。 babel.config.js はプロジェクト設定です(app.config.js と同じ制約があります)。指摘されたプラグインと推奨する修正順(例:「react-native-reanimated/plugin は babel.config.js の plugins 配列の最後に置く必要があります」)を示し、次の問題に進みます。 |
babel の参照がない transform failed | 一般的な変換エラー(多くの場合、Metro のトランスフォーマーが処理できない TS 機能が原因) | 指摘されたファイルを読み込み、特定の TS ライブラリが必要な構文(デコレーター、トップレベルの await など)がないか確認します。既知の問題パターンの場合は、ユーザーに提示し、修正前に確認を求めます。それ以外の場合は引き継ぎます。 |
predev スクリプトの失敗(例:expo start の実行前に npm run generate-schemas がエラーになった) | バンドル出力から、predev ライフサイクルフック中に失敗したことが分かる | これはコード編集ではありません。power.config.json またはコネクタのセットアップに問題があります。引き継ぎ: Power Platform コネクタの場合は /add-connector、Dataverse の場合は /add-dataverse にユーザーを案内します。power.config.json を直接編集しないでください。 |
[BABEL] ... You're trying to use the @babel/plugin-X plugin twice | babel プラグインの重複エントリ | 上記と同じ理由で引き継ぎます。babel.config.js はプロジェクト設定です。重複を示し、ユーザー自身に重複を解消してもらいます。 |
インライン編集(上記の行 1、3、4 のいずれか)を適用すると、Metro はファイルの保存を自動検出して再バンドルします。D4 に直接進み、手動で再読み込みを実行しないでください。検証ステップでは、Metro の Bundling complete(または次のエラーブロック)が自動的に取得されます。 |
.powernative/debug-app/fixes.md に追記します:
[<HH:MM:SS>] Import/Bundle — <file>:<line> — <recipe applied>
D3.2 分類されないエラーに対するベストエフォート修正レシピ
エラーがステップ B の分類テーブルのすべての行と、D3.1 のバンドルレシピのすべての行に該当しない場合でも、スキルは停止せずに修正を試みます。以下の手順に従うことで、ベストエフォートが無謀な推測に陥るのを防ぎます。
ステップ 1 — 該当箇所を特定します。 次の順に試し、編集可能なユーザーコード内のファイルと行番号が見つかった時点で終了します。
- スタックトレースの先頭にあるユーザーフレーム — スタックを先頭からたどり、
node_modules/、src/generated/、React/Hermes の内部(react-native/、hermes-engine/、metro/)にあるフレームはスキップします。最初に残ったフレームが該当箇所です。 - 複数行のバンドルブロック — ステップ B の解析に関する注記を参照してください(最初のバナー以外の行にあるファイルと行番号)。
- リポジトリ全体で完全一致検索 —
app/、src/components/、src/hooks/、src/services/を対象に、エラーメッセージの正確なテキスト(または最も特徴的な 4~6 語のフレーズ。正規表現の特殊文字はエスケープします)をGrepで検索します。throw new Error('...')の箇所で一致した場合、そこが該当箇所です。 - モジュールとシンボルの検索 — エラーに関数名やコンポーネント名(例:
useFoo is not a function)が含まれる場合は、そのシンボルをGrepで検索します。一意に特定できる宣言箇所が該当箇所です。
ステップ 4 までに該当箇所が見つからない場合は、.powernative/debug-app/unresolved.md に構造化されたメモ(最小限にサニタイズしたエラー概要と実行した検索方法)を記録し、ユーザーに提示して、次の問題に進みます。ファイルを推測してはいけません。 ベストエフォートであっても、対象が必要です。
ステップ 2 — 理解を深めます(省略しないでください)。
- エラーに Microsoft スタックのトークン(
AADSTS\d+、Dataverse、Power Platform、MSAL、Entra、Graph API)が含まれる場合:まず D2 のプロジェクト/参照/読み取り専用の診断手順を実行し、動作が不明なままであれば、正確なコードまたはトークンを使ってmcp__plugin_mobile-app_microsoft-learn__microsoft_docs_searchを呼び出します。 - エラーが Expo、Expo Router、Expo SDK モジュール、または React Native の動作に関する場合:インストール済みのバージョンとローカルのパッケージドキュメントを確認し、対象を絞って
https://docs.expo.dev/にWebFetchを実行します。これらのエラーに Microsoft Learn を使用しないでください。 - エラーに
@microsoft/power-apps-native-*が関係する場合は、D2 のファーストパーティネイティブパッケージ所有権ゲートを実行します。パッケージが原因と確認された不具合は、ベストエフォート編集の対象にはなりません。 - 周辺のコンテキストを確認するため、該当ファイルの該当箇所の前後 15 行を読みます。最近追加されたインポート、関数シグネチャ、近くにある
try/catchやuseEffectの依存配列を確認します。 - エラーにサードパーティモジュール(スタックにある
node_modules/内のもの)が関係する場合は、そのモジュールの npm ページまたは GitHub README に対して対象を絞ったWebFetchを 1 回実行してもかまいません。ループ中に範囲を限定しないウェブ検索は行わないでください。
ステップ 3 — 名前を付けた仮説を 1 つ立てます。 編集する前に、次の形式で .powernative/debug-app/fixes.md に記述します。
[<HH:MM:SS>] Hypothesis (best-effort) — <file>:<line> — <one-sentence theory>
Evidence: <sanitized error code/summary + what in the cited code led you here>
Planned change: <what you'll edit, in 1 line>
許容される仮説の例:
- 「
<UserAvatar>はuser.profile.imageを読み取りますが、最初のレンダー時にはuserが未定義の場合があります — null ガードを追加します」 - 「42 行目の
useEffectは、userIdが依存配列に含まれていないため、古いuserIdを捕捉します」 - 「
AsyncStorage.getItemはキーが存在しない場合に null を返しますが、呼び出し元は JSON として解析可能な文字列を想定しています」
許容されない仮説(適用せず、代わりにエスカレーションします):
- 「状態管理に何か問題があります」(曖昧で、具体的な変更内容が示されていません)
- 「try/catch で囲んでみます」(修正ではなく隠蔽であり、実際のバグを黙って無視します)
- 「X、Y、Z も更新するかもしれません」(複数の変更を一度に行うため、「一度に 1 つの修正」という原則に反します)
Step 4 — 最小限の編集を1回だけ適用します。 1回の
Edit呼び出しで、計画した変更を実現する最小限の差分を適用します。無関係なコードを変更したり、シンボル名を変更したり、周辺の構造をリファクタリングしたりしないでください。ファイルパスが編集可能なユーザーコード内にあることを再確認してください(src/generated/、node_modules/、または Constraints セクションの保護対象リストにあるパスは対象外です)。
Step 5 — 検証は D4 に委ねます。 既存の検証サイクル(型チェック+再読み込み+再ポーリング)で、仮説が正しかったかどうかを判断します。「念のため」に2つ目の仮説を先回りして試さないでください。
Step 6 — 検証に失敗した場合、別の仮説は1つだけ許可されます。 D4 で同じエラーが再発した場合、別の仮説を1つ立ててもかまいません(元のエラーに対する修正試行 #2 として数えます)。それも失敗した場合は、既存のエスカレーションルールが発動し、このエラーについてスキルは停止します。ユーザーに報告し、unresolved.md に追記して、次の問題に進んでください。3つ目の仮説を続けて試さないでください。
ベストエフォートモードの制約に関する注意(例外はありません):
src/generated/、node_modules/、app.config.js、app.plugin.js、babel.config.js、metro.config.js、Podfile、build.gradle、gradle.properties、power.config.json、auth.config.jsonは編集しないでください。npm install <pkg>、npm uninstall <pkg>、npx expo install <pkg>、または明示的なユーザーの同意なしにpackage.json/package-lock.jsonを変更するコマンドは実行しないでください(D3.1 のパッケージ名のみを指定する手順と同じ承認条件です)。- Metro を再起動したり、
expo prebuildを実行したり、開発サーバーのライフサイクルに影響する操作をしたりしないでください。 - 考えられる仮説がこれらの制約に違反する場合、そのエラーは対象外として扱い、1行で説明してユーザーに引き継ぎ、次に進んでください。
D4. 修正を検証する
修正を適用した後:
-
型チェック:
npm run type-checkTS エラーがある場合は、続行する前に修正してください。型チェックが終了コード 0 になるまで先に進まないでください。
-
Metro の再バンドルを待つ(Import/Bundle の修正のみ): D3.1 でインライン編集を適用した場合、Metro はファイルを自動監視し、保存時に再バンドルを開始します。Step A のカーソル位置からのテール手順を、回数を限定して再実行し、次のいずれかを確認してください。
Bundling complete/iOS Bundled/Android Bundled→ 成功。手順 4 に進みます。- 新しいバンドルエラーのブロック(異なる file:line または異なるメッセージ)→ 新しい問題として扱い、Step B に戻ります。
- 同じエラーが再発 → 修正は適用されていません。同じエラーに対する修正試行 #2 として扱います(2回の試行後にエスカレーションルールが適用されます)。
- バンドルの動きがないまま30秒経過 → Metro が一時停止または応答不能になっている可能性があります。ユーザーに報告し、Metro を自動再起動しないでください(Constraints)。
-
アプリを再読み込みする(その他すべての修正 — JS Runtime、Network/API、React など): Fast Refresh でほとんどのインライン編集が適用されます。新しいバンドルまたはランタイムの動きが見られない場合、次のようにユーザーに指示してください。
「ネイティブの開発クライアントメニューからアプリを再読み込みしてから、ワークフローをもう一度実行してください。」
ユーザーの確認後、Step A のカーソル位置からのテール手順を実行し、新しい出力のみを確認してください。
-
保存された出力で修正を確認します。 新たに追記されたログバイトに以前のエラーパターンがなく、新しいエラーも発生していなければ、修正は成功です。関連する
[INJECTED-TRACE]行があれば、データパスが正常であることの確認に使用してください。確認後、挿入したログを削除してください(Phase 0.5.5)。 -
クリーンサイクルのカウンターを 0 にリセットして、Step A に戻ります。
エスカレーション
同じエラーが修正を2回試みた後も続く場合は、停止して次のように報告してください。
⚠ Unresolved after 2 attempts: <error summary>
File: <path>
Log: <sanitized bounded error summary>
Last fix tried: <one-line description>
Suggested next step: <manual action>
ブロックを永続化時の編集・秘匿化ゲートに通し、検証ツールの出力のみを .powernative/debug-app/unresolved.md に追記し、終了前に [INJECTED-TRACE] ログを削除してください(Phase 0.5.5 の手順)。
同じエラーに対して自動修正を3回目まで試みないでください。ユーザーの指示を待ってください。
制約
- ネイティブ設定ファイル(
app.config.js、app.plugin.js、Podfile、build.gradle、gradle.properties)は絶対に修正しないでください — エラーを正確な行番号と手動での対処方法の提案を添えてユーザーに報告してください。 src/generated/は絶対に変更しないでください — これらのファイルは自動生成されます。モデル/サービスおよび設定の追加・更新・削除には、データソースを管理するスキルが CLI を使用します。その後、npm run generate-schemasでランタイムマップのみを再構築します。承認済みのソース一覧を維持し、修復中に廃止済みのソースを復活させないでください。- 顧客のプロジェクト内で、ファーストパーティのネイティブパッケージにパッチを当てたり、フォークしたりしないでください —
@microsoft/power-apps-native-*の不具合が確認された場合、node_modules/の編集、patch-packageのアーティファクトや postinstall による書き換えの生成、パッケージソースの同梱/コピー、フォークの生成/インストール、依存関係の Git/tarball/ローカルパスへの置き換え、パッケージをシャドウするリゾルバーエイリアス/シムの追加は行わないでください。サニタイズした証拠を/report-issueに送ってください。 - Dataverse の診断は読み取り専用です —
/debug-appでは、設定済みの環境を解決し、付属のスクリプトを通じて、上限を設けた Dataverse のGETリクエストを実行できます。メタデータ/データの書き込み、公開、レコードのシード、意図的なスロットリングの発生、トークンの無効化、CLI アカウントの切り替え、生成済みサービスの直接 HTTP への置き換えは絶対に行わないでください。 - サイクルの途中で、エラーについてユーザーに質問しないでください — 上記のツールを使って自律的に調査してください。ユーザーに伝えるのは、次の場合のみです。
- 修正にネイティブ設定の変更が必要な場合。
- 修正にテナント管理者の操作(AAD の同意など)が必要な場合。
- 修正を2回試しても同じエラーが続く場合(エスカレーション)。
- 修正を別のスキル(
/add-dataverse、/set-app-registration-native、/list-connections)に引き継ぐ場合。
- 修正は一度に1つだけ — 次の問題に着手する前に、型チェック、再読み込み、ログの検証を含めて、1つの問題を完全に解決してください。
- 挿入したログは必ず削除してください — セッション中に追加した
// [INJECTED-TRACE]の行は、症状がpendingやflaggedであっても、セッション終了前に必ず削除してください。編集可能なapp/およびsrc/ファイルを対象に、src/generated/を除外して、Phase 0.5.5 のfindスキャンを使い、これらの行を見つけてください。 - 既存の動作を維持してください — 修正は最小限かつ的を絞ったものにしてください。バグ修正に伴うリファクタリング、名前変更、コンポーネントの契約変更は行わないでください。
- ポーリングには上限を設けてください — ビジーループを行わないでください。ポーリングのたびに永続化されたバイトカーソルを進め、1サイクルで処理するチャンクは、256 KiB のものを最大4つまでにしてください。
- すべての操作を記録してください — ツールを呼び出す前に、その内容と理由を1行で表示し、ユーザーが作業の進行を追えるようにしてください。
失敗モード
| 症状 | 原因として考えられること | 解決方法 |
|---|---|---|
Phase 0 で not-started または stopped と報告される | 稼働中の .powernative Metro ログがありません | npm run dev を実行し、ネイティブアプリを開いてから、/debug-app を再実行します |
| Phase 0 で最近のエラー行が検出される | 起動中または実行中に Expo/Metro が終了しました | 最新のログ末尾を確認し、サニタイズされたエラーを修正してから、ユーザーに npm run dev を再起動するよう依頼します |
| Phase 0 で「Metro running but no app connected」と報告される | シミュレーター/デバイスでアプリがまだ読み込まれていません | シミュレーター/デバイスでアプリを開いてから、/debug-app を再実行します |
| ループが停止したように見える | 修正に想定以上の時間がかかっています(例:大規模プロジェクトの型チェック) | 待機します。修正の実行中もログ行は出力されるはずです。終了するには stop と入力します |
| ループが「iteration cap reached」で終了する | 症状が断続的に発生している、または再読み込みのたびに修正による問題が再発しています | fixes.md の直近 3 件を調べて循環していないか確認します。より具体的な症状を指定して再実行するか、手動で修正します |
| 修正後も同じエラーが繰り返し発生する | Fast Refresh で変更が反映されなかったか、誤ったファイルを対象に修正しました | git status で確認し、ネイティブ開発クライアントのメニューから再読み込みして、再実行します |
修正後も同じエラーが続き、かつ git status で変更の保存が確認でき、型チェックも問題ない | Metro の変換キャッシュが古いままです | ユーザーに Metro を停止して npm run dev -- --clear を再実行し、再読み込みしてから /debug-app を再実行するよう依頼します |
| エスカレーションが直ちに発生する | エラーのパターンが引き継ぎ対象のカテゴリ(認証、スキーマ、ネイティブ)に該当しています | 提案された手動操作を行ってから、/debug-app を再実行します |
.powernative/debug-app/fixes.md が表示されない | Phase 0 が実行されなかったか、状態ディレクトリが作成されていません | 手動で mkdir -p .powernative/debug-app を実行し、スキルを再実行します |
| 「App is running cleanly」と表示されるが、ユーザーにはまだ問題が見える | 症状駆動モードが使用されていません。ログのポーリングだけでは、ログに現れない失敗を検出できません | /debug-app "<describe what you see>" として再実行し、Phase 0.5(console.log の挿入)を開始します |
Phase 0.5 で screen=unknown と報告される | 症状のテキストがどのルートファイル名にも一致しませんでした | より具体的な症状で再実行します("data is broken" ではなく /debug-app "todos screen empty" を指定します)。または、先に問題の画面へ移動してから再実行します |
再読み込み後に [TRACE 行がない | Metro が古いバンドルをキャッシュしています | ユーザーに Metro を停止して npm run dev -- --clear を再実行し、その後アプリを再読み込みするよう依頼します |
セッション後も [INJECTED-TRACE] 行がコードに残っている | クリーンアップ手順が省略されました | Phase 0.5.5 の find スキャンを実行し、一致した各行を削除します |
注意事項
-
再実行を想定した設計です — 呼び出しのたびに冪等に動作します。
.powernative/debug-app/metro-cursor.jsonは以前に確認したバイト位置を超えて進み、新しい Metro セッションやログのローテーションを検出すると安全にリセットされます。 -
制限を正直に示します — これはフォアグラウンドで動作するループです。実行中は、ほかのスキルを実行できません。これは意図した設計です。モデルは「まず構築し、その後デバッグする」です。一時停止が必要な場合は、
stopと入力して、後で再開してください。 -
専門エージェントはありません — 上流の
app-debugger.agent.mdは、screen-builder、component-author、api-integration、dataverse-data-modelerエージェントに処理を委任します。このプラグインにはそれらのエージェントがすべてそろっていないため、このスキルでは処理をインラインで修正するか、スキル(/add-dataverse、/set-app-registration-native、/list-connections、/add-connector)に振り分けます。対象となるカテゴリでは、同等の動作を実現します。 -
ホスト診断に関する注意点 — ホスト接頭辞付きの診断情報(
[PAHost]、[bridge]、[AuthProvider]など)は、dev-player セッションでは想定されるものであり、主要なテレメトリとして扱う必要があります。dev-player 以外のビルドでこれらの行がないのは想定どおりであり、それ自体はバグではありません。 -
上流との動作対応表:
動作 上流 このスキル ログ駆動の監視ループ はい はい — プロジェクトローカルでサニタイズされた Metro ログを信頼できる情報源とし、ホストのターミナル API は任意でのみ使用します 8 カテゴリの分類 はい はい 検証サイクル(型チェック + リロード + 再ポーリング) はい はい 2 回の試行後にエスカレーション はい はい 制限付きポーリング はい はい — 永続的なバイトカーソル、チャンクサイズを制限 連続してクリーンな状態が続いた後の終了回数を設定可能 3 回に固定 はい — デフォルトは 3 回、 --cyclesで設定可能。症状が解消した場合にのみ適用専門エージェントへの処理委任 はい いいえ。代わりにスキルへ振り分け 作業ディレクトリの監査ログ いいえ はい(追加機能 — .powernative/debug-app/fixes.md、injected-logs.md)不明なエラーに対する MS Learn のフォールバック いいえ はい(追加機能) 永続化された Metro/アプリログの情報源(バンドラーエラー + Hermes コンソール + HTTP リクエストログ) いいえ はい — ホストの再起動後も保持されます。MCP のフォールバックはありません バンドル/変換エラーの修正レシピ(D3.1) いいえ はい(追加機能) バンドル対応の検証(Metro をポーリングして Bundling completeを確認)いいえ はい(追加機能) 分類されないエラーに対するベストエフォートの自動修正(D3.2) いいえ はい(追加機能) 症状駆動モード — console.logの挿入 + ターミナルの読み取り + データパスの追跡いいえ はい(追加機能 — ログのポーリングでは検出できないサイレントな失敗を検出します。 [INJECTED-TRACE]ログを挿入し、ターミナルを読み取り、根本原因が見つかった後にログをクリーンアップします)