SKILL.md
embed-cli の制約
conflict の状態モデル(共通)
以下の各制約(symlink / バイナリ / 不正パス)と通常のテキスト conflict は、同じ状態モデルで動く。pull の挙動を誤解すると無限ループに入るため先に把握する。
- pull は実行のたびに
.embed/base/(前回適用したサーバー内容)+ ローカル + サーバーで 3-way merge を やり直す。衝突ファイルの base は解決まで前進せず、旧 base が次回の再マージ基準として据え置かれる。 - そのため、ローカルがサーバーと衝突する変更を残したまま再 pull しても 同じ衝突が再生成される。収束には衝突を実際に解消する(テキストなら衝突領域をサーバーに揃える、symlink/バイナリ/不正パスならローカル版かサーバー版を手で選ぶ)必要がある。
- 衝突状態はファイル内容とは別に
.embed/state.jsonのpendingPullConflicts(未解決衝突ファイル一覧)でも管理される。pushはこれが残っている限り拒否する。クリアされる(フィールド自体が外れる。空配列ではなくキー省略で表現される)のは 衝突ゼロの pull が完走したときだけ。 .embed/state.json(version + files の全同期透かし)とpendingPullConflictsは、衝突ゼロ pull まで更新されない。これは「中途半端な state が蓄積しない=再試行が安全」を意味するが、安全 ≠ 収束。解決方法が誤っていれば何度 pull しても進まない。
symlink
未サポート。理由: サーバー側のストレージが symlink のメタ情報を保持できないため、push/pull のラウンドトリップで symlink が消えてしまう。
挙動:
pushは warning を出して symlink をスキップするpullは symlink を書き出そうとするパスを conflict 扱いにし、解消されるまで state/base を更新しない
回復手順: symlink を実ファイルに置き換える(または削除する)、そのあと pull を再実行する。symlink を解消しない限り再 pull しても conflict は再生成される(「conflict の状態モデル」参照)。
将来対応: サーバーが symlink のメタ情報を保持できるようになった時点で対応予定。CLI 側は pull で symlink エントリをディスクに書き戻し、push で tar に含めるよう拡張する。
バイナリファイル
3-way merge エンジンは UTF-8 としてデコードする。UTF-8 でないバイトが含まれると Utf8DecodeError になる。バイナリファイルに conflict が起きた場合は自動 merge できない。
回復手順: ローカル版かサーバー版を手で選び、その後 pull/push を再実行する。どちらかに揃えない限り再 pull で conflict は再生成される(「conflict の状態モデル」参照)。
不正パス(unsafe paths)
isUnsafePath が reject する対象:
- ターゲットのファイル自体が通常ファイルでない(symlink、デバイスファイル、fifo 等)
- 親ディレクトリのいずれかが symlink
目的: パストラバーサルの防止とサーバーストレージとの非互換回避。
pull 時は不正パスも conflict 扱いで state/base の更新をブロックする(symlink と同じ回復パターン)。push 時はログに記録してスキップする。