mcpField
B
bmad-loop-resolve

bmad-loop-resolve

github.com/thecontstructエージェントワークフロー074 回インストール5 週間前に更新
リポジトリ

bmad-loop-resolve について

重大なエスカレーションで安全な実装が止まった bmad-loop のストーリーを解決する対話型スキルです。人間と凍結仕様を明確化して決定を記録し、保存済みレビュー用パッチやワークツリー分離にも対応して実行を再開します。

主な機能

  1. 01エスカレーション情報と凍結仕様の確認
  2. 02人間が判断するための選択肢提示
  3. 03仕様と解決マーカーの更新
  4. 04保存済みレビュー用パッチへの対応
  5. 05再実行時のワークツリー動作の考慮

活用シーン

  1. 01仕様の意図の矛盾や欠落の解消
  2. 02未回答の実装上の疑問の明確化
  3. 03重大なエスカレーション後の実行再開
  4. 04対応時にパッチを復元してレビュー

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/thecontstruct/bmad-loop --skill bmad-loop-resolve

インストール後、Claude Code で/bmad-loop-resolveを入力して読み込まれたか確認します。

詳細

bmad-loop エスカレーションの解決

bmad-loop の実行でストーリーを開発 → レビューまで進めたところ、セッションで 重大なエスカレーションが発生しました(安全に作業を続けられない状態です。通常は frozen spec に矛盾があるか、未回答の質問があります)。オーケストレーターは人間の対応を 待つため、実行全体を一時停止しました。エスカレーションを起こしたセッションは終了しており、 あなたは新しい対話セッションです。あなたの役割は、人間と曖昧な点を解決し、frozen spec を 更新することです。これにより、オーケストレーターはストーリーを再び有効化し、修正済みの仕様に 基づいて再実行できます。

これは対話型です。人間が参加しています。質問し、選択肢を提示し、推奨案を示してください。 ただし、決定するのは人間です。このセッションでは $BMAD_LOOP_MODE は意図的に設定されて いません。自動化における「質問しない」ルールは適用されません。

識別情報と入出力の契約

次の環境変数が設定されています。

  • $BMAD_LOOP_RUN_DIR — 一時停止した実行のディレクトリです。
  • $BMAD_LOOP_STORY_KEY — エスカレーションが発生したストーリーキーです(呼び出し引数でもあります)。
  • $BMAD_LOOP_RESOLVE_CONTEXT — あなた向けに書き出された context.json のパスです。

最初に $BMAD_LOOP_RESOLVE_CONTEXT を読み込んでください。 スキーマは次のとおりです。

{
  "story_key": "6-4-cli-list-command",
  "run_id": "20260613-111429-6a14",
  "project_root": "/abs/path/to/bmad-project",
  "code_root": "/abs/path/to/code-repository",
  "spec_file": "/abs/path/to/_bmad-output/implementation-artifacts/spec-<story>.md",
  "spec_reaches_the_redrive": true,
  "redrive_base_ref": "<branch the re-drive reads, or HEAD>",
  "baseline_commit": "<sha>",
  "paused_reason": "CRITICAL escalation from review session: ...",
  "escalations": [
    {
      "type": "<kind>",
      "severity": "CRITICAL",
      "detail": "<what's ambiguous/contradictory>"
    }
  ],
  "resolution_path": "/abs/path/to/<run>/resolve/<story>/resolution.json"
}

escalations 配列は新しいものから順に並んでいます。 収集されたコンテキスト全体で、各エスカレーションは一度だけ記載されています。

対話セッションの作業ディレクトリは常に project_root です。このツリーには、確認または明確化する BMAD アーティファクトと仕様が含まれています。code_root は実行時のコードと Git 作業を行うツリーで、 異なる場合があります。ルートが異なる場合、セッションの作業ディレクトリをコードのチェックアウト先と 取り違えないでください。人間が行うコード修正やコミットは code_root 内で行い、アーティファクトと 仕様の作業は project_root(またはこのコンテキストに記載された明示的な絶対パス)を基準にします。 この解決セッション中に、あなたが実装やコミットを行うことはありません。人間を案内する際は、正しい ツリーを明示してください。

spec_reaches_the_redrive は、編集内容が再実行時に反映されるかどうかを示します。 再実行では 1つのツリーが読み込まれますが、spec_file は別のツリーを指している場合があります。ワークツリーが 分離されている場合、再実行が読み込みを行う前に実行時のマウントが破棄されるため、そのマウント内の 仕様も一緒に消えてしまいます。このフィールドが false の場合、spec_file への書き込みは必ず 成功しますが、その後破棄されます。セッション上は解決済みに見えてしまうため、編集しないよりも 悪い結果になります。null は、通常の frozen spec を編集できないことを意味します。タスクに仕様の 記録がないか、stories モードでセンチネルパスが記録されているかのいずれかです。どちらの場合も手順 4 は適用されません。そのブロックがある場合は、以下のセンチネルに関する案内に従ってください。

redrive_base_ref は、2つの対処方法のどちらを適用するかを示します。 人間に何かを伝える前に 必ず読み込んでください。ブランチ名と HEAD では、適用すべき方法が正反対です。

値が false でも、編集を省略しないでください。修正した仕様が引き継がれるものであり、あなたと人間が 合意した内容を最も明確に示すものです。通常どおり手順 4 を行い、解決内容とあわせて、修正を読み込み 可能な場所に反映する必要があることを人間に伝えてください。どこに反映するかはこのフィールドで 決まります。redrive_base_ref がブランチ名の場合は、そのブランチにコミットします。HEAD の場合は、 メインチェックアウトに再適用し、コミットせずに残します。以下の2つの段落で、それぞれのケースを説明します。

よくある次の2つの対応では、どちらも何も起きないまま失敗するため、正確に説明してください。

  • メインチェックアウトからコミットしても、編集したファイルは含まれません。リンクされたユニットの ワークツリーにあるため、別の作業ツリーになっています。
  • ユニット独自のブランチにコミットしても、再実行には反映されません。置き換え用のワークツリーは、 破棄されたマウントのブランチではなく、redrive_base_ref から新しく作成されます。

そのため、修正内容は redrive_base_ref 自体に反映する必要があります。そのツリーにある仕様のコピーにも 同じ編集を行い、そこでコミットしてください。オーケストレーターはストーリーを再び有効化するときにも 同じ ref を指定します。セッションを終了した後ではなく、終了前に人間が把握できるよう、ここで伝えてください。 redrive_base_ref が HEAD の場合、コミットするよう指示してはいけません。 この場合、再実行はメインのチェックアウトで行われ、作業ツリーを読み取るため、そこでの編集はそのまま読み込まれます。HEAD ベースの横にある spec_reaches_the_redrive: false は、上記とは逆の問題を示しています。spec_file が、この実行で使用を停止したワークツリー内を指しています。ストーリーがエスカレーションされたままになっている間に、分離ポリシーが変更されたためです。対処法は、メインのチェックアウトにある仕様書のコピーにも同じ編集を行うことです。コミットもブランチも不要です。ここでコミットするよう指示すると、再実行が読み取らないツリーに誘導することになり、逆方向の同じ作業喪失につながります。

stories モード(フォルダー+IDによるディスパッチ)では、コンテキストに stories ブロックも含まれます。これはこのストーリーのマニフェスト上の意図を示すため、探し回らなくても何をするものか確認できます。

{
  "stories": {
    "spec_folder": "_bmad-output/epic-1",
    "story": {
      "id": "6-4-cli-list-command",
      "title": "CLI list command",
      "description": "…",
      "spec_checkpoint": false,
      "done_checkpoint": false,
      "invoke_dev_with": "…free-text planner→dev note, or ''…"
    },
    "sentinel": {
      "kind": "unresolved",
      "path": ".../stories/6-4-cli-list-command-unresolved.md",
      "blocking_condition": "…the reason planning halted…"
    }
  }
}

sentinel サブブロックが含まれるのは、エスカレーションされたストーリーがセンチネルである場合のみです(下記の stories モードのセクションを参照)。通常のエスカレーションでは省略されます。

出力マーカーは resolution_path にあるファイルです。正常に解決する場合、これを書き込むのが最後のアクションです。スキーマ:

{
  "story_key": "<key>",
  "decision": "<one or two sentences: the rule you and the human chose>",
  "spec_file": "<the spec you edited>",
  "spec_updated": true,
  "restore_patch": "<optional: path to a saved intent-gap patch to re-apply>"
}

restore_patch は任意で、以下の意図の不一致を解消するパッチ復元の場合のみ使用します。通常の解決では完全に省略してください。

必ず行うこと

  1. コンテキストを読み、次に spec_file の凍結仕様を最後まで読みます — 特に <frozen-after-approval> ブロックを確認してください(開発/レビュー セッションで正として扱われる意図です)。エスカレーションの原因は、ほとんどの場合、 実装で直面したケースについて、このブロックに記載がないか、実装と矛盾していることです。

  2. 現在の一時停止に関する証拠を、人間に明確に提示します:

    • escalations 配列が空でない場合は、記録された項目を現在の順序(新しいものが先)で提示します。記録されたエスカレーションの詳細を paused_reason に置き換えてはいけません。
    • escalations 配列が空の場合は、まず paused_reason に空白以外の文字が少なくとも1文字含まれているテキストが設定されていることを確認します。欠落している場合、null、テキスト以外、またはトリミング後に空欄の場合は、resolve コンテキストの形式が不正であることを報告し、解決マーカーを書き込んではいけません。それ以外の場合は、現在の一時停止に関する入手可能な証拠として paused_reason をそのまま提示し、新しいエスカレーションの詳細は記録されていないことを明示します。ウォーターマークより下を読んだり、フィルターを解除したり、古い成果物のエスカレーションを復元したり、paused_reason からエスカレーションオブジェクトを合成したりしてはいけません。

    選択した証拠を使って、何が曖昧または矛盾しているか、安全な実装を妨げる理由を説明し、明確な推奨案とそのトレードオフを添えて、具体的な解決案を2~4件提示します。簡潔にまとめ、関連する仕様の行を引用してください。

  3. 人間の決定を確認します。 選択が不明確な場合は、追加で質問します。要件を創作してはいけません。人間が判断に迷っている場合は、推測せずに検討を支援してください。

  4. 凍結仕様を更新し、決定が曖昧さなく反映されるようにします:<frozen-after-approval> ブロックと、影響を受ける受け入れ条件/テストマトリックスの行を修正し、新しい開発セッションで解釈が1つに定まるようにします。曖昧さを取り除くための最小限の変更にしてください。より大きな仕様変更が必要な場合は、bmad-spec または bmad-correct-course スキルを使用してもかまいません。spec_reaches_the_redrive が false の場合は、同じ編集を行ったうえで、このコピーはリドライブで読み込まれるものではないことをはっきり伝え、redrive_base_ref が選択する修正方法を明示します:ブランチの場合、修正は redrive_base_ref にコミットする必要があります。HEAD の場合、メインのチェックアウトで再適用し、コミットせずにおく必要があります — ここで変更してもフラグのない編集は失われます。また、誤ったツリーやブランチでのコミットも、完了したように見えて失われる作業です。

  5. resolution_path に解決マーカーを書き込み、その後、人間に解決が記録されたことと、このセッションを終了できることを伝えます — オーケストレーターが、ストーリーを再アームして実行を再開する選択肢を提示します(修正された仕様に基づくクリーンな再ビルドです)。

例外ケース:保存済みパッチがあるレビュー段階の intent gap

エスカレーションが、intent gap で停止したレビュー手順から発生した場合、開発セッションはツリーを元に戻す前に、試みた変更をパッチファイルとして(implementation-artifacts フォルダーに)保存しています。エスカレーションの detail と仕様の ## Review Triage Log に、パッチのパスが記載されています。このパッチは具体的な証拠です。実行時に意図をどのように解釈し、実装したかが正確に示されています。

まず、コンテキストファイルの restore_supported を確認してください。 値が false の場合(worktree 分離実行の場合:再実行ではユニットの worktree が破棄されて再マウントされるため、その場で復元することはできません。仕様が記録されていないエスカレーションの場合:パッチを復元しても再開できるレビューがありません。計画前のセンチネルによる停止の場合:復元する実装がまだ試みられていません)、復元オプションを提示せず、restore_patch も記録しないでください。オーケストレーターが解決を拒否するため、このセッションでの交渉全体が無駄になります。パッチは引き続き証拠として利用できます。

パッチは次の 2 つの方法で使います。

  • 証拠として使う。 パッチ(およびそれが表す差分)を読み、推測した解釈によってどのような結果になったかを確認します。多くの場合、質問だけを見て明確化を書くよりも、参考になる情報が得られます。

  • 試みた解釈が実際に正しかった場合。 実行時の推測が正しく、意図だけが明記されていなかったことがあります。その場合は、人間に明示的な選択肢として提示してください。「実装ではこれを X と解釈しており、実際に求めているのも X です。意図に X と明記し、再実装する代わりに、すでに書かれた変更を使ってレビューを再開します。」人間がこれを選んだ場合:

    1. それでも、仕様の意図を修正し、X と明確に記述します(上記の手順 4 は変わりません。凍結された意図は復元されたコードと一致している必要があります)。
    2. resolution.json に "restore_patch": "<保存されたパッチのパス>" を追加します(エスカレーションの detail/triage log からパスをそのままコピーしてください)。

    その後、オーケストレーターは仕様を in-review に再設定し、パッチをベースラインに再適用して、再度ディスパッチします。これにより、復元された差分を使ってレビュー手順からセッションが再開します。自分でパッチに git apply を実行したり、仕様のステータスを設定したりしないでください。再設定時に、オーケストレーターが両方を決定論的に実行します。

    復元処理と解決コミットを重複させてはいけません。 再設定では再実行のベースラインがブランチの解決後の HEAD に進みますが、保存されたパッチは元のベースラインとの差分です。そのため、このセッションでパッチ対象ファイルに触れるコミットが残っていると、復元時の git apply が失敗し、ストーリーは再びエスカレーションされます(意図的に明示的な動作です。オーケストレーターが解決と古い試行を黙ってマージすることはありません)。解決作業に試みた変更がすでに含まれている場合、または解決作業によってその変更が置き換えられている場合は、restore_patch を省略してください。コミットは再設定後も再実行の開始点として残るため、最初からの再実行でそれらを直接ベースに構築できます。

試みた解釈が間違っていた場合(こちらが一般的なケース)は、restore_patch を完全に省略してください。オーケストレーターは、修正された意図に基づいて最初から再実行します。

絶対にしてはいけないこと

  • オーケストレーターの result.json は絶対に書き換えないでください。これは開発/レビュー用の成果物であり、今回はその種のセッションではありません。
  • sprint-status.yaml は絶対に変更せず、仕様の status: フィールドも絶対に設定しないでください。オーケストレーターは再開時に仕様のステータスを確定的に再設定します。仕様の内容のみを編集してください。
  • ストーリーを実装したり、機能コードを書いたり、テストを実行したり、コミットしたりしては絶対にいけません。作業は修正済みの仕様と解決マーカーを用意した時点で終わりです。spec_reaches_the_redrive が false の場合も同様です。修正済みの仕様を再実行が読み取る場所に反映するのは人間の作業です。redrive_base_ref がブランチを示す場合はそのブランチへのコミット、HEAD の場合はメインのチェックアウトでの再適用が必要です。どちらが必要かを伝えてください。自分で行ってはいけません。
  • スコープを広げてはいけません。エスカレーションされた曖昧さだけを解消してください。無関係な問題に気付いた場合は人間に伝えますが、手を加えてはいけません。

ストーリーモード:センチネルと保存されたコピー

ストーリーモードでは、ストーリーを計画することさえできなかった場合、つまり開発セッションが実際の仕様を書ける段階に達する前に矛盾や不足に突き当たった場合、固定スラッグのセンチネルファイルが、凍結された仕様の代わりに残されます。ファイル名は <id>-unresolved.md(意図が曖昧すぎて計画できなかった場合)または <id>-ambiguous.md(ID に一致するストーリー仕様が複数あった場合)です。コンテキストの stories.sentinel ブロックにセンチネルの名前と、セッションが記録した blocking_condition が含まれています。

センチネルは編集する仕様ではありません。中には計画も <frozen-after-approval> ブロックもありません。そのため、センチネルの場合は次のようにしてください。

  • 凍結された仕様を修正しようとしてはいけません(ステップ 4 の「凍結された仕様を編集する」は該当しません。そもそも仕様がありません)。代わりに、上流の曖昧さを解消して、新たな計画フェーズを成功させてください。通常は、人間と相談して SPEC.md(エピック仕様)または stories.yaml にあるこのストーリーの項目を明確にします。対象となるのは、プランナーが読み取る title/description/invoke_dev_with です。
  • 上流の編集をどこに反映する必要があるかは、仕様の場合とまったく同じく redrive_base_ref で決まります。spec_reaches_the_redrive では判断できません。この値は、センチネルの場合は削除されるファイルである spec_file に関するものだからです。実際に編集する成果物は SPEC.md/stories.yaml であり、同じ問題が当てはまります。redrive_base_ref がブランチを示す場合、再実行では新しいワークツリーがマウントされ、そのブランチのコミット済みツリーから再計画されます。そのため、未コミットの編集は見えず、再計画でも同じセンチネルが再び作成されます。ブランチにコミットする必要があると人間に伝えてください。HEAD の場合、再実行ではメインのチェックアウトの作業ツリーで再計画され、編集内容がそのまま読み取られます。コミットを促してはいけません。オーケストレーターは同じルールで再アームし、ブランチに変更が反映されるまで再開を保留します。
  • 再アーム時、オーケストレーターはセンチネルを ready-for-dev に変更しません(ルーティングする計画がないためです)。センチネルのコピーを {run}/sentinels/<id>-<kind>.md に手掛かりとして保存し、センチネルを削除します。その後のディスパッチで、ストーリーは最初から再計画されます(spec_checkpoint ストーリーの場合は再びレッグ 1 から始まります)。自分でセンチネルファイルに触れてはいけません。
  • 人間が曖昧さの解消方法を決定したら、通常どおり解決マーカーを書きます。編集したもの(例:SPEC.md)を spec_file に設定するか、修正が stories.yaml のみの場合は省略してください。
センチネルではありません:ID に一致するファイルが複数あります

上記の単一ファイルの <id>-ambiguous.md センチネルとは異なり、stories/ 内で <id>-*.md に一致するファイルが複数ある場合(たとえば 3-login.md と 3-signup.md)、ID 自体がディスク上で曖昧なため、オーケストレーターはどちらのファイルも選ばずにストーリーを停止します。この状態は、エスカレーション理由(ambiguous story file match: <names>)と、コンテキストに存在しない内容、すなわち stories.sentinel ブロックも単一の仕様パスもないことで見分けられます。

上記の自動解除は適用されません。保持して削除するセンチネルはなく、再アームするだけでは同じ重複によって再び停止します。解決策はクリーンアップです。人間と相談し、どのファイルがストーリーの正式な仕様なのかを決め、もう一方を削除するか名前を変更します(両方に実作業の内容がある場合は、先に内容を統合してください。名前を変更する場合は、<id>-* パターンから外すか、別の ID に移してください)。一致するファイルが 1 つだけなら、その仕様が再ディスパッチされます。一致するファイルが 0 個なら、最初から再計画されます。その後、通常どおり解決マーカーを書き込めば、再アームと再開が引き継ぎます。

解決できない場合

人間が判断を保留した場合、必要な情報が実際に入手できない場合、または適切な修正が仕様編集の範囲外である場合(たとえば、PRD/アーキテクチャの変更が必要な場合)は、その旨を明確に伝え、解決マーカーを書き込まないでください。マーカーなしで終了すると、ストーリーはエスカレーションされたままになり、実行は一時停止します。これが安全な既定の動作です。オーケストレーターは、解決が記録されていないストーリーを再アームしません。

コメント