johns-harness 2026.9.35 → 2026.9.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/auth-profiles-5CHn7vq1.js +20 -1
  3. package/dist/channels/plugins/actions/telegram.js +1 -0
  4. package/dist/config-koj5M_EO.js +20 -1
  5. package/dist/daemon-cli.js +20 -1
  6. package/dist/model-selection-BGlGpPgM.js +20 -1
  7. package/dist/model-selection-BU6wl1le.js +20 -1
  8. package/dist/model-selection-L7RMwsG-.js +20 -1
  9. package/dist/models-config-CAmcg63r.js +38 -1
  10. package/dist/models-config-DXA5BkaM.js +38 -1
  11. package/dist/plugin-sdk/config-4Fgm-yEH.js +20 -1
  12. package/dist/plugin-sdk/config-Di-lyCdh.js +20 -1
  13. package/dist/plugin-sdk/discord.js +20 -1
  14. package/dist/plugin-sdk/mattermost.js +1 -0
  15. package/dist/plugin-sdk/model-auth-CX9cPHdC.js +20 -1
  16. package/dist/plugin-sdk/model-auth-Ciehz0x5.js +20 -1
  17. package/dist/plugin-sdk/model-auth-DVyo6JSX.js +20 -1
  18. package/dist/plugin-sdk/model-auth-kiHYHGrs.js +20 -1
  19. package/dist/plugin-sdk/model-selection-Dbj4jDYM.js +20 -1
  20. package/dist/plugin-sdk/thinking-B-rIrY_n.js +1 -0
  21. package/dist/plugin-sdk/thinking-CopbP_Cn.js +1 -0
  22. package/dist/plugin-sdk/thinking-WQ4Zq8Nl.js +1 -0
  23. package/dist/plugin-sdk/thinking-WXqkGljb.js +1 -0
  24. package/dist/plugin-sdk/thinking-_uXqFaFO.js +1 -0
  25. package/dist/plugin-sdk/thinking-pTdxk2dr.js +1 -0
  26. package/dist/thinking-B5B36ffe.js +1 -0
  27. package/dist/thinking-BYwvlJ3S.js +1 -0
  28. package/dist/thinking-CAzdgmNV.js +1 -0
  29. package/dist/thinking-DykY2Fzj.js +1 -0
  30. package/docs/PATCHES.md +25 -0
  31. package/docs/PROVIDER-CATALOG.md +12 -6
  32. package/node_modules/@mariozechner/pi-ai/dist/models.generated.js +27 -3
  33. package/node_modules/@mariozechner/pi-ai/dist/models.js +1 -0
  34. package/node_modules/@mariozechner/pi-ai/dist/providers/anthropic.js +2 -2
  35. package/package.json +1 -1
  36. package/vendor/patched-deps/@mariozechner/pi-ai/dist/models.generated.js +27 -3
  37. package/vendor/patched-deps/@mariozechner/pi-ai/dist/models.js +1 -0
  38. package/vendor/patched-deps/@mariozechner/pi-ai/dist/providers/anthropic.js +2 -2
package/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.9.37
4
+
5
+ - Every Sonnet now gets its full native 1M context window. Claude Sonnet 5.5 175K -> 1M, Claude Sonnet 5 175K -> 1M (it was capped), Claude Sonnet 4.6 200K -> 1M; max output unchanged (Sonnet 5.5 and 5 stay at 128K). The "standing Sonnet window = 175K" rule is gone. A new resolver gives `claude-sonnet-4-6` and every later Sonnet 1M in the resolved config and in `models.json`, so a user config that still pins a Sonnet at 175K is lifted at load and future Sonnets need no patch. No beta header is needed (Anthropic serves 1M by default on these models).
6
+ - Live probe: a 463,749-token prompt to `claude-sonnet-5-5` through the harness's Anthropic adapter completed normally; a raw 648,450-token request returned HTTP 200.
7
+ - Folded into the family 82 exact replay (32 files); verifier checks 82.13-82.17. Roll back with `npm i -g johns-harness@2026.9.36`.
8
+
9
+ ## 2026.9.36
10
+
11
+ - Family 82 (daily model integration, 2026-09-29): Claude Sonnet 5.5 (`claude-sonnet-5-5`) ships on `anthropic`. Card data from the official model page checked 2026-09-29: $2/$10 per MTok, cache read $0.20, 5m write $2.50, 1h write $4, 1M native context and 128K max output, adaptive thinking on by default (effort `low` through `max`, default `high`; `between_tools` is the lowest setting), and non-default `temperature`/`top_p`/`top_k` are rejected. `contextWindow` stays the standing 175K Sonnet window (owner caps do not change). Live probe 2026-09-29: the default request and the `thinking: adaptive` + `output_config.effort: xhigh` request both returned 200.
12
+ - Aliases: `sonnet` now resolves to `anthropic/claude-sonnet-5-5`; `sonnet5` keeps Claude Sonnet 5. Everything else is unchanged. A user alias that pins Sonnet 5 under `sonnet` moves forward on the next config load (family 79) and keeps `sonnet5`.
13
+ - Exact replay `scripts/patch-sonnet-5-5-model.py` (29 files); verifier checks 82.1-82.12. Roll back with `npm i -g johns-harness@2026.9.35`.
14
+
3
15
  ## 2026.9.35
4
16
 
5
17
  - Family 81 (session store memory, 2026-09-28): the gateway no longer runs out of memory every few days. `sessions.json` stops storing `skillsSnapshot` and `systemPromptReport` in every entry (they are rebuilt in memory on demand); existing stores shrink on the first write after the update (the live main store: 27 MB to 0.3 MB). Writes are compact JSON with one fewer full clone per load: 347 ms to 5 ms per session update on the live store copy.
@@ -5134,6 +5134,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
5134
5134
  "nano-banana": "google/gemini-3-pro-image-preview",
5135
5135
  image: "openai-codex/gpt-image-2"
5136
5136
  });
5137
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
5138
+ // Sonnet 5 keeps the versioned alias sonnet5.
5139
+ Object.assign(DEFAULT_MODEL_ALIASES, {
5140
+ sonnet: "anthropic/claude-sonnet-5-5",
5141
+ sonnet5: "anthropic/claude-sonnet-5"
5142
+ });
5137
5143
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
5138
5144
  Object.assign(DEFAULT_MODEL_ALIASES, {
5139
5145
  opus: "anthropic/claude-opus-5-5",
@@ -5361,7 +5367,7 @@ function applyModelDefaults(cfg) {
5361
5367
  if (raw.input === void 0) modelMutated = true;
5362
5368
  const cost = resolveModelCost(raw.cost);
5363
5369
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
5364
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5370
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5365
5371
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5366
5372
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5367
5373
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5427,6 +5433,19 @@ function applyModelDefaults(cfg) {
5427
5433
  }
5428
5434
  };
5429
5435
  }
5436
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5437
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5438
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5439
+ config, models.json, compaction and session snapshots all read this one value. */
5440
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5441
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5442
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5443
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5444
+ if (!match) return;
5445
+ const major = Number(match[1]);
5446
+ const minor = Number(match[2] ?? 0);
5447
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5448
+ }
5430
5449
  function applyAgentDefaults(cfg) {
5431
5450
  const agents = cfg.agents;
5432
5451
  const defaults = agents?.defaults;
@@ -2110,6 +2110,7 @@ const XHIGH_MODEL_REFS = [
2110
2110
  "anthropic/claude-fable-5-1",
2111
2111
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
2112
2112
  "meta/muse-spark-1.2",
2113
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
2113
2114
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
2114
2115
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
2115
2116
  "openai/gpt-6-sol",
@@ -1829,6 +1829,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
1829
1829
  "nano-banana": "google/gemini-3-pro-image-preview",
1830
1830
  image: "openai-codex/gpt-image-2"
1831
1831
  });
1832
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
1833
+ // Sonnet 5 keeps the versioned alias sonnet5.
1834
+ Object.assign(DEFAULT_MODEL_ALIASES, {
1835
+ sonnet: "anthropic/claude-sonnet-5-5",
1836
+ sonnet5: "anthropic/claude-sonnet-5"
1837
+ });
1832
1838
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
1833
1839
  Object.assign(DEFAULT_MODEL_ALIASES, {
1834
1840
  opus: "anthropic/claude-opus-5-5",
@@ -2056,7 +2062,7 @@ function applyModelDefaults(cfg) {
2056
2062
  if (raw.input === void 0) modelMutated = true;
2057
2063
  const cost = resolveModelCost(raw.cost);
2058
2064
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
2059
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
2065
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
2060
2066
  if (raw.contextWindow !== contextWindow) modelMutated = true;
2061
2067
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
2062
2068
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -2122,6 +2128,19 @@ function applyModelDefaults(cfg) {
2122
2128
  }
2123
2129
  };
2124
2130
  }
2131
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
2132
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
2133
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
2134
+ config, models.json, compaction and session snapshots all read this one value. */
2135
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
2136
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
2137
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
2138
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
2139
+ if (!match) return;
2140
+ const major = Number(match[1]);
2141
+ const minor = Number(match[2] ?? 0);
2142
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
2143
+ }
2125
2144
  function applyAgentDefaults(cfg) {
2126
2145
  const agents = cfg.agents;
2127
2146
  const defaults = agents?.defaults;
@@ -4981,6 +4981,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
4981
4981
  "nano-banana": "google/gemini-3-pro-image-preview",
4982
4982
  image: "openai-codex/gpt-image-2"
4983
4983
  });
4984
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
4985
+ // Sonnet 5 keeps the versioned alias sonnet5.
4986
+ Object.assign(DEFAULT_MODEL_ALIASES, {
4987
+ sonnet: "anthropic/claude-sonnet-5-5",
4988
+ sonnet5: "anthropic/claude-sonnet-5"
4989
+ });
4984
4990
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
4985
4991
  Object.assign(DEFAULT_MODEL_ALIASES, {
4986
4992
  opus: "anthropic/claude-opus-5-5",
@@ -5208,7 +5214,7 @@ function applyModelDefaults(cfg) {
5208
5214
  if (raw.input === void 0) modelMutated = true;
5209
5215
  const cost = resolveModelCost(raw.cost);
5210
5216
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
5211
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5217
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5212
5218
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5213
5219
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5214
5220
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5274,6 +5280,19 @@ function applyModelDefaults(cfg) {
5274
5280
  }
5275
5281
  };
5276
5282
  }
5283
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5284
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5285
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5286
+ config, models.json, compaction and session snapshots all read this one value. */
5287
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5288
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5289
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5290
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5291
+ if (!match) return;
5292
+ const major = Number(match[1]);
5293
+ const minor = Number(match[2] ?? 0);
5294
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5295
+ }
5277
5296
  function applyAgentDefaults(cfg) {
5278
5297
  const agents = cfg.agents;
5279
5298
  const defaults = agents?.defaults;
@@ -1686,6 +1686,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
1686
1686
  "nano-banana": "google/gemini-3-pro-image-preview",
1687
1687
  image: "openai-codex/gpt-image-2"
1688
1688
  });
1689
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
1690
+ // Sonnet 5 keeps the versioned alias sonnet5.
1691
+ Object.assign(DEFAULT_MODEL_ALIASES, {
1692
+ sonnet: "anthropic/claude-sonnet-5-5",
1693
+ sonnet5: "anthropic/claude-sonnet-5"
1694
+ });
1689
1695
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
1690
1696
  Object.assign(DEFAULT_MODEL_ALIASES, {
1691
1697
  opus: "anthropic/claude-opus-5-5",
@@ -1932,7 +1938,7 @@ function applyModelDefaults(cfg) {
1932
1938
  if (raw.input === void 0) modelMutated = true;
1933
1939
  const cost = resolveModelCost(raw.cost);
1934
1940
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
1935
- const contextWindow = resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS);
1941
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
1936
1942
  if (raw.contextWindow !== contextWindow) modelMutated = true;
1937
1943
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
1938
1944
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -1998,6 +2004,19 @@ function applyModelDefaults(cfg) {
1998
2004
  }
1999
2005
  };
2000
2006
  }
2007
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
2008
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
2009
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
2010
+ config, models.json, compaction and session snapshots all read this one value. */
2011
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
2012
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
2013
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
2014
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
2015
+ if (!match) return;
2016
+ const major = Number(match[1]);
2017
+ const minor = Number(match[2] ?? 0);
2018
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
2019
+ }
2001
2020
  function applyAgentDefaults(cfg) {
2002
2021
  const agents = cfg.agents;
2003
2022
  const defaults = agents?.defaults;
@@ -1661,6 +1661,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
1661
1661
  "nano-banana": "google/gemini-3-pro-image-preview",
1662
1662
  image: "openai-codex/gpt-image-2"
1663
1663
  });
1664
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
1665
+ // Sonnet 5 keeps the versioned alias sonnet5.
1666
+ Object.assign(DEFAULT_MODEL_ALIASES, {
1667
+ sonnet: "anthropic/claude-sonnet-5-5",
1668
+ sonnet5: "anthropic/claude-sonnet-5"
1669
+ });
1664
1670
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
1665
1671
  Object.assign(DEFAULT_MODEL_ALIASES, {
1666
1672
  opus: "anthropic/claude-opus-5-5",
@@ -1907,7 +1913,7 @@ function applyModelDefaults(cfg) {
1907
1913
  if (raw.input === void 0) modelMutated = true;
1908
1914
  const cost = resolveModelCost(raw.cost);
1909
1915
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
1910
- const contextWindow = resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS);
1916
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
1911
1917
  if (raw.contextWindow !== contextWindow) modelMutated = true;
1912
1918
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
1913
1919
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -1973,6 +1979,19 @@ function applyModelDefaults(cfg) {
1973
1979
  }
1974
1980
  };
1975
1981
  }
1982
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
1983
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
1984
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
1985
+ config, models.json, compaction and session snapshots all read this one value. */
1986
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
1987
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
1988
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
1989
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
1990
+ if (!match) return;
1991
+ const major = Number(match[1]);
1992
+ const minor = Number(match[2] ?? 0);
1993
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
1994
+ }
1976
1995
  function applyAgentDefaults(cfg) {
1977
1996
  const agents = cfg.agents;
1978
1997
  const defaults = agents?.defaults;
@@ -1592,6 +1592,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
1592
1592
  "nano-banana": "google/gemini-3-pro-image-preview",
1593
1593
  image: "openai-codex/gpt-image-2"
1594
1594
  });
1595
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
1596
+ // Sonnet 5 keeps the versioned alias sonnet5.
1597
+ Object.assign(DEFAULT_MODEL_ALIASES, {
1598
+ sonnet: "anthropic/claude-sonnet-5-5",
1599
+ sonnet5: "anthropic/claude-sonnet-5"
1600
+ });
1595
1601
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
1596
1602
  Object.assign(DEFAULT_MODEL_ALIASES, {
1597
1603
  opus: "anthropic/claude-opus-5-5",
@@ -1838,7 +1844,7 @@ function applyModelDefaults(cfg) {
1838
1844
  if (raw.input === void 0) modelMutated = true;
1839
1845
  const cost = resolveModelCost(raw.cost);
1840
1846
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
1841
- const contextWindow = resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS);
1847
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
1842
1848
  if (raw.contextWindow !== contextWindow) modelMutated = true;
1843
1849
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
1844
1850
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -1904,6 +1910,19 @@ function applyModelDefaults(cfg) {
1904
1910
  }
1905
1911
  };
1906
1912
  }
1913
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
1914
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
1915
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
1916
+ config, models.json, compaction and session snapshots all read this one value. */
1917
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
1918
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
1919
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
1920
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
1921
+ if (!match) return;
1922
+ const major = Number(match[1]);
1923
+ const minor = Number(match[2] ?? 0);
1924
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
1925
+ }
1907
1926
  function applyAgentDefaults(cfg) {
1908
1927
  const agents = cfg.agents;
1909
1928
  const defaults = agents?.defaults;
@@ -45,6 +45,43 @@ function applyJohnnessOpusContextWindows(providers) {
45
45
  }
46
46
  };
47
47
  }
48
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
49
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
50
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
51
+ config, models.json, compaction and session snapshots all read this one value. */
52
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
53
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
54
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
55
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
56
+ if (!match) return;
57
+ const major = Number(match[1]);
58
+ const minor = Number(match[2] ?? 0);
59
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
60
+ }
61
+ function applyJohnnessSonnetNativeContextWindows(providers) {
62
+ const anthropicKey = Object.keys(providers).find((key) => key.trim().toLowerCase() === "anthropic");
63
+ if (!anthropicKey) return providers;
64
+ const anthropic = providers[anthropicKey];
65
+ if (!Array.isArray(anthropic?.models)) return providers;
66
+ let mutated = false;
67
+ const models = anthropic.models.map((model) => {
68
+ const nativeWindow = resolveJohnnessSonnetNativeContextWindow("anthropic", model?.id);
69
+ if (!nativeWindow || model.contextWindow === nativeWindow) return model;
70
+ mutated = true;
71
+ return {
72
+ ...model,
73
+ contextWindow: nativeWindow
74
+ };
75
+ });
76
+ if (!mutated) return providers;
77
+ return {
78
+ ...providers,
79
+ [anthropicKey]: {
80
+ ...anthropic,
81
+ models
82
+ }
83
+ };
84
+ }
48
85
  function isPositiveFiniteTokenLimit(value) {
49
86
  return typeof value === "number" && Number.isFinite(value) && value > 0;
50
87
  }
@@ -141,7 +178,7 @@ async function resolveProvidersForModelsJson(params) {
141
178
  }
142
179
  const implicitCopilot = await resolveImplicitCopilotProvider({ agentDir });
143
180
  if (implicitCopilot && !providers["github-copilot"]) providers["github-copilot"] = implicitCopilot;
144
- return applyJohnnessOpusContextWindows(providers);
181
+ return applyJohnnessSonnetNativeContextWindows(applyJohnnessOpusContextWindows(providers)); // JOHNNESS_PATCH_SONNET_55_MODEL
145
182
  }
146
183
  function mergeWithExistingProviderSecrets(params) {
147
184
  const { nextProviders, existingProviders, secretRefManagedProviders, explicitBaseUrlProviders } = params;
@@ -45,6 +45,43 @@ function applyJohnnessOpusContextWindows(providers) {
45
45
  }
46
46
  };
47
47
  }
48
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
49
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
50
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
51
+ config, models.json, compaction and session snapshots all read this one value. */
52
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
53
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
54
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
55
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
56
+ if (!match) return;
57
+ const major = Number(match[1]);
58
+ const minor = Number(match[2] ?? 0);
59
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
60
+ }
61
+ function applyJohnnessSonnetNativeContextWindows(providers) {
62
+ const anthropicKey = Object.keys(providers).find((key) => key.trim().toLowerCase() === "anthropic");
63
+ if (!anthropicKey) return providers;
64
+ const anthropic = providers[anthropicKey];
65
+ if (!Array.isArray(anthropic?.models)) return providers;
66
+ let mutated = false;
67
+ const models = anthropic.models.map((model) => {
68
+ const nativeWindow = resolveJohnnessSonnetNativeContextWindow("anthropic", model?.id);
69
+ if (!nativeWindow || model.contextWindow === nativeWindow) return model;
70
+ mutated = true;
71
+ return {
72
+ ...model,
73
+ contextWindow: nativeWindow
74
+ };
75
+ });
76
+ if (!mutated) return providers;
77
+ return {
78
+ ...providers,
79
+ [anthropicKey]: {
80
+ ...anthropic,
81
+ models
82
+ }
83
+ };
84
+ }
48
85
  function isPositiveFiniteTokenLimit(value) {
49
86
  return typeof value === "number" && Number.isFinite(value) && value > 0;
50
87
  }
@@ -141,7 +178,7 @@ async function resolveProvidersForModelsJson(params) {
141
178
  }
142
179
  const implicitCopilot = await resolveImplicitCopilotProvider({ agentDir });
143
180
  if (implicitCopilot && !providers["github-copilot"]) providers["github-copilot"] = implicitCopilot;
144
- return applyJohnnessOpusContextWindows(providers);
181
+ return applyJohnnessSonnetNativeContextWindows(applyJohnnessOpusContextWindows(providers)); // JOHNNESS_PATCH_SONNET_55_MODEL
145
182
  }
146
183
  function mergeWithExistingProviderSecrets(params) {
147
184
  const { nextProviders, existingProviders, secretRefManagedProviders, explicitBaseUrlProviders } = params;
@@ -7079,6 +7079,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
7079
7079
  "nano-banana": "google/gemini-3-pro-image-preview",
7080
7080
  image: "openai-codex/gpt-image-2"
7081
7081
  });
7082
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
7083
+ // Sonnet 5 keeps the versioned alias sonnet5.
7084
+ Object.assign(DEFAULT_MODEL_ALIASES, {
7085
+ sonnet: "anthropic/claude-sonnet-5-5",
7086
+ sonnet5: "anthropic/claude-sonnet-5"
7087
+ });
7082
7088
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
7083
7089
  Object.assign(DEFAULT_MODEL_ALIASES, {
7084
7090
  opus: "anthropic/claude-opus-5-5",
@@ -7306,7 +7312,7 @@ function applyModelDefaults(cfg) {
7306
7312
  if (raw.input === void 0) modelMutated = true;
7307
7313
  const cost = resolveModelCost(raw.cost);
7308
7314
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
7309
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
7315
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
7310
7316
  if (raw.contextWindow !== contextWindow) modelMutated = true;
7311
7317
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
7312
7318
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -7372,6 +7378,19 @@ function applyModelDefaults(cfg) {
7372
7378
  }
7373
7379
  };
7374
7380
  }
7381
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
7382
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
7383
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
7384
+ config, models.json, compaction and session snapshots all read this one value. */
7385
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
7386
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
7387
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
7388
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
7389
+ if (!match) return;
7390
+ const major = Number(match[1]);
7391
+ const minor = Number(match[2] ?? 0);
7392
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
7393
+ }
7375
7394
  function applyAgentDefaults(cfg) {
7376
7395
  const agents = cfg.agents;
7377
7396
  const defaults = agents?.defaults;
@@ -8080,6 +8080,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
8080
8080
  "nano-banana": "google/gemini-3-pro-image-preview",
8081
8081
  image: "openai-codex/gpt-image-2"
8082
8082
  });
8083
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
8084
+ // Sonnet 5 keeps the versioned alias sonnet5.
8085
+ Object.assign(DEFAULT_MODEL_ALIASES, {
8086
+ sonnet: "anthropic/claude-sonnet-5-5",
8087
+ sonnet5: "anthropic/claude-sonnet-5"
8088
+ });
8083
8089
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
8084
8090
  Object.assign(DEFAULT_MODEL_ALIASES, {
8085
8091
  opus: "anthropic/claude-opus-5-5",
@@ -8307,7 +8313,7 @@ function applyModelDefaults(cfg) {
8307
8313
  if (raw.input === void 0) modelMutated = true;
8308
8314
  const cost = resolveModelCost(raw.cost);
8309
8315
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
8310
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
8316
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
8311
8317
  if (raw.contextWindow !== contextWindow) modelMutated = true;
8312
8318
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
8313
8319
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -8373,6 +8379,19 @@ function applyModelDefaults(cfg) {
8373
8379
  }
8374
8380
  };
8375
8381
  }
8382
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
8383
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
8384
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
8385
+ config, models.json, compaction and session snapshots all read this one value. */
8386
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
8387
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
8388
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
8389
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
8390
+ if (!match) return;
8391
+ const major = Number(match[1]);
8392
+ const minor = Number(match[2] ?? 0);
8393
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
8394
+ }
8376
8395
  function applyAgentDefaults(cfg) {
8377
8396
  const agents = cfg.agents;
8378
8397
  const defaults = agents?.defaults;
@@ -5209,6 +5209,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
5209
5209
  "nano-banana": "google/gemini-3-pro-image-preview",
5210
5210
  image: "openai-codex/gpt-image-2"
5211
5211
  });
5212
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
5213
+ // Sonnet 5 keeps the versioned alias sonnet5.
5214
+ Object.assign(DEFAULT_MODEL_ALIASES, {
5215
+ sonnet: "anthropic/claude-sonnet-5-5",
5216
+ sonnet5: "anthropic/claude-sonnet-5"
5217
+ });
5212
5218
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
5213
5219
  Object.assign(DEFAULT_MODEL_ALIASES, {
5214
5220
  opus: "anthropic/claude-opus-5-5",
@@ -5436,7 +5442,7 @@ function applyModelDefaults(cfg) {
5436
5442
  if (raw.input === void 0) modelMutated = true;
5437
5443
  const cost = resolveModelCost(raw.cost);
5438
5444
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
5439
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5445
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5440
5446
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5441
5447
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5442
5448
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5502,6 +5508,19 @@ function applyModelDefaults(cfg) {
5502
5508
  }
5503
5509
  };
5504
5510
  }
5511
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5512
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5513
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5514
+ config, models.json, compaction and session snapshots all read this one value. */
5515
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5516
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5517
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5518
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5519
+ if (!match) return;
5520
+ const major = Number(match[1]);
5521
+ const minor = Number(match[2] ?? 0);
5522
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5523
+ }
5505
5524
  function applyAgentDefaults(cfg) {
5506
5525
  const agents = cfg.agents;
5507
5526
  const defaults = agents?.defaults;
@@ -3135,6 +3135,7 @@ const XHIGH_MODEL_REFS = [
3135
3135
  "anthropic/claude-fable-5-1",
3136
3136
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
3137
3137
  "meta/muse-spark-1.2",
3138
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
3138
3139
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
3139
3140
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
3140
3141
  "openai/gpt-6-sol",
@@ -6000,6 +6000,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
6000
6000
  "nano-banana": "google/gemini-3-pro-image-preview",
6001
6001
  image: "openai-codex/gpt-image-2"
6002
6002
  });
6003
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
6004
+ // Sonnet 5 keeps the versioned alias sonnet5.
6005
+ Object.assign(DEFAULT_MODEL_ALIASES, {
6006
+ sonnet: "anthropic/claude-sonnet-5-5",
6007
+ sonnet5: "anthropic/claude-sonnet-5"
6008
+ });
6003
6009
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
6004
6010
  Object.assign(DEFAULT_MODEL_ALIASES, {
6005
6011
  opus: "anthropic/claude-opus-5-5",
@@ -6227,7 +6233,7 @@ function applyModelDefaults(cfg) {
6227
6233
  if (raw.input === void 0) modelMutated = true;
6228
6234
  const cost = resolveModelCost(raw.cost);
6229
6235
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
6230
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
6236
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
6231
6237
  if (raw.contextWindow !== contextWindow) modelMutated = true;
6232
6238
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
6233
6239
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -6293,6 +6299,19 @@ function applyModelDefaults(cfg) {
6293
6299
  }
6294
6300
  };
6295
6301
  }
6302
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
6303
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
6304
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
6305
+ config, models.json, compaction and session snapshots all read this one value. */
6306
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
6307
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
6308
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
6309
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
6310
+ if (!match) return;
6311
+ const major = Number(match[1]);
6312
+ const minor = Number(match[2] ?? 0);
6313
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
6314
+ }
6296
6315
  function applyAgentDefaults(cfg) {
6297
6316
  const agents = cfg.agents;
6298
6317
  const defaults = agents?.defaults;
@@ -4969,6 +4969,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
4969
4969
  "nano-banana": "google/gemini-3-pro-image-preview",
4970
4970
  image: "openai-codex/gpt-image-2"
4971
4971
  });
4972
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
4973
+ // Sonnet 5 keeps the versioned alias sonnet5.
4974
+ Object.assign(DEFAULT_MODEL_ALIASES, {
4975
+ sonnet: "anthropic/claude-sonnet-5-5",
4976
+ sonnet5: "anthropic/claude-sonnet-5"
4977
+ });
4972
4978
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
4973
4979
  Object.assign(DEFAULT_MODEL_ALIASES, {
4974
4980
  opus: "anthropic/claude-opus-5-5",
@@ -5196,7 +5202,7 @@ function applyModelDefaults(cfg) {
5196
5202
  if (raw.input === void 0) modelMutated = true;
5197
5203
  const cost = resolveModelCost(raw.cost);
5198
5204
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
5199
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5205
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5200
5206
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5201
5207
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5202
5208
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5262,6 +5268,19 @@ function applyModelDefaults(cfg) {
5262
5268
  }
5263
5269
  };
5264
5270
  }
5271
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5272
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5273
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5274
+ config, models.json, compaction and session snapshots all read this one value. */
5275
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5276
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5277
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5278
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5279
+ if (!match) return;
5280
+ const major = Number(match[1]);
5281
+ const minor = Number(match[2] ?? 0);
5282
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5283
+ }
5265
5284
  function applyAgentDefaults(cfg) {
5266
5285
  const agents = cfg.agents;
5267
5286
  const defaults = agents?.defaults;
@@ -4973,6 +4973,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
4973
4973
  "nano-banana": "google/gemini-3-pro-image-preview",
4974
4974
  image: "openai-codex/gpt-image-2"
4975
4975
  });
4976
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
4977
+ // Sonnet 5 keeps the versioned alias sonnet5.
4978
+ Object.assign(DEFAULT_MODEL_ALIASES, {
4979
+ sonnet: "anthropic/claude-sonnet-5-5",
4980
+ sonnet5: "anthropic/claude-sonnet-5"
4981
+ });
4976
4982
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
4977
4983
  Object.assign(DEFAULT_MODEL_ALIASES, {
4978
4984
  opus: "anthropic/claude-opus-5-5",
@@ -5200,7 +5206,7 @@ function applyModelDefaults(cfg) {
5200
5206
  if (raw.input === void 0) modelMutated = true;
5201
5207
  const cost = resolveModelCost(raw.cost);
5202
5208
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
5203
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5209
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5204
5210
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5205
5211
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5206
5212
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5266,6 +5272,19 @@ function applyModelDefaults(cfg) {
5266
5272
  }
5267
5273
  };
5268
5274
  }
5275
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5276
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5277
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5278
+ config, models.json, compaction and session snapshots all read this one value. */
5279
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5280
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5281
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5282
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5283
+ if (!match) return;
5284
+ const major = Number(match[1]);
5285
+ const minor = Number(match[2] ?? 0);
5286
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5287
+ }
5269
5288
  function applyAgentDefaults(cfg) {
5270
5289
  const agents = cfg.agents;
5271
5290
  const defaults = agents?.defaults;
@@ -4973,6 +4973,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
4973
4973
  "nano-banana": "google/gemini-3-pro-image-preview",
4974
4974
  image: "openai-codex/gpt-image-2"
4975
4975
  });
4976
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
4977
+ // Sonnet 5 keeps the versioned alias sonnet5.
4978
+ Object.assign(DEFAULT_MODEL_ALIASES, {
4979
+ sonnet: "anthropic/claude-sonnet-5-5",
4980
+ sonnet5: "anthropic/claude-sonnet-5"
4981
+ });
4976
4982
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
4977
4983
  Object.assign(DEFAULT_MODEL_ALIASES, {
4978
4984
  opus: "anthropic/claude-opus-5-5",
@@ -5200,7 +5206,7 @@ function applyModelDefaults(cfg) {
5200
5206
  if (raw.input === void 0) modelMutated = true;
5201
5207
  const cost = resolveModelCost(raw.cost);
5202
5208
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
5203
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5209
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5204
5210
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5205
5211
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5206
5212
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5266,6 +5272,19 @@ function applyModelDefaults(cfg) {
5266
5272
  }
5267
5273
  };
5268
5274
  }
5275
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5276
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5277
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5278
+ config, models.json, compaction and session snapshots all read this one value. */
5279
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5280
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5281
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5282
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5283
+ if (!match) return;
5284
+ const major = Number(match[1]);
5285
+ const minor = Number(match[2] ?? 0);
5286
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5287
+ }
5269
5288
  function applyAgentDefaults(cfg) {
5270
5289
  const agents = cfg.agents;
5271
5290
  const defaults = agents?.defaults;
@@ -4782,6 +4782,12 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
4782
4782
  "nano-banana": "google/gemini-3-pro-image-preview",
4783
4783
  image: "openai-codex/gpt-image-2"
4784
4784
  });
4785
+ // JOHNNESS_PATCH_SONNET_55_MODEL: Claude Sonnet 5.5 is the newest Sonnet; `sonnet` moves to it and
4786
+ // Sonnet 5 keeps the versioned alias sonnet5.
4787
+ Object.assign(DEFAULT_MODEL_ALIASES, {
4788
+ sonnet: "anthropic/claude-sonnet-5-5",
4789
+ sonnet5: "anthropic/claude-sonnet-5"
4790
+ });
4785
4791
  // JOHNNESS_PATCH_OPUS_55_MODEL: Claude Opus 5.5 is the newest Opus; `opus` moves to it, opus-5 stays in the catalog.
4786
4792
  Object.assign(DEFAULT_MODEL_ALIASES, {
4787
4793
  opus: "anthropic/claude-opus-5-5",
@@ -5009,7 +5015,7 @@ function applyModelDefaults(cfg) {
5009
5015
  if (raw.input === void 0) modelMutated = true;
5010
5016
  const cost = resolveModelCost(raw.cost);
5011
5017
  if (!raw.cost || raw.cost.input !== cost.input || raw.cost.output !== cost.output || raw.cost.cacheRead !== cost.cacheRead || raw.cost.cacheWrite !== cost.cacheWrite) modelMutated = true;
5012
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5018
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5013
5019
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5014
5020
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5015
5021
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5075,6 +5081,19 @@ function applyModelDefaults(cfg) {
5075
5081
  }
5076
5082
  };
5077
5083
  }
5084
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5085
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5086
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5087
+ config, models.json, compaction and session snapshots all read this one value. */
5088
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5089
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5090
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5091
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5092
+ if (!match) return;
5093
+ const major = Number(match[1]);
5094
+ const minor = Number(match[2] ?? 0);
5095
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5096
+ }
5078
5097
  function applyAgentDefaults(cfg) {
5079
5098
  const agents = cfg.agents;
5080
5099
  const defaults = agents?.defaults;
@@ -990,6 +990,7 @@ const XHIGH_MODEL_REFS = [
990
990
  "anthropic/claude-fable-5-1",
991
991
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
992
992
  "meta/muse-spark-1.2",
993
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
993
994
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
994
995
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
995
996
  "openai/gpt-6-sol",
@@ -990,6 +990,7 @@ const XHIGH_MODEL_REFS = [
990
990
  "anthropic/claude-fable-5-1",
991
991
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
992
992
  "meta/muse-spark-1.2",
993
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
993
994
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
994
995
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
995
996
  "openai/gpt-6-sol",
@@ -990,6 +990,7 @@ const XHIGH_MODEL_REFS = [
990
990
  "anthropic/claude-fable-5-1",
991
991
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
992
992
  "meta/muse-spark-1.2",
993
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
993
994
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
994
995
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
995
996
  "openai/gpt-6-sol",
@@ -990,6 +990,7 @@ const XHIGH_MODEL_REFS = [
990
990
  "anthropic/claude-fable-5-1",
991
991
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
992
992
  "meta/muse-spark-1.2",
993
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
993
994
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
994
995
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
995
996
  "openai/gpt-6-sol",
@@ -990,6 +990,7 @@ const XHIGH_MODEL_REFS = [
990
990
  "anthropic/claude-fable-5-1",
991
991
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
992
992
  "meta/muse-spark-1.2",
993
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
993
994
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
994
995
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
995
996
  "openai/gpt-6-sol",
@@ -1014,6 +1014,7 @@ const XHIGH_MODEL_REFS = [
1014
1014
  "anthropic/claude-fable-5-1",
1015
1015
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
1016
1016
  "meta/muse-spark-1.2",
1017
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
1017
1018
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
1018
1019
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
1019
1020
  "openai/gpt-6-sol",
@@ -991,6 +991,7 @@ const XHIGH_MODEL_REFS = [
991
991
  "anthropic/claude-fable-5-1",
992
992
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
993
993
  "meta/muse-spark-1.2",
994
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
994
995
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
995
996
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
996
997
  "openai/gpt-6-sol",
@@ -18,6 +18,7 @@ const XHIGH_MODEL_REFS = [
18
18
  "anthropic/claude-fable-5-1",
19
19
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
20
20
  "meta/muse-spark-1.2",
21
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
21
22
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
22
23
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
23
24
  "openai/gpt-6-sol",
@@ -990,6 +990,7 @@ const XHIGH_MODEL_REFS = [
990
990
  "anthropic/claude-fable-5-1",
991
991
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
992
992
  "meta/muse-spark-1.2",
993
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
993
994
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
994
995
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
995
996
  "openai/gpt-6-sol",
@@ -18,6 +18,7 @@ const XHIGH_MODEL_REFS = [
18
18
  "anthropic/claude-fable-5-1",
19
19
  "meta/muse-spark-1.3", // JOHNNESS_PATCH_MUSE_SPARK
20
20
  "meta/muse-spark-1.2",
21
+ "anthropic/claude-sonnet-5-5", // JOHNNESS_PATCH_SONNET_55_MODEL
21
22
  "anthropic/claude-opus-5-5", // JOHNNESS_PATCH_OPUS_55_MODEL
22
23
  "xai/grok-4.7", // JOHNNESS_PATCH_DAILY_MODELS_80
23
24
  "openai/gpt-6-sol",
package/docs/PATCHES.md CHANGED
@@ -107,6 +107,7 @@ Family 01 is retired. Families 02 through 41, 43 through 81, including the 65.1
107
107
  79. **79, cron reliability and shorthand freshness:** recurring cron transient retry, cron run fallbacks, `cron.failureLog`, and stale shorthand aliases move to the newest shipped model. [Details](#family-79-cron-reliability-and-shorthand-freshness-20269332)
108
108
  80. **80, daily model integration:** GPT-6 Sol and GPT-6 Luna (openai + openai-codex) and xAI Grok 4.7 registered; `sol`/`gpt`/`luna` move to GPT-6 with `sol56`/`luna56` kept, `grok` ships on Grok 4.7 with `grok46` kept. [Details](#80---daily-models-80-2026-09-24)
109
109
  81. **81, session store memory:** `skillsSnapshot` and `systemPromptReport` are no longer written to `sessions.json` (27 MB to under 1 MB on the live store), compact writes, maintenance enforces by default without touching active, main or recent sessions, and the gateway heap rises to min(8 GB, RAM/2). [Details](#81---session-store-memory-2026-09-28)
110
+ 82. **82, daily model integration:** Claude Sonnet 5.5 (`claude-sonnet-5-5`) registered; `sonnet` moves to it with `sonnet5` kept on Sonnet 5. Since 2026.9.37 every Sonnet runs on its full native 1M window. [Details](#82---sonnet-5-5-2026-09-29)
110
111
 
111
112
  ---
112
113
 
@@ -2848,3 +2849,27 @@ The gateway heap grew about 65 MB an hour and hit the Node default limit (about
2848
2849
  - **Exact replay.** `scripts/patch-session-store-memory-81.py` with `patches/session-store-memory-81/changes.json` (11 files: the 10 session store copies and `dist/entry.js`; the `v8` import sits outside family 59's CLI hunk). Verifier 81.1-81.7. Tests: `tests/session-store-memory-81.test.mjs`.
2849
2850
  - **Next family (not in this release):** swarm queue persistence. Queued `swarm_spawn` members live only in gateway memory, so a gateway restart drops them and the swarm never finishes launching.
2850
2851
  - Roll back with `npm i -g johns-harness@2026.9.34`.
2852
+
2853
+ ## 82 - sonnet-5-5 (2026-09-29)
2854
+
2855
+ Second run of the daily model integration. One new model appeared in the authenticated provider lists since the 2026-09-28 run (Anthropic 12 -> 13: `claude-sonnet-5-5`); it is registered from its official page (checked 2026-09-29) and was wire-probed live.
2856
+
2857
+ - **Claude Sonnet 5.5** (`claude-sonnet-5-5`, anthropic, native Messages). Source: <https://platform.claude.com/docs/en/models/sonnet-5-5/overview> (checked 2026-09-29). Fixed API id, no date suffix (Bedrock `anthropic.claude-sonnet-5-5`); released 2026-09-28. 1,000,000-token native context, 128,000 max output (300K on the Message Batches API with the `output-300k-2026-03-24` beta header), text + images in and text out, knowledge cutoff Jun 2026. Adaptive thinking is on by default: the manual-budget thinking type is not accepted, effort is `low|medium|high|xhigh|max` with default `high`, and `between_tools` is the lowest setting (turns up-front thinking off at high or below). Non-default `temperature`/`top_p`/`top_k` return 400. Pricing $2/$10 per MTok, cache reads $0.20, 5m cache writes $2.50, 1h cache writes $4, Batch API 50% off. The authenticated Models API list agrees (max_input_tokens 1,000,000; max_tokens 128,000; adaptive thinking with `enabled: false`; effort incl. xhigh/max).
2858
+ - **Context window.** `contextWindow` is the full native 1,000,000 (since 2026.9.37; it first shipped at 175000). `maxTokens` 128000. See "Sonnet native 1M" below.
2859
+ - **Gates.** `supportsXhigh` gains an exact branch for `claude-sonnet-5-5` on anthropic; the Anthropic adapter's effort map accepts the id with 1:1 low/medium/high/xhigh/max (minimal -> low) and the temperature gate includes it, because non-default sampling params are 400s on this model. Adaptive thinking needs no new code: the existing `sonnet-5` substring gate already covers it. `XHIGH_MODEL_REFS` lists `anthropic/claude-sonnet-5-5` in all 12 copies, directly in front of the family 78 Opus 5.5 ref (families 78/80 refs stay contiguous).
2860
+ - **Aliases** (marker `JOHNNESS_PATCH_SONNET_55_MODEL`, a fourth `Object.assign(DEFAULT_MODEL_ALIASES, ...)` block in all 14 copies): `sonnet` -> `anthropic/claude-sonnet-5-5`, `sonnet5` -> `anthropic/claude-sonnet-5` (the previous version stays reachable). `opus`/`opus5`, the GPT-6/GPT-5.6 lines, `grok`, `astra`, `fable`, `sonnet46`, `deepseek` (Flash), `deepseek-pro`, `muse`, `gemini`, `banana`, `terra` and `image` are unchanged. On the next config load the family 79 migration moves a user alias that pins Sonnet 5 under `sonnet` to Sonnet 5.5 and gives the old model `sonnet5`; cross-line pins (e.g. `sonnet` on a Fable model) stay.
2861
+ - **Exact replay.** `scripts/patch-sonnet-5-5-model.py` with `patches/sonnet-5-5/changes.json` (29 files at 2026.9.36: catalog, `models.js`, the Anthropic adapter, 12 thinking copies, 14 alias copies; 32 since 2026.9.37). Preimage/postimage sha256, all-file preflight, `--check`, `--record`, `--dependency-only`, `--present-only`. Families 67, 78 and 80 reverse the family 82 edits before their historical hash checks (80 re-layers them after replaying its own edits); the family 67 replay fixture now replays 78, 79, 80 and 82 in order.
2862
+ - Verifier 82.1-82.12; 63.12 now expects four contract blocks. Tests: `tests/sonnet-5-5-model.test.mjs` (catalog in both the overlay and installed pi-ai, the adaptive effort/temperature wire path, 12 xhigh copies, 14 alias copies, the family 79 migration, exact replay and older-family replays). Counts pinned by `fable-51-model` (anthropic catalog 30 -> 31) and the family 79 migration fixture were updated.
2863
+ - Live probes 2026-09-29 (128 max tokens, "Answer with the single word: OK"): the default request and the harness-shaped `thinking: {type: "adaptive"}` + `output_config: {effort: "xhigh"}` request both returned HTTP 200 with `stop_reason: end_turn`.
2864
+ - Roll back with `npm i -g johns-harness@2026.9.35`.
2865
+
2866
+ ### Sonnet native 1M (2026.9.37)
2867
+
2868
+ John's rule, permanent: every Sonnet model gets its full native 1M context window. The old "standing Sonnet window = 175K" is gone from the source, the patch scripts, the verifier and the daily model integration cron.
2869
+
2870
+ - **Catalog.** `claude-sonnet-5-5` 175000 -> 1000000, `claude-sonnet-5` 175000 -> 1000000 (it was capped), `claude-sonnet-4-6` 200000 -> 1000000. Max output unchanged (128K, 128K, 64K). Sonnet 4.5 and older keep 200K (their native window). Family 61's Sonnet 5 tuple in `scripts/patch-batteries-included-defaults.py` moves with the catalog so family 61 still regenerates the exact text.
2871
+ - **Resolver.** `resolveJohnnessSonnetNativeContextWindow(providerId, modelId)` returns 1e6 for `anthropic` + `claude-sonnet-4-6` and every later Sonnet (`claude-sonnet-<major>[-<minor>][-<date>]`, major > 4 or 4.6+), so a future Sonnet is 1M without a patch. It runs first in `applyModelDefaults` (all 14 alias copies), which lifts a stale user config that still pins a Sonnet at 175K to 1M at load, and in both `models-config` copies (`applyJohnnessSonnetNativeContextWindows` after the Opus caps) for the raw snapshot that writes `models.json`. Compaction, preflight and session snapshots read the resolved window, so they follow.
2872
+ - **No beta header.** Anthropic serves 1M by default on these models (`max_input_tokens` 1,000,000 in the authenticated Models API for `claude-sonnet-5-5`, `claude-sonnet-5` and `claude-sonnet-4-6`, checked 2026-09-29; the context-windows doc says 1M models need no beta header). The harness sends only `fine-grained-tool-streaming-2025-05-14`.
2873
+ - **Live probe 2026-09-29** through the harness's own pi-ai Anthropic adapter (`completeSimple`, API key auth): a 463,749-token prompt (count_tokens) to `claude-sonnet-5-5` returned `stop: end_turn` with the correct needle answer; usage reported 463,756 total tokens. A raw 648,450-token request also returned HTTP 200 (`usage.input_tokens` 648450).
2874
+ - Folded into the family 82 exact replay (32 files: + `scripts/patch-batteries-included-defaults.py` and the two `models-config` copies). Verifier 82.13-82.17. Tests in `tests/sonnet-5-5-model.test.mjs` execute the resolver in all 16 copies and run the real `loadConfig` in three loader bundles against an isolated state dir with a stale 175K config.
2875
+ - Roll back with `npm i -g johns-harness@2026.9.36`.
@@ -12,7 +12,7 @@ pinned 2026.3.7 foundation, not an upstream upgrade or a default-model change.
12
12
  | Meta | `muse-spark-1.3` (current), `muse-spark-1.2` (retained) | Responses, `https://api.meta.ai/v1` | text/image | 1,048,576 context; 131,072 output |
13
13
  | Google | `gemini-3.8-flash`, `gemini-3.5-flash-lite`; `gemini-3.1-pro-preview` remains explicitly preview | native `generateContent` | text/image in pi-ai; native API also accepts other media | 1,048,576 input; 65,536 output |
14
14
  | OpenAI | `gpt-6-astra`, `gpt-6-sol`, `gpt-6-luna` (Family 80), `gpt-5.6-sol`, `gpt-5.6-terra`, `gpt-5.6-luna` | Responses on API-key provider; Codex Responses on subscription | text/image | Native API 1,050,000 context / 922,000 input / 128,000 output; existing 272,000 effective harness context retained |
15
- | Anthropic | `claude-fable-5-1`, `claude-opus-5`, `claude-sonnet-5` | native Messages | text/image | Native 1M context / 128,000 output; Fable/Opus 300K owner caps retained, Sonnet existing 175K effective context retained |
15
+ | Anthropic | `claude-sonnet-5-5` (Family 82, current), `claude-opus-5-5` (Family 78), `claude-fable-5-1`, `claude-opus-5`, `claude-sonnet-5` | native Messages | text/image | Native 1M context / 128,000 output; Fable/Opus 300K owner caps and Opus 5.5's 500K cap retained; every Sonnet (4.6, 5, 5.5 and later) runs on its full native 1M window (2026.9.37) |
16
16
  | xAI | `grok-4.7` (Family 80, current), `grok-4.6` (retained) | Chat Completions | text/image | Native 500K context; exactly 200K owner cap retained; 64K output (4.7 does not publish a max output; the 4.6 value is kept) |
17
17
 
18
18
  `deepseek-flash` is **DeepSeek V4.1 Flash**, not “V1-flash.” The authenticated
@@ -56,9 +56,9 @@ Registry presence does not promise account entitlement.
56
56
  preserves its native minimal default. 3.8 Flash still maps minimal to LOW because
57
57
  the live API rejects MINIMAL (Family 50). No synthetic thinkingBudget is sent.
58
58
  Deprecated/ignored temperature is omitted on 3.8 Flash and 3.5 Flash-Lite.
59
- - **Claude:** current Fable 5/5.1, Opus 5 and Sonnet 5 preserve native xhigh rather
60
- than silently downgrading it to high or promoting it to max. Low-level max remains
61
- distinct. Minimal maps to low. Adaptive thinking has no manual token budget.
59
+ - **Claude:** current Fable 5/5.1, Opus 5/5.5 and Sonnet 5/5.5 preserve native xhigh
60
+ rather than silently downgrading it to high or promoting it to max. Low-level max
61
+ remains distinct. Minimal maps to low. Adaptive thinking has no manual token budget.
62
62
  Missing effort/thinking stays omitted (current provider defaults). Unsupported
63
63
  sampling temperature is omitted even when the caller supplies no thinking field.
64
64
  Earlier Claude mappings remain untouched. Fable is always-thinking; Opus 5 now
@@ -96,6 +96,7 @@ change global thinking semantics.
96
96
  | GPT-5.6 Sol | 4 | 20 | 0.40 | 5 |
97
97
  | GPT-5.6 Terra | 2 | 12 | 0.20 | 2.50 |
98
98
  | GPT-5.6 Luna | 0.20 | 1.20 | 0.02 | 0.25 |
99
+ | Claude Sonnet 5.5 | 2 | 10 | 0.20 | 2.50 (5m) |
99
100
  | Claude Sonnet 5 | 2 | 10 | 0.20 | 2.50 (5m) |
100
101
  | Claude Opus 5 | 5 | 25 | 0.50 | 6.25 (5m) |
101
102
  | Claude Fable 5.1 | 10 | 50 | 0.25 | 12.50 (5m) |
@@ -140,6 +141,7 @@ requests were sent only to the relevant official host, with redirects disabled.
140
141
  <https://developers.openai.com/api/docs/models/gpt-5.5.md>;
141
142
  authenticated `GET https://api.openai.com/v1/models`.
142
143
  - Anthropic: <https://platform.claude.com/docs/en/models/overview>,
144
+ <https://platform.claude.com/docs/en/models/sonnet-5-5/overview> (2026-09-29),
143
145
  <https://platform.claude.com/docs/en/models/fable-5-1/overview>,
144
146
  <https://platform.claude.com/docs/en/build-with-claude/effort>,
145
147
  <https://platform.claude.com/docs/en/models/opus-5/migration-guide>;
@@ -157,8 +159,12 @@ Harmless direct HTTP inference returned 200 on DeepSeek Flash/Pro, Astra API,
157
159
  Gemini 3.8 Flash and 3.5 Flash-Lite, Grok 4.6, and Claude Fable 5.1/Opus 5/Sonnet 5.
158
160
  On 2026-09-24 (Family 80) direct HTTP inference returned 200 on `gpt-6-sol` and
159
161
  `gpt-6-luna` (OpenAI API key, Responses) and `grok-4.7` (xAI key, Chat Completions).
160
- The Codex subscription entries were not probed directly; they share the Codex
161
- Responses transport already used by the GPT-5.6 and Astra subscription entries.
162
+ On 2026-09-29 (Family 82) direct HTTP inference returned 200 on `claude-sonnet-5-5`
163
+ (Anthropic API key, Messages): the default request and the harness-shaped
164
+ `thinking: {type: "adaptive"}` + `output_config.effort: "xhigh"` request both
165
+ completed with `stop_reason: end_turn`. The Codex subscription entries were not
166
+ probed directly; they share the Codex Responses transport already used by the
167
+ GPT-5.6 and Astra subscription entries.
162
168
  Claude native xhigh and Gemini Lite MINIMAL were specifically exercised. Direct
163
169
  provider probes are not represented as ChatGPT subscription entitlement checks.
164
170
  Offline tests additionally cover actual local HTTP/SSE DeepSeek parsing, tool calls,
@@ -1666,6 +1666,30 @@ export const MODELS = {
1666
1666
  contextWindow: 300000, // JOHNNESS_PATCH_FABLE_51_CONTEXT_300K
1667
1667
  maxTokens: 128000,
1668
1668
  },
1669
+ /* JOHNNESS_PATCH_SONNET_55_MODEL (family 82): Claude Sonnet 5.5. API id "claude-sonnet-5-5" (fixed id, no
1670
+ date suffix) confirmed against platform.claude.com/docs/en/models/sonnet-5-5/overview on
1671
+ 2026-09-29: $2/$10 per MTok, cache reads $0.20, 5m cache writes $2.50, 1h writes $4,
1672
+ 1M native context, 128K max output, adaptive thinking on by default (effort low through
1673
+ max, default high; between_tools turns up-front thinking off). temperature/top_p/top_k
1674
+ non-default values return 400. contextWindow is the full native 1M (every Sonnet gets
1675
+ its native 1M window; no beta header needed). */
1676
+ "claude-sonnet-5-5": {
1677
+ id: "claude-sonnet-5-5",
1678
+ name: "Claude Sonnet 5.5",
1679
+ api: "anthropic-messages",
1680
+ provider: "anthropic",
1681
+ baseUrl: "https://api.anthropic.com",
1682
+ reasoning: true,
1683
+ input: ["text", "image"],
1684
+ cost: {
1685
+ input: 2,
1686
+ output: 10,
1687
+ cacheRead: 0.2,
1688
+ cacheWrite: 2.5,
1689
+ },
1690
+ contextWindow: 1000000,
1691
+ maxTokens: 128000,
1692
+ },
1669
1693
  /* JOHNNESS_PATCH_OPUS_55_MODEL (family 78): Claude Opus 5.5. API id "claude-opus-5-5" (fixed id, no
1670
1694
  date suffix) confirmed against platform.claude.com/docs/en/models/opus-5-5 on
1671
1695
  2026-09-23: $4/$20 per MTok, cache reads $0.20, 5m cache writes $5, 1M native
@@ -1707,7 +1731,7 @@ export const MODELS = {
1707
1731
  contextWindow: 300000,
1708
1732
  maxTokens: 128000,
1709
1733
  },
1710
- /* JOHNNESS_PATCH_DEFAULTS_61 (family 61): Claude Sonnet 5; 175K effective context; native 1M; 2026-09-13 pricing. */
1734
+ /* JOHNNESS_PATCH_DEFAULTS_61 (family 61): Claude Sonnet 5; native 1M context; 2026-09-13 pricing. */
1711
1735
  "claude-sonnet-5": {
1712
1736
  id: "claude-sonnet-5",
1713
1737
  name: "Claude Sonnet 5",
@@ -1722,7 +1746,7 @@ export const MODELS = {
1722
1746
  cacheRead: 0.2,
1723
1747
  cacheWrite: 2.5,
1724
1748
  },
1725
- contextWindow: 175000,
1749
+ contextWindow: 1000000,
1726
1750
  maxTokens: 128000,
1727
1751
  },
1728
1752
  /* JOHNNESS_PATCH_DEFAULTS_61 (family 61): Claude Fable 5; 300K fable cap, same as fable-5-1. */
@@ -2014,7 +2038,7 @@ export const MODELS = {
2014
2038
  cacheRead: 0.3,
2015
2039
  cacheWrite: 3.75,
2016
2040
  },
2017
- contextWindow: 200000,
2041
+ contextWindow: 1000000, // JOHNNESS_PATCH_SONNET_55_MODEL: every Sonnet gets its native 1M window
2018
2042
  maxTokens: 64000,
2019
2043
  },
2020
2044
  },
@@ -39,6 +39,7 @@ export function supportsXhigh(model) {
39
39
  if (model.provider === "deepseek" && ["deepseek-flash", "deepseek-v4-pro"].includes(model.id)) return true;
40
40
  if (model.provider === "anthropic" && ["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1"].includes(model.id)) return true;
41
41
  if (model.provider === "anthropic" && model.id === "claude-opus-5-5") return true; // JOHNNESS_PATCH_OPUS_55_MODEL
42
+ if (model.provider === "anthropic" && model.id === "claude-sonnet-5-5") return true; // JOHNNESS_PATCH_SONNET_55_MODEL
42
43
  // JOHNNESS_PATCH_MUSE_SPARK
43
44
  if (model.provider === "meta" && ["muse-spark-1.3", "muse-spark-1.2"].includes(model.id)) return true;
44
45
  if (model.id.includes("gpt-5.2") || model.id.includes("gpt-5.3")) {
@@ -353,7 +353,7 @@ function supportsAdaptiveThinking(modelId) {
353
353
  */
354
354
  function mapThinkingLevelToEffort(level, modelId) {
355
355
  // JOHNNESS_PATCH_PROVIDER_CATALOG_67: modern Claude supports distinct xhigh/max.
356
- if (["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1", "claude-opus-5-5"].includes(modelId)) { // JOHNNESS_PATCH_OPUS_55_MODEL
356
+ if (["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1", "claude-opus-5-5", "claude-sonnet-5-5"].includes(modelId)) { // JOHNNESS_PATCH_OPUS_55_MODEL JOHNNESS_PATCH_SONNET_55_MODEL
357
357
  if (["low", "medium", "high", "xhigh", "max"].includes(level)) return level;
358
358
  return level === "minimal" ? "low" : "high";
359
359
  }
@@ -533,7 +533,7 @@ function buildParams(model, context, isOAuthToken, options) {
533
533
  }
534
534
  // Temperature is incompatible with extended thinking (adaptive or budget-based).
535
535
  if (options?.temperature !== undefined && !options?.thinkingEnabled &&
536
- !["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-5-5"].includes(model.id)) { // JOHNNESS_PATCH_PROVIDER_CATALOG_67 JOHNNESS_PATCH_OPUS_55_MODEL
536
+ !["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-5-5", "claude-sonnet-5-5"].includes(model.id)) { // JOHNNESS_PATCH_PROVIDER_CATALOG_67 JOHNNESS_PATCH_OPUS_55_MODEL JOHNNESS_PATCH_SONNET_55_MODEL
537
537
  params.temperature = options.temperature;
538
538
  }
539
539
  if (context.tools) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "johns-harness",
3
- "version": "2026.9.35",
3
+ "version": "2026.9.37",
4
4
  "description": "John's Harness: a production agent harness that runs autonomous coding agents as one cooperative swarm.",
5
5
  "keywords": [
6
6
  "ai-agents",
@@ -1666,6 +1666,30 @@ export const MODELS = {
1666
1666
  contextWindow: 300000, // JOHNNESS_PATCH_FABLE_51_CONTEXT_300K
1667
1667
  maxTokens: 128000,
1668
1668
  },
1669
+ /* JOHNNESS_PATCH_SONNET_55_MODEL (family 82): Claude Sonnet 5.5. API id "claude-sonnet-5-5" (fixed id, no
1670
+ date suffix) confirmed against platform.claude.com/docs/en/models/sonnet-5-5/overview on
1671
+ 2026-09-29: $2/$10 per MTok, cache reads $0.20, 5m cache writes $2.50, 1h writes $4,
1672
+ 1M native context, 128K max output, adaptive thinking on by default (effort low through
1673
+ max, default high; between_tools turns up-front thinking off). temperature/top_p/top_k
1674
+ non-default values return 400. contextWindow is the full native 1M (every Sonnet gets
1675
+ its native 1M window; no beta header needed). */
1676
+ "claude-sonnet-5-5": {
1677
+ id: "claude-sonnet-5-5",
1678
+ name: "Claude Sonnet 5.5",
1679
+ api: "anthropic-messages",
1680
+ provider: "anthropic",
1681
+ baseUrl: "https://api.anthropic.com",
1682
+ reasoning: true,
1683
+ input: ["text", "image"],
1684
+ cost: {
1685
+ input: 2,
1686
+ output: 10,
1687
+ cacheRead: 0.2,
1688
+ cacheWrite: 2.5,
1689
+ },
1690
+ contextWindow: 1000000,
1691
+ maxTokens: 128000,
1692
+ },
1669
1693
  /* JOHNNESS_PATCH_OPUS_55_MODEL (family 78): Claude Opus 5.5. API id "claude-opus-5-5" (fixed id, no
1670
1694
  date suffix) confirmed against platform.claude.com/docs/en/models/opus-5-5 on
1671
1695
  2026-09-23: $4/$20 per MTok, cache reads $0.20, 5m cache writes $5, 1M native
@@ -1707,7 +1731,7 @@ export const MODELS = {
1707
1731
  contextWindow: 300000,
1708
1732
  maxTokens: 128000,
1709
1733
  },
1710
- /* JOHNNESS_PATCH_DEFAULTS_61 (family 61): Claude Sonnet 5; 175K effective context; native 1M; 2026-09-13 pricing. */
1734
+ /* JOHNNESS_PATCH_DEFAULTS_61 (family 61): Claude Sonnet 5; native 1M context; 2026-09-13 pricing. */
1711
1735
  "claude-sonnet-5": {
1712
1736
  id: "claude-sonnet-5",
1713
1737
  name: "Claude Sonnet 5",
@@ -1722,7 +1746,7 @@ export const MODELS = {
1722
1746
  cacheRead: 0.2,
1723
1747
  cacheWrite: 2.5,
1724
1748
  },
1725
- contextWindow: 175000,
1749
+ contextWindow: 1000000,
1726
1750
  maxTokens: 128000,
1727
1751
  },
1728
1752
  /* JOHNNESS_PATCH_DEFAULTS_61 (family 61): Claude Fable 5; 300K fable cap, same as fable-5-1. */
@@ -2014,7 +2038,7 @@ export const MODELS = {
2014
2038
  cacheRead: 0.3,
2015
2039
  cacheWrite: 3.75,
2016
2040
  },
2017
- contextWindow: 200000,
2041
+ contextWindow: 1000000, // JOHNNESS_PATCH_SONNET_55_MODEL: every Sonnet gets its native 1M window
2018
2042
  maxTokens: 64000,
2019
2043
  },
2020
2044
  },
@@ -39,6 +39,7 @@ export function supportsXhigh(model) {
39
39
  if (model.provider === "deepseek" && ["deepseek-flash", "deepseek-v4-pro"].includes(model.id)) return true;
40
40
  if (model.provider === "anthropic" && ["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1"].includes(model.id)) return true;
41
41
  if (model.provider === "anthropic" && model.id === "claude-opus-5-5") return true; // JOHNNESS_PATCH_OPUS_55_MODEL
42
+ if (model.provider === "anthropic" && model.id === "claude-sonnet-5-5") return true; // JOHNNESS_PATCH_SONNET_55_MODEL
42
43
  // JOHNNESS_PATCH_MUSE_SPARK
43
44
  if (model.provider === "meta" && ["muse-spark-1.3", "muse-spark-1.2"].includes(model.id)) return true;
44
45
  if (model.id.includes("gpt-5.2") || model.id.includes("gpt-5.3")) {
@@ -353,7 +353,7 @@ function supportsAdaptiveThinking(modelId) {
353
353
  */
354
354
  function mapThinkingLevelToEffort(level, modelId) {
355
355
  // JOHNNESS_PATCH_PROVIDER_CATALOG_67: modern Claude supports distinct xhigh/max.
356
- if (["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1", "claude-opus-5-5"].includes(modelId)) { // JOHNNESS_PATCH_OPUS_55_MODEL
356
+ if (["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1", "claude-opus-5-5", "claude-sonnet-5-5"].includes(modelId)) { // JOHNNESS_PATCH_OPUS_55_MODEL JOHNNESS_PATCH_SONNET_55_MODEL
357
357
  if (["low", "medium", "high", "xhigh", "max"].includes(level)) return level;
358
358
  return level === "minimal" ? "low" : "high";
359
359
  }
@@ -533,7 +533,7 @@ function buildParams(model, context, isOAuthToken, options) {
533
533
  }
534
534
  // Temperature is incompatible with extended thinking (adaptive or budget-based).
535
535
  if (options?.temperature !== undefined && !options?.thinkingEnabled &&
536
- !["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-5-5"].includes(model.id)) { // JOHNNESS_PATCH_PROVIDER_CATALOG_67 JOHNNESS_PATCH_OPUS_55_MODEL
536
+ !["claude-opus-5", "claude-sonnet-5", "claude-fable-5", "claude-fable-5-1", "claude-opus-4-8", "claude-opus-4-7", "claude-opus-5-5", "claude-sonnet-5-5"].includes(model.id)) { // JOHNNESS_PATCH_PROVIDER_CATALOG_67 JOHNNESS_PATCH_OPUS_55_MODEL JOHNNESS_PATCH_SONNET_55_MODEL
537
537
  params.temperature = options.temperature;
538
538
  }
539
539
  if (context.tools) {