workspace clone identity resolved by remote - Liplus-Project/liplus-language GitHub Wiki
ワークスペースのクローン同一性は remote で解決する
Question
Li+update Phase 5 は、USER_REPO<N> の entry に対して「クローンが既に在るか」をどう判定するか。
Current resolution
remote で照合する。 clone 前に workspace 直下1階層の各ディレクトリの origin を読み、対象 URL を追跡するクローンが在ればそのパスを working directory として採用し、clone をスキップする。URL 比較は Phase 2.5 の canonical comparison form(git+ssh → HTTPS、末尾 .git / / の除去、host / owner / repo の大小無視)を単一の正本として使い、Phase 5 は独自の正規化規則を持たない。
判定が一意に定まらない入力は STOP して人間へ報告する(3分岐)。
| 入力 | 帰結 |
|---|---|
| 一致1件 | そのパスを採用、clone しない |
| 一致無し・導出名ディレクトリ無し | git clone |
| 一致1件・導出名ディレクトリが別に在る | STOP |
| 一致無し・導出名ディレクトリが在る | STOP(origin が対象を追跡していない、または読めない) |
| 一致2件以上 | STOP |
STOP した entry は未準備のまま残し、他の entry は続行し、Phase 6 の完了報告に載せる。
Edges
distributed-source-carries-no-resolved-config-valueに relates to —— 同 entry は「解決値を配布面へ書かない」軸、本判断は「解決を名前ではなく実体で行う」軸。どちらもLi+config.mdの記述を実態の代理として扱わない方向に働く。
Background
判定が「ローカルディレクトリの有無」だけを見ており、同じ remote を別名のディレクトリが既に追跡している場合を検出できなかった。旧 literal は導出名のディレクトリが在れば present -> skip clone で黙って通し、無ければ clone する。
2026-08-25 の bootstrap 実行で顕在化した。USER_REPO5 = pullcept に対し、workspace には liplus-chat/ が pullcept.git を追跡した状態で存在していた(2026-08-23 のリポジトリ改名にディレクトリ名が追従していなかった)。判定は名前でしか見ないため「absent」と読み、2つ目のクローンを作る直前まで進んだ。その回は停止して #1807 を起票している。
特殊な壊れ方ではない。 リポジトリを改名すれば必ずこの状態になるため、通常運用で到達する。
Constraints
- 被害は重複クローンそのものより、その後の曖昧さにある。以降のセッションは導出名と一致する新クローンを「正しい方」と読みやすく、dev server を起動したまま実機確認する運用では、実機へ反映されない側へ作業が流れる。git の状態としては壊れていないため CI もテストも何も言わない。
- 走査対象は workspace 直下1階層のみ。再帰せず、
.gitを持たないディレクトリと origin が読めないディレクトリは「origin 無し」として一致しない扱い。 - 比較と導出は別の軸。canonical comparison form の大小無視は比較の規則であり、ディレクトリ名の導出には適用しない(導出は大小を保存する必要がある)。この区別により、Phase 3.2 が LI_PLUS_REPO のクローン有無判定で正規化 HTTPS 形を参照していることは本判断と衝突しない。
Conclusion
採用しなかった案は2つ。
USER_REPO<N>_PATH=を config の任意キーとして許す —— 明示的だが entry ごとに人手が要り、改名のたびに人間の更新を要求する。一般形を塞がない。- 検出のみ(Phase 6 の完了報告で不一致を surface する) —— 是正しないため「どちらが作業ツリーか」の曖昧さが残る。これは被害の本体そのもの。
remote 照合は config 変更を要さず、改名という通常運用のトリガーを一般形で塞ぐ点で最小。
STOP を3分岐置いたのは、走査が件数を返すものである以上、その出力に対して分岐集合が全域でなければ黙って一方を採る挙動が残るため。どちらを working tree とするかは Li+ が決めてよい判断ではない。