johns-harness 2026.9.36 → 2026.9.38

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 (44) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/auth-profiles-5CHn7vq1.js +18 -1
  3. package/dist/channels/plugins/actions/telegram.js +3 -0
  4. package/dist/config-koj5M_EO.js +18 -1
  5. package/dist/daemon-cli.js +18 -1
  6. package/dist/model-selection-BGlGpPgM.js +18 -1
  7. package/dist/model-selection-BU6wl1le.js +18 -1
  8. package/dist/model-selection-L7RMwsG-.js +18 -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 +18 -1
  12. package/dist/plugin-sdk/config-Di-lyCdh.js +18 -1
  13. package/dist/plugin-sdk/discord.js +18 -1
  14. package/dist/plugin-sdk/mattermost.js +3 -0
  15. package/dist/plugin-sdk/model-auth-CX9cPHdC.js +18 -1
  16. package/dist/plugin-sdk/model-auth-Ciehz0x5.js +18 -1
  17. package/dist/plugin-sdk/model-auth-DVyo6JSX.js +18 -1
  18. package/dist/plugin-sdk/model-auth-kiHYHGrs.js +18 -1
  19. package/dist/plugin-sdk/model-selection-Dbj4jDYM.js +18 -1
  20. package/dist/plugin-sdk/thinking-B-rIrY_n.js +3 -0
  21. package/dist/plugin-sdk/thinking-CopbP_Cn.js +3 -0
  22. package/dist/plugin-sdk/thinking-WQ4Zq8Nl.js +3 -0
  23. package/dist/plugin-sdk/thinking-WXqkGljb.js +3 -0
  24. package/dist/plugin-sdk/thinking-_uXqFaFO.js +3 -0
  25. package/dist/plugin-sdk/thinking-pTdxk2dr.js +3 -0
  26. package/dist/thinking-B5B36ffe.js +3 -0
  27. package/dist/thinking-BYwvlJ3S.js +3 -0
  28. package/dist/thinking-CAzdgmNV.js +3 -0
  29. package/dist/thinking-DykY2Fzj.js +3 -0
  30. package/docs/MODELS.md +54 -0
  31. package/docs/PATCHES.md +28 -2
  32. package/docs/PROVIDER-CATALOG.md +6 -2
  33. package/models/models.json +888 -0
  34. package/node_modules/@mariozechner/pi-ai/dist/models.generated.js +853 -6
  35. package/node_modules/@mariozechner/pi-ai/dist/models.js +33 -0
  36. package/node_modules/@mariozechner/pi-ai/dist/providers/openai-codex-responses.js +7 -0
  37. package/node_modules/@mariozechner/pi-ai/dist/providers/openai-responses.js +7 -0
  38. package/package.json +4 -1
  39. package/scripts/check-models-master.mjs +53 -0
  40. package/scripts/models-sync.mjs +383 -0
  41. package/vendor/patched-deps/@mariozechner/pi-ai/dist/models.generated.js +853 -6
  42. package/vendor/patched-deps/@mariozechner/pi-ai/dist/models.js +33 -0
  43. package/vendor/patched-deps/@mariozechner/pi-ai/dist/providers/openai-codex-responses.js +7 -0
  44. package/vendor/patched-deps/@mariozechner/pi-ai/dist/providers/openai-responses.js +7 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.9.38
4
+
5
+ - One master model file: `models/models.json` holds every shipped model (cards, pricing, context windows, max output, xhigh/effort/temperature rules) and every alias, including the "shorthand points to the newest model in its line" rule. `node scripts/models-sync.mjs` generates the catalog, `supportsXhigh`, the Responses/Codex wire rules, the 14 alias tables and the 12 `/think xhigh` gates from it. Adding a model is now: edit that file, run the sync, run the checks, publish (docs/MODELS.md).
6
+ - GPT-6.1 Sol (`gpt-6.1-sol`) ships on `openai` (full native 1,050,000 context) and `openai-codex` (272K, the Codex backend window): 128K max output, $2/$10 per MTok, cached input $0.10, cache write $2.50, effort low through max (default medium). The API rejects `none`/`minimal` (sent as `low`) and `temperature`/`top_p` at every effort (dropped).
7
+ - Aliases: `sol` and `gpt` now resolve to `openai-codex/gpt-6.1-sol`; `sol6` keeps GPT-6 Sol. `luna` stays on GPT-6 Luna (no GPT-6.1 Luna on the API yet); `astra` unchanged.
8
+ - Family 83; verifier checks 83.1-83.6. Roll back with `npm i -g johns-harness@2026.9.37`.
9
+
10
+ ## 2026.9.37
11
+
12
+ - 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).
13
+ - 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.
14
+ - 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`.
15
+
3
16
  ## 2026.9.36
4
17
 
5
18
  - 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.
@@ -5156,6 +5156,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
5156
5156
  grok: "xai/grok-4.7",
5157
5157
  grok46: "xai/grok-4.6"
5158
5158
  });
5159
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
5160
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
5161
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
5162
+ /* JOHNNESS_MODELS_MASTER:END */
5159
5163
  const DEFAULT_MODEL_COST = {
5160
5164
  input: 0,
5161
5165
  output: 0,
@@ -5367,7 +5371,7 @@ function applyModelDefaults(cfg) {
5367
5371
  if (raw.input === void 0) modelMutated = true;
5368
5372
  const cost = resolveModelCost(raw.cost);
5369
5373
  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;
5370
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5374
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5371
5375
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5372
5376
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5373
5377
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5433,6 +5437,19 @@ function applyModelDefaults(cfg) {
5433
5437
  }
5434
5438
  };
5435
5439
  }
5440
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5441
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5442
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5443
+ config, models.json, compaction and session snapshots all read this one value. */
5444
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5445
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5446
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5447
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5448
+ if (!match) return;
5449
+ const major = Number(match[1]);
5450
+ const minor = Number(match[2] ?? 0);
5451
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5452
+ }
5436
5453
  function applyAgentDefaults(cfg) {
5437
5454
  const agents = cfg.agents;
5438
5455
  const defaults = agents?.defaults;
@@ -2131,6 +2131,9 @@ const XHIGH_MODEL_REFS = [
2131
2131
  "github-copilot/gpt-5.2-codex",
2132
2132
  "github-copilot/gpt-5.2"
2133
2133
  ];
2134
+ /* JOHNNESS_MODELS_MASTER:BEGIN xhigh refs (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
2135
+ XHIGH_MODEL_REFS.splice(0, XHIGH_MODEL_REFS.length, ...['deepseek/deepseek-flash','deepseek/deepseek-v4-pro','meta/muse-spark-1.3','meta/muse-spark-1.2','anthropic/claude-fable-5-1','anthropic/claude-sonnet-5-5','anthropic/claude-opus-5-5','anthropic/claude-opus-5','anthropic/claude-sonnet-5','anthropic/claude-fable-5','anthropic/claude-opus-4-6','azure-openai-responses/gpt-5.2','azure-openai-responses/gpt-5.2-chat-latest','azure-openai-responses/gpt-5.2-codex','azure-openai-responses/gpt-5.2-pro','azure-openai-responses/gpt-5.3-codex','azure-openai-responses/gpt-5.3-codex-spark','github-copilot/claude-opus-4.6','github-copilot/gpt-5.2','github-copilot/gpt-5.2-codex','openai/gpt-5.2','openai/gpt-5.2-chat-latest','openai/gpt-5.2-codex','openai/gpt-5.2-pro','openai/gpt-5.3-codex','openai/gpt-5.3-codex-spark','openai/gpt-6-astra','openai/gpt-6.1-sol','openai/gpt-6-sol','openai/gpt-6-luna','openai/gpt-5.6-sol','openai/gpt-5.6-terra','openai/gpt-5.6-luna','openai-codex/gpt-5.2','openai-codex/gpt-5.2-codex','openai-codex/gpt-5.3-codex','openai-codex/gpt-5.3-codex-spark','openai-codex/gpt-6.1-sol','openai-codex/gpt-6-sol','openai-codex/gpt-6-luna','openai-codex/gpt-6-astra','openai-codex/gpt-5.6-sol','openai-codex/gpt-5.6-terra','openai-codex/gpt-5.6-luna','opencode/claude-opus-4-6','opencode/gpt-5.2','opencode/gpt-5.2-codex','opencode/gpt-5.3-codex','openrouter/openai/gpt-5.2','openrouter/openai/gpt-5.2-chat','openrouter/openai/gpt-5.2-codex','openrouter/openai/gpt-5.2-pro','openrouter/openai/gpt-5.3-codex','vercel-ai-gateway/anthropic/claude-opus-4.6','vercel-ai-gateway/openai/gpt-5.2','vercel-ai-gateway/openai/gpt-5.2-chat','vercel-ai-gateway/openai/gpt-5.2-codex','vercel-ai-gateway/openai/gpt-5.2-pro','vercel-ai-gateway/openai/gpt-5.3-codex','xai/grok-4.7','xai/grok-4.6','openai/gpt-5.4','openai/gpt-5.4-pro','openai/gpt-5.6','openai-codex/gpt-5.6','openai-codex/gpt-5.4','openai-codex/gpt-5.1-codex']);
2136
+ /* JOHNNESS_MODELS_MASTER:END */
2134
2137
  new Set(XHIGH_MODEL_REFS.map((entry) => entry.toLowerCase()));
2135
2138
  new Set(XHIGH_MODEL_REFS.map((entry) => entry.split("/")[1]?.toLowerCase()).filter((entry) => Boolean(entry)));
2136
2139
  //#endregion
@@ -1851,6 +1851,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
1851
1851
  grok: "xai/grok-4.7",
1852
1852
  grok46: "xai/grok-4.6"
1853
1853
  });
1854
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
1855
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
1856
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
1857
+ /* JOHNNESS_MODELS_MASTER:END */
1854
1858
  const DEFAULT_MODEL_COST = {
1855
1859
  input: 0,
1856
1860
  output: 0,
@@ -2062,7 +2066,7 @@ function applyModelDefaults(cfg) {
2062
2066
  if (raw.input === void 0) modelMutated = true;
2063
2067
  const cost = resolveModelCost(raw.cost);
2064
2068
  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;
2065
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
2069
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
2066
2070
  if (raw.contextWindow !== contextWindow) modelMutated = true;
2067
2071
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
2068
2072
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -2128,6 +2132,19 @@ function applyModelDefaults(cfg) {
2128
2132
  }
2129
2133
  };
2130
2134
  }
2135
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
2136
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
2137
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
2138
+ config, models.json, compaction and session snapshots all read this one value. */
2139
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
2140
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
2141
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
2142
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
2143
+ if (!match) return;
2144
+ const major = Number(match[1]);
2145
+ const minor = Number(match[2] ?? 0);
2146
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
2147
+ }
2131
2148
  function applyAgentDefaults(cfg) {
2132
2149
  const agents = cfg.agents;
2133
2150
  const defaults = agents?.defaults;
@@ -5003,6 +5003,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
5003
5003
  grok: "xai/grok-4.7",
5004
5004
  grok46: "xai/grok-4.6"
5005
5005
  });
5006
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
5007
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
5008
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
5009
+ /* JOHNNESS_MODELS_MASTER:END */
5006
5010
  const DEFAULT_MODEL_COST = {
5007
5011
  input: 0,
5008
5012
  output: 0,
@@ -5214,7 +5218,7 @@ function applyModelDefaults(cfg) {
5214
5218
  if (raw.input === void 0) modelMutated = true;
5215
5219
  const cost = resolveModelCost(raw.cost);
5216
5220
  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;
5217
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5221
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5218
5222
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5219
5223
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5220
5224
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5280,6 +5284,19 @@ function applyModelDefaults(cfg) {
5280
5284
  }
5281
5285
  };
5282
5286
  }
5287
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5288
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5289
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5290
+ config, models.json, compaction and session snapshots all read this one value. */
5291
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5292
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5293
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5294
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5295
+ if (!match) return;
5296
+ const major = Number(match[1]);
5297
+ const minor = Number(match[2] ?? 0);
5298
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5299
+ }
5283
5300
  function applyAgentDefaults(cfg) {
5284
5301
  const agents = cfg.agents;
5285
5302
  const defaults = agents?.defaults;
@@ -1708,6 +1708,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
1708
1708
  grok: "xai/grok-4.7",
1709
1709
  grok46: "xai/grok-4.6"
1710
1710
  });
1711
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
1712
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
1713
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
1714
+ /* JOHNNESS_MODELS_MASTER:END */
1711
1715
  const DEFAULT_MODEL_COST = {
1712
1716
  input: 0,
1713
1717
  output: 0,
@@ -1938,7 +1942,7 @@ function applyModelDefaults(cfg) {
1938
1942
  if (raw.input === void 0) modelMutated = true;
1939
1943
  const cost = resolveModelCost(raw.cost);
1940
1944
  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;
1941
- const contextWindow = resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS);
1945
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
1942
1946
  if (raw.contextWindow !== contextWindow) modelMutated = true;
1943
1947
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
1944
1948
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -2004,6 +2008,19 @@ function applyModelDefaults(cfg) {
2004
2008
  }
2005
2009
  };
2006
2010
  }
2011
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
2012
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
2013
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
2014
+ config, models.json, compaction and session snapshots all read this one value. */
2015
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
2016
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
2017
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
2018
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
2019
+ if (!match) return;
2020
+ const major = Number(match[1]);
2021
+ const minor = Number(match[2] ?? 0);
2022
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
2023
+ }
2007
2024
  function applyAgentDefaults(cfg) {
2008
2025
  const agents = cfg.agents;
2009
2026
  const defaults = agents?.defaults;
@@ -1683,6 +1683,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
1683
1683
  grok: "xai/grok-4.7",
1684
1684
  grok46: "xai/grok-4.6"
1685
1685
  });
1686
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
1687
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
1688
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
1689
+ /* JOHNNESS_MODELS_MASTER:END */
1686
1690
  const DEFAULT_MODEL_COST = {
1687
1691
  input: 0,
1688
1692
  output: 0,
@@ -1913,7 +1917,7 @@ function applyModelDefaults(cfg) {
1913
1917
  if (raw.input === void 0) modelMutated = true;
1914
1918
  const cost = resolveModelCost(raw.cost);
1915
1919
  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;
1916
- const contextWindow = resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS);
1920
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
1917
1921
  if (raw.contextWindow !== contextWindow) modelMutated = true;
1918
1922
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
1919
1923
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -1979,6 +1983,19 @@ function applyModelDefaults(cfg) {
1979
1983
  }
1980
1984
  };
1981
1985
  }
1986
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
1987
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
1988
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
1989
+ config, models.json, compaction and session snapshots all read this one value. */
1990
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
1991
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
1992
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
1993
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
1994
+ if (!match) return;
1995
+ const major = Number(match[1]);
1996
+ const minor = Number(match[2] ?? 0);
1997
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
1998
+ }
1982
1999
  function applyAgentDefaults(cfg) {
1983
2000
  const agents = cfg.agents;
1984
2001
  const defaults = agents?.defaults;
@@ -1614,6 +1614,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
1614
1614
  grok: "xai/grok-4.7",
1615
1615
  grok46: "xai/grok-4.6"
1616
1616
  });
1617
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
1618
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
1619
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
1620
+ /* JOHNNESS_MODELS_MASTER:END */
1617
1621
  const DEFAULT_MODEL_COST = {
1618
1622
  input: 0,
1619
1623
  output: 0,
@@ -1844,7 +1848,7 @@ function applyModelDefaults(cfg) {
1844
1848
  if (raw.input === void 0) modelMutated = true;
1845
1849
  const cost = resolveModelCost(raw.cost);
1846
1850
  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;
1847
- const contextWindow = resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS);
1851
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? resolveJohnnessOpusContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
1848
1852
  if (raw.contextWindow !== contextWindow) modelMutated = true;
1849
1853
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
1850
1854
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -1910,6 +1914,19 @@ function applyModelDefaults(cfg) {
1910
1914
  }
1911
1915
  };
1912
1916
  }
1917
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
1918
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
1919
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
1920
+ config, models.json, compaction and session snapshots all read this one value. */
1921
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
1922
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
1923
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
1924
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
1925
+ if (!match) return;
1926
+ const major = Number(match[1]);
1927
+ const minor = Number(match[2] ?? 0);
1928
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
1929
+ }
1913
1930
  function applyAgentDefaults(cfg) {
1914
1931
  const agents = cfg.agents;
1915
1932
  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;
@@ -7101,6 +7101,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
7101
7101
  grok: "xai/grok-4.7",
7102
7102
  grok46: "xai/grok-4.6"
7103
7103
  });
7104
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
7105
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
7106
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
7107
+ /* JOHNNESS_MODELS_MASTER:END */
7104
7108
  const DEFAULT_MODEL_COST = {
7105
7109
  input: 0,
7106
7110
  output: 0,
@@ -7312,7 +7316,7 @@ function applyModelDefaults(cfg) {
7312
7316
  if (raw.input === void 0) modelMutated = true;
7313
7317
  const cost = resolveModelCost(raw.cost);
7314
7318
  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;
7315
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
7319
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
7316
7320
  if (raw.contextWindow !== contextWindow) modelMutated = true;
7317
7321
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
7318
7322
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -7378,6 +7382,19 @@ function applyModelDefaults(cfg) {
7378
7382
  }
7379
7383
  };
7380
7384
  }
7385
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
7386
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
7387
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
7388
+ config, models.json, compaction and session snapshots all read this one value. */
7389
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
7390
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
7391
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
7392
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
7393
+ if (!match) return;
7394
+ const major = Number(match[1]);
7395
+ const minor = Number(match[2] ?? 0);
7396
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
7397
+ }
7381
7398
  function applyAgentDefaults(cfg) {
7382
7399
  const agents = cfg.agents;
7383
7400
  const defaults = agents?.defaults;
@@ -8102,6 +8102,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
8102
8102
  grok: "xai/grok-4.7",
8103
8103
  grok46: "xai/grok-4.6"
8104
8104
  });
8105
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
8106
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
8107
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
8108
+ /* JOHNNESS_MODELS_MASTER:END */
8105
8109
  const DEFAULT_MODEL_COST = {
8106
8110
  input: 0,
8107
8111
  output: 0,
@@ -8313,7 +8317,7 @@ function applyModelDefaults(cfg) {
8313
8317
  if (raw.input === void 0) modelMutated = true;
8314
8318
  const cost = resolveModelCost(raw.cost);
8315
8319
  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;
8316
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
8320
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
8317
8321
  if (raw.contextWindow !== contextWindow) modelMutated = true;
8318
8322
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
8319
8323
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -8379,6 +8383,19 @@ function applyModelDefaults(cfg) {
8379
8383
  }
8380
8384
  };
8381
8385
  }
8386
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
8387
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
8388
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
8389
+ config, models.json, compaction and session snapshots all read this one value. */
8390
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
8391
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
8392
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
8393
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
8394
+ if (!match) return;
8395
+ const major = Number(match[1]);
8396
+ const minor = Number(match[2] ?? 0);
8397
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
8398
+ }
8382
8399
  function applyAgentDefaults(cfg) {
8383
8400
  const agents = cfg.agents;
8384
8401
  const defaults = agents?.defaults;
@@ -5231,6 +5231,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
5231
5231
  grok: "xai/grok-4.7",
5232
5232
  grok46: "xai/grok-4.6"
5233
5233
  });
5234
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
5235
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
5236
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
5237
+ /* JOHNNESS_MODELS_MASTER:END */
5234
5238
  const DEFAULT_MODEL_COST = {
5235
5239
  input: 0,
5236
5240
  output: 0,
@@ -5442,7 +5446,7 @@ function applyModelDefaults(cfg) {
5442
5446
  if (raw.input === void 0) modelMutated = true;
5443
5447
  const cost = resolveModelCost(raw.cost);
5444
5448
  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;
5445
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
5449
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
5446
5450
  if (raw.contextWindow !== contextWindow) modelMutated = true;
5447
5451
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
5448
5452
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -5508,6 +5512,19 @@ function applyModelDefaults(cfg) {
5508
5512
  }
5509
5513
  };
5510
5514
  }
5515
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
5516
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
5517
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
5518
+ config, models.json, compaction and session snapshots all read this one value. */
5519
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
5520
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
5521
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
5522
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
5523
+ if (!match) return;
5524
+ const major = Number(match[1]);
5525
+ const minor = Number(match[2] ?? 0);
5526
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
5527
+ }
5511
5528
  function applyAgentDefaults(cfg) {
5512
5529
  const agents = cfg.agents;
5513
5530
  const defaults = agents?.defaults;
@@ -3156,6 +3156,9 @@ const XHIGH_MODEL_REFS = [
3156
3156
  "github-copilot/gpt-5.2-codex",
3157
3157
  "github-copilot/gpt-5.2"
3158
3158
  ];
3159
+ /* JOHNNESS_MODELS_MASTER:BEGIN xhigh refs (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
3160
+ XHIGH_MODEL_REFS.splice(0, XHIGH_MODEL_REFS.length, ...['deepseek/deepseek-flash','deepseek/deepseek-v4-pro','meta/muse-spark-1.3','meta/muse-spark-1.2','anthropic/claude-fable-5-1','anthropic/claude-sonnet-5-5','anthropic/claude-opus-5-5','anthropic/claude-opus-5','anthropic/claude-sonnet-5','anthropic/claude-fable-5','anthropic/claude-opus-4-6','azure-openai-responses/gpt-5.2','azure-openai-responses/gpt-5.2-chat-latest','azure-openai-responses/gpt-5.2-codex','azure-openai-responses/gpt-5.2-pro','azure-openai-responses/gpt-5.3-codex','azure-openai-responses/gpt-5.3-codex-spark','github-copilot/claude-opus-4.6','github-copilot/gpt-5.2','github-copilot/gpt-5.2-codex','openai/gpt-5.2','openai/gpt-5.2-chat-latest','openai/gpt-5.2-codex','openai/gpt-5.2-pro','openai/gpt-5.3-codex','openai/gpt-5.3-codex-spark','openai/gpt-6-astra','openai/gpt-6.1-sol','openai/gpt-6-sol','openai/gpt-6-luna','openai/gpt-5.6-sol','openai/gpt-5.6-terra','openai/gpt-5.6-luna','openai-codex/gpt-5.2','openai-codex/gpt-5.2-codex','openai-codex/gpt-5.3-codex','openai-codex/gpt-5.3-codex-spark','openai-codex/gpt-6.1-sol','openai-codex/gpt-6-sol','openai-codex/gpt-6-luna','openai-codex/gpt-6-astra','openai-codex/gpt-5.6-sol','openai-codex/gpt-5.6-terra','openai-codex/gpt-5.6-luna','opencode/claude-opus-4-6','opencode/gpt-5.2','opencode/gpt-5.2-codex','opencode/gpt-5.3-codex','openrouter/openai/gpt-5.2','openrouter/openai/gpt-5.2-chat','openrouter/openai/gpt-5.2-codex','openrouter/openai/gpt-5.2-pro','openrouter/openai/gpt-5.3-codex','vercel-ai-gateway/anthropic/claude-opus-4.6','vercel-ai-gateway/openai/gpt-5.2','vercel-ai-gateway/openai/gpt-5.2-chat','vercel-ai-gateway/openai/gpt-5.2-codex','vercel-ai-gateway/openai/gpt-5.2-pro','vercel-ai-gateway/openai/gpt-5.3-codex','xai/grok-4.7','xai/grok-4.6','openai/gpt-5.4','openai/gpt-5.4-pro','openai/gpt-5.6','openai-codex/gpt-5.6','openai-codex/gpt-5.4','openai-codex/gpt-5.1-codex']);
3161
+ /* JOHNNESS_MODELS_MASTER:END */
3159
3162
  const XHIGH_MODEL_SET = new Set(XHIGH_MODEL_REFS.map((entry) => entry.toLowerCase()));
3160
3163
  const XHIGH_MODEL_IDS = new Set(XHIGH_MODEL_REFS.map((entry) => entry.split("/")[1]?.toLowerCase()).filter((entry) => Boolean(entry)));
3161
3164
  function supportsXHighThinking(provider, model) {
@@ -6022,6 +6022,10 @@ Object.assign(DEFAULT_MODEL_ALIASES, {
6022
6022
  grok: "xai/grok-4.7",
6023
6023
  grok46: "xai/grok-4.6"
6024
6024
  });
6025
+ /* JOHNNESS_MODELS_MASTER:BEGIN aliases (generated from models/models.json by scripts/models-sync.mjs; edit the master, not this block) */
6026
+ const JOHNNESS_MASTER_ALIASES = {"deepseek":"deepseek/deepseek-flash","deepseek-pro":"deepseek/deepseek-v4-pro","gemini-lite":"google/gemini-3.5-flash-lite","muse":"meta/muse-spark-1.3","muse-spark":"meta/muse-spark-1.3","opus46":"anthropic/claude-opus-4-6","sonnet46":"anthropic/claude-sonnet-4-6","gpt-mini":"openai/gpt-5-mini","gemini":"google/gemini-3.1-pro-preview","gemini-flash":"google/gemini-3.8-flash","gemini-flash-lite":"google/gemini-2.5-flash-lite","flash":"google/gemini-3.8-flash","banana":"google/gemini-3-pro-image-preview","nano-banana":"google/gemini-3-pro-image-preview","image":"openai-codex/gpt-image-2","sonnet5":"anthropic/claude-sonnet-5","opus5":"anthropic/claude-opus-5","sol6":"openai-codex/gpt-6-sol","sol56":"openai-codex/gpt-5.6-sol","luna56":"openai-codex/gpt-5.6-luna","grok46":"xai/grok-4.6","opus":"anthropic/claude-opus-5-5","sonnet":"anthropic/claude-sonnet-5-5","fable":"anthropic/claude-fable-5-1","gpt":"openai-codex/gpt-6.1-sol","sol":"openai-codex/gpt-6.1-sol","luna":"openai-codex/gpt-6-luna","astra":"openai-codex/gpt-6-astra","terra":"openai-codex/gpt-5.6-terra","grok":"xai/grok-4.7"};
6027
+ for (const [alias, ref] of Object.entries(JOHNNESS_MASTER_ALIASES)) DEFAULT_MODEL_ALIASES[alias] = ref;
6028
+ /* JOHNNESS_MODELS_MASTER:END */
6025
6029
  const DEFAULT_MODEL_COST = {
6026
6030
  input: 0,
6027
6031
  output: 0,
@@ -6233,7 +6237,7 @@ function applyModelDefaults(cfg) {
6233
6237
  if (raw.input === void 0) modelMutated = true;
6234
6238
  const cost = resolveModelCost(raw.cost);
6235
6239
  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;
6236
- const contextWindow = isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS;
6240
+ const contextWindow = resolveJohnnessSonnetNativeContextWindow(providerId, raw.id) ?? (isPositiveNumber(raw.contextWindow) ? raw.contextWindow : DEFAULT_CONTEXT_TOKENS); // JOHNNESS_PATCH_SONNET_55_MODEL
6237
6241
  if (raw.contextWindow !== contextWindow) modelMutated = true;
6238
6242
  const defaultMaxTokens = Math.min(DEFAULT_MODEL_MAX_TOKENS, contextWindow);
6239
6243
  const rawMaxTokens = isPositiveNumber(raw.maxTokens) ? raw.maxTokens : defaultMaxTokens;
@@ -6299,6 +6303,19 @@ function applyModelDefaults(cfg) {
6299
6303
  }
6300
6304
  };
6301
6305
  }
6306
+ /* JOHNNESS_PATCH_SONNET_55_MODEL: every Anthropic Sonnet from Sonnet 4.6 on (claude-sonnet-4-6, claude-sonnet-5,
6307
+ claude-sonnet-5-5 and every later Sonnet) runs on its full native 1M context window; the harness
6308
+ never caps a Sonnet. Anthropic serves 1M by default on these models (no beta header). Resolved
6309
+ config, models.json, compaction and session snapshots all read this one value. */
6310
+ function resolveJohnnessSonnetNativeContextWindow(providerId, modelId) {
6311
+ const JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS = 1e6; // function-scoped: callable before module init completes
6312
+ if (String(providerId ?? "").trim().toLowerCase() !== "anthropic") return;
6313
+ const match = /^claude-sonnet-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?$/.exec(String(modelId ?? "").trim().toLowerCase());
6314
+ if (!match) return;
6315
+ const major = Number(match[1]);
6316
+ const minor = Number(match[2] ?? 0);
6317
+ if (major > 4 || (major === 4 && minor >= 6)) return JOHNNESS_SONNET_NATIVE_CONTEXT_TOKENS;
6318
+ }
6302
6319
  function applyAgentDefaults(cfg) {
6303
6320
  const agents = cfg.agents;
6304
6321
  const defaults = agents?.defaults;