sneakoscope 7.1.0 → 7.3.0

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 (534) hide show
  1. package/README.md +9 -1
  2. package/config/architecture-budgets.v1.json +1 -8
  3. package/crates/sks-core/Cargo.lock +225 -1
  4. package/crates/sks-core/Cargo.toml +8 -1
  5. package/crates/sks-core/src/main.rs +7 -1
  6. package/crates/sks-core/src/search/files.rs +114 -0
  7. package/crates/sks-core/src/search/mod.rs +274 -0
  8. package/crates/sks-core/src/search/text.rs +175 -0
  9. package/dist/bin/sks-dispatch.js +4 -3
  10. package/dist/cli/command-manifest-lite.js +177 -6
  11. package/dist/cli/command-registry.js +42 -8
  12. package/dist/cli/help.js +30 -0
  13. package/dist/cli/install-helpers-codex-lb-config.js +9 -6
  14. package/dist/cli/install-helpers-codex-lb-selftest-chain.js +1 -1
  15. package/dist/cli/install-helpers-install-support.js +1 -1
  16. package/dist/cli/install-helpers.js +19 -9
  17. package/dist/cli/router.js +16 -3
  18. package/dist/commands/codex-app.js +40 -5
  19. package/dist/commands/doctor-profile.js +78 -0
  20. package/dist/commands/doctor.js +29 -69
  21. package/dist/commands/search.js +4 -0
  22. package/dist/config/skills-manifest.json +53 -60
  23. package/dist/core/agent-bridge/agent-manifest.js +22 -26
  24. package/dist/core/agent-bridge/host-capability-policy.js +109 -8
  25. package/dist/core/agent-bridge/host-capability-runtime.js +178 -50
  26. package/dist/core/agent-guidance/directive-registry.js +123 -0
  27. package/dist/core/agents/agent-effort-policy.js +45 -6
  28. package/dist/core/agents/agent-worker-pipeline.js +1 -3
  29. package/dist/core/agents/native-worker-backend-router.js +43 -19
  30. package/dist/core/auto-review.js +1 -3
  31. package/dist/core/code-structure.js +282 -19
  32. package/dist/core/codex/codex-config-guard.js +14 -4
  33. package/dist/core/codex/codex-config-toml.js +1 -3
  34. package/dist/core/codex-app/codex-agent-role-sync.js +1 -3
  35. package/dist/core/codex-app/codex-app-fast-ui-repair.js +14 -1
  36. package/dist/core/codex-app/codex-app-types.js +2 -3
  37. package/dist/core/codex-app/codex-desktop-routing-ownership.js +91 -0
  38. package/dist/core/codex-app/codex-hook-approval-probe.js +1 -3
  39. package/dist/core/codex-app/codex-hook-lifecycle.js +1 -3
  40. package/dist/core/codex-app/codex-init-deep.js +22 -10
  41. package/dist/core/codex-app/codex-model-catalog.js +384 -0
  42. package/dist/core/codex-app/codex-models-cache.js +160 -0
  43. package/dist/core/codex-app/desktop-routing-snapshot.js +233 -0
  44. package/dist/core/codex-app/glm-profile-installer.js +1 -3
  45. package/dist/core/codex-app/mcp-manager.js +1 -3
  46. package/dist/core/codex-app/menubar/constants.js +3 -0
  47. package/dist/core/codex-app/menubar/installer.js +11 -1
  48. package/dist/core/codex-app/multi-provider-router-support.js +202 -0
  49. package/dist/core/codex-app/multi-provider-router.js +379 -0
  50. package/dist/core/codex-app/openrouter-activate.js +189 -26
  51. package/dist/core/codex-app/openrouter-base-instructions.js +1 -0
  52. package/dist/core/codex-app/openrouter-model-catalog.js +217 -0
  53. package/dist/core/codex-app/role-model-catalog-priority.js +61 -0
  54. package/dist/core/codex-app.js +30 -6
  55. package/dist/core/codex-compat/codex-hook-semantic-validator.js +1 -3
  56. package/dist/core/codex-control/codex-app-server-v2-client.js +39 -2
  57. package/dist/core/codex-lb/codex-lb-env.js +1 -3
  58. package/dist/core/codex-lb/codex-lb-tool-catalog.js +6 -1
  59. package/dist/core/codex-native/codex-native-feature-broker.js +2 -6
  60. package/dist/core/codex-native/codex-native-interop-policy.js +1 -3
  61. package/dist/core/codex-native/codex-native-reference-cache.js +1 -3
  62. package/dist/core/codex-native/codex-native-reference-source.js +1 -3
  63. package/dist/core/codex-native/codex-native-repair-transaction.js +1 -3
  64. package/dist/core/codex-native/core-skill-manifest.js +3 -2
  65. package/dist/core/codex-native/native-capability-repair-matrix.js +1 -3
  66. package/dist/core/codex-plugins/codex-plugin-repair.js +1 -3
  67. package/dist/core/codex-runtime/codex-desktop-config-policy.js +4 -4
  68. package/dist/core/commands/agent-bridge-command.js +24 -3
  69. package/dist/core/commands/image-ux-review-command.js +5 -11
  70. package/dist/core/commands/menubar-command.js +1 -1
  71. package/dist/core/commands/naruto-command.js +40 -13
  72. package/dist/core/commands/pipeline-command.js +5 -2
  73. package/dist/core/commands/release-command.js +63 -1
  74. package/dist/core/commands/remote-command.js +18 -0
  75. package/dist/core/commands/search-command.js +151 -0
  76. package/dist/core/commands/telegram-command.js +251 -108
  77. package/dist/core/commands/uninstall-command.js +1 -1
  78. package/dist/core/config/secret-preservation.js +1 -3
  79. package/dist/core/context7-client.js +2 -1
  80. package/dist/core/db-review.js +704 -0
  81. package/dist/core/db-safety.js +17 -23
  82. package/dist/core/doctor/browser-use-repair.js +1 -3
  83. package/dist/core/doctor/codex-startup-config-repair.js +1 -3
  84. package/dist/core/doctor/computer-use-repair.js +1 -3
  85. package/dist/core/doctor/context7-mcp-repair.js +1 -3
  86. package/dist/core/doctor/current-project-guidance.js +1 -3
  87. package/dist/core/doctor/doctor-codex-startup-repair.js +1 -3
  88. package/dist/core/doctor/doctor-dirty-planner.js +2 -2
  89. package/dist/core/doctor/doctor-native-capability-repair.js +1 -3
  90. package/dist/core/doctor/doctor-transaction.js +1 -3
  91. package/dist/core/doctor/imagegen-repair.js +1 -3
  92. package/dist/core/doctor/legacy-global-hook-cleanup.js +1 -3
  93. package/dist/core/doctor/mcp-transport-collision-repair.js +1 -3
  94. package/dist/core/doctor/retired-managed-residue-private.js +1 -3
  95. package/dist/core/doctor/supabase-mcp-repair.js +1 -3
  96. package/dist/core/engineering-sanity-review.js +186 -0
  97. package/dist/core/errors/message.js +3 -0
  98. package/dist/core/evidence/evidence-schema.js +1 -3
  99. package/dist/core/feature-fixtures.js +1 -0
  100. package/dist/core/feature-registry.js +1 -3
  101. package/dist/core/fsx.js +13 -0
  102. package/dist/core/git-hygiene/shared-memory-publish.js +1 -3
  103. package/dist/core/git-hygiene/validators.js +1 -3
  104. package/dist/core/harness-guard.js +21 -3
  105. package/dist/core/hooks-runtime/hook-context.js +2 -2
  106. package/dist/core/image-ux-review/imagegen-adapter.js +52 -56
  107. package/dist/core/image-ux-review/real-callout-extractor.js +6 -1
  108. package/dist/core/image-ux-review.js +3 -5
  109. package/dist/core/imagegen/codex-lb-imagegen-target.js +70 -0
  110. package/dist/core/imagegen/imagegen-capability.js +11 -11
  111. package/dist/core/imagegen/imagegen-evidence.js +32 -0
  112. package/dist/core/init/skills.js +9 -11
  113. package/dist/core/init.js +4 -6
  114. package/dist/core/json/records.js +9 -0
  115. package/dist/core/json-schema-validator.js +1 -3
  116. package/dist/core/lean-engineering-policy.js +54 -0
  117. package/dist/core/loops/loop-continuation-enforcer.js +1 -3
  118. package/dist/core/mad-sks/sql-plane/mcp-executor.js +2 -1
  119. package/dist/core/mad-sks/sql-plane/policy.js +2 -1
  120. package/dist/core/managed-assets/managed-assets-manifest.js +4 -3
  121. package/dist/core/mcp-config/codex-cli-adapter.js +1 -3
  122. package/dist/core/mcp-config/config-reader.js +2 -3
  123. package/dist/core/mcp-config/guarded-patch.js +1 -1
  124. package/dist/core/mcp-config/health-check.js +2 -1
  125. package/dist/core/mcp-config/mutation.js +1 -1
  126. package/dist/core/mcp-config/restore.js +1 -1
  127. package/dist/core/mcp-config/secret-policy.js +1 -3
  128. package/dist/core/migration/migration-transaction-journal.js +3 -3
  129. package/dist/core/naruto/naruto-concurrency-governor.js +2 -2
  130. package/dist/core/perf/import-graph-budget.js +91 -1
  131. package/dist/core/pipeline/pipeline-plan-writer.js +1 -1
  132. package/dist/core/pipeline-internals/runtime-core.js +121 -23
  133. package/dist/core/pipeline-internals/runtime-gates.js +193 -4
  134. package/dist/core/pipeline.js +1 -1
  135. package/dist/core/ppt-review/slide-imagegen-review.js +7 -7
  136. package/dist/core/ppt.js +3 -3
  137. package/dist/core/product-design-app-server.js +2 -1
  138. package/dist/core/proof/fake-real-proof-policy.js +1 -3
  139. package/dist/core/proof/root-cause-policy.js +1 -3
  140. package/dist/core/proof/validation.js +1 -3
  141. package/dist/core/provider/model-router.js +4 -0
  142. package/dist/core/provider/provider-context.js +1 -3
  143. package/dist/core/providers/openrouter/openrouter-account.js +1 -3
  144. package/dist/core/quality/helper-dedup.js +0 -0
  145. package/dist/core/recallpulse.js +1 -1
  146. package/dist/core/release/file-ownership.js +26 -17
  147. package/dist/core/release/macos-menubar-proof.js +59 -1
  148. package/dist/core/release/main-push-guard.js +288 -24
  149. package/dist/core/release/main-push-receipt.js +10 -45
  150. package/dist/core/release/package-size-budget.js +1 -1
  151. package/dist/core/release/release-gate-contract.js +2 -0
  152. package/dist/core/release/release-pack-receipt.js +1 -1
  153. package/dist/core/release/release-proof-io.js +33 -0
  154. package/dist/core/release/release-upgrade-baseline.js +9 -0
  155. package/dist/core/release/runtime-script-pack-closure.js +153 -4
  156. package/dist/core/release/stage-publish.js +194 -0
  157. package/dist/core/remote/index.js +2 -0
  158. package/dist/core/remote/local-worker-client.js +35 -0
  159. package/dist/core/remote/machine-registry.js +18 -13
  160. package/dist/core/remote/owner-proof.js +1 -3
  161. package/dist/core/remote/protocol.js +1 -3
  162. package/dist/core/remote/readiness.js +1 -3
  163. package/dist/core/remote/session-binding.js +153 -0
  164. package/dist/core/remote/session-index.js +1 -3
  165. package/dist/core/remote/types.js +1 -0
  166. package/dist/core/remote/worker.js +228 -14
  167. package/dist/core/responses-stream.js +151 -0
  168. package/dist/core/routes/dollar-manifest-lite.js +1 -1
  169. package/dist/core/routes.js +8 -8
  170. package/dist/core/rust-accelerator.js +12 -2
  171. package/dist/core/safety/ssot-guard.js +1 -3
  172. package/dist/core/search/benchmark.js +358 -0
  173. package/dist/core/search/cache.js +65 -0
  174. package/dist/core/search/context.js +144 -0
  175. package/dist/core/search/doctor.js +74 -0
  176. package/dist/core/search/files.js +192 -0
  177. package/dist/core/search/index.js +5 -0
  178. package/dist/core/search/ipc.js +64 -0
  179. package/dist/core/search/provider.js +142 -0
  180. package/dist/core/search/rust-bridge.js +24 -0
  181. package/dist/core/search/structure.js +230 -0
  182. package/dist/core/search/symbol.js +272 -0
  183. package/dist/core/search/text.js +146 -0
  184. package/dist/core/search/types.js +22 -0
  185. package/dist/core/search/typescript-ls.js +215 -0
  186. package/dist/core/search-visibility/discovery.js +1 -3
  187. package/dist/core/skill-forge.js +1 -1
  188. package/dist/core/stop-gate/gate-evaluator.js +3 -3
  189. package/dist/core/stop-gate/stop-gate-check.js +1 -3
  190. package/dist/core/structured-output-adapter.js +62 -2
  191. package/dist/core/subagents/agent-catalog.js +56 -43
  192. package/dist/core/subagents/model-policy.js +17 -7
  193. package/dist/core/subagents/naruto-proof-projection.js +2 -6
  194. package/dist/core/subagents/official-subagent-config.js +1 -3
  195. package/dist/core/subagents/official-subagent-preparation.js +73 -10
  196. package/dist/core/subagents/official-subagent-prompt.js +85 -18
  197. package/dist/core/subagents/official-subagent-runner.js +10 -5
  198. package/dist/core/subagents/role-model-preferences.js +202 -44
  199. package/dist/core/subagents/subagent-evidence.js +1 -3
  200. package/dist/core/subagents/thread-budget.js +1 -1
  201. package/dist/core/subagents/triwiki-attention.js +1 -5
  202. package/dist/core/telegram/config.js +29 -12
  203. package/dist/core/telegram/hub.js +8 -2
  204. package/dist/core/telegram/index.js +2 -0
  205. package/dist/core/telegram/messages.js +8 -2
  206. package/dist/core/telegram/runtime-projection.js +8 -5
  207. package/dist/core/telegram/runtime.js +19 -9
  208. package/dist/core/telegram/service.js +181 -0
  209. package/dist/core/telegram/setup.js +220 -0
  210. package/dist/core/text/regex.js +3 -0
  211. package/dist/core/text/strings.js +6 -0
  212. package/dist/core/triwiki-wrongness/image-wrongness.js +1 -3
  213. package/dist/core/triwiki-wrongness/wrongness-ledger.js +1 -3
  214. package/dist/core/triwiki-wrongness/wrongness-proof-linker.js +1 -3
  215. package/dist/core/triwiki-wrongness/wrongness-retrieval.js +1 -3
  216. package/dist/core/triwiki-wrongness/wrongness-schema.js +1 -3
  217. package/dist/core/triwiki-wrongness/wrongness-trust-policy.js +1 -3
  218. package/dist/core/trust-kernel/completion-contract.js +1 -3
  219. package/dist/core/trust-kernel/route-contract.js +1 -3
  220. package/dist/core/update/update-migration-state.js +1 -3
  221. package/dist/core/update-check.js +20 -6
  222. package/dist/core/verification/diff-quality.js +3 -4
  223. package/dist/core/verification/impact-scan.js +36 -89
  224. package/dist/core/verification/mistake-rule-compiler.js +17 -4
  225. package/dist/core/version-manager.js +3 -20
  226. package/dist/core/version.js +1 -1
  227. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +23 -3
  228. package/dist/native/sks-menubar/Sources/ControlKit.swift +102 -0
  229. package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +23 -11
  230. package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +7 -3
  231. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +17 -1
  232. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +22 -15
  233. package/dist/native/sks-menubar/Sources/ProcessClient.swift +15 -5
  234. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +324 -0
  235. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +154 -214
  236. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +252 -0
  237. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +77 -71
  238. package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +167 -51
  239. package/dist/native/sks-menubar/Sources/SettingsViewController.swift +14 -5
  240. package/dist/native/sks-menubar/Sources/SidebarItem.swift +15 -1
  241. package/dist/native/sks-menubar/Sources/StatusItemController.swift +2 -2
  242. package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +16 -12
  243. package/dist/scripts/agent-guidance-dedup-check.js +23 -0
  244. package/dist/scripts/agent-message-bus-reader-check.js +1 -1
  245. package/dist/scripts/all-feature-deep-completion-check.js +1 -1
  246. package/dist/scripts/appshots-thread-attachment-discovery-check.js +1 -1
  247. package/dist/scripts/architecture-guard-check.js +1 -2
  248. package/dist/scripts/certificate-sla-check.js +1 -1
  249. package/dist/scripts/cli-output-consistency-check.js +1 -1
  250. package/dist/scripts/codex-0-134-runner-truth-check.js +1 -1
  251. package/dist/scripts/codex-0138-capability-artifact-check.js +1 -1
  252. package/dist/scripts/codex-0138-capability-check.js +1 -1
  253. package/dist/scripts/codex-0138-doctor-check.js +1 -1
  254. package/dist/scripts/codex-0138-feature-probes-check.js +1 -1
  255. package/dist/scripts/codex-0144-app-server-v2-check.js +1 -1
  256. package/dist/scripts/codex-0144-binary-identity-check.js +1 -1
  257. package/dist/scripts/codex-0144-capability-check.js +1 -1
  258. package/dist/scripts/codex-0144-core-real-probes-check.js +1 -1
  259. package/dist/scripts/codex-0144-manifest-check.js +1 -1
  260. package/dist/scripts/codex-0144-policy-check.js +1 -1
  261. package/dist/scripts/codex-0144-thread-store-check.js +1 -1
  262. package/dist/scripts/codex-agent-role-rich-content-check.js +2 -2
  263. package/dist/scripts/codex-agent-role-sync-check.js +2 -2
  264. package/dist/scripts/codex-agent-type-routing-check.js +2 -2
  265. package/dist/scripts/codex-app-execution-profile-check.js +2 -2
  266. package/dist/scripts/codex-app-handoff-check.js +1 -1
  267. package/dist/scripts/codex-app-handoff-launch-check.js +1 -1
  268. package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +1 -1
  269. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +1 -3
  270. package/dist/scripts/codex-native-feature-broker-blackbox.js +2 -2
  271. package/dist/scripts/codex-native-feature-broker-check.js +2 -2
  272. package/dist/scripts/{sks-3-1-6-directive-check-lib.js → codex-native-gate-lib.js} +5 -5
  273. package/dist/scripts/codex-native-harness-compat-check.js +2 -2
  274. package/dist/scripts/codex-native-hook-lifecycle-proof-check.js +2 -2
  275. package/dist/scripts/codex-plugin-app-template-policy-check.js +1 -1
  276. package/dist/scripts/codex-sdk-backend-router-check.js +1 -1
  277. package/dist/scripts/codex-sdk-capability-check.js +1 -1
  278. package/dist/scripts/context7-evidence-dedupe-check.js +1 -1
  279. package/dist/scripts/core-skill-card-schema-check.js +1 -1
  280. package/dist/scripts/core-skill-deployment-snapshot-check.js +1 -1
  281. package/dist/scripts/core-skill-heldout-validation-check.js +1 -1
  282. package/dist/scripts/core-skill-no-inference-optimizer-check.js +1 -1
  283. package/dist/scripts/core-skill-patch-check.js +1 -1
  284. package/dist/scripts/core-skill-route-runtime-integration-check.js +1 -1
  285. package/dist/scripts/current-command-surface-check.js +1 -1
  286. package/dist/scripts/current-surface-update-e2e-check.js +4 -1
  287. package/dist/scripts/current-upgrade-matrix-check.js +1 -1
  288. package/dist/scripts/dfix-fixture-check.js +1 -1
  289. package/dist/scripts/dfix-patch-handoff-check.js +1 -1
  290. package/dist/scripts/dfix-verification-check.js +1 -1
  291. package/dist/scripts/dfix-verification-recommendation-check.js +1 -1
  292. package/dist/scripts/docs-truthfulness-check.js +16 -3
  293. package/dist/scripts/doctor-codex-app-harness-check.js +2 -2
  294. package/dist/scripts/evidence-flagship-coverage-check.js +1 -1
  295. package/dist/scripts/{sks-1-18-gate-lib.js → gate-lib.js} +1 -1
  296. package/dist/scripts/gate-policy-audit-check.js +4 -1
  297. package/dist/scripts/git-worktree-checkpoint-check.js +1 -1
  298. package/dist/scripts/git-worktree-cross-rebase-check.js +1 -1
  299. package/dist/scripts/git-worktree-diff-envelope-check.js +1 -1
  300. package/dist/scripts/git-worktree-dirty-lock-check.js +1 -1
  301. package/dist/scripts/git-worktree-dirty-main-detection-check.js +1 -1
  302. package/dist/scripts/git-worktree-integration-primary-check.js +1 -1
  303. package/dist/scripts/git-worktree-manifest-append-check.js +1 -1
  304. package/dist/scripts/git-worktree-untracked-diff-check.js +1 -1
  305. package/dist/scripts/harness-benchmark-check.js +1 -1
  306. package/dist/scripts/helper-dedup-check.js +62 -0
  307. package/dist/scripts/hook-latency-budget-check.js +1 -1
  308. package/dist/scripts/image-artifact-path-contract-check.js +1 -1
  309. package/dist/scripts/imagegen-real-smoke-check.js +2 -5
  310. package/dist/scripts/installed-package-smoke-check.js +1 -1
  311. package/dist/scripts/legacy-gate-inventory-check.js +1 -1
  312. package/dist/scripts/legacy-gate-purge-check.js +1 -1
  313. package/dist/scripts/legacy-strong-inventory-check.js +1 -1
  314. package/dist/scripts/lib/codex-sdk-gate-lib.js +1 -1
  315. package/dist/scripts/mad-sks-launch-sql-plane-boundary-check.js +1 -1
  316. package/dist/scripts/mad-sks-sql-plane-capability-check.js +1 -1
  317. package/dist/scripts/mad-sks-sql-plane-lifecycle-hook-decision-check.js +1 -1
  318. package/dist/scripts/mad-sks-sql-plane-result-lifecycle-check.js +1 -1
  319. package/dist/scripts/managed-config-merge-check.js +1 -1
  320. package/dist/scripts/mcp-plugin-inventory-check.js +1 -1
  321. package/dist/scripts/model-call-concurrency-check.js +1 -1
  322. package/dist/scripts/mutation-callsite-coverage-check.js +1 -1
  323. package/dist/scripts/naruto-ssot-gate-aliases-check.js +1 -1
  324. package/dist/scripts/naruto-ssot-pipeline-default-check.js +1 -1
  325. package/dist/scripts/naruto-ssot-route-normalization-check.js +1 -1
  326. package/dist/scripts/naruto-ssot-routing-check.js +1 -1
  327. package/dist/scripts/naruto-worktree-coding-blackbox.js +1 -1
  328. package/dist/scripts/native-capability-repair-matrix-check.js +1 -1
  329. package/dist/scripts/native-image-generation-repair-check.js +1 -1
  330. package/dist/scripts/official-subagent-workflow-check.js +3 -3
  331. package/dist/scripts/package-published-contract-check.js +37 -4
  332. package/dist/scripts/packlist-performance-check.js +17 -1
  333. package/dist/scripts/pipeline-codex-native-doctor-mad-routing-real-blackbox.js +1 -3
  334. package/dist/scripts/ppt-real-export-adapter-check.js +1 -1
  335. package/dist/scripts/ppt-real-imagegen-wiring-check.js +1 -1
  336. package/dist/scripts/ppt-reexport-rereview-check.js +1 -1
  337. package/dist/scripts/prepublish-fast-check.js +1 -1
  338. package/dist/scripts/probe-memoization-check.js +2 -2
  339. package/dist/scripts/prompt-placeholder-guard-check.js +1 -1
  340. package/dist/scripts/qa-loop-app-handoff-capability-check.js +1 -1
  341. package/dist/scripts/qa-loop-app-handoff-check.js +1 -1
  342. package/dist/scripts/qa-loop-app-handoff-cli-check.js +1 -1
  343. package/dist/scripts/qa-loop-app-handoff-confirmation-check.js +1 -1
  344. package/dist/scripts/qa-loop-app-handoff-gate-lifecycle-check.js +1 -1
  345. package/dist/scripts/qa-loop-app-handoff-launch-check.js +1 -1
  346. package/dist/scripts/qa-loop-app-handoff-status-lifecycle-check.js +1 -1
  347. package/dist/scripts/qa-loop-budget-policy-check.js +1 -1
  348. package/dist/scripts/qa-loop-effort-escalation-check.js +1 -1
  349. package/dist/scripts/qa-loop-execution-profile-routing-check.js +2 -2
  350. package/dist/scripts/qa-loop-image-path-exposure-check.js +1 -1
  351. package/dist/scripts/qa-loop-image-path-prompt-injection-check.js +1 -1
  352. package/dist/scripts/{sks-1-12-real-execution-check-lib.js → real-execution-check-lib.js} +1 -1
  353. package/dist/scripts/release-affected-selector-check.js +1 -1
  354. package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
  355. package/dist/scripts/release-cache-glob-hashing-check.js +1 -1
  356. package/dist/scripts/release-cache-input-classifier-check.js +1 -1
  357. package/dist/scripts/release-cache-neutralization-report-check.js +1 -1
  358. package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -1
  359. package/dist/scripts/release-dynamic-presets-check.js +2 -2
  360. package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
  361. package/dist/scripts/release-gate-batch-runner-check.js +1 -1
  362. package/dist/scripts/release-gate-budget-check.js +1 -1
  363. package/dist/scripts/release-gate-dag-runner-check.js +1 -1
  364. package/dist/scripts/release-latency-slo-check.js +1 -1
  365. package/dist/scripts/release-metadata-check.js +256 -2
  366. package/dist/scripts/release-parallel-speed-budget-check.js +1 -1
  367. package/dist/scripts/release-proof-truth-check.js +1 -1
  368. package/dist/scripts/release-provenance-check.js +4 -2
  369. package/dist/scripts/release-runtime-truth-matrix-check.js +1 -1
  370. package/dist/scripts/research-blueprint-densifier-check.js +1 -1
  371. package/dist/scripts/research-claim-builder-check.js +1 -1
  372. package/dist/scripts/research-complete-package-fixture-check.js +1 -1
  373. package/dist/scripts/research-execution-profile-routing-check.js +2 -2
  374. package/dist/scripts/research-final-reviewer-blackbox.js +1 -1
  375. package/dist/scripts/{sks-3-1-4-directive-check-lib.js → runtime-domain-gate-lib.js} +2 -2
  376. package/dist/scripts/runtime-proof-summary-check.js +1 -1
  377. package/dist/scripts/runtime-script-pack-closure-check.js +7 -1
  378. package/dist/scripts/scheduler-batch-dispatch-check.js +1 -1
  379. package/dist/scripts/scheduler-parallel-proof-consistency-check.js +1 -1
  380. package/dist/scripts/scheduler-utilization-integral-check.js +1 -1
  381. package/dist/scripts/search-visibility-gate-lib.js +1 -1
  382. package/dist/scripts/secret-preservation-check.js +1 -1
  383. package/dist/scripts/seo-geo-geo-disambiguation-check.js +1 -1
  384. package/dist/scripts/seo-geo-skill-rich-content-check.js +1 -1
  385. package/dist/scripts/side-effect-runtime-report-check.js +1 -1
  386. package/dist/scripts/{sks-3-1-8-check-lib.js → skill-fixture-check-lib.js} +1 -1
  387. package/dist/scripts/skill-name-canonicalizer-check.js +1 -1
  388. package/dist/scripts/skills-manifest-continuity-check.js +1 -1
  389. package/dist/scripts/sks-uninstall-regression-check.js +1 -1
  390. package/dist/scripts/sksd-daemon-check.js +1 -1
  391. package/dist/scripts/super-search-provider-interface-check.js +1 -1
  392. package/dist/scripts/triwiki-cache-key-check.js +1 -1
  393. package/dist/scripts/triwiki-proof-bank-blackbox.js +2 -2
  394. package/dist/scripts/triwiki-proof-bank-check.js +1 -1
  395. package/dist/scripts/triwiki-proof-card-check.js +1 -1
  396. package/dist/scripts/type-surface-codex-app-check.js +2 -2
  397. package/dist/scripts/{sks-3-1-5-directive-check-lib.js → typed-routing-gate-lib.js} +2 -2
  398. package/dist/scripts/ultra-router-auto-router-check.js +1 -1
  399. package/dist/scripts/ux-review-extract-wires-real-extractor-check.js +1 -1
  400. package/dist/scripts/ux-review-patch-diff-recheck-check.js +1 -1
  401. package/dist/scripts/ux-review-run-wires-imagegen-check.js +9 -2
  402. package/package.json +5 -7
  403. package/release-gates.v2.json +66 -11
  404. package/runtime-required-scripts.json +138 -14
  405. package/config/bench-baseline.json +0 -7
  406. package/dist/core/codex-app/sks-menubar.js +0 -1
  407. package/dist/core/release/release-closure-contract.js +0 -30
  408. package/dist/core/release/release-closure-helpers.js +0 -293
  409. package/dist/core/release/release-closure-validation.js +0 -284
  410. package/dist/core/release/release-closure.js +0 -163
  411. package/dist/scripts/build-dist.js +0 -124
  412. package/dist/scripts/build-once-runner-check.js +0 -6
  413. package/dist/scripts/canonical-test-runner.js +0 -234
  414. package/dist/scripts/changelog-check.js +0 -45
  415. package/dist/scripts/check-architecture.js +0 -295
  416. package/dist/scripts/check-cli-entrypoint.js +0 -41
  417. package/dist/scripts/check-command-module-budget.js +0 -77
  418. package/dist/scripts/check-feature-quality.js +0 -51
  419. package/dist/scripts/check-legacy-free.js +0 -64
  420. package/dist/scripts/check-pipeline-budget.js +0 -49
  421. package/dist/scripts/check-pipeline-runtime.js +0 -16
  422. package/dist/scripts/check-publish-tag.js +0 -56
  423. package/dist/scripts/check-route-modularity.js +0 -72
  424. package/dist/scripts/codex-0140-capability-check.js +0 -14
  425. package/dist/scripts/codex-0140-feature-probes-check.js +0 -23
  426. package/dist/scripts/codex-permission-profiles-check.js +0 -34
  427. package/dist/scripts/codex-project-config-policy-splitter-check.js +0 -49
  428. package/dist/scripts/competitor-scorecard-check.js +0 -24
  429. package/dist/scripts/core-skill-no-drift-check.js +0 -23
  430. package/dist/scripts/db-route-materialization-check.js +0 -32
  431. package/dist/scripts/doctor-context7-mcp-repair-blackbox.js +0 -15
  432. package/dist/scripts/doctor-fastpath-check.js +0 -25
  433. package/dist/scripts/doctor-fix-production-blackbox.js +0 -35
  434. package/dist/scripts/doctor-idempotence-check.js +0 -6
  435. package/dist/scripts/doctor-ops-semantics-check.js +0 -83
  436. package/dist/scripts/doctor-startup-config-repair-blackbox.js +0 -18
  437. package/dist/scripts/doctor-supabase-mcp-repair-blackbox.js +0 -13
  438. package/dist/scripts/ensure-bin-executable.js +0 -16
  439. package/dist/scripts/fsx-hotpath-check.js +0 -9
  440. package/dist/scripts/high-risk-contracts-check.js +0 -183
  441. package/dist/scripts/hook-latency-quantum-check.js +0 -120
  442. package/dist/scripts/import-graph-budget-check.js +0 -9
  443. package/dist/scripts/mcp-tool-naming-parity-check.js +0 -14
  444. package/dist/scripts/naruto-codex-e2e-check.js +0 -105
  445. package/dist/scripts/naruto-write-e2e-check.js +0 -31
  446. package/dist/scripts/native-capability-postcheck-check.js +0 -16
  447. package/dist/scripts/ops-diagnostics-bundle-check.js +0 -11
  448. package/dist/scripts/parallel-production-smoke-check.js +0 -20
  449. package/dist/scripts/perf-budget-check.js +0 -12
  450. package/dist/scripts/project-skill-dedupe-blackbox.js +0 -62
  451. package/dist/scripts/release-dag-full-coverage-check.js +0 -98
  452. package/dist/scripts/release-dist-freshness-check.js +0 -6
  453. package/dist/scripts/release-file-ownership-check.js +0 -35
  454. package/dist/scripts/release-gate-script-parity-check.js +0 -148
  455. package/dist/scripts/release-macos-menubar-proof.js +0 -167
  456. package/dist/scripts/release-main-push-guard.js +0 -37
  457. package/dist/scripts/release-main-push-receipt.js +0 -43
  458. package/dist/scripts/release-metadata-1-19-check.js +0 -257
  459. package/dist/scripts/release-version-truth-check.js +0 -138
  460. package/dist/scripts/retention-apply-smoke-check.js +0 -19
  461. package/dist/scripts/retention-budget-check.js +0 -6
  462. package/dist/scripts/retention-dry-run-check.js +0 -8
  463. package/dist/scripts/rollback-recovery-smoke-check.js +0 -70
  464. package/dist/scripts/route-intent-regression-check.js +0 -42
  465. package/dist/scripts/runtime-current-terminal-check.js +0 -108
  466. package/dist/scripts/runtime-dist-parity-check.js +0 -76
  467. package/dist/scripts/runtime-no-src-mjs-check.js +0 -30
  468. package/dist/scripts/runtime-ts-rust-boundary-check.js +0 -58
  469. package/dist/scripts/runtime-ts-source-of-truth-check.js +0 -53
  470. package/dist/scripts/secret-preservation-guard-check.js +0 -36
  471. package/dist/scripts/seo-marketing-truthfulness-check.js +0 -98
  472. package/dist/scripts/seo-metadata-sync-check.js +0 -60
  473. package/dist/scripts/sizecheck.js +0 -148
  474. package/dist/scripts/sks-menubar-install-check.js +0 -333
  475. package/dist/scripts/supabase-secret-preservation-blackbox.js +0 -28
  476. package/dist/scripts/super-search-live-smoke-check.js +0 -115
  477. package/dist/scripts/super-search-local-http-smoke-check.js +0 -16
  478. package/dist/scripts/super-search-offline-contract-check.js +0 -43
  479. package/dist/scripts/update-fastpath-check.js +0 -28
  480. package/dist/scripts/update-preserves-supabase-keys-blackbox.js +0 -26
  481. package/dist/scripts/upgrade-migration-matrix-check.js +0 -351
  482. package/dist/scripts/write-build-manifest.js +0 -70
  483. package/dist/scripts/zellij-capability-check.js +0 -13
  484. package/dist/scripts/zellij-developer-controls-check.js +0 -16
  485. package/dist/scripts/zellij-doctor-readiness-check.js +0 -49
  486. package/dist/scripts/zellij-dynamic-pane-lifecycle-check.js +0 -19
  487. package/dist/scripts/zellij-fake-adapter-check.js +0 -31
  488. package/dist/scripts/zellij-first-slot-down-stack-check.js +0 -20
  489. package/dist/scripts/zellij-first-slot-down-stack-real-check.js +0 -348
  490. package/dist/scripts/zellij-homebrew-policy-check.js +0 -3
  491. package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -21
  492. package/dist/scripts/zellij-lane-renderer-check.js +0 -78
  493. package/dist/scripts/zellij-launch-command-truth-check.js +0 -62
  494. package/dist/scripts/zellij-layout-valid-check.js +0 -120
  495. package/dist/scripts/zellij-pane-creation-lock-metrics-check.js +0 -10
  496. package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -78
  497. package/dist/scripts/zellij-pane-lock-does-not-block-worker-check.js +0 -12
  498. package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -134
  499. package/dist/scripts/zellij-qa-app-handoff-status-check.js +0 -7
  500. package/dist/scripts/zellij-right-column-geometry-proof.js +0 -158
  501. package/dist/scripts/zellij-right-column-headless-overflow-check.js +0 -20
  502. package/dist/scripts/zellij-right-column-manager-check.js +0 -24
  503. package/dist/scripts/zellij-self-heal-check.js +0 -3
  504. package/dist/scripts/zellij-self-heal-dry-run-check.js +0 -3
  505. package/dist/scripts/zellij-self-heal-status-contract-check.js +0 -3
  506. package/dist/scripts/zellij-self-heal-typed-blackbox.js +0 -3
  507. package/dist/scripts/zellij-slot-column-anchor-check.js +0 -65
  508. package/dist/scripts/zellij-slot-column-anchor-telemetry-check.js +0 -8
  509. package/dist/scripts/zellij-slot-only-ui-check.js +0 -29
  510. package/dist/scripts/zellij-slot-pane-renderer-check.js +0 -149
  511. package/dist/scripts/zellij-slot-pane-stale-detection-check.js +0 -65
  512. package/dist/scripts/zellij-slot-pane-telemetry-renderer-check.js +0 -11
  513. package/dist/scripts/zellij-slot-renderer-proof-semantics-check.js +0 -58
  514. package/dist/scripts/zellij-slot-telemetry-check.js +0 -38
  515. package/dist/scripts/zellij-slot-telemetry-incremental-check.js +0 -46
  516. package/dist/scripts/zellij-slot-telemetry-live-flush-check.js +0 -55
  517. package/dist/scripts/zellij-slot-telemetry-performance-check.js +0 -32
  518. package/dist/scripts/zellij-slot-telemetry-real-blackbox.js +0 -19
  519. package/dist/scripts/zellij-slot-telemetry-renderer-check.js +0 -11
  520. package/dist/scripts/zellij-slot-telemetry-runtime-check.js +0 -23
  521. package/dist/scripts/zellij-spawn-on-demand-layout-check.js +0 -45
  522. package/dist/scripts/zellij-stacked-capability-routing-check.js +0 -9
  523. package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -78
  524. package/dist/scripts/zellij-stacked-version-matrix-check.js +0 -29
  525. package/dist/scripts/zellij-stacked-version-parser-check.js +0 -19
  526. package/dist/scripts/zellij-ui-design-check.js +0 -92
  527. package/dist/scripts/zellij-update-missing-self-heal-check.js +0 -3
  528. package/dist/scripts/zellij-update-prompt-matrix-check.js +0 -16
  529. package/dist/scripts/zellij-update-prompt-mode-check.js +0 -18
  530. package/dist/scripts/zellij-update-prompt-safety-check.js +0 -8
  531. package/dist/scripts/zellij-worker-pane-manager-check.js +0 -108
  532. package/dist/scripts/zellij-worker-pane-manager-single-owner-check.js +0 -47
  533. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -199
  534. /package/dist/scripts/{sks-1-11-gate-lib.js → sks-cli-gate-lib.js} +0 -0
@@ -0,0 +1,252 @@
1
+ import Cocoa
2
+
3
+ final class RoleModelControls {
4
+ let role: String
5
+ let model = NSPopUpButton()
6
+ let reasoning = NSPopUpButton()
7
+ let current = NativeView.detail("Current: loading…")
8
+ let save: NSButton
9
+ let reset: NSButton
10
+
11
+ init(role: String, target: AnyObject) {
12
+ self.role = role
13
+ save = NativeView.button("Save", target: target, action: #selector(ProvidersViewController.saveRoleModel(_:)))
14
+ reset = NativeView.button("Reset", target: target, action: #selector(ProvidersViewController.resetRoleModel(_:)))
15
+ save.identifier = NSUserInterfaceItemIdentifier(role)
16
+ reset.identifier = NSUserInterfaceItemIdentifier(role)
17
+ }
18
+ }
19
+
20
+ // Role-scoped model overrides (Models by Work Type). Split from
21
+ // ProvidersOpenRouter.swift to keep both files inside the release line budget.
22
+ extension ProvidersViewController {
23
+ func makeRoleModelsCard() -> NSBox {
24
+ let definitions = [
25
+ ("ui_implementer", "UI implementation"),
26
+ ("native_app_specialist", "Native app"),
27
+ ("implementation_specialist", "Implementation"),
28
+ ("test_engineer", "Testing")
29
+ ]
30
+ var views: [NSView] = [roleStatus]
31
+ for (role, title) in definitions {
32
+ let controls = RoleModelControls(role: role, target: self)
33
+ controls.model.addItem(withTitle: "Loading profiles…")
34
+ controls.model.setAccessibilityLabel("\(title) model")
35
+ controls.model.widthAnchor.constraint(greaterThanOrEqualToConstant: 210).isActive = true
36
+ controls.model.identifier = NSUserInterfaceItemIdentifier(role)
37
+ controls.model.target = self
38
+ controls.model.action = #selector(roleModelSelectionChanged(_:))
39
+ controls.reasoning.addItem(withTitle: "Loading…")
40
+ controls.reasoning.setAccessibilityLabel("\(title) reasoning effort")
41
+ controls.current.setAccessibilityLabel("\(title) current and effective model")
42
+ controls.save.setAccessibilityLabel("Save \(title) model override")
43
+ controls.reset.setAccessibilityLabel("Reset \(title) model override")
44
+ controls.model.isEnabled = false
45
+ controls.reasoning.isEnabled = false
46
+ controls.save.isEnabled = false
47
+ controls.reset.isEnabled = false
48
+ roleRows[role] = controls
49
+ actionButtons += [controls.save, controls.reset]
50
+
51
+ let heading = NativeView.sectionTitle(title)
52
+ let roleId = NativeView.detail(role)
53
+ let modelLabel = NSTextField(labelWithString: "Model")
54
+ let reasoningLabel = NSTextField(labelWithString: "Reasoning")
55
+ views.append(NativeView.row([heading, roleId]))
56
+ views.append(controls.current)
57
+ views.append(NativeView.row([modelLabel, controls.model, reasoningLabel, controls.reasoning]))
58
+ views.append(NativeView.row([controls.save, controls.reset]))
59
+ if role != definitions.last?.0 { let separator = NSBox(); separator.boxType = .separator; views.append(separator) }
60
+ }
61
+ let refresh = NativeView.button("Refresh Role Settings", target: self, action: #selector(refreshRoleModelsAction(_:)))
62
+ roleRefreshButton = refresh
63
+ actionButtons.append(refresh)
64
+ views.append(refresh)
65
+ return NativeView.card(
66
+ title: "Models by Work Type",
67
+ subtitle: "Overrides apply only to the selected agent role. Without an override, new work inherits the active main model; if no main model is selected, the managed GPT role default is used. Multi-Provider Router catalog slugs let different roles use different upstream providers.",
68
+ views: views
69
+ )
70
+ }
71
+
72
+ @objc func refreshRoleModelsAction(_ sender: NSButton) {
73
+ refreshRoleModels()
74
+ }
75
+
76
+ func refreshRoleModels() {
77
+ guard !roleRefreshInFlight else { return }
78
+ roleRefreshInFlight = true
79
+ roleRefreshButton?.isEnabled = false
80
+ roleStatus.stringValue = "Loading role model settings…"
81
+ processClient.run(["codex-app", "role-models", "--json"], timeout: NativeView.statusTimeout) { [weak self] result in
82
+ guard let self = self else { return }
83
+ self.roleRefreshInFlight = false
84
+ self.roleRefreshButton?.isEnabled = !self.busy
85
+ // role-models exits 1 on recoverable preference blockers (an override
86
+ // outside the active catalog, no router selected) while still returning
87
+ // the full roles/supported_profiles payload. Gating on the exit code
88
+ // would disable Reset — the only control that clears such an override.
89
+ // A store-level blocker is different: the preference file could not be
90
+ // read, so every save/reset fails closed and the controls must lock.
91
+ let storeBlockers = (self.json(result.output)?["store_blockers"] as? [String] ?? [])
92
+ guard let json = self.json(result.output), storeBlockers.isEmpty else {
93
+ self.roleProfilesLoaded = false
94
+ self.updateRoleControlAvailability()
95
+ self.roleStatus.stringValue = storeBlockers.isEmpty
96
+ ? "Role settings unavailable · existing configuration was not changed."
97
+ : "Role settings unavailable · \(storeBlockers.joined(separator: ", ")) · existing configuration was not changed."
98
+ return
99
+ }
100
+ let roleBlockers = (json["preference_blockers"] as? [String] ?? json["blockers"] as? [String] ?? []).joined(separator: ", ")
101
+ self.configureSupportedRoleProfiles(json)
102
+ var loaded = 0
103
+ for (role, controls) in self.roleRows {
104
+ guard let payload = self.rolePayload(json, role: role) else {
105
+ controls.current.stringValue = "Current: unavailable · Effective: unavailable"
106
+ continue
107
+ }
108
+ let configured = (payload["configured"] as? [String: Any]) ?? (payload["override"] as? [String: Any])
109
+ let effective = (payload["effective"] as? [String: Any]) ?? payload
110
+ let configuredModel = (configured?["model"] as? String) ?? (payload["configured_model"] as? String)
111
+ let configuredReasoning = self.reasoningValue(configured) ?? (payload["configured_reasoning"] as? String)
112
+ let configuredProvider = (configured?["provider"] as? String) ?? (payload["configured_provider"] as? String)
113
+ let defaultModel = payload["default_model"] as? String
114
+ let defaultReasoning = payload["default_reasoning_effort"] as? String
115
+ let effectiveModel = (effective["model"] as? String) ?? (payload["effective_model"] as? String) ?? "unavailable"
116
+ let effectiveProvider = (effective["provider"] as? String)
117
+ ?? (payload["effective_provider"] as? String)
118
+ ?? "unknown"
119
+ let effectiveReasoning = self.reasoningValue(effective)
120
+ ?? (payload["effective_reasoning_effort"] as? String)
121
+ ?? (payload["effective_reasoning"] as? String)
122
+ ?? "unavailable"
123
+ let effectiveSource = payload["effective_source"] as? String
124
+ let editorModel = configuredModel ?? (effectiveSource == "selected-main-model" ? effectiveModel : (defaultModel ?? effectiveModel))
125
+ let editorReasoning = configuredReasoning ?? (effectiveSource == "selected-main-model" ? effectiveReasoning : (defaultReasoning ?? effectiveReasoning))
126
+ self.selectRoleProfile(model: editorModel, reasoning: editorReasoning, controls: controls)
127
+ let current = configuredModel.map {
128
+ "\(self.roleModelDisplay(provider: configuredProvider ?? effectiveProvider, model: $0)) / \(configuredReasoning ?? "default")"
129
+ } ?? "default (no override)"
130
+ let effectiveDisplay = self.roleModelDisplay(provider: effectiveProvider, model: effectiveModel)
131
+ let inherited = effectiveSource == "selected-main-model" ? " · inherits active main model" : ""
132
+ controls.current.stringValue = "Current: \(current) · Effective: \(effectiveDisplay) / \(effectiveReasoning)\(inherited)"
133
+ loaded += 1
134
+ }
135
+ self.roleProfilesLoaded = !self.supportedRoleProfiles.isEmpty
136
+ self.updateRoleControlAvailability()
137
+ self.roleStatus.stringValue = roleBlockers.isEmpty
138
+ ? "Loaded \(loaded) of \(self.roleRows.count) role settings. Save creates an override; Reset removes it."
139
+ : "Loaded \(loaded) of \(self.roleRows.count) role settings · needs attention: \(roleBlockers). Reset removes an override."
140
+ }
141
+ }
142
+
143
+ func updateRoleControlAvailability() {
144
+ let enabled = !busy && roleProfilesLoaded
145
+ for controls in roleRows.values {
146
+ controls.model.isEnabled = enabled
147
+ controls.reasoning.isEnabled = enabled
148
+ controls.save.isEnabled = enabled
149
+ controls.reset.isEnabled = enabled
150
+ }
151
+ }
152
+
153
+ private func configureSupportedRoleProfiles(_ json: [String: Any]) {
154
+ let rows = json["supported_profiles"] as? [[String: Any]] ?? []
155
+ supportedRoleProfiles = rows.compactMap { row in
156
+ guard let model = row["model"] as? String,
157
+ let reasoning = row["reasoning_effort"] as? String,
158
+ !model.isEmpty, !reasoning.isEmpty else { return nil }
159
+ return (model, reasoning)
160
+ }
161
+ let models = Array(Set(supportedRoleProfiles.map(\.model))).sorted()
162
+ for controls in roleRows.values {
163
+ controls.model.removeAllItems()
164
+ controls.model.addItems(withTitles: models)
165
+ controls.reasoning.removeAllItems()
166
+ }
167
+ }
168
+
169
+ private func rolePayload(_ json: [String: Any], role: String) -> [String: Any]? {
170
+ if let roles = json["roles"] as? [String: Any], let payload = roles[role] as? [String: Any] { return payload }
171
+ if let payload = json[role] as? [String: Any] { return payload }
172
+ if let roles = json["roles"] as? [[String: Any]] {
173
+ return roles.first { ($0["role"] as? String) == role || ($0["id"] as? String) == role }
174
+ }
175
+ return nil
176
+ }
177
+
178
+ private func reasoningValue(_ json: [String: Any]?) -> String? {
179
+ (json?["reasoning"] as? String) ?? (json?["reasoning_effort"] as? String) ?? (json?["model_reasoning_effort"] as? String)
180
+ }
181
+
182
+ private func roleModelDisplay(provider: String, model: String) -> String { model.contains("/") ? model : "\(provider):\(model)" }
183
+
184
+ private func selectRoleProfile(model: String, reasoning: String, controls: RoleModelControls) {
185
+ if !controls.model.itemTitles.contains(model) {
186
+ controls.model.addItem(withTitle: model)
187
+ }
188
+ controls.model.selectItem(withTitle: model)
189
+ updateReasoningChoices(controls, preferred: reasoning)
190
+ }
191
+
192
+ @objc private func roleModelSelectionChanged(_ sender: NSPopUpButton) {
193
+ guard let role = sender.identifier?.rawValue, let controls = roleRows[role] else { return }
194
+ updateReasoningChoices(controls, preferred: nil)
195
+ }
196
+
197
+ private func updateReasoningChoices(_ controls: RoleModelControls, preferred: String?) {
198
+ let model = controls.model.titleOfSelectedItem ?? ""
199
+ var efforts = supportedRoleProfiles.filter { $0.model == model }.map(\.reasoning)
200
+ if let preferred = preferred, !preferred.isEmpty, !efforts.contains(preferred) {
201
+ efforts.append(preferred)
202
+ }
203
+ controls.reasoning.removeAllItems()
204
+ controls.reasoning.addItems(withTitles: efforts)
205
+ if let preferred = preferred, efforts.contains(preferred) { controls.reasoning.selectItem(withTitle: preferred) }
206
+ }
207
+
208
+ @objc func saveRoleModel(_ sender: NSButton) {
209
+ guard let role = sender.identifier?.rawValue, let controls = roleRows[role] else { return }
210
+ let model = controls.model.titleOfSelectedItem ?? ""
211
+ let reasoning = controls.reasoning.titleOfSelectedItem ?? "medium"
212
+ guard !model.isEmpty else { roleStatus.stringValue = "Save blocked for \(role) · enter a model id."; return }
213
+ runRoleMutation(
214
+ ["codex-app", "set-role-model", "--role", role, "--model", model, "--reasoning", reasoning, "--json"],
215
+ role: role,
216
+ kind: "role-model-set",
217
+ running: "Saving \(role) override…",
218
+ success: "Saved \(role) · \(model) / \(reasoning). Next: new tasks for this role use the effective override."
219
+ )
220
+ }
221
+
222
+ @objc func resetRoleModel(_ sender: NSButton) {
223
+ guard let role = sender.identifier?.rawValue else { return }
224
+ runRoleMutation(
225
+ ["codex-app", "reset-role-model", "--role", role, "--json"],
226
+ role: role,
227
+ kind: "role-model-reset",
228
+ running: "Resetting \(role) override…",
229
+ success: "Reset \(role). Next: new tasks use the effective default shown below."
230
+ )
231
+ }
232
+
233
+ private func runRoleMutation(_ args: [String], role: String, kind: String, running: String, success: String) {
234
+ guard !busy else { roleStatus.stringValue = "Another provider action is already running."; return }
235
+ guard let snapshot = operations.begin(kind: kind, mutationGroup: "codex-config", summary: running) else {
236
+ roleStatus.stringValue = "Another guarded mutation is already running. Wait or open Diagnostics."
237
+ return
238
+ }
239
+ setBusy(true)
240
+ roleStatus.stringValue = running
241
+ _ = operations.update(snapshot, state: .running, stage: "saving", progress: nil, summary: running)
242
+ processClient.run(args, timeout: NativeView.mutationTimeout) { [weak self] result in
243
+ guard let self = self else { return }
244
+ self.setBusy(false)
245
+ let json = self.json(result.output)
246
+ let ok = result.code == 0 && json?["ok"] as? Bool == true
247
+ _ = self.operations.update(snapshot, state: ok ? .succeeded : .failed, stage: "complete", progress: 1, summary: ok ? "Role model setting saved" : "Role model setting needs action")
248
+ self.roleStatus.stringValue = ok ? success : "\(role) change failed · \(self.structuredPublicDetail(json, fallback: result.output))"
249
+ self.refreshRoleModels()
250
+ }
251
+ }
252
+ }
@@ -1,23 +1,6 @@
1
1
  import Cocoa
2
2
 
3
- final class RoleModelControls {
4
- let role: String
5
- let model = NSPopUpButton()
6
- let reasoning = NSPopUpButton()
7
- let current = NativeView.detail("Current: loading…")
8
- let save: NSButton
9
- let reset: NSButton
10
-
11
- init(role: String, target: AnyObject) {
12
- self.role = role
13
- save = NativeView.button("Save", target: target, action: #selector(ProvidersViewController.saveRoleModel(_:)))
14
- reset = NativeView.button("Reset", target: target, action: #selector(ProvidersViewController.resetRoleModel(_:)))
15
- save.identifier = NSUserInterfaceItemIdentifier(role)
16
- reset.identifier = NSUserInterfaceItemIdentifier(role)
17
- }
18
- }
19
-
20
- final class ProvidersViewController: NSViewController, ControlCenterPage {
3
+ final class ProvidersViewController: NSViewController, ControlCenterPage, NSTextFieldDelegate {
21
4
  private struct CodexLbReadiness {
22
5
  let selected: Bool
23
6
  let providerReady: Bool
@@ -39,24 +22,34 @@ final class ProvidersViewController: NSViewController, ControlCenterPage {
39
22
  let openRouterModelField: NSTextField = {
40
23
  let field = NSTextField(frame: NSRect(x: 0, y: 0, width: 280, height: 24))
41
24
  field.placeholderString = "z-ai/glm-5.2"
42
- field.stringValue = "z-ai/glm-5.2"
43
25
  field.setAccessibilityLabel("Manual OpenRouter model id")
44
26
  field.setAccessibilityPlaceholderValue("provider/model")
45
27
  return field
46
28
  }()
47
29
  let openRouterModelPopup = NSPopUpButton()
30
+ let multiProvider = MultiProviderRouterControls()
48
31
  let roleStatus = NativeView.detail("Role model settings are loading…")
49
32
  let globalSpinner = NativeView.spinner(label: "Provider operation in progress")
50
33
  let fastStatus = NativeView.detail("Fast Mode: checking current desktop setting…")
34
+ let activeProviderBadge = ControlKit.badge("Checking the active Codex provider…", tone: .busy)
35
+ var codexLbSelectedNow = false
36
+ var openRouterSelectedNow = false
37
+ var openRouterActiveModel = ""
38
+ var routerSelectedNow = false
39
+ var routerActiveModel = ""
51
40
  var roleRows: [String: RoleModelControls] = [:]
52
41
  var actionButtons: [NSButton] = []
53
42
  var openRouterModels: [String] = []
54
43
  var supportedRoleProfiles: [(model: String, reasoning: String)] = []
55
44
  var roleProfilesLoaded = false
56
45
  weak var openRouterRefreshButton: NSButton?
46
+ weak var openRouterRestoreButton: NSButton?
47
+ var openRouterRestoreAvailable = false
57
48
  weak var roleRefreshButton: NSButton?
58
49
  var catalogRefreshInFlight = false
59
50
  var roleRefreshInFlight = false
51
+ var openRouterModelSelectionPending = false
52
+ var openRouterActionRan = false
60
53
  var busy = false
61
54
 
62
55
  init(processClient: ProcessClient, operations: OperationCoordinator) {
@@ -78,7 +71,6 @@ final class ProvidersViewController: NSViewController, ControlCenterPage {
78
71
  useOAuth.setAccessibilityLabel("Restore ChatGPT OAuth and restart Codex App")
79
72
  actionButtons = [setDomain, replace, testConnection, useOAuth, useLb, fastOn, fastOff]
80
73
 
81
- let titleRow = NativeView.row([NativeView.title("Providers & Models"), globalSpinner])
82
74
  let codexLb = NativeView.card(
83
75
  title: "codex-lb",
84
76
  subtitle: "Credentials and activation are separate. Test the saved endpoint before making codex-lb the active Codex provider.",
@@ -90,9 +82,10 @@ final class ProvidersViewController: NSViewController, ControlCenterPage {
90
82
  views: [fastStatus, NativeView.row([fastOn, fastOff])]
91
83
  )
92
84
  view = NativeView.page([
93
- titleRow,
85
+ NativeView.row([NativeView.title("Providers & Models"), globalSpinner]),
94
86
  NativeView.detail("Save credentials, verify connectivity, then explicitly activate a provider. Secrets are sent through stdin and redacted from logs."),
95
- makeOpenRouterCard(), codexLb, makeRoleModelsCard(), fast
87
+ makeActiveProviderCard(),
88
+ makeOpenRouterCard(), makeMultiProviderRouterCard(), codexLb, makeRoleModelsCard(), fast
96
89
  ])
97
90
  refresh()
98
91
  }
@@ -105,7 +98,9 @@ final class ProvidersViewController: NSViewController, ControlCenterPage {
105
98
  openRouterModelField.isEnabled = !value
106
99
  openRouterModelPopup.isEnabled = !value && !openRouterModels.isEmpty
107
100
  openRouterRefreshButton?.isEnabled = !value && !catalogRefreshInFlight
101
+ openRouterRestoreButton?.isEnabled = !value && openRouterRestoreAvailable
108
102
  roleRefreshButton?.isEnabled = !value && !roleRefreshInFlight
103
+ setMultiProviderRouterBusy(value)
109
104
  updateRoleControlAvailability()
110
105
  if value { globalSpinner.startAnimation(nil) }
111
106
  else { globalSpinner.stopAnimation(nil) }
@@ -148,9 +143,12 @@ final class ProvidersViewController: NSViewController, ControlCenterPage {
148
143
  if !self.busy { self.providerStatus.stringValue = "Provider status unavailable. Retry or open Diagnostics." }
149
144
  return
150
145
  }
146
+ self.codexLbSelectedNow = self.codexLbReadiness(self.codexLbPayload(json)).selected
147
+ self.renderActiveProviderSummary()
151
148
  if !self.busy { self.providerStatus.stringValue = self.describeProviderStatus(json) }
152
149
  }
153
150
  refreshOpenRouterStatus()
151
+ refreshMultiProviderRouterStatus()
154
152
  if openRouterModels.isEmpty { refreshOpenRouterModels() }
155
153
  refreshRoleModels()
156
154
  refreshFastStatus()
@@ -424,64 +422,72 @@ final class ProvidersViewController: NSViewController, ControlCenterPage {
424
422
  providerStatus.stringValue = "Another provider action is already running."
425
423
  return
426
424
  }
427
- guard let snapshot = operations.begin(kind: "codex-lb-use-oauth", mutationGroup: "codex-config", summary: "Restore Chat / Pro") else {
428
- providerStatus.stringValue = "Another guarded mutation is already running. Wait or open Diagnostics."
429
- return
430
- }
431
- setBusy(true)
432
- providerStatus.stringValue = "Restoring Chat / Pro with ChatGPT OAuth and restarting Codex App…"
433
- _ = operations.update(snapshot, state: .running, stage: "switching", progress: nil, summary: "Restore Chat / Pro")
434
- processClient.run(["codex-lb", "use-oauth", "--restart-app", "--json"], timeout: NativeView.mutationTimeout) { [weak self] result in
435
- guard let self = self else { return }
436
- self.setBusy(false)
437
- let outcome = self.describeOAuthResult(self.json(result.output), processCode: result.code)
438
- _ = self.operations.update(
439
- snapshot,
440
- state: outcome.ok ? .succeeded : .failed,
441
- stage: "complete",
442
- progress: 1,
443
- summary: outcome.ok ? "Chat / Pro restored after restart" : "Chat / Pro restore needs action"
444
- )
445
- self.providerStatus.stringValue = outcome.message
446
- self.refreshFastStatus()
447
- }
448
- }
449
- @objc private func useCodexLb() {
450
- guard !busy else {
451
- providerStatus.stringValue = "Another provider action is already running."
452
- return
453
- }
454
- guard let snapshot = operations.begin(kind: "codex-lb-use-lb", mutationGroup: "codex-config", summary: "Use codex-lb") else {
455
- providerStatus.stringValue = "Another guarded mutation is already running. Wait or open Diagnostics."
456
- return
457
- }
458
- setBusy(true)
459
- providerStatus.stringValue = "Activating codex-lb and restarting Codex App…"
460
- _ = operations.update(snapshot, state: .running, stage: "activating", progress: nil, summary: "Use codex-lb")
461
- processClient.run(["codex-lb", "use-codex-lb", "--restart-app", "--json"], timeout: NativeView.mutationTimeout) { [weak self] activationResult in
462
- guard let self = self else { return }
463
- let activationJson = self.json(activationResult.output)
464
- _ = self.operations.update(snapshot, state: .running, stage: "verifying", progress: nil, summary: "Verify codex-lb after restart")
465
- self.providerStatus.stringValue = "Verifying codex-lb readiness after restart…"
466
- self.processClient.run(["codex-lb", "status", "--json"], timeout: NativeView.statusTimeout) { [weak self] statusResult in
425
+ guard let window = view.window else { return }
426
+ AlertFactory.confirmSheet(window: window, title: "Restore Chat / Pro?", message: "Codex App restarts with ChatGPT OAuth. Saved codex-lb credentials stay available for later reuse.", destructive: false) { [weak self] approved in
427
+ guard let self = self, approved else { return }
428
+ guard let snapshot = self.operations.begin(kind: "codex-lb-use-oauth", mutationGroup: "codex-config", summary: "Restore Chat / Pro") else {
429
+ self.providerStatus.stringValue = "Another guarded mutation is already running. Wait or open Diagnostics."
430
+ return
431
+ }
432
+ self.setBusy(true)
433
+ self.providerStatus.stringValue = "Restoring Chat / Pro with ChatGPT OAuth and restarting Codex App…"
434
+ _ = self.operations.update(snapshot, state: .running, stage: "switching", progress: nil, summary: "Restore Chat / Pro")
435
+ self.processClient.run(["codex-lb", "use-oauth", "--restart-app", "--json"], timeout: NativeView.mutationTimeout) { [weak self] result in
467
436
  guard let self = self else { return }
468
437
  self.setBusy(false)
469
- let statusJson = self.json(statusResult.output)
470
- let outcome = self.describeActivationResult(
471
- activationJson,
472
- status: statusJson,
473
- activationCode: activationResult.code,
474
- statusCode: statusResult.code
475
- )
438
+ let outcome = self.describeOAuthResult(self.json(result.output), processCode: result.code)
476
439
  _ = self.operations.update(
477
440
  snapshot,
478
441
  state: outcome.ok ? .succeeded : .failed,
479
442
  stage: "complete",
480
443
  progress: 1,
481
- summary: outcome.ok ? "codex-lb active after restart" : "codex-lb activation needs action"
444
+ summary: outcome.ok ? "Chat / Pro restored after restart" : "Chat / Pro restore needs action"
482
445
  )
483
446
  self.providerStatus.stringValue = outcome.message
484
- self.refreshOpenRouterStatus()
447
+ self.refreshFastStatus()
448
+ }
449
+ }
450
+ }
451
+ @objc private func useCodexLb() {
452
+ guard !busy else {
453
+ providerStatus.stringValue = "Another provider action is already running."
454
+ return
455
+ }
456
+ guard let window = view.window else { return }
457
+ AlertFactory.confirmSheet(window: window, title: "Use codex-lb?", message: "codex-lb becomes the active Codex provider and Codex App restarts.", destructive: false) { [weak self] approved in
458
+ guard let self = self, approved else { return }
459
+ guard let snapshot = self.operations.begin(kind: "codex-lb-use-lb", mutationGroup: "codex-config", summary: "Use codex-lb") else {
460
+ self.providerStatus.stringValue = "Another guarded mutation is already running. Wait or open Diagnostics."
461
+ return
462
+ }
463
+ self.setBusy(true)
464
+ self.providerStatus.stringValue = "Activating codex-lb and restarting Codex App…"
465
+ _ = self.operations.update(snapshot, state: .running, stage: "activating", progress: nil, summary: "Use codex-lb")
466
+ self.processClient.run(["codex-lb", "use-codex-lb", "--restart-app", "--json"], timeout: NativeView.mutationTimeout) { [weak self] activationResult in
467
+ guard let self = self else { return }
468
+ let activationJson = self.json(activationResult.output)
469
+ _ = self.operations.update(snapshot, state: .running, stage: "verifying", progress: nil, summary: "Verify codex-lb after restart")
470
+ self.providerStatus.stringValue = "Verifying codex-lb readiness after restart…"
471
+ self.processClient.run(["codex-lb", "status", "--json"], timeout: NativeView.statusTimeout) { [weak self] statusResult in
472
+ guard let self = self else { return }
473
+ self.setBusy(false)
474
+ let statusJson = self.json(statusResult.output)
475
+ let outcome = self.describeActivationResult(
476
+ activationJson,
477
+ status: statusJson,
478
+ activationCode: activationResult.code,
479
+ statusCode: statusResult.code
480
+ )
481
+ _ = self.operations.update(
482
+ snapshot,
483
+ state: outcome.ok ? .succeeded : .failed,
484
+ stage: "complete",
485
+ progress: 1,
486
+ summary: outcome.ok ? "codex-lb active after restart" : "codex-lb activation needs action"
487
+ )
488
+ self.providerStatus.stringValue = outcome.message
489
+ self.refreshOpenRouterStatus()
490
+ }
485
491
  }
486
492
  }
487
493
  }