目的
wiki sync は docs/ をローカルクローンから読むが、そのクローンが upstream に対して最新であることを確認する手順が経路上に無い。古いクローンから sync すると、マージ済みの docs 変更が wiki 側で静かに巻き戻る。
観測事実(2026-08-24、v1.19.17 リリース時の実測)
release + wiki sync を委譲した subagent が、C:/Users/smile/Code/liplus-language を detached HEAD 8dd8d92、origin/main から5コミット遅れの状態で発見した。作業ツリーは clean、stash 無し、余分な worktree 無し。8dd8d92 が origin/main の祖先であることを確認したうえで main を checkout して fast-forward し、そのうえで sync を実行している。
捕まえたのは手順ではなく、その agent がクローンの状態を先に確認したからである。 確認せずに sync していれば、wiki は5コミット前の docs/ ツリーからミラーされ、当日マージした3本(#1799 / #1801 / #1802)の docs 変更が wiki 上で巻き戻っていた。
この巻き戻しが既存の防御を素通りする理由
skills/operations-on-wiki-sync/SKILL.md の pre-push assertion は3つとも通ってしまう。
| assertion |
古いクローンでの挙動 |
| status check |
通る。全エントリが M で、名前は docs/ に存在する。内容が古いだけで、削除も未追跡も出ない |
| sidebar integrity |
通る。ページ集合は変わらないため slug の数も参照も一致する |
| cross-reference integrity |
通る。古い本文どうしで参照は閉じている |
unclassified も空のままである。ページは wiki と docs/ の両側に在り、所有は location で決まるため、内容が古いことは分類に現れない。したがって #1720 が入れた STOP 経路にも掛からない。
3つの assertion はいずれも所有と参照解決を測っており、source ツリーが最新かどうかは測っていない。軸が違う。
前提
docs/ が正本、wiki はミラー(rules/operations/operations.md Operations Rules)。したがって巻き戻りの方向は「正本は無事、ミラーだけが古くなる」であり、git revert 範囲の内側で復旧できる。破壊の深刻度としては中位。
- ただし検出されない。次の sync が新しいクローンから走れば黙って直るため、その間 wiki を読んだ人間・RAG 索引・Discussions bot は古い記述を正本として読む。github-rag-mcp は wiki を索引しているので、RAG の回答にも入る。
- 本ワークスペースのクローンが detached HEAD で放置されていたのは、tag ベースの Li+ 同期(
LI_PLUS_CHANNEL=tag)の副作用と読める。異常な状態ではなく、通常運用で到達する状態である点が重要。
論点
どこで測るか。
- sync 手順の先頭に freshness assertion を足す ——
git fetch 後、docs/ を読むクローンの HEAD が origin/main を含んでいることを確認し、含んでいなければ STOP。既存3 assertion と同じ場所・同じ形で並べられる。
- クローンを読まず、リリースタグから直接取る ——
git archive / gh api contents?ref=<tag> でリリース対象 tag の docs/ を取得する。そもそもローカル状態に依存しなくなるため、assertion を足す必要が無い。rules/model/subtractive-structural-beauty.md の「手続きではなく構造へ置き換える」に近いのはこちら。
- 両方(tag から取得しつつ、取得元 tag がリリース対象と一致することを assert)。
方向2には検討すべき点がある。sync が mirror する対象は「リリースされた tag の docs」なのか「現在の main の docs」なのか。本 run では両者が一致していた(tag == origin/main)が、一致しない場合の正解は未確定であり、先に決める必要がある。
変更予定ファイル(方向未確定のため暫定)
skills/operations-on-wiki-sync/SKILL.md —— 手順と assertion
docs/4.-Operations.md —— 対応するミラー記述があれば追従
tests/ —— 古い source ツリーからの sync が STOP することの契約テスト
目的
wiki sync は
docs/をローカルクローンから読むが、そのクローンが upstream に対して最新であることを確認する手順が経路上に無い。古いクローンから sync すると、マージ済みの docs 変更が wiki 側で静かに巻き戻る。観測事実(2026-08-24、v1.19.17 リリース時の実測)
release + wiki sync を委譲した subagent が、
C:/Users/smile/Code/liplus-languageを detached HEAD8dd8d92、origin/mainから5コミット遅れの状態で発見した。作業ツリーは clean、stash 無し、余分な worktree 無し。8dd8d92がorigin/mainの祖先であることを確認したうえでmainを checkout して fast-forward し、そのうえで sync を実行している。捕まえたのは手順ではなく、その agent がクローンの状態を先に確認したからである。 確認せずに sync していれば、wiki は5コミット前の
docs/ツリーからミラーされ、当日マージした3本(#1799 / #1801 / #1802)の docs 変更が wiki 上で巻き戻っていた。この巻き戻しが既存の防御を素通りする理由
skills/operations-on-wiki-sync/SKILL.mdの pre-push assertion は3つとも通ってしまう。Mで、名前はdocs/に存在する。内容が古いだけで、削除も未追跡も出ないunclassifiedも空のままである。ページは wiki とdocs/の両側に在り、所有は location で決まるため、内容が古いことは分類に現れない。したがって #1720 が入れた STOP 経路にも掛からない。3つの assertion はいずれも所有と参照解決を測っており、source ツリーが最新かどうかは測っていない。軸が違う。
前提
docs/が正本、wiki はミラー(rules/operations/operations.mdOperations Rules)。したがって巻き戻りの方向は「正本は無事、ミラーだけが古くなる」であり、git revert 範囲の内側で復旧できる。破壊の深刻度としては中位。LI_PLUS_CHANNEL=tag)の副作用と読める。異常な状態ではなく、通常運用で到達する状態である点が重要。論点
どこで測るか。
git fetch後、docs/を読むクローンの HEAD がorigin/mainを含んでいることを確認し、含んでいなければ STOP。既存3 assertion と同じ場所・同じ形で並べられる。git archive/gh api contents?ref=<tag>でリリース対象 tag のdocs/を取得する。そもそもローカル状態に依存しなくなるため、assertion を足す必要が無い。rules/model/subtractive-structural-beauty.mdの「手続きではなく構造へ置き換える」に近いのはこちら。方向2には検討すべき点がある。sync が mirror する対象は「リリースされた tag の docs」なのか「現在の main の docs」なのか。本 run では両者が一致していた(tag ==
origin/main)が、一致しない場合の正解は未確定であり、先に決める必要がある。変更予定ファイル(方向未確定のため暫定)
skills/operations-on-wiki-sync/SKILL.md—— 手順と assertiondocs/4.-Operations.md—— 対応するミラー記述があれば追従tests/—— 古い source ツリーからの sync が STOP することの契約テスト