作業ツリーが汚れた端末にだけ配布が届かない — フォールバックの自家中毒まで含めて塞ぐ
複数端末へgit pullでツールを配る運用で、開発端末にだけ配布が永久に届かない障害。フォールバックの発動条件・人の作業の保護・自分の出力を人の編集と誤認して凍結する二次不具合・自己修復の循環・定期タスクの参照先ずれまで、実際に踏んで直した手順とチェックリスト。
約4.1万トークンの節約 (API料金換算で約62円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。
この巻物について
「作業ツリーが汚れた端末にだけ配布が届かない — フォールバックの自家中毒まで含めて塞ぐ」は、開発プロセスカテゴリのAI指示書(MDファイル)です。複数端末へgit pullでツールを配る運用で、開発端末にだけ配布が永久に届かない障害。フォールバックの発動条件・人の作業の保護・自分の出力を人の編集と誤認して凍結する二次不具合・自己修復の循環・定期タスクの参照先ずれまで、実際に踏んで直した手順とチェックリスト。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約4.1万トークン(API料金換算で約62円)・91%のトークンを節約できます。
- カテゴリ
- 開発プロセス
- 対応AI
- claude-code、cursor、codex-cli
- ライセンス
- 商用利用可 (再販不可)
- 価格
- 無料
- ゼロから開発時
- 約4.5万トークン
- この巻物使用時
- 約4,000トークン
- 節約量
- 約4.1万トークン (約62円)
- 更新日
- 2026-08-30
使い方 (AIに渡す3つの方法)
いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。
claude "https://makimono-md.vercel.app/api/v1/files/md-40f34f0d/raw を読み込んで、この指示書どおりに実装して"
中身
作業ツリーが汚れた端末にだけ配布が届かない — フォールバックの自家中毒まで含めて塞ぐ
複数端末へ git pull でツール群を配る運用で、開発に使っている端末にだけ配布が永久に届かない型の障害。
新規端末でも、きれいな端末でも再現しないため気付けない。さらに素朴に直すと
「1回目は直るが2回目から凍結する」二次不具合を作り込む。実際に踏んで直した記録。
対象は、配布インストーラ/セッション開始フック/定期実行タスクで複数端末に同じツールを配っている運用者と、 その作業を代行する AI。
1. 症状
- 新規端末・きれいな端末では新機能が動く
- 開発に使っている端末(未コミットの変更がある/ブランチが分岐している)にだけ届かない
- 同期処理のログには「スキル配布 完了」「フック登録 完了」「設定ファイル更新」と成功が並ぶ
- テストは全部 green、CI も緑
- 誰もエラーを見ていない(=静かに何も起きない)
2. 原因の型(3つ)
2-1. フォールバックの発動条件が「リポジトリが無いこと」になっている
よくある実装:
if (fs.existsSync(path.join(repoPath, '.git'))) {
execFileSync('git', ['-C', repoPath, 'pull', '--ff-only']); // ← 失敗しうる
} else {
// アーカイブを落として tools/ を上書きコピー(フォールバック)
}
// ↑ 全体が try{}catch{} で囲まれ、失敗はログ1行で握り潰される
.git が在るのに pull が失敗する端末(作業ツリーが汚れている/分岐している)では、
フォールバックへ行かない。catch が飲むので tools/ は永久に古いまま。
正しい条件は「リポジトリが無いこと」ではなく「取得できなかったこと」。
2-2. フォールバックが人の作業を消す/消さないために何もしない
アーカイブ展開はたいてい リポジトリごと削除 → 展開物を移動 で実装される。
未コミットの作業を守るためこれを避けると、結局「汚れた端末を直す経路が一つも無い」状態になる。
解: リポジトリは削除せず、配布対象ディレクトリのファイルだけを上書きし、
git status --porcelain -z --untracked-files=all に出たパスは除外する。
// rename/copy は次の NUL 要素が旧パス。新旧どちらも除外する
function parsePorcelainZ(output) {
const entries = String(output).split('\0');
const changed = new Set();
for (let i = 0; i < entries.length; i++) {
const e = entries[i]; if (!e) continue;
const status = e.slice(0, 2);
changed.add(e.slice(3).replaceAll('\\', '/'));
if (/[RC]/.test(status) && entries[i + 1]) changed.add(entries[++i].replaceAll('\\', '/'));
}
return changed;
}
status が取得できないときは1ファイルも書かずに終える。
黙って人の作業を消すより、届かないほうが安全。
2-3.(本丸)フォールバックが自分の出力を「人の変更」と誤認して凍結する
2-2 を実装すると1回目は正しく直る。2回目で壊れる。
フォールバックが書いたファイルは、その端末の git から見ると「変更あり」または「未追跡」になる (HEAD は古いコミットのままなので)。次回の実行は自分が前回書いたファイルを保護対象と誤認し、 除外リストが膨張してその版で永久に凍結する。
実測: 1回目の除外 2 件 → 2回目 55 件。届かないより質が悪い。 「更新できている」と表示されたまま古いまま止まる。
解: 書き込んだ内容のハッシュを記録し、自分の出力と人の編集を区別する。
// 記録: { files: { "<リポジトリ相対パス>": "<sha256>" }, updatedAt: "<ISO>" }
for (const rel of changedPaths) {
const abs = path.join(repo, ...rel.split('/'));
if (prev?.files?.[rel] && fs.existsSync(abs) && sha256(abs) === prev.files[rel]) {
selfOutput.add(rel); // 前回の自分の出力 → 更新してよい
} else {
protectedPaths.add(rel); // 人がそのあと編集した → 保護する
}
}
記録が読めない・壊れている場合は全部保護に倒す。
3. 自己修復には循環がある
配布を直す道具そのもの(同期スクリプト)が、更新できない端末には届かない。 リポジトリ内のツールで自己修復させようとすると必ず詰む。
循環を破れるのは「毎回リモートから取り直される要素」だけ=インストーラ、 または人が外から1ファイルだけ持ち込む操作。
そのためインストーラ側にも同じ修復ロジックを入れること。 インストーラだけは配布のたびに最新が取得されるので、唯一の救出経路になる。
応急処置(1回だけ・以後は自動化に戻る):
# 同期スクリプト1本だけをリモートから上書きしてから走らせる
<remote-raw>/tools/sync.mjs → <repo>/tools/sync.mjs
node <repo>/tools/sync.mjs --force
依存モジュールを解決させるため、リポジトリ内の元の位置に置いてから実行する (1本だけ別の場所に置いて実行すると import が連鎖的に落ちる)。
4. 定期タスクが見ているのは本当にそのリポジトリか
見落としやすい前提。同じリポジトリのチェックアウトが2箇所あることがある。
実例: 同期処理の対象は <home>/<repo> にハードコードされているのに、
定期実行タスクは <home>/Downloads/<repo> を指していた。後者は誰も更新しない。
結果、呼び出し側のスクリプトには新しい処理が入っているのに、
そこから呼ぶツールが存在せず「ファイルなし」で毎晩無言で空振りしていた。
# 定期タスクが実際に叩くパスを読む。~/ だと決めつけない
(Get-ScheduledTask -TaskName '<TaskName>').Actions | % { $_.Arguments }
5. 失敗を必ず1行で出す
握り潰しをやめ、3値を必ず出力する。
tools を更新しました (git pull)
pull できないためアーカイブで更新しました (理由: …) / 人の変更を保護: n件 / 前回の自分の出力なので更新: m件
⚠ tools を更新できませんでした (理由: …)。この端末は配布が届いていません
「スキル配布 完了」だけが並ぶログは、配布本体が死んでいても成功に見える。
6. 検証のしかた(ここを省くと必ず取り逃す)
きれいな端末だけで確認して終わらせない。
- 汚れた作業ツリーを実際に作る — 古いコミットへ移動し、追跡ファイルを1つ改変、未追跡ファイルを1つ作る
- 2回連続で実行する — 1回目だけの確認では 2-3 の自家中毒を取り逃す
- 毎回この4点をアサートする
- 配布物が届いたか
- 改変した追跡ファイルと未追跡ファイルが両方とも無傷か
- 除外件数が2回目に膨張していないか
- リポジトリ(
.git)が消えていないか
- 自分が書いたファイルを人が編集した場合に保護へ再分類されるかも確認する
7. チェックリスト
- フォールバックの条件は「リポジトリが無い」ではなく「取得できなかった」になっているか
- フォールバックはリポジトリを削除していないか
- 変更中・未追跡ファイルを除外しているか(rename の旧パスも)
- 書き込んだ内容のハッシュを記録し、自分の出力と人の編集を区別しているか
- 状態が取得できないとき、1ファイルも書かずに終えているか
- インストーラ側にも同じ修復ロジックが入っているか(循環を破る唯一の経路)
- 定期タスクが見ているパスを実際に読んだか
- 成功・フォールバック・全滅の3値を必ず1行で出しているか
- 汚れた作業ツリーで2回連続実行して検証したか
よくある質問
+「作業ツリーが汚れた端末にだけ配布が届かない — フォールバックの自家中毒まで含めて塞ぐ」とは何ですか?
複数端末へgit pullでツールを配る運用で、開発端末にだけ配布が永久に届かない障害。フォールバックの発動条件・人の作業の保護・自分の出力を人の編集と誤認して凍結する二次不具合・自己修復の循環・定期タスクの参照先ずれまで、実際に踏んで直した手順とチェックリスト。
+どれくらいトークン(費用)を節約できますか?
ゼロから開発すると約4.5万トークンかかりますが、この巻物を使えば約4,000トークンで済みます。差し引き約4.1万トークン(API料金換算で約62円)・91%の節約です。
+どうやって使いますか?
無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。
+どのAIツールに対応していますか?
claude-code、cursor、codex-cli に対応しています。
+商用利用できますか?
ライセンスは「商用利用可 (再販不可)」です。
🤝 自分でAIを動かすのは、まだ不安…という方へ
この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。
関連する巻物
ドキュメント駆動開発プロセス CLAUDE.md — 作るものを固めてから書かせる
「AIが暴走して意図と違うものを作る」を根絶する開発プロセス指示書。UI仕様→機能設計→実装の順をAIに強制し、1ファイルごとに承認ゲートを挟む。受託開発・チーム開発向け。
AIに指示書マーケットを自動参照させ、終了時に自動出品させるMD
開発依頼を受けた瞬間にマーケットの完成済み指示書を検索してAIに読ませ、セッション終了時には汎用ノウハウを自動出品させる仕組みの作り方。全台配布・秘密情報スキャン・実際に踏んだ配布バグ3つの回避込み。
「そのPCにしか直せない障害」をAIに自分で気付かせて着手させる
特定の1台にしかリポジトリが無い機能は、修正手順を書いても誰にも実行されず放置される。SessionStart hook で当該PCのAIだけに指示を出し、完了後は指示書へ状態を書き戻して再実装事故を防ぐ型。走査の時間予算とセッション跨ぎの再開、メール一致だけの自動承認がなりすまされる理由と署名キー方式、状態問い合わせAPI、鍵の自動配布、no-op通知の抑止まで、実際に94件の滞留を解消した実例に基づく手順。
この巻物、誰かのトークンも救えます
𝕏 で節約レシートをシェア