sneakoscope 8.1.2 → 8.2.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 (261) hide show
  1. package/README.md +96 -58
  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 +5 -51
  5. package/dist/cli/command-manifest-lite.js +2 -1
  6. package/dist/cli/command-registry.js +2 -1
  7. package/dist/cli/global-mode-router.js +1 -1
  8. package/dist/cli/install-helpers-codex-lb-config.js +112 -914
  9. package/dist/cli/install-helpers-codex-lb-shared.js +3 -44
  10. package/dist/cli/install-helpers-install-support.js +4 -20
  11. package/dist/cli/install-helpers.js +36 -2716
  12. package/dist/cli/router.js +9 -9
  13. package/dist/commands/bridge-command-output.js +111 -0
  14. package/dist/commands/bridge.js +320 -0
  15. package/dist/commands/codex-app.js +39 -123
  16. package/dist/commands/doctor-helpers.js +380 -0
  17. package/dist/commands/doctor-profile.js +3 -0
  18. package/dist/commands/doctor.js +114 -873
  19. package/dist/commands/mad-sks.js +0 -4
  20. package/dist/config/skills-manifest.json +1 -1
  21. package/dist/core/agents/agent-effort-policy.js +11 -21
  22. package/dist/core/agents/agent-recursion-guard.js +26 -0
  23. package/dist/core/agents/agent-runner-codex-exec.js +7 -9
  24. package/dist/core/architecture-hardening/contracts/contracts.js +225 -161
  25. package/dist/core/architecture-hardening/state/state-service.js +49 -13
  26. package/dist/core/auto-review.js +15 -9
  27. package/dist/core/codex/codex-config-guard.js +8 -0
  28. package/dist/core/codex-adapter.js +8 -10
  29. package/dist/core/codex-app/codex-app-fast-ui-repair.js +7 -29
  30. package/dist/core/codex-app/codex-app-launcher.js +10 -12
  31. package/dist/core/codex-app/codex-app-restart.js +10 -12
  32. package/dist/core/codex-app/menubar/constants.js +2 -5
  33. package/dist/core/codex-app/menubar/global-install.js +3 -2
  34. package/dist/core/codex-app/menubar/installer/result.js +23 -0
  35. package/dist/core/codex-app/menubar/installer/runtime.js +28 -0
  36. package/dist/core/codex-app/menubar/installer.js +5 -96
  37. package/dist/core/codex-app/menubar/migration.js +1 -42
  38. package/dist/core/codex-app/openrouter-provider.js +0 -78
  39. package/dist/core/codex-app.js +97 -360
  40. package/dist/core/codex-control/codex-app-server-runtime-env.js +8 -28
  41. package/dist/core/codex-control/codex-current-image-path-real-probe.js +2 -3
  42. package/dist/core/codex-control/codex-current-web-search-probe.js +2 -3
  43. package/dist/core/codex-control/codex-sdk-adapter.js +5 -48
  44. package/dist/core/codex-control/codex-task-runner.js +16 -60
  45. package/dist/core/codex-control/desktop-bridge-launch-guard.js +227 -0
  46. package/dist/core/codex-exec-output-schema.js +11 -13
  47. package/dist/core/codex-lb/bridge-contracts.js +2 -0
  48. package/dist/core/codex-lb/bridge-runtime-validation/capability.js +104 -0
  49. package/dist/core/codex-lb/bridge-runtime-validation/catalog.js +52 -0
  50. package/dist/core/codex-lb/bridge-runtime-validation/shared.js +109 -0
  51. package/dist/core/codex-lb/bridge-runtime-validation/status.js +250 -0
  52. package/dist/core/codex-lb/bridge-runtime-validation.js +106 -0
  53. package/dist/core/codex-lb/capability-runner.js +505 -201
  54. package/dist/core/codex-lb/codex-lb-env.js +179 -12
  55. package/dist/core/codex-lb/combined-catalog/builder.js +86 -0
  56. package/dist/core/codex-lb/combined-catalog/contracts.js +5 -0
  57. package/dist/core/codex-lb/combined-catalog/normalize.js +170 -0
  58. package/dist/core/codex-lb/combined-catalog/persistence.js +207 -0
  59. package/dist/core/codex-lb/combined-catalog/shared.js +12 -0
  60. package/dist/core/codex-lb/combined-catalog/storage.js +171 -0
  61. package/dist/core/codex-lb/combined-catalog.js +12 -0
  62. package/dist/core/codex-lb/desktop-bridge/client.js +4 -1
  63. package/dist/core/codex-lb/desktop-bridge/header-policy.js +48 -63
  64. package/dist/core/codex-lb/desktop-bridge/http-forward.js +115 -83
  65. package/dist/core/codex-lb/desktop-bridge/launchd.js +20 -13
  66. package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +4 -1
  67. package/dist/core/codex-lb/desktop-bridge/security.js +381 -267
  68. package/dist/core/codex-lb/desktop-bridge/server.js +148 -19
  69. package/dist/core/codex-lb/desktop-bridge/state.js +56 -70
  70. package/dist/core/codex-lb/desktop-bridge/types.js +6 -1
  71. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +281 -106
  72. package/dist/core/codex-lb/desktop-bridge-migration/historical-config.js +245 -0
  73. package/dist/core/codex-lb/desktop-bridge-migration/historical-toml.js +56 -0
  74. package/dist/core/codex-lb/desktop-bridge-migration/metadata.js +73 -0
  75. package/dist/core/codex-lb/desktop-bridge-migration/receipt.js +52 -0
  76. package/dist/core/codex-lb/desktop-bridge-migration/retired-runtime-cleanup.js +106 -0
  77. package/dist/core/codex-lb/desktop-bridge-migration/types.js +1 -0
  78. package/dist/core/codex-lb/desktop-bridge-migration.js +238 -0
  79. package/dist/core/codex-lb/desktop-controller-v3/catalog.js +257 -0
  80. package/dist/core/codex-lb/desktop-controller-v3/diagnostics.js +62 -0
  81. package/dist/core/codex-lb/desktop-controller-v3/lifecycle-commands.js +203 -0
  82. package/dist/core/codex-lb/desktop-controller-v3/live-probes.js +293 -0
  83. package/dist/core/codex-lb/desktop-controller-v3/preflight-probes.js +144 -0
  84. package/dist/core/codex-lb/desktop-controller-v3/provider-commands.js +182 -0
  85. package/dist/core/codex-lb/desktop-controller-v3/shared.js +279 -0
  86. package/dist/core/codex-lb/desktop-controller-v3/status.js +269 -0
  87. package/dist/core/codex-lb/desktop-controller-v3/types.js +1 -0
  88. package/dist/core/codex-lb/desktop-controller-v3/verification.js +89 -0
  89. package/dist/core/codex-lb/desktop-controller-v3.js +67 -0
  90. package/dist/core/codex-lb/desktop-controller.js +2 -1730
  91. package/dist/core/codex-lb/desktop-service.js +462 -627
  92. package/dist/core/codex-lb/migration-receipt.js +560 -118
  93. package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +37 -53
  94. package/dist/core/codex-lb/probes/bridge-probe.js +125 -64
  95. package/dist/core/codex-lb/probes/catalog-probe.js +36 -136
  96. package/dist/core/codex-lb/probes/computer-use-probe.js +63 -39
  97. package/dist/core/codex-lb/probes/image-generation-probe.js +98 -41
  98. package/dist/core/codex-lb/probes/probe-evidence.js +32 -33
  99. package/dist/core/codex-lb/probes/voice-realtime-probe.js +69 -43
  100. package/dist/core/codex-lb/provider-credentials/configuration.js +127 -0
  101. package/dist/core/codex-lb/provider-credentials/locks.js +11 -0
  102. package/dist/core/codex-lb/provider-credentials/private-snapshot.js +28 -0
  103. package/dist/core/codex-lb/provider-credentials/removal.js +33 -0
  104. package/dist/core/codex-lb/provider-credentials/resolution.js +59 -0
  105. package/dist/core/codex-lb/provider-credentials/runtime.js +55 -0
  106. package/dist/core/codex-lb/provider-credentials/types.js +1 -0
  107. package/dist/core/codex-lb/provider-credentials/validation-store.js +137 -0
  108. package/dist/core/codex-lb/provider-credentials.js +5 -0
  109. package/dist/core/codex-lb/provider-registry.js +323 -0
  110. package/dist/core/codex-lb/provider-route-policy.js +118 -0
  111. package/dist/core/codex-lb/request-route-resolver.js +172 -0
  112. package/dist/core/codex-lb/route-index.js +148 -0
  113. package/dist/core/codex-lb/trusted-deep-evidence.js +158 -286
  114. package/dist/core/commands/basic-cli.js +1 -1
  115. package/dist/core/commands/check-command.js +3 -10
  116. package/dist/core/commands/gate-result-contract.js +10 -14
  117. package/dist/core/commands/intent-normalization/normalizer.js +1 -1
  118. package/dist/core/commands/mad-sks-command.js +2 -6
  119. package/dist/core/commands/release-command.js +11 -1
  120. package/dist/core/commands/telegram-command.js +46 -6
  121. package/dist/core/doctor/doctor-readiness-matrix.js +9 -7
  122. package/dist/core/doctor/skill-legacy-surface.js +5 -5
  123. package/dist/core/evidence/v2/evidence-key.js +30 -3
  124. package/dist/core/feature-fixtures.js +8 -1
  125. package/dist/core/feature-registry.js +3 -2
  126. package/dist/core/hooks-runtime/stop-finalization.js +11 -1
  127. package/dist/core/hooks-runtime/subagent-context.js +15 -1
  128. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +1 -1
  129. package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
  130. package/dist/core/hooks-runtime.js +73 -87
  131. package/dist/core/image-ux-review/imagegen-adapter.js +108 -94
  132. package/dist/core/image-ux-review/real-callout-extractor.js +144 -14
  133. package/dist/core/imagegen/desktop-bridge-imagegen-target.js +77 -0
  134. package/dist/core/imagegen/imagegen-capability.js +43 -151
  135. package/dist/core/init/skills/filesystem.js +89 -0
  136. package/dist/core/init/skills/inventory.js +97 -0
  137. package/dist/core/init/skills/manifest.js +151 -0
  138. package/dist/core/init/skills.js +5 -325
  139. package/dist/core/init.js +0 -63
  140. package/dist/core/install/installed-package-smoke.js +1 -1
  141. package/dist/core/managed-assets/managed-assets-manifest.js +0 -1
  142. package/dist/core/policy/latest-version-guidance.js +15 -2
  143. package/dist/core/preflight/parallel-preflight-engine.js +27 -51
  144. package/dist/core/provider/provider-badge.js +9 -4
  145. package/dist/core/provider/provider-context.js +57 -107
  146. package/dist/core/providers/openrouter/openrouter-account.js +3 -1
  147. package/dist/core/providers/openrouter/openrouter-secret-store.js +91 -22
  148. package/dist/core/release/desktop-bridge-release-evidence.js +457 -0
  149. package/dist/core/release/gate-manifest.js +0 -1
  150. package/dist/core/release/main-push-guard.js +13 -0
  151. package/dist/core/release/main-push-receipt.js +11 -0
  152. package/dist/core/release/physical-release-gates.js +664 -61
  153. package/dist/core/release/publish-preflight.js +3 -3
  154. package/dist/core/release/release-gate-batch-runner.js +19 -6
  155. package/dist/core/release/release-gate-dag.js +33 -6
  156. package/dist/core/release/release-gate-node.js +1 -3
  157. package/dist/core/release/release-gate-output-contract.js +55 -0
  158. package/dist/core/release/release-pack-contract.js +1 -1
  159. package/dist/core/release/release-pack-receipt.js +209 -8
  160. package/dist/core/release/release-real-contract.js +1 -1
  161. package/dist/core/release/stage-publish.js +106 -28
  162. package/dist/core/retention/temp-lease.js +204 -0
  163. package/dist/core/retention.js +18 -195
  164. package/dist/core/routes.js +1 -2
  165. package/dist/core/safety/intent-contract/intent-contract.js +3 -3
  166. package/dist/core/subagents/naruto-host-credentials.js +6 -1
  167. package/dist/core/subagents/official-subagent-config.js +27 -9
  168. package/dist/core/subagents/official-subagent-runner.js +14 -31
  169. package/dist/core/subagents/wave-lifecycle.js +36 -8
  170. package/dist/core/subagents/wave-parent-guidance.js +2 -1
  171. package/dist/core/telegram/doctor.js +2 -2
  172. package/dist/core/telegram/liveness.js +10 -4
  173. package/dist/core/triwiki/context-graph/compiler/index.js +18 -18
  174. package/dist/core/update/update-migration-state/fast-mode-config.js +172 -0
  175. package/dist/core/update/update-migration-state/session-state-split.js +247 -0
  176. package/dist/core/update/update-migration-state/simple-stages.js +46 -0
  177. package/dist/core/update/update-migration-state.js +4 -481
  178. package/dist/core/version.js +1 -1
  179. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +28 -4
  180. package/dist/native/sks-menubar/Sources/OperationModels.swift +112 -2
  181. package/dist/native/sks-menubar/Sources/ProviderRouteExplanation.swift +21 -0
  182. package/dist/native/sks-menubar/Sources/ProvidersBridgeCatalog.swift +140 -0
  183. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +107 -470
  184. package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +27 -197
  185. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +335 -269
  186. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +233 -437
  187. package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +16 -7
  188. package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +39 -9
  189. package/dist/native/sks-menubar/Sources/TelegramSupport.swift +56 -0
  190. package/dist/scripts/canonical-test-runner.js +7 -1
  191. package/dist/scripts/check-runtime-schemas.js +7 -2
  192. package/dist/scripts/codex-sdk-real-smoke-check.js +3 -1
  193. package/dist/scripts/desktop-bridge-capabilities-check.js +123 -0
  194. package/dist/scripts/{codex-lb-desktop-bridge-latency-check.js → desktop-bridge-latency-check.js} +61 -16
  195. package/dist/scripts/desktop-bridge-real-evidence-check.js +64 -0
  196. package/dist/scripts/{codex-lb-desktop-bridge-check.js → desktop-bridge-transport-check.js} +92 -155
  197. package/dist/scripts/desktop-bridge-transport-client.js +116 -0
  198. package/dist/scripts/desktop-bridge-unification-check.js +276 -0
  199. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +12 -8
  200. package/dist/scripts/gate-policy-audit-check.js +52 -2
  201. package/dist/scripts/provider-badge-context-check.js +55 -12
  202. package/dist/scripts/publish-preflight.js +1 -2
  203. package/dist/scripts/release-affected-selector-check.js +1 -2
  204. package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
  205. package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
  206. package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -0
  207. package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
  208. package/dist/scripts/release-gate-batch-runner-check.js +9 -0
  209. package/dist/scripts/release-gate-dag-runner-check.js +6 -0
  210. package/dist/scripts/release-gate-dag-runner.js +4 -2
  211. package/dist/scripts/release-metadata-check.js +16 -3
  212. package/dist/scripts/release-pack-receipt.js +29 -6
  213. package/dist/scripts/release-physical-gates-check.js +39 -0
  214. package/dist/scripts/release-real-check.js +7 -5
  215. package/package.json +6 -8
  216. package/release-gates.v2.json +156 -157
  217. package/runtime-required-scripts.json +11 -11
  218. package/schemas/codex/desktop-bridge-status-v3.schema.json +286 -0
  219. package/schemas/codex/desktop-capabilities-v3.schema.json +198 -0
  220. package/schemas/release/release-gate-node.schema.json +2 -3
  221. package/dist/cli/codex-lb-setup-warning-output.js +0 -17
  222. package/dist/cli/install-helpers-codex-lb-chain.js +0 -529
  223. package/dist/commands/codex-lb.js +0 -1232
  224. package/dist/core/architecture-hardening/migration/migration.js +0 -111
  225. package/dist/core/codex-app/auxiliary-oauth-policy.js +0 -36
  226. package/dist/core/codex-app/catalog-compat/catalog-service.js +0 -104
  227. package/dist/core/codex-app/child-policy/child-policy.js +0 -35
  228. package/dist/core/codex-app/desktop-routing-snapshot.js +0 -233
  229. package/dist/core/codex-app/glm-model-profile.js +0 -1
  230. package/dist/core/codex-app/glm-profile-installer.js +0 -191
  231. package/dist/core/codex-app/glm-profile-schema.js +0 -42
  232. package/dist/core/codex-app/multi-provider-router.js +0 -391
  233. package/dist/core/codex-app/openrouter-activate.js +0 -405
  234. package/dist/core/codex-app/openrouter-model-catalog.js +0 -217
  235. package/dist/core/codex-app/provider-child-policy.js +0 -64
  236. package/dist/core/codex-app/provider-mode.js +0 -91
  237. package/dist/core/codex-app/provider-session-policy.js +0 -85
  238. package/dist/core/codex-app/session-policy/session-pinning.js +0 -68
  239. package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -319
  240. package/dist/core/codex-lb/codex-lb-setup.js +0 -293
  241. package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -456
  242. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +0 -290
  243. package/dist/core/codex-lb/desktop-center-credentials.js +0 -1083
  244. package/dist/core/codex-lb/desktop-mode.js +0 -32
  245. package/dist/core/codex-lb/desktop-real-evidence.js +0 -168
  246. package/dist/core/codex-lb/legacy-migration.js +0 -576
  247. package/dist/core/codex-lb/native-openai-transport/transport.js +0 -68
  248. package/dist/core/codex-lb/provider-routing/provider-router.js +0 -58
  249. package/dist/core/codex-lb/routing-truth.js +0 -327
  250. package/dist/core/imagegen/codex-lb-imagegen-target.js +0 -92
  251. package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +0 -118
  252. package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +0 -17
  253. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +0 -331
  254. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +0 -260
  255. package/dist/scripts/codex-lb-catalog-passthrough-check.js +0 -120
  256. package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +0 -169
  257. package/dist/scripts/codex-lb-desktop-capabilities-check.js +0 -287
  258. package/dist/scripts/codex-lb-desktop-real-evidence-check.js +0 -123
  259. package/dist/scripts/codex-lb-fast-mode-truth-check.js +0 -114
  260. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +0 -152
  261. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +0 -231
@@ -2,7 +2,7 @@ import { flag, readOption } from '../cli/args.js';
2
2
  import { printJson } from '../cli/output.js';
3
3
  import { codexAccessTokenStatus, codexAppIntegrationStatus, codexChromeExtensionStatus, codexProductDesignPluginStatus, formatCodexAppStatus, formatCodexProductDesignPluginStatus } from '../core/codex-app.js';
4
4
  import { codexAppRemoteControlCommand } from '../cli/codex-app-command.js';
5
- import { readStdin, sksRoot } from '../core/fsx.js';
5
+ import { sksRoot } from '../core/fsx.js';
6
6
  import { buildCodexAppHarnessMatrix } from '../core/codex-app/codex-app-harness-matrix.js';
7
7
  import { syncCodexSksSkills } from '../core/codex-app/codex-skill-sync.js';
8
8
  import { syncCodexAgentRoles } from '../core/codex-app/codex-agent-role-sync.js';
@@ -10,14 +10,8 @@ import { runCodexInitDeep } from '../core/codex-app/codex-init-deep.js';
10
10
  import { buildCodexHookLifecycle } from '../core/codex-app/codex-hook-lifecycle.js';
11
11
  import { resolveCodexAppExecutionProfile } from '../core/codex-app/codex-app-execution-profile.js';
12
12
  import { repairCodexNativeManagedAssets } from '../core/codex-native/codex-native-repair-transaction.js';
13
- import { doctorCodexAppGlmProfile, installCodexAppGlmProfile } from '../core/codex-app/glm-profile-installer.js';
14
- import { openRouterStatus, restoreDesktopRoutingSnapshot, useOpenRouter } from '../core/codex-app/openrouter-activate.js';
15
- import { promptForOpenRouterKeyHidden, writeStoredOpenRouterKey } from '../core/providers/openrouter/openrouter-secret-store.js';
16
- import { compactOpenRouterModelsResult, listOpenRouterModels, testOpenRouterConnection } from '../core/providers/openrouter/openrouter-account.js';
17
13
  import { restartCodexApp } from '../core/codex-app/codex-app-restart.js';
18
- import { MULTI_PROVIDER_ROUTER_DEFAULT_BASE_URL, multiProviderRouterStatus, testMultiProviderRouter, useMultiProviderRouter } from '../core/codex-app/multi-provider-router.js';
19
14
  import { resetRoleModelPreference, roleModelPreferencesStatus, setRoleModelPreference } from '../core/subagents/role-model-preferences.js';
20
- import { codexLbDesktopStatusV2 } from '../core/codex-lb/desktop-controller.js';
21
15
  export async function run(_command, args = []) {
22
16
  const action = args[0] || 'check';
23
17
  if (action === 'restart')
@@ -38,96 +32,6 @@ export async function run(_command, args = []) {
38
32
  return printCodexAppResult(args, await buildCodexHookLifecycle({ root: await sksRoot(), apply: flag(args, '--apply') || flag(args, '--fix') }));
39
33
  if (action === 'execution-profile')
40
34
  return printCodexAppResult(args, await resolveCodexAppExecutionProfile({ root: await sksRoot() }));
41
- if (action === 'glm-profile') {
42
- const subcommand = args[1] || 'doctor';
43
- const root = await sksRoot();
44
- const result = subcommand === 'install' || subcommand === 'repair' || subcommand === 'remove'
45
- ? await installCodexAppGlmProfile({ root, apply: true })
46
- : await doctorCodexAppGlmProfile({ root });
47
- return printCodexAppResult(args, result);
48
- }
49
- if (action === 'set-openrouter-key' || action === 'openrouter-key') {
50
- const root = await sksRoot();
51
- const key = await readOpenRouterKeyFromArgs(args.slice(1));
52
- if (!key) {
53
- const result = { schema: 'sks.codex-app-openrouter-key.v1', ok: false, status: 'missing_key', blockers: ['openrouter_key_missing'], warnings: [] };
54
- return printCodexAppResult(args, result);
55
- }
56
- const record = await writeStoredOpenRouterKey(key);
57
- const profile = await installCodexAppGlmProfile({ root, apply: true });
58
- const restart = await restartCodexApp({ enabled: flag(args, '--restart-app') || flag(args, '--restart') });
59
- const result = {
60
- schema: 'sks.codex-app-openrouter-key.v1',
61
- ok: Boolean(profile.ok && restart.ok),
62
- status: !profile.ok ? 'stored_profile_blocked' : restart.ok ? 'stored' : 'stored_restart_blocked',
63
- key_preview: record.key_preview,
64
- raw_key_recorded: false,
65
- secret_store: 'sks-openrouter-secret-store',
66
- selected: false,
67
- glm_profile: profile,
68
- restart_app: restart,
69
- blockers: [...(profile.blockers || []), ...(restart.blockers || [])],
70
- warnings: profile.warnings || []
71
- };
72
- return printCodexAppResult(args, result);
73
- }
74
- if (action === 'use-openrouter' || action === 'use-or') {
75
- const root = await sksRoot();
76
- const model = readOption(args, '--model', '');
77
- const result = await useOpenRouter({
78
- root,
79
- model,
80
- restartApp: flag(args, '--restart-app') || flag(args, '--restart') || !flag(args, '--no-restart-app'),
81
- preserveThreadSidebar: !flag(args, '--no-preserve-thread-sidebar')
82
- });
83
- return printCodexAppResult(args, result);
84
- }
85
- if (action === 'restore-desktop-routing' || action === 'restore-previous-provider') {
86
- const result = await restoreDesktopRoutingSnapshot({
87
- restartApp: flag(args, '--restart-app') || flag(args, '--restart') || !flag(args, '--no-restart-app'),
88
- restartImpl: restartCodexApp
89
- });
90
- return printCodexAppResult(args, result);
91
- }
92
- if (action === 'openrouter-status') {
93
- const result = await openRouterStatus({});
94
- return printCodexAppResult(args, result);
95
- }
96
- if (action === 'openrouter-models') {
97
- const models = await listOpenRouterModels({});
98
- const result = flag(args, '--ids-only') ? compactOpenRouterModelsResult(models) : models;
99
- return printCodexAppResult(args, result);
100
- }
101
- if (action === 'openrouter-test') {
102
- const result = await testOpenRouterConnection({ model: readOption(args, '--model', '') });
103
- return printCodexAppResult(args, result);
104
- }
105
- if (action === 'router-status' || action === 'multi-provider-status' || action === 'opencodex-status') {
106
- const result = await multiProviderRouterStatus({
107
- baseUrl: readOption(args, '--base-url', ''),
108
- catalogPath: readOption(args, '--catalog', '')
109
- });
110
- return printCodexAppResult(args, result);
111
- }
112
- if (action === 'router-test' || action === 'multi-provider-test' || action === 'opencodex-test') {
113
- const result = await testMultiProviderRouter({
114
- baseUrl: readOption(args, '--base-url', MULTI_PROVIDER_ROUTER_DEFAULT_BASE_URL),
115
- catalogPath: readOption(args, '--catalog', ''),
116
- model: readOption(args, '--model', '')
117
- });
118
- return printCodexAppResult(args, result);
119
- }
120
- if (action === 'use-router' || action === 'use-multi-provider' || action === 'use-opencodex') {
121
- const result = await useMultiProviderRouter({
122
- model: readOption(args, '--model', ''),
123
- baseUrl: readOption(args, '--base-url', MULTI_PROVIDER_ROUTER_DEFAULT_BASE_URL),
124
- catalogPath: readOption(args, '--catalog', ''),
125
- replaceCatalog: flag(args, '--replace-catalog'),
126
- forceRoutingOverride: flag(args, '--force-routing-override'),
127
- restartApp: flag(args, '--restart-app') || flag(args, '--restart') || !flag(args, '--no-restart-app')
128
- });
129
- return printCodexAppResult(args, result);
130
- }
131
35
  if (action === 'role-models') {
132
36
  return printCodexAppResult(args, await roleModelPreferencesStatus());
133
37
  }
@@ -190,7 +94,7 @@ export async function run(_command, args = []) {
190
94
  return;
191
95
  }
192
96
  if (action === 'check' || action === 'status') {
193
- const status = await codexAppStatusWithCodexLbCapabilities({
97
+ const status = await codexAppStatusWithDesktopBridgeCapabilities({
194
98
  autoInstallProductDesign: flag(args, '--install-product-design') || flag(args, '--auto-install-product-design')
195
99
  });
196
100
  if (flag(args, '--json')) {
@@ -204,38 +108,58 @@ export async function run(_command, args = []) {
204
108
  process.exitCode = 1;
205
109
  return;
206
110
  }
207
- console.error('Usage: sks codex-app check|status|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|set-openrouter-key [--api-key-stdin]|use-openrouter --model <id>|restore-desktop-routing|openrouter-status|openrouter-models [--ids-only]|openrouter-test [--model <id>]|router-status [--base-url <loopback-url>] [--catalog <path>]|router-test --model <provider/model> [--base-url <loopback-url>] [--catalog <path>]|use-router --model <provider/model> [--base-url <loopback-url>] [--catalog <path>] [--replace-catalog] [--force-routing-override]|role-models|set-role-model --role <name> [--provider <id>] --model <catalog-slug> --reasoning <effort>|reset-role-model --role <name>|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
208
- console.error('Note: glm-profile is retired (strips leftover Desktop GLM profiles); use set-openrouter-key / use-openrouter.');
111
+ console.error('Usage: sks codex-app check|status|restart|harness-matrix|skill-sync|agent-role-sync|init-deep|hook-lifecycle|execution-profile|role-models|set-role-model --role <name> [--provider <id>] --model <catalog-slug> --reasoning <effort>|reset-role-model --role <name>|product-design [--check-only]|ensure-product-design|chrome-extension|pat status|remote-control [--json]');
112
+ console.error('Provider routing moved to: sks bridge provider configure|validate|enable; sks bridge catalog sync; sks bridge route set-default.');
209
113
  process.exitCode = 1;
210
114
  }
211
- export async function codexAppStatusWithCodexLbCapabilities(opts = {}) {
212
- const { codexAppStatusImpl = codexAppIntegrationStatus, codexLbStatusImpl = codexLbDesktopStatusV2, codexLbStatusOptions, ...integrationOptions } = opts;
213
- let codexLbCapabilityReport;
115
+ export async function codexAppStatusWithDesktopBridgeCapabilities(opts = {}) {
116
+ const { codexAppStatusImpl = codexAppIntegrationStatus, desktopBridgeStatusImpl = currentDesktopBridgeStatus, desktopBridgeStatusOptions, ...integrationOptions } = opts;
117
+ let desktopBridgeStatus = null;
118
+ let desktopBridgeCapabilityReport;
214
119
  try {
215
- const status = await codexLbStatusImpl(codexLbStatusOptions || {});
120
+ const status = await desktopBridgeStatusImpl(desktopBridgeStatusOptions || {});
121
+ desktopBridgeStatus = status;
122
+ const statusRecord = status;
216
123
  const capabilities = status?.capabilities;
217
- codexLbCapabilityReport = capabilities && typeof capabilities === 'object' && !Array.isArray(capabilities)
124
+ const report = capabilities && typeof capabilities === 'object' && !Array.isArray(capabilities)
125
+ ? capabilities
126
+ : null;
127
+ const summary = report?.summary && typeof report.summary === 'object' && !Array.isArray(report.summary)
128
+ ? report.summary
129
+ : null;
130
+ desktopBridgeCapabilityReport = report
218
131
  ? {
219
- ...capabilities,
132
+ ...report,
220
133
  availability: 'reported',
221
- mode: status.mode || null,
222
- overall: status.overall || capabilities.state || 'available_unverified',
223
- full_capability_verified: status.full_capability_verified === true,
224
- deep_evidence_validation: status.deep_evidence_validation || null
134
+ runtime: status.management && typeof status.management === 'object'
135
+ ? status.management.runtime || null
136
+ : null,
137
+ overall: summary
138
+ ? summary.level_satisfied === true ? 'verified' : 'available_unverified'
139
+ : statusRecord.overall || report.state || 'available_unverified',
140
+ full_capability_verified: summary
141
+ ? summary.full_feature_verified === true
142
+ : statusRecord.full_capability_verified === true,
143
+ deep_evidence_validation: statusRecord.deep_evidence_validation || null
225
144
  }
226
- : unavailableCodexLbCapabilityReport('codex_lb_capability_report_missing');
145
+ : unavailableDesktopBridgeCapabilityReport('desktop_bridge_capability_report_missing');
227
146
  }
228
147
  catch {
229
- codexLbCapabilityReport = unavailableCodexLbCapabilityReport('codex_lb_capability_report_unavailable');
148
+ desktopBridgeCapabilityReport = unavailableDesktopBridgeCapabilityReport('desktop_bridge_capability_report_unavailable');
230
149
  }
231
150
  return codexAppStatusImpl({
232
151
  ...integrationOptions,
233
- codexLbCapabilityReport
152
+ desktopBridgeStatus,
153
+ desktopBridgeCapabilityReport
234
154
  });
235
155
  }
236
- function unavailableCodexLbCapabilityReport(blocker) {
156
+ async function currentDesktopBridgeStatus(options) {
157
+ const controller = await import('../core/codex-lb/desktop-controller.js');
158
+ return controller.desktopBridgeStatusV3(options);
159
+ }
160
+ function unavailableDesktopBridgeCapabilityReport(blocker) {
237
161
  return {
238
- schema: 'sks.codex-lb-desktop-capability-status.v2',
162
+ schema: 'sks.desktop-bridge-capability-status.v3',
239
163
  availability: 'unavailable',
240
164
  ready: false,
241
165
  state: 'available_unverified',
@@ -243,14 +167,6 @@ function unavailableCodexLbCapabilityReport(blocker) {
243
167
  blockers: [blocker]
244
168
  };
245
169
  }
246
- async function readOpenRouterKeyFromArgs(args = []) {
247
- const key = readOption(args, '--api-key', readOption(args, '--key', ''));
248
- if (key)
249
- return String(key).trim();
250
- if (flag(args, '--api-key-stdin') || flag(args, '--key-stdin'))
251
- return String(await readStdin()).trim();
252
- return await promptForOpenRouterKeyHidden() || '';
253
- }
254
170
  function printCodexAppResult(args = [], result) {
255
171
  if (flag(args, '--json')) {
256
172
  printJson(result);
@@ -0,0 +1,380 @@
1
+ import { flag } from '../cli/args.js';
2
+ import { projectRoot, exists, nowIso } from '../core/fsx.js';
3
+ import { normalizeInstallScope } from '../core/init.js';
4
+ import { appendMigrationEvents, hashConfigText } from '../core/migration/migration-transaction-journal.js';
5
+ import { inspectSksMenuBarStatus, sksMenuBarPaths, sksMenuBarRestartDeferred } from '../core/codex-app/menubar/index.js';
6
+ import { restartLaunchAgent } from '../core/codex-app/menubar/launch-agent.js';
7
+ export function buildRuntimeReadiness(matrix) {
8
+ const defaults = matrix?.invocation_defaults || {};
9
+ const hookPolicy = defaults.hook_evidence_policy || 'unknown-do-not-count';
10
+ const agentStrategy = defaults.loop_worker_role_strategy || 'message-role';
11
+ const multiAgentMode = defaults.multi_agent_mode || 'none';
12
+ const rolloutBudget = defaults.rollout_budget_strategy || 'sks-local-only';
13
+ const researchSource = defaults.research_source_strategy || 'local-files';
14
+ const codexNative = matrix?.ok === true ? 'ok' : matrix?.codex_cli?.available ? 'degraded' : 'blocked';
15
+ const repairActions = [];
16
+ if (codexNative !== 'ok') {
17
+ repairActions.push([
18
+ 'Codex Native managed assets: sks doctor',
19
+ '--fix',
20
+ '--repair-codex-native',
21
+ '--yes'
22
+ ].join(' '));
23
+ }
24
+ if (matrix?.features?.project_memory?.ok !== true)
25
+ repairActions.push('Project memory: sks codex-native init-deep --apply --directory-local');
26
+ return {
27
+ schema: 'sks.runtime-readiness-story.v1',
28
+ codex_native: codexNative,
29
+ loop_mesh: agentStrategy === 'agent_type' ? 'ok' : 'fallback',
30
+ qa_visual: defaults.qa_visual_review_strategy || 'blocked',
31
+ research_sources: researchSource,
32
+ image_followup: defaults.image_followup_strategy || 'blocked',
33
+ hook_evidence_policy: hookPolicy,
34
+ agent_role_strategy: agentStrategy,
35
+ multi_agent_mode: multiAgentMode,
36
+ rollout_budget_strategy: rolloutBudget,
37
+ current_time_source: defaults.current_time_source || 'external-clock',
38
+ overload_retry_policy: defaults.overload_retry_policy || 'generic',
39
+ notes: [
40
+ ...(hookPolicy !== 'approved-only' ? ['hook-derived evidence will not count'] : []),
41
+ ...(agentStrategy !== 'agent_type' ? ['message-role fallback active'] : []),
42
+ ...(multiAgentMode === 'proactive' ? ['Proactive multi-agent mode is available for Naruto-style routes'] : []),
43
+ ...(rolloutBudget === 'codex-current-shared' ? ['Shared rollout budgeting is available for route proof'] : []),
44
+ ...(researchSource === 'indexed-web-search' ? ['Indexed web search is selected for source-intelligence routes'] : [])
45
+ ],
46
+ repair_actions: [...new Set(repairActions)]
47
+ };
48
+ }
49
+ export function deferredNativeRepair(schema, doctorFix, nextActions) {
50
+ return {
51
+ schema,
52
+ generated_at: nowIso(),
53
+ ok: true,
54
+ skipped: true,
55
+ status: 'deferred_to_explicit_native_capability_probe',
56
+ attempted: false,
57
+ apply: doctorFix,
58
+ recovered: false,
59
+ blockers: [],
60
+ next_actions: nextActions,
61
+ manual_actions: nextActions
62
+ };
63
+ }
64
+ export function fallbackCodexNativeFeatureMatrix(codex, blockers = [], warnings = []) {
65
+ return {
66
+ schema: 'sks.codex-native-feature-matrix.v1',
67
+ ok: blockers.length === 0,
68
+ skipped: blockers.length === 0,
69
+ codex_cli: { available: Boolean(codex?.bin || codex?.available), version: codex?.version || null, bin: codex?.bin || null },
70
+ features: {},
71
+ invocation_defaults: {
72
+ loop_worker_role_strategy: 'message-role',
73
+ multi_agent_mode: 'none',
74
+ rollout_budget_strategy: 'sks-local-only',
75
+ qa_visual_review_strategy: 'route-gated',
76
+ research_source_strategy: 'local-files',
77
+ image_followup_strategy: 'artifact-path',
78
+ hook_evidence_policy: 'unknown-do-not-count',
79
+ skill_bridge_strategy: 'cli-only',
80
+ current_time_source: 'external-clock',
81
+ overload_retry_policy: 'generic'
82
+ },
83
+ blockers,
84
+ warnings
85
+ };
86
+ }
87
+ export async function writeJsonReportFile(file, value) {
88
+ const fsp = await import('node:fs/promises');
89
+ const path = await import('node:path');
90
+ await fsp.mkdir(path.dirname(file), { recursive: true });
91
+ await fsp.writeFile(file, `${JSON.stringify(value, null, 2)}\n`, 'utf8');
92
+ }
93
+ export function nativeCapabilityStatus(rows, id, fallback) {
94
+ const row = rows.find((entry) => entry?.id === id);
95
+ if (!row)
96
+ return fallback;
97
+ if (row.after === 'verified' || row.before === 'verified')
98
+ return 'verified';
99
+ if (id === 'image_path_exposure') {
100
+ if (row.before === 'degraded' || row.after === 'degraded' || row.repairability === 'doctor-fix')
101
+ return 'fallback';
102
+ return fallback;
103
+ }
104
+ if (id === 'app_handoff')
105
+ return 'unavailable';
106
+ if (row.repairability === 'manual-required')
107
+ return 'manual_required';
108
+ if (row.before === 'degraded' || row.after === 'degraded')
109
+ return 'degraded';
110
+ if (row.repairability === 'doctor-fix')
111
+ return row.after === 'blocked' ? 'blocked' : 'repair_required';
112
+ if (row.repairability === 'unavailable')
113
+ return 'unavailable';
114
+ return fallback;
115
+ }
116
+ export function uniqueNativeManualActions(rows) {
117
+ return [...new Set(rows
118
+ .filter((row) => row?.repairability === 'manual-required' && row?.after !== 'verified')
119
+ .flatMap((row) => Array.isArray(row.repair_actions) ? row.repair_actions : [])
120
+ .filter((action) => typeof action === 'string' && action.trim()))];
121
+ }
122
+ export function doctorSkillStatus(coreSkills) {
123
+ if (!coreSkills)
124
+ return 'drift_detected';
125
+ if (Array.isArray(coreSkills.restored) && coreSkills.restored.length)
126
+ return 'repaired';
127
+ if (Array.isArray(coreSkills.blockers) && coreSkills.blockers.length)
128
+ return 'drift_detected';
129
+ return 'current';
130
+ }
131
+ export function doctorDedupeStatus(skillDedupe) {
132
+ if (!skillDedupe)
133
+ return 'manual_required';
134
+ if (Array.isArray(skillDedupe.actions) && skillDedupe.actions.some((action) => action.action === 'quarantined'))
135
+ return 'repaired';
136
+ if (Array.isArray(skillDedupe.blockers) && skillDedupe.blockers.length)
137
+ return 'manual_required';
138
+ return 'none';
139
+ }
140
+ async function codexHomeConfigPath() {
141
+ const path = await import('node:path');
142
+ const os = await import('node:os');
143
+ const home = process.env.CODEX_HOME || path.join(process.env.HOME || os.homedir(), '.codex');
144
+ return path.join(home, 'config.toml');
145
+ }
146
+ export async function captureCodexConfigSnapshot() {
147
+ const fsp = await import('node:fs/promises');
148
+ const path = await import('node:path');
149
+ const read = async (p) => {
150
+ if (!p)
151
+ return null;
152
+ try {
153
+ return await fsp.readFile(p, 'utf8');
154
+ }
155
+ catch {
156
+ return null;
157
+ }
158
+ };
159
+ const root = await projectRoot();
160
+ const projectPath = root ? path.join(root, '.codex', 'config.toml') : null;
161
+ const homePath = await codexHomeConfigPath();
162
+ return {
163
+ project_path: projectPath,
164
+ project_text: await read(projectPath),
165
+ home_path: homePath,
166
+ home_text: await read(homePath)
167
+ };
168
+ }
169
+ export async function writeFixMigrationJournal(root, preFix, configRepair, setupRepair) {
170
+ if (!preFix)
171
+ return null;
172
+ const fsp = await import('node:fs/promises');
173
+ const read = async (p) => {
174
+ if (!p)
175
+ return null;
176
+ try {
177
+ return await fsp.readFile(p, 'utf8');
178
+ }
179
+ catch {
180
+ return null;
181
+ }
182
+ };
183
+ const projectAfter = await read(preFix.project_path);
184
+ const homeAfter = await read(preFix.home_path);
185
+ const structureRepairs = Array.isArray(configRepair?.structure_repairs) ? configRepair.structure_repairs : [];
186
+ const projectStructure = structureRepairs.find((repair) => repair.scope === 'project');
187
+ const homeStructure = structureRepairs.find((repair) => repair.scope === 'codex_home');
188
+ const events = [
189
+ {
190
+ step: 'doctor_fix_project_config',
191
+ target: preFix.project_path || '.codex/config.toml',
192
+ beforeHash: preFix.project_text != null ? hashConfigText(preFix.project_text) : null,
193
+ afterHash: projectAfter != null ? hashConfigText(projectAfter) : null,
194
+ backupPath: setupRepair?.config_backup_path || projectStructure?.backup_path || configRepair?.policy?.backup_path || null
195
+ },
196
+ {
197
+ step: 'doctor_fix_codex_home_config',
198
+ target: preFix.home_path || '~/.codex/config.toml',
199
+ beforeHash: preFix.home_text != null ? hashConfigText(preFix.home_text) : null,
200
+ afterHash: homeAfter != null ? hashConfigText(homeAfter) : null,
201
+ backupPath: homeStructure?.backup_path || null
202
+ }
203
+ ].filter((event) => event.beforeHash != null || event.afterHash != null);
204
+ if (!events.length)
205
+ return null;
206
+ return appendMigrationEvents(root, events);
207
+ }
208
+ async function backupProjectConfigBeforeFix() {
209
+ try {
210
+ const fsp = await import('node:fs/promises');
211
+ const path = await import('node:path');
212
+ const root = await projectRoot();
213
+ if (!root)
214
+ return null;
215
+ const configPath = path.join(root, '.codex', 'config.toml');
216
+ if (!(await exists(configPath)))
217
+ return null;
218
+ const text = await fsp.readFile(configPath, 'utf8');
219
+ const backupPath = `${configPath}.doctor-pre-fix-${Date.now().toString(36)}.bak`;
220
+ await fsp.writeFile(backupPath, text);
221
+ return backupPath;
222
+ }
223
+ catch {
224
+ return null;
225
+ }
226
+ }
227
+ export function installScopeFromArgs(args = []) {
228
+ if (flag(args, '--project'))
229
+ return 'project';
230
+ if (flag(args, '--global'))
231
+ return 'global';
232
+ const index = args.indexOf('--install-scope');
233
+ return normalizeInstallScope(index >= 0 && args[index + 1] ? args[index + 1] : 'global');
234
+ }
235
+ export function isMigrationUserOwnedProjectConfigBlocker(blocker) {
236
+ const value = String(blocker || '').trim();
237
+ return value === 'user_owned_file_without_sks_marker'
238
+ || value.endsWith(':user_owned_file_without_sks_marker')
239
+ || value === 'config_write_guard:blocked_unmanaged_project_config'
240
+ || value.endsWith(':config_write_guard:blocked_unmanaged_project_config');
241
+ }
242
+ export function readOption(args = [], name, fallback = null) {
243
+ const index = args.indexOf(name);
244
+ return index >= 0 && args[index + 1] ? args[index + 1] : fallback;
245
+ }
246
+ export function buildCodexAppUiDiagnosticFailure(apply, error) {
247
+ return {
248
+ schema: 'sks.codex-app-fast-ui-repair.v1',
249
+ ok: false,
250
+ apply,
251
+ safe_auto_apply: false,
252
+ requires_confirmation: true,
253
+ fast_selector: 'manual_action_required',
254
+ provider_selector: 'manual_action_required',
255
+ host_owned_config: 'diagnostic_failed',
256
+ next_action: 'Review Codex App UI config manually.',
257
+ actions: [],
258
+ blockers: [error instanceof Error ? error.message : String(error)]
259
+ };
260
+ }
261
+ export function formatCodexDoctorConsoleStatus(report) {
262
+ if (!report || report.available !== true)
263
+ return 'unavailable';
264
+ return report.disposition || (report.exit_code === 0 ? 'pass' : 'warn');
265
+ }
266
+ export function sksMenuBarRunningVersionConsoleLines(status) {
267
+ const runningVersion = status?.running_process?.package_version
268
+ || status?.menubar_version_probe?.running_version
269
+ || null;
270
+ const runningPid = status?.running_process?.pid ?? status?.menubar_version_probe?.pid ?? null;
271
+ if (typeof runningVersion !== 'string' || !runningVersion || !Number.isInteger(runningPid) || runningPid <= 0) {
272
+ return [];
273
+ }
274
+ const expectedVersion = status?.menubar_version_probe?.expected_version
275
+ || status?.action_target?.expected_version
276
+ || status?.package_version
277
+ || null;
278
+ const installedVersion = status?.installed_version || status?.build_stamp?.package_version || null;
279
+ return [
280
+ ` RUNNING: version ${runningVersion} (PID ${runningPid})`,
281
+ ...(typeof expectedVersion === 'string' && expectedVersion && expectedVersion !== runningVersion
282
+ ? [` expected: version ${expectedVersion}`]
283
+ : []),
284
+ ...(typeof installedVersion === 'string' && installedVersion && installedVersion !== runningVersion
285
+ ? [` installed: version ${installedVersion}`]
286
+ : [])
287
+ ];
288
+ }
289
+ export async function rebootstrapSksMenuBarLaunchdForDoctorFix(input, deps = {}) {
290
+ const env = input.env || process.env;
291
+ const status = input.status;
292
+ const expectedVersion = status?.menubar_version_probe?.expected_version
293
+ || status?.action_target?.expected_version
294
+ || status?.installed_version
295
+ || null;
296
+ const warningOnlyVerifiedProcess = input.fix
297
+ && !sksMenuBarRestartDeferred(env)
298
+ && status?.launchd?.checked === true
299
+ && status?.launchd?.ok === false
300
+ && Array.isArray(status?.warnings)
301
+ && status.warnings.includes('launchd_not_running_process_active')
302
+ && !(Array.isArray(status?.blockers) && status.blockers.includes('launchd_not_running'))
303
+ && status?.running_process?.ok === true
304
+ && typeof expectedVersion === 'string'
305
+ && status.running_process.package_version === expectedVersion;
306
+ if (!warningOnlyVerifiedProcess) {
307
+ return { attempted: false, ok: true, status, restart: null };
308
+ }
309
+ const paths = sksMenuBarPaths(input.home || env.HOME, input.root);
310
+ const restartImpl = deps.restartLaunchAgentImpl || restartLaunchAgent;
311
+ const inspectImpl = deps.inspectSksMenuBarStatusImpl || inspectSksMenuBarStatus;
312
+ const restart = await restartImpl(paths, env).catch((error) => ({
313
+ ok: false,
314
+ error: error instanceof Error ? error.message : String(error)
315
+ }));
316
+ if (restart?.ok !== true) {
317
+ const detail = restart?.error ? `:${restart.error}` : '';
318
+ return {
319
+ attempted: true,
320
+ ok: false,
321
+ restart,
322
+ status: {
323
+ ...status,
324
+ ok: false,
325
+ blockers: [...new Set([...(status?.blockers || []), `launchd_rebootstrap_failed${detail}`])]
326
+ }
327
+ };
328
+ }
329
+ const refreshed = await inspectImpl({
330
+ root: input.root,
331
+ ...(input.home ? { home: input.home } : {}),
332
+ ...(input.env ? { env: input.env } : {})
333
+ }).catch((error) => ({
334
+ ...status,
335
+ ok: false,
336
+ blockers: [...new Set([
337
+ ...(status?.blockers || []),
338
+ `launchd_rebootstrap_status_failed:${error instanceof Error ? error.message : String(error)}`
339
+ ])]
340
+ }));
341
+ if (refreshed?.launchd?.checked !== true || refreshed?.launchd?.ok !== true) {
342
+ return {
343
+ attempted: true,
344
+ ok: false,
345
+ restart,
346
+ status: {
347
+ ...refreshed,
348
+ ok: false,
349
+ blockers: [...new Set([...(refreshed?.blockers || []), 'launchd_rebootstrap_not_confirmed'])]
350
+ }
351
+ };
352
+ }
353
+ return { attempted: true, ok: true, status: refreshed, restart };
354
+ }
355
+ export function mergeObservedCodexStartupWarnings(startupRepair, codexDoctor) {
356
+ const text = `${codexDoctor?.stdout_tail || ''}\n${codexDoctor?.stderr_tail || ''}`;
357
+ const manual = new Set(Array.isArray(startupRepair?.manual_actions) ? startupRepair.manual_actions : []);
358
+ const warnings = new Set(Array.isArray(startupRepair?.warnings) ? startupRepair.warnings : []);
359
+ const blockers = new Set(Array.isArray(startupRepair?.blockers) ? startupRepair.blockers : []);
360
+ if (/codex_apps[\s\S]{0,500}token_expired|token_expired[\s\S]{0,500}codex_apps/i.test(text)) {
361
+ manual.add('Codex Apps MCP token is expired; sign in to Codex App/CLI again so the connector can mint a fresh token.');
362
+ warnings.add('codex_apps_token_expired_observed');
363
+ blockers.add('codex_apps_token_expired_manual_reauth_required');
364
+ }
365
+ if (/SUPABASE_ACCESS_TOKEN[\s\S]{0,500}mcp server ['"`]?supabase['"`]?|mcp server ['"`]?supabase['"`]?[\s\S]{0,500}SUPABASE_ACCESS_TOKEN/i.test(text)) {
366
+ manual.add('Supabase MCP uses SUPABASE_ACCESS_TOKEN but the variable is unset; export the token or migrate that server to a read-only remote URL.');
367
+ warnings.add('supabase_access_token_missing_observed');
368
+ blockers.add('supabase_access_token_missing_manual_auth_required');
369
+ }
370
+ if (/node_repl[\s\S]{0,500}No such file or directory|No such file or directory[\s\S]{0,500}node_repl/i.test(text)) {
371
+ warnings.add('node_repl_missing_command_observed');
372
+ }
373
+ return {
374
+ ...startupRepair,
375
+ ok: blockers.size === 0 && startupRepair?.ok !== false,
376
+ manual_actions: [...manual],
377
+ warnings: [...warnings],
378
+ blockers: [...blockers]
379
+ };
380
+ }
@@ -48,6 +48,9 @@ export function doctorPhaseIdsForProfile(profile) {
48
48
  return ['setup', ...required, ...optional];
49
49
  return [...required, ...optional];
50
50
  }
51
+ export function doctorProfileRequiresDesktopBridgeReadiness(profile) {
52
+ return profile !== 'migration';
53
+ }
51
54
  function unknownDoctorFlags(args) {
52
55
  const knownBoolean = new Set([
53
56
  '--fix', '--yes', '-y', '--machine-only', '--actual-codex', '--require-actual-codex',