sneakoscope 4.8.6 → 5.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/README.md +51 -726
  2. package/bench/tasks/t01-off-by-one/repo/package.json +9 -0
  3. package/bench/tasks/t01-off-by-one/repo/src/pagination.js +5 -0
  4. package/bench/tasks/t01-off-by-one/repo/test.js +5 -0
  5. package/bench/tasks/t01-off-by-one/task.json +13 -0
  6. package/bench/tasks/t02-signature-cochange/repo/package.json +9 -0
  7. package/bench/tasks/t02-signature-cochange/repo/src/admin.js +5 -0
  8. package/bench/tasks/t02-signature-cochange/repo/src/audit.js +5 -0
  9. package/bench/tasks/t02-signature-cochange/repo/src/labels.js +3 -0
  10. package/bench/tasks/t02-signature-cochange/repo/src/profile.js +5 -0
  11. package/bench/tasks/t02-signature-cochange/repo/test.js +9 -0
  12. package/bench/tasks/t02-signature-cochange/task.json +12 -0
  13. package/bench/tasks/t03-type-puzzle/repo/package.json +9 -0
  14. package/bench/tasks/t03-type-puzzle/repo/src/config.js +4 -0
  15. package/bench/tasks/t03-type-puzzle/repo/test.js +6 -0
  16. package/bench/tasks/t03-type-puzzle/task.json +13 -0
  17. package/bench/tasks/t04-refactor-preserve/repo/package.json +9 -0
  18. package/bench/tasks/t04-refactor-preserve/repo/src/cart.js +8 -0
  19. package/bench/tasks/t04-refactor-preserve/repo/test.js +4 -0
  20. package/bench/tasks/t04-refactor-preserve/task.json +12 -0
  21. package/bench/tasks/t05-performance/repo/package.json +9 -0
  22. package/bench/tasks/t05-performance/repo/src/pairs.js +9 -0
  23. package/bench/tasks/t05-performance/repo/test.js +11 -0
  24. package/bench/tasks/t05-performance/task.json +12 -0
  25. package/bench/tasks/t06-mistake-rule/repo/package.json +9 -0
  26. package/bench/tasks/t06-mistake-rule/repo/src/loader.js +6 -0
  27. package/bench/tasks/t06-mistake-rule/repo/test.js +7 -0
  28. package/bench/tasks/t06-mistake-rule/task.json +12 -0
  29. package/config/bench-baseline.json +7 -0
  30. package/crates/sks-core/Cargo.lock +1 -1
  31. package/crates/sks-core/Cargo.toml +1 -1
  32. package/crates/sks-core/src/main.rs +1 -1
  33. package/dist/bin/install.js +35 -0
  34. package/dist/bin/sks.js +1 -1
  35. package/dist/cli/cli-theme.js +51 -0
  36. package/dist/cli/command-registry.js +75 -42
  37. package/dist/cli/help-fast.js +18 -8
  38. package/dist/cli/insane-search-command.js +36 -8
  39. package/dist/cli/install-helpers.js +147 -47
  40. package/dist/cli/router.js +58 -2
  41. package/dist/commands/codex-lb.js +6 -4
  42. package/dist/commands/doctor.js +146 -8
  43. package/dist/commands/proof.js +6 -3
  44. package/dist/commands/zellij-monitor-pane.js +25 -0
  45. package/dist/commands/zellij-slot-pane.js +39 -2
  46. package/dist/commands/zellij-viewport-pane.js +56 -0
  47. package/dist/commands/zellij.js +55 -2
  48. package/dist/config/skills-manifest.json +493 -0
  49. package/dist/core/agents/agent-conflict-graph.js +5 -0
  50. package/dist/core/agents/agent-lease.js +5 -0
  51. package/dist/core/agents/agent-ledger-schemas.js +1 -0
  52. package/dist/core/agents/agent-lifecycle.js +86 -35
  53. package/dist/core/agents/agent-orchestrator.js +287 -72
  54. package/dist/core/agents/agent-output-validator.js +14 -3
  55. package/dist/core/agents/agent-patch-queue-store.js +108 -4
  56. package/dist/core/agents/agent-patch-queue.js +10 -3
  57. package/dist/core/agents/agent-patch-schema.js +13 -0
  58. package/dist/core/agents/agent-proof-evidence.js +6 -1
  59. package/dist/core/agents/agent-runner-fake.js +40 -0
  60. package/dist/core/agents/agent-scheduler.js +2 -3
  61. package/dist/core/agents/agent-worker-pipeline.js +36 -2
  62. package/dist/core/agents/codex-exec-worker-adapter.js +2 -0
  63. package/dist/core/agents/native-cli-session-swarm.js +30 -13
  64. package/dist/core/agents/native-cli-worker.js +2 -1
  65. package/dist/core/agents/native-worker-backend-router.js +58 -1
  66. package/dist/core/auto-review.js +25 -4
  67. package/dist/core/codex/agent-config-file-repair.js +15 -2
  68. package/dist/core/codex/codex-config-eperm-repair.js +8 -2
  69. package/dist/core/codex/codex-config-guard.js +289 -0
  70. package/dist/core/codex/codex-config-toml.js +122 -0
  71. package/dist/core/codex/codex-project-config-policy.js +59 -7
  72. package/dist/core/codex-app/sks-menubar.js +780 -122
  73. package/dist/core/codex-app.js +1 -0
  74. package/dist/core/codex-control/codex-fake-sdk-adapter.js +6 -4
  75. package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
  76. package/dist/core/codex-control/codex-sdk-env-policy.js +1 -1
  77. package/dist/core/codex-control/codex-task-runner.js +32 -14
  78. package/dist/core/codex-control/python-codex-sdk-adapter.js +4 -1
  79. package/dist/core/codex-control/schemas/agent-worker-result.schema.js +12 -3
  80. package/dist/core/codex-hooks/codex-hook-managed-install.js +5 -0
  81. package/dist/core/codex-hooks/codex-hook-state-writer.js +70 -11
  82. package/dist/core/codex-hooks/codex-hook-trust-doctor.js +2 -2
  83. package/dist/core/codex-lb/codex-lb-env.js +20 -1
  84. package/dist/core/codex-lb/codex-lb-setup.js +2 -5
  85. package/dist/core/codex-native/skill-registry-ledger.js +24 -5
  86. package/dist/core/commands/basic-cli.js +21 -2
  87. package/dist/core/commands/check-command.js +37 -5
  88. package/dist/core/commands/command-utils.js +22 -2
  89. package/dist/core/commands/computer-use-command.js +62 -7
  90. package/dist/core/commands/db-command.js +31 -5
  91. package/dist/core/commands/fast-mode-command.js +39 -11
  92. package/dist/core/commands/gate-result-contract.js +43 -0
  93. package/dist/core/commands/gates-command.js +6 -1
  94. package/dist/core/commands/gc-command.js +29 -2
  95. package/dist/core/commands/goal-command.js +9 -2
  96. package/dist/core/commands/gx-command.js +79 -7
  97. package/dist/core/commands/image-ux-review-command.js +188 -13
  98. package/dist/core/commands/mad-db-command.js +85 -176
  99. package/dist/core/commands/mad-sks-command.js +248 -34
  100. package/dist/core/commands/menubar-command.js +146 -0
  101. package/dist/core/commands/naruto-command.js +64 -10
  102. package/dist/core/commands/pipeline-command.js +21 -2
  103. package/dist/core/commands/plan-command.js +76 -0
  104. package/dist/core/commands/ppt-command.js +159 -24
  105. package/dist/core/commands/qa-loop-command.js +6 -2
  106. package/dist/core/commands/release-command.js +55 -2
  107. package/dist/core/commands/research-command.js +1 -1
  108. package/dist/core/commands/review-command.js +217 -0
  109. package/dist/core/commands/route-command.js +62 -0
  110. package/dist/core/commands/route-success-helpers.js +59 -0
  111. package/dist/core/commands/run-command.js +19 -7
  112. package/dist/core/commands/seo-command.js +49 -1
  113. package/dist/core/commands/status-command.js +21 -1
  114. package/dist/core/commands/team-legacy-observe-command.js +221 -3
  115. package/dist/core/commands/ui-command.js +161 -0
  116. package/dist/core/commands/uninstall-command.js +312 -0
  117. package/dist/core/db-safety.js +7 -3
  118. package/dist/core/doctor/codex-startup-config-repair.js +14 -3
  119. package/dist/core/doctor/confirm-repair.js +27 -0
  120. package/dist/core/doctor/context7-mcp-repair.js +35 -7
  121. package/dist/core/doctor/doctor-codex-startup-repair.js +10 -3
  122. package/dist/core/doctor/doctor-context7-repair.js +17 -4
  123. package/dist/core/doctor/doctor-dirty-planner.js +27 -9
  124. package/dist/core/doctor/doctor-native-capability-repair.js +12 -2
  125. package/dist/core/doctor/doctor-readiness-matrix.js +27 -2
  126. package/dist/core/doctor/doctor-repair-postcheck.js +4 -0
  127. package/dist/core/doctor/doctor-transaction.js +21 -5
  128. package/dist/core/doctor/doctor-zellij-repair.js +1 -0
  129. package/dist/core/doctor/imagegen-repair.js +161 -0
  130. package/dist/core/doctor/supabase-mcp-repair.js +23 -5
  131. package/dist/core/feature-fixture-runner.js +2 -2
  132. package/dist/core/feature-fixtures.js +65 -37
  133. package/dist/core/feature-registry.js +106 -3
  134. package/dist/core/fsx.js +91 -2
  135. package/dist/core/hooks-runtime/skill-reconcile-preflight.js +43 -0
  136. package/dist/core/hooks-runtime.js +86 -46
  137. package/dist/core/image-ux-review/imagegen-adapter.js +48 -11
  138. package/dist/core/image-ux-review.js +16 -0
  139. package/dist/core/imagegen/imagegen-capability.js +11 -5
  140. package/dist/core/imagegen/require-imagegen.js +57 -0
  141. package/dist/core/init/skills.js +271 -14
  142. package/dist/core/init.js +13 -10
  143. package/dist/core/mad-db/mad-db-coordinator.js +96 -20
  144. package/dist/core/mad-db/mad-db-policy.js +12 -10
  145. package/dist/core/mad-sks/executors/executor-base.js +8 -2
  146. package/dist/core/mad-sks/executors/index.js +4 -0
  147. package/dist/core/mad-sks/executors/sql-plane-executor.js +194 -0
  148. package/dist/core/mission.js +138 -5
  149. package/dist/core/naruto/naruto-active-pool.js +84 -30
  150. package/dist/core/naruto/naruto-backpressure.js +5 -1
  151. package/dist/core/naruto/naruto-real-worker-child.js +10 -0
  152. package/dist/core/naruto/naruto-real-worker-runtime.js +9 -7
  153. package/dist/core/naruto/naruto-role-policy.js +3 -0
  154. package/dist/core/naruto/naruto-task-hints.js +10 -0
  155. package/dist/core/naruto/naruto-work-graph.js +8 -2
  156. package/dist/core/naruto/naruto-work-item.js +6 -0
  157. package/dist/core/naruto/resource-pressure-monitor.js +33 -15
  158. package/dist/core/naruto/solution-tournament.js +101 -0
  159. package/dist/core/permission-gates.js +30 -0
  160. package/dist/core/pipeline-internals/runtime-core.js +72 -222
  161. package/dist/core/pipeline-internals/runtime-gates.js +140 -24
  162. package/dist/core/ppt-review/index.js +6 -1
  163. package/dist/core/ppt-review/slide-imagegen-review.js +75 -10
  164. package/dist/core/ppt.js +70 -2
  165. package/dist/core/proof/auto-finalize.js +70 -11
  166. package/dist/core/proof/proof-schema.js +2 -0
  167. package/dist/core/proof/route-adapter.js +5 -1
  168. package/dist/core/proof/route-finalizer.js +8 -5
  169. package/dist/core/proof/selftest-proof-fixtures.js +18 -5
  170. package/dist/core/proof/validation.js +2 -0
  171. package/dist/core/provider/model-router.js +53 -0
  172. package/dist/core/questions.js +1 -1
  173. package/dist/core/recallpulse.js +1 -1
  174. package/dist/core/release/gate-manifest.js +2 -2
  175. package/dist/core/release/release-gate-affected-selector.js +3 -10
  176. package/dist/core/release/release-gate-batch-runner.js +4 -2
  177. package/dist/core/release/release-gate-cache-v2.js +27 -14
  178. package/dist/core/release/release-gate-dag.js +6 -1
  179. package/dist/core/release/release-gate-hermetic-env.js +10 -0
  180. package/dist/core/release/release-gate-node.js +3 -0
  181. package/dist/core/release/release-gate-resource-governor.js +1 -0
  182. package/dist/core/retention.js +89 -4
  183. package/dist/core/routes/constants.js +1 -1
  184. package/dist/core/routes/diagnostic-allowlist.js +55 -0
  185. package/dist/core/routes.js +83 -33
  186. package/dist/core/safety/mutation-guard.js +5 -1
  187. package/dist/core/skill-forge.js +9 -4
  188. package/dist/core/stop-gate/gate-evaluator.js +102 -0
  189. package/dist/core/stop-gate/stop-gate-check.js +26 -4
  190. package/dist/core/stop-gate/stop-gate-resolver.js +19 -3
  191. package/dist/core/stop-gate/stop-gate-writer.js +20 -1
  192. package/dist/core/team-dag.js +12 -465
  193. package/dist/core/team-dashboard-renderer.js +13 -94
  194. package/dist/core/team-live.js +68 -804
  195. package/dist/core/triwiki/agents-md-projector.js +184 -0
  196. package/dist/core/triwiki-wrongness/wrongness-schema.js +3 -1
  197. package/dist/core/trust-kernel/trust-kernel-schema.js +1 -0
  198. package/dist/core/trust-kernel/trust-report.js +1 -1
  199. package/dist/core/trust-kernel/trust-status.js +2 -0
  200. package/dist/core/ui/dashboard-html.js +111 -0
  201. package/dist/core/update/update-migration-state.js +383 -42
  202. package/dist/core/update-check.js +201 -78
  203. package/dist/core/verification/diff-quality.js +100 -0
  204. package/dist/core/verification/impact-scan.js +164 -0
  205. package/dist/core/verification/machine-feedback.js +146 -0
  206. package/dist/core/verification/mistake-rule-compiler.js +195 -0
  207. package/dist/core/version.js +1 -1
  208. package/dist/core/zellij/zellij-layout-builder.js +44 -16
  209. package/dist/core/zellij/zellij-monitor-renderer.js +53 -0
  210. package/dist/core/zellij/zellij-self-heal.js +27 -32
  211. package/dist/core/zellij/zellij-slot-pane-renderer.js +162 -153
  212. package/dist/core/zellij/zellij-slot-telemetry.js +2 -0
  213. package/dist/core/zellij/zellij-theme.js +67 -0
  214. package/dist/core/zellij/zellij-ui-mode.js +16 -0
  215. package/dist/core/zellij/zellij-viewport-binder.js +59 -0
  216. package/dist/core/zellij/zellij-worker-pane-manager.js +53 -5
  217. package/dist/scripts/agent-patch-swarm-gate-lib.js +2 -2
  218. package/dist/scripts/build-dist.js +8 -0
  219. package/dist/scripts/check-feature-quality.js +2 -2
  220. package/dist/scripts/cli-output-consistency-check.js +57 -0
  221. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +106 -0
  222. package/dist/scripts/codex-lb-gpt55-fast-profile-check.js +105 -0
  223. package/dist/scripts/codex-lb-missing-env-regression.js +2 -3
  224. package/dist/scripts/codex-project-config-policy-merge-regression.js +3 -3
  225. package/dist/scripts/coding-bench-check.js +136 -0
  226. package/dist/scripts/concurrent-session-collision-check.js +67 -0
  227. package/dist/scripts/docs-truthfulness-check.js +1 -1
  228. package/dist/scripts/doctor-imagegen-repair-check.js +62 -0
  229. package/dist/scripts/ensure-bin-executable.js +11 -3
  230. package/dist/scripts/gate-policy-audit-check.js +130 -0
  231. package/dist/scripts/harness-benchmark-check.js +104 -0
  232. package/dist/scripts/hook-latency-budget-check.js +45 -0
  233. package/dist/scripts/legacy-update-e2e-check.js +228 -0
  234. package/dist/scripts/lib/codex-sdk-gate-lib.js +2 -2
  235. package/dist/scripts/lib/real-codex-parallel-gate.js +2 -2
  236. package/dist/scripts/loop-directive-check-lib.js +1 -1
  237. package/dist/scripts/mad-db-command-check.js +11 -8
  238. package/dist/scripts/mad-db-real-supabase-e2e.js +2 -2
  239. package/dist/scripts/mad-db-route-identity-check.js +8 -6
  240. package/dist/scripts/mad-db-safety-conflict-matrix-check.js +31 -8
  241. package/dist/scripts/mad-db-skill-policy-snapshot-check.js +4 -5
  242. package/dist/scripts/mad-sks-zellij-default-pane-worker-check.js +3 -2
  243. package/dist/scripts/mad-sks-zellij-launch-check.js +1 -1
  244. package/dist/scripts/naruto-zellij-dynamic-right-column-check.js +7 -7
  245. package/dist/scripts/parallel-claim-enforcement-check.js +14 -5
  246. package/dist/scripts/ppt-real-imagegen-wiring-check.js +5 -1
  247. package/dist/scripts/project-skill-dedupe-check.js +23 -5
  248. package/dist/scripts/proof-root-cause-policy-check.js +2 -0
  249. package/dist/scripts/release-affected-selector-check.js +2 -2
  250. package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
  251. package/dist/scripts/release-dag-full-coverage-check.js +13 -4
  252. package/dist/scripts/release-gate-dag-runner-check.js +10 -2
  253. package/dist/scripts/release-gate-dag-runner.js +22 -0
  254. package/dist/scripts/release-gate-existence-audit.js +2 -1
  255. package/dist/scripts/release-gate-planner.js +2 -1
  256. package/dist/scripts/release-gate-script-parity-check.js +1 -1
  257. package/dist/scripts/release-metadata-1-19-check.js +2 -1
  258. package/dist/scripts/release-readiness-report.js +38 -7
  259. package/dist/scripts/release-stability-report-check.js +12 -8
  260. package/dist/scripts/search-visibility-gate-lib.js +2 -2
  261. package/dist/scripts/seo-geo-feature-fixture-quality-check.js +1 -1
  262. package/dist/scripts/skills-manifest-continuity-check.js +46 -0
  263. package/dist/scripts/sks-1-11-gate-lib.js +8 -6
  264. package/dist/scripts/sks-menubar-install-check.js +87 -21
  265. package/dist/scripts/sks-uninstall-regression-check.js +54 -0
  266. package/dist/scripts/uninstall-inventory-check.js +3 -0
  267. package/dist/scripts/ux-review-real-loop-fixture-check.js +9 -4
  268. package/dist/scripts/ux-review-run-wires-imagegen-check.js +4 -0
  269. package/dist/scripts/zellij-layout-valid-check.js +18 -11
  270. package/dist/scripts/zellij-right-column-geometry-proof.js +2 -4
  271. package/dist/scripts/zellij-slot-pane-renderer-check.js +9 -9
  272. package/dist/scripts/zellij-slot-pane-stale-detection-check.js +3 -4
  273. package/dist/scripts/zellij-slot-pane-telemetry-renderer-check.js +3 -2
  274. package/dist/scripts/zellij-slot-telemetry-renderer-check.js +4 -2
  275. package/dist/scripts/zellij-spawn-on-demand-layout-check.js +8 -2
  276. package/dist/scripts/zellij-viewport-binder-check.js +9 -0
  277. package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
  278. package/docs/demo.tape +28 -0
  279. package/package.json +70 -3
  280. package/schemas/codex/completion-proof.schema.json +3 -2
  281. package/schemas/release/release-gate-node.schema.json +2 -1
  282. package/dist/scripts/agent-backfill-route-blackbox.js +0 -5
  283. package/dist/scripts/agent-dynamic-pool-route-blackbox.js +0 -5
  284. package/dist/scripts/agent-parallel-write-blackbox.js +0 -56
  285. package/dist/scripts/agent-patch-swarm-route-blackbox.js +0 -10
  286. package/dist/scripts/agent-route-blackbox-lib.js +0 -132
  287. package/dist/scripts/blackbox-command-import-smoke.js +0 -143
  288. package/dist/scripts/blackbox-global-shim.js +0 -77
  289. package/dist/scripts/blackbox-matrix.js +0 -70
  290. package/dist/scripts/blackbox-npx-one-shot.js +0 -69
  291. package/dist/scripts/blackbox-pack-install.js +0 -174
  292. package/dist/scripts/brand-neutrality-zero-leakage-blackbox.js +0 -4
  293. package/dist/scripts/build-once-runner-blackbox.js +0 -34
  294. package/dist/scripts/codex-0140-integration-blackbox.js +0 -13
  295. package/dist/scripts/codex-agent-type-blackbox.js +0 -4
  296. package/dist/scripts/codex-app-harness-blackbox.js +0 -4
  297. package/dist/scripts/codex-app-skill-agent-blackbox.js +0 -4
  298. package/dist/scripts/codex-hook-approval-blackbox.js +0 -4
  299. package/dist/scripts/codex-init-deep-directory-local-blackbox.js +0 -4
  300. package/dist/scripts/codex-native-feature-broker-blackbox.js +0 -4
  301. package/dist/scripts/codex-native-pattern-analysis-blackbox.js +0 -4
  302. package/dist/scripts/codex-native-read-repair-split-blackbox.js +0 -55
  303. package/dist/scripts/codex-native-reference-cache-blackbox.js +0 -41
  304. package/dist/scripts/core-skill-integrity-blackbox.js +0 -33
  305. package/dist/scripts/dfix-fast-blackbox-check.js +0 -37
  306. package/dist/scripts/dfix-parallel-write-blackbox.js +0 -48
  307. package/dist/scripts/dfix-patch-swarm-route-blackbox.js +0 -10
  308. package/dist/scripts/doctor-context7-mcp-repair-blackbox.js +0 -16
  309. package/dist/scripts/doctor-dirty-repair-blackbox.js +0 -22
  310. package/dist/scripts/doctor-dirty-semantic-blackbox.js +0 -8
  311. package/dist/scripts/doctor-fix-production-blackbox.js +0 -26
  312. package/dist/scripts/doctor-native-capability-repair-blackbox.js +0 -39
  313. package/dist/scripts/doctor-startup-config-repair-blackbox.js +0 -13
  314. package/dist/scripts/doctor-supabase-mcp-repair-blackbox.js +0 -14
  315. package/dist/scripts/doctor-transaction-engine-blackbox.js +0 -28
  316. package/dist/scripts/doctor-zellij-fix-blackbox.js +0 -4
  317. package/dist/scripts/doctor-zellij-no-homebrew-blackbox.js +0 -4
  318. package/dist/scripts/doctor-zellij-upgrade-blackbox.js +0 -4
  319. package/dist/scripts/gate-pack-runner-blackbox.js +0 -27
  320. package/dist/scripts/gate-pack-v2-blackbox.js +0 -18
  321. package/dist/scripts/geo-cli-blackbox-check.js +0 -18
  322. package/dist/scripts/loop-collision-blackbox.js +0 -3
  323. package/dist/scripts/loop-concurrency-oversubscription-blackbox.js +0 -3
  324. package/dist/scripts/loop-fixture-production-misuse-blackbox.js +0 -3
  325. package/dist/scripts/loop-kill-interrupt-real-blackbox.js +0 -3
  326. package/dist/scripts/loop-merge-strategy-blackbox.js +0 -3
  327. package/dist/scripts/loop-mesh-production-e2e-blackbox.js +0 -3
  328. package/dist/scripts/loop-side-effect-blackbox.js +0 -3
  329. package/dist/scripts/mad-db-operation-lifecycle-blackbox.js +0 -29
  330. package/dist/scripts/mad-sks-actual-executor-blackbox.js +0 -5
  331. package/dist/scripts/mad-zellij-headless-fallback-blackbox.js +0 -4
  332. package/dist/scripts/mad-zellij-self-heal-blackbox.js +0 -4
  333. package/dist/scripts/naruto-loop-mesh-blackbox.js +0 -3
  334. package/dist/scripts/naruto-real-parallelism-blackbox.js +0 -307
  335. package/dist/scripts/naruto-worktree-coding-blackbox.js +0 -29
  336. package/dist/scripts/parallel-runtime-real-blackbox.js +0 -44
  337. package/dist/scripts/pipeline-codex-native-doctor-mad-routing-real-blackbox.js +0 -77
  338. package/dist/scripts/pipeline-codex-native-e2e-blackbox.js +0 -13
  339. package/dist/scripts/pipeline-codex-native-image-routing-real-blackbox.js +0 -50
  340. package/dist/scripts/pipeline-codex-native-loop-routing-real-blackbox.js +0 -74
  341. package/dist/scripts/pipeline-codex-native-qa-routing-real-blackbox.js +0 -51
  342. package/dist/scripts/pipeline-codex-native-research-routing-real-blackbox.js +0 -45
  343. package/dist/scripts/pipeline-execution-profile-routing-blackbox.js +0 -4
  344. package/dist/scripts/postinstall-global-doctor-blackbox.js +0 -12
  345. package/dist/scripts/ppt-full-e2e-blackbox-check.js +0 -109
  346. package/dist/scripts/ppt-imagegen-blackbox-check.js +0 -46
  347. package/dist/scripts/project-skill-dedupe-blackbox.js +0 -36
  348. package/dist/scripts/qa-backfill-route-blackbox.js +0 -5
  349. package/dist/scripts/qa-patch-swarm-route-blackbox.js +0 -10
  350. package/dist/scripts/release-full-parallelism-blackbox.js +0 -41
  351. package/dist/scripts/release-triwiki-first-runner-blackbox.js +0 -48
  352. package/dist/scripts/release-wiring-3110-blackbox.js +0 -27
  353. package/dist/scripts/release-wiring-3112-blackbox.js +0 -17
  354. package/dist/scripts/release-wiring-3113-blackbox.js +0 -17
  355. package/dist/scripts/research-backfill-route-blackbox.js +0 -5
  356. package/dist/scripts/research-final-reviewer-blackbox.js +0 -70
  357. package/dist/scripts/research-stage-cycle-runtime-blackbox.js +0 -40
  358. package/dist/scripts/research-synthesis-writer-blackbox.js +0 -24
  359. package/dist/scripts/route-blackbox-realism-check.js +0 -21
  360. package/dist/scripts/scheduler-resource-claim-blackbox.js +0 -24
  361. package/dist/scripts/seo-cli-blackbox-check.js +0 -18
  362. package/dist/scripts/sks-3110-all-feature-regression-blackbox.js +0 -116
  363. package/dist/scripts/sks-3112-all-feature-regression-blackbox.js +0 -29
  364. package/dist/scripts/sks-3113-all-feature-regression-blackbox.js +0 -17
  365. package/dist/scripts/sks-400-all-feature-regression-blackbox.js +0 -21
  366. package/dist/scripts/sks-400-extreme-parallel-blackbox.js +0 -8
  367. package/dist/scripts/sks-400-five-minute-blackbox.js +0 -9
  368. package/dist/scripts/sks-400-legacy-purge-blackbox.js +0 -8
  369. package/dist/scripts/sks-401-all-feature-regression-blackbox.js +0 -46
  370. package/dist/scripts/sks-401-five-minute-actual-blackbox.js +0 -23
  371. package/dist/scripts/sks-402-all-feature-regression-blackbox.js +0 -9
  372. package/dist/scripts/sks-402-five-minute-real-blackbox.js +0 -22
  373. package/dist/scripts/sksd-warm-cache-blackbox.js +0 -12
  374. package/dist/scripts/supabase-secret-preservation-blackbox.js +0 -29
  375. package/dist/scripts/team-backfill-route-blackbox.js +0 -5
  376. package/dist/scripts/team-parallel-write-blackbox.js +0 -55
  377. package/dist/scripts/team-patch-swarm-route-blackbox.js +0 -10
  378. package/dist/scripts/triwiki-affected-graph-blackbox.js +0 -28
  379. package/dist/scripts/triwiki-proof-bank-blackbox.js +0 -30
  380. package/dist/scripts/triwiki-proof-bank-lock-blackbox.js +0 -7
  381. package/dist/scripts/update-preserves-supabase-keys-blackbox.js +0 -27
  382. package/dist/scripts/ux-patch-swarm-route-blackbox.js +0 -10
  383. package/dist/scripts/ux-review-imagegen-blackbox-check.js +0 -67
  384. package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -28
  385. package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -80
  386. package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -137
  387. package/dist/scripts/zellij-self-heal-typed-blackbox.js +0 -4
  388. package/dist/scripts/zellij-slot-telemetry-real-blackbox.js +0 -20
  389. package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -81
  390. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -202
@@ -8,17 +8,21 @@ import { createRequestedScopeContract } from '../core/safety/requested-scope-con
8
8
  import { guardedPackageInstall, guardContextForRoute } from '../core/safety/mutation-guard.js';
9
9
  import { EMPTY_CODEX_INFO, getCodexInfo } from '../core/codex-adapter.js';
10
10
  import { formatHarnessConflictReport, llmHarnessCleanupPrompt, scanHarnessConflicts } from '../core/harness-conflicts.js';
11
- import { initProject, installSkills } from '../core/init.js';
11
+ import { initProject, installGlobalSkills } from '../core/init.js';
12
12
  import { context7ConfigToml, DOLLAR_SKILL_NAMES, GETDESIGN_REFERENCE, hasContext7ConfigText, RECOMMENDED_SKILLS } from '../core/routes.js';
13
13
  import { checkZellijCapability } from '../core/zellij/zellij-capability.js';
14
14
  import { reconcileCodexAppUpgradeProcesses } from '../core/codex-app.js';
15
15
  import { restartCodexApp } from '../core/codex-app/codex-app-restart.js';
16
+ import { cleanupMacLaunchSecretEnvironment } from '../core/codex-app/sks-menubar.js';
16
17
  import { recordCodexLbHealthEvent } from '../core/codex-lb-circuit.js';
17
18
  import { loadCodexLbEnv, writeCodexLbKeychain, codexLbMetadataPath } from '../core/codex-lb/codex-lb-env.js';
18
19
  import { GLM_CODEX_CONFIG_PROFILE_ID, GLM_CODEX_CONFIG_PROVIDER_ID, GLM_CODEX_CONFIG_REASONING_PROFILES } from '../core/providers/glm/glm-52-profile.js';
19
20
  import { GLM_52_OPENROUTER_MODEL } from '../core/providers/glm/glm-52-settings.js';
20
21
  import { buildCodexLbSetupPlan, codexLbPersistenceSummary, installCodexLbShellProfileSnippet, selectedCodexLbPersistenceModes } from '../core/codex-lb/codex-lb-setup.js';
22
+ import { extractTomlTable, writeCodexConfigGuarded } from '../core/codex/codex-config-guard.js';
23
+ import { cleanupCodexConfigBackups, validateCodexConfigRoundTrip } from '../core/codex/codex-config-toml.js';
21
24
  import { runPostinstallGlobalDoctorAndMarkPending } from '../core/update/update-migration-state.js';
25
+ import { repairCodexImagegen } from '../core/doctor/imagegen-repair.js';
22
26
  const CODEX_LB_PROVIDER_NAME = 'openai';
23
27
  const CODEX_LB_PROVIDER_ENV_KEY = 'CODEX_LB_API_KEY';
24
28
  const CODEX_LB_CANONICAL_FAST_SERVICE_TIER = 'priority';
@@ -87,6 +91,15 @@ export async function postinstall({ bootstrap, args = [] }) {
87
91
  console.log(`Codex App Fast mode: skipped (${fastModeRepair.reason}).`);
88
92
  else if (fastModeRepair.status === 'failed')
89
93
  console.log(`Codex App Fast mode: auto repair failed. Run \`sks setup\`. ${fastModeRepair.error || ''}`.trim());
94
+ const imagegenRepair = await ensureCodexImagegenDuringInstall();
95
+ if (imagegenRepair.status === 'ready')
96
+ console.log('Codex App Image Gen: ready ($imagegen/gpt-image-2 detected).');
97
+ else if (imagegenRepair.status === 'recovered')
98
+ console.log('Codex App Image Gen: recovered and re-detected.');
99
+ else if (imagegenRepair.status === 'blocked')
100
+ console.log(`Codex App Image Gen: blocked; run \`sks doctor --fix\`. ${(imagegenRepair.blockers || []).join(', ')}`.trim());
101
+ else if (imagegenRepair.status === 'skipped')
102
+ console.log(`Codex App Image Gen: skipped (${imagegenRepair.reason}).`);
90
103
  const postinstallDoctor = await runPostinstallGlobalDoctorAndMarkPending().catch((err) => ({
91
104
  ok: false,
92
105
  doctor: null,
@@ -397,7 +410,7 @@ export async function configureCodexLb(opts = {}) {
397
410
  const useDefaultProvider = opts.useDefaultProvider !== false;
398
411
  const writeEnvFile = opts.writeEnvFile !== false;
399
412
  const storeKeychain = opts.storeKeychain === true || opts.keychain === true;
400
- const syncLaunchctl = opts.syncLaunchctl !== false && opts.syncLaunchEnv !== false;
413
+ const syncLaunchctl = opts.syncLaunchctl === true || opts.syncLaunchEnv === true;
401
414
  const shellProfile = opts.shellProfile || 'skip';
402
415
  const setupAnswers = {
403
416
  host_or_base_url: rawHost,
@@ -464,7 +477,7 @@ export async function configureCodexLb(opts = {}) {
464
477
  appliedActions.push({ type: 'store_keychain', target: 'macOS Keychain service sks-codex-lb', ok: keychain.ok === true, status: keychain.status });
465
478
  const codexEnvironment = await syncCodexLbProviderEnvironment({ env_path: envPath, base_url: baseUrl }, { ...opts, home, apiKey, baseUrl, syncLaunchEnv: syncLaunchctl });
466
479
  if (syncLaunchctl)
467
- appliedActions.push({ type: 'sync_launchctl', target: 'macOS launchctl user environment', ok: codexEnvironment.ok === true, status: codexEnvironment.status });
480
+ appliedActions.push({ type: 'sync_launchctl', target: 'macOS launchctl user environment (base URL only; API-key env removed)', ok: codexEnvironment.ok === true, status: codexEnvironment.status });
468
481
  const shellProfileResult = await installCodexLbShellProfileSnippet({ home, envPath, shellProfile }).catch((err) => ({ ok: false, status: 'failed', files: [], error: err.message }));
469
482
  if (shellProfile !== 'skip')
470
483
  appliedActions.push({ type: 'install_shell_profile_snippet', target: shellProfileResult.files?.join(', ') || shellProfile, ok: shellProfileResult.ok === true, status: shellProfileResult.status });
@@ -979,6 +992,10 @@ function topLevelTomlString(text = '', key) {
979
992
  const topLevel = String(text || '').split(/\n\s*\[/)[0] || '';
980
993
  return topLevel.match(new RegExp(`(^|\\n)\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]+)"\\s*(?:#.*)?(?=\\n|$)`))?.[2] || '';
981
994
  }
995
+ function tomlTableString(text = '', table, key) {
996
+ const block = String(text || '').match(new RegExp(`(^|\\n)\\[${escapeRegExp(table)}\\]([\\s\\S]*?)(?=\\n\\[[^\\]]+\\]|\\s*$)`))?.[2] || '';
997
+ return block.match(new RegExp(`(^|\\n)\\s*${escapeRegExp(key)}\\s*=\\s*"([^"]+)"\\s*(?:#.*)?(?=\\n|$)`))?.[2] || '';
998
+ }
982
999
  export async function repairCodexLbAuth(opts = {}) {
983
1000
  let status = await codexLbStatus(opts);
984
1001
  let configRepaired = false;
@@ -995,7 +1012,11 @@ export async function repairCodexLbAuth(opts = {}) {
995
1012
  }
996
1013
  if (status.env_key_configured && status.base_url && (!status.provider_contract_ok || !status.selected || legacyAuthMigrated || hasTopLevelCodexModeLock(currentConfig) || (opts.forceCodexLbApiKeyAuth === true && !status.ok))) {
997
1014
  await ensureDir(path.dirname(status.config_path));
998
- const next = normalizeCodexFastModeUiConfig(upsertCodexLbConfig(currentConfig, status.base_url), {
1015
+ const preservedUserFastMode = extractTomlTable(currentConfig, 'user.fast_mode');
1016
+ let next = upsertCodexLbConfig(currentConfig, status.base_url);
1017
+ if (preservedUserFastMode)
1018
+ next = upsertTomlTable(next, 'user.fast_mode', preservedUserFastMode);
1019
+ next = normalizeCodexFastModeUiConfig(next, {
999
1020
  forceFastMode: opts.forceFastMode === true || opts.forceCodexLbApiKeyAuth === true
1000
1021
  });
1001
1022
  const safeWrite = await safeWriteCodexConfigToml(status.config_path, currentConfig, next, 'codex-lb-repair');
@@ -1337,8 +1358,8 @@ export async function unselectCodexLbProvider(opts = {}) {
1337
1358
  return { status: 'not_selected', config_path: configPath };
1338
1359
  try {
1339
1360
  const next = ensureTrailingNewline(removeTopLevelTomlString(current, 'model_provider'));
1340
- await writeTextAtomic(configPath, next);
1341
- return { status: 'unselected', config_path: configPath };
1361
+ const safeWrite = await safeWriteCodexConfigToml(configPath, current, next, 'codex-lb-unselect');
1362
+ return { status: safeWrite.ok ? 'unselected' : safeWrite.status, config_path: configPath, backup_path: safeWrite.backup_path };
1342
1363
  }
1343
1364
  catch (err) {
1344
1365
  return { status: 'failed', reason: 'write_failed', config_path: configPath, error: err.message };
@@ -1552,11 +1573,11 @@ async function syncCodexLbProviderEnvironment(status = {}, opts = {}) {
1552
1573
  process.env.CODEX_LB_API_KEY = apiKey;
1553
1574
  if (baseUrl)
1554
1575
  process.env.CODEX_LB_BASE_URL = baseUrl;
1555
- const launchEnv = await syncCodexLbMacLaunchEnvironment({ CODEX_LB_API_KEY: apiKey, ...(baseUrl ? { CODEX_LB_BASE_URL: baseUrl } : {}) }, opts);
1576
+ const launchEnv = await syncCodexLbMacLaunchEnvironment(baseUrl ? { CODEX_LB_BASE_URL: baseUrl } : {}, opts);
1556
1577
  const ok = launchEnv.ok || launchEnv.skipped || launchEnv.status === 'not_macos';
1557
1578
  return {
1558
1579
  ok,
1559
- status: launchEnv.status === 'synced' ? 'synced' : ok ? 'process_env' : launchEnv.status,
1580
+ status: launchEnv.status === 'synced' ? 'launch_base_url_synced_secret_env_removed' : ok ? 'process_env' : launchEnv.status,
1560
1581
  env_path: envPath,
1561
1582
  base_url: baseUrl || null,
1562
1583
  launch_environment: launchEnv,
@@ -1571,7 +1592,15 @@ async function syncCodexLbMacLaunchEnvironment(values = {}, opts = {}) {
1571
1592
  const launchctl = opts.launchctlBin || await which('launchctl').catch(() => null) || await exists('/bin/launchctl').then((ok) => ok ? '/bin/launchctl' : null).catch(() => null);
1572
1593
  if (!launchctl)
1573
1594
  return { ok: false, status: 'launchctl_missing', error: 'launchctl not found on PATH' };
1574
- const variables = Object.entries(values).filter(([, value]) => value);
1595
+ const secretCleanup = await cleanupMacLaunchSecretEnvironment({ force: opts.forceLaunchEnv === true }).catch((err) => ({
1596
+ ok: false,
1597
+ status: 'partial',
1598
+ variables: ['CODEX_LB_API_KEY', 'OPENROUTER_API_KEY'],
1599
+ cleaned: [],
1600
+ failed: [{ key: 'CODEX_LB_API_KEY', error: err?.message || String(err) }, { key: 'OPENROUTER_API_KEY', error: err?.message || String(err) }],
1601
+ next_actions: ['Run launchctl unsetenv for CODEX_LB_API_KEY and OPENROUTER_API_KEY']
1602
+ }));
1603
+ const variables = Object.entries(values).filter(([key, value]) => value && !['CODEX_LB_API_KEY', 'OPENROUTER_API_KEY'].includes(String(key)));
1575
1604
  const results = [];
1576
1605
  for (const [key, value] of variables) {
1577
1606
  const result = await runProcess(launchctl, ['setenv', key, String(value)], { timeoutMs: 5000, maxOutputBytes: 8192 });
@@ -1583,8 +1612,14 @@ async function syncCodexLbMacLaunchEnvironment(values = {}, opts = {}) {
1583
1612
  }
1584
1613
  const failed = results.filter((result) => !result.ok);
1585
1614
  if (failed.length)
1586
- return { ok: false, status: 'launch_env_failed', variables: results.map((result) => result.key), failed, error: failed.map((result) => `${result.key}: ${result.error}`).join('; ') };
1587
- return { ok: true, status: 'synced', variables: results.map((result) => result.key) };
1615
+ return { ok: false, status: 'launch_env_failed', variables: results.map((result) => result.key), failed, secret_env_cleanup: secretCleanup, error: failed.map((result) => `${result.key}: ${result.error}`).join('; ') };
1616
+ return {
1617
+ ok: secretCleanup.ok !== false,
1618
+ status: variables.length ? 'synced' : 'secret_env_removed',
1619
+ variables: results.map((result) => result.key),
1620
+ skipped_secret_variables: ['CODEX_LB_API_KEY', 'OPENROUTER_API_KEY'],
1621
+ secret_env_cleanup: secretCleanup
1622
+ };
1588
1623
  }
1589
1624
  async function inspectCodexLbMacLaunchEnvironment(baseUrl = '', opts = {}) {
1590
1625
  if (process.platform !== 'darwin' && !opts.forceLaunchEnv)
@@ -1598,20 +1633,33 @@ async function inspectCodexLbMacLaunchEnvironment(baseUrl = '', opts = {}) {
1598
1633
  };
1599
1634
  const currentBaseUrl = await readVar('CODEX_LB_BASE_URL');
1600
1635
  const currentApiKey = await readVar('CODEX_LB_API_KEY');
1636
+ const currentOpenRouterKey = await readVar('OPENROUTER_API_KEY');
1601
1637
  const baseMatches = !baseUrl || currentBaseUrl === String(baseUrl || '').trim();
1602
1638
  const basePresent = Boolean(currentBaseUrl);
1603
1639
  const keyPresent = Boolean(currentApiKey);
1640
+ const openRouterKeyPresent = Boolean(currentOpenRouterKey);
1604
1641
  return {
1605
1642
  checked: true,
1606
1643
  available: true,
1607
- status: basePresent && keyPresent && baseMatches ? 'synced' : basePresent || keyPresent ? 'partial' : 'missing',
1644
+ status: keyPresent || openRouterKeyPresent
1645
+ ? 'secret_env_present'
1646
+ : basePresent && baseMatches
1647
+ ? 'base_url_only'
1648
+ : basePresent
1649
+ ? 'partial'
1650
+ : 'missing',
1608
1651
  variables: [
1609
1652
  ...(keyPresent ? ['CODEX_LB_API_KEY'] : []),
1653
+ ...(openRouterKeyPresent ? ['OPENROUTER_API_KEY'] : []),
1610
1654
  ...(basePresent ? ['CODEX_LB_BASE_URL'] : [])
1611
1655
  ],
1612
1656
  base_url_present: basePresent,
1613
1657
  base_url_matches: baseMatches,
1614
- api_key_present: keyPresent
1658
+ api_key_present: keyPresent,
1659
+ openrouter_api_key_present: openRouterKeyPresent,
1660
+ next_actions: keyPresent || openRouterKeyPresent
1661
+ ? ['Run: sks doctor --fix', 'Rotate CODEX_LB_API_KEY and OPENROUTER_API_KEY if they were exposed in launchd.']
1662
+ : []
1615
1663
  };
1616
1664
  }
1617
1665
  async function maybeSyncCodexLbSharedLogin(apiKey, opts = {}) {
@@ -1731,7 +1779,9 @@ function detectCodexLbSetupDrift(state = {}) {
1731
1779
  if (!state.storeKeychain && state.keychain?.status && state.keychain.status !== 'skipped')
1732
1780
  drift.push('keychain_touched_despite_no_keychain');
1733
1781
  if (!state.syncLaunchctl && state.codexEnvironment?.launch_environment?.status === 'synced')
1734
- drift.push('launchctl_synced_despite_no_launchctl');
1782
+ drift.push('launchctl_base_url_synced_despite_no_launchctl');
1783
+ if (state.codexEnvironment?.launch_environment?.secret_env_cleanup?.status === 'partial')
1784
+ drift.push('launchctl_secret_env_cleanup_incomplete');
1735
1785
  if (state.shellProfile === 'skip' && state.shellProfileResult?.status === 'installed')
1736
1786
  drift.push('shell_profile_written_despite_skip');
1737
1787
  if (state.shellProfile === 'skip' && state.beforeState && state.afterState && state.beforeState.profileHash !== state.afterState.profileHash)
@@ -1773,7 +1823,7 @@ function appliedCodexLbPersistenceModes(state = {}) {
1773
1823
  if (state.storeKeychain && state.keychain?.ok === true)
1774
1824
  modes.push('durable_keychain');
1775
1825
  if (state.syncLaunchctl && state.codexEnvironment?.launch_environment?.status === 'synced')
1776
- modes.push('durable_launchctl');
1826
+ modes.push('process_only_ephemeral');
1777
1827
  if (state.shellProfile !== 'skip' && state.shellProfileResult?.status === 'installed')
1778
1828
  modes.push('shell_profile');
1779
1829
  if (!modes.length && state.apiKeySource === 'process.env')
@@ -1805,14 +1855,13 @@ export async function ensureGlobalCodexFastModeDuringInstall(opts = {}) {
1805
1855
  });
1806
1856
  if (next === ensureTrailingNewline(current))
1807
1857
  return { status: 'present', config_path: configPath };
1808
- // Safety gate 2: never WRITE a config that would not parse.
1809
- const nextSmoke = codexConfigParseSmoke(next);
1810
- if (!nextSmoke.ok)
1811
- return { status: 'skipped_unsafe_rewrite', config_path: configPath, parse_smoke: nextSmoke };
1812
- // Safety gate 3: back up the user's good config before mutating it.
1813
- const backupPath = current.trim() ? await backupCodexConfig(configPath, current, 'pre-update') : null;
1814
- await writeTextAtomic(configPath, next);
1815
- return { status: 'updated', config_path: configPath, backup_path: backupPath };
1858
+ const safeWrite = await safeWriteCodexConfigToml(configPath, current, next, 'codex-fast-mode-install');
1859
+ return {
1860
+ status: safeWrite.status === 'written' ? 'updated' : safeWrite.status,
1861
+ config_path: configPath,
1862
+ backup_path: safeWrite.backup_path,
1863
+ parse_smoke: safeWrite.ok ? undefined : safeWrite
1864
+ };
1816
1865
  }
1817
1866
  catch (err) {
1818
1867
  return { status: 'failed', config_path: configPath, error: err.message };
@@ -1827,7 +1876,9 @@ function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
1827
1876
  // Keep model and reasoning selection out of top-level config so Codex Desktop can
1828
1877
  // expose its native model/speed selectors. SKS-owned defaults live in profiles below.
1829
1878
  let next = String(text || '');
1879
+ const misplacedDefaultProfile = tomlTableString(next, 'user.fast_mode', 'default_profile');
1830
1880
  next = removeLegacyTopLevelCodexModeLocks(next);
1881
+ next = removeTomlTableKey(next, 'user.fast_mode', 'default_profile');
1831
1882
  next = removeTomlTableKey(next, 'notice', 'fast_default_opt_out');
1832
1883
  next = removeTomlTableKey(next, 'features', 'codex_hooks');
1833
1884
  if (opts.forceFastMode === true) {
@@ -1846,19 +1897,25 @@ function normalizeCodexFastModeUiConfigOnce(text = '', opts = {}) {
1846
1897
  'fast_mode_ui = true', 'codex_git_commit = true', 'computer_use = true', 'browser_use = true',
1847
1898
  'browser_use_external = true', 'image_generation = true', 'in_app_browser = true',
1848
1899
  'guardian_approval = true', 'tool_suggest = true', 'apps = true', 'plugins = true'
1849
- ])
1850
- next = upsertTomlTableKeyIfAbsent(next, 'features', featureLine);
1900
+ ]) {
1901
+ const featureKey = featureLine.split('=')[0]?.trim();
1902
+ next = opts.forceFastMode === true && ['fast_mode', 'fast_mode_ui'].includes(String(featureKey || ''))
1903
+ ? upsertTomlTableKey(next, 'features', featureLine)
1904
+ : upsertTomlTableKeyIfAbsent(next, 'features', featureLine);
1905
+ }
1851
1906
  if (opts.forceFastMode === true || opts.forceFastModeOff === true) {
1852
1907
  next = upsertTomlTableKey(next, 'user.fast_mode', 'visible = true');
1853
1908
  next = upsertTomlTableKey(next, 'user.fast_mode', 'enabled = true');
1854
1909
  next = opts.forceFastMode === true
1855
- ? upsertTomlTableKey(next, 'user.fast_mode', 'default_profile = "sks-fast-high"')
1856
- : removeTomlTableKey(next, 'user.fast_mode', 'default_profile');
1910
+ ? upsertTopLevelTomlString(next, 'default_profile', 'sks-fast-high')
1911
+ : removeTopLevelTomlKeyIfValue(next, 'default_profile', 'sks-fast-high');
1857
1912
  }
1858
1913
  else {
1859
1914
  next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'visible = true');
1860
1915
  next = upsertTomlTableKeyIfAbsent(next, 'user.fast_mode', 'enabled = true');
1861
- next = removeTomlTableKey(next, 'user.fast_mode', 'default_profile');
1916
+ if (misplacedDefaultProfile === 'sks-fast-high') {
1917
+ next = upsertTopLevelTomlString(next, 'default_profile', 'sks-fast-high');
1918
+ }
1862
1919
  }
1863
1920
  // Keep ONLY the sks-fast-high config-profile table for explicit fast-mode opt-in
1864
1921
  // and CLI `--profile` use. The other SKS config profiles are
@@ -1955,6 +2012,8 @@ function upsertTomlTableKey(text, table, line) {
1955
2012
  return lines.join('\n').replace(/\n{3,}/g, '\n\n');
1956
2013
  }
1957
2014
  }
2015
+ if (hasTomlTableKey(lines.join('\n'), table, key))
2016
+ return lines.join('\n').replace(/\n{3,}/g, '\n\n');
1958
2017
  lines.splice(end, 0, line);
1959
2018
  return lines.join('\n').replace(/\n{3,}/g, '\n\n');
1960
2019
  }
@@ -2039,6 +2098,7 @@ async function backupCodexConfig(configPath, text, tag) {
2039
2098
  const stamp = `${PACKAGE_VERSION}-${Date.now().toString(36)}`;
2040
2099
  const backupPath = `${configPath}.sks-${tag}-${stamp}.bak`;
2041
2100
  await writeTextAtomic(backupPath, text);
2101
+ await cleanupCodexConfigBackups(configPath, { keepPerTag: 3, maxAgeMs: 30 * 24 * 60 * 60 * 1000 }).catch(() => undefined);
2042
2102
  return backupPath;
2043
2103
  }
2044
2104
  catch {
@@ -2052,20 +2112,32 @@ async function backupCodexConfig(configPath, text, tag) {
2052
2112
  // string), leaving the existing config untouched,
2053
2113
  // - otherwise back up the prior config before mutating.
2054
2114
  export async function safeWriteCodexConfigToml(configPath, current, next, tag = 'codex-lb') {
2055
- const cur = String(current || '');
2056
- if (cur.trim() && !codexConfigParseSmoke(cur).ok) {
2057
- const backupPath = await backupCodexConfig(configPath, cur, `${tag}-unparseable`);
2058
- return { ok: false, status: 'unparseable_config_preserved', config_path: configPath, backup_path: backupPath };
2059
- }
2060
- if (!codexConfigParseSmoke(next).ok) {
2061
- return { ok: false, status: 'skipped_unsafe_rewrite', config_path: configPath, backup_path: null };
2062
- }
2063
- if (next === ensureTrailingNewline(cur)) {
2064
- return { ok: true, status: 'present', config_path: configPath, backup_path: null, changed: false };
2065
- }
2066
- const backupPath = cur.trim() ? await backupCodexConfig(configPath, cur, tag) : null;
2067
- await writeTextAtomic(configPath, next);
2068
- return { ok: true, status: 'written', config_path: configPath, backup_path: backupPath, changed: true };
2115
+ return writeCodexConfigGuarded({
2116
+ configPath,
2117
+ before: String(current || ''),
2118
+ cause: tag,
2119
+ removeTopLevelModeLocks: true,
2120
+ mutate: () => String(next || '')
2121
+ });
2122
+ }
2123
+ export function codexFastModeDesktopStatus(text = '') {
2124
+ const validation = validateCodexConfigRoundTrip(String(text || ''));
2125
+ const profile = validation.parsed?.profiles?.['sks-fast-high'];
2126
+ const globalOn = validation.ok
2127
+ && validation.default_profile === 'sks-fast-high'
2128
+ && profile?.model === 'gpt-5.5'
2129
+ && profile?.service_tier === 'fast';
2130
+ return {
2131
+ schema: 'sks.codex-fast-mode-desktop-status.v1',
2132
+ ok: validation.ok,
2133
+ on: Boolean(globalOn),
2134
+ default_profile: validation.default_profile || null,
2135
+ top_level_default_profile: validation.top_level_default_profile === true,
2136
+ user_fast_mode_default_profile: validation.user_fast_mode_default_profile,
2137
+ profile_model: profile?.model || null,
2138
+ profile_service_tier: profile?.service_tier || null,
2139
+ validation
2140
+ };
2069
2141
  }
2070
2142
  function upsertTopLevelTomlBoolean(text, key, value) {
2071
2143
  const line = `${key} = ${value ? 'true' : 'false'}`;
@@ -2374,14 +2446,14 @@ export async function ensureGlobalCodexSkillsDuringInstall(opts = {}) {
2374
2446
  return { status: 'skipped', reason: 'home directory unavailable' };
2375
2447
  const root = globalCodexSkillsRoot(home);
2376
2448
  try {
2377
- const install = await installSkills(home);
2449
+ const install = await installGlobalSkills(home);
2378
2450
  const skills = await checkRequiredSkills(home, root);
2379
2451
  return {
2380
2452
  status: skills.ok ? 'installed' : 'partial',
2381
2453
  root,
2382
- installed_count: install.installed_skills.length,
2383
- removed_aliases: install.removed_agent_skill_aliases,
2384
- removed_stale_generated_skills: install.removed_stale_generated_skills,
2454
+ installed_count: install.installed.length,
2455
+ removed_aliases: [],
2456
+ removed_stale_generated_skills: install.removed,
2385
2457
  missing_skills: skills.missing
2386
2458
  };
2387
2459
  }
@@ -2407,6 +2479,28 @@ async function ensureGlobalGetdesignSkillDuringInstall() {
2407
2479
  return { status: 'present', command: skillsBin };
2408
2480
  return { status: 'failed', command: skillsBin, error: out.trim() || 'skills add failed' };
2409
2481
  }
2482
+ export async function ensureCodexImagegenDuringInstall(opts = {}) {
2483
+ if (process.env.SKS_POSTINSTALL_SKIP_IMAGEGEN_REPAIR === '1' || opts.skip === true) {
2484
+ return { status: 'skipped', reason: 'SKS_POSTINSTALL_SKIP_IMAGEGEN_REPAIR' };
2485
+ }
2486
+ const report = await repairCodexImagegen({
2487
+ root: opts.root || process.cwd(),
2488
+ apply: opts.apply !== false,
2489
+ codexBin: opts.codexBin || null,
2490
+ autoInstallCodex: opts.autoInstallCodex === true || process.env.SKS_IMAGEGEN_AUTO_INSTALL_CODEX === '1'
2491
+ }).catch((err) => ({
2492
+ recovered: false,
2493
+ blockers: [err?.message || String(err)],
2494
+ before: null,
2495
+ after: null
2496
+ }));
2497
+ if (report.before?.core_ready === true || (report.after?.core_ready === true && report.attempted === false)) {
2498
+ return { status: 'ready', report };
2499
+ }
2500
+ if (report.recovered === true)
2501
+ return { status: 'recovered', report };
2502
+ return { status: 'blocked', blockers: report.blockers || ['codex_imagegen_unavailable'], report };
2503
+ }
2410
2504
  export async function ensureRelatedCliTools(args = []) {
2411
2505
  const skip = args.includes('--skip-cli-tools') || process.env.SKS_SKIP_CLI_TOOLS === '1';
2412
2506
  const codex = await ensureCodexCliTool({ skip, args });
@@ -2685,7 +2779,13 @@ export async function ensureProjectContext7Config(root, transport = 'local') {
2685
2779
  }
2686
2780
  if (hasContext7ConfigText(current))
2687
2781
  return false;
2688
- await writeTextAtomic(configPath, `${current.trimEnd()}${current.trim() ? '\n\n' : ''}${block}\n`);
2782
+ await writeCodexConfigGuarded({
2783
+ root,
2784
+ configPath,
2785
+ before: current,
2786
+ cause: 'context7-project-config',
2787
+ mutate: () => `${current.trimEnd()}${current.trim() ? '\n\n' : ''}${block}\n`
2788
+ });
2689
2789
  return true;
2690
2790
  }
2691
2791
  export async function checkRequiredSkills(root, skillRoot = root ? path.join(root, '.agents', 'skills') : globalCodexSkillsRoot()) {
@@ -1,6 +1,8 @@
1
1
  import { COMMAND_ALIASES, COMMANDS, } from './command-registry.js';
2
2
  import { detectGlobalMode, glmWithoutMadResult } from './global-mode-router.js';
3
3
  import { ensureCurrentMigrationBeforeCommand } from '../core/update/update-migration-state.js';
4
+ import { projectRoot, readJson } from '../core/fsx.js';
5
+ import { stateFile } from '../core/mission.js';
4
6
  export function isCommandName(value) {
5
7
  return Object.prototype.hasOwnProperty.call(COMMANDS, value);
6
8
  }
@@ -49,15 +51,29 @@ export async function dispatch(args) {
49
51
  return result;
50
52
  }
51
53
  const entry = COMMANDS[command];
52
- const migrationGate = await ensureCurrentMigrationBeforeCommand({ command, args: rest });
54
+ const commandGate = await ensureActiveRouteCommandGate(command, rest);
55
+ if (!commandGate.ok) {
56
+ console.error(commandGate.message);
57
+ process.exitCode = 1;
58
+ return commandGate;
59
+ }
60
+ const migrationGate = await ensureCurrentMigrationBeforeCommand({
61
+ command,
62
+ args: rest,
63
+ skipMigrationGate: entry.skipMigrationGate === true || entry.readonly === true
64
+ });
53
65
  if (!migrationGate.ok) {
54
66
  console.error('SKS project migration blocked.');
67
+ console.error(`Scope: ${migrationGate.scope || 'project'}`);
68
+ console.error(`Stage: ${migrationGate.failed_stage_id || migrationGate.status}`);
69
+ if (migrationGate.failed_stage_id)
70
+ console.error(`Failed stage: ${migrationGate.failed_stage_id}`);
55
71
  for (const blocker of migrationGate.blockers)
56
72
  console.error(`Required blocker: ${blocker}`);
57
73
  for (const warning of migrationGate.warnings)
58
74
  console.error(`Optional warning: ${warning}`);
59
75
  console.error(`Receipt: ${migrationGate.receipt_path}`);
60
- console.error('Run: sks doctor --fix --yes');
76
+ console.error('Remedies: run `sks doctor --fix --yes`, then retry; diagnostics that must bypass this gate are marked skipMigrationGate in the command registry.');
61
77
  process.exitCode = 1;
62
78
  return migrationGate;
63
79
  }
@@ -66,4 +82,44 @@ export async function dispatch(args) {
66
82
  throw new Error(`Command ${command} must export run(command, args)`);
67
83
  return mod.run(rawCommand || command, rest);
68
84
  }
85
+ async function ensureActiveRouteCommandGate(command, args) {
86
+ const entry = COMMANDS[command];
87
+ if (command === 'route' || entry.readonly === true || entry.allowedDuringActiveRoute === true && entry.mutatesRouteState !== true) {
88
+ return { ok: true, status: 'allowed' };
89
+ }
90
+ if (entry.mutatesRouteState !== true)
91
+ return { ok: true, status: 'allowed' };
92
+ if (safeReadOnlySubcommand(args))
93
+ return { ok: true, status: 'allowed_status_subcommand' };
94
+ const root = await projectRoot(process.cwd()).catch(() => process.cwd());
95
+ const state = await readJson(stateFile(root), {}).catch(() => ({}));
96
+ if (!activeRouteStateBlocksCommand(state))
97
+ return { ok: true, status: 'allowed' };
98
+ return {
99
+ schema: 'sks.command-gate-active-route.v1',
100
+ ok: false,
101
+ status: 'blocked',
102
+ command,
103
+ active_mission_id: state.mission_id || null,
104
+ active_route: state.route || state.route_command || state.mode || null,
105
+ active_phase: state.phase || null,
106
+ message: `SKS command gate blocked '${command}' because active route mission ${state.mission_id} is not closed. Run: sks route close --mission ${state.mission_id}`
107
+ };
108
+ }
109
+ function safeReadOnlySubcommand(args) {
110
+ const sub = String(args.find((arg) => !String(arg).startsWith('-')) || '').toLowerCase();
111
+ if (!['status', 'show', 'list', 'observe', 'watch', 'doctor', 'help'].includes(sub))
112
+ return false;
113
+ return !args.some((arg) => ['--fix', '--yes', '-y', '--write', '--apply', '--execute', '--force', '--real'].includes(String(arg)));
114
+ }
115
+ function activeRouteStateBlocksCommand(state = {}) {
116
+ if (!state?.mission_id || state.route_closed === true)
117
+ return false;
118
+ const mode = String(state.mode || '').toUpperCase();
119
+ if (!mode || ['WIKI', 'STATUS', 'HELP'].includes(mode))
120
+ return false;
121
+ if (/(?:DONE|COMPLETE|CLOSED|BLOCKED|FAILED)$/i.test(String(state.phase || '')))
122
+ return false;
123
+ return Boolean(state.route || state.route_command || ['NARUTO', 'AGENT', 'QALOOP', 'RESEARCH', 'LOOP', 'MADSKS', 'MADDB', 'GOAL'].includes(mode));
124
+ }
69
125
  //# sourceMappingURL=router.js.map
@@ -73,6 +73,8 @@ export async function run(command, args = []) {
73
73
  codex_lb: status,
74
74
  chain,
75
75
  evidence,
76
+ degraded_models: Array.isArray(chain.degraded_models) ? chain.degraded_models : [],
77
+ quota_low: Boolean(chain.quota_low),
76
78
  blockers: [
77
79
  ...(providerReady ? [] : ['codex_lb_provider_contract_drift']),
78
80
  ...(chain.ok
@@ -443,8 +445,8 @@ function shapeCodexLbStatus(status = {}) {
443
445
  modes.push('durable_env_file');
444
446
  if (status.env_loader?.api_key?.source === 'keychain' || status.env_loader?.keychain?.status === 'present')
445
447
  modes.push('durable_keychain');
446
- if (status.launch_environment?.status === 'synced')
447
- modes.push('durable_launchctl');
448
+ if (status.launch_environment?.status === 'secret_env_present')
449
+ modes.push('process_only_ephemeral');
448
450
  if (!modes.length && status.env_loader?.api_key?.source === 'process.env')
449
451
  modes.push('process_only_ephemeral');
450
452
  const mode = modes[0] || 'none';
@@ -493,7 +495,7 @@ async function codexLbSetupOptions(args = []) {
493
495
  writeEnvFile = true;
494
496
  if (flag(args, '--no-keychain'))
495
497
  keychain = false;
496
- let syncLaunchctl = flag(args, '--no-launchctl') ? false : true;
498
+ let syncLaunchctl = false;
497
499
  if (flag(args, '--launchctl'))
498
500
  syncLaunchctl = true;
499
501
  const shellProfile = normalizeShellProfile(readOption(args, '--shell-profile', 'skip'));
@@ -508,7 +510,7 @@ async function codexLbSetupOptions(args = []) {
508
510
  writeEnvFile = parseYesNo(await ask('4. Write shell env loader to ~/.codex/sks-codex-lb.env? [Y/n] '), true);
509
511
  const storeKeychain = (await ask('5. Store the key in macOS Keychain when available? [Y/n] ')).trim();
510
512
  keychain = !/^(n|no|아니|아니요|ㄴ)$/i.test(storeKeychain || 'y');
511
- syncLaunchctl = parseYesNo(await ask('6. Sync macOS launchctl environment when available? [Y/n] '), true);
513
+ syncLaunchctl = parseYesNo(await ask('6. Sync non-secret macOS launchctl base URL only? API keys are never stored in launchd. [y/N] '), false);
512
514
  const profile = (await ask('7. Install shell profile snippet? [zsh/bash/fish/all/skip] ')).trim();
513
515
  const interactiveShellProfile = normalizeShellProfile(profile || 'skip');
514
516
  const runHealth = (await ask('8. Run health check now? [Y/n] ')).trim();