feat(snowball): baseline 差し引き + 最小ターン数ゲートで heavy-context 起動時の誤発火を抑止#5
Merged
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
なぜ
SessionStart フックや CLAUDE.md / MEMORY.md / system prompt 注入が重い環境では、Claude Code セッションの 1 ターン目から
cache_creation_input_tokensだけで 200–300k token を消費する。従来のdetectSnowballはcumulativeUncachedを直接閾値 (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)を追加snowballMinTurns未満なら閾値超でもtriggered=falseSnowballStateにbaselineTokens/turns/minTurnsを追加(観測性)mcp/tools.tsとwatch.tsのdetectSnowball呼び出しにsnowballMinTurnsを伝搬tests/snowball.test.tsを新規追加(5 ケース、heavy-context 起動の再現含む)設計判断
cache_creationは実会話で新しく追加された context のみなので、純粋な成長分として扱える。cumulativeUncached - baselineをMath.max(0, ...)でクランプするか — 異常データ(タイムスタンプ逆順、Claude Code 側のログ書き込み事故など)で負になっても閾値判定で誤動作しないため。detectSnowballの第 3 引数はデフォルト値 (3) 付きで追加したので、内部 API 互換性は保たれる。MCP / watch から呼ぶ箇所は明示的に config から渡す形に更新。スコープ外
scripts/backtest-snowball.ts) の再実行と閾値の再キャリブレーション — 別 PR でやるcogsync-cli@alphaの次バージョン publish — リリース PR で扱う検証方法
npm run typecheckパスnpm testパス(既存 16 + 新規 5 = 21 件)triggered=falseを確認(新規テストheavy SessionStart で初手 300k でも 1 ターンなら誤発火しない)get_recommended_actionが起動直後にcreate_handoffを返さないことbacktest-snowball.tsで再評価し、新ロジックでの triggered 率分布を確認(別 PR)依存
~/.config/cogsync/config.yaml既存ファイルとの後方互換性あり(snowballMinTurns未指定なら既定値 3 を使う)🤖 Generated with Claude Code