mcpField
A
agent-sync

agent-sync

github.com/sshelegエージェントワークフロー5259 回インストール2 日前に更新
リポジトリ

agent-sync について

agent-syncは、同じリポジトリで並行作業する複数のエージェントを調整するSkillです。Gitの永続記録と期限付きの調整状態を組み合わせ、リース、編集保護、設定チェックを提供します。

主な機能

  1. 01期限付きリースによるエージェント調整
  2. 02共有レジストリ編集の保護
  3. 03リポジトリ間依存関係の追跡
  4. 04プロジェクト設定の構成と検証
  5. 05Git記録とクラウド状態の照合

活用シーン

  1. 01複数エージェントによる共有ファイルの上書き防止
  2. 02エージェントセッション間でのタスク取得と解放
  3. 03不在中に発生した依存関係の変更確認

インストール

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

$npx skills add https://github.com/ssheleg/agent-sync --skill agent-sync

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

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
adapter-contract.md
backend-fs.md
backend-notion.md
backend-outline.md
branching.md
earned-rules.md
fabric-coordination.md
hooks.md
lease-protocol.md
pipeline-binding.md
roadmap.md
two-sources.md
scripts/
agent_sync.py
bash_writes.py

詳細

agent-sync — 1つのプロジェクトで複数のエージェントが衝突せずに作業する

2つのプレーンと、その間にある1つのルールです。

Git は記録プレーンです。クラウドは調整プレーンです。 残す必要がある事実は、まず Git に書き込み、クラウドから参照します。 今、誰が何をしているかという事実はクラウドに置き、有効期限を設けます。

永続的な事実を保持する場所が、クラウドオブジェクトだけになることはありません。以下のすべては、複数のエージェントが同時に書き込んでもこの原則を守るためのものです。

頼まれていなくても実行する場面: .claude/agent-sync.json があるプロジェクトで、共有レジストリ(決定事項、未解決の質問、ロードマップ、ワークストリーム、依存関係)を編集する前。編集の申告がなければ、2つのエージェントが互いの変更を上書きしかねません。また、/agent-sync も実行してください。

4つの落とし穴 — 何よりも先に読んでください

1. ナレッジベースはリースを決定しません。 それは不可能です。同じOutlineドキュメントに12回同時に追記したところ、12回とも成功を返し、残ったのは3行でした。排他制御には、実際の比較交換(compare-and-swap)を行うものが必要です。このプレーンが担うのは記録だけです。

2. 自分がどのリースを持っているか把握し、それを明示してください。 leaseBackend: "local" はアトミックなファイル作成で、同じファイルシステム上のプロセス間では排他的ですが、マシンをまたぐと助言的な制御にとどまります。leaseBackend: "git" は ref をプッシュし、リモート側での非早送り拒否が比較交換そのものとなるため、マシンをまたいで排他制御できます。acquire はどちらの方式かを表示します。見せかけのリースは、リースがない状態よりも悪いものです。ほかのエージェントが確認をやめてしまうからです。

acquire はロードマップにも申告を書き込み、release は元の状態を正確に復元します。 1行、1セルに限定し、曖昧さがある場合は拒否し、往復後の git diff は空になります。claimTags を設定したりタスクをクローズしたりする前に、references/roadmap.md を読んでください。タスクのクローズは作業に関する表明であり、その責任はあなたにあります。

ブランチで作業してください。統合ブランチは、ほかの誰かが使う安定したベースです。 acquire が申告を書き込むのは、統合ブランチだけです。それ以外のブランチでは、保持者の情報は調整プレーンにとどまり、status で全エージェントに表示されます。ブランチにコミットした申告はマージするまで見えず、共有ロードマップは双方のブランチが編集するファイルになってしまいます。作業を取り込むときは merge を使ってください。変更前に競合を計算し、マージを docs/MERGES.md に記録して、--key リースを解放します。merges では、離れている間に取り込まれた内容を確認できます。マージする前に、references/branching.md を読んでください。

3. Claude フックアダプターを検証してください。 強制が検証されていない場合は、guard を明示的に実行してください。フックの証拠は、gated のリース調停とは分けて報告します。各モードの5つの機能フィールドは、1か所だけに記載されています。references/adapter-contract.md → The status capability contract を参照してください。ここで繰り返して説明しないでください。保護されていないプロジェクトを、保護されていると説明してはいけません。

4. 読み取れないログは、競合に負けたことを意味しません。 - を出力し、-/*/+ を受け入れ、フィルタリングの前にエントリー形式の不正な行をすべて数え、解析できない行が2%を超える場合は拒否します。解析の契約と確認された失敗は references/lease-protocol.md に記載されています。

どんなプロジェクトにも導入する — 一連の手順

scaffold  → create the documentation architecture, only where it is absent
adopt     → read the repository, propose a config, write nothing
init      → write the approved config + the gitignored env file
            (operator places the token — never you)
reconcile --set-baseline    → make history a counted backlog, once
setup     → generate the snapshot that describes this project's wiring
check     → validate the whole thing; non-zero if it is not healthy

check は、ルールの参照先、認証情報、レジストリのベースラインがない場合、スナップショットが古い場合、または Git で追跡されている env ファイルがある場合に拒否します。 導入後、設定変更後、CI で実行してください。失敗している条件をすべて表示します。

scaffold は既存ファイルを上書きしません。 決定事項レジストリと、スナップショットを参照する AGENTS.md を用意し、既存ファイルには一切手を加えません。

既存のプロジェクト:まず adopt を実行

init の前に adopt を実行してください。リポジトリを調べて、見つかった内容(IDレジストリ、レジストリファイル、ゲート)と、代わりに判断することを拒否する項目を表示し、設定案を提示します。

python3 "$SKILL_DIR/scripts/agent_sync.py" adopt

まず担当者とともに、レジストリとガード対象ファイルを確認してください。レジストリが誤ったファイルを参照していると、以降のチェックがすべて自信満々に誤った結果を出します。また、共有ファイルをガード対象に含め損ねると、衝突が起こる唯一の場所が保護されないままになります。サブモジュールではレジストリを宣言しません。決定事項は親プロジェクトに属するためです。その後、上記の一連の手順を init から進めてください。

プロジェクトで最初に実行するコマンド:init

未初期化のプロジェクトに対して、ほかの操作を実行してはいけません。 init はストレージに関する質問を一度だけ行って回答を受け、その内容を書き留めます。

チャットでオペレーターに次の2点を確認してください。推測したり、デフォルトを選んだりしてはいけません。

  1. 調整状態をどこに置きますか?

    • ナレッジクラウド — outline(ホスト型またはセルフホスト型)、あるいは notion — マシン間で共有する記録、状況認識、ボードです — どちらもリースの決定は行いません(落とし穴1)。
    • またはローカルファイル(fs) — 認証情報は不要ですが、別のマシン上のエージェントには見えません — 状況認識、リポジトリ間のシグナル、ボードの共有はありません。

    リースは別途 leaseBackend で決まり、gated は記録プレーンではなく、その選択に従います — 実際に得られる保証を報告してください。ID も同様です。leaseBackend: "git" の場合、レジストリは fs 上でも git refs から予約されます。

  2. クラウドの場合:どこにしますか? Outline にはインスタンス URL が必要です。Notion には、コンテナを配置するページの ID が必要です。どちらも設定値であり、秘密情報ではないため、書き留めてもかまいません。トークンは違います — チャットで尋ねてはいけません。読み返してはいけません。自分で設定してもいけません。

回答を受けたら、次のように実行します。

python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend outline --url https://<their-instance>
python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend notion
python3 "$SKILL_DIR/scripts/agent_sync.py" init --backend fs

init は .claude/agent-sync.json(構造、コミット対象)と、トークン欄が空の .env.agent-sync(ID、モード 600)を書き込み、両方を gitignore に追加して、オペレーターが行う唯一の手順 — トークンを作成して設定すること(notion の場合は vault)— を出力します。--force を指定しない限り、どちらのファイルも上書きしません。最後に表示される手順は一言一句そのまま伝えてください。この設計は、トークンをオペレーター自身の管理下に置くことを前提としています。

その後、各セッションの開始前に

python3 "$SKILL_DIR/scripts/agent_sync.py" status

べき等です。状態を調査・修復・報告し、check の判定とともに次に行うべきアクションを1つ示します。

両方の状況認識セクションを読んでください。

  • 現時点で、このプロジェクトに取り組んでいるほかの実行。 誰が何を保持しているかを、その時点で確認します。それらを引き継いだり、対象となるファイルを「ちょっと見るだけ」と開いたりしてはいけません。
  • 前回確認してからの新しい変更。 不在中に反映された、リポジトリ間の依存関係の変更です。実行ごとにウォーターマークが付くため、変更があるまで通知は静かなままです。依存関係の変更によって、計画していた作業のブロックが解除されることも、計画が無効になることもあります。

status は次の判断も行います。認証情報がない場合は縮退モードになります。task-pipeline が存在しない場合は、インストールコマンドを出力して停止します。存在確認は、すべてのホストレイアウト、または明示的に指定された pipelinePath を対象に行われます。いずれかのホストにあるコピーによって、存在確認が省略されたり、見落とされたりすることはありません。リースのコア(acquire/renew/release)に必要なのは、バインディングではなくバックエンドとリースです。

npx sshlg-skills install

コマンド

コマンド内容
init最初に実行します。 状態の保存場所を尋ね、設定と Git の追跡対象外となる環境変数ファイルを書き込み、オペレーターが行う手順を表示します
status状態を調査・修復して報告し、次のアクションを 1 つ提示します
bootstrapクラウドコンテナを作成し、環境変数ファイルに貼り付ける ID を表示します
acquire <KEY>タスク ID のリースを取得します。won または lost <holder> を表示します
renew <KEY>明示的にキープアライブします。フックは --active-only を使用するため、無関係な呼び出しによってリース期間が延長されることはありません
release <KEY>どの経路でもリースを返却します。released はリモート参照が削除されたことを意味します
release --heldこの実行が保持するすべてのリースを 1 つのプロセスで返却します。SessionEnd が実行する処理です
reserve <REG> [--key K] [--offline]レジスター(DEC、OQ、DEP など)で次の ID を予約し、表示します。--key を指定すると再試行が冪等になり(1 つのキーに 1 つの番号)、--offline を指定するとグローバルな権限を持たない名前空間付きの REG-o-… ID を発行します
map-offline <REG> <ID> <N>オフライン ID を正式に予約した番号に紐付けます。追記のみで、紐付けを変更することはありません
release-id <REG> <ID>Git に書き込まなかった ID を返却します
journal <text>この実行のジャーナルに 1 行追記します
record <text>実際に構築したものを追記します。--decision DEC-…、--files a,b を指定できます
reconcile意図(Git)と実際に構築したもの(クラウド)を照合します。プロジェクトごとに 1 回、--set-baseline を指定します
signal <DEP-ID> <state>依存関係の状態を記録します。依頼は行いません。Fabric を使う場合は、com.submit で依頼し、DEP にボード上のメッセージを記載します
guard <path>この実行でそのパスに書き込めるかどうかを判定します。終了コード 0 は許可、2 は不許可です
board共有ボードとこのリポジトリのページを再生成します。--mirror を指定すると、設定済みの Git ドキュメントも plane にレンダリングします
whoamiこの実行の ID と保持しているリースを表示します
residueディスク上の期限切れロックと、有効なリースがないクレームタグという、両方の plane に実行が残したものを表示します
reap [KEY…]この実行が所有し、使用済みであると証明できるものだけを消去し、ディレクトリを再読み込みして削除されたことを確認します
reap --long-expired両方の plane で 7 日以上前に期限切れとなったロックを、それぞれの判定結果とともに一覧表示します。--apply は経過時間だけを基準に消去します。これはオペレーターの判断であり、あなたが行うことではありません
setupエージェントが読めるように、このプロジェクトの構成を示す生成済みスナップショットを書き込みます
adopt既存のプロジェクトを調査し、設定を提案します。何も書き込みません
mergeこのブランチを取り込みます。何かに触れる前に競合を確認し、マージログを書き込み、プッシュ後に --key のリースを解放します。--summary、--dry-run、--push を指定できます
mergesこのブランチにいた間に取り込まれた内容を表示します。--all を指定すると、圧縮済みの履歴も含めます
checkセットアップ全体を最初から最後まで検証します。正常でない場合は 0 以外の終了コードを返します
scaffold [--full]不足しているものだけを作成し、既存の内容は一切変更しません。--full を指定すると、質問レジスター、インデックス、依存関係ボード、データモデル、ドキュメントゲートも作成します
finish [--gates]作業は完了していますか。すべてのリポジトリがクリーンで、プッシュ済みかつ参照先が設定され、保持中のものが残っていない状態です。プロジェクトが正しく構成されているかは check が確認し、完了しているかはこちらが確認します

アクティブな SKILL.md の場所から $SKILL_DIR を解決し、その絶対パスを再利用してください; ${CLAUDE_PLUGIN_ROOT}/skills/agent-sync は Claude によるテキスト置換であり、Bash 環境変数として保証されているわけではありません。

セッションごとに 1 つの ID、その決定方法

ID の優先順位(references/earned-rules.md):AGENT_SYNC_RUN_ID · CLAUDE_SESSION_ID · CLAUDE_CODE_SESSION_ID(すべての Claude Code の Bash 呼び出しに付与されます)· このシェルを 起動したセッション(SessionStart が .agent-sync/sessions/<CLI pid> に記録し、コマンドは プロセスの祖先をたどって特定します)· 共有 ID。共有 ID を使う場合はその旨を明言し、分離されているかのように 示すことはありません。

クレーム — 重要な仕組み

acquire → do the work → release

失敗した場合でもリリースしてください。放置されたリースがあると、TTL が切れるまでタスクがブロックされます。 PR の場合は、永続的な引き継ぎをプッシュしてからリリースしてください。references/branching.md を参照してください。 別のリポジトリで取得したリースもこのセッションに表示され、renew フックと SessionEnd フックもそこで動作します(AS-07)。

リースはクレームではありません。 リースが示すのは、現在誰が保持しているかとその有効期限です。永続的な クレームは git 内のタグで、acquire によって書き込まれ、release によってクリアされます。事実の 記録場所は一つだけにしてください。所有者を記録する第三の場所を作らないでください。

どちらのプレーンも、同じ「保持中」の定義を参照します。 TTL が切れるとリースは終了するため、リースが終了した 実行を示すタグは残存データです。status、residue、reconcile で報告され、 誰のものだったかを示す release <KEY> でクリアされます。リースがまだ有効なタグには、別の実行が決して触れません。

取得、期限切れ、横取り、ID 割り当てを変更する前に、references/lease-protocol.md を読んでください。

ガード対象ファイル

設定には、複数のエージェントが書き込むレジストリファイルが記載されています。編集する前に:

python3 "$SKILL_DIR/scripts/agent_sync.py" guard docs/DECISIONS.md

終了コード 2 が示すのは、この実行がリースを保持していないことです。他の誰かがそのファイルを保持しているという意味ではありません。 拒否メッセージには相手の実行とそのキーが含まれます。パスの横に「r-x がリースを保持している」とあると、 「r-x がこのファイルを保持している」と誤って伝わるためです。それでも編集したり、「一行だけ修正」したりしないでください。 判断を上書きすると、まったく同じ判断に見えてしまいます。

書き込みモードは二つです。 タスクのリースが許可するのはタスクであり、ファイルではありません。そのため、ガード対象への書き込みには ファイルのリソースクレーム(res--<repo>--<canonical path>、SY-04)も必要です。これは 短時間のトランザクションロックです。一つのレジストリでは排他制御されますが、独立したファイル同士は排他制御されません。 leaseBackend: "git" の場合に限り、マシンをまたいで有効です。大きな変更が重複する場合は、分離した worktree とマージを使用してください。 ガードが保証しないのは、単一のタスク所有者による強制です。

同梱の PreToolUse アダプターは、Edit/Write、git commit(同じコマンドでステージする内容を含む)、 および scripts/bash_writes.py で解析した Bash の書き込みについて、所有リポジトリ内でこの処理を実行します。 これはパーサーであり、サンドボックスではありません。検証済みのアダプターがない場合は、自分で実行してください。

ID の予約

「次の空き ID」の行を読むだけでは予約になりません。二つのエージェントが同じ番号を読み、両方が使ってしまいます。

python3 "$SKILL_DIR/scripts/agent_sync.py" reserve DEC   # → DEC-0216

割り当てはマージ済みログ全体(すべてのシャード。現在の実行分だけではありません)に対して順番に行われるため、 すべてのエージェントが同じ答えを計算します。予約した ID を git に書き込んでいない場合は、release-id してください。そうしないと、 番号が欠番となり、ボードで漏れとして報告されます。

ログは編集も削除もしません

ログは順番に再生されるため、編集すると、他のエージェントがすでに行動の根拠にした結論がひそかに書き換わります。 正しく修正するには、追記してください。リースをリリースし、未使用の ID は release-id で解放し、誤った as-built エントリーは後続のエントリーで置き換えます。 例外は生成ページのみです。ライフサイクルと生成オブジェクトの契約については、references/two-sources.md を参照してください。

二つのドキュメントソースと、整合させる責務

Git のドキュメントが示すのはあるべき姿であり、as-built レコードが示すのは実際の姿です。 どちらが優先されるわけでもなく、両者の隔たりこそが発見事項であり、欠陥ではありません。タスクの開始時と終了時の両方に責務があります。 開始前に reconcile を実行し、完了後に record と reconcile を実行してください。reconcile は機械的な処理であるため、 成功を一致とみなすと、差異が開始時にも終了時にも見過ごされます。

最初の reconcile の前に、references/two-sources.md を読んでください。そこには、責務の全容、 reconcile が判断しない内容、生成される setup スナップショット、ドキュメントの配置場所、削除しない理由が記載されています。

task-pipeline との連携

このスキルはステージを提供します。ステージ名は task-pipeline が定義するものです。 11 個のステージのうち五つに順序ルールがあります。0 brief をコミットする前に acquire、 1 コード着手前に reconcile、3 git に書き込む前に ID を reserve、 9 メインの書き込み、10 すべてのリースを merge/release。

pipeline.json を設定する際は、references/pipeline-binding.md を読んでください。ステージごとの理由、 skills[] エントリー、ガード対象、ゲート式が記載されています。

設定

2つのファイルがあり、その分離がセキュリティモデルのすべてです。

.claude/agent-sync.json — 構成。コミット対象です。使用するバックエンド、TTL、保護するファイル、存在するレジスター、実行するゲートを指定します。

.env.agent-sync — ID。init が作成し、パーミッションは 600 で、gitignore の対象です。ここ、スーパープロジェクト内、または AGENT_SYNC_ENV で見つかります。check はその場所を表示します。このツールはファイルを自ら読み込むため、source しないでください。notion トークンは Observatory vault(1.22.0)に保管してください。init は vault.py put の行を表示します。レコードプレーンのコマンドは use_secret.py run --vault-only で再実行され、ガードが vault に問い合わせることはありません。outline はファイル内にトークンを保持します。scheduledIntervalSeconds(60 以上):リースがそれより長く保持されると、警告が 1 回表示されます。

ホスト名やトークンを設定ファイル、テスト、例、コミットに書き込まないでください。トークンの値を扱ったり、エコーしたり、argv に渡したりしないでください。チャットでトークンを提示された場合は、代わりにそのファイルを指し示してください。

サブモジュールの設定には、そのサブモジュール自身のレジスターだけを記述します。 リポジトリをまたぐ事実は親に属します。親の意思決定レジスターを列挙するサービスリポジトリは、設定上の欠陥です。

必須事項

  • 追記して読み戻してから、操作します。調整ドキュメントを書き換えてはいけません。
  • agent-sync:generated マーカーのない生成オブジェクトは、上書きせず拒否します。人間が引き継いだためです。仕様については references/two-sources.md を参照してください。
  • 失敗時も含め、どの経路でも acquire したものは release します。
  • 実行結果では、後に残るものを報告します。期限切れになるのはリースであり、ファイルではありません。これを residue と呼びます。
  • 認証情報を argv、ログ行、リポジトリに渡してはいけません。
  • 劣化した状態は明示します。ungated は許容される状態ですが、強制されていると虚偽の主張をすることは許されません。
  • 同じチェックアウト内に2つのエージェントがいる場合、それぞれ別の ID が必要です。そうでなければリースは飾りにすぎません。
  • サブモジュールのコミットは、親がそのコミットを指すまで未完了です。finish を実行してください。
  • クラウドが永続的な事実について保持する情報はすべて、git へのリンクであり、代替物ではありません。
  • 境界は .claude/agent-sync.json です。設定がない場合、またはエージェントが1つだけの場合は、別の経路に回してください。オペレーターによる免除:「調整なし」/«без координации»。

トリガー

説明の文言に加えて、「このタスクを取得して」「誰が取り組んでいるか」「エージェントの調整を設定して」/«настрой координацию агентов»、「サブモジュールをプッシュした」/«сабмодуль запушен»、「親が古いコミットを参照している」/«родитель на старом коммите»。

参照資料

各ファイルは、対応するトリガーが発生したときにのみ読み込みます。デフォルトでは読み込みません。

ファイル読むタイミング
references/adapter-contract.mdナレッジバックエンドを追加または監査するとき — 6つのプリミティブ、機能フラグ、正直な劣化経路について
references/lease-protocol.md取得、期限切れ、強制解放、ID 割り当てを変更するとき
references/backend-outline.mdOutline API を呼び出すとき、またはその呼び出しをデバッグするとき
references/backend-notion.mdNotion API を呼び出すとき、またはその呼び出しをデバッグするとき
references/backend-fs.mdクラウドバックエンドなしで実行するとき、または劣化モードを説明するとき
references/pipeline-binding.mdpipeline.json を接続するとき、またはステージフックを追加するとき
references/hooks.mdClaude Code フックをインストール、デバッグ、削除するとき
references/two-sources.md最初の reconcile の前、ドキュメントの配置先を決めるとき、または生成オブジェクトを書くとき
references/roadmap.mdclaimTags の設定、タスクの取得または完了、ボードの再計画を行うとき
references/branching.mdコミットを作成する作業の開始、ブランチのマージ、または不在中に取り込まれた変更を確認するとき
references/earned-rules.mdID がそのように解決される理由、または finish が存在する理由を尋ねるとき
references/fabric-coordination.mdFabric の調整契約、または reap --long-expired を使うとき

references/ がない場合は、https://raw.githubusercontent.com/ssheleg/agent-sync/main/plugins/agent-sync/skills/agent-sync/references/<file> から取得してください。

コメント