ログを開いて最初に目に入ったのは、「本日発効」と自分で書いたメモでした。
その数時間後に届いたのは、撤回の知らせです。headless の claude -p 実行・Agent SDK・GitHub Actions を別枠の月次クレジットへ移す、と予告されていた課金変更が、発効当日に保留へ回されました。これらは引き続き、従来どおりサブスクリプションの上限内で扱われます。
私は前夜まで、パイプラインの headless 工程を組み替える準備をしていました。スクリプトを開き、分岐を足しかけて、手が止まったところでした。
止まってよかった、と思いました。もし先回りで書き換えていたら、撤回後に不要な分岐をもう一度はがす作業が待っていたはずです。今日は、この「予告 → 発効 → 撤回」のどの段階でもコードを触らずに済ませるための設計を、淡々と書き残しておきます。
条件は、どの段階でも分岐を増やさないこと
個人開発で4サイトを自動運用していると、プラットフォーム側の挙動は自分では決められません。決められるのは、その挙動の変化を、自分のコードのどこで受け止めるかだけです。
受け止め方を間違えると、こうなります。予告が出るたびにスクリプトへ分岐を足し、発効すれば古い分岐を消し、撤回されればまた戻す。変更そのものより、変更に追随する作業のほうが事故を生みます。
私が置いた条件は一つでした。予告・発効・撤回のどの段階でも、生成や push の本体コードには指一本触れない。触るのは「設定」だけにする。これを満たすには、プラットフォームの挙動を本体から切り離して、一箇所に集める必要がありました。
プラットフォームの挙動を一箇所に集める
まず、課金やクレジットに関わる「外部の事実」を、すべて一つのオブジェクトへ寄せました。本体コードはこのオブジェクトしか見ません。
// src/config/platform.ts
// プラットフォーム側の挙動を集約する単一の真実の源。
// 本体コードはここだけを参照し、外部の変更はこのファイルの値だけで吸収する。
export type PlatformState = {
// headless 実行が別枠クレジットへ分離されたか
headlessSeparateCredits: boolean;
// 1 工程あたりの概算コスト(USD)。実測ログから更新する
costPerStageUsd: Record<string, number>;
// この設定が「発効済み」か「保留(予告のみ)」か
status: "applied" | "staged";
// 根拠と最終確認日。撤回・再予告のたびに追記する
note: string;
verifiedOn: string; // YYYY-MM-DD (JST)
};
export const PLATFORM: PlatformState = {
headlessSeparateCredits: false, // 撤回されたので false のまま据え置き
costPerStageUsd: {
"topic-select": 0.04,
"body-generate": 0.21,
"quality-gate": 0.03,
"push": 0.01,
},
status: "staged",
note: "6/15 予告の課金分離は当日に撤回(保留)。発効が再確認できるまで staged。",
verifiedOn: "2026-06-17",
};
本体側は、この値を読むだけです。
// src/pipeline/run.ts
import { PLATFORM } from "../config/platform";
// headless をどの実行枠で走らせるかは、フラグ一つで決まる。
// 分岐は「設定を読む」だけで、ロジックの書き換えはどこにもない。
const runner = PLATFORM.headlessSeparateCredits
? "metered-credits"
: "subscription";
console.log(`[stage] runner=${runner} status=${PLATFORM.status}`);
ここが要点です。予告が来ても、run.ts は触りません。変わるのは platform.ts の真偽値一つだけ。発効が確認できれば true に、撤回されれば false のまま。status を staged にしておけば、「予告は知っているが、まだ適用していない」状態をコードとして表現できます。
「適用したら月額がどう動くか」を先に出す
フラグを切り替える前に知りたいのは、切り替えたとき月額がどう動くか、です。予告の文面ではなく、自分の実測から出します。
私は工程ごとの消費を毎日 1 行のログに残しています。そこから、現在の構成と「変更を適用した構成」の月額差分を算出する小さなスクリプトを置きました。
// scripts/cost-diff.ts
// 実測ログ(工程ごとの呼び出し回数)から、変更適用時の月額差分を見積もる。
// 予告を信じる前に、自分の数字で意思決定する。
import { PLATFORM } from "../src/config/platform";
type DailyUsage = { stage: string; calls: number };
// 過去 30 日の 1 日平均(実測ログを集計した値)
const dailyAvg: DailyUsage[] = [
{ stage: "topic-select", calls: 4 },
{ stage: "body-generate", calls: 8 },
{ stage: "quality-gate", calls: 8 },
{ stage: "push", calls: 4 },
];
const DAYS = 30;
// 現状(サブスク枠・実コストは枠内なので 0 とみなす)
const currentMonthly = 0;
// 変更適用後(別枠クレジットで実費が発生)
const projectedMonthly = dailyAvg.reduce((sum, u) => {
const unit = PLATFORM.costPerStageUsd[u.stage] ?? 0;
return sum + unit * u.calls * DAYS;
}, 0);
console.log(`現状(サブスク枠内): $${currentMonthly.toFixed(2)}/月`);
console.log(`適用後の見積もり : $${projectedMonthly.toFixed(2)}/月`);
console.log(`差分 : $${projectedMonthly.toFixed(2)}/月`);
このスクリプトを 6/15 の予告時点で回した結果が、月あたりおよそ 26 ドルの増分でした。body-generate 工程だけで全体の七割近くを占めていたので、もし発効していたら、まずこの工程をサブスク枠へ寄せる判断になっていたはずです。
撤回によって、その判断は不要になりました。けれど見積もりは無駄になっていません。次に同じ予告が来たとき、回すべきスクリプトはもう手元にあります。
撤回は「戻す」のではなく「保留のまま」にする
撤回されたとき、最もやってはいけないのは、予告に合わせて加えた変更を慌ててはがすことです。そもそも本体を触っていなければ、はがす対象がありません。
platform.ts の status を staged のままにし、note に経緯を一行足すだけで終わりました。
// 撤回時の対応は、この 2 行の更新だけ
note: "6/15 予告は当日撤回。再予告が出れば staged のまま見積もりを回し、発効確認後に applied へ。",
verifiedOn: "2026-06-17",
status を持たせておくと、撤回と発効を同じ語彙で扱えます。予告は staged で受け、発効が公式に確認できたら applied へ進め、撤回されたら staged に留める。三つの状態が、一つのフィールドの上で完結します。
先回り改修が招く、二重の事故
この設計に行き着いたのは、過去に逆をやって痛い目を見たからです。
予告を真に受けて本体へ分岐を入れると、二つの事故が連鎖します。一つ目は、撤回後に分岐が残ること。if (新課金) { ... } の条件が常に偽になり、読まれないコードがそのまま居座ります。二つ目は、その死んだ分岐を後で「使われていないから」と誰か(多くは数か月後の自分)が消すとき、本当は将来のために置いたものだったと気づけないことです。
設定に寄せておくと、この連鎖が起きません。死ぬのは本体コードではなく、フラグの値一つ。note と verifiedOn が、なぜその値なのかを語り続けてくれます。
落とし穴も書いておきます。フラグの真実の源を二重に持たないことです。環境変数と platform.ts の両方で同じ挙動を制御し始めると、撤回時にどちらを直すかで迷い、片方を直し忘れます。切り替えたい一点だけを platform.ts に置き、環境変数からは参照するだけにすると、迷いが消えます。
予告を受けたときの手順
新しい予告を見たら、私は次の順序で動きます。Dolice Labs の自動運用では、この手順を一枚のメモにして手元に置いています。
platform.ts の status を staged にし、note に予告の要点と日付を一行で残します。
cost-diff.ts を回し、適用時の月額差分を自分の実測から出します。
- 差分が許容範囲を超える工程だけを特定し、サブスク枠へ寄せる候補として控えます(まだ実装はしません)。
- 公式の最終確認を待ちます。発効が確定したら
headlessSeparateCredits を true、status を applied にします。
- 撤回されたら、
status は staged のまま、note に経緯を一行追記して終わりです。
私の推奨は、3 の段階で手を動かしすぎないことです。候補を控えるところで止め、発効が確定するまで本体には触れません。先回りで実装した行の数だけ、撤回時にはがす作業が増えます。今回のように当日撤回されると、その差は丸ごと節約できた時間になります。
次の予告が来る前に
プラットフォームの予告は、これからも出ます。発効することもあれば、今回のように撤回されることもあります。そのたびに本体コードを開くのか、フラグ一つで受けるのかは、予告が来る前に決めておくものです。
次に同じ通知を見たら、まず cost-diff.ts を一度回してみてください。自分の数字を持ってから、フラグを staged のまま置くか applied へ進めるかを決める。それだけで、予告にも撤回にも振り回されずに済みます。
同じように複数の自動運用を抱えている方の、静かな手がかりになれば幸いです。