sneakoscope 8.0.2 → 8.0.4

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 (376) hide show
  1. package/README.md +150 -37
  2. package/config/skills-hash-ledger.v1.json +1 -1
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/bin/fast-inline.js +55 -27
  6. package/dist/bin/install.js +6 -32
  7. package/dist/bin/sks-dispatch.js +1 -1
  8. package/dist/cli/args.js +0 -2
  9. package/dist/cli/cli-theme.js +18 -9
  10. package/dist/cli/command-manifest-lite.js +6 -6
  11. package/dist/cli/command-registry.js +6 -6
  12. package/dist/cli/feature-commands.js +9 -7
  13. package/dist/cli/install-helpers-codex-lb-chain.js +198 -7
  14. package/dist/cli/install-helpers-codex-lb-config.js +78 -10
  15. package/dist/cli/install-helpers-install-support.js +9 -6
  16. package/dist/cli/install-helpers.js +101 -49
  17. package/dist/cli/install-tool-helpers.js +2 -82
  18. package/dist/cli/output.js +6 -1
  19. package/dist/cli/router.js +101 -2
  20. package/dist/commands/codex-lb.js +119 -19
  21. package/dist/commands/doctor-profile.js +1 -1
  22. package/dist/commands/doctor.js +727 -144
  23. package/dist/commands/mad-sks.js +1 -5
  24. package/dist/config/skills-manifest.json +4 -2
  25. package/dist/core/agents/agent-codex-cockpit.js +0 -3
  26. package/dist/core/agents/agent-effort-policy.js +5 -5
  27. package/dist/core/agents/agent-janitor.js +0 -20
  28. package/dist/core/agents/agent-orchestrator.js +9 -56
  29. package/dist/core/agents/agent-output-validator.js +2 -3
  30. package/dist/core/agents/agent-patch-schema.js +2 -2
  31. package/dist/core/agents/agent-proof-evidence.js +0 -65
  32. package/dist/core/agents/agent-recursion-guard.js +1 -1
  33. package/dist/core/agents/agent-runner-codex-exec.js +5 -3
  34. package/dist/core/agents/agent-scheduler.js +327 -85
  35. package/dist/core/agents/agent-schema.js +1 -1
  36. package/dist/core/agents/agent-trust-report.js +0 -36
  37. package/dist/core/agents/agent-worker-pipeline.js +0 -1
  38. package/dist/core/agents/fast-mode-policy.js +1 -3
  39. package/dist/core/agents/native-cli-worker-runtime-proof.js +1 -1
  40. package/dist/core/agents/native-cli-worker-runtime.js +69 -647
  41. package/dist/core/agents/native-cli-worker.js +6 -7
  42. package/dist/core/agents/native-worker-backend-router.js +2 -32
  43. package/dist/core/agents/no-subagent-scaling-policy.js +1 -1
  44. package/dist/core/agents/parallel-runtime-proof.js +1 -6
  45. package/dist/core/agents/runtime-proof-summary.js +1 -35
  46. package/dist/core/architecture-hardening/contracts/contracts.js +193 -0
  47. package/dist/core/architecture-hardening/migration/migration.js +111 -0
  48. package/dist/core/architecture-hardening/state/state-service.js +155 -0
  49. package/dist/core/artifact-schemas.js +0 -3
  50. package/dist/core/codex/codex-config-guard.js +238 -52
  51. package/dist/core/codex-adapter.js +5 -3
  52. package/dist/core/codex-app/auxiliary-oauth-policy.js +36 -0
  53. package/dist/core/codex-app/catalog-compat/catalog-service.js +104 -0
  54. package/dist/core/codex-app/child-policy/child-policy.js +35 -0
  55. package/dist/core/codex-app/codex-app-handoff.js +0 -1
  56. package/dist/core/codex-app/codex-hook-lifecycle.js +1 -1
  57. package/dist/core/codex-app/codex-init-deep.js +1 -1
  58. package/dist/core/codex-app/menubar/app-bundle.js +2 -0
  59. package/dist/core/codex-app/menubar/constants.js +14 -1
  60. package/dist/core/codex-app/menubar/global-install.js +288 -0
  61. package/dist/core/codex-app/menubar/installer.js +79 -14
  62. package/dist/core/codex-app/menubar/launch-agent.js +267 -45
  63. package/dist/core/codex-app/menubar/paths.js +3 -0
  64. package/dist/core/codex-app/menubar/rollback.js +55 -7
  65. package/dist/core/codex-app/menubar/status.js +75 -4
  66. package/dist/core/codex-app/provider-child-policy.js +64 -0
  67. package/dist/core/codex-app/provider-mode.js +91 -0
  68. package/dist/core/codex-app/provider-operation-stages.js +20 -0
  69. package/dist/core/codex-app/provider-session-policy.js +85 -0
  70. package/dist/core/codex-app/session-policy/session-pinning.js +68 -0
  71. package/dist/core/codex-app.js +3 -2
  72. package/dist/core/codex-control/codex-0139-image-path-real-probe.js +3 -1
  73. package/dist/core/codex-control/codex-0139-web-search-probe.js +3 -1
  74. package/dist/core/codex-control/codex-app-server-runtime-env.js +13 -4
  75. package/dist/core/codex-control/codex-app-server-v2-client.js +3 -3
  76. package/dist/core/codex-control/codex-control-proof.js +0 -1
  77. package/dist/core/codex-control/codex-task-runner.js +1 -4
  78. package/dist/core/codex-exec-output-schema.js +4 -1
  79. package/dist/core/codex-lb/codex-lb-env.js +63 -72
  80. package/dist/core/codex-lb/codex-lb-setup.js +15 -2
  81. package/dist/core/codex-lb/desktop-bridge/header-policy.js +6 -0
  82. package/dist/core/codex-lb/desktop-bridge/http-forward.js +48 -6
  83. package/dist/core/codex-lb/desktop-bridge/security.js +134 -0
  84. package/dist/core/codex-lb/desktop-bridge/server.js +9 -3
  85. package/dist/core/codex-lb/desktop-bridge/state.js +26 -6
  86. package/dist/core/codex-lb/desktop-bridge/types.js +1 -0
  87. package/dist/core/codex-lb/desktop-center-credentials.js +517 -58
  88. package/dist/core/codex-lb/desktop-controller.js +177 -56
  89. package/dist/core/codex-lb/desktop-service.js +179 -40
  90. package/dist/core/codex-lb/legacy-migration.js +1 -3
  91. package/dist/core/codex-lb/native-openai-transport/transport.js +68 -0
  92. package/dist/core/codex-lb/probes/cli-image-tool-probe.js +1 -1
  93. package/dist/core/codex-lb/provider-routing/provider-router.js +58 -0
  94. package/dist/core/codex-lb/routing-truth.js +327 -0
  95. package/dist/core/codex-native/codex-native-feature-broker.js +4 -0
  96. package/dist/core/codex-native/codex-native-pattern-analysis.js +1 -2
  97. package/dist/core/codex-native/core-skill-manifest.js +1 -1
  98. package/dist/core/codex-plugins/codex-plugin-json.js +26 -6
  99. package/dist/core/codex-plugins/codex-plugin-repair.js +32 -6
  100. package/dist/core/commands/basic-cli.js +9 -7
  101. package/dist/core/commands/computer-use-command.js +1 -1
  102. package/dist/core/commands/image-ux-review-command.js +16 -9
  103. package/dist/core/commands/install-package-command.js +105 -0
  104. package/dist/core/commands/intent-normalization/normalizer.js +96 -0
  105. package/dist/core/commands/mad-sks-command.js +23 -274
  106. package/dist/core/commands/mad-sks-headless.js +11 -30
  107. package/dist/core/commands/naruto-command.js +0 -25
  108. package/dist/core/commands/qa-loop-command.js +104 -22
  109. package/dist/core/commands/remote-command.js +2 -2
  110. package/dist/core/commands/research-command.js +10 -5
  111. package/dist/core/commands/telegram-command.js +407 -0
  112. package/dist/core/config-adopt/config-adopt-command.js +35 -0
  113. package/dist/core/config-adopt/config-adopt.js +346 -0
  114. package/dist/core/config-adopt/index.js +3 -0
  115. package/dist/core/doctor/command-alias-cleanup.js +4 -1
  116. package/dist/core/doctor/current-project-guidance-nested.js +37 -6
  117. package/dist/core/doctor/current-project-guidance.js +15 -9
  118. package/dist/core/doctor/doctor-dirty-planner.js +1 -4
  119. package/dist/core/doctor/doctor-readiness-matrix.js +15 -18
  120. package/dist/core/doctor/retired-managed-residue-private.js +4 -3
  121. package/dist/core/doctor/retired-managed-residue-runtime.js +2 -2
  122. package/dist/core/doctor/skill-legacy-surface.js +11 -10
  123. package/dist/core/doctor/sks-menubar-doctor.js +4 -0
  124. package/dist/core/evaluation.js +0 -19
  125. package/dist/core/evidence/v2/evidence-key.js +105 -0
  126. package/dist/core/feature-fixtures.js +12 -7
  127. package/dist/core/feature-registry.js +52 -21
  128. package/dist/core/hooks-runtime/hook-context.js +9 -0
  129. package/dist/core/hooks-runtime/managed-skill-admission.js +54 -4
  130. package/dist/core/hooks-runtime/official-subagent-lifecycle.js +69 -52
  131. package/dist/core/hooks-runtime/stop-finalization.js +226 -0
  132. package/dist/core/hooks-runtime/stop-repeat-guard.js +21 -2
  133. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +2 -2
  134. package/dist/core/hooks-runtime/subagent-skill-availability-evidence.js +3 -3
  135. package/dist/core/hooks-runtime/subagent-skill-availability-guards.js +43 -5
  136. package/dist/core/hooks-runtime/subagent-skill-availability.js +64 -30
  137. package/dist/core/hooks-runtime/subagent-stop-hook.js +15 -2
  138. package/dist/core/hooks-runtime.js +179 -212
  139. package/dist/core/image/reference-evidence/reference-registry.js +145 -0
  140. package/dist/core/image-ux-review/imagegen-adapter.js +21 -9
  141. package/dist/core/image-ux-review/reference-policy/reference-policy.js +9 -0
  142. package/dist/core/imagegen/codex-lb-imagegen-target.js +8 -0
  143. package/dist/core/imagegen/imagegen-capability.js +59 -2
  144. package/dist/core/imagegen/require-imagegen.js +2 -2
  145. package/dist/core/init/skills.js +17 -3
  146. package/dist/core/init.js +3 -3
  147. package/dist/core/install/installed-package-smoke.js +23 -5
  148. package/dist/core/json/canonical.js +9 -0
  149. package/dist/core/locks/file-lock.js +0 -1
  150. package/dist/core/loops/loop-continuation-enforcer.js +65 -7
  151. package/dist/core/loops/loop-decomposer.js +0 -1
  152. package/dist/core/loops/loop-gate-runner.js +65 -4
  153. package/dist/core/loops/loop-gate-selector.js +0 -2
  154. package/dist/core/loops/loop-proof-validation.js +38 -0
  155. package/dist/core/loops/loop-risk-classifier.js +1 -1
  156. package/dist/core/loops/loop-runtime.js +14 -2
  157. package/dist/core/loops/loop-scheduler.js +7 -2
  158. package/dist/core/loops/loop-worker-runtime.js +0 -15
  159. package/dist/core/loops/loop-worktree-runtime.js +52 -4
  160. package/dist/core/managed-assets/managed-assets-manifest.js +14 -14
  161. package/dist/core/naruto/hardware-capacity-probe.js +9 -6
  162. package/dist/core/naruto/naruto-active-pool.js +2 -14
  163. package/dist/core/naruto/naruto-concurrency-governor.js +71 -31
  164. package/dist/core/naruto/naruto-loop-worker-router.js +0 -2
  165. package/dist/core/naruto/naruto-verification-dag.js +0 -1
  166. package/dist/core/naruto/naruto-write-e2e.js +1 -2
  167. package/dist/core/naruto/resource-pressure-monitor.js +0 -4
  168. package/dist/core/observability/architecture-hardening/safe-projection.js +65 -0
  169. package/dist/core/perf/import-graph-budget.js +0 -1
  170. package/dist/core/perf/release-latency-slo.js +3 -2
  171. package/dist/core/preflight/parallel-preflight-engine.js +2 -15
  172. package/dist/core/product-design-app-server.js +13 -1
  173. package/dist/core/proof/fake-real-proof-policy.js +2 -17
  174. package/dist/core/proof/route-proof-gate.js +2 -10
  175. package/dist/core/proof/route-proof-policy.js +1 -1
  176. package/dist/core/proof/runtime-evidence-policy.js +185 -0
  177. package/dist/core/proof/runtime-truth-matrix.js +64 -39
  178. package/dist/core/proof/validation.js +27 -11
  179. package/dist/core/provider/provider-context.js +18 -2
  180. package/dist/core/providers/openrouter/openrouter-account.js +3 -2
  181. package/dist/core/python-tools/python-tool-runner.js +1 -1
  182. package/dist/core/qa-loop/qa-execution-control.js +57 -0
  183. package/dist/core/questions.js +1 -1
  184. package/dist/core/release/extreme-parallel-scheduler.js +0 -3
  185. package/dist/core/release/gate-manifest.js +3 -7
  186. package/dist/core/release/gate-pack-manifest.js +3 -7
  187. package/dist/core/release/package-size-budget.js +2 -2
  188. package/dist/core/release/physical-release-gates.js +189 -0
  189. package/dist/core/release/publish-preflight.js +113 -0
  190. package/dist/core/release/release-gate-affected-selector.js +0 -2
  191. package/dist/core/release/release-gate-batch-runner.js +1 -1
  192. package/dist/core/release/release-gate-node.js +0 -1
  193. package/dist/core/release/release-gate-resource-governor.js +0 -1
  194. package/dist/core/release/release-pack-receipt.js +5 -8
  195. package/dist/core/release/release-real-contract.js +0 -6
  196. package/dist/core/release/resource-class-budget.js +0 -1
  197. package/dist/core/release/stage-publish.js +178 -36
  198. package/dist/core/research/research-adversarial-review.js +103 -9
  199. package/dist/core/research.js +1 -1
  200. package/dist/core/retention.js +0 -1
  201. package/dist/core/routes/constants.js +1 -1
  202. package/dist/core/routes/diagnostic-allowlist.js +0 -1
  203. package/dist/core/routes/dollar-manifest-lite.js +1 -1
  204. package/dist/core/routes.js +46 -15
  205. package/dist/core/runtime/execution-control.js +226 -0
  206. package/dist/core/runtime/progress-recovery/progress-recovery.js +89 -0
  207. package/dist/core/runtime/task-profile.js +10 -4
  208. package/dist/core/runtime/verification-budget.js +10 -1
  209. package/dist/core/safety/intent-contract/intent-contract.js +94 -0
  210. package/dist/core/safety/mutation-guard.js +0 -2
  211. package/dist/core/safety/mutation-ledger.js +0 -2
  212. package/dist/core/safety/requested-scope-contract.js +0 -0
  213. package/dist/core/search-visibility/discovery.js +1 -1
  214. package/dist/core/search-visibility/index.js +12 -0
  215. package/dist/core/search-visibility/verifier.js +112 -3
  216. package/dist/core/security/private-credential-file.js +209 -0
  217. package/dist/core/session/project-namespace.js +0 -5
  218. package/dist/core/skills/skill-agent-metadata.js +1 -3
  219. package/dist/core/strategy/adhd-orchestrating-gate.js +0 -1
  220. package/dist/core/subagents/agent-catalog.js +19 -34
  221. package/dist/core/subagents/model-policy.js +65 -24
  222. package/dist/core/subagents/naruto-help-contract.js +8 -8
  223. package/dist/core/subagents/naruto-host-credentials.js +13 -0
  224. package/dist/core/subagents/official-subagent-config.js +16 -6
  225. package/dist/core/subagents/official-subagent-preparation.js +35 -16
  226. package/dist/core/subagents/official-subagent-prompt.js +7 -7
  227. package/dist/core/subagents/official-subagent-runner.js +27 -4
  228. package/dist/core/subagents/role-model-preferences.js +1 -1
  229. package/dist/core/subagents/thread-budget.js +19 -12
  230. package/dist/core/subagents/wave-lifecycle.js +18 -6
  231. package/dist/core/telegram/access.js +58 -0
  232. package/dist/core/telegram/client.js +157 -0
  233. package/dist/core/telegram/confirmation.js +37 -0
  234. package/dist/core/telegram/doctor.js +154 -0
  235. package/dist/core/telegram/index.js +9 -0
  236. package/dist/core/telegram/keychain.js +317 -0
  237. package/dist/core/telegram/liveness.js +118 -0
  238. package/dist/core/telegram/poller.js +90 -0
  239. package/dist/core/telegram/redaction.js +15 -0
  240. package/dist/core/telegram/state-lock.js +416 -0
  241. package/dist/core/telegram/types.js +1 -0
  242. package/dist/core/text/strings.js +3 -0
  243. package/dist/core/triwiki/context-graph/store/evidence-write-lock.js +29 -0
  244. package/dist/core/triwiki/context-graph/store/fragment-cache.js +24 -0
  245. package/dist/core/triwiki/context-graph/store/snapshot-store.js +69 -21
  246. package/dist/core/triwiki/triwiki-gate-impact-map.js +2 -2
  247. package/dist/core/triwiki/triwiki-module-card.js +1 -2
  248. package/dist/core/update/installed-cli-resolution.js +170 -0
  249. package/dist/core/update/update-diagnostics.js +52 -0
  250. package/dist/core/update/update-migration-state.js +30 -12
  251. package/dist/core/update/update-operation.js +2 -1
  252. package/dist/core/update/update-stage-diagnostics.js +38 -0
  253. package/dist/core/update/update-status.js +2 -9
  254. package/dist/core/update-check.js +279 -91
  255. package/dist/core/version.js +1 -1
  256. package/dist/native/sks-menubar/Sources/AppDelegate.swift +19 -1
  257. package/dist/native/sks-menubar/Sources/AppIdentity.swift +7 -0
  258. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +6 -2
  259. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +159 -92
  260. package/dist/native/sks-menubar/Sources/OperationModels.swift +389 -0
  261. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +57 -0
  262. package/dist/native/sks-menubar/Sources/ProcessClient.swift +3 -1
  263. package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +115 -0
  264. package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +17 -0
  265. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +3 -0
  266. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +58 -17
  267. package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +302 -0
  268. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +5 -0
  269. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +190 -0
  270. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +158 -126
  271. package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +462 -26
  272. package/dist/native/sks-menubar/Sources/SKSKeychainStore.swift +344 -0
  273. package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +27 -0
  274. package/dist/native/sks-menubar/Sources/SingletonInstanceGuard.swift +328 -0
  275. package/dist/native/sks-menubar/Sources/StatusItemController.swift +10 -2
  276. package/dist/native/sks-menubar/Sources/TelegramPrivateFileStore.swift +498 -0
  277. package/dist/native/sks-menubar/Sources/TelegramPrivateFileSupport.swift +236 -0
  278. package/dist/native/sks-menubar/Sources/TelegramProcessGateway.swift +454 -0
  279. package/dist/native/sks-menubar/Sources/TelegramRuntimeSupport.swift +56 -0
  280. package/dist/native/sks-menubar/Sources/TelegramStateLock.swift +448 -0
  281. package/dist/native/sks-menubar/Sources/TelegramSupport.swift +187 -0
  282. package/dist/native/sks-menubar/Sources/TelegramTransport.swift +499 -0
  283. package/dist/native/sks-menubar/Sources/main.swift +15 -1
  284. package/dist/scripts/all-feature-deep-completion-check.js +5 -1
  285. package/dist/scripts/check-publish-tag.js +56 -0
  286. package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
  287. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +12 -3
  288. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +4 -2
  289. package/dist/scripts/codex-native-agent-role-content-check.js +3 -3
  290. package/dist/scripts/codex-native-gate-lib.js +14 -7
  291. package/dist/scripts/current-command-surface-check.js +7 -7
  292. package/dist/scripts/current-surface-update-e2e-check.js +4 -3
  293. package/dist/scripts/current-upgrade-matrix-check.js +5 -24
  294. package/dist/scripts/docs-truthfulness-check.js +17 -13
  295. package/dist/scripts/gate-lib.js +0 -2
  296. package/dist/scripts/gate-policy-audit-check.js +3 -2
  297. package/dist/scripts/harness-benchmark-check.js +1 -1
  298. package/dist/scripts/init-deep-backup-retention-check.js +1 -1
  299. package/dist/scripts/lib/codex-sdk-gate-lib.js +1 -2
  300. package/dist/scripts/loop-directive-check-lib.js +28 -38
  301. package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +14 -180
  302. package/dist/scripts/mad-sks-launch-sql-plane-boundary-check.js +2 -11
  303. package/dist/scripts/official-subagent-workflow-check.js +1 -1
  304. package/dist/scripts/packlist-performance-check.js +1 -2
  305. package/dist/scripts/prepublish-release-check-or-fast.js +32 -0
  306. package/dist/scripts/publish-preflight.js +12 -0
  307. package/dist/scripts/release-affected-selector-check.js +2 -2
  308. package/dist/scripts/release-gate-batch-runner-check.js +2 -2
  309. package/dist/scripts/release-metadata-check.js +8 -12
  310. package/dist/scripts/release-real-check.js +2 -54
  311. package/dist/scripts/runtime-domain-gate-lib.js +2 -96
  312. package/dist/scripts/runtime-proof-summary-check.js +2 -6
  313. package/dist/scripts/search-visibility-gate-lib.js +0 -1
  314. package/dist/scripts/sks-cli-gate-lib.js +1 -1
  315. package/dist/scripts/typed-routing-gate-lib.js +7 -59
  316. package/docs/demo.tape +1 -1
  317. package/infra-harness-gates.json +1 -1456
  318. package/package.json +10 -7
  319. package/release-gates.v2.json +0 -1
  320. package/schemas/agents/parallel-runtime-proof.schema.json +0 -2
  321. package/schemas/codex/agent-result.schema.json +0 -6
  322. package/schemas/naruto/naruto-concurrency-governor.schema.json +1 -3
  323. package/schemas/release/release-gate-node.schema.json +1 -1
  324. package/dist/commands/zellij-lane.js +0 -22
  325. package/dist/commands/zellij-monitor-pane.js +0 -26
  326. package/dist/commands/zellij-slot-column-anchor.js +0 -22
  327. package/dist/commands/zellij-slot-pane.js +0 -80
  328. package/dist/commands/zellij-viewport-pane.js +0 -57
  329. package/dist/commands/zellij.js +0 -422
  330. package/dist/core/agents/agent-runner-zellij.js +0 -164
  331. package/dist/core/agents/agent-slot-pane-binding-proof.js +0 -96
  332. package/dist/core/agents/parallel-write-fixture.js +0 -305
  333. package/dist/core/agents/worker-pane-communication-contract.js +0 -100
  334. package/dist/core/agents/zellij-lane-supervisor.js +0 -428
  335. package/dist/core/agents/zellij-right-lane-cockpit.js +0 -66
  336. package/dist/core/doctor/doctor-zellij-repair.js +0 -40
  337. package/dist/core/ops/upgrade-migration-fixtures.js +0 -119
  338. package/dist/core/proof/route-finalizer-fixtures.js +0 -21
  339. package/dist/core/zellij/homebrew-policy.js +0 -43
  340. package/dist/core/zellij/zellij-capability.js +0 -126
  341. package/dist/core/zellij/zellij-clipboard-config.js +0 -52
  342. package/dist/core/zellij/zellij-command.js +0 -149
  343. package/dist/core/zellij/zellij-fake-adapter.js +0 -186
  344. package/dist/core/zellij/zellij-lane-renderer.js +0 -706
  345. package/dist/core/zellij/zellij-lane-runtime.js +0 -189
  346. package/dist/core/zellij/zellij-launcher.js +0 -268
  347. package/dist/core/zellij/zellij-layout-builder.js +0 -191
  348. package/dist/core/zellij/zellij-monitor-renderer.js +0 -52
  349. package/dist/core/zellij/zellij-official-subagent-activity.js +0 -526
  350. package/dist/core/zellij/zellij-official-subagent-telemetry.js +0 -258
  351. package/dist/core/zellij/zellij-pane-proof.js +0 -226
  352. package/dist/core/zellij/zellij-right-column-manager.js +0 -308
  353. package/dist/core/zellij/zellij-screen-proof.js +0 -120
  354. package/dist/core/zellij/zellij-self-heal-types.js +0 -44
  355. package/dist/core/zellij/zellij-self-heal.js +0 -408
  356. package/dist/core/zellij/zellij-slot-column-anchor.js +0 -304
  357. package/dist/core/zellij/zellij-slot-pane-renderer.js +0 -521
  358. package/dist/core/zellij/zellij-slot-telemetry.js +0 -384
  359. package/dist/core/zellij/zellij-theme.js +0 -66
  360. package/dist/core/zellij/zellij-ui-mode.js +0 -34
  361. package/dist/core/zellij/zellij-update.js +0 -348
  362. package/dist/core/zellij/zellij-viewport-binder.js +0 -61
  363. package/dist/core/zellij/zellij-worker-pane-manager.js +0 -881
  364. package/dist/core/zellij/zellij-worker-pane-summary.js +0 -64
  365. package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +0 -26
  366. package/dist/native/sks-menubar/Tests/OperationCoordinatorTests.swift +0 -174
  367. package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +0 -20
  368. package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +0 -142
  369. package/dist/scripts/zellij-pane-proof-check.js +0 -88
  370. package/dist/scripts/zellij-real-session-cleanup-check.js +0 -139
  371. package/dist/scripts/zellij-real-session-launch-check.js +0 -126
  372. package/dist/scripts/zellij-screen-proof-check.js +0 -43
  373. package/schemas/zellij/zellij-right-column-state.schema.json +0 -40
  374. package/schemas/zellij/zellij-slot-telemetry.schema.json +0 -89
  375. package/schemas/zellij/zellij-worker-pane.schema.json +0 -53
  376. package/scripts/build-clean-atomic.mjs +0 -323
@@ -0,0 +1,389 @@
1
+ import Foundation
2
+
3
+ // SKS CLI timestamps come from JavaScript Date.toISOString() and carry
4
+ // fractional seconds ("2026-07-24T00:00:00.000Z"), which the default
5
+ // ISO8601DateFormatter options cannot parse. Try fractional first, then plain.
6
+ enum SKSTimestamp {
7
+ private static let fractional: ISO8601DateFormatter = {
8
+ let formatter = ISO8601DateFormatter()
9
+ formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
10
+ return formatter
11
+ }()
12
+ private static let plain = ISO8601DateFormatter()
13
+
14
+ static func date(from value: String) -> Date? {
15
+ fractional.date(from: value) ?? plain.date(from: value)
16
+ }
17
+ }
18
+
19
+ enum OperationState: String, Codable {
20
+ case queued, running, waitingForConfirmation, succeeded, failed, cancelled, terminalUncertain
21
+ }
22
+
23
+ enum OperationProgressSignal: String, Codable, CaseIterable {
24
+ case evidence, fileChange, testResult, modelResponse, toolResponse, none
25
+ }
26
+
27
+ enum OperationRecoveryCause: String, Codable, CaseIterable {
28
+ case transientNetwork
29
+ case authentication
30
+ case providerMode
31
+ case accountBinding
32
+ case externalConfiguration
33
+ case unknown
34
+ }
35
+
36
+ enum OperationRecoveryState: String, Codable {
37
+ case active
38
+ case warning
39
+ case autoResumePending
40
+ case pausedResumable
41
+ }
42
+
43
+ enum ProviderApplyStageName: String, Codable, CaseIterable {
44
+ case configSaved = "config_saved"
45
+ case proxyApplied = "proxy_applied"
46
+ case catalogRefreshed = "catalog_refreshed"
47
+ case newSessionReady = "new_session_ready"
48
+ }
49
+
50
+ enum ProviderApplyStageState: String, Codable {
51
+ case pending, running, succeeded, failed
52
+ }
53
+
54
+ struct ProviderApplyStageReceipt: Codable, Equatable {
55
+ let stage: ProviderApplyStageName
56
+ let status: ProviderApplyStageState
57
+ let reasonCode: String?
58
+ let updatedAt: String
59
+
60
+ enum CodingKeys: String, CodingKey {
61
+ case stage, status
62
+ case reasonCode = "reason_code"
63
+ case updatedAt = "updated_at"
64
+ }
65
+ }
66
+
67
+ struct ProviderSessionCopy: Codable, Equatable {
68
+ let mode: String
69
+ let model: String
70
+ let catalogVersion: String
71
+
72
+ enum CodingKeys: String, CodingKey {
73
+ case mode, model
74
+ case catalogVersion = "catalog_version"
75
+ }
76
+ }
77
+
78
+ struct ProviderApplyProjection: Codable, Equatable {
79
+ let schema: String
80
+ let stages: [ProviderApplyStageReceipt]
81
+ let existingSession: ProviderSessionCopy?
82
+ let newSessionDefault: ProviderSessionCopy
83
+
84
+ enum CodingKeys: String, CodingKey {
85
+ case schema, stages
86
+ case existingSession = "existing_session"
87
+ case newSessionDefault = "new_session_default"
88
+ }
89
+
90
+ static func initial(
91
+ existingSession: ProviderSessionCopy?,
92
+ newSessionDefault: ProviderSessionCopy,
93
+ now: Date = Date()
94
+ ) -> ProviderApplyProjection {
95
+ let timestamp = ISO8601DateFormatter().string(from: now)
96
+ return ProviderApplyProjection(
97
+ schema: "sks.provider-apply-projection.v1",
98
+ stages: ProviderApplyStageName.allCases.map {
99
+ ProviderApplyStageReceipt(stage: $0, status: .pending, reasonCode: nil, updatedAt: timestamp)
100
+ },
101
+ existingSession: existingSession,
102
+ newSessionDefault: newSessionDefault
103
+ )
104
+ }
105
+
106
+ func transitioning(
107
+ stage: ProviderApplyStageName,
108
+ to status: ProviderApplyStageState,
109
+ reasonCode: String? = nil,
110
+ now: Date = Date()
111
+ ) throws -> ProviderApplyProjection {
112
+ guard schema == "sks.provider-apply-projection.v1",
113
+ stages.map(\.stage) == ProviderApplyStageName.allCases,
114
+ let index = stages.firstIndex(where: { $0.stage == stage }) else {
115
+ throw ProviderApplyProjectionError.invalidProjection
116
+ }
117
+ if status == .failed, reasonCode == nil { throw ProviderApplyProjectionError.failureReasonRequired }
118
+ if status != .failed, reasonCode != nil { throw ProviderApplyProjectionError.unexpectedReason }
119
+ let current = stages[index].status
120
+ let validTransition = current == status
121
+ || current == .pending && status == .running
122
+ || current == .running && (status == .succeeded || status == .failed)
123
+ || current == .failed && status == .running
124
+ guard validTransition else { throw ProviderApplyProjectionError.invalidTransition }
125
+ if status != .pending, index > 0, stages[index - 1].status != .succeeded {
126
+ throw ProviderApplyProjectionError.previousStageIncomplete
127
+ }
128
+ var next = stages
129
+ next[index] = ProviderApplyStageReceipt(
130
+ stage: stage,
131
+ status: status,
132
+ reasonCode: reasonCode,
133
+ updatedAt: ISO8601DateFormatter().string(from: now)
134
+ )
135
+ return ProviderApplyProjection(
136
+ schema: schema,
137
+ stages: next,
138
+ existingSession: existingSession,
139
+ newSessionDefault: newSessionDefault
140
+ )
141
+ }
142
+
143
+ var allSucceeded: Bool { stages.allSatisfy { $0.status == .succeeded } }
144
+ var failedStage: ProviderApplyStageReceipt? { stages.first { $0.status == .failed } }
145
+ }
146
+
147
+ enum ProviderApplyProjectionError: Error {
148
+ case invalidProjection
149
+ case failureReasonRequired
150
+ case unexpectedReason
151
+ case invalidTransition
152
+ case previousStageIncomplete
153
+ }
154
+
155
+ struct OperationRecoveryStatus: Codable, Equatable {
156
+ let schema: String
157
+ let state: OperationRecoveryState
158
+ let cause: OperationRecoveryCause?
159
+ let automaticResume: Bool
160
+ let retryCount: Int
161
+ let maxAutomaticRetries: Int
162
+ let lastProgressSignal: OperationProgressSignal
163
+ let lastProgressAt: String
164
+ let stallReason: String?
165
+ let recoveryAttempt: String?
166
+ let nextAction: String
167
+ let pinnedMode: String?
168
+ let pinnedModel: String?
169
+ let accountBinding: String
170
+ let evidenceIntegrity: String
171
+
172
+ enum CodingKeys: String, CodingKey {
173
+ case schema, state, cause
174
+ case automaticResume = "automatic_resume"
175
+ case retryCount = "retry_count"
176
+ case maxAutomaticRetries = "max_automatic_retries"
177
+ case lastProgressSignal = "last_progress_signal"
178
+ case lastProgressAt = "last_progress_at"
179
+ case stallReason = "stall_reason"
180
+ case recoveryAttempt = "recovery_attempt"
181
+ case nextAction = "next_action"
182
+ case pinnedMode = "pinned_mode"
183
+ case pinnedModel = "pinned_model"
184
+ case accountBinding = "account_binding"
185
+ case evidenceIntegrity = "evidence_integrity"
186
+ }
187
+ }
188
+
189
+ struct OperationRecoveryAttemptOutcome {
190
+ let succeeded: Bool
191
+ let cause: OperationRecoveryCause?
192
+ let progressSignal: OperationProgressSignal
193
+
194
+ static func success(_ signal: OperationProgressSignal) -> OperationRecoveryAttemptOutcome {
195
+ OperationRecoveryAttemptOutcome(succeeded: true, cause: nil, progressSignal: signal)
196
+ }
197
+
198
+ static func failure(_ cause: OperationRecoveryCause) -> OperationRecoveryAttemptOutcome {
199
+ OperationRecoveryAttemptOutcome(succeeded: false, cause: cause, progressSignal: .none)
200
+ }
201
+ }
202
+
203
+ enum OperationRecoveryPolicy {
204
+ static let maxAutomaticNetworkRetries = 2
205
+
206
+ /// Time is diagnostic only. A fresh progress signal always keeps the work
207
+ /// active, even after a warning threshold. Only a classified cause may choose
208
+ /// automatic or manual recovery, and only transient network causes auto-resume.
209
+ static func evaluate(
210
+ cause: OperationRecoveryCause?,
211
+ sameCauseRetryCount: Int,
212
+ progressSignal: OperationProgressSignal,
213
+ progressObserved: Bool,
214
+ secondsWithoutProgress: TimeInterval,
215
+ warningAfter: TimeInterval,
216
+ pinnedMode: String? = nil,
217
+ pinnedModel: String? = nil,
218
+ now: Date = Date()
219
+ ) -> OperationRecoveryStatus {
220
+ let retryCount = max(0, sameCauseRetryCount)
221
+ let timestamp = ISO8601DateFormatter().string(from: now)
222
+ let shared = (
223
+ schema: "sks.operation-recovery.v1",
224
+ signal: progressSignal,
225
+ timestamp: timestamp,
226
+ mode: pinnedMode,
227
+ model: pinnedModel
228
+ )
229
+ if progressObserved {
230
+ return OperationRecoveryStatus(
231
+ schema: shared.schema, state: .active, cause: nil,
232
+ automaticResume: false, retryCount: retryCount,
233
+ maxAutomaticRetries: maxAutomaticNetworkRetries,
234
+ lastProgressSignal: shared.signal, lastProgressAt: shared.timestamp,
235
+ stallReason: nil, recoveryAttempt: nil,
236
+ nextAction: "Work is progressing; keep running.",
237
+ pinnedMode: shared.mode, pinnedModel: shared.model,
238
+ accountBinding: "pinned_unchanged", evidenceIntegrity: "preserved"
239
+ )
240
+ }
241
+ guard let cause = cause else {
242
+ let warning = secondsWithoutProgress >= max(1, warningAfter)
243
+ return OperationRecoveryStatus(
244
+ schema: shared.schema, state: warning ? .warning : .active, cause: nil,
245
+ automaticResume: false, retryCount: retryCount,
246
+ maxAutomaticRetries: maxAutomaticNetworkRetries,
247
+ lastProgressSignal: shared.signal, lastProgressAt: shared.timestamp,
248
+ stallReason: warning ? "No progress signal observed; time budget is warning-only." : nil,
249
+ recoveryAttempt: warning ? "Inspect runner health without terminating the operation." : nil,
250
+ nextAction: warning ? "Keep state resumable and inspect the stalled stage." : "Keep running.",
251
+ pinnedMode: shared.mode, pinnedModel: shared.model,
252
+ accountBinding: "pinned_unchanged", evidenceIntegrity: "preserved"
253
+ )
254
+ }
255
+ if cause == .transientNetwork, retryCount < maxAutomaticNetworkRetries {
256
+ let nextRetry = retryCount + 1
257
+ return OperationRecoveryStatus(
258
+ schema: shared.schema, state: .autoResumePending, cause: cause,
259
+ automaticResume: true, retryCount: nextRetry,
260
+ maxAutomaticRetries: maxAutomaticNetworkRetries,
261
+ lastProgressSignal: shared.signal, lastProgressAt: shared.timestamp,
262
+ stallReason: "Transient network interruption.",
263
+ recoveryAttempt: "Bounded automatic resume \(nextRetry)/\(maxAutomaticNetworkRetries).",
264
+ nextAction: "Retry the same request with the same pinned mode, model, and account binding.",
265
+ pinnedMode: shared.mode, pinnedModel: shared.model,
266
+ accountBinding: "pinned_unchanged", evidenceIntegrity: "preserved"
267
+ )
268
+ }
269
+ let reason = cause == .transientNetwork
270
+ ? "Transient network retry limit reached."
271
+ : "\(cause.rawValue) requires explicit user review."
272
+ return OperationRecoveryStatus(
273
+ schema: shared.schema, state: .pausedResumable, cause: cause,
274
+ automaticResume: false, retryCount: min(retryCount, maxAutomaticNetworkRetries),
275
+ maxAutomaticRetries: maxAutomaticNetworkRetries,
276
+ lastProgressSignal: shared.signal, lastProgressAt: shared.timestamp,
277
+ stallReason: reason, recoveryAttempt: nil,
278
+ nextAction: "Review the cause in SKS Center, then resume explicitly from the owning section.",
279
+ pinnedMode: shared.mode, pinnedModel: shared.model,
280
+ accountBinding: "pinned_unchanged", evidenceIntegrity: "preserved"
281
+ )
282
+ }
283
+ }
284
+
285
+ struct OperationSnapshot: Codable {
286
+ let schema: String
287
+ let id: String
288
+ let kind: String
289
+ let state: OperationState
290
+ let stage: String?
291
+ let progress: Double?
292
+ let startedAt: String
293
+ let updatedAt: String
294
+ let publicSummary: String
295
+ let logPath: String?
296
+ let retryable: Bool
297
+ let targetVersion: String?
298
+ let projectRoot: String?
299
+ let registry: String?
300
+ let recovery: OperationRecoveryStatus?
301
+ let providerApply: ProviderApplyProjection?
302
+
303
+ init(
304
+ schema: String,
305
+ id: String,
306
+ kind: String,
307
+ state: OperationState,
308
+ stage: String?,
309
+ progress: Double?,
310
+ startedAt: String,
311
+ updatedAt: String,
312
+ publicSummary: String,
313
+ logPath: String?,
314
+ retryable: Bool,
315
+ targetVersion: String?,
316
+ projectRoot: String?,
317
+ registry: String?,
318
+ recovery: OperationRecoveryStatus? = nil,
319
+ providerApply: ProviderApplyProjection? = nil
320
+ ) {
321
+ self.schema = schema
322
+ self.id = id
323
+ self.kind = kind
324
+ self.state = state
325
+ self.stage = stage
326
+ self.progress = progress
327
+ self.startedAt = startedAt
328
+ self.updatedAt = updatedAt
329
+ self.publicSummary = publicSummary
330
+ self.logPath = logPath
331
+ self.retryable = retryable
332
+ self.targetVersion = targetVersion
333
+ self.projectRoot = projectRoot
334
+ self.registry = registry
335
+ self.recovery = recovery
336
+ self.providerApply = providerApply
337
+ }
338
+ }
339
+
340
+ struct UpdateOperationStageSnapshot: Codable {
341
+ let id: String
342
+ let ok: Bool
343
+ let status: String
344
+ let updatedAt: String
345
+
346
+ enum CodingKeys: String, CodingKey {
347
+ case id, ok, status
348
+ case updatedAt = "updated_at"
349
+ }
350
+ }
351
+
352
+ struct UpdateOperationReceiptSnapshot: Codable {
353
+ let schema: String
354
+ let id: String
355
+ let kind: String
356
+ let state: String
357
+ let currentStage: String?
358
+ let startedAt: String
359
+ let updatedAt: String
360
+ let fromVersion: String
361
+ let targetVersion: String?
362
+ let previousVersion: String
363
+ let projectRoot: String?
364
+ let registry: String?
365
+ let rollbackCommand: String
366
+ let sideEffectsStarted: Bool
367
+ let stages: [UpdateOperationStageSnapshot]
368
+ let resultStatus: String?
369
+ let publicError: String?
370
+ let receiptPath: String
371
+
372
+ enum CodingKeys: String, CodingKey {
373
+ case schema, id, kind, state, stages
374
+ case currentStage = "current_stage"
375
+ case startedAt = "started_at"
376
+ case updatedAt = "updated_at"
377
+ case fromVersion = "from_version"
378
+ case targetVersion = "target_version"
379
+ case previousVersion = "previous_version"
380
+ case projectRoot = "project_root"
381
+ case registry
382
+ case rollbackCommand = "rollback_command"
383
+ case sideEffectsStarted = "side_effects_started"
384
+ case resultStatus = "result_status"
385
+ case publicError = "public_error"
386
+ case receiptPath = "receipt_path"
387
+ }
388
+ }
389
+
@@ -186,6 +186,7 @@ final class OverviewViewController: NSViewController, ControlCenterPage {
186
186
  private let operations: OperationCoordinator
187
187
  private let status = NativeView.detail("Loading local SKS status…")
188
188
  private let notificationInbox = NativeView.detail("Notifications: checking authorization…")
189
+ private let recoveryStatus = NativeView.detail("Progress recovery: no operation state loaded yet.")
189
190
  private let healthBadge = NativeView.badge("Checking local status", color: .systemBlue)
190
191
  private let statusSpinner = NativeView.spinner(label: "Checking SKS Center status")
191
192
  private var generation = 0
@@ -193,6 +194,7 @@ final class OverviewViewController: NSViewController, ControlCenterPage {
193
194
  private var doctorButton: NSButton!
194
195
  private var refreshButton: NSButton!
195
196
  private var updateCodexButton: NSButton!
197
+ private var reviewAndResumeButton: NSButton!
196
198
  /// Section navigation by sidebar title, wired by ControlCenterWindowController.
197
199
  var openSection: ((String) -> Void)?
198
200
 
@@ -207,6 +209,8 @@ final class OverviewViewController: NSViewController, ControlCenterPage {
207
209
  doctorButton = NativeView.button("Run Doctor", target: self, action: #selector(doctor))
208
210
  refreshButton = NativeView.button("Refresh", target: self, action: #selector(refreshStatus))
209
211
  updateCodexButton = NativeView.button("Update Codex CLI", target: self, action: #selector(updateCodexCLI))
212
+ reviewAndResumeButton = NativeView.button("Review & Resume…", target: self, action: #selector(reviewAndResume))
213
+ reviewAndResumeButton.isEnabled = false
210
214
  updateCodexButton.setAccessibilityHelp("Update the operator Codex CLI to the preferred latest channel.")
211
215
  let buttons = NativeView.row([refreshButton, doctorButton, updateCodexButton])
212
216
  let shortcuts = NativeView.row([
@@ -226,10 +230,16 @@ final class OverviewViewController: NSViewController, ControlCenterPage {
226
230
  subtitle: "Results remain available here even when macOS notifications are disabled.",
227
231
  views: [notificationInbox, shortcuts]
228
232
  )
233
+ let recoveryCard = NativeView.card(
234
+ title: "Progress, pause & recovery",
235
+ subtitle: "Time budgets are warnings, never automatic termination. Only transient network failures can auto-resume, at most twice. Authentication, mode, account binding, and external configuration always wait for explicit review.",
236
+ views: [recoveryStatus, NativeView.row([reviewAndResumeButton])]
237
+ )
229
238
  view = NativeView.page([
230
239
  NativeView.title("Overview"),
231
240
  NativeView.detail("Menu Bar build \(AppRuntime.packageVersion) · Local health for SKS, Codex CLI, MCP, and operations. Prefer the latest Codex CLI; SKS stays version-agnostic and capability-gates features."),
232
241
  healthCard,
242
+ recoveryCard,
233
243
  nextStepsCard
234
244
  ])
235
245
  }
@@ -238,6 +248,28 @@ final class OverviewViewController: NSViewController, ControlCenterPage {
238
248
  @objc private func openUpdates() { openSection?("Updates") }
239
249
  @objc private func openDiagnostics() { openSection?("Diagnostics") }
240
250
 
251
+ @objc private func reviewAndResume() {
252
+ guard let operation = operations.latestSnapshot(),
253
+ let recovery = operation.recovery,
254
+ recovery.state == .pausedResumable || recovery.state == .warning else {
255
+ recoveryStatus.stringValue = "No resumable pause is available. Refresh status to inspect the latest progress signal."
256
+ reviewAndResumeButton.isEnabled = false
257
+ return
258
+ }
259
+ let section: String
260
+ if operation.kind.localizedCaseInsensitiveContains("provider")
261
+ || operation.kind.localizedCaseInsensitiveContains("openrouter")
262
+ || operation.kind.localizedCaseInsensitiveContains("codex-lb") {
263
+ section = "Providers"
264
+ } else if operation.kind.localizedCaseInsensitiveContains("update") {
265
+ section = "Updates"
266
+ } else {
267
+ section = "Diagnostics"
268
+ }
269
+ recoveryStatus.stringValue = "Review opened for \(operation.kind). Confirm the unchanged mode/model/account binding, then retry from \(section). Nothing resumed automatically."
270
+ openSection?(section)
271
+ }
272
+
241
273
  func refreshOnAppear() {
242
274
  loadStatus(forceUpdateRefresh: false)
243
275
  }
@@ -381,6 +413,7 @@ final class OverviewViewController: NSViewController, ControlCenterPage {
381
413
  private func renderStatus(update: [String: Any]?, mcp: [String: Any]?, partial: Bool) {
382
414
  let rendered = summary(update: update, mcp: mcp)
383
415
  status.stringValue = rendered
416
+ renderRecoveryStatus(operations.latestSnapshot())
384
417
  if partial {
385
418
  NativeView.setBadge(healthBadge, text: "Partial status · still checking", color: .systemBlue)
386
419
  } else if rendered.localizedCaseInsensitiveContains("unavailable")
@@ -391,6 +424,30 @@ final class OverviewViewController: NSViewController, ControlCenterPage {
391
424
  }
392
425
  }
393
426
 
427
+ private func renderRecoveryStatus(_ operation: OperationSnapshot?) {
428
+ guard let operation = operation else {
429
+ recoveryStatus.stringValue = "Progress recovery: no operation recorded · automatic resume inactive."
430
+ reviewAndResumeButton.isEnabled = false
431
+ return
432
+ }
433
+ guard let recovery = operation.recovery else {
434
+ recoveryStatus.stringValue = "Progress recovery: no pause/retry decision recorded for \(operation.kind) · critical path \(operation.stage ?? "unknown") · cache evidence not reported."
435
+ reviewAndResumeButton.isEnabled = false
436
+ return
437
+ }
438
+ let cause = recovery.cause?.rawValue ?? "none"
439
+ let automatic = recovery.automaticResume ? "yes" : "no"
440
+ let mode = recovery.pinnedMode ?? "not reported"
441
+ let model = recovery.pinnedModel ?? "not reported"
442
+ let stall = recovery.stallReason.map { " · stop reason: \($0)" } ?? ""
443
+ let attempt = recovery.recoveryAttempt.map { " · recovery: \($0)" } ?? ""
444
+ recoveryStatus.stringValue = "State \(recovery.state.rawValue) · progress \(recovery.lastProgressSignal.rawValue) at \(recovery.lastProgressAt) · cause \(cause) · auto resume \(automatic) · retry \(recovery.retryCount)/\(recovery.maxAutomaticRetries) · critical path \(operation.stage ?? "unknown") · mode \(mode) · model \(model) · account \(recovery.accountBinding) · evidence \(recovery.evidenceIntegrity)\(stall)\(attempt) · next: \(recovery.nextAction)"
445
+ reviewAndResumeButton.isEnabled = recovery.state == .pausedResumable || recovery.state == .warning
446
+ reviewAndResumeButton.toolTip = reviewAndResumeButton.isEnabled
447
+ ? "Open the owning section for explicit review; this button never changes authentication, mode, account, or evidence."
448
+ : "No manual resume action is required for the current state."
449
+ }
450
+
394
451
  private func summary(update: [String: Any]?, mcp: [String: Any]?) -> String {
395
452
  let codexRunning = AppRuntime.codexBundleId.map { bundle in
396
453
  NSWorkspace.shared.runningApplications.contains { $0.bundleIdentifier == bundle }
@@ -421,7 +421,9 @@ final class ProcessClient {
421
421
  }
422
422
 
423
423
  private func sensitiveStdinValues(arguments: [String], stdin: String?) -> [String] {
424
- guard arguments.contains("--api-key-stdin"), let stdin = stdin else { return [] }
424
+ let receivesSensitiveStdin = arguments.contains("--api-key-stdin")
425
+ || arguments.contains("--token-stdin")
426
+ guard receivesSensitiveStdin, let stdin = stdin else { return [] }
425
427
  let normalized = stdin.trimmingCharacters(in: .whitespacesAndNewlines)
426
428
  guard !normalized.isEmpty else { return [] }
427
429
  return normalized == stdin ? [normalized] : [normalized, stdin]
@@ -0,0 +1,115 @@
1
+ import Cocoa
2
+
3
+ extension ProvidersViewController {
4
+ func makeCliConnectProgressView() -> NSStackView {
5
+ cliConnectConfigurationStage.setAccessibilityLabel("Codex LB configuration stage: waiting")
6
+ cliConnectConfigurationStage.setAccessibilityIdentifier("sks-center-codex-lb-configuration-stage")
7
+ cliConnectRequestStage.setAccessibilityLabel("Codex LB one-request low-token test stage: waiting")
8
+ cliConnectRequestStage.setAccessibilityIdentifier("sks-center-codex-lb-request-stage")
9
+ cliConnectResponseStage.setAccessibilityLabel("Codex LB response stage: not received")
10
+ cliConnectResponseStage.setAccessibilityIdentifier("sks-center-codex-lb-response-stage")
11
+ cliConnectResult.setAccessibilityLabel("Codex LB connection proof result: not run")
12
+ cliConnectResult.setAccessibilityIdentifier("sks-center-codex-lb-connect-result")
13
+ let title = NativeView.sectionTitle("Connection Proof")
14
+ title.setAccessibilityIdentifier("sks-center-codex-lb-connect-heading")
15
+ let stack = NSStackView(views: [title, cliConnectProgress, cliConnectConfigurationStage, cliConnectRequestStage, cliConnectResponseStage, cliConnectResult])
16
+ stack.orientation = .vertical
17
+ stack.alignment = .width
18
+ stack.spacing = 6
19
+ stack.setAccessibilityRole(.group)
20
+ stack.setAccessibilityLabel("Codex LB connection proof")
21
+ stack.setAccessibilityIdentifier("sks-center-codex-lb-connect-proof")
22
+ return stack
23
+ }
24
+
25
+ func renderCliConnectStages(
26
+ progress: Double,
27
+ configuration: String,
28
+ request: String,
29
+ response: String,
30
+ result: String,
31
+ tone: NSColor
32
+ ) {
33
+ cliConnectProgress.doubleValue = min(3, max(0, progress))
34
+ cliConnectProgress.setAccessibilityValue("Stage \(Int(cliConnectProgress.doubleValue)) of 3")
35
+ cliConnectConfigurationStage.stringValue = "1. Configuration · \(configuration)"
36
+ cliConnectConfigurationStage.setAccessibilityLabel("Codex LB configuration stage: \(configuration)")
37
+ cliConnectRequestStage.stringValue = "2. One-request low-token test · \(request)"
38
+ cliConnectRequestStage.setAccessibilityLabel("Codex LB one-request low-token test stage: \(request)")
39
+ cliConnectResponseStage.stringValue = "3. Response · \(response)"
40
+ cliConnectResponseStage.setAccessibilityLabel("Codex LB response stage: \(response)")
41
+ cliConnectResult.stringValue = result
42
+ cliConnectResult.textColor = tone
43
+ cliConnectResult.setAccessibilityLabel("Codex LB connection proof result: \(result)")
44
+ }
45
+
46
+ @objc func testConnection() {
47
+ runConnectTest()
48
+ }
49
+
50
+ func runConnectTest() {
51
+ guard !connectTestInFlight else {
52
+ cliProviderStatus.stringValue = "A Codex LB connection proof is already running."
53
+ return
54
+ }
55
+ guard !busy else { cliProviderStatus.stringValue = "Another provider action is already running."; return }
56
+ guard let snapshot = operations.begin(kind: "codex-lb-connect-test", mutationGroup: nil, summary: "Run Codex LB connect test") else {
57
+ cliProviderStatus.stringValue = "Another guarded operation is already running. Wait or open Diagnostics."
58
+ return
59
+ }
60
+ connectTestInFlight = true
61
+ setBusy(true)
62
+ cliProviderStatus.stringValue = "Codex LB mode \(codexLbSelectedNow ? "selected" : "selection unconfirmed") · sending one bounded low-token request…"
63
+ renderCliConnectStages(
64
+ progress: 2,
65
+ configuration: codexLbSelectedNow ? "CLI provider selected" : "selection unconfirmed",
66
+ request: "sending one bounded request…",
67
+ response: "waiting",
68
+ result: "Waiting for structured proof. Connectivity has not been claimed.",
69
+ tone: .secondaryLabelColor
70
+ )
71
+ _ = operations.update(snapshot, state: .running, stage: "one-request-low-token-test", progress: 2.0 / 3.0, summary: "Run Codex LB connect test")
72
+ processClient.run(["codex-lb", "connect-test", "--json"], timeout: NativeView.mutationTimeout) { [weak self] result in
73
+ guard let self = self else { return }
74
+ self.connectTestInFlight = false
75
+ self.setBusy(false)
76
+ let parsed = self.json(result.output)
77
+ let proof = parsed.flatMap(CodexLbConnectTestTruth.success(from:))
78
+ let proved = result.code == 0 && proof != nil
79
+ _ = self.operations.update(snapshot, state: proved ? .succeeded : .failed, stage: "complete", progress: 1, summary: proved ? "Codex LB connection proved" : "Codex LB connection proof failed")
80
+ if let proof = proof, result.code == 0 {
81
+ self.codexLbSelectedNow = true
82
+ self.cliProviderStatus.stringValue = "Codex LB mode selected · connection proved by one live response."
83
+ ControlKit.setBadge(self.activeProviderBadge, text: "Codex LB · active · model \(proof.model) · \(proof.latencyMs) ms", tone: .ok)
84
+ self.renderCliConnectStages(
85
+ progress: 3,
86
+ configuration: "CLI provider selected",
87
+ request: "completed · \(proof.outputTokens) output tokens",
88
+ response: "received · id \(proof.responseId)",
89
+ result: proof.renderedSummary,
90
+ tone: .systemGreen
91
+ )
92
+ return
93
+ }
94
+ let selected = self.codexLbSelectedNow
95
+ let failure = parsed.map(CodexLbConnectTestTruth.validationFailure(from:))
96
+ ?? "structured connect-test JSON was not returned"
97
+ self.cliProviderStatus.stringValue = selected
98
+ ? "Codex LB mode is selected, but connection proof failed · \(failure)."
99
+ : "Codex LB connection proof failed and provider selection is unconfirmed · \(failure)."
100
+ if selected {
101
+ ControlKit.setBadge(self.activeProviderBadge, text: "Codex LB · selected · connection proof failed", tone: .warning)
102
+ }
103
+ self.renderCliConnectStages(
104
+ progress: 3,
105
+ configuration: selected ? "CLI provider remains selected" : "selection unconfirmed",
106
+ request: "completed without valid proof",
107
+ response: "failed",
108
+ result: selected
109
+ ? "Mode is selected, but connection proof failed · \(failure). Use Run Connect Test to retry."
110
+ : "Connection proof failed · \(failure). Confirm the provider, then retry.",
111
+ tone: .systemRed
112
+ )
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,17 @@
1
+ import Cocoa
2
+
3
+ extension ProvidersViewController {
4
+ func refreshFastStatus() {
5
+ if !busy { fastStatus.stringValue = "Codex Fast: checking the official service-tier setting…" }
6
+ processClient.run(["fast-mode", "status", "--json"], timeout: NativeView.statusTimeout) { [weak self] result in
7
+ guard let self = self else { return }
8
+ guard result.code == 0, let json = self.json(result.output),
9
+ let global = json["global"] as? [String: Any], let on = global["on"] as? Bool else {
10
+ self.fastStatus.stringValue = "Codex Fast: unavailable — no state was assumed."
11
+ return
12
+ }
13
+ let tier = global["service_tier"] as? String ?? (on ? "fast" : "default")
14
+ self.fastStatus.stringValue = "Codex Fast: \(on ? "On" : "Off") · official service_tier=\(tier) · model and reasoning remain separate."
15
+ }
16
+ }
17
+ }
@@ -63,6 +63,9 @@ extension ProvidersViewController {
63
63
  test.setAccessibilityHelp("Checks that the selected model exists in both the local catalog and the live loopback router. No configuration is changed.")
64
64
  activate.setAccessibilityHelp("Validates the loopback router, writes its provider and catalog settings to Codex config, and restarts Codex App. Runtime adoption still requires a live Codex check.")
65
65
  multiProvider.refreshButton = refresh
66
+ registerProviderAction(refresh, id: "sks-provider-refresh-router")
67
+ registerProviderAction(test, id: "sks-provider-test-router")
68
+ registerProviderAction(activate, id: "sks-provider-configure-router")
66
69
  actionButtons += [refresh, test, activate]
67
70
 
68
71
  let routerLabel = NSTextField(labelWithString: "Router URL")