sneakoscope 6.0.0 → 6.0.2

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 (89) hide show
  1. package/README.md +2 -1
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/bin/fast-inline.js +0 -40
  5. package/dist/bin/sks-dispatch.js +0 -16
  6. package/dist/cli/codex-app-command.js +1 -2
  7. package/dist/cli/help-fast.js +2 -2
  8. package/dist/cli/install-helpers.js +26 -21
  9. package/dist/config/skills-manifest.json +57 -57
  10. package/dist/core/agents/agent-effort-policy.js +19 -38
  11. package/dist/core/agents/agent-orchestrator.js +2 -2
  12. package/dist/core/agents/agent-role-config.js +17 -10
  13. package/dist/core/agents/agent-roster.js +19 -39
  14. package/dist/core/agents/agent-scheduler.js +6 -5
  15. package/dist/core/agents/agent-schema.js +4 -5
  16. package/dist/core/agents/agent-task-graph.js +1 -1
  17. package/dist/core/agents/agent-work-partition.js +2 -1
  18. package/dist/core/agents/native-worker-backend-router.js +1 -1
  19. package/dist/core/agents/route-collaboration-ledger.js +2 -2
  20. package/dist/core/auto-review.js +1 -4
  21. package/dist/core/codex/codex-config-guard.js +11 -9
  22. package/dist/core/codex-adapter.js +2 -2
  23. package/dist/core/codex-app/codex-agent-role-sync.js +0 -1
  24. package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -4
  25. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +1 -7
  26. package/dist/core/codex-app.js +0 -2
  27. package/dist/core/codex-control/codex-model-capabilities.js +1 -2
  28. package/dist/core/codex-control/codex-model-metadata.js +13 -6
  29. package/dist/core/codex-control/codex-sdk-config-policy.js +3 -3
  30. package/dist/core/codex-control/codex-task-runner.js +2 -3
  31. package/dist/core/codex-model-guard.js +24 -89
  32. package/dist/core/commands/basic-cli.js +6 -0
  33. package/dist/core/commands/loop-command.js +2 -2
  34. package/dist/core/commands/mad-db-command.js +1 -1
  35. package/dist/core/commands/naruto-command.js +11 -11
  36. package/dist/core/commands/profile-command.js +14 -5
  37. package/dist/core/commands/qa-loop-command.js +2 -2
  38. package/dist/core/commands/research-command.js +2 -2
  39. package/dist/core/doctor/doctor-codex-startup-repair.js +0 -3
  40. package/dist/core/evaluation.js +1 -1
  41. package/dist/core/feature-fixtures.js +2 -2
  42. package/dist/core/feature-registry.js +1 -1
  43. package/dist/core/hooks-runtime.js +7 -45
  44. package/dist/core/image-ux-review/imagegen-adapter.js +17 -2
  45. package/dist/core/init/skills.js +6 -7
  46. package/dist/core/init.js +7 -20
  47. package/dist/core/loops/loop-concurrency-budget.js +6 -4
  48. package/dist/core/loops/loop-planner.js +1 -1
  49. package/dist/core/loops/loop-runtime.js +2 -2
  50. package/dist/core/loops/loop-scheduler.js +7 -7
  51. package/dist/core/managed-assets/managed-assets-manifest.js +1 -4
  52. package/dist/core/naruto/naruto-concurrency-governor.js +20 -17
  53. package/dist/core/naruto/naruto-loop-mesh.js +3 -3
  54. package/dist/core/naruto/resource-pressure-monitor.js +5 -2
  55. package/dist/core/provider/model-router.js +15 -35
  56. package/dist/core/release/release-gate-batch-runner.js +2 -1
  57. package/dist/core/release/release-gate-resource-governor.js +12 -12
  58. package/dist/core/release/resource-class-budget.js +5 -5
  59. package/dist/core/routes/constants.js +3 -4
  60. package/dist/core/routes.js +1 -1
  61. package/dist/core/structured-output-adapter.js +15 -1
  62. package/dist/core/update/update-migration-state.js +3 -16
  63. package/dist/core/version.js +1 -1
  64. package/dist/scripts/agent-backfill-replenishment-check.js +1 -1
  65. package/dist/scripts/agent-dynamic-pool-check.js +3 -3
  66. package/dist/scripts/agent-dynamic-pool-fixture.js +1 -1
  67. package/dist/scripts/agent-goal-mode-propagation-check.js +1 -1
  68. package/dist/scripts/agent-patch-swarm-gate-lib.js +2 -2
  69. package/dist/scripts/agent-role-config-repair-check.js +9 -5
  70. package/dist/scripts/agent-scheduler-proof-check.js +1 -1
  71. package/dist/scripts/agent-scheduler-proof-hardening-check.js +1 -1
  72. package/dist/scripts/agent-source-intelligence-propagation-check.js +1 -1
  73. package/dist/scripts/agent-strategy-to-lease-wiring-check.js +2 -2
  74. package/dist/scripts/agent-zellij-dynamic-backfill-panes-check.js +1 -1
  75. package/dist/scripts/codex-app-fast-ui-preservation-check.js +2 -2
  76. package/dist/scripts/codex-app-ui-preservation-check.js +6 -5
  77. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +4 -4
  78. package/dist/scripts/codex-lb-gpt55-fast-profile-check.js +3 -2
  79. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +6 -6
  80. package/dist/scripts/install-update-preserves-config-check.js +3 -3
  81. package/dist/scripts/loop-hardening-check-lib.js +1 -1
  82. package/dist/scripts/naruto-parallelism-mode-check.js +2 -1
  83. package/dist/scripts/naruto-shadow-clone-swarm-check.js +25 -32
  84. package/dist/scripts/npm-publish-performance-check.js +1 -1
  85. package/dist/scripts/release-aggressive-resource-governor-check.js +2 -2
  86. package/dist/scripts/release-parallel-check.js +1 -2
  87. package/dist/scripts/release-real-check.js +1 -1
  88. package/dist/scripts/sizecheck.js +3 -3
  89. package/package.json +3 -2
package/README.md CHANGED
@@ -25,7 +25,7 @@ sneakoscope is a proof-first Codex trust layer for bounded agent workflows, sear
25
25
 
26
26
  Sneakoscope Codex (`sks`) is a Codex CLI and Codex App harness for people who want parallel AI coding without losing proof. It gives Codex a simple front door, a dynamic worker swarm, a local dashboard, TriWiki project memory, and release gates that separate machine evidence from LLM opinion.
27
27
 
28
- Current release: SKS **6.0.0**. New in this release: GPT-5.6 Sol/Terra/Luna compatibility, removal of legacy `multi_agent_v2`/Fast-mode config stamps, renewed Codex App feature flags, safer menu bar and doctor repair paths, and release metadata prepared for `npm publish --ignore-scripts`. See [CHANGELOG.md](CHANGELOG.md).
28
+ Current release: SKS **6.0.2**. This release lets Codex own the complete model catalog—including current and future GPT-5.6 options—without SKS allowlists or silent model replacement. It also bounds agent, loop, and release concurrency to keep Codex Desktop responsive, preserves explicit user model/provider choices during repair and updates, and adds a clean-build verification path for `npm publish --ignore-scripts`. See [CHANGELOG.md](CHANGELOG.md).
29
29
 
30
30
  ## Install
31
31
 
@@ -96,6 +96,7 @@ It shows the v5 flow: one-line install, `$Plan`, `$Work`/`$Swarm`, `sks review`,
96
96
  - Native capability repair: `sks doctor --fix` (imagegen/Computer Use/Browser Use), `.sneakoscope/reports/native-capability-readiness.json`
97
97
  - Agent bridge for any agent system: `sks mcp-server`, `sks agent-bridge setup`, `SKS_AGENT_MODE=1` — see [docs/AGENT-BRIDGE.md](docs/AGENT-BRIDGE.md)
98
98
  - Release gates: `node ./dist/scripts/release-gate-dag-runner.js --preset release --full`
99
+ - Lifecycle-disabled npm release: run `npm run publish:verify-ignore-scripts` first, then `npm publish --ignore-scripts`; the raw publish command intentionally cannot run build or validation hooks.
99
100
  - Release readiness notes: [docs/release-readiness.md](docs/release-readiness.md) and [CHANGELOG.md](CHANGELOG.md)
100
101
  - Image generation review routes require Codex App `$imagegen`/`gpt-image-2` evidence with recorded output hashes; direct API fallback and mock fixtures do not satisfy full route gates.
101
102
 
@@ -76,7 +76,7 @@ dependencies = [
76
76
 
77
77
  [[package]]
78
78
  name = "sks-core"
79
- version = "6.0.0"
79
+ version = "6.0.2"
80
80
  dependencies = [
81
81
  "serde_json",
82
82
  ]
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "sks-core"
3
- version = "6.0.0"
3
+ version = "6.0.2"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -151,43 +151,3 @@ exports.rootJsonFastInline = rootJsonFastInline;
151
151
  exports.doctorJsonFastInline = doctorJsonFastInline;
152
152
  exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
153
153
  exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
154
-
155
- exports.rootJsonFastInline = rootJsonFastInline;
156
- exports.doctorJsonFastInline = doctorJsonFastInline;
157
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
158
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
159
-
160
- exports.rootJsonFastInline = rootJsonFastInline;
161
- exports.doctorJsonFastInline = doctorJsonFastInline;
162
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
163
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
164
-
165
- exports.rootJsonFastInline = rootJsonFastInline;
166
- exports.doctorJsonFastInline = doctorJsonFastInline;
167
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
168
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
169
-
170
- exports.rootJsonFastInline = rootJsonFastInline;
171
- exports.doctorJsonFastInline = doctorJsonFastInline;
172
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
173
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
174
-
175
- exports.rootJsonFastInline = rootJsonFastInline;
176
- exports.doctorJsonFastInline = doctorJsonFastInline;
177
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
178
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
179
-
180
- exports.rootJsonFastInline = rootJsonFastInline;
181
- exports.doctorJsonFastInline = doctorJsonFastInline;
182
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
183
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
184
-
185
- exports.rootJsonFastInline = rootJsonFastInline;
186
- exports.doctorJsonFastInline = doctorJsonFastInline;
187
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
188
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
189
-
190
- exports.rootJsonFastInline = rootJsonFastInline;
191
- exports.doctorJsonFastInline = doctorJsonFastInline;
192
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
193
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
@@ -60,19 +60,3 @@ async function runSks(args) {
60
60
  }
61
61
 
62
62
  exports.runSks = runSks;
63
-
64
- exports.runSks = runSks;
65
-
66
- exports.runSks = runSks;
67
-
68
- exports.runSks = runSks;
69
-
70
- exports.runSks = runSks;
71
-
72
- exports.runSks = runSks;
73
-
74
- exports.runSks = runSks;
75
-
76
- exports.runSks = runSks;
77
-
78
- exports.runSks = runSks;
@@ -1,6 +1,5 @@
1
1
  import { spawn } from 'node:child_process';
2
2
  import { codexRemoteControlStatus, formatCodexRemoteControlStatus } from '../core/codex-app.js';
3
- import { forceRequiredCodexModelConfigArgs } from '../core/codex-model-guard.js';
4
3
  export async function codexAppRemoteControlCommand(args = [], opts = {}) {
5
4
  const controlArgs = argsBeforeSeparator(args);
6
5
  if (controlArgs.includes('--help') || controlArgs.includes('-h')) {
@@ -25,7 +24,7 @@ export async function codexAppRemoteControlCommand(args = [], opts = {}) {
25
24
  process.exitCode = 1;
26
25
  return;
27
26
  }
28
- const passthrough = forceRequiredCodexModelConfigArgs(stripSeparator(args));
27
+ const passthrough = stripSeparator(args).map((arg) => String(arg));
29
28
  const spawnFn = opts.spawn || spawn;
30
29
  const code = await spawnInherited(spawnFn, status.codex_cli.bin, ['remote-control', ...passthrough], {
31
30
  cwd: process.cwd(),
@@ -1,8 +1,8 @@
1
1
  import { COMMAND_MANIFEST_LITE } from './command-manifest-lite.js';
2
- const FAST_PACKAGE_VERSION = '5.10.0';
2
+ import { PACKAGE_VERSION } from '../core/version.js';
3
3
  export function helpFast() {
4
4
  console.log(`SKS
5
- SNEAKOSCOPE CODEX v${FAST_PACKAGE_VERSION}
5
+ SNEAKOSCOPE CODEX v${PACKAGE_VERSION}
6
6
 
7
7
  3-pillar frontdoor
8
8
 
@@ -23,7 +23,6 @@ import { extractTomlTable, writeCodexConfigGuarded } from '../core/codex/codex-c
23
23
  import { cleanupCodexConfigBackups, validateCodexConfigRoundTrip } from '../core/codex/codex-config-toml.js';
24
24
  import { runPostinstallGlobalDoctorAndMarkPending } from '../core/update/update-migration-state.js';
25
25
  import { repairCodexImagegen } from '../core/doctor/imagegen-repair.js';
26
- import { GPT55_CODEX_MODEL, REQUIRED_CODEX_MODEL } from '../core/codex-model-guard.js';
27
26
  const CODEX_LB_PROVIDER_NAME = 'openai';
28
27
  const CODEX_LB_PROVIDER_ENV_KEY = 'CODEX_LB_API_KEY';
29
28
  const CODEX_LB_CANONICAL_FAST_SERVICE_TIER = 'priority';
@@ -276,7 +275,7 @@ async function postinstallHarnessConflictNotice(conflictScan) {
276
275
  console.log(formatHarnessConflictReport(conflictScan, { includePrompt: false }));
277
276
  console.log('\nWhat this means: npm can finish installing the package, but `sks setup` and `sks doctor --fix` will refuse to activate SKS until the conflicting harness is removed with human approval.');
278
277
  console.log('No files were removed by postinstall.');
279
- console.log(`Cleanup requires a human-approved Codex App session. Recommended model: ${REQUIRED_CODEX_MODEL}, reasoning: high.`);
278
+ console.log('Cleanup requires a human-approved Codex App session. Keep the model selected in Codex and use high reasoning effort.');
280
279
  if (shouldAskPostinstallQuestion()) {
281
280
  const answer = await askPostinstallQuestion('Show the cleanup prompt now? [y/N] ');
282
281
  if (/^(y|yes|예|네|응)$/i.test(answer.trim())) {
@@ -902,7 +901,9 @@ export async function checkCodexLbResponseChain(status = {}, opts = {}) {
902
901
  const fetchImpl = opts.fetch || globalThis.fetch;
903
902
  if (typeof fetchImpl !== 'function')
904
903
  return { ok: true, status: 'skipped', skipped: true, reason: 'fetch unavailable' };
905
- const model = opts.model || env.SKS_CODEX_MODEL || REQUIRED_CODEX_MODEL;
904
+ const model = String(opts.model || env.SKS_CODEX_MODEL || env.CODEX_MODEL || '').trim();
905
+ if (!model)
906
+ return { ok: true, status: 'skipped', skipped: true, reason: 'model_unselected_use_explicit_model_or_codex_catalog' };
906
907
  const timeoutMs = Number(opts.timeoutMs || env.SKS_CODEX_LB_CHAIN_CHECK_TIMEOUT_MS || 8000);
907
908
  const serviceTier = opts.fastMode === true || opts.serviceTier === 'fast' || opts.serviceTier === CODEX_LB_CANONICAL_FAST_SERVICE_TIER
908
909
  ? CODEX_LB_CANONICAL_FAST_SERVICE_TIER
@@ -1894,7 +1895,7 @@ function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
1894
1895
  // `default_profile`, `[profiles.<name>]` tables, `[user.fast_mode]`, and
1895
1896
  // `notice.fast_default_opt_out`. The only documented fast-default mechanism is
1896
1897
  // the plain top-level `service_tier = "fast"`. This pass strips every legacy
1897
- // stamp SKS ever wrote and keeps user-authored top-level choices intact.
1898
+ // schema stamps SKS wrote and keeps user-authored top-level choices intact.
1898
1899
  let next = String(text || '');
1899
1900
  next = removeLegacyTopLevelCodexModeLocks(next);
1900
1901
  next = removeTopLevelTomlKeyIfValue(next, 'default_profile', 'sks-fast-high');
@@ -1925,6 +1926,10 @@ function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
1925
1926
  for (const featureLine of ['hooks = true', 'multi_agent = true', 'fast_mode = true', 'apps = true']) {
1926
1927
  next = upsertTomlTableKeyIfAbsent(next, 'features', featureLine);
1927
1928
  }
1929
+ if (process.env.SKS_ALLOW_HIGH_AGENT_CONCURRENCY !== '1') {
1930
+ next = upsertTomlTableKey(next, 'agents', 'max_threads = 4');
1931
+ }
1932
+ next = removeTomlTable(next, 'features.multi_agent_v2');
1928
1933
  // Plugin auto-enable is OPT-IN only. Force-writing `[plugins."name@marketplace"] enabled =
1929
1934
  // true` for marketplace plugins the App may not have installed (different build/channel)
1930
1935
  // makes the App reference plugins it cannot load -> broken/blocked plugin UI. It also
@@ -1966,16 +1971,16 @@ function removeLegacyTopLevelCodexModeLocks(text = '') {
1966
1971
  const lines = String(text || '').split('\n');
1967
1972
  const firstTable = lines.findIndex((x) => /^\s*\[.+\]\s*$/.test(x));
1968
1973
  const end = firstTable === -1 ? lines.length : firstTable;
1969
- const topLevelModel = topLevelTomlString(text, 'model');
1970
- // Recognize both the current default stamp and the legacy gpt-5.5 stamp older
1971
- // SKS versions wrote, so upgrades keep cleaning locks written before the 5.6 bump.
1972
- const removeSksOwnedModeLock = topLevelModel === REQUIRED_CODEX_MODEL || topLevelModel === GPT55_CODEX_MODEL;
1973
1974
  return lines.filter((line, index) => {
1974
1975
  if (index >= end)
1975
1976
  return true;
1976
- if (!removeSksOwnedModeLock)
1977
+ if (!/^\s*(?:model|model_reasoning_effort)\s*=/.test(line))
1977
1978
  return true;
1978
- return !/^\s*(?:model|model_reasoning_effort)\s*=/.test(line);
1979
+ return ![line, lines[index - 1] || ''].some((candidate) => {
1980
+ const trimmed = String(candidate || '').trim();
1981
+ const comment = trimmed.startsWith('#') ? trimmed : trimmed.includes('#') ? trimmed.slice(trimmed.indexOf('#')) : '';
1982
+ return /(?:SKS|Sneakoscope|codex-lb|sks fast)/i.test(comment);
1983
+ });
1979
1984
  }).join('\n').replace(/^\n+/, '').replace(/\n{3,}/g, '\n\n');
1980
1985
  }
1981
1986
  function removeTopLevelTomlKeyIfValue(text = '', key = '', value = '') {
@@ -2866,8 +2871,8 @@ export async function selftestCodexLb(tmp) {
2866
2871
  // escape that dash emits literally and bash collapses to `"`).
2867
2872
  await writeTextAtomic(codexLbFakeCodex, "#!/bin/sh\nif [ \"$1\" = \"--version\" ]; then echo \"codex-cli 99.0.0\"; exit 0; fi\nif [ \"$1\" = \"login\" ] && [ \"$2\" = \"status\" ]; then echo \"logged in with browser auth\"; exit 0; fi\nif [ \"$1\" = \"login\" ] && [ \"$2\" = \"--with-api-key\" ]; then read key; mkdir -p \"$HOME/.codex\"; printf '{\"auth_mode\":\"apikey\",\"OPENAI_API_KEY\":\"%s\"}\\n' \"$key\" > \"$HOME/.codex/auth.json\"; printf '%s\\n' \"$key\" >> \"$HOME/.codex/login-calls.log\"; exit 0; fi\necho \"fake codex unsupported\" >&2\nexit 1\n");
2868
2873
  await fsp.chmod(codexLbFakeCodex, 0o755);
2869
- await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `model = "${REQUIRED_CODEX_MODEL}"\nmodel_reasoning_effort = "low"\nservice_tier = "fast"\nsuppress_unstable_features_warning = true\n\n[profiles.custom]\nmodel_reasoning_effort = "low"\n\n[notice]\nfast_default_opt_out = true\n\n[features]\nhooks = true\n`);
2870
- const codexLbEnvForSelftest = { HOME: codexLbHome, SKS_GLOBAL_ROOT: path.join(tmp, 'codex-lb-global'), PATH: `${codexLbFakeBin}${path.delimiter}${process.env.PATH || ''}`, SKS_SKIP_CODEX_LB_LAUNCH_ENV: '1' };
2874
+ await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `model_reasoning_effort = "low"\nservice_tier = "fast"\nsuppress_unstable_features_warning = true\n\n[profiles.custom]\nmodel_reasoning_effort = "low"\n\n[notice]\nfast_default_opt_out = true\n\n[features]\nhooks = true\n`);
2875
+ const codexLbEnvForSelftest = { HOME: codexLbHome, SKS_GLOBAL_ROOT: path.join(tmp, 'codex-lb-global'), PATH: `${codexLbFakeBin}${path.delimiter}${process.env.PATH || ''}`, SKS_SKIP_CODEX_LB_LAUNCH_ENV: '1', SKS_CODEX_MODEL: 'selftest-codex-model' };
2871
2876
  const codexLbSetup = await runProcess(process.execPath, [packagedSksEntrypoint(), 'codex-lb', 'setup', '--host', 'lb.example.test', '--api-key', 'sk-test', '--json'], {
2872
2877
  cwd: tmp,
2873
2878
  env: codexLbEnvForSelftest,
@@ -2971,7 +2976,7 @@ export async function selftestCodexLb(tmp) {
2971
2976
  await postinstall({
2972
2977
  bootstrap: async () => {
2973
2978
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"browser"}\n');
2974
- await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `model = "${REQUIRED_CODEX_MODEL}"\nservice_tier = "fast"\nsuppress_unstable_features_warning = true\n\n[features]\nhooks = true\n`);
2979
+ await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `service_tier = "fast"\nsuppress_unstable_features_warning = true\n\n[features]\nhooks = true\n`);
2975
2980
  }
2976
2981
  });
2977
2982
  }
@@ -2997,7 +3002,7 @@ export async function selftestCodexLb(tmp) {
2997
3002
  await writeTextAtomic(path.join(doctorProject, 'package.json'), '{"name":"codex-lb-doctor-project","version":"0.0.0"}\n');
2998
3003
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'sks-codex-lb.env'), "export CODEX_LB_BASE_URL='https://lb.example.test/backend-api/codex'\nexport CODEX_LB_API_KEY='sk-test'\n");
2999
3004
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"browser"}\n');
3000
- await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `model = "${REQUIRED_CODEX_MODEL}"\nservice_tier = "fast"\nsuppress_unstable_features_warning = true\n\n[features]\nhooks = true\n`);
3005
+ await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `service_tier = "fast"\nsuppress_unstable_features_warning = true\n\n[features]\nhooks = true\n`);
3001
3006
  const codexLbDoctorRepair = await runProcess(process.execPath, [packagedSksEntrypoint(), 'doctor', '--fix', '--json'], {
3002
3007
  cwd: doctorProject,
3003
3008
  env: { ...codexLbEnvForSelftest, SKS_GLOBAL_ROOT: path.join(tmp, 'codex-lb-doctor-global') },
@@ -3190,7 +3195,7 @@ export async function selftestCodexLb(tmp) {
3190
3195
  if (!codexLbLegacyDoctorJson.repair?.codex_lb?.ok || !codexLbLegacyDoctorJson.repair.codex_lb.legacy_auth_migrated || !codexLbLegacyDoctorEnv.includes("CODEX_LB_API_KEY='sk-legacy-doctor'") || !codexLbLegacyDoctorAuth.includes('"auth_mode":"apikey"') || !codexLbLegacyDoctorAuth.includes('sk-legacy-doctor') || !hasTopLevelCodexLbSelected(codexLbLegacyDoctorConfig) || !codexLbLegacyDoctorConfig.includes('env_key = "CODEX_LB_API_KEY"'))
3191
3196
  throw new Error('selftest: legacy doctor codex-lb restore');
3192
3197
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'sks-codex-lb.env'), "export CODEX_LB_BASE_URL='https://lb.example.test/backend-api/codex'\n");
3193
- await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `model = "${REQUIRED_CODEX_MODEL}"\nservice_tier = "fast"\n`);
3198
+ await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), 'service_tier = "fast"\n');
3194
3199
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"apikey","key":"sk-env-only"}\n');
3195
3200
  const codexLbLoginCallsBeforeEnvOnlyPostinstall = await codexLbLoginCallCount(codexLbHome);
3196
3201
  const codexLbEnvOnlyPostinstall = await runProcess(process.execPath, [packagedSksEntrypoint(), 'postinstall'], {
@@ -3208,7 +3213,7 @@ export async function selftestCodexLb(tmp) {
3208
3213
  if (!String(codexLbEnvOnlyPostinstall.stdout || '').includes('codex-lb auth: restored from existing Codex login cache') || !codexLbEnvOnlyPostinstallEnv.includes("CODEX_LB_API_KEY='sk-env-only'") || !codexLbEnvOnlyPostinstallConfig.includes('env_key = "CODEX_LB_API_KEY"') || !hasTopLevelCodexLbSelected(codexLbEnvOnlyPostinstallConfig) || !codexLbEnvOnlyPostinstallAuth.includes('sk-env-only') || codexLbLoginCallsAfterEnvOnlyPostinstall !== codexLbLoginCallsBeforeEnvOnlyPostinstall)
3209
3214
  throw new Error('selftest: env-only codex-lb postinstall restore');
3210
3215
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'sks-codex-lb.env'), "export CODEX_LB_BASE_URL='https://lb.example.test/backend-api/codex'\n");
3211
- await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `model = "${REQUIRED_CODEX_MODEL}"\nservice_tier = "fast"\n`);
3216
+ await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), 'service_tier = "fast"\n');
3212
3217
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"apikey","key":"sk-env-only-doctor"}\n');
3213
3218
  const codexLbEnvOnlyDoctorProject = tmpdir();
3214
3219
  await ensureDir(path.join(codexLbEnvOnlyDoctorProject, '.git'));
@@ -3338,7 +3343,7 @@ export async function selftestCodexLb(tmp) {
3338
3343
  }
3339
3344
  if (autobypassLaunch.status !== 'chain_unhealthy' || autobypassLaunch.bypass_codex_lb !== true || autobypassLaunch.chain_health?.status !== 'second_request_failed')
3340
3345
  throw new Error('selftest: SKS_CODEX_LB_AUTOBYPASS=1 should bypass codex-lb on hard chain failure');
3341
- await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), `model = "${REQUIRED_CODEX_MODEL}"\nservice_tier = "fast"\n`);
3346
+ await writeTextAtomic(path.join(codexLbHome, '.codex', 'config.toml'), 'service_tier = "fast"\n');
3342
3347
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'sks-codex-lb.env'), "export CODEX_LB_BASE_URL='https://lb.example.test/backend-api/codex'\nexport CODEX_LB_API_KEY='sk-test'\n");
3343
3348
  const missingProviderLaunchCalls = [];
3344
3349
  const missingProviderLaunch = await maybePromptCodexLbSetupForLaunch([], {
@@ -3405,11 +3410,11 @@ export async function selftestCodexLb(tmp) {
3405
3410
  throw new Error(`selftest: codex-lb setup did not enforce the renewed feature-flag contract (documented flags present, legacy stamps stripped, user profile tables preserved)${survivingLegacy.length ? ` — surviving legacy stamps: ${survivingLegacy.join(', ')}` : ''}`);
3406
3411
  if (!hasCodexUnstableFeatureWarningSuppression(codexLbConfig))
3407
3412
  throw new Error('selftest: codex-lb setup did not suppress Codex unstable feature warning');
3408
- const codexLbLaunch = `source ${path.join(tmp, '.codex', 'sks-codex-lb.env')} && codex '--model' '${REQUIRED_CODEX_MODEL}'`;
3413
+ const codexLbLaunch = `source ${path.join(tmp, '.codex', 'sks-codex-lb.env')} && codex`;
3409
3414
  if (!codexLbLaunch.includes('sks-codex-lb.env'))
3410
3415
  throw new Error('selftest: Zellij launch command does not source codex-lb env file');
3411
- if (!codexLbLaunch.includes(`'--model' '${REQUIRED_CODEX_MODEL}'`))
3412
- throw new Error(`selftest: Zellij launch command without args did not force ${REQUIRED_CODEX_MODEL}`);
3416
+ if (codexLbLaunch.includes('--model'))
3417
+ throw new Error('selftest: Zellij launch command without an explicit model must inherit the Codex selection');
3413
3418
  const madLaunchSource = await safeReadText(path.join(packageRoot(), 'src', 'core', 'commands', 'mad-sks-command.js'));
3414
3419
  if (!madLaunchSource.includes('const lb = await deps.maybePromptCodexLbSetupForLaunch(args)') || !madLaunchSource.includes("const launchLb = lb.status === 'present'") || !madLaunchSource.includes('codexLbImmediateLaunchOpts(cleanArgs, launchLb') || !madLaunchSource.includes('bypass_codex_lb') || !madLaunchSource.includes('model_provider="openai"') || !madLaunchSource.includes('codexLbFreshSession: true'))
3415
3420
  throw new Error('selftest: MAD launch does not sync codex-lb auth and fresh-session launch options');
@@ -3418,7 +3423,7 @@ function hasTopLevelCodexModeLock(text = '') {
3418
3423
  const lines = String(text || '').split('\n');
3419
3424
  const firstTable = lines.findIndex((x) => /^\s*\[.+\]\s*$/.test(x));
3420
3425
  const top = (firstTable === -1 ? lines : lines.slice(0, firstTable)).join('\n');
3421
- return /(^|\n)\s*(?:model|model_reasoning_effort)\s*=/.test(top);
3426
+ return /(^|\n)\s*model_reasoning_effort\s*=/.test(top);
3422
3427
  }
3423
3428
  function hasDeprecatedCodexHooksFeatureFlag(text = '') {
3424
3429
  const lines = String(text || '').split('\n');