Skip to content

feat(snowball): baseline 差し引き + 最小ターン数ゲートで heavy-context 起動時の誤発火を抑止#5

Merged
akihidem merged 1 commit into
mainfrom
feat/snowball-baseline-and-minturns
May 11, 2026
Merged

feat(snowball): baseline 差し引き + 最小ターン数ゲートで heavy-context 起動時の誤発火を抑止#5
akihidem merged 1 commit into
mainfrom
feat/snowball-baseline-and-minturns

Conversation

@akihidem
Copy link
Copy Markdown
Owner

なぜ

SessionStart フックや CLAUDE.md / MEMORY.md / system prompt 注入が重い環境では、Claude Code セッションの 1 ターン目から cache_creation_input_tokens だけで 200–300k token を消費する。従来の detectSnowballcumulativeUncached を直接閾値 (snowballToken=150_000) と比較していたため、実作業が 1 件も無い起動直後の get_recommended_action 呼び出しで create_handoff を推奨してしまう 誤発火が発生していた(今回のセッションで実際に観測、cumulative_kt=307 / threshold=150)。

snowball の本来の目的は「会話を進めるうちに context が膨らんで Lost-in-the-middle になっているセッションを検出する」こと。初期コストはこの目的に含まれない

何を

  • detectSnowball を「成長分(growth above baseline)」ベースに変更
    • 最初のサンプルの tokens.cacheCreation を baseline として控除
    • growth = latest.cumulativeUncached - baseline を閾値と比較
  • 新しい設定 thresholds.snowballMinTurns(既定 3)を追加
    • assistant ターン数が snowballMinTurns 未満なら閾値超でも triggered=false
  • SnowballStatebaselineTokens / turns / minTurns を追加(観測性)
  • mcp/tools.tswatch.tsdetectSnowball 呼び出しに snowballMinTurns を伝搬
  • tests/snowball.test.ts を新規追加(5 ケース、heavy-context 起動の再現含む)

設計判断

  • なぜ baseline を「最初のサンプルの cache_creation」にしたか — Claude Code は 1 ターン目で system prompt + CLAUDE.md + SessionStart hook 注入を cache 化するため、ここに「環境固有の初期コスト」が集約される。2 ターン目以降の cache_creation は実会話で新しく追加された context のみなので、純粋な成長分として扱える。
  • なぜ cumulativeUncached - baselineMath.max(0, ...) でクランプするか — 異常データ(タイムスタンプ逆順、Claude Code 側のログ書き込み事故など)で負になっても閾値判定で誤動作しないため。
  • なぜ minTurns=3 を既定値にしたか — 1 ターンでは baseline しか無いので growth=0、2 ターンでは「最初のユーザー応答」だけで判定するには情報が浅い。3 ターンあれば「context が積み上がってるか」を見るには十分。bigger デフォルトはバックテストで決める余地あり(scripts/backtest-snowball.ts)。
  • 既存テストへの影響なしdetectSnowball の第 3 引数はデフォルト値 (3) 付きで追加したので、内部 API 互換性は保たれる。MCP / watch から呼ぶ箇所は明示的に config から渡す形に更新。

スコープ外

  • バックテスト (scripts/backtest-snowball.ts) の再実行と閾値の再キャリブレーション — 別 PR でやる
  • cogsync-cli@alpha の次バージョン publish — リリース PR で扱う
  • ccusage 側の cumulative メトリクス変更 — ccusage はセッション単位ではなく 5h ブロック単位なので無関係

検証方法

  • npm run typecheck パス
  • npm test パス(既存 16 + 新規 5 = 21 件)
  • 「初手 cache_creation 307k のみ・1 ターン」のサンプルで triggered=false を確認(新規テスト heavy SessionStart で初手 300k でも 1 ターンなら誤発火しない
  • MCP サーバ再起動後、ユーザー環境の get_recommended_action が起動直後に create_handoff を返さないこと
  • 既存ユーザーの過去 30 日セッションを backtest-snowball.ts で再評価し、新ロジックでの triggered 率分布を確認(別 PR)

依存

  • ランタイム依存の変更なし
  • ~/.config/cogsync/config.yaml 既存ファイルとの後方互換性あり(snowballMinTurns 未指定なら既定値 3 を使う)
  • DEFAULT_CONFIG のみの変更なので migration 不要

🤖 Generated with Claude Code

SessionStart フックや MEMORY.md 自動注入で起動直後から数百 k token を
消費する環境では、従来の単純な cumulativeUncached 閾値判定だと
1 ターン目から snowball_detected が誤発火していた。

- 最初の assistant サンプルの cache_creation を baseline として控除し
  「成長分」を閾値と比較する
- snowballMinTurns(既定 3)未満なら閾値超でも triggered=false
- SnowballState に baselineTokens / turns / minTurns を追加(観測性向上)
- detectSnowball のユニットテストを新規追加(5 ケース)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@akihidem akihidem merged commit 4e78d2a into main May 11, 2026
2 checks passed
@akihidem akihidem deleted the feat/snowball-baseline-and-minturns branch May 11, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant