マキモノ
開発プロセス無料✅ 公式検証済みv1.0.0 / 更新

同期で巻き戻る設定を「固定時刻の貼り直し」で守ろうとして失敗する — 状態の検出で駆動する収束に変える

配布物の同期で上書きされる設定にパッチを当て続けたい時、同期の直後の時刻に貼り直しジョブを置くと失敗する。上書き側がN時間ガードで発火するため壁時計時刻が毎日漂うから。時刻でなく「当たっているか」で駆動する収束への作り替え方、no-opを無音・exit0にする理由、本番を触らず対照群で検定する手順、cmdのexit=行が消える罠まで。

出品者: seisaku-team@orgiast.jp📖 読込 約3,138トークン (約5円)💰 コスパ 11倍
トークン節約メーター79%節約
ゼロからAIに作らせた場合約4.2万トークン
このMDを読ませた場合約9,000トークン

約3.3万トークンの節約 (API料金換算で約50円分)。 要件定義・技術調査・試行錯誤ぶんのトークンがまるごと不要になります。※ 出品者申告とレビューに基づく推定値。モデル・タスク内容により変動します。

この巻物について

「同期で巻き戻る設定を「固定時刻の貼り直し」で守ろうとして失敗する — 状態の検出で駆動する収束に変える」は、開発プロセスカテゴリのAI指示書(MDファイル)です。配布物の同期で上書きされる設定にパッチを当て続けたい時、同期の直後の時刻に貼り直しジョブを置くと失敗する。上書き側がN時間ガードで発火するため壁時計時刻が毎日漂うから。時刻でなく「当たっているか」で駆動する収束への作り替え方、no-opを無音・exit0にする理由、本番を触らず対照群で検定する手順、cmdのexit=行が消える罠まで。この巻物をAIに読み込ませると、ゼロから設計・調査する場合に比べて 約3.3万トークン(API料金換算で約50円)・79%のトークンを節約できます。

カテゴリ
開発プロセス
対応AI
claude-code、cursor、codex-cli
ライセンス
商用利用可 (再販不可)
価格
無料
ゼロから開発時
約4.2万トークン
この巻物使用時
約9,000トークン
節約量
約3.3万トークン (約50円)
更新日
2026-09-24

使い方 (AIに渡す3つの方法)

いちばん簡単なのはワンライナー。Claude Code のターミナルに貼るだけです。

⬇ .md をダウンロード
claude "https://makimono-md.vercel.app/api/v1/files/md-1238f442/raw を読み込んで、この指示書どおりに実装して"
claude-codecursorcodex-cliライセンス: 商用利用可 (再販不可)

中身

同期で巻き戻る設定を「固定時刻の貼り直し」で守ろうとして失敗する — 状態の検出で駆動する収束に変える

配布物(zip / パッケージ / 設定の同期)で上書きされるディレクトリに、自前のパッチを当て続けたい。 定番の対処は「同期の直後の時刻に貼り直しジョブを置く」。これは高い確率で失敗する。 本書はその診断手順と、時刻に依存しない直し方、そして直したことを検定する方法を示す。

症状

  • 貼り直しジョブはログ上は成功している(「適用済み」と出る)。
  • なのに、ある時刻を境にパッチが消えている。
  • 貼り直しの時刻をずらしても再発する。

1. まず「上書きする側」を特定して、発火の契機と頻度を測る

「いつ走るか」ではなく 「何をきっかけに走るか」 を測る。ここを飛ばすと、ずっと時刻を動かし続けることになる。

# 配布ディレクトリの実ファイルが最後に書かれた時刻
ls -la --time-style=full-iso <配布ディレクトリ>/<対象ファイル>

# 定時ジョブの一覧と最終実行(Windows。cron なら crontab -l と実行ログ)
# 名前・トリガ・最終実行・終了コードを一覧化する

そのうえで、上書きする実体のコードを読む。典型的な作りはこうなっている。

// 同期スクリプトの中核
function syncRepository() {
  const previous = loadState();                       // 例: ~/.config/<配布物>/sync-state.json
  if (now - previous.last < 24 * 3600 * 1000) return; // ← N時間ガード
  saveState(now);
  downloadArchive();
  extractAndCopy();                                   // ← ここで無条件コピー
}

このガードが犯人。「24時間経ってから、最初にイベントが起きた瞬間」に走るので、 壁時計の時刻が毎日ずれていく。実測例では前日 03:20、翌日 14:06(34時間47分後)に落ちた。 固定時刻の貼り直しをどこへ動かしても追いつけない。

ついでに確認する: 人の変更を守る保護が効いているか

配布物の同期には「ローカルで変更されたファイルは上書きしない」保護が付いていることがあるが、 前提が崩れていると丸ごとスキップされることがある。

const hasGit = fs.existsSync(path.join(targetDir, '.git'));
// hasGit が false だと、以降の「ローカル変更を除外する」判定が全部飛ぶ

配布先が clone ではなくアーカイブの展開先だと .git が無いので、保護は一度も働かない。 「保護があるはずなのに消える」ときはここを疑う。

2. 「同期の後段に置く」で解こうとする前に、順序が保証されるか確かめる

イベントフック(セッション開始フック等)で同期が走っている場合、 同一イベントのフックは並列起動する実装が多い。配列の後ろに置いても後に走る保証は無い。 async / sync の区別以前の問題なので、まずここを確認する。順序で解けないなら次へ。

3. 直し方: 時刻でなく「当たっているか」で駆動する

推測しない。直接見て、当たっていなければ当てる。 冪等なら短い間隔で回してよい。

貼り直しツールに「書かずに未適用件数だけ返す」モード(--check 等)が既にあるなら、それを再利用するのが最短。

if (ifNeeded && !check) {
  const probe = run({ check: true });          // 書かない
  if (probe.pending === 0) {
    console.log('変更不要(未適用 0 件)');      // 出力は1行だけ
    process.exitCode = 0;                      // ← 既知の警告を混ぜない(下記)
  } else {
    // ASCII の目印を先頭に置く(呼び出し側の .bat/.cmd が findstr で拾うため)
    console.log(`REPAIRED 巻き戻りを検出(未適用 ${probe.pending} 件) 同期の最終実行=${syncedAt() ?? '不明'}`);
    const applied = run({ check: false });
    printResult(applied, false);
    process.exitCode = applied.stale.length ? 3 : (applied.ok ? 0 : 2);
  }
}

設計上ゆずれない3点

  1. no-op は静かにする。 30分おきに回すなら、何もしなかった時は出力1行・ログ0バイト・exit 0。 毎回フル出力を吐くと1年で数万行になり、本当に直した回が埋もれる。
  2. no-op の終了コードに「既知の警告」を混ぜない。 「もう二度と当たらないパッチが N 件ある」といった恒常的な警告で exit 3 を返す作りだと、 スケジューラの最終結果が常時3になり、本物の異常を見分けられなくなる。 恒常警告は「1日1回のフル実行」側だけで報告し、収束ジョブは黙らせる。
  3. 状態ファイルの読み取りで落ちない。 同期時刻を証拠として添えるのは有用だが、それが読めないことを理由に貼り直しを止めない。
export function syncedAt(stateFile = defaultStatePath) {
  try {
    const raw = JSON.parse(fs.readFileSync(stateFile, 'utf8'));
    return typeof raw.last === 'string' ? raw.last : null;
  } catch { return null; }   // 無い・壊れている・型違い のどれでも null
}

運用: 「毎日1回のフル実行」と「短間隔の収束」を分ける

ジョブ間隔役割
フル実行1日1回心拍。全項目の適用結果と恒常警告を必ずログに残す
収束(--if-needed)30分巻き戻りを検出した時だけ動く。平常時は無音

4. 検定: 本番を触らずに、対照群で確かめる

(a) 対象ディレクトリを環境変数で差し替えられるようにする

export const TARGET_DIR = path.join(process.env.<ツール名>_ROOT || defaultRoot, 'tools');

本番の複製に対してだけ走らせれば、実環境を1バイトも変えずに検定できる。

cp -r <配布ディレクトリ> "$TMP/fake"
<ツール名>_ROOT="$TMP/fake" node repair.mjs --if-needed   # 1回目: REPAIRED が出て当たる
<ツール名>_ROOT="$TMP/fake" node repair.mjs --if-needed   # 2回目: 変更不要・exit 0・ログ増分 0

(b) 旧版と新版を同じ複製に当てて出力を突き合わせる

既存モードの互換を壊していないことは、旧版を実際に走らせて diff を取るまで分からない。

git show HEAD:tools/repair.mjs > "$OLD/repair.mjs"     # ← ファイル名を変えないこと(後述)
<ツール名>_ROOT="$FAKE" node "$OLD/repair.mjs" --check > old.txt 2>&1
<ツール名>_ROOT="$FAKE" node tools/repair.mjs      --check > new.txt 2>&1
diff old.txt new.txt && echo "出力は新旧で完全一致"

🔴 落とし穴: CLI の起動条件が path.basename(process.argv[1]) === 'repair.mjs' のような 自己名判定になっていると、別名で保存した旧版は何も出力せず無言で終わる。 対照群が「0行 vs 49行」になって偽の不一致が出る。旧版は同じファイル名でディレクトリを分けて置く。

5. おまけ: .bat / .cmd で exit=%RC%>> がログに書かれない

Windows のラッパでよくある事故。

rem 壊れている: 数字の直後の >> がストリーム番号として解釈され、行が消える
echo [%DATE% %TIME%] exit=%RC%>> "%LOG%"

rem 正しい: 括弧で囲んで数字と >> を離す
(echo [%DATE% %TIME%] exit=%RC%)>> "%LOG%"

%RC% が 0 なら exit=0>> となり、cmd はこれを「ハンドル0(標準入力)のリダイレクト」と読む。 echo はコンソールへ出て、ログには1行も残らない。 ログに exit= 行が1つも見当たらないときは、ジョブが動いていないのではなくこれを疑う。

なお .bat / .cmd は ANSI コードページで読まれるため、UTF-8 の非ASCIIコメントを書かない。 化けた断片がコマンドとして実行される。先頭でコードページを変えても手遅れ。

6. 収束ジョブのラッパ(動いた時だけログを書く)

@echo off
rem Runs every 30 minutes. Only log when something was actually repaired.
rem ASCII only.
set LOGDIR=%USERPROFILE%\<ログ置き場>
if not exist "%LOGDIR%" mkdir "%LOGDIR%"
set TMPOUT=%TEMP%\repair-guard.out
"<node のフルパス>" "%~dp0repair.mjs" --if-needed > "%TMPOUT%" 2>&1
set RC=%ERRORLEVEL%
findstr /B /C:"REPAIRED" "%TMPOUT%" > nul
if %ERRORLEVEL% equ 0 (
  echo [%DATE% %TIME%] repair-guard>> "%LOGDIR%\repair.log"
  type "%TMPOUT%" >> "%LOGDIR%\repair.log"
  (echo [%DATE% %TIME%] exit=%RC%)>> "%LOGDIR%\repair.log"
)
del "%TMPOUT%" 2> nul
exit /b %RC%

判定に使う目印は必ず ASCIIにする。findstr に非ASCIIを渡すとコードページで壊れる。

7. 効果の検定は「次に上書きが起きた後」でしかできない

貼り直した直後にパッチが在るのは当たり前で、上書きがまだ起きていないだけかもしれない。 合格を宣言する前に、上書きジョブが1回走った後の状態を見る。 上書きの時刻が漂うなら、状態ファイル(同期の last)が更新されたことを確認してから判定する。

チェックリスト

  • 上書きする実体のコードを読み、発火の契機(時刻ではなく)を特定した
  • ガード(N時間・状態ファイル)の有無を確認し、壁時計時刻が漂うかを判定した
  • 「ローカル変更を守る保護」が前提崩れでスキップされていないか確認した
  • 同一イベントのフックが並列か逐次かを確認した(並列なら「後段に置く」は捨てる)
  • 貼り直しを --if-needed(状態検出)に変え、no-op を無音・exit 0 にした
  • no-op の終了コードに恒常警告を混ぜていない
  • 対象ディレクトリを環境変数で差し替え、本番の複製で1回目/2回目を実測した
  • 旧版を同じファイル名で別ディレクトリに置き、既存モードの出力一致を diff で確認した
  • ラッパの exit= 行が実際にログに出ることを目視した
  • 上書きが1回起きた後に、パッチが生存していることを確認した

よくある質問

+「同期で巻き戻る設定を「固定時刻の貼り直し」で守ろうとして失敗する — 状態の検出で駆動する収束に変える」とは何ですか?

配布物の同期で上書きされる設定にパッチを当て続けたい時、同期の直後の時刻に貼り直しジョブを置くと失敗する。上書き側がN時間ガードで発火するため壁時計時刻が毎日漂うから。時刻でなく「当たっているか」で駆動する収束への作り替え方、no-opを無音・exit0にする理由、本番を触らず対照群で検定する手順、cmdのexit=行が消える罠まで。

+どれくらいトークン(費用)を節約できますか?

ゼロから開発すると約4.2万トークンかかりますが、この巻物を使えば約9,000トークンで済みます。差し引き約3.3万トークン(API料金換算で約50円)・79%の節約です。

+どうやって使いますか?

無料です。MDファイルを Claude Code などのAIに読み込ませるだけ。ワンライナーをターミナルに貼れば実装が始まります。要件定義や技術調査を省いて実装だけにトークンを使えます。

+どのAIツールに対応していますか?

claude-code、cursor、codex-cli に対応しています。

+商用利用できますか?

ライセンスは「商用利用可 (再販不可)」です。

🤝 自分でAIを動かすのは、まだ不安…という方へ

この巻物の内容を、AIを使うプロに丸ごと任せることもできます。姉妹サービスAI代行堂なら「LINEで頼むだけで、仕事が完成」。

AI代行堂を見る →

関連する巻物

この巻物、誰かのトークンも救えます

𝕏 で節約レシートをシェア