何を見つけたか
cross-review / cross-refactoring をサブエージェントへ委ねると、ラウンドの待ちで応答を終えて止まる。 マイルストーン「04 worktree 運用の残課題」の進行で 4 回 起きた。いずれも進行側(親セッション)が「続けてください」と指示して再開している。
止まった場面は、どちらの Skill も「待ちから戻った後に何をするか」が次の段へ書かれているのに、待ちそのものが 1 回の応答の区切りになりうる形である。
cross-review は light モードの rotation で、ループ全体を 1 回の bash で完結させず exit 10 で停止して親の介入を待つ設計を持つ(SKILL.md 「light モード rotation の再開プロトコル」)
cross-refactoring は提案・適用・修正のそれぞれで monitor.py を待ち、結果ファイルの有無で次を決める
待ちは正常な状態であるため、止まったことが出力に現れない。 ハートビートは出続け、担当は「結果を待っています」で応答を終える。親から見ると作業中と区別が付かない。
両 Skill とも、待ちで応答を終えないことをまだ書いていない。
$ git grep -n " 応答を終え\|同じターン\|run_in_background" -- plugins/ndf/skills/cross-review plugins/ndf/skills/cross-refactoring
(出力なし)
構造的な原因: 待ちが Bash ツールの上限より長い
Claude Code の Bash ツールは 1 回の実行が 600 秒で打ち切られる。 600 秒を超える待ちは、バックグラウンド実行(run_in_background)と待ちの道具(Monitor など)を使わざるをえない。そこで応答の区切りが生まれる。
上限は v10.13.0(#598 / #537 )で工程ごとの表(scripts/lib/limits.py)が決めるようになり、値が変わった。
秒数は SKILL.md に書かれず、monitor.py --phase <工程> が表から解決する。
工程
監視の上限
1 回の Bash に収まるか
cross-refactoring の提案(--phase propose)
1200 秒
収まらない
cross-refactoring の適用・修正・最終ゲートの修正(--phase apply / fix / final-fix)
3600 秒
収まらない
cross-review のレビュー・批評(--phase review / critique)
1200 秒
収まらない(以前は 420 秒で収まっていた)
cross-review も 1 回の Bash に閉じられなくなった。 agy の打ち切りを直すために上限を 600 秒より
長くしたためで、この課題が言う「待ちが Bash ツールの上限より長い」状態が全工程へ広がった。
直さないと何が起きる
直し方の候補
両 Skill の駆動の節へ、待ちの区切りで応答を終えない ことを明示する。待ちと、その後の判定・次のラウンドの起動までを 1 つの実行の単位として書く(段が分かれているため、段の境目が応答の境目になりうる)
待ちを 1 回の Bash 実行へ閉じる。monitor.py の呼び出しと、その直後の merge-* / start-round までを同じ実行に入れる。exit 10 のように親の介入が要る箇所だけを区切りにする。監視の上限が 600 秒を超える工程では成り立たない (上の表)
サブエージェントへ委ねるときの起動プロンプトへ「待ちで応答を終えない。結果が出るまで同じターンの中で待つ」を入れる(issue-plan-strategy / 進行を委ねる側の手順)
Bash ツールの上限 600 秒を超える待ちは、バックグラウンド実行と待ちの道具を使う前提で書き方を決める。 待ちの道具から戻った後に同じ応答の中で次の段へ進むこと、戻る前に応答を終えないことを手順に書く
v10.13.0 で道具の側は入った。 cross-review/scripts/bg-wait.sh が背景で起動して終了コードを
rc ファイルへ残し、wait が 540 秒以内で区切って待つ(124 = まだ終わっていない)。cross-review の
骨組みはこの形で待つようになった。残っているのは 2 つである。
cross-refactoring の待ちは bg-wait.sh の形になっていない (上限の表で監視・CLI・無進捗の許容の順序を決め、600 秒を超える監視を区切って待つ(#598 #537) #683 の範囲外として明示的に残した)。
cross-refactoring の骨組みは monitor.py を前面で呼ぶ(cross-refactoring/SKILL.md:322 / :331 / :343 / :365)。
道具の置き場所が、cross-refactoring から使えない位置にある。 bg-wait.sh は
plugins/ndf/skills/cross-review/scripts/ にあり、共通層の plugins/ndf/scripts/lib/ には無い。
冒頭のコメント(bg-wait.sh:22-23)は「置き場所は cross-review の scripts/ にする。いま使うのは
cross-review だけで、cross-refactoring の待ちは cross-review / cross-refactoring をサブエージェントへ委ねると、ラウンドの待ちで応答を終えて止まる #656 が扱う」と書く。別の Skill の scripts/ を
起動する参照は、scripts/check-cross-skill-refs.py が例外の一覧に無い限り失敗として返す
サブエージェントへ委ねたときに応答を終えないことは、どちらの Skill にもまだ書かれていない。
道具があっても、区切りで応答を終えれば同じことが起きる
$ git grep -c " 応答を終え\|同じターン\|run_in_background" -- plugins/ndf/skills/cross-review plugins/ndf/skills/cross-refactoring
(出力なし。2026-09-16 に確認)
v10.15.0 で入ったもの(規則の側)
候補 3 と、候補 4 の「戻る前に応答を終えない」は、3 層(conductor / supervisor / worker)の規則として
plugins/ndf/skills/development-workflow/references/agent-layers.md に入った。
規則
場所
supervisor の規則 4「待ちで応答を終えない。待ちの道具から戻った後、同じ応答の中で次の段へ進む」
agent-layers.md「conductor → supervisor」
待ちで応答を終えた相手は上の層に「完了」で届く。報告の見出しが無ければ完了として扱わず、SendMessage で 3 回まで続けさせる
agent-layers.md「報告が無いまま終わったとき」
cross-review の収束ループを回すのは supervisor。修正は worker
agent-layers.md「委譲の線」、cross-review/references/context-budget.md「メインが指すもの」
確定仕様 docs/specifications/ndf-agent-layers-unattended-run.md はこの課題の事象を「上の層から completed で届く」形として扱う。
待ち方の規約は development-workflow/references/waiting.md に置く。 #829 の実装(PR #844 )がこの文書を新設し、「サブエージェントは、背景の処理を残したまま応答を終えない」と書く。あわせて「他の作業が無いまま待つときの手は #656 が扱う」とこの課題を名指しする。
残るのは 3 つである。
他の作業が無いまま待つときの手を waiting.md に足す(待ちの問い合わせと長い conductor の工程の起動を hook で止める(#829 #830) #844 のマージの後)。 候補は bg-wait.sh wait を前景で呼ぶ形(sleep がスクリプトの中にあり、hook に止められない)と Monitor。呼び直しの回数が費用になるため、待つ間の繰り返し問い合わせ(sleep ループ・出力ファイルの読み直し)をやめ、完了通知か Monitor で待つ #829 の費用の表と並べて比べる
cross-refactoring の待ちを bg-wait.sh の形にする。 cross-review / cross-refactoring: SKILL.md に埋め込んだ駆動の bash を scripts/ へ出す #560 が駆動を scripts/ へ切り出す行と同じ場所なので、cross-review / cross-refactoring: SKILL.md に埋め込んだ駆動の bash を scripts/ へ出す #560 と同じ PR で行う。bg-wait.sh を共通層 plugins/ndf/scripts/lib/ へ移すのは 長い待ちを区切る道具を共通層へ移し、サブエージェントで止まる待ちと上限の無い待ちを根本原因の場所で直す #731 で、この駆動がその最初の読み手になる
両 Skill の骨組みから waiting.md を指す。 規則を写さない(「待ちで応答を終えない」の正本は waiting.md と agent-layers.md)
由来
マイルストーン「04 worktree 運用の残課題」の振り返り。#637 / #639 / #640 / #643 / #646 の cross-review / cross-refactoring のラウンド待ちで 4 回。
関連
何を見つけたか
cross-review/cross-refactoringをサブエージェントへ委ねると、ラウンドの待ちで応答を終えて止まる。 マイルストーン「04 worktree 運用の残課題」の進行で 4 回起きた。いずれも進行側(親セッション)が「続けてください」と指示して再開している。止まった場面は、どちらの Skill も「待ちから戻った後に何をするか」が次の段へ書かれているのに、待ちそのものが 1 回の応答の区切りになりうる形である。
cross-reviewは light モードの rotation で、ループ全体を 1 回の bash で完結させずexit 10で停止して親の介入を待つ設計を持つ(SKILL.md「light モード rotation の再開プロトコル」)cross-refactoringは提案・適用・修正のそれぞれでmonitor.pyを待ち、結果ファイルの有無で次を決める待ちは正常な状態であるため、止まったことが出力に現れない。 ハートビートは出続け、担当は「結果を待っています」で応答を終える。親から見ると作業中と区別が付かない。
両 Skill とも、待ちで応答を終えないことをまだ書いていない。
構造的な原因: 待ちが Bash ツールの上限より長い
Claude Code の Bash ツールは 1 回の実行が 600 秒で打ち切られる。 600 秒を超える待ちは、バックグラウンド実行(
run_in_background)と待ちの道具(Monitor など)を使わざるをえない。そこで応答の区切りが生まれる。上限は v10.13.0(#598 / #537)で工程ごとの表(
scripts/lib/limits.py)が決めるようになり、値が変わった。秒数は SKILL.md に書かれず、
monitor.py --phase <工程>が表から解決する。--phase propose)--phase apply/fix/final-fix)--phase review/critique)cross-review も 1 回の Bash に閉じられなくなった。 agy の打ち切りを直すために上限を 600 秒より
長くしたためで、この課題が言う「待ちが Bash ツールの上限より長い」状態が全工程へ広がった。
直さないと何が起きる
直し方の候補
monitor.pyの呼び出しと、その直後のmerge-*/start-roundまでを同じ実行に入れる。exit 10のように親の介入が要る箇所だけを区切りにする。監視の上限が 600 秒を超える工程では成り立たない(上の表)issue-plan-strategy/ 進行を委ねる側の手順)v10.13.0 で道具の側は入った。
cross-review/scripts/bg-wait.shが背景で起動して終了コードをrc ファイルへ残し、
waitが 540 秒以内で区切って待つ(124 = まだ終わっていない)。cross-review の骨組みはこの形で待つようになった。残っているのは 2 つである。
bg-wait.shの形になっていない(上限の表で監視・CLI・無進捗の許容の順序を決め、600 秒を超える監視を区切って待つ(#598 #537) #683 の範囲外として明示的に残した)。cross-refactoring の骨組みは
monitor.pyを前面で呼ぶ(cross-refactoring/SKILL.md:322/:331/:343/:365)。道具の置き場所が、cross-refactoring から使えない位置にある。
bg-wait.shはplugins/ndf/skills/cross-review/scripts/にあり、共通層のplugins/ndf/scripts/lib/には無い。冒頭のコメント(
bg-wait.sh:22-23)は「置き場所は cross-review の scripts/ にする。いま使うのはcross-review だけで、cross-refactoring の待ちは cross-review / cross-refactoring をサブエージェントへ委ねると、ラウンドの待ちで応答を終えて止まる #656 が扱う」と書く。別の Skill の
scripts/を起動する参照は、
scripts/check-cross-skill-refs.pyが例外の一覧に無い限り失敗として返す道具があっても、区切りで応答を終えれば同じことが起きる
v10.15.0 で入ったもの(規則の側)
候補 3 と、候補 4 の「戻る前に応答を終えない」は、3 層(conductor / supervisor / worker)の規則として
plugins/ndf/skills/development-workflow/references/agent-layers.mdに入った。agent-layers.md「conductor → supervisor」SendMessageで 3 回まで続けさせるagent-layers.md「報告が無いまま終わったとき」cross-reviewの収束ループを回すのは supervisor。修正は workeragent-layers.md「委譲の線」、cross-review/references/context-budget.md「メインが指すもの」確定仕様
docs/specifications/ndf-agent-layers-unattended-run.mdはこの課題の事象を「上の層からcompletedで届く」形として扱う。待ち方の規約は
development-workflow/references/waiting.mdに置く。 #829 の実装(PR #844)がこの文書を新設し、「サブエージェントは、背景の処理を残したまま応答を終えない」と書く。あわせて「他の作業が無いまま待つときの手は #656 が扱う」とこの課題を名指しする。残るのは 3 つである。
waiting.mdに足す(待ちの問い合わせと長い conductor の工程の起動を hook で止める(#829 #830) #844 のマージの後)。 候補はbg-wait.sh waitを前景で呼ぶ形(sleep がスクリプトの中にあり、hook に止められない)とMonitor。呼び直しの回数が費用になるため、待つ間の繰り返し問い合わせ(sleep ループ・出力ファイルの読み直し)をやめ、完了通知か Monitor で待つ #829 の費用の表と並べて比べるbg-wait.shの形にする。 cross-review / cross-refactoring: SKILL.md に埋め込んだ駆動の bash を scripts/ へ出す #560 が駆動をscripts/へ切り出す行と同じ場所なので、cross-review / cross-refactoring: SKILL.md に埋め込んだ駆動の bash を scripts/ へ出す #560 と同じ PR で行う。bg-wait.shを共通層plugins/ndf/scripts/lib/へ移すのは 長い待ちを区切る道具を共通層へ移し、サブエージェントで止まる待ちと上限の無い待ちを根本原因の場所で直す #731 で、この駆動がその最初の読み手になるwaiting.mdを指す。 規則を写さない(「待ちで応答を終えない」の正本はwaiting.mdとagent-layers.md)由来
マイルストーン「04 worktree 運用の残課題」の振り返り。#637 / #639 / #640 / #643 / #646 の cross-review / cross-refactoring のラウンド待ちで 4 回。
関連
agent-layers.md)はここで入った(v10.15.0)waiting.mdと hook(PR 待ちの問い合わせと長い conductor の工程の起動を hook で止める(#829 #830) #844)。この課題はwaiting.mdから名指しされるため、開いたまま残すrun_in_backgroundの完了通知を 1 回受ける)。残り 2 の上に乗る