●SCIENCE — Claude Scienceがベータ公開され、研究ツールを統合し監査可能な成果物を生成するワークベンチが使えます●MODEL — Claude Opus 4.7のfast modeが7月24日に廃止され、Opus 4.8のfast modeへの移行が必要になります●CODE — Claude Code v2.1.195でフルスクリーン時のマウス操作を無効化できるトグルが追加されました●CODE — ハイフン入りのhook matcherが部分一致ではなく厳密一致になるよう修正されました●AGENT — Claude Scienceは調整役エージェントが専門エージェントを呼び出し、引用や計算をレビューする多段構成です●CLOUD — ClaudeがMicrosoft Foundry(Azure)で一般提供され、Azureネイティブで利用できます●SCIENCE — Claude Scienceがベータ公開され、研究ツールを統合し監査可能な成果物を生成するワークベンチが使えます●MODEL — Claude Opus 4.7のfast modeが7月24日に廃止され、Opus 4.8のfast modeへの移行が必要になります●CODE — Claude Code v2.1.195でフルスクリーン時のマウス操作を無効化できるトグルが追加されました●CODE — ハイフン入りのhook matcherが部分一致ではなく厳密一致になるよう修正されました●AGENT — Claude Scienceは調整役エージェントが専門エージェントを呼び出し、引用や計算をレビューする多段構成です●CLOUD — ClaudeがMicrosoft Foundry(Azure)で一般提供され、Azureネイティブで利用できます
type Verdict = | { level: "ok" } | { level: "warn"; daysLeft: number; entry: DeprecationEntry } | { level: "expired"; entry: DeprecationEntry };const DAY = 24 * 60 * 60 * 1000;function evaluate( req: OutgoingRequest, now: Date, warnWindowDays: number,): Verdict[] { const parts = decompose(req); const verdicts: Verdict[] = []; for (const entry of DEPRECATION_CALENDAR) { if (!matches(parts, entry)) continue; // タイムゾーン付き文字列を Date にすれば、比較は UTC 上で正しく行われる const effective = new Date(entry.effectiveAt).getTime(); const diff = effective - now.getTime(); if (diff <= 0) { verdicts.push({ level: "expired", entry }); } else if (diff <= warnWindowDays * DAY) { verdicts.push({ level: "warn", daysLeft: Math.ceil(diff / DAY), entry }); } } if (verdicts.length === 0) verdicts.push({ level: "ok" }); return verdicts;}
new Date(entry.effectiveAt) は、タイムゾーン付きの ISO 文字列を渡している限り、内部で UTC の絶対時刻に直してくれます。だからこそ effectiveAt にゾーンを書くことが効いてきます。ここを日付だけで持つと、now との比較が実行環境のローカル時間に引きずられ、廃止日の前後半日で判定が揺れます。
この設計の弱点は明白で、廃止カレンダーへの追記を人間が忘れたら意味がありません。そこで、カレンダー自身の健全性を CI で守ります。守りたいのは二つです。ひとつは「すでに失効した行を、対象の設定を残したままマージできない」こと。もうひとつは「カレンダーの各行が、少なくとも出典を持っている」ことです。
import { test, expect } from "vitest";// 実際にスケジュールタスクが投げる設定を集めた配列(実運用の真実を反映させる)import { LIVE_REQUESTS } from "./live-requests";test("失効済みの部品を含む稼働中リクエストが存在しない", () => { const now = new Date(); for (const req of LIVE_REQUESTS) { const verdicts = evaluate(req, now, 0); const expired = verdicts.filter((v) => v.level === "expired"); expect( expired, `失効済み設定が残っています: ${JSON.stringify(req)}`, ).toHaveLength(0); }});test("カレンダーの各行は出典と移行先を持つ", () => { for (const entry of DEPRECATION_CALENDAR) { expect(entry.source.length).toBeGreaterThan(0); expect(entry.migrateTo.length).toBeGreaterThan(0); }});
一つ目のテストは、実際に稼働している設定 LIVE_REQUESTS を対象にしている点が肝です。カレンダーだけを机上で検証しても、本番の設定がそれに追随していなければ意味がありません。稼働中の設定に失効行が刺さっていたら、その時点で CI が赤くなり、廃止日をまたいだままのデプロイが止まります。公式のドキュメントには「廃止告知をどう自分のコードに取り込むか」までは書かれていません。この二つのテストは、その取り込みを人間の記憶ではなく仕組みに移すための、最小の担保です。