sneakoscope 7.3.0 → 7.6.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 (283) hide show
  1. package/README.md +129 -10
  2. package/crates/sks-core/Cargo.lock +1 -1
  3. package/crates/sks-core/Cargo.toml +1 -1
  4. package/dist/cli/codex-app-command.js +1 -1
  5. package/dist/cli/command-manifest-lite.js +4 -1
  6. package/dist/cli/command-registry.js +2 -0
  7. package/dist/cli/install-helpers-codex-lb-chain.js +42 -0
  8. package/dist/cli/install-helpers-codex-lb-config.js +114 -9
  9. package/dist/cli/install-helpers-install-support.js +6 -16
  10. package/dist/cli/install-helpers.js +788 -600
  11. package/dist/cli/router.js +30 -2
  12. package/dist/commands/codex-app.js +37 -1
  13. package/dist/commands/codex-lb.js +491 -300
  14. package/dist/config/skills-manifest.json +57 -71
  15. package/dist/core/align/align-route.js +127 -0
  16. package/dist/core/codex-app/codex-app-fast-ui-repair.js +8 -4
  17. package/dist/core/codex-app/codex-app-restart.js +83 -0
  18. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +8 -4
  19. package/dist/core/codex-app/desktop-routing-snapshot.js +1 -1
  20. package/dist/core/codex-app/menubar/constants.js +5 -0
  21. package/dist/core/codex-app/menubar/generation-transaction-journal.js +1 -3
  22. package/dist/core/codex-app/menubar/installer.js +18 -0
  23. package/dist/core/codex-app/multi-provider-router.js +22 -10
  24. package/dist/core/codex-app/openrouter-activate.js +26 -1
  25. package/dist/core/codex-app.js +118 -26
  26. package/dist/core/codex-control/codex-app-server-runtime-env.js +86 -0
  27. package/dist/core/codex-control/codex-app-server-v2-client.js +78 -8
  28. package/dist/core/codex-control/codex-task-runner.js +2 -2
  29. package/dist/core/codex-lb/capability-runner.js +204 -0
  30. package/dist/core/codex-lb/capability-types.js +1 -0
  31. package/dist/core/codex-lb/codex-lb-env.js +9 -13
  32. package/dist/core/codex-lb/codex-lb-setup.js +45 -8
  33. package/dist/core/codex-lb/codex-lb-tool-catalog.js +52 -74
  34. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
  35. package/dist/core/codex-lb/desktop-auth-invariant.js +185 -0
  36. package/dist/core/codex-lb/desktop-bridge/client.js +34 -0
  37. package/dist/core/codex-lb/desktop-bridge/header-policy.js +106 -0
  38. package/dist/core/codex-lb/desktop-bridge/http-forward.js +101 -0
  39. package/dist/core/codex-lb/desktop-bridge/index.js +10 -0
  40. package/dist/core/codex-lb/desktop-bridge/launchd.js +81 -0
  41. package/dist/core/codex-lb/desktop-bridge/location-rewrite.js +27 -0
  42. package/dist/core/codex-lb/desktop-bridge/security.js +274 -0
  43. package/dist/core/codex-lb/desktop-bridge/server.js +179 -0
  44. package/dist/core/codex-lb/desktop-bridge/state.js +119 -0
  45. package/dist/core/codex-lb/desktop-bridge/types.js +16 -0
  46. package/dist/core/codex-lb/desktop-bridge/websocket-forward.js +151 -0
  47. package/dist/core/codex-lb/desktop-center-credentials.js +189 -0
  48. package/dist/core/codex-lb/desktop-controller.js +1410 -0
  49. package/dist/core/codex-lb/desktop-mode.js +32 -0
  50. package/dist/core/codex-lb/desktop-real-evidence.js +168 -0
  51. package/dist/core/codex-lb/desktop-service.js +613 -0
  52. package/dist/core/codex-lb/legacy-migration.js +575 -0
  53. package/dist/core/codex-lb/migration-receipt.js +246 -0
  54. package/dist/core/codex-lb/probes/auxiliary-surfaces-probe.js +60 -0
  55. package/dist/core/codex-lb/probes/bridge-probe.js +75 -0
  56. package/dist/core/codex-lb/probes/catalog-probe.js +128 -0
  57. package/dist/core/codex-lb/probes/computer-use-probe.js +50 -0
  58. package/dist/core/codex-lb/probes/image-generation-probe.js +47 -0
  59. package/dist/core/codex-lb/probes/probe-evidence.js +39 -0
  60. package/dist/core/codex-lb/probes/voice-realtime-probe.js +44 -0
  61. package/dist/core/codex-lb/trusted-deep-evidence.js +403 -0
  62. package/dist/core/codex-native/core-skill-manifest.js +22 -6
  63. package/dist/core/codex-runtime/codex-desktop-config-policy.js +2 -1
  64. package/dist/core/commands/align-command.js +220 -0
  65. package/dist/core/commands/image-ux-review-command.js +280 -68
  66. package/dist/core/commands/naruto-command.js +257 -8
  67. package/dist/core/commands/ppt-command.js +2 -2
  68. package/dist/core/commands/telegram-command.js +402 -34
  69. package/dist/core/commands/triwiki-command.js +11 -1
  70. package/dist/core/commands/triwiki-graph-command.js +160 -0
  71. package/dist/core/commands/wiki-command.js +100 -20
  72. package/dist/core/doctor/skill-legacy-surface.js +1 -3
  73. package/dist/core/errors/message.js +3 -0
  74. package/dist/core/evidence/evidence-freshness.js +14 -0
  75. package/dist/core/feature-fixtures.js +9 -1
  76. package/dist/core/feature-registry.js +5 -3
  77. package/dist/core/fsx.js +7 -3
  78. package/dist/core/hooks-runtime/codex-commit-hooks-selftest.js +82 -0
  79. package/dist/core/hooks-runtime/context-graph-freshness-preflight.js +113 -0
  80. package/dist/core/hooks-runtime/hook-context.js +15 -2
  81. package/dist/core/hooks-runtime/managed-skill-generation-heal.js +46 -0
  82. package/dist/core/hooks-runtime/naruto-terminal-finalization.js +1 -0
  83. package/dist/core/hooks-runtime/official-subagent-lifecycle.js +1 -1
  84. package/dist/core/hooks-runtime/tool-output-quarantine.js +1 -1
  85. package/dist/core/hooks-runtime.js +33 -89
  86. package/dist/core/image-ux-review/callout-extraction.js +6 -0
  87. package/dist/core/image-ux-review/imagegen-adapter.js +64 -23
  88. package/dist/core/image-ux-review/real-callout-extractor.js +1 -0
  89. package/dist/core/image-ux-review.js +230 -12
  90. package/dist/core/imagegen/codex-lb-imagegen-target.js +21 -7
  91. package/dist/core/imagegen/imagegen-capability.js +10 -4
  92. package/dist/core/imagegen/require-imagegen.js +29 -5
  93. package/dist/core/init/skills.js +25 -13
  94. package/dist/core/init.js +1 -1
  95. package/dist/core/install/installed-package-smoke.js +157 -4
  96. package/dist/core/managed-assets/managed-assets-manifest.js +2 -1
  97. package/dist/core/managed-path-safety.js +8 -10
  98. package/dist/core/mcp-config/backup.js +2 -4
  99. package/dist/core/mcp-config/config-reader.js +2 -4
  100. package/dist/core/mcp-config/scope.js +3 -5
  101. package/dist/core/naruto/context-graph-advisor-scope.js +242 -0
  102. package/dist/core/naruto/context-graph-advisor.js +0 -0
  103. package/dist/core/perf/release-latency-slo.js +12 -6
  104. package/dist/core/pipeline-internals/runtime-core.js +78 -0
  105. package/dist/core/pipeline-internals/runtime-gates.js +5 -2
  106. package/dist/core/policy/latest-version-guidance.js +113 -0
  107. package/dist/core/ppt.js +8 -8
  108. package/dist/core/preflight/parallel-preflight-engine.js +1 -1
  109. package/dist/core/proof/auto-finalize.js +98 -6
  110. package/dist/core/proof/route-proof-gate.js +12 -1
  111. package/dist/core/proof/route-proof-policy.js +8 -8
  112. package/dist/core/release/gate-manifest.js +32 -1
  113. package/dist/core/release/npm-stage-contract.js +21 -0
  114. package/dist/core/release/package-size-budget.js +2 -2
  115. package/dist/core/release/release-gate-contract.js +5 -0
  116. package/dist/core/release/release-proof-io.js +1 -3
  117. package/dist/core/release/release-real-contract.js +5 -4
  118. package/dist/core/release/release-stamp-proof.js +1 -3
  119. package/dist/core/release/stage-publish.js +27 -0
  120. package/dist/core/remote/audit-idempotency.js +50 -18
  121. package/dist/core/remote/codex-public-activity.js +283 -0
  122. package/dist/core/remote/index.js +1 -0
  123. package/dist/core/remote/ssh-worker-client.js +4 -1
  124. package/dist/core/remote/worker.js +206 -27
  125. package/dist/core/research/research-adversarial-review.js +1 -3
  126. package/dist/core/research/research-claim-synthesizer.js +1 -3
  127. package/dist/core/research/research-falsification-runner.js +1 -3
  128. package/dist/core/research/research-source-evidence.js +1 -3
  129. package/dist/core/responses-stream.js +65 -19
  130. package/dist/core/routes/constants.js +1 -1
  131. package/dist/core/routes/design-policy.js +7 -2
  132. package/dist/core/routes/dollar-manifest-lite.js +2 -4
  133. package/dist/core/routes/evidence.js +1 -1
  134. package/dist/core/routes.js +30 -10
  135. package/dist/core/safety/command-contract/contracts.js +2 -0
  136. package/dist/core/safety/command-contract/types.js +1 -1
  137. package/dist/core/search/context-graph-seeds.js +205 -0
  138. package/dist/core/search/context.js +0 -0
  139. package/dist/core/search/provider.js +2 -2
  140. package/dist/core/secret-redaction.js +6 -0
  141. package/dist/core/subagents/naruto-help-contract.js +2 -1
  142. package/dist/core/subagents/naruto-host-credentials.js +161 -0
  143. package/dist/core/subagents/official-subagent-preparation.js +4 -1
  144. package/dist/core/subagents/official-subagent-prompt.js +44 -2
  145. package/dist/core/subagents/official-subagent-runner.js +26 -8
  146. package/dist/core/subagents/triwiki-attention.js +135 -123
  147. package/dist/core/telegram/bot-api.js +85 -10
  148. package/dist/core/telegram/center-snapshot.js +718 -0
  149. package/dist/core/telegram/config.js +158 -31
  150. package/dist/core/telegram/hub.js +288 -33
  151. package/dist/core/telegram/index.js +2 -0
  152. package/dist/core/telegram/ingress-spool.js +419 -0
  153. package/dist/core/telegram/ledgers.js +188 -29
  154. package/dist/core/telegram/messages.js +26 -6
  155. package/dist/core/telegram/owner-lock.js +10 -7
  156. package/dist/core/telegram/runtime-projection.js +38 -3
  157. package/dist/core/telegram/runtime.js +298 -63
  158. package/dist/core/telegram/service.js +137 -8
  159. package/dist/core/telegram/setup.js +291 -73
  160. package/dist/core/text/strings.js +3 -0
  161. package/dist/core/triwiki/code-pack.js +12 -120
  162. package/dist/core/triwiki/context-graph/compiler/cache-key.js +277 -0
  163. package/dist/core/triwiki/context-graph/compiler/extract.js +104 -0
  164. package/dist/core/triwiki/context-graph/compiler/freshness.js +108 -0
  165. package/dist/core/triwiki/context-graph/compiler/index.js +237 -0
  166. package/dist/core/triwiki/context-graph/compiler/merge.js +0 -0
  167. package/dist/core/triwiki/context-graph/compiler/serialize.js +115 -0
  168. package/dist/core/triwiki/context-graph/contracts.js +236 -0
  169. package/dist/core/triwiki/context-graph/extractors/code/builders.js +150 -0
  170. package/dist/core/triwiki/context-graph/extractors/code/declarations.js +161 -0
  171. package/dist/core/triwiki/context-graph/extractors/code/index.js +265 -0
  172. package/dist/core/triwiki/context-graph/extractors/code/inventory.js +237 -0
  173. package/dist/core/triwiki/context-graph/extractors/code/module-graph.js +252 -0
  174. package/dist/core/triwiki/context-graph/extractors/code/modules.js +79 -0
  175. package/dist/core/triwiki/context-graph/extractors/code/references.js +184 -0
  176. package/dist/core/triwiki/context-graph/extractors/code/selection.js +100 -0
  177. package/dist/core/triwiki/context-graph/extractors/code/ts-config.js +161 -0
  178. package/dist/core/triwiki/context-graph/extractors/code/types.js +18 -0
  179. package/dist/core/triwiki/context-graph/extractors/evidence/claims.js +289 -0
  180. package/dist/core/triwiki/context-graph/extractors/evidence/index.js +54 -0
  181. package/dist/core/triwiki/context-graph/extractors/evidence/proof-index.js +213 -0
  182. package/dist/core/triwiki/context-graph/extractors/evidence/proofs.js +266 -0
  183. package/dist/core/triwiki/context-graph/extractors/evidence/redaction.js +177 -0
  184. package/dist/core/triwiki/context-graph/extractors/evidence/shared.js +0 -0
  185. package/dist/core/triwiki/context-graph/extractors/evidence/sources.js +154 -0
  186. package/dist/core/triwiki/context-graph/extractors/index.js +7 -0
  187. package/dist/core/triwiki/context-graph/extractors/topology/commands.js +207 -0
  188. package/dist/core/triwiki/context-graph/extractors/topology/gate-edges.js +201 -0
  189. package/dist/core/triwiki/context-graph/extractors/topology/gates.js +182 -0
  190. package/dist/core/triwiki/context-graph/extractors/topology/globs.js +124 -0
  191. package/dist/core/triwiki/context-graph/extractors/topology/index.js +92 -0
  192. package/dist/core/triwiki/context-graph/extractors/topology/routes.js +135 -0
  193. package/dist/core/triwiki/context-graph/extractors/topology/shared.js +215 -0
  194. package/dist/core/triwiki/context-graph/graph-index.js +143 -0
  195. package/dist/core/triwiki/context-graph/ids.js +0 -0
  196. package/dist/core/triwiki/context-graph/lint/index.js +0 -0
  197. package/dist/core/triwiki/context-graph/lint/rules.js +232 -0
  198. package/dist/core/triwiki/context-graph/lint/warnings.js +93 -0
  199. package/dist/core/triwiki/context-graph/paths.js +116 -0
  200. package/dist/core/triwiki/context-graph/profiles.js +78 -0
  201. package/dist/core/triwiki/context-graph/projections/anchors.js +91 -0
  202. package/dist/core/triwiki/context-graph/projections/attention.js +58 -0
  203. package/dist/core/triwiki/context-graph/projections/code-pack-workspace.js +62 -0
  204. package/dist/core/triwiki/context-graph/projections/code-pack.js +144 -0
  205. package/dist/core/triwiki/context-graph/projections/index.js +7 -0
  206. package/dist/core/triwiki/context-graph/projections/module-view.js +140 -0
  207. package/dist/core/triwiki/context-graph/projections/node-summary.js +118 -0
  208. package/dist/core/triwiki/context-graph/projections/pack-contract.js +6 -0
  209. package/dist/core/triwiki/context-graph/query/explain.js +0 -0
  210. package/dist/core/triwiki/context-graph/query/index.js +178 -0
  211. package/dist/core/triwiki/context-graph/query/load.js +116 -0
  212. package/dist/core/triwiki/context-graph/query/pack.js +117 -0
  213. package/dist/core/triwiki/context-graph/query/rank.js +142 -0
  214. package/dist/core/triwiki/context-graph/query/ranking-config.js +64 -0
  215. package/dist/core/triwiki/context-graph/query/seeds.js +241 -0
  216. package/dist/core/triwiki/context-graph/query/snapshot-cache.js +72 -0
  217. package/dist/core/triwiki/context-graph/query/traverse.js +154 -0
  218. package/dist/core/triwiki/context-graph/query-types.js +29 -0
  219. package/dist/core/triwiki/context-graph/store/compile-lock.js +21 -0
  220. package/dist/core/triwiki/context-graph/store/event-log.js +48 -0
  221. package/dist/core/triwiki/context-graph/store/fragment-cache.js +85 -0
  222. package/dist/core/triwiki/context-graph/store/graph-status.js +85 -0
  223. package/dist/core/triwiki/context-graph/store/snapshot-store.js +155 -0
  224. package/dist/core/triwiki/triwiki-proof-bank-index-repair.js +115 -0
  225. package/dist/core/triwiki/triwiki-proof-bank-index-store.js +290 -0
  226. package/dist/core/triwiki/triwiki-proof-bank-index.js +126 -0
  227. package/dist/core/triwiki/triwiki-proof-bank.js +7 -1
  228. package/dist/core/verification/context-graph-affected.js +271 -0
  229. package/dist/core/version.js +1 -1
  230. package/dist/native/sks-menubar/Sources/AlertFactory.swift +11 -3
  231. package/dist/native/sks-menubar/Sources/AppDelegate.swift +9 -0
  232. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +25 -3
  233. package/dist/native/sks-menubar/Sources/ControlKit.swift +19 -8
  234. package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +1 -2
  235. package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +45 -17
  236. package/dist/native/sks-menubar/Sources/OverviewSummary.swift +162 -0
  237. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +136 -190
  238. package/dist/native/sks-menubar/Sources/ProcessClient.swift +107 -11
  239. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +5 -1
  240. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +16 -4
  241. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +4 -1
  242. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +131 -0
  243. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +288 -341
  244. package/dist/native/sks-menubar/Sources/RemoteTelegramCenterState.swift +447 -0
  245. package/dist/native/sks-menubar/Sources/RemoteTelegramRendering.swift +484 -0
  246. package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +364 -115
  247. package/dist/native/sks-menubar/Sources/SettingsViewController.swift +73 -12
  248. package/dist/native/sks-menubar/Sources/SidebarItem.swift +3 -3
  249. package/dist/native/sks-menubar/Sources/StatusItemController.swift +13 -13
  250. package/dist/native/sks-menubar/Sources/TelegramHubSupervisor.swift +469 -0
  251. package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +1 -6
  252. package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +12 -0
  253. package/dist/native/sks-menubar/Tests/NativeTelegramRegressionRunner.swift +55 -0
  254. package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +33 -0
  255. package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +142 -0
  256. package/dist/native/sks-menubar/Tests/RemoteTelegramCenterStateTests.swift +56 -0
  257. package/dist/native/sks-menubar/Tests/TelegramHubSupervisorTests.swift +55 -0
  258. package/dist/scripts/codex-lb-catalog-passthrough-check.js +120 -0
  259. package/dist/scripts/codex-lb-desktop-auth-invariant-check.js +169 -0
  260. package/dist/scripts/codex-lb-desktop-bridge-check.js +394 -0
  261. package/dist/scripts/codex-lb-desktop-bridge-latency-check.js +196 -0
  262. package/dist/scripts/codex-lb-desktop-capabilities-check.js +287 -0
  263. package/dist/scripts/codex-lb-desktop-real-evidence-check.js +123 -0
  264. package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
  265. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +81 -40
  266. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +99 -37
  267. package/dist/scripts/context-graph-check.js +191 -0
  268. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +1 -1
  269. package/dist/scripts/gate-policy-audit-check.js +1 -1
  270. package/dist/scripts/helper-dedup-check.js +0 -2
  271. package/dist/scripts/installed-package-smoke-check.js +4 -1
  272. package/dist/scripts/latest-version-guidance-check.js +74 -0
  273. package/dist/scripts/release-metadata-check.js +21 -4
  274. package/dist/scripts/release-real-check.js +7 -0
  275. package/dist/scripts/ux-review-imagegen-blackbox-check.js +25 -1
  276. package/dist/scripts/ux-review-run-wires-imagegen-check.js +9 -1
  277. package/package.json +8 -3
  278. package/release-gates.v2.json +176 -1
  279. package/runtime-required-scripts.json +30 -0
  280. package/schemas/triwiki/context-graph.schema.json +119 -0
  281. package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -112
  282. package/dist/cli/install-helpers-codex-lb-selftest.js +0 -481
  283. package/dist/core/triwiki/code-index-scanner.js +0 -309
@@ -1,17 +1,24 @@
1
1
  import Cocoa
2
2
 
3
3
  final class SettingsViewController: NSViewController, ControlCenterPage {
4
+ private enum ConfigReadResult {
5
+ case loaded([String: Any])
6
+ case missing
7
+ case unreadable
8
+ case malformed
9
+ }
10
+
4
11
  private let notifications: NotificationCoordinator
5
12
  private let quitWithCodex = NSButton(checkboxWithTitle: "Quit SKS Menu when Codex quits", target: nil, action: nil)
6
13
  private let status = NativeView.detail("Settings use the native app configuration file.")
14
+ private var notificationButton: NSButton!
7
15
  init(notifications: NotificationCoordinator) { self.notifications = notifications; super.init(nibName: nil, bundle: nil) }
8
16
  required init?(coder: NSCoder) { nil }
9
17
 
10
18
  override func loadView() {
11
19
  quitWithCodex.target = self; quitWithCodex.action = #selector(save)
12
- quitWithCodex.state = readConfig()["quit_with_codex"] as? Bool == true ? .on : .off
13
20
  quitWithCodex.setAccessibilityLabel("Quit SKS Menu when Codex quits")
14
- let authorize = NativeView.button("Enable Notifications", target: self, action: #selector(enableNotifications))
21
+ notificationButton = NativeView.button("Enable Notifications", target: self, action: #selector(enableNotifications))
15
22
  let lifecycleCard = NativeView.card(
16
23
  title: "Codex lifecycle",
17
24
  subtitle: "Off keeps the menu icon available on cold start and hides it only after a Codex session ends.",
@@ -20,33 +27,76 @@ final class SettingsViewController: NSViewController, ControlCenterPage {
20
27
  let notificationsCard = NativeView.card(
21
28
  title: "Notifications",
22
29
  subtitle: "Operation results always stay available in Control Center, even when notifications are denied.",
23
- views: [NativeView.row([authorize]), status]
30
+ views: [NativeView.row([notificationButton]), status]
24
31
  )
25
32
  view = NativeView.page([
26
33
  ControlKit.header("Settings", "These options stay on this Mac. Notification permission and Codex lifecycle behavior never leave the machine."),
27
34
  lifecycleCard, notificationsCard
28
35
  ])
29
- refreshOnAppear()
30
36
  }
31
37
 
32
38
  func refreshOnAppear() {
33
- quitWithCodex.state = readConfig()["quit_with_codex"] as? Bool == true ? .on : .off
39
+ let configResult = readConfig()
40
+ switch configResult {
41
+ case .loaded(let config):
42
+ quitWithCodex.isEnabled = true
43
+ quitWithCodex.state = config["quit_with_codex"] as? Bool == true ? .on : .off
44
+ case .missing:
45
+ quitWithCodex.isEnabled = true
46
+ quitWithCodex.state = .off
47
+ case .unreadable, .malformed:
48
+ quitWithCodex.isEnabled = false
49
+ }
34
50
  if notifications.authorizationDenied {
35
- status.stringValue = "Notifications are denied in macOS Settings. Operation results still appear in Control Center."
36
- } else if FileManager.default.fileExists(atPath: AppRuntime.configPath) {
37
- status.stringValue = "Settings loaded from the native app configuration file."
51
+ notificationButton.title = "Open Notification Settings…"
52
+ notificationButton.setAccessibilityLabel("Open macOS Notification Settings")
53
+ status.stringValue = "Notifications are blocked by macOS. Open System Settings, select SKS, and allow notifications. Operation results still appear in Control Center."
38
54
  } else {
55
+ notificationButton.title = "Enable Notifications"
56
+ notificationButton.setAccessibilityLabel("Enable Notifications")
57
+ switch configResult {
58
+ case .loaded:
59
+ status.stringValue = "Settings loaded from the native app configuration file."
60
+ case .missing:
39
61
  status.stringValue = "No settings file yet. Changing an option creates one with owner-only permissions."
62
+ case .unreadable:
63
+ status.stringValue = "The settings file exists but cannot be read. No option can be changed until file access is restored."
64
+ case .malformed:
65
+ status.stringValue = "The settings file is malformed. No option can be changed or overwritten; repair it, then reopen Settings."
66
+ }
40
67
  }
41
68
  }
42
69
 
43
70
  @objc private func enableNotifications() {
71
+ if notifications.authorizationDenied {
72
+ guard openSystemSettings() else {
73
+ status.stringValue = "System Settings could not be opened. Open it manually, then choose Notifications → SKS."
74
+ return
75
+ }
76
+ status.stringValue = "System Settings opened. Choose Notifications → SKS and allow notifications."
77
+ return
78
+ }
44
79
  notifications.requestAuthorizationFromSettings()
45
80
  status.stringValue = "Notification authorization was requested from macOS."
46
81
  }
47
82
 
48
83
  @objc private func save() {
49
- var config = readConfig()
84
+ let previous = readConfig()
85
+ var config: [String: Any]
86
+ switch previous {
87
+ case .loaded(let value):
88
+ config = value
89
+ case .missing:
90
+ config = [:]
91
+ case .unreadable:
92
+ quitWithCodex.isEnabled = false
93
+ status.stringValue = "Settings were not saved because the existing file cannot be read. No file was overwritten."
94
+ return
95
+ case .malformed:
96
+ quitWithCodex.isEnabled = false
97
+ status.stringValue = "Settings were not saved because the existing file is malformed. No file was overwritten."
98
+ return
99
+ }
50
100
  config["schema"] = "sks.sks-menubar-config.v1"
51
101
  config["codex_bundle_id"] = AppRuntime.codexBundleId as Any
52
102
  config["quit_with_codex"] = quitWithCodex.state == .on
@@ -75,8 +125,19 @@ final class SettingsViewController: NSViewController, ControlCenterPage {
75
125
  }
76
126
  }
77
127
 
78
- private func readConfig() -> [String: Any] {
79
- guard let data = FileManager.default.contents(atPath: AppRuntime.configPath) else { return [:] }
80
- return (try? JSONSerialization.jsonObject(with: data)) as? [String: Any] ?? [:]
128
+ private func readConfig() -> ConfigReadResult {
129
+ let manager = FileManager.default
130
+ guard manager.fileExists(atPath: AppRuntime.configPath) else { return .missing }
131
+ guard let data = manager.contents(atPath: AppRuntime.configPath) else { return .unreadable }
132
+ guard let object = try? JSONSerialization.jsonObject(with: data),
133
+ let config = object as? [String: Any] else { return .malformed }
134
+ return .loaded(config)
135
+ }
136
+
137
+ private func openSystemSettings() -> Bool {
138
+ guard let settings = NSWorkspace.shared.urlForApplication(withBundleIdentifier: "com.apple.systempreferences") else {
139
+ return false
140
+ }
141
+ return NSWorkspace.shared.open(settings)
81
142
  }
82
143
  }
@@ -1,13 +1,13 @@
1
1
  import Foundation
2
2
 
3
- // Ordered by expected use frequency: provider/model work first, then updates,
4
- // then integrations, then maintenance.
3
+ // Keep first-run connection setup near Overview, then provider/update work,
4
+ // integrations, and maintenance.
5
5
  enum SidebarItem: String, CaseIterable {
6
6
  case overview = "Overview"
7
+ case remoteTelegram = "Remote & Telegram"
7
8
  case providers = "Providers"
8
9
  case updates = "Updates"
9
10
  case mcpServers = "MCP Servers"
10
- case remoteTelegram = "Remote & Telegram"
11
11
  case diagnostics = "Diagnostics"
12
12
  case settings = "Settings"
13
13
 
@@ -12,7 +12,7 @@ final class StatusItemController: NSObject, NSMenuDelegate {
12
12
  private let statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.squareLength)
13
13
  private let statusLine = NSMenuItem(title: "Status: Starting", action: nil, keyEquivalent: "")
14
14
  private let pendingLine = NSMenuItem(title: "Pending approvals (0)", action: nil, keyEquivalent: "")
15
- private let fastLine = NSMenuItem(title: "Fast: Checking…", action: nil, keyEquivalent: "")
15
+ private let fastLine = NSMenuItem(title: "Codex Fast: Checking…", action: nil, keyEquivalent: "")
16
16
  private var fastOnItem: NSMenuItem?
17
17
  private var fastOffItem: NSMenuItem?
18
18
  private var timer: Timer?
@@ -47,7 +47,7 @@ final class StatusItemController: NSObject, NSMenuDelegate {
47
47
  statusLine.isEnabled = false
48
48
  pendingLine.isEnabled = false
49
49
  fastLine.isEnabled = false
50
- fastLine.setAccessibilityLabel("Current Fast mode state")
50
+ fastLine.setAccessibilityLabel("Current Codex Fast state")
51
51
  menu.addItem(version)
52
52
  menu.addItem(statusLine)
53
53
  menu.addItem(NSMenuItem.separator())
@@ -55,12 +55,12 @@ final class StatusItemController: NSObject, NSMenuDelegate {
55
55
  menu.addItem(pendingLine)
56
56
  menu.addItem(NSMenuItem.separator())
57
57
  menu.addItem(fastLine)
58
- let fastOn = item("Fast Mode On", #selector(fastOn))
59
- fastOn.setAccessibilityLabel("Turn Fast mode on")
58
+ let fastOn = item("Codex Fast On", #selector(fastOn))
59
+ fastOn.setAccessibilityLabel("Turn Codex Fast on")
60
60
  fastOnItem = fastOn
61
61
  menu.addItem(fastOn)
62
- let fastOff = item("Fast Mode Off", #selector(fastOff))
63
- fastOff.setAccessibilityLabel("Turn Fast mode off")
62
+ let fastOff = item("Codex Fast Off", #selector(fastOff))
63
+ fastOff.setAccessibilityLabel("Turn Codex Fast off")
64
64
  fastOffItem = fastOff
65
65
  menu.addItem(fastOff)
66
66
  menu.addItem(NSMenuItem.separator())
@@ -182,13 +182,13 @@ final class StatusItemController: NSObject, NSMenuDelegate {
182
182
  private func refreshFastState() {
183
183
  guard !fastRefreshInFlight else { fastRefreshPending = true; return }
184
184
  fastRefreshInFlight = true
185
- fastLine.title = "Fast: Checking…"
185
+ fastLine.title = "Codex Fast: Checking…"
186
186
  processClient.run(["fast-mode", "status", "--json"]) { [weak self] result in
187
187
  guard let self = self else { return }
188
188
  self.fastRefreshInFlight = false
189
189
  guard result.code == 0, let json = self.readJson(text: result.output),
190
190
  let global = json["global"] as? [String: Any], let on = global["on"] as? Bool else {
191
- self.fastLine.title = "Fast: Unavailable"
191
+ self.fastLine.title = "Codex Fast: Unavailable"
192
192
  self.fastOnItem?.state = .off
193
193
  self.fastOffItem?.state = .off
194
194
  self.fastOnItem?.isEnabled = true
@@ -197,7 +197,7 @@ final class StatusItemController: NSObject, NSMenuDelegate {
197
197
  return
198
198
  }
199
199
  let tier = global["service_tier"] as? String ?? (on ? "fast" : "default")
200
- self.fastLine.title = "Fast: \(on ? "On" : "Off") · \(tier)"
200
+ self.fastLine.title = "Codex Fast: \(on ? "On" : "Off") · service tier \(tier)"
201
201
  self.fastOnItem?.state = on ? .on : .off
202
202
  self.fastOffItem?.state = on ? .off : .on
203
203
  self.fastOnItem?.isEnabled = !on
@@ -332,16 +332,16 @@ final class StatusItemController: NSObject, NSMenuDelegate {
332
332
  }
333
333
  }
334
334
  @objc private func fastOn() {
335
- fastLine.title = "Fast: Turning On…"
335
+ fastLine.title = "Codex Fast: Turning On…"
336
336
  fastOnItem?.isEnabled = false
337
337
  fastOffItem?.isEnabled = false
338
- run(["fast-mode", "on", "--json"], kind: "fast-mode-on", mutationGroup: "codex-config", summary: "Turn Fast Mode on") { [weak self] in self?.refreshFastState() }
338
+ run(["fast-mode", "on", "--json"], kind: "fast-mode-on", mutationGroup: "codex-config", summary: "Turn Codex Fast on") { [weak self] in self?.refreshFastState() }
339
339
  }
340
340
  @objc private func fastOff() {
341
- fastLine.title = "Fast: Turning Off…"
341
+ fastLine.title = "Codex Fast: Turning Off…"
342
342
  fastOnItem?.isEnabled = false
343
343
  fastOffItem?.isEnabled = false
344
- run(["fast-mode", "off", "--json"], kind: "fast-mode-off", mutationGroup: "codex-config", summary: "Turn Fast Mode off") { [weak self] in self?.refreshFastState() }
344
+ run(["fast-mode", "off", "--json"], kind: "fast-mode-off", mutationGroup: "codex-config", summary: "Turn Codex Fast off") { [weak self] in self?.refreshFastState() }
345
345
  }
346
346
  @objc private func viewLastOperation() {
347
347
  if FileManager.default.fileExists(atPath: AppRuntime.lastActionLogPath) { NSWorkspace.shared.open(URL(fileURLWithPath: AppRuntime.lastActionLogPath)) }