Skip to content

v0.14.0 — 同じファイルでも競合しない

Choose a tag to compare

@tacyan tacyan released this 10 Aug 19:10
· 159 commits to main since this release
79fe8c5

「同じファイルでも、違う行なら 2 人が同時に書ける」 — 並列エージェント開発の天井を、ファイル単位の所有から行域単位へ引き上げました。

1 ファイルに 64 体をぶつけた実測

tools/coedit-bench.sh --agents 64 --lines 2000(2000 行のファイル 1 個に 64 体が同時に書き込む):

守り方 書けた担当 断られた 衝突した枝 衝突行 人の手
守らない(素の git) 64 0 48 960 48
ファイル単位で持つ(〜v0.13) 1 63 0 0 0
行の単位で持つ 11 53 0 0 0
行の単位 + 交渉(v0.14) 64 0 0 0 0

誇張せずに言うと: 衝突ゼロ自体は v0.13 でも達成できていました。v0.14 が買うのは並列度です(64 体中 1 体しか書けなかったのが、全員書けるようになりました)。素の git は詰めた条件でも 64 体全部が書けますが、48 枝が衝突して 960 行・48 回の手作業を要します。

どのリポジトリでも 1 コマンド

$ zai czero init      # 台帳・git フック・マージドライバ・.gitattributes を一度に入れて自己診断
$ zai czero verify    # 使い捨ての一時リポジトリで実際に競合を起こし、本当に止まるか実演する
$ zai czero uninstall # 入れたものだけを綺麗に戻す

verify は設定を読むだけではありません。実際に競合を起こして止まることを実演します(対象リポジトリは 1 バイトも汚しません)。「入れたのに効いていない」が構造的に起こらないようにするためです。

変更点

  • 断られる代わりに、近くの空いている行へ自動でずらすようになりましたzai lease claim --shift)。1 ファイルへ 64 体をぶつける検証で、断られた件数が 53 件 → 0 件、書けた担当が 11 → 64 になります。マージ衝突は 0 件・人の手も 0 回のままです。ずらされた場合は「要求 → 実際に取れた場所」を必ず表示します(黙って別の場所を渡しません)
  • 「ここに足す」だけの予約ができるようになりましたsrc/a.rs#@120)。関数や use を足す作業は既存の行を 1 行も必要としないので、幅 0 で予約します。300 行のファイルに 64 体が全員入ります
  • 同じファイルでも、違う行なら 2 人が同時に書けるようになりました。これまでは「誰かが持っているファイルには書けない」でした。1 ファイルへ 64 体をぶつける検証で、ファイル単位の所有だと書けたのは 64 体中 1 体(63 体は拒否)でしたが、行域なら64 体全部が書けてマージ衝突は 0 件・人の手も 0 回です。zai lease claim 'src/app.rs#L1200-1260' のように行を指定して確保します
  • エージェント同士が裏で認識し合うようになりました。Erlang のプロセスと同じ仕組みで、それぞれが身元(再起動したら別物として扱われる ID)とメールボックスを持ち、互いを監視します。担当を持ったまま落ちたエージェントの担当は自動で解放されるので、人が掃除する必要がありません
  • 断られる代わりに「ずらす」ようになりました。要求した行域が埋まっていても、近くの空いている行域を提案して振り替えます。ただし**「ずらしてよい」と言った要求だけ**です — 行域は行番号ではなく「そこにある内容」に紐づくので、黙ってずらすと別の場所を編集させることになります
  • 「いま統合したら一撃で通るか」を証明できるようになりました。複数ブランチの変更行域が離れていれば、git merge は必ず衝突しません。実際の git で網羅的に確かめて見逃し 0 件です。証明が立てば N 本を人手ゼロで統合します。作業ツリーを一度も触らず、最後に参照を 1 回だけ動かすので、途中で失敗しても中途半端な状態が残りません
  • どのリポジトリでも、一覧への追記が衝突しなくなりました.gitignoreCHANGELOG.mdpackage.json の依存・import 宣言のような「両方の行を残すだけ」の衝突を、中身を見て自動で判定して解決します。目印を書く必要はありません。マーカ無しの検証で人が読む衝突行が 80% 減り、誤って自動解決した件数は 0 です。一覧と判断できないファイルでは素の git と 1 バイトも変わりません
  • 誰がどのファイルの何行目を持っているかが 1 画面で分かるようになりました。同じファイルを複数人が持っている状態を横帯で見せ、近すぎる組だけを赤枠にして「あと何行空ければ一撃で通るか」を出します
  • 64 体以上で確保が「混雑しています」と断られることがあるのを直しました。待ち時間の予算が固定だったため、体数が増えると必ず足りなくなっていました。台数に依存しない待ち方へ変えています
  • 行域を指定すると保護が効かなくなる不具合を直しました。誰かがファイル全体を持っていても、行を指定した確保が通ってしまい、重なる 2 つの行域も両方通っていました
  • 全文置換で他人の担当を黙って消せる不具合を直しました。200 行のファイルを 2 行に置き換えると「触れたのは 1〜2 行目」と判定され、他の行の持ち主を巻き込んでいました
  • これから書く場所を予約すると、その予約が消えて別人に取られる不具合を直しました。まだ短いファイルへ「1〜10 行目」を確保しても、実際には 1 行目しか押さえられておらず、重なる「5〜15 行目」が通っていました
  • エージェントが行を上に足すと、下にいる担当の位置がずれる問題を直しました。担当は行番号ではなく「そこにある内容」で覚えるようになったので、他の人が上に 10 行足しても同じ場所を指し続けます
  • どのリポジトリでも 1 コマンドで導入できるようになりました。zai czero init で台帳・git フック・マージドライバ・.gitattributes が一度に入り、入れた直後に自己診断まで走りますzai czero doctor は段ごとに理由と直し方を出し、zai czero verify使い捨ての一時リポジトリで実際に競合を起こして、本当に止まるかを実演します。zai czero uninstall で入れたものだけを綺麗に戻します(他人が書いた .gitattributes の行や既存のフックは無傷です)
  • 離れた行を担当する 2 人が、どちらもコミットできなかったのを直しました。コミット前の点検が行番号を見ておらず、同じファイルというだけで両方止めていました。あわせて点検を 685 倍速くしています(400 ファイル × 200 担当で 5.04 秒 → 7.4 ミリ秒)
  • 統合の順番決めが、24 体を超えると裏目に出ていたのを直しました。「手が止まるまでに自動で入る本数」が 2 → 1 に減っていました。24 体で 1 本 → 10 本、32 体で 1 本 → 11 本になります。ただし衝突の総数は変わりません — 減るのは手が止まる回数だけです
  • 互いに干渉しないブランチなら、順番を決めずに一撃で統合できるようになりました。24 本が互いに素なら「順序は不要」と出して、そのまま人手 0 回で入ります

数字と線引き(効かない条件も含めて)は docs/conflict-zero.md にあります。

検証: 全テスト 4273 件緑(6 回連続)/ clippy 緑 / macOS・Linux・Windows の CI 8 ジョブ全通過。