mcpField
W
worktree

worktree

github.com/davidlee開発2141 回インストール4 日前に更新
リポジトリ

worktree について

隔離されたGit worktreeの作成と引き渡しを管理するスキルで、doctrineコマンドを使ってワークスペースを作成、プロビジョニング、検証します。solo、worker、独立したcoordination worktreeの経路に対応し、それぞれ異なる隔離要件があります。

主な機能

  1. 01既存のlinked worktreeを検出して利用
  2. 02doctrine worktree forkで分岐ワークスペースを作成・設定
  3. 03solo、worker、coordinationの各経路に対応
  4. 04分岐前にソースツリーのクリーン状態を確認
  5. 05引き渡し前にプロジェクトのベースラインを検証
  6. 06設定時に許可リスト内の無視対象ファイルだけをコピー

活用シーン

  1. 01solo作業用の隔離ワークスペースを準備
  2. 02明示したベースコミットからworker用forkを作成
  3. 03dispatch coordination worktreeを作成または再開
  4. 04エージェントへの引き渡し前にforkを検証

インストール

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

$npx skills add https://github.com/davidlee/doctrine --skill worktree

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

同梱ファイルNOTICE.md

詳細

Worktree

分離された Git worktree のライフサイクルを管理します。既存の分離状態を検出し、doctrine worktree fork を使ってフォークを作成します(worktree の追加、プロビジョニング、可能な場合はフェーズへの紐付けまでを担う動詞です。すべて補償ロールバックに対応し、フォークは自身のツリー内の target/ にビルドします)。スポーンガードを実行し、引き継ぎ前にベースラインが正常であることを確認します。

開始時に宣言します:「worktree スキルを使って、分離されたワークスペースをセットアップします。」

これはサブスキルです。 /execute(mode=solo)は、オプトインされた分離のためにこのスキルを呼び出します。ディスパッチのスポーンスクリプトはハーネスに関係なく、すべてのワーカーに対して fork を呼び出します。/dispatch ルーターは、実行ごとの dispatch/<slice> ツリーに対して、調整パス(以下の worktree coordinate)を呼び出します。これは /route の遷移先ではありません。呼び出し元を通じてアクセスしてください。

モードの契約

このスキルはパラメーター化されているため、ファネルで再利用しても、solo のセマンティクスを引き継ぎません(分岐点)。

入力:

  • mode = solo | worker
  • allow_work_in_place: bool — solo の場合のみ true
  • 要求されたブランチ/パス
  • base — フォークの作成元となる ref。solo の既定値は HEAD です。 worker では明示的な base が必須です(オーケストレーターの調整用 HEAD B)。 詳しくは lib:reference/dispatch-mechanics.md § フォークの base は明示指定し、セッションの HEAD は使わない を参照してください。

動作:

  • solo — サンドボックスによって拒否された場合、work-in-place の段階にフォールバックしてもかまいません(フォークなし。許可されたトランクパスです)。
  • worker — フォールバックしてはいけません。 実際のフォークがないワーカーは重大な失敗です。ファネルでは分離が必須です。fork --worker --base <B> は base を明示的に固定します。暗黙のセッション HEAD は使用しないでください。ワーカーの場合は B ではなく、S.parent == B が成立しなくなります。作成後、worker 側では制約付きの編集→検証→単一の S をフォークにコミットするループを実行します。詳しくはWorker モードを参照してください。

出力: { fork_path, branch, head_sha, provision_report, baseline_result }。 worker は、単一の差分 S をコミットした時点で { fork_branch, head_sha_after } を追加します。オーケストレーターは B..head_sha_after をインポートします。

調整モード — doctrine worktree coordinate(第 3 のパス)

上記の solo/worker はどちらも fork を経由します。ディスパッチ調整用 worktree は別の作成動詞であり、fork のモードではありません。/dispatch ルーターがバッチ 1 の前に、実行ごとに 1 回呼び出します。

doctrine worktree coordinate --slice <N> --dir <path>

これは、ファネル唯一の書き込み先である解決済みトランクから、独自の worktree に dispatch/<slice> を作成(または再開)します。重要なすべての点で fork とは異なります。

  • オーケストレーター自身のツリーです。 調整用ツリーはオーケストレーターそのものです(worker モードは OFF。ワーカーであることはプロセスの属性であり、ディレクトリの属性ではありません。ワーカーの jail 内で DOCTRINE_WORKER によって引き継がれます)。 オーケストレーター用の動詞クラスに属し、他の同クラスの動詞と同様、worker モードでは拒否されます。
  • 作成または再開であり、二つ目のブランチは作りません。 dispatch/<slice> 上にすでに存在する稼働中の worktree は拒否されます(coordination-live — 同じスライスの同時ディスパッチは正当ではありません)。ブランチが存在し、稼働中の worktree がない場合は再開(再接続)します。これにより、/handover 後の新しいオーケストレーターも同じブランチを引き継げます(再開しても安定するため、実行ごとの識別子を使うと再開が壊れます)。
  • コミット済みの plan.toml から、唯一のコピー処理を介してランタイムフェーズシートを再生成します(プロビジョニングに関する処理であり、調整層でのコピーはありません)。

これはワーカー差分のパスではありません。S もインポートもありません。ライフサイクルの大小関係は worktree-life < branch-life です。まとめの時点でディレクトリは削除されますが、dispatch/<slice> と、投影された review/phase refs は成果物として保持されます(/dispatch を参照)。以下の solo/worker の作成方法に変更はありません。

検出(作り直さず、適応する)

CWD がすでにリンクされたワークツリー内にある場合は、それに適応し、別のワークツリーを作成しないでください。

git rev-parse --git-dir          # differs from common-dir ⇒ linked worktree
git rev-parse --git-common-dir

--git-dir ≠ --git-common-dir ⇒ すでにリンクされたワークツリー内にある → 作成をスキップします。

サブモジュールのガード。 サブモジュールでも同じ不等式が成立します。次の方法で区別します。

  • .git の gitdir が …/worktrees/ 以下に解決される ⇒ ワークツリー、…/modules/ 以下に解決される ⇒ サブモジュール。または
  • git rev-parse --show-superproject-working-tree の結果が空でない ⇒ サブモジュール。

サブモジュールは、求める分離状態ではありません。「まだフォークされていない」として扱います。

作成 — doctrine worktree fork(制御されたパス)

フォークディレクトリを選び、コミット前のガードを実行してから、動詞を呼び出します。

doctrine worktree fork --base <B> --branch <name> --dir <path> [--worker]

fork は、作成+プロビジョニング+(マーク付け)+出力を行う唯一の動詞であり、補償ロールバックによってアトミックに処理します(git worktree add の後に失敗すると、可能な範囲で worktree remove --force / branch -D / ディレクトリの削除を実行します。ロールバック自体が失敗した場合は、残ったものを明示して、ゼロ以外の終了コードで終了し、中途半端なロールバックを黙って残すことはありません)。次の処理を行います。

  1. git worktree add -b <branch> <dir> <base> — <dir> / <branch> が存在する場合、または <base> がコミットでない場合は拒否します。<base> は明示的に指定してください。単独実行なら HEAD、ワーカーなら B を指定します。この明示的なベース指定が、このパスを制御されたものにする理由です。
  2. フォークをプロビジョニングします(唯一のコピー処理です。コピー時に調整/ランタイム層は除外します。プロビジョニングを参照)。
  3. --worker を指定する場合、さらに --slice と --phase の両方、および <coord>/.worktrees/<name> ディレクトリが必要です。これらを指定すると、フォークをその (slice, phase) にバインドします。いずれかが欠けている場合、フォークは単に未バインドとなり、下流の動詞は推測で補わず、その状態を正直に報告します(単独実行では --worker を省略します)。
  4. 人間向けのステータスは stderr に報告し、stdout は空のままにします(機械処理に適した状態です)。フォークは自身のツリー内にある <dir>/target にビルドします。環境変数の契約は出力されません。プラットフォームはビルド環境の提供から撤退したためです。

fork はオーケストレーター級であり、worker-mode 中は拒否されます(ワーカーはフォークしません。オーケストレーター/単独実行が worker-mode を OFF にして呼び出します)。

作成バックエンドの優先順位 — 順にフォールバックします。

  1. 既存の分離状態(上記の検出)→ 作成をスキップし、フォークを採用します。
  2. ハーネスネイティブの作成機能が存在し、作成のみ(自動コピーなし)で呼び出せる場合は使用します。これは機会があれば使うだけです。(Claude Code の WorktreeCreate フックが該当しますが、ペイロードにベース/パス/タイプがないため doctrine から駆動できず、ディスパッチも使用しません。代わりに明示的にフォークします。)これを前提に設計してはいけません。依存しないでください。
  3. doctrine worktree fork — 推奨され、テスト済みのデフォルトです。これを優先してください。
  4. サンドボックスによる拒否時は、作業場所での作業(solo のみ、allow_work_in_place=true)に切り替えます。フォークせず、トランクのパスを使います。worker は中止します。
ワークツリーのディレクトリ選択

fork を呼び出す前に、次の優先順位でフォークディレクトリを選びます (superpowers:using-git-worktrees)。

  1. 既存のディレクトリを再利用する — 両方存在する場合は worktrees より .worktrees を優先します。
  2. CLAUDE.md を確認する — 希望が記載されている場合は、確認せずにそれを使用します。
  3. ディレクトリが存在せず、希望も記載されていない場合は、ユーザーに尋ねます。

フォークのパスは <dir>/<branch> です。安全性: 作成前に、ディレクトリが Git の除外対象になっていることを確認する必要があります(git check-ignore -q .worktrees)。確認しないと、フォークの内容が追跡対象になります。除外されていない場合は、.gitignore に行を追加してから、先にコミットしてください。(プロジェクト外のグローバルディレクトリには、この確認は不要です。)

プロビジョニング

fork が自動的にプロビジョニングします。2つ目のコピー処理を実行してはいけません。 doctrine worktree provision <fork> は、単独で使う唯一のコピー処理として用意されています(fork をスキップした、まれな既存フォーク採用時に限り、ソースルートから実行してください。フォーク内からは実行しないでください)。.worktreeinclude を読み込み、層名を指定するパターンがあれば安全側に倒して失敗し、許可リストにある Git 除外対象のファイルのみをコピーします。広範な ** パターンが指定されていても、コピー時に調整/ランタイム層は除外されます。

正直な不変条件の説明(誇張しない)

コピー境界の保証が成り立つのは、プロビジョニングだけがコピーを行うためです。

  • doctrine worktree check-allowlist は静的な問題検出テストです。成功は、パターン名にそのティアが含まれていないことを示すだけで、網羅性を示すものではありません。実際の保証を担うのは、プロビジョニング内の select_copies です。
  • ハーネスが作成時に強制的にコピーし、作成のみで実行できない場合、doctrine ではそのコピーを防げません。保証は check-allowlist のみとなり、プロジェクトは .worktreeinclude を正確に保つ必要があります。だからこそ、デフォルトでは(完全に制御可能な)fork 動詞を使い、ハーネスネイティブの段階には決して依存しません。

ガード

スポーンの前後にこれらを実行します。ガードに失敗した場合は中止し、報告してください。独自の判断で先に進めてはいけません。

  • スポーン前のコミット。 fork の前に、フォークにコミット済みの HEAD だけが反映されるよう、ソースツリーをクリーンにする必要があります。git status --porcelain -z を実行します。追跡対象のファイルに変更がある場合、または未追跡の非無視ファイルがある場合(フォークに暗黙のうちに含まれないため)は中止します。無視対象のファイルは問題ありません。プロビジョニングが許可リストの対象サブセットを処理します。
  • ブランチポイントの確認。 fork は構成上、ワークツリーを <base> に配置します。並行処理拡張では、一括コミットの境界を確認します。doctrine worktree branch-point-check --base <B> は、調整用 HEAD がオーケストレーターのスポーン前の B と一致する場合に 0、それ以外の場合は 1 を返します(→ 再ディスパッチ)。これはインポート時にオーケストレーターが使うガードであり、ワーカーモードは OFF です。ワーカー側のガードではありません。これは HEAD が不動であることの比較であり、マージベースではありません。
  • ベースラインの検証。 作成後、プロジェクトの再生成・検証コマンドをフォーク内で実行し、成功した場合にのみ引き継ぎを許可します(このリポジトリでは doctrine check gate)。コマンドはプロジェクトが提供するものを使い、cargo … のようにハードコードしてはいけません。ビルドできないフォークはプロビジョニング時に修正し、決して引き渡してはいけません。

ワーカーモード(ファネルの半分)

mode=worker は、ディスパッチされたワーカーが fork --worker ワークツリー内で実行する経路です。作成、プロビジョニング、および上記のガードを先に変更せずに実行します。これはベースライン検証の成功後、単独での引き継ぎに代わって実行される処理です。ワーカーは制約付きの書き手です。インポート可能な差分を 1 つ作成して返し、調整/ランタイムのティアには触れません(フォークがすでにそのティアを含めないためです)。

lib:reference/dispatch-mechanics.md の § Worker identity は、スポーン時に設定されるプロセスの属性です。

lib:reference/dispatch-mechanics.md の §§ "The worker returns a working tree, not a commit" と "Workers can silently discard their own work" を参照してください。

作業場所を変えずに作業する形へ劣化させてはいけません。 実際のフォークがないワーカーは必ず中止し、暗黙のうちに同じツリーを編集してはいけません(solo の段階 4 とは対照的です)。作成に失敗した場合は、報告して停止してください。

構造化されたレポート(オーケストレーターのコンテキストに保持し、doctrine のアーティファクトにはしない)を返します。変更内容、検証結果、記憶に値するメモ、フォークのブランチを記載します。ナレッジはフォークではなく、オーケストレーターが確認したコミットに追随します(以下の「trunk への記録」を参照)。

スカッシュによる孤児化の注意点(trunk への記録)

ワークツリーのブランチ内に記録されたメモリは、スカッシュマージによって孤児化します(内容は残りますが、Git の参照先は取り込まれないコミットを指すため、古さの検出が発生します)。永続的なメモリをフォーク後も残す必要がある場合は、ワークツリーのブランチ内ではなく、trunk に記録してください。

.worktreeinclude テンプレート(プロジェクト所有。インストールされません)

Doctrine には秘密情報やローカル固有のファイルがないため、デフォルトではコピーするものはありません。インストーラーも .worktreeinclude を同梱しません(ルートファイルをインストールすると、利用側プロジェクトのファイルを上書きしてしまいます)。Provision はファイルがなくても問題なく動作し(何もコピーせず、終了コード 0 を返します)。

gitignore 対象のローカルファイルをフォークに引き継ぐ必要があるプロジェクトは、リポジトリルートに .worktreeinclude を配置できます。空行、# コメント、リポジトリルートからの相対パス(リテラル)、単純な glob パターン(*、**、?)を指定できます。! による否定やアンカー指定はできません(パーサーが拒否します)。調整/ランタイム層は、いずれの場合も引き継がれません。 静的検証(完全性の確認ではなく、問題の兆候を検出するテスト)を実行します:doctrine worktree check-allowlist。

クイックリファレンス

状況対応
--git-dir ≠ --git-common-dir で、サブモジュールではないすでにフォーク済み → そのまま採用し、作成をスキップ
サブモジュール(modules/ の gitdir/スーパープロジェクト)分離ではない → 未フォークとして扱う
ディスパッチ調整ツリー(実行ごと)doctrine worktree coordinate --slice <N> --dir <path> — 解決済みの trunk を起点に作成または再開。fork モードではありません
デフォルトのフォーク(単独またはディスパッチワーカー)doctrine worktree fork --base <B> --branch <name> --dir <path> [--worker]
ワーカーフォークのベース--base <B> を明示。暗黙のセッション HEAD は使用しません(B ではありません)
Worktree ディレクトリが ignore 対象ではないfork の前に .gitignore に追加し、コミット
サンドボックスがフォークを拒否、mode=solo作業ツリー上で作業(フォークなし)
サンドボックスがフォークを拒否、mode=worker中断(分離が必須)
fork をスキップしたフォークを採用ソースルートから doctrine worktree provision <fork> を実行(唯一のコピー手段)
ツリーが dirty/未追跡かつ ignore 対象ではない中断。起動前にコミット
バッチコミットの境界doctrine worktree branch-point-check --base <B> → 1 の場合は再ディスパッチ
フォーク内でベースラインが失敗プロビジョニングで修正し、絶対に引き渡さない
worker の開始export DOCTRINE_WORKER=1(自動で有効化。失敗しても処理を続行)
worker の検証が成功マージではないコミット S を1つ作成し、{fork_branch, head_sha_after} を返す
worker が2つ以上コミット/マージ/リベース済みフォーク契約違反 — オーケストレーターがインポート前に拒否
worker の検証が失敗報告する。失敗した差分はコミットしない

注意事項

絶対にしないこと:

  • fork/provision 以外の方法で、gitignore 対象ファイルをフォークにコピーすること(唯一のコピー手段です。除外の保証はこれらに依存します)。
  • fork の後に2つ目のコピーを行うこと、またはフォーク内から provision を実行すること。
  • check-allowlist の成功が、許可リストの完全性を意味するかのように扱うこと(これは問題の兆候を検出するテストです)。
  • worker が作業ツリー上での作業に切り替わることを許すこと。
  • worker モードで、作成済みの .doctrine/ ツリーに書き込むこと、export DOCTRINE_WORKER=1 を省略すること、またはマージではないコミット S を2つ以上作成すること。
  • dirty なツリーからフォークすること、または失敗したベースラインを引き渡すこと。
  • --base <B> の代わりに、暗黙のセッション HEAD から worker をフォークすること — ワーカーではセッション HEAD は B ではありません。異なるベースから作成すると、S.parent == B が成立しません。
  • このスキルのマスターを作成または編集すること。gitignore 対象の .doctrine/skills/ にインストールされたコピーは、再インストール時に上書きされます。

必ず行うこと:

  • 作成前に検出し、既存の分離環境に合わせる。
  • fork 動詞を優先し、ハーネスネイティブの段階は利用できる場合に限って使う。
  • 3つのガードをすべて実行し、引き渡し前にベースラインの成功を確認する。
  • 永続的なメモリはフォークブランチではなく trunk に記録する。

結果

出力を報告します:fork_path、branch、head_sha、プロビジョニングレポート(コピーされたファイル/引き継がれなかったファイル)、およびベースラインの結果。フォークブランチを成果物として呼び出し元に返します。

コメント