sneakoscope 6.0.3 → 6.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 (378) hide show
  1. package/README.md +29 -12
  2. package/config/codex-releases/{rust-v0.142.0.json → rust-v0.144.1.json} +6 -6
  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 +18 -14
  6. package/dist/bin/sks-dispatch.js +2 -4
  7. package/dist/cli/args.js +2 -0
  8. package/dist/cli/command-manifest-lite.js +2 -3
  9. package/dist/cli/command-registry.js +3 -4
  10. package/dist/cli/help-fast.js +1 -1
  11. package/dist/cli/install-helpers.js +348 -763
  12. package/dist/cli/install-tool-helpers.js +287 -0
  13. package/dist/cli/router.js +91 -6
  14. package/dist/commands/codex-lb.js +188 -53
  15. package/dist/commands/codex.js +44 -5
  16. package/dist/commands/doctor.js +302 -46
  17. package/dist/commands/tmux.js +5 -1
  18. package/dist/commands/versioning.js +7 -0
  19. package/dist/commands/zellij-monitor-pane.js +2 -0
  20. package/dist/commands/zellij-viewport-pane.js +3 -1
  21. package/dist/commands/zellij.js +1 -1
  22. package/dist/config/skills-manifest.json +59 -59
  23. package/dist/core/agent-bridge/agent-manifest.js +48 -0
  24. package/dist/core/agents/agent-central-ledger.js +9 -0
  25. package/dist/core/agents/agent-cleanup-executor.js +334 -41
  26. package/dist/core/agents/agent-cleanup.js +20 -1
  27. package/dist/core/agents/agent-command-surface.js +3 -1
  28. package/dist/core/agents/agent-effort-policy.js +30 -38
  29. package/dist/core/agents/agent-janitor.js +9 -10
  30. package/dist/core/agents/agent-namespace-safety.js +56 -0
  31. package/dist/core/agents/agent-orchestrator.js +25 -3
  32. package/dist/core/agents/agent-output-validator.js +1 -1
  33. package/dist/core/agents/agent-plan.js +100 -21
  34. package/dist/core/agents/agent-role-config.js +43 -49
  35. package/dist/core/agents/agent-runner-codex-exec.js +18 -3
  36. package/dist/core/agents/agent-runner-process.js +1 -0
  37. package/dist/core/agents/agent-schema.js +3 -2
  38. package/dist/core/agents/fast-mode-policy.js +3 -5
  39. package/dist/core/agents/native-cli-session-swarm.js +1 -1
  40. package/dist/core/agents/native-worker-backend-router.js +2 -1
  41. package/dist/core/agents/work-partition/repo-inventory.js +68 -7
  42. package/dist/core/agents/zellij-right-lane-cockpit.js +2 -2
  43. package/dist/core/code-structure.js +5 -4
  44. package/dist/core/codex/agent-config-file-repair.js +94 -193
  45. package/dist/core/codex/codex-cli-update.js +723 -0
  46. package/dist/core/codex/codex-config-guard.js +38 -11
  47. package/dist/core/codex/codex-project-config-policy.js +3 -6
  48. package/dist/core/codex/codex-startup-config-postcheck.js +52 -42
  49. package/dist/core/codex-adapter.js +35 -22
  50. package/dist/core/codex-app/codex-agent-role-sync.js +13 -54
  51. package/dist/core/codex-app/codex-app-fast-ui-repair.js +51 -20
  52. package/dist/core/codex-app/codex-app-launcher.js +48 -17
  53. package/dist/core/codex-app/codex-app-restart.js +23 -2
  54. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +11 -3
  55. package/dist/core/codex-app/sks-menubar.js +136 -5
  56. package/dist/core/codex-app.js +35 -14
  57. package/dist/core/codex-compat/codex-hook-warning-detector.js +10 -1
  58. package/dist/core/codex-compat/codex-release-manifest.js +6 -6
  59. package/dist/core/codex-control/codex-0139-doctor-real-probe.js +7 -1
  60. package/dist/core/codex-control/codex-0139-image-path-real-probe.js +29 -12
  61. package/dist/core/codex-control/codex-0139-probe-runner.js +103 -28
  62. package/dist/core/codex-control/codex-0139-real-probe-summary.js +7 -3
  63. package/dist/core/codex-control/codex-0139-real-probes.js +21 -6
  64. package/dist/core/codex-control/codex-0139-sandbox-real-probe.js +39 -13
  65. package/dist/core/codex-control/codex-0139-web-search-probe.js +28 -14
  66. package/dist/core/codex-control/{codex-0142-capability.js → codex-0144-capability.js} +22 -22
  67. package/dist/core/codex-control/codex-0144-collab-agent-real-probe.js +63 -0
  68. package/dist/core/codex-control/codex-lb-launch-recovery.js +278 -0
  69. package/dist/core/codex-control/codex-multi-agent-event-normalizer.js +5 -1
  70. package/dist/core/codex-control/codex-reliability-shield.js +93 -30
  71. package/dist/core/codex-control/codex-sdk-adapter.js +96 -13
  72. package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
  73. package/dist/core/codex-control/codex-sdk-sandbox-policy.js +6 -3
  74. package/dist/core/codex-control/codex-task-runner.js +62 -9
  75. package/dist/core/codex-control/python-codex-sdk-adapter.js +30 -3
  76. package/dist/core/codex-exec-output-schema.js +35 -6
  77. package/dist/core/codex-lb/codex-lb-env.js +30 -1
  78. package/dist/core/codex-lb/codex-lb-tool-catalog.js +478 -0
  79. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +291 -0
  80. package/dist/core/codex-native/codex-native-feature-broker.js +31 -38
  81. package/dist/core/codex-native/codex-native-feature-matrix.js +2 -2
  82. package/dist/core/codex-native/codex-native-repair-transaction.js +1 -1
  83. package/dist/core/codex-native/core-skill-manifest.js +8 -4
  84. package/dist/core/codex-native/native-capability-postcheck.js +16 -8
  85. package/dist/core/codex-native/native-capability-repair-matrix.js +76 -27
  86. package/dist/core/codex-plugins/codex-plugin-json.js +67 -21
  87. package/dist/core/codex-plugins/codex-plugin-repair.js +118 -0
  88. package/dist/core/codex-runtime/codex-desktop-config-policy.js +305 -0
  89. package/dist/core/commands/agent-bridge-command.js +23 -2
  90. package/dist/core/commands/agent-command.js +38 -5
  91. package/dist/core/commands/basic-cli.js +77 -30
  92. package/dist/core/commands/command-utils.js +1 -1
  93. package/dist/core/commands/gc-command.js +27 -4
  94. package/dist/core/commands/image-ux-review-command.js +55 -24
  95. package/dist/core/commands/mad-sks-command.js +182 -137
  96. package/dist/core/commands/naruto-command.js +643 -1153
  97. package/dist/core/commands/pipeline-command.js +1 -0
  98. package/dist/core/commands/research-command.js +293 -231
  99. package/dist/core/commands/run-command.js +100 -23
  100. package/dist/core/commands/team-command.js +2 -3
  101. package/dist/core/commands/team-legacy-observe-command.js +94 -359
  102. package/dist/core/commands/wiki-command.js +179 -83
  103. package/dist/core/computer-use-live-evidence.js +166 -3
  104. package/dist/core/computer-use-status.js +5 -2
  105. package/dist/core/daemon/sksd-hook-daemon-entrypoint.js +2 -2
  106. package/dist/core/daemon/sksd-hook-daemon.js +171 -28
  107. package/dist/core/daemon/sksd-hook-dispatch.js +2 -2
  108. package/dist/core/db-safety.js +2 -2
  109. package/dist/core/decision-lattice.js +6 -6
  110. package/dist/core/dfix/verification-selector.js +6 -4
  111. package/dist/core/doctor/browser-use-repair.js +54 -13
  112. package/dist/core/doctor/codex-0139-doctor.js +3 -2
  113. package/dist/core/doctor/codex-startup-config-repair.js +8 -3
  114. package/dist/core/doctor/computer-use-repair.js +28 -39
  115. package/dist/core/doctor/doctor-codex-startup-repair.js +24 -149
  116. package/dist/core/doctor/doctor-context7-repair.js +1 -1
  117. package/dist/core/doctor/doctor-dirty-planner.js +1 -1
  118. package/dist/core/doctor/doctor-native-capability-repair.js +74 -3
  119. package/dist/core/doctor/imagegen-repair.js +47 -12
  120. package/dist/core/doctor/legacy-global-hook-cleanup.js +179 -0
  121. package/dist/core/feature-fixture-executor.js +71 -7
  122. package/dist/core/feature-fixture-runner.js +53 -12
  123. package/dist/core/feature-fixtures.js +47 -14
  124. package/dist/core/feature-registry.js +53 -58
  125. package/dist/core/fsx.js +54 -6
  126. package/dist/core/harness-conflicts.js +19 -10
  127. package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +5 -4
  128. package/dist/core/hooks-runtime/hook-invocation-dedupe.js +147 -0
  129. package/dist/core/hooks-runtime/hook-io.js +14 -4
  130. package/dist/core/hooks-runtime/light-turn.js +70 -0
  131. package/dist/core/hooks-runtime/payload-signals.js +270 -0
  132. package/dist/core/hooks-runtime/team-digest.js +0 -1
  133. package/dist/core/hooks-runtime/tool-output-quarantine.js +93 -0
  134. package/dist/core/hooks-runtime.js +418 -250
  135. package/dist/core/image/image-artifact-path-contract.js +8 -6
  136. package/dist/core/image/image-artifact-registry.js +5 -1
  137. package/dist/core/image-ux-review/imagegen-adapter.js +5 -2
  138. package/dist/core/imagegen/imagegen-capability.js +10 -13
  139. package/dist/core/imagegen/require-imagegen.js +37 -11
  140. package/dist/core/init/skills.js +16 -30
  141. package/dist/core/init.js +144 -36
  142. package/dist/core/managed-assets/managed-assets-manifest.js +417 -14
  143. package/dist/core/mission.js +24 -1
  144. package/dist/core/naruto/naruto-work-graph.js +70 -4
  145. package/dist/core/ops/reporting.js +3 -0
  146. package/dist/core/pipeline-internals/runtime-core.js +578 -180
  147. package/dist/core/pipeline-internals/runtime-gates.js +191 -49
  148. package/dist/core/ppt/style-tokens.js +1 -1
  149. package/dist/core/ppt-review/index.js +1 -1
  150. package/dist/core/ppt-review/slide-exporter.js +23 -17
  151. package/dist/core/ppt-review/slide-imagegen-review.js +1 -1
  152. package/dist/core/ppt-review/slide-issue-extraction.js +4 -2
  153. package/dist/core/preflight/parallel-preflight-engine.js +50 -1
  154. package/dist/core/product-design-plugin.js +2 -2
  155. package/dist/core/proof/route-finalizer.js +1 -1
  156. package/dist/core/proof/route-proof-gate.js +7 -2
  157. package/dist/core/proof-field.js +3 -3
  158. package/dist/core/provider/model-router.js +38 -32
  159. package/dist/core/recallpulse/policy.js +12 -28
  160. package/dist/core/recallpulse.js +11 -6
  161. package/dist/core/release/gate-manifest.js +18 -12
  162. package/dist/core/release/gate-pack-manifest.js +1 -1
  163. package/dist/core/release/npm-pack-proof.js +247 -0
  164. package/dist/core/release/package-dist-snapshot.js +151 -0
  165. package/dist/core/release/package-size-budget.js +5 -0
  166. package/dist/core/release/release-authorization-snapshot.js +115 -0
  167. package/dist/core/release/release-gate-affected-selector.js +15 -3
  168. package/dist/core/release/release-gate-cache-v2.js +30 -0
  169. package/dist/core/release/release-gate-contract.js +161 -0
  170. package/dist/core/release/release-gate-dag.js +44 -3
  171. package/dist/core/release/release-gate-hermetic-env.js +28 -17
  172. package/dist/core/release/release-real-contract.js +496 -0
  173. package/dist/core/release-parallel-full-coverage.js +31 -143
  174. package/dist/core/research/claim-evidence-matrix.js +41 -6
  175. package/dist/core/research/experiment-plan.js +14 -10
  176. package/dist/core/research/falsification.js +9 -2
  177. package/dist/core/research/implementation-blueprint-densifier.js +82 -60
  178. package/dist/core/research/implementation-blueprint.js +32 -26
  179. package/dist/core/research/mock-result.js +122 -11
  180. package/dist/core/research/replication-pack.js +15 -8
  181. package/dist/core/research/research-adversarial-review.js +1068 -0
  182. package/dist/core/research/research-claim-builder.js +69 -17
  183. package/dist/core/research/research-claim-synthesizer.js +343 -0
  184. package/dist/core/research/research-cycle-runner.js +53 -3
  185. package/dist/core/research/research-falsification-runner.js +176 -0
  186. package/dist/core/research/research-final-reviewer.js +44 -125
  187. package/dist/core/research/research-realistic-report.js +14 -6
  188. package/dist/core/research/research-review-artifact-digest.js +66 -0
  189. package/dist/core/research/research-source-evidence.js +144 -0
  190. package/dist/core/research/research-source-layer-catalog.js +68 -0
  191. package/dist/core/research/research-source-ledger-merge.js +250 -12
  192. package/dist/core/research/research-source-shards.js +26 -70
  193. package/dist/core/research/research-stage-runner.js +237 -247
  194. package/dist/core/research/research-super-search.js +184 -0
  195. package/dist/core/research/research-synthesis-prompt.js +20 -1
  196. package/dist/core/research/research-synthesis-writer.js +86 -5
  197. package/dist/core/research/research-work-graph.js +25 -18
  198. package/dist/core/research/source-quality-report.js +21 -0
  199. package/dist/core/research.js +429 -280
  200. package/dist/core/retention/retention-budget.js +25 -6
  201. package/dist/core/retention.js +980 -101
  202. package/dist/core/routes/constants.js +1 -1
  203. package/dist/core/routes/dollar-manifest-lite.js +11 -11
  204. package/dist/core/routes/evidence.js +4 -4
  205. package/dist/core/routes/ppt-policy.js +1 -1
  206. package/dist/core/routes.js +92 -64
  207. package/dist/core/runtime/task-profile.js +66 -0
  208. package/dist/core/runtime/verification-budget.js +12 -0
  209. package/dist/core/secret-redaction.js +4 -0
  210. package/dist/core/security/high-risk-contracts.js +6 -6
  211. package/dist/core/stop-gate/stop-gate-check.js +49 -12
  212. package/dist/core/subagents/agent-catalog.js +215 -0
  213. package/dist/core/subagents/model-policy.js +118 -0
  214. package/dist/core/subagents/naruto-help-contract.js +40 -0
  215. package/dist/core/subagents/official-subagent-config.js +488 -0
  216. package/dist/core/subagents/official-subagent-preparation.js +251 -0
  217. package/dist/core/subagents/official-subagent-prompt.js +137 -0
  218. package/dist/core/subagents/official-subagent-runner.js +129 -0
  219. package/dist/core/subagents/subagent-evidence.js +663 -0
  220. package/dist/core/subagents/terminology.js +16 -0
  221. package/dist/core/subagents/thread-budget.js +21 -0
  222. package/dist/core/subagents/triwiki-attention.js +65 -0
  223. package/dist/core/super-search/runtime-helpers.js +173 -19
  224. package/dist/core/super-search/runtime.js +140 -15
  225. package/dist/core/super-search/source-records.js +49 -8
  226. package/dist/core/team-review-policy.js +15 -0
  227. package/dist/core/triwiki/code-pack.js +8 -2
  228. package/dist/core/triwiki/triwiki-cache-key.js +108 -29
  229. package/dist/core/triwiki/triwiki-module-card.js +1 -1
  230. package/dist/core/triwiki-attention.js +13 -6
  231. package/dist/core/triwiki-provenance.js +274 -0
  232. package/dist/core/triwiki-runtime.js +21 -7
  233. package/dist/core/triwiki-wrongness/wrongness-ledger.js +187 -61
  234. package/dist/core/triwiki-wrongness/wrongness-retrieval.js +11 -2
  235. package/dist/core/triwiki-wrongness/wrongness-trust-policy.js +2 -0
  236. package/dist/core/update-check.js +23 -15
  237. package/dist/core/version-manager.js +51 -1
  238. package/dist/core/version.js +1 -1
  239. package/dist/core/wiki-coordinate.js +128 -12
  240. package/dist/core/work-order-ledger.js +208 -10
  241. package/dist/core/zellij/zellij-command.js +12 -1
  242. package/dist/core/zellij/zellij-dashboard-pane.js +3 -3
  243. package/dist/core/zellij/zellij-fake-adapter.js +3 -1
  244. package/dist/core/zellij/zellij-launcher.js +51 -21
  245. package/dist/core/zellij/zellij-layout-builder.js +14 -5
  246. package/dist/core/zellij/zellij-official-subagent-activity.js +477 -0
  247. package/dist/core/zellij/zellij-official-subagent-telemetry.js +264 -0
  248. package/dist/core/zellij/zellij-pane-proof.js +32 -6
  249. package/dist/core/zellij/zellij-slot-pane-renderer.js +17 -5
  250. package/dist/core/zellij/zellij-slot-telemetry.js +15 -3
  251. package/dist/core/zellij/zellij-ui-mode.js +1 -1
  252. package/dist/core/zellij/zellij-viewport-binder.js +3 -0
  253. package/dist/core/zellij/zellij-worker-pane-manager.js +5 -3
  254. package/dist/scripts/agent-fast-mode-default-check.js +48 -29
  255. package/dist/scripts/agent-role-config-repair-check.js +34 -15
  256. package/dist/scripts/agent-wiki-context-proof-check.js +16 -2
  257. package/dist/scripts/all-feature-deep-completion-check.js +14 -4
  258. package/dist/scripts/architecture-guard-check.js +8 -1
  259. package/dist/scripts/build-dist.js +17 -5
  260. package/dist/scripts/canonical-test-runner.js +188 -0
  261. package/dist/scripts/check-command-module-budget.js +38 -16
  262. package/dist/scripts/check-legacy-free.js +1 -1
  263. package/dist/scripts/check-route-modularity.js +0 -1
  264. package/dist/scripts/check-ts-contracts.js +1 -1
  265. package/dist/scripts/codex-0139-interrupt-agent-check.js +5 -1
  266. package/dist/scripts/{codex-0142-app-server-v2-check.js → codex-0144-app-server-v2-check.js} +11 -10
  267. package/dist/scripts/{codex-0142-binary-identity-check.js → codex-0144-binary-identity-check.js} +4 -4
  268. package/dist/scripts/codex-0144-capability-check.js +21 -0
  269. package/dist/scripts/{codex-0139-real-probes-check.js → codex-0144-core-real-probes-check.js} +19 -5
  270. package/dist/scripts/{codex-0142-doctor-wiring-check.js → codex-0144-doctor-wiring-check.js} +6 -6
  271. package/dist/scripts/{codex-0142-manifest-check.js → codex-0144-manifest-check.js} +11 -3
  272. package/dist/scripts/{codex-0142-policy-check.js → codex-0144-policy-check.js} +2 -2
  273. package/dist/scripts/{codex-0142-thread-store-check.js → codex-0144-thread-store-check.js} +3 -3
  274. package/dist/scripts/codex-app-provider-model-ui-check.js +53 -19
  275. package/dist/scripts/codex-app-ui-preservation-check.js +35 -4
  276. package/dist/scripts/codex-control-all-pipelines-check.js +7 -3
  277. package/dist/scripts/codex-control-side-effect-scope-check.js +2 -2
  278. package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +27 -0
  279. package/dist/scripts/codex-effort-auto-discovery-check.js +1 -1
  280. package/dist/scripts/codex-lb-fast-mode-truth-check.js +1 -0
  281. package/dist/scripts/{codex-lb-gpt55-fast-profile-check.js → codex-lb-gpt56-fast-profile-check.js} +56 -5
  282. package/dist/scripts/codex-model-metadata-check.js +1 -1
  283. package/dist/scripts/codex-native-agent-role-content-check.js +15 -7
  284. package/dist/scripts/codex-native-repair-transaction-check.js +3 -1
  285. package/dist/scripts/codex-sdk-all-pipelines-check.js +7 -4
  286. package/dist/scripts/codex-sdk-research-pipeline-check.js +30 -8
  287. package/dist/scripts/codex-sdk-sandbox-policy-check.js +5 -1
  288. package/dist/scripts/codex-sdk-version-compat-check.js +2 -1
  289. package/dist/scripts/db-route-materialization-check.js +33 -0
  290. package/dist/scripts/dfix-fixture-check.js +1 -1
  291. package/dist/scripts/docs-truthfulness-check.js +4 -2
  292. package/dist/scripts/doctor-codex-startup-repair-check.js +47 -25
  293. package/dist/scripts/doctor-context7-repair-check.js +2 -1
  294. package/dist/scripts/doctor-fix-production-blackbox.js +12 -2
  295. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +34 -7
  296. package/dist/scripts/doctor-imagegen-repair-check.js +14 -4
  297. package/dist/scripts/doctor-startup-config-repair-blackbox.js +9 -3
  298. package/dist/scripts/doctor-startup-config-repair-check.js +13 -3
  299. package/dist/scripts/install-update-preserves-config-check.js +7 -2
  300. package/dist/scripts/legacy-gate-inventory-check.js +7 -5
  301. package/dist/scripts/legacy-strong-inventory-check.js +7 -5
  302. package/dist/scripts/legacy-upgrade-matrix-check.js +4 -4
  303. package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +173 -13
  304. package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +165 -6
  305. package/dist/scripts/managed-role-manifest-parity-check.js +5 -4
  306. package/dist/scripts/mutation-callsite-coverage-check.js +0 -11
  307. package/dist/scripts/naruto-codex-e2e-check.js +14 -7
  308. package/dist/scripts/naruto-shadow-clone-swarm-check.js +4 -201
  309. package/dist/scripts/npm-publish-performance-check.js +20 -12
  310. package/dist/scripts/official-subagent-workflow-check.js +145 -0
  311. package/dist/scripts/package-published-contract-check.js +6 -20
  312. package/dist/scripts/packlist-performance-check.js +17 -3
  313. package/dist/scripts/parallel-verification-engine-check.js +2 -2
  314. package/dist/scripts/postinstall-safe-side-effects-check.js +8 -3
  315. package/dist/scripts/ppt-no-mock-as-real-check.js +3 -1
  316. package/dist/scripts/prepublish-release-check-or-fast.js +23 -86
  317. package/dist/scripts/product-design-plugin-routing-check.js +1 -1
  318. package/dist/scripts/release-affected-selector-check.js +74 -1
  319. package/dist/scripts/release-check-stamp.js +324 -239
  320. package/dist/scripts/release-dag-full-coverage-check.js +7 -15
  321. package/dist/scripts/release-dynamic-presets-check.js +10 -1
  322. package/dist/scripts/release-gate-dag-runner-check.js +3 -3
  323. package/dist/scripts/release-gate-dag-runner.js +35 -11
  324. package/dist/scripts/release-gate-existence-audit.js +1 -2
  325. package/dist/scripts/release-gate-script-parity-check.js +1 -1
  326. package/dist/scripts/release-parallel-full-coverage-check.js +12 -6
  327. package/dist/scripts/release-parallel-speed-budget-check.js +18 -2
  328. package/dist/scripts/release-real-check.js +390 -157
  329. package/dist/scripts/release-registry-check.js +61 -16
  330. package/dist/scripts/release-runtime-truth-matrix-check.js +22 -0
  331. package/dist/scripts/research-blueprint-densifier-check.js +2 -2
  332. package/dist/scripts/research-real-cycle-no-legacy-final-md-check.js +11 -7
  333. package/dist/scripts/route-proof-artifact-structure-check.js +1 -0
  334. package/dist/scripts/search-visibility-gate-lib.js +1 -1
  335. package/dist/scripts/seo-geo-route-identity-check.js +30 -4
  336. package/dist/scripts/sizecheck.js +4 -4
  337. package/dist/scripts/sks-1-11-gate-lib.js +53 -6
  338. package/dist/scripts/sks-3-1-4-directive-check-lib.js +8 -2
  339. package/dist/scripts/sks-3-1-5-directive-check-lib.js +3 -2
  340. package/dist/scripts/sks-3-1-6-directive-check-lib.js +5 -3
  341. package/dist/scripts/sks-menubar-install-check.js +8 -0
  342. package/dist/scripts/sks-uninstall-regression-check.js +1 -1
  343. package/dist/scripts/sksd-daemon-check.js +16 -6
  344. package/dist/scripts/trust-fixture-check.js +32 -10
  345. package/dist/scripts/write-build-manifest.js +2 -1
  346. package/dist/scripts/wrongness-fixture-check.js +1 -1
  347. package/dist/scripts/zellij-layout-valid-check.js +36 -11
  348. package/dist/scripts/zellij-pane-proof-check.js +33 -2
  349. package/dist/scripts/zellij-real-session-cleanup-check.js +122 -2
  350. package/dist/scripts/zellij-real-session-launch-check.js +76 -5
  351. package/dist/scripts/zellij-slot-pane-renderer-check.js +4 -4
  352. package/dist/scripts/zellij-spawn-on-demand-layout-check.js +3 -3
  353. package/docs/demo.tape +1 -1
  354. package/infra-harness-gates.json +1486 -0
  355. package/package.json +32 -19
  356. package/release-gates.v2.json +4060 -0
  357. package/runtime-required-scripts.json +9 -0
  358. package/schemas/codex/{app-server-0.142 → app-server-0.144}/codex_app_server_protocol.v2.schemas.json +1146 -781
  359. package/schemas/codex/codex-0139-real-probe-result.schema.json +39 -5
  360. package/schemas/codex/ppt-slide-issue-ledger.schema.json +2 -1
  361. package/dist/commands/db.js +0 -6
  362. package/dist/core/codex-control/codex-0139-multi-agent-real-probe.js +0 -107
  363. package/dist/core/commands/db-command.js +0 -146
  364. package/dist/core/research/prompt.js +0 -15
  365. package/dist/scripts/agent-native-release-gate.js +0 -274
  366. package/dist/scripts/codex-0142-capability-check.js +0 -21
  367. package/dist/scripts/codex-control-tool-call-sequence-repair-check.js +0 -14
  368. package/dist/scripts/command-performance-scorecard-check.js +0 -204
  369. package/dist/scripts/config-managed-merge-callsite-coverage-check.js +0 -212
  370. package/dist/scripts/dollar-performance-scorecard-check.js +0 -257
  371. package/dist/scripts/gate-timing-check.js +0 -16
  372. package/dist/scripts/ops-maturity-scorecard-check.js +0 -12
  373. package/dist/scripts/performance-baseline-check.js +0 -12
  374. package/dist/scripts/performance-improvement-report-check.js +0 -58
  375. package/dist/scripts/release-parallel-check.js +0 -389
  376. package/dist/scripts/release-runner-efficiency-check.js +0 -15
  377. package/dist/scripts/retention-long-run-smoke-check.js +0 -299
  378. package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
@@ -9,7 +9,7 @@ export async function writeCodexConfigGuarded(input) {
9
9
  const root = path.resolve(input.root || process.cwd());
10
10
  const cause = input.cause || 'codex-config';
11
11
  const before = input.before === undefined ? String(await readText(configPath, '')) : String(input.before || '');
12
- if (isUnmanagedProjectCodexConfig(root, configPath, before)) {
12
+ if (isUnmanagedProjectCodexConfig(root, configPath, before) && input.ownershipVerified !== true) {
13
13
  const result = { ok: false, status: 'blocked_unmanaged_project_config', config_path: configPath, backup_path: null, changed: false };
14
14
  await recordCodexConfigGuard(root, input.reportPath, {
15
15
  cause,
@@ -64,6 +64,7 @@ export async function writeCodexConfigGuarded(input) {
64
64
  return result;
65
65
  }
66
66
  if (next === ensureTrailingNewline(before)) {
67
+ await writeTextAtomic(configPath, next, { mode: 0o600 });
67
68
  const result = { ok: true, status: 'present', config_path: configPath, backup_path: null, changed: false, repaired_keys: preserved.keys, forbidden_top_level: forbiddenTopLevel };
68
69
  if (preserved.keys.length || forbiddenTopLevel.length) {
69
70
  await recordCodexConfigGuard(root, input.reportPath, {
@@ -80,7 +81,7 @@ export async function writeCodexConfigGuarded(input) {
80
81
  }
81
82
  const backupPath = before.trim() ? await backupCodexConfig(configPath, before, input.backupTag || cause) : null;
82
83
  await ensureDir(path.dirname(configPath));
83
- await writeTextAtomic(configPath, next);
84
+ await writeTextAtomic(configPath, next, { mode: 0o600 });
84
85
  const afterSnapshot = await snapshotForConfig(root, configPath).catch(() => null);
85
86
  const diff = beforeSnapshot && afterSnapshot ? diffCodexAppUiSnapshots(beforeSnapshot, afterSnapshot) : null;
86
87
  const result = {
@@ -145,7 +146,12 @@ export function isProjectCodexConfig(root, configPath) {
145
146
  return path.resolve(configPath) === path.resolve(root, '.codex', 'config.toml');
146
147
  }
147
148
  export function hasSksManagedCodexConfigMarker(text) {
148
- return /(?:SKS managed|Sneakoscope|sneakoscope|sks_|agents\.native_agent|agents\.implementation_worker|multi_agent)/i.test(String(text || ''));
149
+ const source = String(text || '');
150
+ return /^\s*#\s*SKS-MANAGED-CODEX-CONFIG\b/im.test(source)
151
+ || /(?:SKS managed|Sneakoscope|sneakoscope|sks_|agents\.native_agent|agents\.implementation_worker|multi_agent)/i.test(source)
152
+ || /^\s*model_provider\s*=\s*["']codex-lb["']\s*(?:#.*)?$/mi.test(source)
153
+ || /^\s*default_profile\s*=\s*["']sks-fast-high["']\s*(?:#.*)?$/mi.test(source)
154
+ || /^\s*\[(?:user\.fast_mode|model_providers\.(?:"codex-lb"|codex-lb)|profiles\.(?:"sks-fast-high"|sks-fast-high))\]\s*(?:#.*)?$/mi.test(source);
149
155
  }
150
156
  export function isUnmanagedProjectCodexConfig(root, configPath, text) {
151
157
  return isProjectCodexConfig(root, configPath)
@@ -161,15 +167,36 @@ export function removeLegacyTopLevelCodexModeLocks(text = '') {
161
167
  return true;
162
168
  if (!/^\s*(?:model|model_reasoning_effort)\s*=/.test(line))
163
169
  return true;
164
- return !isSksProvenanceLine(line, lines[index - 1] || '');
170
+ return !hasSksModeLockProvenance(lines, index);
165
171
  }).join('\n').replace(/^\n+/, '').replace(/\n{3,}/g, '\n\n'));
166
172
  }
167
- function isSksProvenanceLine(...lines) {
168
- return lines.some((line) => {
169
- const trimmed = String(line || '').trim();
170
- const comment = trimmed.startsWith('#') ? trimmed : trimmed.includes('#') ? trimmed.slice(trimmed.indexOf('#')) : '';
171
- return /(?:SKS|Sneakoscope|codex-lb|sks fast)/i.test(comment);
172
- });
173
+ function hasSksModeLockProvenance(lines, index) {
174
+ const current = String(lines[index] || '');
175
+ const inlineComment = current.includes('#') ? current.slice(current.indexOf('#')) : '';
176
+ if (isSksModeLockMarker(inlineComment))
177
+ return true;
178
+ const allowedManagedKeys = new Set([
179
+ 'service_tier', 'model', 'model_reasoning_effort', 'model_provider',
180
+ 'approval_policy', 'sandbox_mode', 'web_search', 'notify', 'preferred_auth_method'
181
+ ]);
182
+ const lowerBound = Math.max(0, index - 16);
183
+ for (let cursor = index - 1; cursor >= lowerBound; cursor -= 1) {
184
+ const candidate = String(lines[cursor] || '').trim();
185
+ if (!candidate)
186
+ continue;
187
+ if (candidate.startsWith('#')) {
188
+ if (isSksModeLockMarker(candidate))
189
+ return true;
190
+ continue;
191
+ }
192
+ const key = candidate.match(/^([A-Za-z0-9_-]+)\s*=/)?.[1] || '';
193
+ if (!allowedManagedKeys.has(key))
194
+ return false;
195
+ }
196
+ return false;
197
+ }
198
+ function isSksModeLockMarker(value = '') {
199
+ return /^#\s*(?:SKS|Sneakoscope)\b.*(?:moved machine-local Codex config|forced fast UI|managed (?:Codex )?(?:model|reasoning)|codex-lb (?:model|reasoning))/i.test(String(value || '').trim());
173
200
  }
174
201
  function mergeLostFastUiKeys(before, nextInput) {
175
202
  let next = String(nextInput || '');
@@ -301,7 +328,7 @@ async function snapshotForConfig(root, configPath) {
301
328
  async function backupCodexConfig(configPath, text, tag) {
302
329
  try {
303
330
  const backupPath = `${configPath}.sks-${tag}-${Date.now().toString(36)}.bak`;
304
- await writeTextAtomic(backupPath, text);
331
+ await writeTextAtomic(backupPath, text, { mode: 0o600 });
305
332
  await cleanupCodexConfigBackups(configPath, { keepPerTag: 3, maxAgeMs: 30 * 24 * 60 * 60 * 1000 }).catch(() => undefined);
306
333
  return backupPath;
307
334
  }
@@ -2,7 +2,7 @@ import fsp from 'node:fs/promises';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { ensureDir, nowIso, readText, writeJsonAtomic } from '../fsx.js';
5
- import { writeCodexConfigGuarded } from './codex-config-guard.js';
5
+ import { hasSksManagedCodexConfigMarker, writeCodexConfigGuarded } from './codex-config-guard.js';
6
6
  import { cleanupCodexConfigBackups } from './codex-config-toml.js';
7
7
  export const CODEX_PROJECT_CONFIG_POLICY_SCHEMA = 'sks.codex-project-config-policy.v1';
8
8
  const MACHINE_LOCAL_TOP_LEVEL_KEYS = new Set([
@@ -95,7 +95,7 @@ export async function splitCodexProjectConfigPolicy(rootInput = process.cwd(), o
95
95
  await writeJsonAtomic(reportPath, { ...report, report_path: reportPath });
96
96
  return report;
97
97
  }
98
- if (opts.apply && isCodexConfigToml(configPath) && !hasSksManagedCodexMarker(String(original))) {
98
+ if (opts.apply && isCodexConfigToml(configPath) && !hasSksManagedCodexConfigMarker(String(original))) {
99
99
  const report = {
100
100
  schema: CODEX_PROJECT_CONFIG_POLICY_SCHEMA,
101
101
  generated_at: nowIso(),
@@ -208,7 +208,7 @@ export async function repairCodexConfigStructure(configPathInput, opts = {}) {
208
208
  if (original === null) {
209
209
  return { config_path: configPath, ok: true, status: 'config_missing', changed: false, applied: false, hoisted_keys: [], backup_path: null };
210
210
  }
211
- if (opts.apply && isCodexConfigToml(configPath) && !hasSksManagedCodexMarker(String(original))) {
211
+ if (opts.apply && isCodexConfigToml(configPath) && !hasSksManagedCodexConfigMarker(String(original))) {
212
212
  return {
213
213
  config_path: configPath,
214
214
  ok: false,
@@ -249,9 +249,6 @@ export async function repairCodexConfigStructure(configPathInput, opts = {}) {
249
249
  function isCodexConfigToml(file) {
250
250
  return path.basename(file) === 'config.toml' && path.basename(path.dirname(file)) === '.codex';
251
251
  }
252
- function hasSksManagedCodexMarker(text) {
253
- return /(?:SKS managed|Sneakoscope|sneakoscope|sks_|agents\.native_agent|agents\.implementation_worker|multi_agent)/i.test(text);
254
- }
255
252
  function hoistMisplacedMachineLocalKeys(text) {
256
253
  const blocks = tomlBlocks(text);
257
254
  const preamble = [];
@@ -1,64 +1,64 @@
1
1
  import fs from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { nowIso, writeJsonAtomic } from '../fsx.js';
4
- import { missingAgentConfigFiles } from './agent-config-file-repair.js';
5
- import { managedAgentRoleConfigForFile, managedAgentRoleConfigForRole } from '../agents/agent-role-config.js';
4
+ import { inspectOfficialSubagentToml, installOfficialSubagentAgentConfigs, readOfficialSubagentConfig } from '../subagents/official-subagent-config.js';
6
5
  export async function postcheckCodexStartupConfig(input) {
7
6
  const root = path.resolve(input.root);
8
7
  const configPath = path.join(root, '.codex', 'config.toml');
9
8
  const text = await fs.readFile(configPath, 'utf8').catch(() => '');
10
- const missing = await missingAgentConfigFiles(text);
11
- const managedBlocks = managedAgentBlocks(text);
12
- const unsupportedRoleFields = managedBlocks.some((block) => /^\s*message_role_prefix\s*=/m.test(block.text));
13
- const relativePaths = managedBlocks
14
- .map((block) => block.text.match(/^\s*config_file\s*=\s*"([^"]+)"/m)?.[1])
15
- .filter((file) => Boolean(file && !path.isAbsolute(file)));
9
+ const configPresent = Boolean(text.trim());
10
+ const tomlValidation = inspectOfficialSubagentToml(text);
11
+ const officialConfig = await readOfficialSubagentConfig(root, {
12
+ ...(input.home ? { home: input.home } : {}),
13
+ ...(input.codexHome ? { codexHome: input.codexHome } : {}),
14
+ projectConfigPath: configPath
15
+ });
16
+ const rolePlan = await installOfficialSubagentAgentConfigs(root, { apply: false });
16
17
  const tomlSmoke = tomlSyntaxSmoke(text);
17
18
  const orphanChildTables = orphanMcpChildTables(text);
19
+ const blockers = [
20
+ ...(!configPresent ? ['project_official_subagent_config_missing'] : []),
21
+ ...(!tomlValidation.ok ? ['project_official_subagent_config_toml_parse_failed'] : []),
22
+ ...officialConfig.blockers.map((item) => `official_subagent_config:${item}`),
23
+ ...rolePlan.missing.map((file) => `missing_official_subagent_agent:${file}`),
24
+ ...rolePlan.stale.map((file) => `stale_official_subagent_agent:${file}`),
25
+ ...rolePlan.manual_blockers,
26
+ ...tomlSmoke.blockers,
27
+ ...orphanChildTables.map((table) => `orphan_mcp_child_table:${table}`)
28
+ ];
18
29
  const report = {
19
30
  schema: 'sks.codex-startup-config-postcheck.v1',
20
31
  generated_at: nowIso(),
21
- ok: missing.length === 0 && relativePaths.length === 0 && !unsupportedRoleFields && tomlSmoke.ok && orphanChildTables.length === 0,
32
+ ok: blockers.length === 0,
22
33
  config_path: configPath,
23
- missing_config_files: missing,
24
- relative_config_files: relativePaths,
25
- unsupported_managed_role_fields: unsupportedRoleFields,
34
+ missing_config_files: [],
35
+ relative_config_files: [],
36
+ unsupported_managed_role_fields: false,
37
+ official_subagent_config: {
38
+ max_threads: officialConfig.maxThreads,
39
+ max_depth: officialConfig.maxDepth,
40
+ job_max_runtime_seconds: officialConfig.jobMaxRuntimeSeconds,
41
+ interrupt_message: officialConfig.interruptMessage,
42
+ sources: officialConfig.sources,
43
+ warnings: officialConfig.warnings
44
+ },
45
+ official_subagent_agents: {
46
+ missing: rolePlan.missing,
47
+ stale: rolePlan.stale,
48
+ existing: rolePlan.existing,
49
+ preserved: rolePlan.preserved,
50
+ manual_blockers: rolePlan.manual_blockers
51
+ },
52
+ legacy_agent_tables_preserved: true,
26
53
  toml_syntax_smoke_ok: tomlSmoke.ok,
27
54
  orphan_mcp_child_tables: orphanChildTables,
28
- blockers: [
29
- ...missing.map((file) => `missing_agent_config_file:${file}`),
30
- ...relativePaths.map((file) => `relative_agent_config_file:${file}`),
31
- ...(unsupportedRoleFields ? ['unsupported_message_role_prefix_field'] : []),
32
- ...tomlSmoke.blockers,
33
- ...orphanChildTables.map((table) => `orphan_mcp_child_table:${table}`)
34
- ]
55
+ blockers
35
56
  };
36
- if (input.reportPath !== null)
57
+ if (input.reportPath !== null) {
37
58
  await writeJsonAtomic(input.reportPath || path.join(root, '.sneakoscope', 'reports', 'codex-startup-config-postcheck.json'), report).catch(() => undefined);
59
+ }
38
60
  return report;
39
61
  }
40
- function managedAgentBlocks(text) {
41
- const blocks = tomlBlocks(text);
42
- return blocks.filter((block) => {
43
- if (!block.header.startsWith('agents.'))
44
- return false;
45
- const role = block.header.slice('agents.'.length);
46
- if (managedAgentRoleConfigForRole(role))
47
- return true;
48
- const configFile = block.text.match(/^\s*config_file\s*=\s*"([^"]+)"/m)?.[1] || '';
49
- return Boolean(configFile && managedAgentRoleConfigForFile(configFile));
50
- });
51
- }
52
- function tomlBlocks(text) {
53
- const source = String(text || '');
54
- const matches = [...source.matchAll(/(^|\n)\s*\[([^\]]+)\]\s*(?:#.*)?(?:\n|$)/g)];
55
- return matches.map((match, index) => {
56
- const start = Number(match.index || 0) + (match[1] ? 1 : 0);
57
- const next = matches[index + 1];
58
- const end = next ? Number(next.index || 0) + (next[1] ? 1 : 0) : source.length;
59
- return { header: String(match[2] || '').trim(), text: source.slice(start, end) };
60
- });
61
- }
62
62
  function tomlSyntaxSmoke(text) {
63
63
  const blockers = [];
64
64
  for (const [index, line] of String(text || '').split(/\r?\n/).entries()) {
@@ -80,4 +80,14 @@ function orphanMcpChildTables(text) {
80
80
  return Boolean(match && !headers.has(`mcp_servers.${match[1]}`));
81
81
  });
82
82
  }
83
+ function tomlBlocks(text) {
84
+ const source = String(text || '');
85
+ const matches = [...source.matchAll(/(^|\n)\s*\[([^\]]+)\]\s*(?:#.*)?(?:\n|$)/g)];
86
+ return matches.map((match, index) => {
87
+ const start = Number(match.index || 0) + (match[1] ? 1 : 0);
88
+ const next = matches[index + 1];
89
+ const end = next ? Number(next.index || 0) + (next[1] ? 1 : 0) : source.length;
90
+ return { header: String(match[2] || '').trim(), text: source.slice(start, end) };
91
+ });
92
+ }
83
93
  //# sourceMappingURL=codex-startup-config-postcheck.js.map
@@ -3,6 +3,7 @@ import { runProcess } from './fsx.js';
3
3
  import { preserveCodexModelArgs } from './codex-model-guard.js';
4
4
  import { managedProxyEnvForChild } from './codex/managed-proxy-env.js';
5
5
  import { resolveCodexRuntime } from './codex-runtime/resolve-codex-runtime.js';
6
+ import { codexLbRecoveryBlockedProcessResult, withCodexLbCliLaunchRecovery } from './codex-control/codex-lb-launch-recovery.js';
6
7
  export async function findCodexBinary() {
7
8
  const resolved = await resolveCodexRuntime({
8
9
  explicitPath: process.env.DCODEX_CODEX_BIN || null,
@@ -39,30 +40,42 @@ export function buildCodexExecArgs({ root, prompt, outputFile, json = true, prof
39
40
  args.push(prompt);
40
41
  return args;
41
42
  }
42
- export async function runCodexExec({ root, prompt, outputFile, json = true, profile = null, extraArgs = [], onStdout, onStderr, logDir = null, stdoutFile = null, stderrFile = null, maxBufferBytes = 256 * 1024, timeoutMs = null }) {
43
- const bin = await findCodexBinary();
44
- if (!bin) {
45
- return {
46
- code: 127,
47
- stdout: '',
48
- stderr: 'Codex CLI not found. Install @openai/codex or set SKS_CODEX_BIN.',
49
- stdoutBytes: 0,
50
- stderrBytes: 0,
51
- truncated: false,
52
- timedOut: false
53
- };
54
- }
43
+ export async function runCodexExec({ root, recoveryRoot = root, prompt, outputFile, json = true, profile = null, extraArgs = [], onStdout, onStderr, logDir = null, stdoutFile = null, stderrFile = null, maxBufferBytes = 256 * 1024, timeoutMs = null, env = process.env, codexBin = null, findCodexBinaryImpl = findCodexBinary, runProcessImpl = runProcess, recoveryFetch = undefined, recoveryTimeoutMs = undefined }) {
55
44
  const args = buildCodexExecArgs({ root, prompt, outputFile, json, profile, extraArgs });
56
45
  const effectiveTimeoutMs = Number(timeoutMs || process.env.SKS_CODEX_TIMEOUT_MS || process.env.DCODEX_CODEX_TIMEOUT_MS || 30 * 60 * 1000);
57
- return runProcess(bin, args, {
58
- cwd: root,
59
- env: managedProxyEnvForChild(process.env),
60
- onStdout,
61
- onStderr,
62
- timeoutMs: effectiveTimeoutMs,
63
- maxOutputBytes: maxBufferBytes,
64
- stdoutFile: stdoutFile || (logDir ? path.join(logDir, 'codex.stdout.log') : undefined),
65
- stderrFile: stderrFile || (logDir ? path.join(logDir, 'codex.stderr.log') : undefined)
46
+ const recoveryArgs = args.slice(1, -1);
47
+ const guarded = await withCodexLbCliLaunchRecovery({
48
+ root: recoveryRoot,
49
+ env,
50
+ cliArgs: recoveryArgs,
51
+ ...(typeof recoveryFetch === 'function' ? { fetchImpl: recoveryFetch } : {}),
52
+ ...(recoveryTimeoutMs === undefined ? {} : { timeoutMs: recoveryTimeoutMs })
53
+ }, async () => {
54
+ const bin = codexBin || await findCodexBinaryImpl();
55
+ if (!bin) {
56
+ return {
57
+ code: 127,
58
+ stdout: '',
59
+ stderr: 'Codex CLI not found. Install @openai/codex or set SKS_CODEX_BIN.',
60
+ stdoutBytes: 0,
61
+ stderrBytes: 0,
62
+ truncated: false,
63
+ timedOut: false
64
+ };
65
+ }
66
+ return runProcessImpl(bin, args, {
67
+ cwd: root,
68
+ env: { ...env, ...managedProxyEnvForChild(env) },
69
+ onStdout,
70
+ onStderr,
71
+ timeoutMs: effectiveTimeoutMs,
72
+ maxOutputBytes: maxBufferBytes,
73
+ stdoutFile: stdoutFile || (logDir ? path.join(logDir, 'codex.stdout.log') : undefined),
74
+ stderrFile: stderrFile || (logDir ? path.join(logDir, 'codex.stderr.log') : undefined)
75
+ });
66
76
  });
77
+ return guarded.launched
78
+ ? guarded.value
79
+ : codexLbRecoveryBlockedProcessResult(guarded.toolOutputRecovery);
67
80
  }
68
81
  //# sourceMappingURL=codex-adapter.js.map
@@ -1,23 +1,14 @@
1
- import fs from 'node:fs/promises';
2
1
  import path from 'node:path';
3
2
  import os from 'node:os';
4
- import { PACKAGE_VERSION, nowIso, writeJsonAtomic, writeTextAtomic, ensureDir } from '../fsx.js';
3
+ import { nowIso, writeJsonAtomic } from '../fsx.js';
5
4
  import { repairAgentRoleConfigs } from '../agents/agent-role-config.js';
5
+ import { MANAGED_OFFICIAL_SUBAGENT_ROLES } from '../managed-assets/managed-assets-manifest.js';
6
6
  import { agentRolePayloadFor, probeCodexAgentTypeSupport } from './codex-agent-type-probe.js';
7
- const DIRECTIVE_ROLES = [
8
- 'sks-explorer',
9
- 'sks-planner',
10
- 'sks-implementer',
11
- 'sks-checker',
12
- 'sks-release-verifier',
13
- 'sks-zellij-ui-verifier',
14
- 'sks-codex-probe-verifier'
15
- ];
7
+ const OFFICIAL_ROLES = MANAGED_OFFICIAL_SUBAGENT_ROLES.map((role) => role.codex_name);
16
8
  export async function syncCodexAgentRoles(input) {
17
9
  const root = path.resolve(input.root);
18
10
  const env = input.env || process.env;
19
11
  const codexHome = input.codexHome || process.env.CODEX_HOME || path.join(os.homedir(), '.codex');
20
- const targetDir = path.join(codexHome, 'agents');
21
12
  const baseRepair = await repairAgentRoleConfigs({
22
13
  root,
23
14
  apply: input.apply === true,
@@ -49,19 +40,9 @@ export async function syncCodexAgentRoles(input) {
49
40
  blockers: [],
50
41
  warnings: []
51
42
  };
52
- const rolePayloads = Object.fromEntries(DIRECTIVE_ROLES.map((role) => [role, agentRolePayloadFor(role, agentTypeProbe)]));
53
- const created = [];
54
- if (input.apply === true) {
55
- await ensureDir(targetDir);
56
- for (const role of DIRECTIVE_ROLES) {
57
- const file = path.join(targetDir, `${role}.toml`);
58
- const current = await fs.readFile(file, 'utf8').catch(() => '');
59
- if (current && !isSksManagedDirectiveRole(current))
60
- continue;
61
- await writeTextAtomic(file, roleToml(role, rolePayloads[role]));
62
- created.push(file);
63
- }
64
- }
43
+ const rolePayloads = Object.fromEntries(OFFICIAL_ROLES.map((role) => [role, agentRolePayloadFor(role, agentTypeProbe)]));
44
+ const created = stringList(baseRepair, 'created');
45
+ const updated = stringList(baseRepair, 'repaired');
65
46
  const report = {
66
47
  schema: 'sks.codex-agent-role-sync.v1',
67
48
  generated_at: nowIso(),
@@ -73,42 +54,18 @@ export async function syncCodexAgentRoles(input) {
73
54
  probe_artifact_path: '.sneakoscope/reports/codex-agent-type-probe.json',
74
55
  clobbered_user_roles: false,
75
56
  codex_home: codexHome,
76
- directive_roles: DIRECTIVE_ROLES,
57
+ official_roles: [...OFFICIAL_ROLES],
58
+ directive_roles: [],
77
59
  role_payloads: rolePayloads,
78
60
  agent_type_probe: agentTypeProbe,
79
61
  created,
62
+ updated,
80
63
  base_repair: baseRepair,
81
64
  blockers: blockersOf(baseRepair)
82
65
  };
83
66
  await writeJsonAtomic(path.join(root, '.sneakoscope', 'reports', 'codex-agent-role-sync.json'), report).catch(() => undefined);
84
67
  return report;
85
68
  }
86
- function roleToml(role, payload) {
87
- return [
88
- `name = "${role}"`,
89
- `description = "SKS managed ${PACKAGE_VERSION} directive role: ${role}"`,
90
- role.includes('implementer') ? 'sandbox_mode = "workspace-write"' : 'sandbox_mode = "read-only"',
91
- 'approval_policy = "never"',
92
- 'developer_instructions = """',
93
- `You are ${role}. SKS managed ${PACKAGE_VERSION} directive role with bounded ownership.`,
94
- 'Bounded ownership: use only the assigned owner files/directories and treat memory as guidance, not permission.',
95
- role.includes('implementer') ? 'Maker/checker separation: implementer may patch only owner scope and cannot self-approve.' : 'Maker/checker separation: checker is read-only and must reject missing gates or missing proof artifacts.',
96
- role.includes('implementer') ? 'Allowed sandbox: workspace-write only within assigned owner scope.' : 'Allowed sandbox: read-only; checker roles cannot mutate.',
97
- role.includes('release') ? 'Release verifier: verify version truth, release DAG coverage, package scripts, packlist, and changelog evidence.' : '',
98
- role.includes('zellij') ? 'UI/Zellij verifier: inspect readiness status, headless fallback, repair_required, pane proof, and slot telemetry without mutating unrelated UI state.' : '',
99
- role.includes('codex') ? 'Codex native verifier: inspect hook approval, agent_type, skill sync, plugin inventory, MCP candidates, and invocation plan artifacts.' : '',
100
- 'Side-effect restrictions: no destructive shell, package publish, global config mutation, database mutation, or external service write unless the sealed route contract explicitly allows it.',
101
- 'Required proof artifacts: cite concrete repo paths, command outputs, and route-local JSON proof before claiming completion.',
102
- 'Final arbiter constraints: parent integration owns final acceptance; this role supplies evidence and cannot override missing gates.',
103
- `Execution role strategy: ${payload?.strategy || 'message-role'}. Probe: ${payload?.probe_artifact_path || '.sneakoscope/reports/codex-agent-type-probe.json'}.`,
104
- '"""',
105
- ''
106
- ].join('\n');
107
- }
108
- function isSksManagedDirectiveRole(text) {
109
- return /SKS managed (?:3\.1\.(?:4|5|6|7|11)|4\.1\.\d+) (?:directive|bounded) role/.test(text)
110
- || /\bmessage_role_prefix\s*=/.test(text) && /SKS managed 3\.1\./.test(text);
111
- }
112
69
  function blockersOf(value) {
113
70
  return Boolean(value) && typeof value === 'object' && Array.isArray(value.blockers)
114
71
  ? (value.blockers).map((item) => String(item)).filter(Boolean)
@@ -119,8 +76,10 @@ function recordOk(value) {
119
76
  ? value.ok
120
77
  : undefined;
121
78
  }
122
- function escapeToml(value) {
123
- return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
79
+ function stringList(value, key) {
80
+ return Boolean(value) && typeof value === 'object' && Array.isArray(value[key])
81
+ ? value[key].map(String).filter(Boolean)
82
+ : [];
124
83
  }
125
84
  function messageOf(err) {
126
85
  return err instanceof Error ? err.message : String(err);
@@ -4,8 +4,12 @@ import { ensureDir, nowIso, readText, sha256, writeJsonAtomic, writeTextAtomic }
4
4
  import { codexHome, scanProjectLocalForbiddenKeys, snapshotCodexAppUiState } from './codex-app-ui-state-snapshot.js';
5
5
  import { assertCodexAppUiMutationAllowed } from './codex-app-ui-clobber-guard.js';
6
6
  import { codexProviderModelUiStatus } from '../codex-app.js';
7
+ import { cleanupCodexConfigBackups } from '../codex/codex-config-toml.js';
7
8
  export const CODEX_APP_FAST_UI_REPAIR_SCHEMA = 'sks.codex-app-fast-ui-repair.v1';
8
- const FAST_UI_TOP_LEVEL_RE = /^\s*(?:model|model_reasoning_effort|service_tier)\s*=/;
9
+ // `service_tier = "fast"` is the current Codex Desktop default-selection
10
+ // contract. Removing it would silently turn Fast mode off, not restore the
11
+ // selector. Only legacy SKS model/effort pins lock the native picker.
12
+ const FAST_UI_TOP_LEVEL_RE = /^\s*(?:model|model_reasoning_effort)\s*=/;
9
13
  const FAST_UI_FEATURE_LINE_RE = /^\s*fast_mode\s*=/;
10
14
  const FAST_UI_LEGACY_TABLES = new Set(['user.fast_mode', 'profiles.sks-fast-high']);
11
15
  const SKS_CAUSED_RE = /(?:SKS|Sneakoscope|codex-lb|sks-mad|sks fast)/i;
@@ -20,6 +24,7 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
20
24
  const actions = [];
21
25
  const detectedProjectLocalForbiddenKeys = [];
22
26
  const unsafeReasons = [];
27
+ let permissionsHardened = 0;
23
28
  let detectedSksCausedMutation = false;
24
29
  for (const candidate of candidates) {
25
30
  const text = await readText(candidate.file, null);
@@ -27,34 +32,39 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
27
32
  actions.push({ scope: candidate.scope, file: displayPath(candidate.file), status: 'missing', changed: false });
28
33
  continue;
29
34
  }
35
+ if (input.apply === true)
36
+ permissionsHardened += await hardenCodexConfigPermissions(candidate.file);
30
37
  const repaired = candidate.mode === 'project_forbidden_keys'
31
38
  ? stripProjectLocalForbiddenKeys(text)
32
39
  : stripSksCausedHostOwnedLines(text);
40
+ const candidateUnsafeReasons = detectUnsafeFastUiRepair(text);
41
+ unsafeReasons.push(...candidateUnsafeReasons);
33
42
  if (candidate.mode === 'project_forbidden_keys')
34
43
  detectedProjectLocalForbiddenKeys.push(...repaired.removedKeys);
35
44
  if (candidate.mode === 'sks_caused_host_owned_keys') {
36
- const unsafe = detectUnsafeFastUiRepair(text);
37
- unsafeReasons.push(...unsafe);
38
45
  if (repaired.text !== text)
39
46
  detectedSksCausedMutation = true;
40
47
  }
41
48
  if (repaired.text === text) {
42
- actions.push({ scope: candidate.scope, file: displayPath(candidate.file), status: unsafeReasons.length && candidate.mode === 'sks_caused_host_owned_keys' ? 'requires_confirmation' : 'ok', changed: false, removed_keys: repaired.removedKeys });
49
+ actions.push({ scope: candidate.scope, file: displayPath(candidate.file), status: candidateUnsafeReasons.length ? 'requires_confirmation' : 'ok', changed: false, removed_keys: repaired.removedKeys });
43
50
  continue;
44
51
  }
45
52
  const backupPath = `${candidate.file}.codex-app-ui-repair-${Date.now().toString(36)}.bak`;
46
- if (input.apply) {
53
+ const applyAllowed = input.apply === true && (candidateUnsafeReasons.length === 0 || input.force === true);
54
+ if (applyAllowed) {
47
55
  await ensureDir(path.dirname(candidate.file));
48
- await fs.writeFile(backupPath, text, 'utf8');
56
+ await fs.writeFile(backupPath, text, { encoding: 'utf8', mode: 0o600 });
57
+ await fs.chmod(backupPath, 0o600);
49
58
  assertCodexAppUiMutationAllowed({ kind: 'codex_app_ui_state', scope: 'codex-app-ui-repair', backupPath });
50
- await writeTextAtomic(candidate.file, repaired.text);
59
+ await writeTextAtomic(candidate.file, repaired.text, { mode: 0o600 });
60
+ await cleanupCodexConfigBackups(candidate.file, { keepPerTag: 3, maxAgeMs: 30 * 24 * 60 * 60 * 1000 }).catch(() => undefined);
51
61
  }
52
62
  actions.push({
53
63
  scope: candidate.scope,
54
64
  file: displayPath(candidate.file),
55
- status: input.apply ? 'repaired' : 'planned',
65
+ status: applyAllowed ? 'repaired' : input.apply ? 'requires_confirmation' : 'planned',
56
66
  changed: true,
57
- backup_path: input.apply ? displayPath(backupPath) : null,
67
+ backup_path: applyAllowed ? displayPath(backupPath) : null,
58
68
  before_hash: sha256(text),
59
69
  after_hash: sha256(repaired.text),
60
70
  removed_keys: repaired.removedKeys
@@ -63,17 +73,24 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
63
73
  const after = await snapshotCodexAppUiState(resolvedRoot, { codexHome: home });
64
74
  const providerModelUi = await codexProviderModelUiStatus({
65
75
  cwd: resolvedRoot,
76
+ env: input.env,
66
77
  home: path.dirname(home),
67
78
  configPath: path.join(home, 'config.toml'),
68
79
  codexLbEnvPath: path.join(home, 'sks-codex-lb.env')
69
80
  });
70
81
  const changed = actions.some((action) => action.changed);
82
+ const applied = actions.some((action) => action.status === 'repaired');
83
+ const pending = actions.some((action) => action.changed && action.status !== 'repaired');
71
84
  const requiresConfirmation = unsafeReasons.length > 0 && input.force !== true;
85
+ const selectedProviderBlockers = Array.isArray(providerModelUi.selected_provider_blockers)
86
+ ? providerModelUi.selected_provider_blockers
87
+ : [];
72
88
  const safeAutoApply = changed && !requiresConfirmation;
73
89
  const manual = changed && !input.apply;
74
90
  const blockers = [
75
91
  ...(requiresConfirmation ? ['codex_app_fast_ui_repair_requires_confirmation'] : []),
76
92
  ...(manual && !safeAutoApply ? ['codex_app_fast_ui_repair_requires_explicit_apply'] : []),
93
+ ...selectedProviderBlockers.map((blocker) => `selected_provider:${blocker}`),
77
94
  ...(after.indicators.secret_leak_suspected ? ['codex_app_ui_repair_secret_leak_suspected'] : [])
78
95
  ];
79
96
  const report = {
@@ -86,12 +103,15 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
86
103
  detected_sks_caused_mutation: detectedSksCausedMutation,
87
104
  detected_project_local_forbidden_keys: [...new Set(detectedProjectLocalForbiddenKeys)],
88
105
  unsafe_repair_reasons: [...new Set(unsafeReasons)],
89
- fast_selector: changed ? (input.apply ? 'repaired' : 'manual_action_required') : before.indicators.fast_selector === 'maybe_hidden_or_locked' ? 'manual_action_required' : 'ok',
90
- provider_selector: providerModelUi.ok ? 'ok' : 'manual_action_required',
106
+ permissions_hardened: permissionsHardened,
107
+ fast_selector: pending ? 'manual_action_required' : applied ? 'repaired' : before.indicators.fast_selector === 'maybe_hidden_or_locked' ? 'manual_action_required' : 'ok',
108
+ provider_selector: selectedProviderBlockers.length ? 'manual_action_required' : 'selected_provider_ready',
91
109
  provider_model_ui: providerModelUi,
92
110
  provider_actions: providerModelUi.ui_actions || [],
93
111
  provider_blockers: providerModelUi.blockers || [],
94
- host_owned_config: input.apply && changed ? 'repaired_with_backup' : changed ? 'preserved_until_explicit_apply' : 'preserved',
112
+ selected_provider_blockers: selectedProviderBlockers,
113
+ optional_provider_blockers: providerModelUi.optional_provider_blockers || [],
114
+ host_owned_config: applied && !pending ? 'repaired_with_backup' : changed ? 'preserved_until_explicit_apply' : 'preserved',
95
115
  actions,
96
116
  before_fast_selector: before.indicators.fast_selector,
97
117
  after_fast_selector: after.indicators.fast_selector,
@@ -102,16 +122,27 @@ export async function repairCodexAppFastUi(root = process.cwd(), input = {}) {
102
122
  await writeJsonAtomic(input.reportPath, report);
103
123
  return report;
104
124
  }
125
+ async function hardenCodexConfigPermissions(configFile) {
126
+ const dir = path.dirname(configFile);
127
+ const base = path.basename(configFile);
128
+ const entries = await fs.readdir(dir, { withFileTypes: true }).catch(() => []);
129
+ const targets = [configFile, ...entries
130
+ .filter((entry) => entry.isFile() && entry.name.startsWith(`${base}.`) && entry.name.endsWith('.bak'))
131
+ .map((entry) => path.join(dir, entry.name))];
132
+ let hardened = 0;
133
+ for (const target of targets) {
134
+ const stat = await fs.lstat(target).catch(() => null);
135
+ if (!stat?.isFile() || stat.isSymbolicLink())
136
+ continue;
137
+ if ((stat.mode & 0o777) !== 0o600) {
138
+ await fs.chmod(target, 0o600);
139
+ hardened += 1;
140
+ }
141
+ }
142
+ return hardened;
143
+ }
105
144
  function detectUnsafeFastUiRepair(text) {
106
145
  const reasons = [];
107
- const lines = text.split(/\r?\n/);
108
- for (let i = 0; i < lines.length; i += 1) {
109
- const line = lines[i] || '';
110
- const serviceTier = line.match(/^\s*service_tier\s*=\s*"(standard|flex)"\s*(?:#.*)?$/i)?.[1];
111
- const sksMarked = SKS_CAUSED_RE.test(line) || SKS_CAUSED_RE.test(lines[i - 1] || '') || SKS_CAUSED_RE.test(lines[i + 1] || '');
112
- if (serviceTier && !sksMarked)
113
- reasons.push(`user_selected_service_tier_${serviceTier.toLowerCase()}`);
114
- }
115
146
  if (hasOddUnescapedQuotes(text))
116
147
  reasons.push('unparseable_config_requires_manual_review');
117
148
  return [...new Set(reasons)];