diff --git a/lib/context-zone.fixtures.mjs b/lib/context-zone.fixtures.mjs index d1a860b00c..508e489c6d 100644 --- a/lib/context-zone.fixtures.mjs +++ b/lib/context-zone.fixtures.mjs @@ -31,20 +31,20 @@ export default [ {"name":"tokens 99000+999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, {"name":"tokens 99000+1000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":1000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, {"name":"tokens 99000+1001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":1001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+9999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":9999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+10000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":10000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+10001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":10001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, + {"name":"tokens 140000+9999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":9999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 140000+10000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":10000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 140000+10001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":10001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 199000+1000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":199000,"total_output_tokens":1000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 200000+1 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":1,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, - {"name":"tokens 190000+10000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":190000,"total_output_tokens":10000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, - {"name":"tokens 200000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 399000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":399000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 400000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":400000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, + {"name":"tokens 118000+10000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":118000,"total_output_tokens":10000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, + {"name":"tokens 128000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":128000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 249000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":249000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 250000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":250000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 999000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":999000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 1000000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":1000000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, - {"name":"window 500000 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":0,"context_window_size":500000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"window 500000 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":110000,"total_output_tokens":0,"context_window_size":500000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, {"name":"window 999999 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":170000,"total_output_tokens":0,"context_window_size":999999},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, - {"name":"window 2000000 takes the 1000000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":300000,"total_output_tokens":0,"context_window_size":2000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"window 2000000 takes the 1000000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":0,"context_window_size":2000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, {"name":"window 100000 has no class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":10000,"total_output_tokens":0,"context_window_size":100000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, {"name":"window 0 is not computable","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":0,"total_output_tokens":0,"context_window_size":0},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, {"name":"negative input tokens","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":-1,"total_output_tokens":0,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, diff --git a/lib/context-zone.sh b/lib/context-zone.sh index f0e4f31603..f31dcdb5a2 100755 --- a/lib/context-zone.sh +++ b/lib/context-zone.sh @@ -52,8 +52,8 @@ # smart ≤ 50 < acceptable ≤ 75 < dumb over used_percentage, and per # window-class token bands over occupancy: # -# window class 200000: smart ≤ 100000 < acceptable ≤ 160000 < dumb -# window class 1000000: smart ≤ 200000 < acceptable ≤ 400000 < dumb +# window class 200000: smart ≤ 100000 < acceptable ≤ 150000 < dumb +# window class 1000000: smart ≤ 128000 < acceptable ≤ 250000 < dumb # # All are declared judgment defaults, NOT doc- or benchmark-derived # constants (anchors and provenance are recorded in the reader contract). @@ -63,8 +63,8 @@ # "smart_max_used_percentage": 50, # "acceptable_max_used_percentage": 75, # "token_bands": { -# "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 160000 }, -# "1000000": { "smart_max_tokens": 200000, "acceptable_max_tokens": 400000 } +# "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 150000 }, +# "1000000": { "smart_max_tokens": 128000, "acceptable_max_tokens": 250000 } # } # } # @@ -92,7 +92,7 @@ DEFAULT_ACCEPTABLE_MAX=75 # [class, smart_max, acceptable_max] rows, ascending class order. JSON rather # than whitespace rows because the bands are handed to the snapshot pass as # data, so the comparison happens there instead of in a separate awk process. -DEFAULT_TOKEN_BANDS='[[200000,100000,160000],[1000000,200000,400000]]' +DEFAULT_TOKEN_BANDS='[[200000,100000,150000],[1000000,128000,250000]]' unknown() { printf 'unknown\n' @@ -197,7 +197,7 @@ if [[ -e "$zones" ]]; then acceptable_max=${zpct#* } fi if [[ "$ztb" == "invalid" ]]; then - printf 'context-guard: zones.json token_bands malformed — using shipped default token bands (200000:100000/160000, 1000000:200000/400000)\n' >&2 + printf 'context-guard: zones.json token_bands malformed — using shipped default token bands (200000:100000/150000, 1000000:128000/250000)\n' >&2 elif [[ "$ztb" != "absent" ]]; then token_bands=$ztb fi diff --git a/plugins/context-guard/.claude-plugin/plugin.json b/plugins/context-guard/.claude-plugin/plugin.json index e587489b8e..f48d2c6501 100644 --- a/plugins/context-guard/.claude-plugin/plugin.json +++ b/plugins/context-guard/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "context-guard", - "version": "0.12.3", + "version": "0.13.0", "description": "Per-session context-window observability. A mod writes each session's context-window figures to a snapshot file and tells Claude its context zone (smart, acceptable or dumb, from bands in zones.json) at each crossing, approach and compaction; the person gets a toast and a transcript line. /context-guard prints status and toggles an optional band row. It answers a status tool. Optional blocking mode gates new mutating work in a blocked zone, except handoffs. A PostCompact hook leaves a marker.", "author": { "name": "Melodic Software", diff --git a/plugins/context-guard/CHANGELOG.md b/plugins/context-guard/CHANGELOG.md index bdd8bf3fe3..b203f8f0a9 100644 --- a/plugins/context-guard/CHANGELOG.md +++ b/plugins/context-guard/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to the `context-guard` plugin. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.13.0] - 2026-10-04 + +### Changed + +- **Tighter shipped token bands.** On a 1M-token window a session now leaves `smart` above 128,000 tokens (was 200,000) and reads `dumb` above 250,000 (was 400,000); on a 200k window `dumb` starts above 150,000 (was 160,000). Percent bands stay at 50/75 and the worse of the two still decides. 128K is the last length at which a current Claude model was measured strong on long-context retrieval; the reader contract records the basis. Set `token_bands` in `zones.json` to keep the old edges. + ## [0.12.3] - 2026-10-04 ### Changed diff --git a/plugins/context-guard/README.md b/plugins/context-guard/README.md index 25e7fb81e8..bbc76b0de8 100644 --- a/plugins/context-guard/README.md +++ b/plugins/context-guard/README.md @@ -13,8 +13,8 @@ degraded context **before** quality slips, instead of guessing. Four parts: word: `smart` / `acceptable` / `dumb` / `unknown`. Two band shapes, combined conservatively (the worse computable zone wins): percentage bands over `used_percentage` (shipped defaults smart ≤ 50 < acceptable ≤ 75 < dumb) and window-class token bands over occupancy - (`total_input_tokens + total_output_tokens`; shipped defaults 100k/160k on a 200k window, - 200k/400k on a 1M window). Bands come from the machine-scope + (`total_input_tokens + total_output_tokens`; shipped defaults 100k/150k on a 200k window, + 128k/250k on a 1M window). Bands come from the machine-scope `~/.claude/context-guard/zones.json` when present and valid, else from the shipped defaults. Zones say *where you are*; consumers decide *what to do*. - **PostCompact marker hook** (`hooks/post-compact-mark.sh`), a settings hook, so it runs where diff --git a/plugins/context-guard/hooks/context-guard.test.ts b/plugins/context-guard/hooks/context-guard.test.ts index e7033f8824..9c15b24dad 100644 --- a/plugins/context-guard/hooks/context-guard.test.ts +++ b/plugins/context-guard/hooks/context-guard.test.ts @@ -1283,7 +1283,7 @@ test('command: no argument prints the status and details', BLOCKING(7), async ($ '60% of a 200000-token window used (120000 tokens)', // The token band of the session's window class is shown beside the percent band, since the // worse of the two decides the zone. - 'Bands (the worse decides): smart up to 50% and 100000 tokens, acceptable up to 75% and 160000 tokens', + 'Bands (the worse decides): smart up to 50% and 100000 tokens, acceptable up to 75% and 150000 tokens', 'approach margin 4 points', 'gate blocking, 7 grace calls', 'band row off', @@ -1379,7 +1379,7 @@ test('pull tool: the latest figures and zone, with no line attached, whatever th total_input_tokens: 120_000, total_output_tokens: 900, context_window_size: 200_000, - bands: { smart_max_used_percentage: 50, acceptable_max_used_percentage: 75, smart_max_tokens: 100_000, acceptable_max_tokens: 160_000 }, + bands: { smart_max_used_percentage: 50, acceptable_max_used_percentage: 75, smart_max_tokens: 100_000, acceptable_max_tokens: 150_000 }, approach_margin: 5, gate: { mode: 'advisory', grace_calls: 20, calls_counted: 0 }, }) diff --git a/plugins/context-guard/hooks/zone.ts b/plugins/context-guard/hooks/zone.ts index 9e6610aeef..0f04dbd608 100644 --- a/plugins/context-guard/hooks/zone.ts +++ b/plugins/context-guard/hooks/zone.ts @@ -12,8 +12,8 @@ export const DEFAULT_BANDS: Bands = { smart: 50, acceptable: 75, tokens: [ - [200_000, 100_000, 160_000], - [1_000_000, 200_000, 400_000], + [200_000, 100_000, 150_000], + [1_000_000, 128_000, 250_000], ], } export const RANK: Record = { smart: 0, acceptable: 1, dumb: 2 } diff --git a/plugins/context-guard/reference/reader-contract.md b/plugins/context-guard/reference/reader-contract.md index efcc871e4a..452c801ee9 100644 --- a/plugins/context-guard/reference/reader-contract.md +++ b/plugins/context-guard/reference/reader-contract.md @@ -58,8 +58,8 @@ same triggers. These stamps are probe results with a date, not standing facts. Zones below). - **Default token bands (over occupancy = `total_input_tokens` + `total_output_tokens`, uppers inclusive, selected by window class as described under "Occupancy and combination rule"):** - window class **200000**: `smart` ≤ **100000** < `acceptable` ≤ **160000** < `dumb`; - window class **1000000**: `smart` ≤ **200000** < `acceptable` ≤ **400000** < `dumb`. + window class **200000**: `smart` ≤ **100000** < `acceptable` ≤ **150000** < `dumb`; + window class **1000000**: `smart` ≤ **128000** < `acceptable` ≤ **250000** < `dumb`. - **Token-shape version floor (fixed):** the token shape is computable only when the snapshot's `cli_version` is present, purely numeric dotted, and **≥ 2.1.132**, the release from which the token fields mean current occupancy rather than cumulative session totals. @@ -225,12 +225,29 @@ also marks the token shape not-computable**. That is corrupt or forged data, and a version field cannot (there is no writer authentication, so `cli_version` is untrusted like every other snapshot value). The bundled resolver implements both gates. -**Band provenance:** all shipped band numbers are **declared judgment defaults with named -anchors**, not benchmark-derived constants. The 1M row's anchor is an informal range a named staff -member gave and hedged as task-dependent; the 200k row is declared judgment near practitioner -folklore values, but deliberately below them. Both rows carry equally low confidence; -`zones.json` is the correction path, and the numeric agreement of the 200k row's percentage -translation with the shipped 50/75 percentage defaults is coincidence, not validation. +**Band provenance:** the shipped token bands are **declared judgment anchored on measured +data**, not benchmark-derived constants. The 1M row's `smart` edge, 128000, is the last measured +strong point for a current Claude model on long-context retrieval (Claude Opus 5 (max), 8-needle +MRCR: 91.3% at 128K; AUC 97.5% to 128K, 45.7% to 1M). Its `acceptable` edge, 250000, is judgment +between that point and a 300K cap in practice. The 200k row's `acceptable` edge, 150000, sits at +the top of the practitioner consensus of about 125-150K. `zones.json` is the correction path, and +the numeric agreement of the 200k row's percentage translation with the shipped 50/75 percentage +defaults is coincidence, not validation. + +- **Pointer**: when re-deriving a band edge, fetch live: the 1M `smart` edge, + [Context Arena, 8 needles](https://contextarena.ai/?needles=8), Claude Opus 5 (max) row; the 1M + `acceptable` edge's cap, [Cursor's Claude Opus 5.5 page](https://cursor.com/docs/models/claude-opus-5-5), + "Context window" field; the absence of per-length data, the + [Opus 5.5 system card](https://www-cdn.anthropic.com/fc1b44717c85dc068bc6ba5024219938094694bd/Claude%20Opus%205.5%20System%20Card.pdf) + section 8.10 and the [Fable 5.1 system card](https://www-cdn.anthropic.com/0339e6a7c5c7b87f5c07798616dc32c215d14235/Claude%20Fable%205.1%20&%20Claude%20Mythos%205.1%20System%20Card.pdf) + section 8.11. For the 200k row, correlate with [AI Hero, "Smart Zone"](https://www.aihero.dev/ai-coding-dictionary/smart-zone) + and [Geoffrey Huntley, "Ralph"](https://ghuntley.com/ralph/); no docs page covers where quality + degrades on a 200K window as of 2026-10-04. +- **As of**: 2026-10-04 +- **Recheck trigger**: Opus 5.5, Fable 5.1 or Sonnet 5.5 appear on Context Arena; a new or revised + Anthropic system card publishes per-length scores; Cursor changes Opus 5.5's default context + window; or a docs page starts covering where quality degrades on a 200K window, at which point the + 200k row's pointer moves there. ## The module (first shipped consumer) @@ -434,10 +451,10 @@ on the session's behalf and the boundary was reached too late. Auto-compact offe hook, so a firing is best read diagnostically: **it means the boundary was missed**, not that the window was managed. Lowering the window moves the trigger, so the bands in `zones.json` must move with it, normalized into the percentage shape. A 400000-token window on a 1M-class model puts the -trigger at **40% of the full window**, which is *inside* the shipped `smart` band (≤ 50), so -auto-compact would fire while every zone still reads green. Keeping bands below that trigger means -pulling the percentage bands under 40, not comparing 400000 against the same-looking `dumb` -occupancy number. Those two 400000s are different quantities. +trigger at **40% of the full window**, which is *inside* the shipped percentage `smart` band +(≤ 50), so the percentage shape still reads smart when auto-compact fires (the token shape decides +the zone there). Keeping the percentage bands below that trigger means pulling them under 40, not +comparing 400000 against the token bands' occupancy edges, which measure a different quantity. That diagnostic reading is adopted; the prescription that usually travels with it is not. **Leave auto-compact enabled.** Disabling it is a defensible operator choice on an attended machine, but it @@ -482,8 +499,8 @@ what the human sees and what consumers decide on. Zones say *where you are*; con "smart_max_used_percentage": 50, "acceptable_max_used_percentage": 75, "token_bands": { - "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 160000 }, - "1000000": { "smart_max_tokens": 200000, "acceptable_max_tokens": 400000 } + "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 150000 }, + "1000000": { "smart_max_tokens": 128000, "acceptable_max_tokens": 250000 } } } ``` diff --git a/plugins/context-guard/scripts/context-zone.fixtures.mjs b/plugins/context-guard/scripts/context-zone.fixtures.mjs index 3d364b060b..815c045ab1 100644 --- a/plugins/context-guard/scripts/context-zone.fixtures.mjs +++ b/plugins/context-guard/scripts/context-zone.fixtures.mjs @@ -33,20 +33,20 @@ export default [ {"name":"tokens 99000+999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, {"name":"tokens 99000+1000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":1000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, {"name":"tokens 99000+1001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":1001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+9999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":9999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+10000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":10000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+10001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":10001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, + {"name":"tokens 140000+9999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":9999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 140000+10000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":10000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 140000+10001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":10001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 199000+1000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":199000,"total_output_tokens":1000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 200000+1 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":1,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, - {"name":"tokens 190000+10000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":190000,"total_output_tokens":10000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, - {"name":"tokens 200000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 399000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":399000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 400000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":400000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, + {"name":"tokens 118000+10000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":118000,"total_output_tokens":10000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, + {"name":"tokens 128000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":128000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 249000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":249000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 250000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":250000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 999000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":999000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 1000000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":1000000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, - {"name":"window 500000 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":0,"context_window_size":500000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"window 500000 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":110000,"total_output_tokens":0,"context_window_size":500000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, {"name":"window 999999 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":170000,"total_output_tokens":0,"context_window_size":999999},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, - {"name":"window 2000000 takes the 1000000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":300000,"total_output_tokens":0,"context_window_size":2000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"window 2000000 takes the 1000000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":0,"context_window_size":2000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, {"name":"window 100000 has no class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":10000,"total_output_tokens":0,"context_window_size":100000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, {"name":"window 0 is not computable","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":0,"total_output_tokens":0,"context_window_size":0},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, {"name":"negative input tokens","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":-1,"total_output_tokens":0,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, diff --git a/plugins/context-guard/scripts/context-zone.sh b/plugins/context-guard/scripts/context-zone.sh index 9856066bb8..3ae893e045 100755 --- a/plugins/context-guard/scripts/context-zone.sh +++ b/plugins/context-guard/scripts/context-zone.sh @@ -54,8 +54,8 @@ # smart ≤ 50 < acceptable ≤ 75 < dumb over used_percentage, and per # window-class token bands over occupancy: # -# window class 200000: smart ≤ 100000 < acceptable ≤ 160000 < dumb -# window class 1000000: smart ≤ 200000 < acceptable ≤ 400000 < dumb +# window class 200000: smart ≤ 100000 < acceptable ≤ 150000 < dumb +# window class 1000000: smart ≤ 128000 < acceptable ≤ 250000 < dumb # # All are declared judgment defaults, NOT doc- or benchmark-derived # constants (anchors and provenance are recorded in the reader contract). @@ -65,8 +65,8 @@ # "smart_max_used_percentage": 50, # "acceptable_max_used_percentage": 75, # "token_bands": { -# "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 160000 }, -# "1000000": { "smart_max_tokens": 200000, "acceptable_max_tokens": 400000 } +# "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 150000 }, +# "1000000": { "smart_max_tokens": 128000, "acceptable_max_tokens": 250000 } # } # } # @@ -94,7 +94,7 @@ DEFAULT_ACCEPTABLE_MAX=75 # [class, smart_max, acceptable_max] rows, ascending class order. JSON rather # than whitespace rows because the bands are handed to the snapshot pass as # data, so the comparison happens there instead of in a separate awk process. -DEFAULT_TOKEN_BANDS='[[200000,100000,160000],[1000000,200000,400000]]' +DEFAULT_TOKEN_BANDS='[[200000,100000,150000],[1000000,128000,250000]]' unknown() { printf 'unknown\n' @@ -199,7 +199,7 @@ if [[ -e "$zones" ]]; then acceptable_max=${zpct#* } fi if [[ "$ztb" == "invalid" ]]; then - printf 'context-guard: zones.json token_bands malformed — using shipped default token bands (200000:100000/160000, 1000000:200000/400000)\n' >&2 + printf 'context-guard: zones.json token_bands malformed — using shipped default token bands (200000:100000/150000, 1000000:128000/250000)\n' >&2 elif [[ "$ztb" != "absent" ]]; then token_bands=$ztb fi diff --git a/plugins/context-guard/scripts/context-zone.test.sh b/plugins/context-guard/scripts/context-zone.test.sh index b51b715274..544ced7740 100755 --- a/plugins/context-guard/scripts/context-zone.test.sh +++ b/plugins/context-guard/scripts/context-zone.test.sh @@ -177,13 +177,13 @@ write_snapshot_tok() { HT="$WORK/h-token" # Token shape stands alone when used_percentage is null but tokens are valid. -write_snapshot_tok "$HT" t1 null 150000 10000 1000000 && expect "tokens alone: occ=160k on 1M" smart "$HT" t1 -write_snapshot_tok "$HT" t2 null 280000 20000 1000000 && expect "tokens alone: occ=300k on 1M" acceptable "$HT" t2 -write_snapshot_tok "$HT" t3 null 390000 10001 1000000 && expect "tokens alone: occ=400001 on 1M" dumb "$HT" t3 +write_snapshot_tok "$HT" t1 null 110000 10000 1000000 && expect "tokens alone: occ=120k on 1M" smart "$HT" t1 +write_snapshot_tok "$HT" t2 null 180000 20000 1000000 && expect "tokens alone: occ=200k on 1M" acceptable "$HT" t2 +write_snapshot_tok "$HT" t3 null 240000 10001 1000000 && expect "tokens alone: occ=250001 on 1M" dumb "$HT" t3 # Shipped 200k-class edges, uppers inclusive. write_snapshot_tok "$HT" t4 null 90000 10000 200000 && expect "200k class: occ=100000 (smart edge)" smart "$HT" t4 -write_snapshot_tok "$HT" t5 null 150000 10000 200000 && expect "200k class: occ=160000 (acceptable edge)" acceptable "$HT" t5 -write_snapshot_tok "$HT" t6 null 150001 10000 200000 && expect "200k class: occ=160001" dumb "$HT" t6 +write_snapshot_tok "$HT" t5 null 140000 10000 200000 && expect "200k class: occ=150000 (acceptable edge)" acceptable "$HT" t5 +write_snapshot_tok "$HT" t6 null 140001 10000 200000 && expect "200k class: occ=150001" dumb "$HT" t6 # Combination rule: the worse of the two computable shapes wins. write_snapshot_tok "$HT" c1 40 150000 20000 200000 && expect "pct smart + tokens dumb → dumb" dumb "$HT" c1 write_snapshot_tok "$HT" c2 80 40000 10000 200000 && expect "pct dumb + tokens smart → dumb" dumb "$HT" c2 diff --git a/plugins/context-guard/skills/setup/SKILL.md b/plugins/context-guard/skills/setup/SKILL.md index e5dc7058ad..9534494a98 100644 --- a/plugins/context-guard/skills/setup/SKILL.md +++ b/plugins/context-guard/skills/setup/SKILL.md @@ -176,8 +176,8 @@ The `defaults` argument changes only how a present file is treated: "smart_max_used_percentage": 50, "acceptable_max_used_percentage": 75, "token_bands": { - "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 160000 }, - "1000000": { "smart_max_tokens": 200000, "acceptable_max_tokens": 400000 } + "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 150000 }, + "1000000": { "smart_max_tokens": 128000, "acceptable_max_tokens": 250000 } } } ``` diff --git a/plugins/plugin-quality/.claude-plugin/plugin.json b/plugins/plugin-quality/.claude-plugin/plugin.json index 8fed08cb44..b3a54f14fd 100644 --- a/plugins/plugin-quality/.claude-plugin/plugin.json +++ b/plugins/plugin-quality/.claude-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "plugin-quality", - "version": "0.13.7", + "version": "0.13.8", "description": "Post-use behavioral audit (plugin-quality:audit) of any Claude Code plugin skill, agent, hook, command, or config you have used. Six steps: capture evidence; map behavior in a fresh subagent that records errors, improvements, and quality-of-life items against standards; a blindspot pass; an interactive contract lock; review with a research gate on each finding's claims and fixes; and a confirmed work item for the maintainers. Uses context-guard snapshots when present.", "author": { "name": "Melodic Software", diff --git a/plugins/plugin-quality/CHANGELOG.md b/plugins/plugin-quality/CHANGELOG.md index 1007c4dc8c..2ecc5b2215 100644 --- a/plugins/plugin-quality/CHANGELOG.md +++ b/plugins/plugin-quality/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to the `plugin-quality` plugin. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.13.8] - 2026-10-04 + +### Changed + +- **Shared `context-zone.sh` resolver synced to context-guard's tighter token bands.** Shipped defaults are now 100000/150000 on a 200000 window and 128000/250000 on a 1000000 window; the resolver tests and the zones inline-drift check follow. + ## [0.13.7] - 2026-10-04 ### Changed diff --git a/plugins/plugin-quality/scripts/context-zone.fixtures.mjs b/plugins/plugin-quality/scripts/context-zone.fixtures.mjs index 3d364b060b..815c045ab1 100644 --- a/plugins/plugin-quality/scripts/context-zone.fixtures.mjs +++ b/plugins/plugin-quality/scripts/context-zone.fixtures.mjs @@ -33,20 +33,20 @@ export default [ {"name":"tokens 99000+999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, {"name":"tokens 99000+1000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":1000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, {"name":"tokens 99000+1001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":99000,"total_output_tokens":1001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+9999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":9999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+10000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":10000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 150000+10001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":10001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, + {"name":"tokens 140000+9999 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":9999,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 140000+10000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":10000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 140000+10001 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":140000,"total_output_tokens":10001,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 199000+1000 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":199000,"total_output_tokens":1000,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 200000+1 in 200000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":1,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, - {"name":"tokens 190000+10000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":190000,"total_output_tokens":10000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, - {"name":"tokens 200000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 399000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":399000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, - {"name":"tokens 400000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":400000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, + {"name":"tokens 118000+10000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":118000,"total_output_tokens":10000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"smart","notices":[]}, + {"name":"tokens 128000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":128000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 249000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":249000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"tokens 250000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":250000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 999000+1000 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":999000,"total_output_tokens":1000,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, {"name":"tokens 1000000+1 in 1000000","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":1000000,"total_output_tokens":1,"context_window_size":1000000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, - {"name":"window 500000 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":150000,"total_output_tokens":0,"context_window_size":500000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"window 500000 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":110000,"total_output_tokens":0,"context_window_size":500000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, {"name":"window 999999 takes the 200000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":170000,"total_output_tokens":0,"context_window_size":999999},"cli_version":"2.1.200"},"zones":null,"word":"dumb","notices":[]}, - {"name":"window 2000000 takes the 1000000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":300000,"total_output_tokens":0,"context_window_size":2000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, + {"name":"window 2000000 takes the 1000000 class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":200000,"total_output_tokens":0,"context_window_size":2000000},"cli_version":"2.1.200"},"zones":null,"word":"acceptable","notices":[]}, {"name":"window 100000 has no class","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":10000,"total_output_tokens":0,"context_window_size":100000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, {"name":"window 0 is not computable","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":0,"total_output_tokens":0,"context_window_size":0},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, {"name":"negative input tokens","sid":"s1","snapshot":{"captured_at":"@now-30","session_id":"s1","context_window":{"used_percentage":null,"remaining_percentage":80,"current_usage":{"input_tokens":100},"total_input_tokens":-1,"total_output_tokens":0,"context_window_size":200000},"cli_version":"2.1.200"},"zones":null,"word":"unknown","notices":[]}, diff --git a/plugins/plugin-quality/scripts/context-zone.sh b/plugins/plugin-quality/scripts/context-zone.sh index 9856066bb8..3ae893e045 100755 --- a/plugins/plugin-quality/scripts/context-zone.sh +++ b/plugins/plugin-quality/scripts/context-zone.sh @@ -54,8 +54,8 @@ # smart ≤ 50 < acceptable ≤ 75 < dumb over used_percentage, and per # window-class token bands over occupancy: # -# window class 200000: smart ≤ 100000 < acceptable ≤ 160000 < dumb -# window class 1000000: smart ≤ 200000 < acceptable ≤ 400000 < dumb +# window class 200000: smart ≤ 100000 < acceptable ≤ 150000 < dumb +# window class 1000000: smart ≤ 128000 < acceptable ≤ 250000 < dumb # # All are declared judgment defaults, NOT doc- or benchmark-derived # constants (anchors and provenance are recorded in the reader contract). @@ -65,8 +65,8 @@ # "smart_max_used_percentage": 50, # "acceptable_max_used_percentage": 75, # "token_bands": { -# "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 160000 }, -# "1000000": { "smart_max_tokens": 200000, "acceptable_max_tokens": 400000 } +# "200000": { "smart_max_tokens": 100000, "acceptable_max_tokens": 150000 }, +# "1000000": { "smart_max_tokens": 128000, "acceptable_max_tokens": 250000 } # } # } # @@ -94,7 +94,7 @@ DEFAULT_ACCEPTABLE_MAX=75 # [class, smart_max, acceptable_max] rows, ascending class order. JSON rather # than whitespace rows because the bands are handed to the snapshot pass as # data, so the comparison happens there instead of in a separate awk process. -DEFAULT_TOKEN_BANDS='[[200000,100000,160000],[1000000,200000,400000]]' +DEFAULT_TOKEN_BANDS='[[200000,100000,150000],[1000000,128000,250000]]' unknown() { printf 'unknown\n' @@ -199,7 +199,7 @@ if [[ -e "$zones" ]]; then acceptable_max=${zpct#* } fi if [[ "$ztb" == "invalid" ]]; then - printf 'context-guard: zones.json token_bands malformed — using shipped default token bands (200000:100000/160000, 1000000:200000/400000)\n' >&2 + printf 'context-guard: zones.json token_bands malformed — using shipped default token bands (200000:100000/150000, 1000000:128000/250000)\n' >&2 elif [[ "$ztb" != "absent" ]]; then token_bands=$ztb fi diff --git a/plugins/plugin-quality/scripts/context-zone.test.sh b/plugins/plugin-quality/scripts/context-zone.test.sh index b51b715274..544ced7740 100755 --- a/plugins/plugin-quality/scripts/context-zone.test.sh +++ b/plugins/plugin-quality/scripts/context-zone.test.sh @@ -177,13 +177,13 @@ write_snapshot_tok() { HT="$WORK/h-token" # Token shape stands alone when used_percentage is null but tokens are valid. -write_snapshot_tok "$HT" t1 null 150000 10000 1000000 && expect "tokens alone: occ=160k on 1M" smart "$HT" t1 -write_snapshot_tok "$HT" t2 null 280000 20000 1000000 && expect "tokens alone: occ=300k on 1M" acceptable "$HT" t2 -write_snapshot_tok "$HT" t3 null 390000 10001 1000000 && expect "tokens alone: occ=400001 on 1M" dumb "$HT" t3 +write_snapshot_tok "$HT" t1 null 110000 10000 1000000 && expect "tokens alone: occ=120k on 1M" smart "$HT" t1 +write_snapshot_tok "$HT" t2 null 180000 20000 1000000 && expect "tokens alone: occ=200k on 1M" acceptable "$HT" t2 +write_snapshot_tok "$HT" t3 null 240000 10001 1000000 && expect "tokens alone: occ=250001 on 1M" dumb "$HT" t3 # Shipped 200k-class edges, uppers inclusive. write_snapshot_tok "$HT" t4 null 90000 10000 200000 && expect "200k class: occ=100000 (smart edge)" smart "$HT" t4 -write_snapshot_tok "$HT" t5 null 150000 10000 200000 && expect "200k class: occ=160000 (acceptable edge)" acceptable "$HT" t5 -write_snapshot_tok "$HT" t6 null 150001 10000 200000 && expect "200k class: occ=160001" dumb "$HT" t6 +write_snapshot_tok "$HT" t5 null 140000 10000 200000 && expect "200k class: occ=150000 (acceptable edge)" acceptable "$HT" t5 +write_snapshot_tok "$HT" t6 null 140001 10000 200000 && expect "200k class: occ=150001" dumb "$HT" t6 # Combination rule: the worse of the two computable shapes wins. write_snapshot_tok "$HT" c1 40 150000 20000 200000 && expect "pct smart + tokens dumb → dumb" dumb "$HT" c1 write_snapshot_tok "$HT" c2 80 40000 10000 200000 && expect "pct dumb + tokens smart → dumb" dumb "$HT" c2 diff --git a/plugins/plugin-quality/scripts/zones-inline-drift.test.sh b/plugins/plugin-quality/scripts/zones-inline-drift.test.sh index e754a5adc1..96a8a48a78 100755 --- a/plugins/plugin-quality/scripts/zones-inline-drift.test.sh +++ b/plugins/plugin-quality/scripts/zones-inline-drift.test.sh @@ -74,8 +74,8 @@ resolver_and_contract "staleness window (10 minutes)" "10 minutes" resolver_and_contract "snapshot path pattern" "~/.claude/context-guard/context/.json" resolver_and_contract "zones file path" "~/.claude/context-guard/zones.json" resolver_and_contract "percentage floor" "smart ≤ 50 < acceptable ≤ 75 < dumb" -resolver_and_contract "200k-class token band" "200000: smart ≤ 100000 < acceptable ≤ 160000 < dumb" -resolver_and_contract "1M-class token band" "1000000: smart ≤ 200000 < acceptable ≤ 400000 < dumb" +resolver_and_contract "200k-class token band" "200000: smart ≤ 100000 < acceptable ≤ 150000 < dumb" +resolver_and_contract "1M-class token band" "1000000: smart ≤ 128000 < acceptable ≤ 250000 < dumb" resolver_and_contract "occupancy definition" "total_input_tokens + total_output_tokens" resolver_and_contract "token-shape version floor" "cli_version" resolver_and_contract "token-shape version floor value" "2.1.132"