SSD Nodes Learn Hosting plans →
ガイド Matt Connor著者 Matt Connor

unlazy skillのDepth Treeで完了漏れを防ぐ方法

coding agentが作業途中で完了を宣言する問題を、Depth Tree、gates files、PLAN.md契約で防ぎます。install手順と、深さに応じたコストも解説します。

unlazy skill の役割

unlazy skill は、1 つの失敗を防ぐために作られた agent skill です。つまり、作業が完了する前に coding agent が完了を報告する失敗です。中核となるのは Depth Tree です。これは、タスクを実際の境界に沿って分割し、各リーフに固有の受け入れ条件を設定する手法です。Version 2 では、強制の仕組みを文章からファイルへ移しました。そのため agent は、完了したと主張するのではなく、実行可能なコマンドの一覧に対して完了を証明する必要があります。

これは Leonxlnx が github.com/Leonxlnx/unlazy で MIT license の下で公開しています。固定すべきタグ付きリリースはありません。2026-10-11 時点で、リポジトリの tags と releases の一覧はどちらも空です。このガイドは、2026-08-10 の 2.0.0 source milestone に基づいて最初に作成しました。2026-10-11 に、現在の main の source に対して再確認しました。CHANGELOG では、その source を "Unreleased, target 2.1.0" と表記し、2.1.0 の Git tag または GitHub Release を主張していないと説明しています。現在 install command を実行すると、2.0.0 ではなく、その新しい source が取得されます。この分野の skill は急速に変化するため、稼働状態の setup にこの内容をコピーする前に、リポジトリの CHANGELOG を確認してください。

ここでいう skill は、通常の意味での skill です。タスクが説明に一致すると、harness がモデルの context に読み込む SKILL.md file を指します。この仕組みが初めての場合は、agent skill とは何か、harness がどのように読み込むか から始めてください。unlazy は通常の markdown と少数の Node scripts で構成されているため、独自の server も API key も必要ありません。

エージェントが 80 パーセントで停止し、3 つ目の指示を落とす理由

この動作には、見分けやすいパターンがあります。4 つの作業を依頼すると、返答には 1 つ目、2 つ目、4 つ目が含まれます。最後の要約では、4 つすべてが完了したことになっています。エラーは発生していないため、検知もされません。そして、1 週間後に抜け落ちた作業に気付きます。

unlazy README は、この現象をモデルの怠慢に関する公表研究に基づいて説明しています。arXiv 2512.20662 を引用し、「詳細な複数パートのプロンプトでも、テストしたモデルでは部分的な準拠と早期の打ち切りが発生する」と述べています。gates のリファレンスは、設計上の前提を明確に示しています。「上記のルールは文章であり、文章はこのプロジェクトがすでに最も弱い層として扱っているものです。」エージェントにもっと努力するよう指示しても、未達を生んだ同じコンテキストに文章を追加するだけです。

そのため、version 2 は状態をファイルに保持します。GATES.md 内のチェックボックスは、モデルの裁量の外側にあります。ゲートの下に証拠があるかどうかだけが問題であり、エージェントに確認しなくてもスクリプトで判定できます。

深さツリーをレイヤーごとに理解する

深さツリーは、分割してよい場所にルールを設けた分解方法です。メソッドリファレンスには次のように記載されています。

実際のドメイン、コンポーネント、検証の境界でのみ分割する。二分割は任意とする。
レイヤー 1 を要求されたタスクにする。

成果物はリーフが担います。リーフより上の各レイヤーは、子が返した内容を統合して検証します。

リーフは箇条書き 1 項目より大きな単位です。リファレンスでは、時間ではなく成果でその大きさを決めています。

各リーフを、1 つの一貫した成果物にする。
隣接する小さなリーフを統合し、複数の独立した成果を隠しているリーフは分割する。

このルールによって、深いツリーが単なる作業のための作業になるのを防げます。「変数名を変更する」と書かれたリーフはこの基準を満たしません。その上の分割が 1 レイヤー深すぎたということです。

各リーフでは、4 つのパスを実行します。まずプレースホルダーを残さず完全に実装します。次に、ドメインの専門家の視点で読み直します。その後、欠陥を探し、手間をかけずに改善できる箇所を整えます。完全な改善パスで何も見つからなくなるまで、これを繰り返します。小さなリーフを統合するもう 1 つの理由は、この 4 つのパスです。2 分で済む変更に対して 4 回のパスを実行するのは、形式だけの作業です。

深さは、skill を呼び出すときに指定します。

/unlazy tree 5 refactor the payment module

スラッシュコマンドを使わず、自然言語で指定することもできます。skill の説明は、スラッシュコマンドではなく意図に基づいて照合するためです。

tree 3 build the landing page and do not stop until every gate is checked

このガイドの以前のバージョンでは、深さごとのリーフ数を含む深さの範囲を示していました。現在のメソッドリファレンスにはリーフ数の指定がなく、次のように記載されています。「深さを、作業量やトークン数に関する算術的な約束として扱わないこと。」残っているのは、質的な指針だけです。「機能、範囲が限定されたバグ調査、文書には、浅いツリーまたは単独の台帳を使用する。」オーケストレーションされたツリーは、複数の一貫した成果物について、新しいコンテキストや独立した担当が有効な場合に使用します。より深いツリーが正当化されるのは、追加された分岐が実際の統合境界に対応する場合だけです。

深さを指定しない場合、リファレンスでは「独立した成果物と統合ポイントをすべて明らかにする、最小のツリーを選ぶ」としています。作業に合わない数値を指定した場合は、水増しせずにその不一致を伝えるよう指示しています。「要求された深さが埋め草のリーフを生む場合は、不一致を明示し、最も近い妥当な分解を使用する。」深さは作業の構造を表すため、数を水増ししても品質は向上しません。

gates ファイルの形式

作業を開始する前に、agent は受け入れ基準を gates ファイルに記録します。各 gate はチェックボックスで、その下にコマンドを置きます。

# Gates: pricing section

- [ ] G1: three tiers render with real copy
  CHECK: node check.js pricing --tiers
  EXPECT: 3/3 tiers ok
  EVIDENCE: pending

- [ ] G2: annual toggle changes both price and label
  CHECK: node check.js pricing --toggle
  EXPECT: toggle ok
  EVIDENCE: pending

CHECK はコマンドです。EXPECT は合格と判定する出力で、合格にはコマンドが終了コード 0 で終了することも必要です。EVIDENCE は pending から始まります。合格した実行の後、checker は生の出力ではなく、出力の fingerprint を記録します。manual gate にはコマンドがないため、結果を証明する最小限の事実を記録します。この処理には skill の scripts/gate-check.mjs を使用します。--status を指定すると、コマンドを実行したりファイルを変更したりせずに、未完了の gate を報告します。これにより、transcript を読まずに実行結果を監査できます。ledger のコマンドを実行するのは --approve を渡した場合だけです。そのため、渡す前にすべてのコマンドと、それらが呼び出すすべての script を確認してください。別の scripts/gate-lint.mjs は、何も実行せずに ledger の品質を確認します。

SKILL.md の報告ルールは、1 行で表せます。

必須の gate に未達、放棄、延期、または owner の判断待ちが 1 つでもある間は、完了報告を作成しないでください。

これに加えて、agent には「報告の直前に、すべての数値と完了に関する主張を再測定する」よう指示します。agent が完了したと感じただけでは、gate は閉じられません。EXPECT に一致する出力、または一致しない出力を返す実行を行って、初めて閉じられます。

第三者が実行できる gates を記述してください。「問題なさそう」はチェックになりません。test -s dist/index.html && echo ok で ok を出力することはチェックになります。空のファイルや存在しないファイルでは明確に失敗するためです。

並列作業を始める前のPLAN.md契約

ツリーが十分に広がり、葉が別々のコンテキストで実行されるようになると、葉同士で前提を共有できなくなります。メソッドリファレンスでは、分岐の前に契約を置くよう求めています。「分岐の前に契約を修正する」。計画にはPLAN.mdのすべての必須成果を記載し、「その後、葉を開始する前にインターフェース、形式、共有する前提、エラー規約、命名、所有権を記録する」必要があります。

理由は明確です。2 つのサブエージェントにそれぞれ「エラーハンドリングを追加する」と指示すると、異なるエラー形式をそれぞれ考案します。各葉は局所的には正しいため、どちらも独自のゲートを通過します。問題が現れるのは、両者が接続される箇所だけです。その接続箇所を担当するのは上位層であり、オーケストレーションリファレンスには「子を再検証し、その後にインターフェース、エンドツーエンド、回帰のチェックを実行する」と明記されています。

オーケストレーションモードでは、ドライバーに対して「各葉には共有契約、正確な所有範囲と依存関係、その葉自身の台帳だけを渡す」こと、および「関係のない葉の履歴を漏らさない」ことが求められます。各葉の台帳には書き込み可能なパスを記載し、OWNSのパスが、同時にディスパッチされる他の葉と重複しないようにする必要があります。サブエージェントが戻ったら、ドライバーは「返された葉の実行可能なゲートを、すでにチェック済みのゲートも含めて再実行する」必要があります。--statusだけでは再検証になりません。実際の証拠なしにチェックされた葉の項目は、この再実行を通過できません。

オーケストレーションには下限があります。オーケストレーションリファレンスでは、「1 つの集中したコンテキストで、独立した成果物を隠さずにタスクを実装して検証できる場合は、単独で作業する」よう求めています。各サブエージェントはタスクの理解を最初から組み立て直す必要があるため、小規模なタスクでは、その準備コストが新たに得られる集中力を上回ります。

unlazy skill をインストールするにはどうすればよいですか?

サポートされている方法は skills CLI です。

npx skills add Leonxlnx/unlazy

ユーザーレベルでインストールするには -g を、CLI が検出するすべての agent にインストールするには --all を追加します。このコマンドは、その時点で main にある内容をインストールします。タグ付きリリースはないため、更新によって内容が変わらないインストールが必要な場合は、特定の commit に固定するよう README で説明されています。

手動でインストールする場合は、agent の skills ディレクトリに clone します。

git clone https://github.com/Leonxlnx/unlazy ~/.claude/skills/unlazy
git clone https://github.com/Leonxlnx/unlazy ~/.codex/skills/unlazy

その後、配置されたことを確認します。

ls ~/.claude/skills/unlazy/SKILL.md

パスが表示されれば、ファイルがディスク上に存在します。No such file or directory の場合は、clone 先が別の場所になっています。通常は、想定していた名前で skills ディレクトリが存在せず、git が新しいディレクトリを作成したことが原因です。agent の申告だけで判断してはいけません。agent が skill はインストール済みだと述べても、ファイルが存在することを示したことにはなりません。checker とオプションの hook には Node 16 以降が必要です。サードパーティのランタイムパッケージは使用しません。

2026-10-11 時点で、README には2つの harness が記載されています。Claude Code では /unlazy として skill を呼び出し、Codex CLI では $unlazy として呼び出します。skill loader を持たない harness 向けの手順は記載されていません。そのため、別のツールの rules file に SKILL.md を貼り付ける方法は未検証です。SKILL.md を最初から確実に読み込ませる方法を知りたい場合は、独自の agent skill を作成するで、起動するかどうかを決める frontmatter と description の照合について説明しています。

Claude Code の外部でも Stop hook は機能しますか?

いいえ。この点は正確に理解してください。上記の内容はすべて指示であり、指示は無視される可能性があります。構造的な強制機構は Stop hook の 1 つだけであり、Stop hook は Claude Code の機能です。

node <path-to-skill>/scripts/install-hooks.mjs            # this project only (settings.local.json)
node <path-to-skill>/scripts/install-hooks.mjs --global   # every project
node <path-to-skill>/scripts/install-hooks.mjs --uninstall

Stop hook は、エージェントがターンを終了しようとした時点で実行されます。この hook は現在のセッションの ledger と dispatch 状態を確認し、ゲートが未達成であれば停止をブロックします。そのため、未確認のチェックボックスを残したままターンを終了できません。チェック自体を実行することはなく、独自にモデル呼び出しを行うこともありません。ただし、無料ではありません。token-economy のリファレンスにも「ブロックするとエージェントが継続実行されるため、モデル処理が消費される」とあります。一般的な仕組みと、関連付け可能なその他のイベントについては、ターン中に Claude Code の hook が実行される仕組みを参照してください。README では、ユーザーの同意を得た場合にだけ hook をインストールするよう求めています。また、.claude/settings.local.json、.unlazy/、.unlazy-hook-state.json を ignore ルールに残すよう求めています。

停止を解除する仕組みもあります。これは見た目以上に重要です。エージェントが 6 回連続してブロックされた停止の間にゲートを 1 つも進めなかった場合、hook はエージェントを拘束せずに停止を許可します。metadata だけを変更する編集では、この回数はリセットされません。ABANDON: <gate> <reason> 行がある場合もセッションを終了できますが、合格ではなく、可視化された引き継ぎとして扱われます。放棄されたゲートは、完了した作業ではなく、成功しなかった結果として報告されます。この 2 つの逃げ道がなければ、環境上実行不可能なゲートによって、ユーザー自身がセッションを終了するまで token が消費され続けます。

Codex やその他の harness では、install-hooks.mjs をインストールする対象がありません。これは Claude の設定ファイルにだけ書き込むためです。ゲートファイルと実行可能なチェックは利用できますが、モデルが早い段階でターンを終了することを構造的に防ぐものはありません。その環境では、ゲートファイルを自分で読む必要があります。

unlazy と ponytail: どちらを選びますか?

この 2 つのスキルは同じ時期に注目を集め、ボリュームに対して逆方向に働くため、混同しやすいものです。

ponytail を使うと、エージェントはコードを本当に存在させる必要があるのかを最初に確認するシニア開発者のように動作します。スコープを絞り、標準ライブラリを優先し、差分を小さくします。unlazy はスコープがすでに合意されていることを前提にし、その範囲のすべてを完了して検証できるまで作業を進めます。

そのため、実際に発生している失敗に応じて選んでください。エージェントが小さな機能をフレームワークにまで拡大してしまうなら、ponytail スキルと、その怠惰なシニア開発者のペルソナが必要です。4 つの項目からなる依頼の 3 番目を未完了のままにして成功を報告するなら、unlazy が必要です。

両方を実行することもできますが、順序が重要です。まず ponytail の質問でスコープを確定し、合意したスコープを unlazy のゲートに渡してください。逆の順序にすると、ponytail なら削除していた作業のために、葉が増え続ける作業ツリーを構築し、そのすべてに余分な労力を費やすことになります。この順序は私の推奨であり、2 つのプロジェクト間で文書化された統合ではありません。

VPS 上でエージェントを実行する場合、深さによるコストはどの程度か

作業量はトークンで決まり、独自の API key を使って VPS 上でエージェントを実行する場合、トークンは費用になります。unlazy によってどの程度増えるかについて、プロジェクトは現在、数値での回答を控えています。

このガイドの以前の版では、著者による6回の実行比較に基づき、出力トークンとコストの倍率を示していました。その後、著者はこれらの数値を撤回しました。references/token-economy.md には、根拠となった raw prompt、trace、output、評価記録がリポジトリから失われており、「そのため、ここでは数値を再現できない」と記載されています。さらに、「これらを製品の保証として使用しないでください」とも記載されています。手法のリファレンスでは、さらに踏み込んで「深さを、作業量やトークン数に関する算術的な約束として扱わないでください」としています。著者自身が支持しなくなった数値を繰り返さないため、ここでは削除しました。

コストについてリファレンスが現在示しているのは、方向性です。冒頭では、「繰り返し行う決定的な検証はコマンドに移し、オーケストレーションのコンテキストを狭く保つ」ことを勧めています。Solo mode では、1つのコンテキスト内で追加の出力トークンを消費します。Orchestrated mode ではコンテキストが増え、新しいコンテキストは、有用な作業を始める前に契約と独自の台帳を読み取ります。リファレンスは、両方向について警告しています。「1つの集中したセッションで実装と検証を確実に完了できるタスクをオーケストレーションしないでください。」一方で、末端の作業単位と契約が明確なのに、サブエージェントのオーバーヘッドを避けるためだけにビルド全体を1つのコンテキストに保持することも避けるよう警告しています。

ここから、次の4つの設定が導かれます。

  • 末端が実際の作業単位になる最小限の深さを選び、そこで止めます。不要な深さは、不要な支出です。
  • 1つの集中したセッションでタスクの構築と検証ができる場合は、Solo mode を使用します。サブエージェントのセットアップコストが、新しいコンテキストによる効果を上回るためです。
  • Claude Code を使用している場合は、Stop hook を導入します。この hook 自体は model call を行いませんが、ブロックするたびにエージェントを作業へ戻すため、その作業には費用が発生します。
  • 長時間の作業を始める前に、アカウントレベルで厳格な支出上限を設定します。

最後の点が、正直な回答です。早期停止を拒否するよう設計された skill は、設計上、作業を継続します。予算とアラートの設定は、プロンプト作成とは別の作業です。VPS 上でエージェントのコストを制御する方法では、最初に設定すべき上限について説明しています。

著者が測定した内容と、それが示すこと

このリポジトリは以前、独自のテストを公開していました。このような対応は本来もっと一般的であるべきですが、実際には珍しいものでした。その後、そのテストの扱いを撤回しました。これはさらに珍しい対応です。現在の README には、「以前の README では、6 回実行した内部比較にも言及していた」と「それらの正確な比率と件数を再現するために必要な生データは、このリポジトリにはない」とだけ記載されています。README は、「結果はベンチマークの保証ではなく、過去の設計材料として扱うこと」としています。

この構成は research/validation-protocol.md に残っています。2 つのビルドタスクを用い、それぞれで 3 つの条件(スキルなし、tree 3、tree 6)を試し、実行ごとに新しいフォルダーとセッションを使用します。このプロトコルでは、これを「メンテナーが実施する探索的比較」と呼んでいます。また、そこで得られたトークン比率、自己発見した欠陥の件数、実行中の失敗件数、レポート番号の誤りは、リポジトリから再現も監査もできないと説明しています。さらに、この比較を unlazy が特定の改善やコスト倍率をもたらす証拠として説明してはならないとしています。以前の版のこのガイドでは、そのテストにおける実行ごとの件数を図示していました。著者が撤回したため、これらは削除しました。

数値がなくなっても、設計上の教訓は残っています。「報告する直前に、すべての数値と完了に関する主張を再測定する」という規則は、現在も SKILL.md にあります。また、gates のテンプレートでは、与えられた数値を EXPECT にコピーして、それ自体を証拠にしないよう注意しています。壊れたビルドの上に自信のある要約を載せることは、まさに gates が防ごうとしている問題です。

ここで限界を確認します。2026-10-11 時点で、検討できる公開結果は残っていません。残っているのは、適切に再実行するための手法とプロトコルだけです。代わりに、自分の作業で試してください。同じタスクを 2 回実行します。1 回は通常どおり、もう 1 回は gates ファイルを使用します。その後、自分で再実行できる証拠を伴って完了した gates の数を数えます。この領域で自分に属する数値は、その件数だけです。

FAQ

unlazy skill の Depth Tree とは何ですか?

分解手法です。タスクは、実際のドメイン、コンポーネント、または検証の境界でのみ分割します。layer 1 は依頼されたタスクです。各 leaf は、固有のゲートを持つ、まとまりのある 1 つの成果物です。隣接する小さな leaf は統合し、複数の独立した成果を隠している leaf は再度分割します。leaf より上の各 layer は統合と検証を担います。子の内容を再確認した後、インターフェース、エンドツーエンド、回帰のチェックを実行します。呼び出し時に深さを指定します。たとえば tree 5 のように指定します。深さを指定しない場合、skill は、独立したすべての成果物と統合ポイントを明らかにできる最小の tree を選びます。

unlazy skill は Claude Code 以外でも動作しますか?

一部は動作します。skill は plain markdown で記述されており、README には Claude Code とともに Codex CLI も記載されています。そのため、Depth Tree、gates file、実行可能なチェック、各 leaf の 4 つの pass は Codex CLI でも利用できます。現在のドキュメントでは、その他の harnesses は扱っていません。強制の仕組みは異なります。ゲートが未達成の間、turn の終了をブロックする Stop hook は Claude Code の機能であり、node <path-to-skill>/scripts/install-hooks.mjs でインストールします。それ以外の環境では、モデルが早期に turn を終了することを構造的に防ぐものはありません。そのため、gates file を読み、再度モデルに渡すのは利用者です。

unlazy skill によって token bill はどの程度増えますか?

現時点で信頼できる数値を示せる人はいません。作者が以前示した token 比率は、再現できない 6 回の実行結果に基づいています。現在のドキュメントでは、これらを製品の保証値として使用しないこと、また depth を作業量や token 数に関する算術的な約束として扱わないことが明記されています。ただし、方向性は明確です。Solo mode では、1 つの context 内の出力が増えます。Orchestrated mode では、各 leaf に新しい context が追加され、作業前に contract と ledger を読み込みます。Stop hook 自体は model call を実行しませんが、ブロックされるたびに agent は作業へ戻されます。自分のタスクを使い、自分の課金条件に対して測定してください。

unlazy と ponytail のどちらを使うべきですか?

目の前の失敗に合わせて skill を選んでください。ponytail は、書きすぎる agent 向けです。senior developer のように、コードが存在する必要があるかを問い、まず standard library を使おうとします。unlazy は、依頼した内容を十分に完了しない agent 向けです。分解を強制し、証拠がない限りゲートを完了扱いにしません。両方使う場合は、まず ponytail で scope を確定し、その scope を unlazy に渡してください。削除すべき作業に対して effort multiplier を支払わずに済みます。

unlazy をインストールした後も agent が早期に停止するのはなぜですか?

4 つ確認してください。まず ls ~/.claude/skills/unlazy/SKILL.md で skill がディスク上に存在することを確認します。存在しないディレクトリへ clone したことが、よくある見落としです。次に、作業開始前に gates file が作成されていることを確認します。hook は session の ledger をスキャンするため、GATES.md がないとブロック対象がありません。3 つ目に、hook のインストール先を確認します。単純な install-hooks.mjs の実行では、この project の settings.local.json にのみ書き込まれるため、別の project では --global が必要です。4 つ目に、release valve は仕様どおりに動作していることを確認してください。ゲートの進展がないまま 6 回連続して停止がブロックされると、agent は解放されます。また、ABANDON: <gate> <reason> の行は意図的に試行を終了し、成功ではない handoff を明示します。