はじめに
Microsoftが公開している SkillOpt は、「エージェントのスキル(プロンプト/手順書)をニューラルネットの重みのように"訓練"する」というコンセプトのフレームワークです。
そこに2026年6月、SkillOpt-Sleep という新しいプレビュー機能が追加されました。ざっくり言うと「ローカルのコーディングエージェント(Claude Code / Codex / Copilot)に毎晩の"睡眠サイクル"を与え、日中の利用ログを振り返らせて、繰り返しのタスクをリプレイし、学んだことを検証済みの長期記憶・スキルとして提案する」という機能です。
「日中の実利用ログから、本当に夜間で自己改善できるのか(今回は夜間に行う想定のタスクを日中に手動実行)」を実際に検証してみたところ、意図的に不完全にしたスキルが、実際のClaude Code利用ログをもとに、held-outゲートによる検証を経て、狙い通りの内容へと自己改善される様子を確認できました。本記事はその検証記録です。
執筆時点でSkillOpt-SleepはPreview機能であり、インターフェースや挙動は今後変わる可能性があります。
SkillOptとは何か
SkillOptは、「スキルドキュメント(SKILL.mdのようなMarkdown)を、ニューラルネットの重みのように訓練する」という手法を提案するフレームワークです。2026年6月2日にv0.1.0としてPyPIで公開された、比較的新しいプロジェクトです。
- モデルの重みは一切変更しない(frozen agent)
- スキルドキュメント(数百〜2000トークン程度のMarkdown)を「学習対象のパラメータ」とみなす
- 別の"optimizer"モデルが、実行結果(rollout)を見て
add/delete/replaceの境界付き編集をスキル文書に加える - 編集はheld-outな検証セットでスコアが改善した場合のみ採用(=勾配降下法における更新の承認に相当)
- テキストの「学習率」予算、却下された編集のバッファ、エポック単位のslow/meta更新という仕組みで、訓練を安定させている
- デプロイ時の推論には追加のモデル呼び出しが一切発生しない(zero inference-time overhead)
公式リポジトリによれば、6ベンチマーク×7モデル×3実行環境(直接チャット/Codex CLI/Claude Code CLI)の52セル全てで最良ないしタイの性能を達成し、GPT-5.5では直接チャットで+23.5pt、Codexのエージェントループで+24.8pt、Claude Codeで+19.1ptの改善を報告しています(論文)。
SkillOpt自体は「オフラインでベンチマークに対してスキルを訓練する」ためのツールです。
SkillOpt-Sleepとは何か
SkillOpt-Sleepは、SkillOptの考え方を「日々の自分自身の利用ログ」に適用するデプロイ後(deployment-time)の相棒ツールです(docs/sleep/README.md)。2026年6月15日にプレビューとして発表され、2026年7月2日のSkillOpt v0.2.0でskillopt-sleepCLIとして正式にPyPI配信されました。SkillOpt本体からは約1ヶ月遅れで登場した、さらに新しい機能です。
- モデルの重み学習は不要(no weight training)
- 推論時のオーバーヘッドはゼロ(夜間バッチ処理のみ)
- SkillOpt(validation-gated bounded edits)、Claude Dreams(オフライン統合・review-then-adopt)、agent-sleep(短期経験→長期能力への転換)という3つのアイデアを合成したもの
公式ドキュメント(RESULTS.md)では、GPT-5.4-nanoとSearchQAを使った実験で、ゲート無しだと精度が0.554→0.026(-52.8pt)まで崩壊する一方、ゲート有りだと0.570→0.570(安全に拒否)という結果や、公開ベンチマークgbrain-evalsで、意図的に不完全にしたスキルがClaude Code・Codex双方で0.00→1.00まで改善した、という実証結果が報告されています。
実際にユーザーが使う入り口はskillopt-sleepというCLI(Claude Code / Codex / Copilot向けのプラグインも同じものを内部で叩いている)で、以下のサブコマンドを持ちます。
「Sleep」という単語があるので夜間に動くものと思われがちですが、例えばCronなどのスケジュール設定で夜間などに改善タスクを実行することができます。夜間にかかわらず日中でも手動でいつでも改善タスクを実行することができるので、Skillをしばらく使ってログがたまったら任意のタイミングで改善タスクを実行する運用で良いと思います。
skillopt-sleep harvest # 収集+タスク抽出だけ行う(無料・デバッグ用)
skillopt-sleep dry-run # フルサイクルを実行し、結果をレポートのみ(ステージングしない)
skillopt-sleep run # フルサイクルを実行し、提案をステージング
skillopt-sleep status # 最新のステージング済み提案を表示
skillopt-sleep adopt # 提案を適用(バックアップ付き)
各工程の意味
記事中で何度も出てくる「harvest→mine→replay→consolidate→gate→stage→adopt」という一連の工程は、それぞれ次のような役割を持っています。
| 工程 | 意味 | 補足 |
|---|---|---|
| harvest(収集) |
~/.claudeなどに溜まった過去のセッション履歴(トランスクリプト)を読み込む |
読み取り専用。何も書き換えない |
| mine(抽出) | 収集したセッションから「繰り返し出てくるタスク」を検出し、学習材料(TaskRecord)として抽出する | ヒューリスティック(否定/肯定フィードバックの検出など)か、LLMによる合成のどちらかで行われる |
| replay(再実行) | 抽出したタスクを、今のスキル/メモリを使って改めて実行してみる | 日中の実セッションとは別に、夜間バッチの中でオフラインに再現する |
| consolidate(統合・振り返り) | replayの結果(成功/失敗)をもとに、LLMの"optimizer"がスキル/メモリへの具体的な編集案を提案する | 提案はadd/delete/replaceの境界付き編集のみ |
| gate(検証ゲート) | consolidateで提案された編集案を、held-out(学習に使っていない)タスクで採点し、今のスコアを上回った場合のみ採用する | ここがSkillOpt-Sleepの安全装置。悪い提案を弾く役割 |
| stage(ステージング) | gateを通過した編集案を、まだ本番ファイルには反映せず、レビュー用に保存しておく |
statusコマンドで中身を確認できる |
| adopt(採用) | ステージングされた提案を人間が確認し、実際にSKILL.md/CLAUDE.mdへ反映する |
反映前に自動でバックアップが作られる |
ステージングフォルダの中身
stage工程で作られる.skillopt-sleep/staging/<タイムスタンプ>/フォルダには、実際には以下のファイルが生成されます。
| ファイル | 内容 | 用途 |
|---|---|---|
proposed_SKILL.md |
提案後のSKILL.md全文 |
adopt時にこの内容がそのまま本番ファイルにコピーされる |
proposed_CLAUDE.md |
提案後のCLAUDE.md全文 | 同上 |
report.md |
人間可読な提案サマリー |
skillopt-sleep statusが表示する内容そのもの |
report.json |
report.mdと同じ内容の機械可読版 |
プログラムから読み取る用 |
manifest.json |
本番ファイルの実パス(live_skill_path/live_memory_path)や、SKILL/CLAUDE提案の有無 |
adoptコマンドが「どこに」「何を」コピーすべきか判断するための設定情報 |
diagnostics.json |
held-outタスクごとの詳細(baseline_score/candidate_score/holdout_detailなど) |
その夜の判断根拠を後から確認できる、自己診断用の情報 |
ソースコード(skillopt_sleep/cycle.py, harvest.py, mine.py, config.py)を読んで分かった、意外と誤解しやすいポイントを先に共有します。
ログ・出力の見方
記事中でrun/dry-run/status/harvestの出力例(JSON・テキスト)が何度も登場します。よく出てくるフィールドの意味を先にまとめておきます。
夜間サイクル(run/dry-run)の結果に出てくるフィールド:
| フィールド | 意味 |
|---|---|
night |
何回目の夜間サイクルか(回数のカウンタ) |
baseline |
編集を適用する前の、held-outタスクでのスコア |
candidate |
提案された編集を適用した場合の、held-outタスクでのスコア |
accepted |
その夜の編集提案が採用されたかどうか(true/false) |
gate_action |
ゲートの判定結果。accept_new_best(採用)、reject(却下)など |
n_sessions |
harvestで収集されたセッション数 |
n_tasks |
mineで抽出され、replayされたタスク数 |
n_accepted_edits / n_rejected_edits
|
採用/却下された編集の件数 |
edits / rejected_edits
|
採用/却下された編集の具体的な内容(target=編集対象、op=add/delete/replace、content=編集内容、rationale=採用理由) |
staging_dir |
提案が保存されたステージングフォルダのパス |
adopted |
その場で自動的にadoptまで行われたか(既定ではfalse。人間が別途adoptを実行する) |
tokens_used |
その夜のサイクルで消費したトークン数 |
candidateがbaselineを上回った場合のみ、gateが編集を採用(gate_action: accept_new_best)します。candidateがbaseline以下であれば、どれだけ良さそうな編集案でも却下(gate_action: reject)され、既存のスキルはそのまま維持されます。
harvestで抽出される個別タスク(TaskRecord)に出てくるフィールド:
| フィールド | 意味 |
|---|---|
intent |
そのタスクでユーザーが実際に依頼した内容(プロンプト) |
context_excerpt |
同じセッション内での追加のやり取り(否定フィードバックなど) |
attempted_solution |
そのタスクに対してエージェントが実際に返した応答 |
outcome |
そのタスクの成否判定。fail(否定フィードバック等で失敗と判定)/success(肯定フィードバック等で成功と判定)/unknown(判定材料なし)/mixed(やり取りが3ターン以上で判定が曖昧) |
split |
train(reflectの材料)かval(gateでの採点対象)か |
ソースコード(skillopt_sleep/cycle.py, harvest.py, mine.py, config.py)を読んで分かった、意外と誤解しやすいポイントを先に共有します。
「日中の利用」と「夜間の処理」は別イベントだが、夜間処理の中の5工程は一括実行される
- 日中: 普段通りClaude Codeで作業する。この時SkillOpt-Sleepは一切関与しない。Claude Code自体が普通のセッションログを
~/.claude/projects/配下に記録していく、という副次的な処理が起きているだけ(SkillOpt-Sleepが無くてもClaude Codeは元々これをやっている)。 -
skillopt-sleep runを叩く瞬間: ここで初めてharvest→mine→replay→consolidate→gate→stageが1回のプロセス実行内で連続して動く。「harvestだけ今日、consolidateは別日に」という工程単位の分割はデフォルトでは無い(harvest単体コマンド+--tasks-fileで後からreplayする、という分割の逃げ道はある)。
--target-skill-pathを指定しないと、意図しない場所に新規スキルが作られる
config.pyの既定では、進化させる対象は
~/.claude/skills/skillopt-sleep-learned/SKILL.md
という新規の管理対象スキルになる。プロジェクトの既存CLAUDE.mdが自動的に書き換わるわけではない。
フィードバック検出が英語フレーズ決め打ち(実証済み)
harvest.pyのヒューリスティック("still wrong" "thanks" "lgtm"等)は英語のみが既定です。これは実際に検証しました。日本語で「それは違います。Key Risksセクションと確信度(Confidence)の記載が抜けています。」という否定フィードバックを送ったセッションをharvestしたところ:
- 環境変数を設定しない場合:
outcome: "unknown"(否定フィードバックとして検出されない) -
SKILLOPT_SLEEP_NEG_FEEDBACK="それは違います,まだ直ってない"を設定した場合:outcome: "fail"(正しく検出される)
日本語でやり取りする場合は、環境変数SKILLOPT_SLEEP_NEG_FEEDBACK/_POS_FEEDBACKに日本語フレーズを追加することで、英語の場合と同じようにユーザーの良い/悪い反応シグナルを拾えることが確認できました。
検証方針
「意図的に欠陥のあるスキルを用意し、実際に自分でClaude Codeセッションを回して得られたトランスクリプトからharvest→mineさせ、held-outで前後比較する」という設計で検証しました。
- データソース: 実際に自分で動かしたClaude Codeセッション(模擬的な"日中の実利用")
- スコープ: 専用のテストプロジェクトディレクトリに限定(
--scope invoked)し、個人の実利用履歴とは混同しないよう設計 - 欠陥スキル: 公開ベンチマークgbrain-evalsの
brief-writerシードと同型("Key Risksセクション"と"Confidence:"表記が欠落したブリーフ作成スキル)を自作し、--target-skill-pathで明示指定
この検証の制約(本番運用そのままではない点)
本記事の検証には、効果を測定可能にするために意図的に追加した「検証専用の工程」が含まれており、実際の本番運用ではそのままでは発生しない点を先に明記しておきます。
| 検証で行うこと | 本番運用での扱い |
|---|---|
| わざと欠陥のあるSKILL.mdを用意する | 本番では自分のスキルをわざと壊したりしない。今あるスキル(不完全な点も含めて)をそのまま使うだけ |
claude -pを複数回連続実行してログを人為的にまとめて生成する |
本番では普段の実作業の副産物として自然にログが溜まるのを待つだけ |
| 否定/肯定フィードバックを意図的に混ぜる | 本番では、本当にその回答に満足/不満だった時に自然に出てくる反応 |
harvestを単独で先に実行して中身を確認する |
本番ではしばしば省略される、デバッグ的な確認ステップ |
| 「日中ログ生成」と「夜間処理」を意識的に日を分けて実行する | 本番では意識して分けない。日中は普通に作業し、気が向いた時(または自動スケジュール実行で)処理が走るだけ |
一方で、使用するCLIコマンド自体(harvest/dry-run/run/status/adopt)とその内部パイプライン(harvest→mine→replay→consolidate→gate→stage→adopt)は本番運用と完全に同一であり、そこは模擬ではなく実際の挙動を確認しています。
本番運用での完全自動化(skillopt-sleep scheduleによるcron登録)について、実際にこの環境でscheduleコマンドを実行して確認したところ、次のような結果でした。
$ skillopt-sleep schedule --project ...
[sleep] crontab not found on this system. Add this line to your scheduler manually:
17 3 * * * mkdir -p "..." ; cd "..." && ...python.exe -m skillopt_sleep run ...
crontabが存在しない環境では、手動登録用のコマンド行を案内して終了する、という穏当なフォールバック動作でした(skillopt_sleep/scheduler.pyのコメント通り)。自動でのcron登録がされない環境では、表示されたコマンドをタスクスケジューラなどに自分で登録すれば、同じスケジュールで夜間実行できます。
検証環境
| 項目 | 値 |
|---|---|
| OS | Windows 11 Home |
| Python | 3.12.7 |
| SkillOpt | v0.2.0 相当、commit e4ea6a6(pip install -e ".[claude]"でeditable install) |
| Claude Code CLI | 2.1.150 |
| モデル | Haiku |
手順概要
| Step | 内容 | 区分 |
|---|---|---|
| 1 | テスト専用プロジェクトフォルダを作成し、欠陥SKILL.mdを設置 | 検証専用 |
| 2 | そのフォルダで実際にclaude -pを複数回実行し、"日中の利用ログ"に相当するセッション履歴を生成(否定/肯定フィードバックも意図的に混ぜる) |
検証専用 |
| 3 |
skillopt-sleep harvestで、ログが正しく収集・タスク抽出されるか確認 |
検証専用(デバッグ確認) |
| 4 |
dry-run(mockで配線確認→claudeバックエンドで本番)でreplay→consolidate→gateまで通す |
本番運用と同一 |
| 5 |
statusでステージングされた提案内容を確認 |
本番運用と同一 |
| 6 |
adoptで実際にSKILL.mdが更新されるか、Before/Afterをdiff確認 |
本番運用と同一 |
「検証専用」の工程がなぜ必要か、本番運用とどう違うかは前節「この検証の制約」を参照。
通常運用の3段階と、今回の検証Stepの対応
SkillOpt-Sleepの本番運用は、大きく分けると次の3段階になります。
| 段階 | 内容 | 誰が/何が行うか |
|---|---|---|
| ① 日中: Skillを実行してログ取得 | 普段通りClaude Codeを使う。ログは副次的に~/.claudeへ自動記録される |
人間(普段の作業) |
| ② 夜間: ログを見て改善案作成 | harvest→mine→replay→consolidate→gateが1回のコマンドで一括実行され、改善案がステージングされる | システムが全自動(skillopt-sleep run) |
| ③ 人間が承認するか判断 | ステージングされた提案を確認し、採用するか判断する | 人間(status→adopt) |
②を「ログを見て改善案作成」と表現すると人間が目視で判断しているように聞こえますが、実際には人間は一切介在せず、reflect(LLMによる編集提案)→ gate(held-outスコアでの検証)までが機械的に一括処理されます。人間の判断が入るのは③のみです。また「次の日」という表現も厳密な制約ではなく、②が完了した後の任意のタイミングで③を行えばよい、という位置づけです(今回の検証では、①はStep 1〜2、②はStep 3〜4、③はStep 5〜6が対応します)。
検証結果
Step 1〜2: テストプロジェクト作成・ログ生成
検証専用のテストプロジェクトフォルダに、"Key Risksセクション"と"Confidence:"表記が欠落したSKILL.mdを設置しました。
---
name: brief-writer-planb
version: 0.1.0
description: Brief Writer (Plan B verification copy)
---
## Brief Writer
When asked, write a short, clear research brief that answers the question.
Keep it focused and readable. Lead with the answer.
その中で実際にclaude -pを使い、複数件のブリーフ作成タスクを実行しました。例えば「レガシーAPIを廃止すべきか」というタスクへの最初の回答は、次のように"Key Risks"も"Confidence"も無い内容でした。
## Brief: Deprecating a Legacy API with Active Users
### Recommendation: Deprecate with a structured transition plan
You should deprecate the legacy API, but only with a well-defined migration path...
### Rationale
...
### How to make it work
...
### The risk of *not* deprecating
...
Bottom line: Deprecation is a feature, not a bug. Do it early, do it clearly, support the transition, then move on.
これに続けて否定フィードバック("That's wrong, it's missing a Key Risks section and a Confidence indicator. Please redo it with both.")を送ったところ、単発の会話内でモデルが即座に自己修正しました。
### Key Risks
1. User exodus before migration. If the replacement API isn't ready or isn't clearly better, users may fork or switch to competitors.
2. Stranded critical integrations. Some users may have no bandwidth to migrate...
3. Hidden dependencies. ...
4. Timeline slip. ...
### Confidence: High
This approach aligns with how mature platforms (AWS, Google Cloud, Stripe) handle similar transitions...
このやり取りは~/.claude/projects/配下にセッションとして想定通り記録され、後段のharvestで正しく取得できることを確認しました。
Step 3: harvestの結果
skillopt-sleep harvestコマンドを実行すると、実施したセッションから正しくタスクが抽出されました(抜粋)。
{
"tasks": [
{
"id": "task_6c20a6745066",
"intent": "Using the SKILL.md in this directory as your guide, write a brief on whether to deprecate a legacy API with active users.",
"context_excerpt": "Follow-up constraints from the same session:\n- That's wrong, it's missing a Key Risks section and a Confidence indicator. Please redo it with both.",
"attempted_solution": "# Brief: Deprecating a Legacy API with Active Users\n\n## Recommendation: Deprecate with a structured transition plan\n\n...",
"outcome": "fail",
"reference_kind": "none",
"split": "train",
"origin": "real"
}
]
}
先ほど送った否定フィードバックがcontext_excerptに「Follow-up constraints from the same session」として正しく反映され、outcomeも"fail"と判定されています。ヒューリスティックのリトライ連鎖検出が、実際のセッションログに対して意図通り機能していることが確認できました。
Step 4: dry-run / run の結果
mockバックエンドでのdry-runは変化なしという結果になりました(mockは実際の学習をシミュレートしないため、これは想定通りの挙動です)。
{
"night": 1,
"accepted": false,
"gate_action": "reject",
"baseline": 0.0,
"candidate": 0.0,
"n_tasks": 3,
"n_sessions": 3,
"n_accepted_edits": 0,
"edits": [],
"adopted": false
}
続けてclaudeバックエンドで本番のrunを実行したところ、次のような結果になりました。
{
"baseline": 0.0,
"candidate": 0.16666666666666666,
"gate_action": "accept_new_best",
"accepted": true,
"edits": [
{"target": "memory", "content": "...always include a section titled 'Key Risks'"},
{"target": "memory", "content": "...always include a section titled 'Confidence'"},
{"target": "memory", "content": "...always include the text 'Recommendation' in the response"},
{"target": "memory", "content": "...do not ask the user for a format file or clarification—proceed immediately..."}
]
}
狙っていた"Key Risks"と"Confidence"が、held-outスコアの改善(0.0→0.167)とともに正しく学習対象になっていました。加えて、実際のログから「"Recommendation"という語を含めること」「確認を求めずに即座に文書を作成すること」という2つの追加ルールまで拾ってきています。gbrain-evalsのような事前定義されたルールベース判定と違い、実際のharvest→mineフローでは判定がLLMによる汎用的なルーブリック採点になるため、狙った内容だけでなく、実際のログから拾える改善点まで幅広く学習対象にできる、ということが分かります。
Step 5: 提案内容確認(status)
skillopt-sleep statusを実行すると、以下のような提案内容が表示されました。
[sleep] nights so far: 1
[sleep] project: C:\...\test-project
[sleep] latest staged proposal: C:\...\staging\20260711-153831
## SkillOpt-Sleep — night 1 report
- project: `C:\...\test-project`
- backend: `claude` replay: `mock`
- sessions harvested: 3
- tasks mined: 1 (replayed: 1)
- held-out score: 0.000 -> 0.167
- gate: accept_new_best (accepted=True)
- tokens used: 2593
### Accepted edits
- [memory/add] When writing a brief or structured document, always include a section titled 'Key Risks'
_why: Failed outputs did not include the required 'Key Risks' section_
- [memory/add] When writing a brief or structured document, always include a section titled 'Confidence'
_why: Failed outputs did not include the required 'Confidence' section_
- [memory/add] When writing a brief or structured document, always include the text 'Recommendation' in the response
_why: Failed outputs did not contain the required word 'Recommendation'_
- [memory/add] When writing a structured document and no explicit format reference is provided, do not ask the user for a format file or clarification—proceed immediately with the document...
_why: Agent was requesting a reference file instead of writing the document with required sections._
_Review, then run `/sleep adopt` to apply, or discard this folder._
held-outスコア、採用された編集内容とその理由まで、レビューに必要な情報が一目で確認できます。
Step 6: adoptの結果 ― Before/After比較
skillopt-sleep adoptを実行すると、ステージングされていた提案が実際にファイルへ反映されました。
Before (SKILL.md):
---
name: brief-writer-planb
version: 0.1.0
description: Brief Writer (Plan B verification copy)
---
## Brief Writer
When asked, write a short, clear research brief that answers the question.
Keep it focused and readable. Lead with the answer.
After (CLAUDE.md、adopt後に新規作成):
<!-- SKILLOPT-SLEEP:LEARNED START -->
### Learned preferences & procedures
_This block is maintained by SkillOpt-Sleep. Edits here are proposed offline, validated against your past tasks, and adopted only after you approve them. Hand-edits outside this block are never touched._
- When writing a brief or structured document, always include a section titled 'Key Risks'
- When writing a brief or structured document, always include a section titled 'Confidence'
- When writing a brief or structured document, always include the text 'Recommendation' in the response
- When writing a structured document and no explicit format reference is provided, do not ask the user for a format file or clarification—proceed immediately with the document, ensuring it includes the mandatory sections 'Key Risks' and 'Confidence' and the text 'Recommendation'
<!-- SKILLOPT-SLEEP:LEARNED END -->
当初狙っていた"Key Risks"/"Confidence"の欠落が、実際のClaude Code利用ログをもとに正しく学習・反映されていることが確認できました。元のSKILL.mdはSkillOpt-Sleepの設計通り一切変更されず、学習内容はCLAUDE.md側に<!-- SKILLOPT-SLEEP:LEARNED -->ブロックとして追記される形で、既存の記述には触れずに反映されます。adopt実行時にはバックアップも自動的に作成されました。
SkillOpt-SleepはSKILL.md(スキル本体)とCLAUDE.md(メモリ、学習した振る舞いを蓄積する場所)という2つの別々のファイルを進化させる仕組みになっており、どちらに書き込むかはoptimizerがその都度判断します。
Step 5のstatus出力をよく見ると、採用された4件の編集は全て[memory/add](=target: "memory")となっており、target: "skill"の編集は1件もありませんでした。つまり今回のケースでは、optimizerが「これらのルールはSKILL.md本体ではなくCLAUDE.md(メモリ)に書くべき」と判断した結果です。
そのため、SKILL.md自体は変更されず、CLAUDE.mdが新規作成される形になりました。
複数タスクでの検証
タスク数を増やして複数回runを実行し、規模の異なる検証も行いました。report.jsonに記録されたstarted_at/ended_at/tokens_usedから、実測値をまとめます(バックエンドは全てClaude Haiku)。
| タスク数 | 所要時間 | 消費トークン |
|---|---|---|
| 1 | 1分41秒 | 2,593 |
| 5 | 6分41秒 | 17,182 |
| 6 | 10分6秒 | 25,252 |
タスク数が増えるほど所要時間・トークン消費も増える傾向が見られましたが、単純な比例ではありませんでした。これはgateが候補編集を検証するたびにval split全体をreplayし直すため、タスク数だけでなく採用候補の編集数によっても呼び出し回数が変わるためと考えられます。今回はタスク数を絞った小規模な検証だったため、config.pyの既定値max_tasks_per_night: 40のような本番規模での所要時間は、別途確認が必要です。
日本語フィードバックの検出
日本語での否定フィードバックが正しく検出されるかも別途検証しました。新しいタスクを1件実行後、日本語で「それは違います。Key Risksセクションと確信度(Confidence)の記載が抜けています。両方を含めて書き直してください。」と否定フィードバックを送信したところ、SKILLOPT_SLEEP_NEG_FEEDBACK="それは違います,まだ直ってない"という環境変数を設定するだけで、このタスクのoutcomeが"fail"と正しく検出されました。英語フレーズが既定のヒューリスティックも、環境変数を追加するだけで日本語のフィードバックに対応できることが確認できました。
考察
「日中の実利用ログをharvestし、夜間にmine→replay→consolidate→gateで検証つき改善を行う」という本来のワークフローは、実際に意図通り機能することを確認できました。意図的に不完全にしたSKILL.mdが、実際のClaude Code利用ログをもとに正しく学習され、held-outスコアが改善し、狙い通りの内容(Key Risks / Confidence)が実際のファイルへ反映される様子を、一連の流れとして確認できています。
特に印象的だったのは以下の点です。
- held-outゲートによる安全設計が、レポート上できちんと可視化されている(
baseline→candidateのスコア、採用/却下された編集とその理由)ため、何がどう学習されたのかを人間が容易にレビューできる - 学習内容は
<!-- SKILLOPT-SLEEP:LEARNED -->ブロックとして追記される形式になっており、元のスキル記述には一切手を加えない設計になっている - 固定ベンチマークの判定基準に頼らずとも、LLMベースの汎用的なルーブリック採点によって、狙った改善点(Key Risks/Confidence)に加えて実際のログから拾える追加の改善点まで学習対象にできる
- 日本語フィードバックのように、既定では対応していない部分も、環境変数の追加程度の設定で拡張できる柔軟性がある
固定ベンチマークでの評価だけでなく、実際に自分のClaude Code利用ログを使った検証でも、SkillOpt-Sleepの核となる主張が確認できたのは大きな収穫でした。
まとめ
- SkillOpt-Sleep本来の「harvest→mine→replay→consolidate→gate→stage→adopt」フローを、実際のClaude Code利用ログを使って検証し、意図通りの自己改善(held-outスコアの改善・具体的な編集の採用・adopt成功)を確認できました。
- 意図的に不完全にしたSKILL.mdの"Key Risks"/"Confidence"欠落が、実際のログから正しく学習され、
CLAUDE.mdへ反映される一部始終を、実際のコマンド出力とともに確認できました。 - 日本語フィードバックも、環境変数の追加設定で英語と同じように検出できることを確認しました。
- held-outゲートによる安全設計、編集内容のレビュー可能性、元のスキル記述を変更しない追記型の設計など、SkillOpt-Sleepの設計思想が実際の挙動としてもしっかり機能していることが確認できました。
さいごに
人手だとなかなか評価や改善が難しいSkillですが、SkillOpt-Sleepを利用することで日中に人のSkillの使い方やフィードバックなどのログを集めて、Skillを動かしていないときにそのログを元にAIが改善を行うという改善のループを作れます。
今利用しているSkillの品質を改善できるかどうか知りたい場合や、改善したいけど評価基準が作れない場合などには特に有用なツールだと思います。
参考資料
Skillの評価については以下の記事が特にわかりやすいのでご参照ください
