sneakoscope 6.0.1 → 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 (87) 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 -60
  5. package/dist/bin/sks-dispatch.js +0 -24
  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 +25 -31
  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 +9 -13
  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 +6 -40
  25. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +1 -7
  26. package/dist/core/codex-control/codex-model-capabilities.js +1 -2
  27. package/dist/core/codex-control/codex-model-metadata.js +13 -6
  28. package/dist/core/codex-control/codex-sdk-config-policy.js +3 -3
  29. package/dist/core/codex-control/codex-task-runner.js +2 -3
  30. package/dist/core/codex-model-guard.js +24 -87
  31. package/dist/core/commands/basic-cli.js +6 -0
  32. package/dist/core/commands/loop-command.js +2 -2
  33. package/dist/core/commands/naruto-command.js +11 -11
  34. package/dist/core/commands/profile-command.js +14 -5
  35. package/dist/core/commands/qa-loop-command.js +2 -2
  36. package/dist/core/commands/research-command.js +2 -2
  37. package/dist/core/doctor/doctor-codex-startup-repair.js +0 -3
  38. package/dist/core/evaluation.js +1 -1
  39. package/dist/core/feature-fixtures.js +2 -2
  40. package/dist/core/feature-registry.js +1 -1
  41. package/dist/core/hooks-runtime.js +7 -45
  42. package/dist/core/image-ux-review/imagegen-adapter.js +17 -2
  43. package/dist/core/init/skills.js +6 -7
  44. package/dist/core/init.js +6 -20
  45. package/dist/core/loops/loop-concurrency-budget.js +6 -4
  46. package/dist/core/loops/loop-planner.js +1 -1
  47. package/dist/core/loops/loop-runtime.js +2 -2
  48. package/dist/core/loops/loop-scheduler.js +7 -7
  49. package/dist/core/managed-assets/managed-assets-manifest.js +1 -4
  50. package/dist/core/naruto/naruto-concurrency-governor.js +20 -17
  51. package/dist/core/naruto/naruto-loop-mesh.js +3 -3
  52. package/dist/core/naruto/resource-pressure-monitor.js +5 -2
  53. package/dist/core/provider/model-router.js +15 -35
  54. package/dist/core/release/release-gate-batch-runner.js +2 -1
  55. package/dist/core/release/release-gate-resource-governor.js +12 -12
  56. package/dist/core/release/resource-class-budget.js +5 -5
  57. package/dist/core/routes/constants.js +3 -4
  58. package/dist/core/routes.js +1 -1
  59. package/dist/core/structured-output-adapter.js +15 -1
  60. package/dist/core/update/update-migration-state.js +3 -32
  61. package/dist/core/version.js +1 -1
  62. package/dist/scripts/agent-backfill-replenishment-check.js +1 -1
  63. package/dist/scripts/agent-dynamic-pool-check.js +3 -3
  64. package/dist/scripts/agent-dynamic-pool-fixture.js +1 -1
  65. package/dist/scripts/agent-goal-mode-propagation-check.js +1 -1
  66. package/dist/scripts/agent-patch-swarm-gate-lib.js +2 -2
  67. package/dist/scripts/agent-role-config-repair-check.js +9 -5
  68. package/dist/scripts/agent-scheduler-proof-check.js +1 -1
  69. package/dist/scripts/agent-scheduler-proof-hardening-check.js +1 -1
  70. package/dist/scripts/agent-source-intelligence-propagation-check.js +1 -1
  71. package/dist/scripts/agent-strategy-to-lease-wiring-check.js +2 -2
  72. package/dist/scripts/agent-zellij-dynamic-backfill-panes-check.js +1 -1
  73. package/dist/scripts/codex-app-fast-ui-preservation-check.js +2 -2
  74. package/dist/scripts/codex-app-ui-preservation-check.js +6 -5
  75. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +3 -3
  76. package/dist/scripts/codex-lb-gpt55-fast-profile-check.js +2 -3
  77. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +7 -7
  78. package/dist/scripts/install-update-preserves-config-check.js +4 -4
  79. package/dist/scripts/loop-hardening-check-lib.js +1 -1
  80. package/dist/scripts/naruto-parallelism-mode-check.js +2 -1
  81. package/dist/scripts/naruto-shadow-clone-swarm-check.js +25 -34
  82. package/dist/scripts/npm-publish-performance-check.js +1 -1
  83. package/dist/scripts/release-aggressive-resource-governor-check.js +2 -2
  84. package/dist/scripts/release-parallel-check.js +1 -2
  85. package/dist/scripts/release-real-check.js +1 -1
  86. package/dist/scripts/sizecheck.js +3 -3
  87. 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.1**. New in this release: GPT-5.6 Codex App model selection repair, 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.1"
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.1"
3
+ version = "6.0.2"
4
4
  edition = "2021"
5
5
 
6
6
  [dependencies]
@@ -151,63 +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;
194
-
195
- exports.rootJsonFastInline = rootJsonFastInline;
196
- exports.doctorJsonFastInline = doctorJsonFastInline;
197
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
198
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
199
-
200
- exports.rootJsonFastInline = rootJsonFastInline;
201
- exports.doctorJsonFastInline = doctorJsonFastInline;
202
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
203
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
204
-
205
- exports.rootJsonFastInline = rootJsonFastInline;
206
- exports.doctorJsonFastInline = doctorJsonFastInline;
207
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
208
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
209
-
210
- exports.rootJsonFastInline = rootJsonFastInline;
211
- exports.doctorJsonFastInline = doctorJsonFastInline;
212
- exports.narutoHelpJsonFastInline = narutoHelpJsonFastInline;
213
- exports.hookUserPromptSubmitPerfInline = hookUserPromptSubmitPerfInline;
@@ -60,27 +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;
79
-
80
- exports.runSks = runSks;
81
-
82
- exports.runSks = runSks;
83
-
84
- exports.runSks = runSks;
85
-
86
- 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, GPT56_CODEX_MODELS, 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,10 +1895,9 @@ 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
- next = normalizeCodexAppDefaultModel(next);
1901
1901
  next = removeTopLevelTomlKeyIfValue(next, 'default_profile', 'sks-fast-high');
1902
1902
  next = removeTomlTable(next, 'user.fast_mode');
1903
1903
  next = removeTomlTable(next, 'profiles.sks-fast-high');
@@ -1926,6 +1926,10 @@ function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
1926
1926
  for (const featureLine of ['hooks = true', 'multi_agent = true', 'fast_mode = true', 'apps = true']) {
1927
1927
  next = upsertTomlTableKeyIfAbsent(next, 'features', featureLine);
1928
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');
1929
1933
  // Plugin auto-enable is OPT-IN only. Force-writing `[plugins."name@marketplace"] enabled =
1930
1934
  // true` for marketplace plugins the App may not have installed (different build/channel)
1931
1935
  // makes the App reference plugins it cannot load -> broken/blocked plugin UI. It also
@@ -1967,28 +1971,18 @@ function removeLegacyTopLevelCodexModeLocks(text = '') {
1967
1971
  const lines = String(text || '').split('\n');
1968
1972
  const firstTable = lines.findIndex((x) => /^\s*\[.+\]\s*$/.test(x));
1969
1973
  const end = firstTable === -1 ? lines.length : firstTable;
1970
- const topLevelModel = topLevelTomlString(text, 'model');
1971
- const removeSksOwnedModeLock = isLegacySksCodexModelStamp(topLevelModel);
1972
1974
  return lines.filter((line, index) => {
1973
1975
  if (index >= end)
1974
1976
  return true;
1975
- if (!removeSksOwnedModeLock)
1977
+ if (!/^\s*(?:model|model_reasoning_effort)\s*=/.test(line))
1976
1978
  return true;
1977
- return !/^\s*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
+ });
1978
1984
  }).join('\n').replace(/^\n+/, '').replace(/\n{3,}/g, '\n\n');
1979
1985
  }
1980
- function normalizeCodexAppDefaultModel(text = '') {
1981
- const currentModel = topLevelTomlString(text, 'model');
1982
- if (!currentModel)
1983
- return upsertTopLevelTomlString(text, 'model', REQUIRED_CODEX_MODEL);
1984
- if (isLegacySksCodexModelStamp(currentModel))
1985
- return upsertTopLevelTomlString(text, 'model', REQUIRED_CODEX_MODEL);
1986
- return String(text || '');
1987
- }
1988
- function isLegacySksCodexModelStamp(value = '') {
1989
- const model = String(value || '').trim().toLowerCase();
1990
- return model === REQUIRED_CODEX_MODEL || model === GPT55_CODEX_MODEL || GPT56_CODEX_MODELS.includes(model);
1991
- }
1992
1986
  function removeTopLevelTomlKeyIfValue(text = '', key = '', value = '') {
1993
1987
  const lines = String(text || '').split('\n');
1994
1988
  const firstTable = lines.findIndex((x) => /^\s*\[.+\]\s*$/.test(x));
@@ -2877,8 +2871,8 @@ export async function selftestCodexLb(tmp) {
2877
2871
  // escape that dash emits literally and bash collapses to `"`).
2878
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");
2879
2873
  await fsp.chmod(codexLbFakeCodex, 0o755);
2880
- 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`);
2881
- 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' };
2882
2876
  const codexLbSetup = await runProcess(process.execPath, [packagedSksEntrypoint(), 'codex-lb', 'setup', '--host', 'lb.example.test', '--api-key', 'sk-test', '--json'], {
2883
2877
  cwd: tmp,
2884
2878
  env: codexLbEnvForSelftest,
@@ -2982,7 +2976,7 @@ export async function selftestCodexLb(tmp) {
2982
2976
  await postinstall({
2983
2977
  bootstrap: async () => {
2984
2978
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"browser"}\n');
2985
- 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`);
2986
2980
  }
2987
2981
  });
2988
2982
  }
@@ -3008,7 +3002,7 @@ export async function selftestCodexLb(tmp) {
3008
3002
  await writeTextAtomic(path.join(doctorProject, 'package.json'), '{"name":"codex-lb-doctor-project","version":"0.0.0"}\n');
3009
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");
3010
3004
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"browser"}\n');
3011
- 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`);
3012
3006
  const codexLbDoctorRepair = await runProcess(process.execPath, [packagedSksEntrypoint(), 'doctor', '--fix', '--json'], {
3013
3007
  cwd: doctorProject,
3014
3008
  env: { ...codexLbEnvForSelftest, SKS_GLOBAL_ROOT: path.join(tmp, 'codex-lb-doctor-global') },
@@ -3201,7 +3195,7 @@ export async function selftestCodexLb(tmp) {
3201
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"'))
3202
3196
  throw new Error('selftest: legacy doctor codex-lb restore');
3203
3197
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'sks-codex-lb.env'), "export CODEX_LB_BASE_URL='https://lb.example.test/backend-api/codex'\n");
3204
- 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');
3205
3199
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"apikey","key":"sk-env-only"}\n');
3206
3200
  const codexLbLoginCallsBeforeEnvOnlyPostinstall = await codexLbLoginCallCount(codexLbHome);
3207
3201
  const codexLbEnvOnlyPostinstall = await runProcess(process.execPath, [packagedSksEntrypoint(), 'postinstall'], {
@@ -3219,7 +3213,7 @@ export async function selftestCodexLb(tmp) {
3219
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)
3220
3214
  throw new Error('selftest: env-only codex-lb postinstall restore');
3221
3215
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'sks-codex-lb.env'), "export CODEX_LB_BASE_URL='https://lb.example.test/backend-api/codex'\n");
3222
- 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');
3223
3217
  await writeTextAtomic(path.join(codexLbHome, '.codex', 'auth.json'), '{"auth_mode":"apikey","key":"sk-env-only-doctor"}\n');
3224
3218
  const codexLbEnvOnlyDoctorProject = tmpdir();
3225
3219
  await ensureDir(path.join(codexLbEnvOnlyDoctorProject, '.git'));
@@ -3349,7 +3343,7 @@ export async function selftestCodexLb(tmp) {
3349
3343
  }
3350
3344
  if (autobypassLaunch.status !== 'chain_unhealthy' || autobypassLaunch.bypass_codex_lb !== true || autobypassLaunch.chain_health?.status !== 'second_request_failed')
3351
3345
  throw new Error('selftest: SKS_CODEX_LB_AUTOBYPASS=1 should bypass codex-lb on hard chain failure');
3352
- 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');
3353
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");
3354
3348
  const missingProviderLaunchCalls = [];
3355
3349
  const missingProviderLaunch = await maybePromptCodexLbSetupForLaunch([], {
@@ -3416,11 +3410,11 @@ export async function selftestCodexLb(tmp) {
3416
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(', ')}` : ''}`);
3417
3411
  if (!hasCodexUnstableFeatureWarningSuppression(codexLbConfig))
3418
3412
  throw new Error('selftest: codex-lb setup did not suppress Codex unstable feature warning');
3419
- 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`;
3420
3414
  if (!codexLbLaunch.includes('sks-codex-lb.env'))
3421
3415
  throw new Error('selftest: Zellij launch command does not source codex-lb env file');
3422
- if (!codexLbLaunch.includes(`'--model' '${REQUIRED_CODEX_MODEL}'`))
3423
- 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');
3424
3418
  const madLaunchSource = await safeReadText(path.join(packageRoot(), 'src', 'core', 'commands', 'mad-sks-command.js'));
3425
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'))
3426
3420
  throw new Error('selftest: MAD launch does not sync codex-lb auth and fresh-session launch options');