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
@@ -16,12 +16,15 @@ const sources = {
16
16
  coreSkill: readText('src/core/skills/core-skill-types.ts')
17
17
  };
18
18
  const teamCreateRedirectsToNaruto = sources.team.includes('redirectTeamCreateToNaruto') && sources.team.includes('narutoCommand');
19
- assertGate(teamCreateRedirectsToNaruto, 'Team create must route through Naruto codex-sdk SSOT');
19
+ assertGate(teamCreateRedirectsToNaruto, 'Team create must route through the Naruto official-subagent SSOT');
20
20
  assertGate(sources.qa.includes("mock ? 'fake' : 'codex-sdk'"), 'QA must route native agents through codex-sdk');
21
- assertGate(sources.research.includes("mock ? 'fake' : 'codex-sdk'"), 'Research must route native agents through codex-sdk');
22
- assertGate(sources.naruto.includes("backend: 'codex-sdk'"), 'Naruto defaults must name codex-sdk');
21
+ assertGate(sources.research.includes("backend: mock ? 'mock' : 'codex-sdk'")
22
+ && sources.research.includes("reviewer_workflow: 'official_codex_subagent'"), 'Research must use the Codex SDK stage backend plus the official subagent reviewer workflow');
23
+ assertGate(sources.naruto.includes('runOfficialSubagentWorkflow'), 'Naruto must invoke the official Codex subagent runner');
24
+ assertGate(sources.naruto.includes("workflow: 'official_codex_subagent'"), 'Naruto must persist the official subagent workflow contract');
25
+ assertGate(!sources.naruto.includes("backend: 'codex-sdk'"), 'Naruto must not select the legacy codex-sdk backend');
23
26
  assertGate(sources.coreSkill.includes("'codex-sdk'"), 'Core skill backend type must include codex-sdk');
24
27
  const fixture = await runFakeCodexSdkTaskFixture('all-pipelines');
25
28
  assertGate(fixture.result.ok === true, 'all pipeline SDK fixture must pass', fixture.result);
26
- emitGate('codex-sdk:all-pipelines', { gates: required.length, sdk_thread_id: fixture.result.sdkThreadId });
29
+ emitGate('codex-sdk:all-pipelines', { gates: required.length, naruto_workflow: 'official_codex_subagent', sdk_thread_id: fixture.result.sdkThreadId });
27
30
  //# sourceMappingURL=codex-sdk-all-pipelines-check.js.map
@@ -5,21 +5,29 @@ import os from 'node:os';
5
5
  import path from 'node:path';
6
6
  import { assertGate, emitGate, importDist, readText } from './lib/codex-sdk-gate-lib.js';
7
7
  const researchCommand = readText('src/core/commands/research-command.ts');
8
- assertGate(researchCommand.includes("backend: mock ? 'fake' : 'codex-sdk'"), 'Research pipeline must default native agents to codex-sdk');
9
- assertGate(researchCommand.includes("flag(args, '--autoresearch') ? '$AutoResearch' : '$Research'"), 'Research/AutoResearch route selection missing');
10
- assertGate(researchCommand.includes('narutoWorkGraph: researchWorkGraph'), 'Research pipeline must pass the stage-aware Naruto work graph');
11
- assertGate(researchCommand.includes('readonly: true'), 'Research pipeline must force read-only native orchestration');
8
+ assertGate(researchCommand.includes("backend: mock ? 'mock' : 'codex-sdk'"), 'Research stage cycle must use the Codex SDK only as a bounded source/synthesis adapter');
9
+ assertGate(researchCommand.includes("source_acquisition: 'super-search'"), 'Research must route source acquisition through Super Search');
10
+ assertGate(researchCommand.includes("reviewer_workflow: 'official_codex_subagent'"), 'Research must use the official Codex subagent reviewer workflow');
12
11
  assertGate(researchCommand.includes('quality_metrics'), 'Research pipeline JSON output must include quality metrics');
13
12
  assertGate(researchCommand.includes('const cycleResult = await runResearchCycle({'), 'Research default path must use runResearchCycle');
14
- assertGate(researchCommand.includes('--legacy-research-cycle'), 'Legacy final.md loop must be opt-in only');
13
+ for (const removed of ['runNativeAgentOrchestrator', 'SKS_RESEARCH_LEGACY_CYCLE', 'runCodexExec({']) {
14
+ assertGate(!researchCommand.includes(removed), `Research legacy runtime token must be removed: ${removed}`);
15
+ }
16
+ assertGate(researchCommand.includes('REMOVED_RESEARCH_RUNTIME_FLAGS')
17
+ && researchCommand.includes('Unsupported legacy Research runtime option:'), 'Research must fail closed on removed runtime options');
18
+ for (const removedFlag of ['--legacy-research-cycle', '--native-proof-only']) {
19
+ assertGate(researchCommand.includes(removedFlag), `Research removed-option blocker must include ${removedFlag}`);
20
+ }
15
21
  const researchCore = readText('src/core/research.ts');
16
22
  assertGate(researchCore.includes('readResearchQualityContract'), 'Research gate must read research-quality-contract.json');
17
23
  assertGate(researchCore.includes('claim_evidence_matrix_missing'), 'Research gate must require claim-evidence-matrix.json');
18
24
  assertGate(researchCore.includes('research_final_review_not_approved'), 'Research gate must require final reviewer approval');
19
25
  for (const [file, tokens] of Object.entries({
20
- 'src/core/research/research-work-graph.ts': ['buildResearchWorkGraph', 'source_shard_academic_literature'],
26
+ 'src/core/research/research-work-graph.ts': ['buildResearchWorkGraph', 'REQUIRED_SOURCE_SHARD_IDS', 'source_shard_${layer.id}'],
21
27
  'src/core/research/research-cycle-runner.ts': ['runResearchCycle', 'Promise.race'],
22
- 'src/core/research/research-final-reviewer.ts': ['runResearchCodexFinalReviewer'],
28
+ 'src/core/research/research-final-reviewer.ts': ['runResearchCodexFinalReviewer', 'research_final_reviewer_static_plus_official_subagents'],
29
+ 'src/core/research/research-adversarial-review.ts': ['runResearchAdversarialReviewLoop', 'official_codex_subagent', 'critical_objections_unresolved'],
30
+ 'src/core/research/research-super-search.ts': ['runResearchSuperSearchShard', 'runSuperSearch'],
23
31
  'src/core/research/claim-evidence-matrix.ts': ['claim-evidence-matrix'],
24
32
  'src/core/research/implementation-blueprint.ts': ['implementation-blueprint'],
25
33
  'src/core/research/research-quality-contract.ts': ['research-quality-contract']
@@ -30,6 +38,8 @@ for (const [file, tokens] of Object.entries({
30
38
  }
31
39
  const research = await importDist('core/research.js');
32
40
  const fsx = await importDist('core/fsx.js');
41
+ const adversarial = await importDist('core/research/research-adversarial-review.js');
42
+ const finalReviewer = await importDist('core/research/research-final-reviewer.js');
33
43
  const dirShort = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-codex-research-short-'));
34
44
  const planShort = await research.writeResearchPlan(dirShort, 'codex sdk short rejection fixture', { missionId: 'M-CODEX-SHORT' });
35
45
  await fsx.writeTextAtomic(path.join(dirShort, 'research-report.md'), `# Short Report\n\n${Array.from({ length: 300 }, (_unused, index) => `word${index}`).join(' ')}\n`);
@@ -40,7 +50,19 @@ assertGate(shortGate.passed === false, 'codex-sdk research pipeline must reject
40
50
  assertGate((shortGate.reasons || []).includes('research_report_too_short'), 'short rejection must include report length reason', shortGate);
41
51
  const dirComplete = fs.mkdtempSync(path.join(os.tmpdir(), 'sks-codex-research-complete-'));
42
52
  const planComplete = await research.writeResearchPlan(dirComplete, 'codex sdk complete package fixture', { missionId: 'M-CODEX-COMPLETE' });
43
- const completeGate = await research.writeMockResearchResult(dirComplete, planComplete);
53
+ await research.writeMockResearchResult(dirComplete, planComplete);
54
+ const adversarialResult = await adversarial.runResearchAdversarialReviewLoop({
55
+ root: process.cwd(),
56
+ dir: dirComplete,
57
+ plan: planComplete,
58
+ timeoutMs: 1_000,
59
+ maxCycles: 1,
60
+ maxThreads: 5,
61
+ mock: true
62
+ });
63
+ assertGate(adversarialResult.ok === true, 'mock complete package must pass official-subagent adversarial contract', adversarialResult);
64
+ await finalReviewer.runResearchFinalReviewer(dirComplete, { plan: planComplete, root: process.cwd(), mock: true });
65
+ const completeGate = await research.evaluateResearchGate(dirComplete);
44
66
  assertGate(completeGate.passed === true, 'codex-sdk research pipeline must pass complete package fixture', completeGate);
45
67
  assertGate(completeGate.metrics?.final_review_approved === true, 'complete package must include approved final review', completeGate.metrics);
46
68
  emitGate('codex-sdk:research-pipeline', { route: '$Research', short_dir: dirShort, complete_dir: dirComplete });
@@ -12,10 +12,14 @@ const base = {
12
12
  mutationLedgerRoot: process.cwd()
13
13
  };
14
14
  const readOnly = mod.mapCodexSdkSandboxPolicy({ ...base, sandboxPolicy: 'read-only', requestedScopeContract: { read_only: true } });
15
+ const readOnlyContract = mod.mapCodexSdkSandboxPolicy({ ...base, sandboxPolicy: 'workspace-write', requestedScopeContract: { read_only: true, allowed_paths: ['tmp'], write_paths: ['tmp'] } });
16
+ const emptyWriteScope = mod.mapCodexSdkSandboxPolicy({ ...base, sandboxPolicy: 'workspace-write', requestedScopeContract: { read_only: false, allowed_paths: [], write_paths: [] } });
15
17
  const workspace = mod.mapCodexSdkSandboxPolicy({ ...base, sandboxPolicy: 'workspace-write', requestedScopeContract: { read_only: false, allowed_paths: ['tmp'], write_paths: ['tmp'] } });
16
18
  const fullBlocked = mod.mapCodexSdkSandboxPolicy({ ...base, sandboxPolicy: 'full-access', requestedScopeContract: { read_only: false } });
17
19
  assertGate(readOnly.ok && readOnly.sandboxMode === 'read-only', 'read-only sandbox mapping failed', readOnly);
20
+ assertGate(readOnlyContract.ok && readOnlyContract.sandboxMode === 'read-only', 'read-only scope contract must not be escalated by a stale workspace policy', readOnlyContract);
21
+ assertGate(emptyWriteScope.ok && emptyWriteScope.sandboxMode === 'read-only', 'empty write scope must collapse to read-only', emptyWriteScope);
18
22
  assertGate(workspace.ok && workspace.sandboxMode === 'workspace-write', 'workspace-write sandbox mapping failed', workspace);
19
23
  assertGate(!fullBlocked.ok && fullBlocked.blockers.includes('codex_sdk_full_access_requires_explicit_mad_scope'), 'full-access must require explicit authorization', fullBlocked);
20
- emitGate('codex-sdk:sandbox-policy', { read_only: readOnly.sandboxMode, workspace: workspace.sandboxMode, full_blockers: fullBlocked.blockers });
24
+ emitGate('codex-sdk:sandbox-policy', { read_only: readOnly.sandboxMode, read_only_contract: readOnlyContract.sandboxMode, empty_write_scope: emptyWriteScope.sandboxMode, workspace: workspace.sandboxMode, full_blockers: fullBlocked.blockers });
21
25
  //# sourceMappingURL=codex-sdk-sandbox-policy-check.js.map
@@ -1,10 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  // @ts-nocheck
3
3
  import { assertGate, emitGate, readJson } from './sks-1-18-gate-lib.js';
4
+ import { CURRENT_CODEX_RELEASE_MANIFEST } from '../core/codex-compat/codex-release-manifest.js';
4
5
  const pkg = readJson('package.json');
5
6
  const lock = readJson('package-lock.json');
6
7
  const dep = pkg.dependencies?.['@openai/codex-sdk'];
7
8
  const lockDep = lock.packages?.['node_modules/@openai/codex-sdk']?.version;
8
- assertGate(dep === '0.142.0' && lockDep === '0.142.0', '@openai/codex-sdk must be pinned to 0.142.0 compatibility in package and lockfile', { dep, lockDep });
9
+ assertGate(dep === CURRENT_CODEX_RELEASE_MANIFEST.sdkVersion && lockDep === CURRENT_CODEX_RELEASE_MANIFEST.sdkVersion, `@openai/codex-sdk must be pinned to ${CURRENT_CODEX_RELEASE_MANIFEST.sdkVersion} compatibility in package and lockfile`, { dep, lockDep, manifestSdkVersion: CURRENT_CODEX_RELEASE_MANIFEST.sdkVersion });
9
10
  emitGate('codex-sdk:version-compat', { dependency: dep, lock_version: lockDep });
10
11
  //# sourceMappingURL=codex-sdk-version-compat-check.js.map
@@ -0,0 +1,33 @@
1
+ #!/usr/bin/env node
2
+ import fsp from 'node:fs/promises';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { prepareRoute } from '../core/pipeline-internals/runtime-core.js';
6
+ const root = await fsp.mkdtemp(path.join(os.tmpdir(), 'sks-db-route-materialization-'));
7
+ try {
8
+ await fsp.writeFile(path.join(root, 'package.json'), `${JSON.stringify({ name: 'sks-db-route-fixture', private: true }, null, 2)}\n`);
9
+ const prepared = await prepareRoute(root, '$DB inspect the local migration safely', {});
10
+ const missionId = String(prepared?.mission_id || '');
11
+ if (!missionId || prepared?.route?.id !== 'DB')
12
+ throw new Error('DB route did not materialize a mission');
13
+ const dir = path.join(root, '.sneakoscope', 'missions', missionId);
14
+ const scan = JSON.parse(await fsp.readFile(path.join(dir, 'db-safety-scan.json'), 'utf8'));
15
+ const review = JSON.parse(await fsp.readFile(path.join(dir, 'db-review.json'), 'utf8'));
16
+ if (typeof scan?.ok !== 'boolean')
17
+ throw new Error('db-safety-scan.json is missing an ok decision');
18
+ if (typeof review?.scan_ok !== 'boolean' || review?.destructive_operation_zero !== true) {
19
+ throw new Error('db-review.json is missing the fail-closed safety baseline');
20
+ }
21
+ console.log(JSON.stringify({
22
+ schema: 'sks.db-route-materialization-check.v1',
23
+ ok: true,
24
+ route: '$DB',
25
+ mission_id: missionId,
26
+ artifacts: ['db-safety-scan.json', 'db-review.json'],
27
+ legacy_cli_registered: false
28
+ }, null, 2));
29
+ }
30
+ finally {
31
+ await fsp.rm(root, { recursive: true, force: true });
32
+ }
33
+ //# sourceMappingURL=db-route-materialization-check.js.map
@@ -2,5 +2,5 @@
2
2
  // @ts-nocheck
3
3
  import { emitGate, runDfixFixture } from './sks-1-11-gate-lib.js';
4
4
  const result = runDfixFixture();
5
- emitGate('dfix:fixture', { mission_id: result.mission_id });
5
+ emitGate('dfix:fixture', { mission_id: result.mission_id, fixture_root: result.fixture_root });
6
6
  //# sourceMappingURL=dfix-fixture-check.js.map
@@ -12,6 +12,7 @@ const files = [
12
12
  'docs/codex-0.136-compat.md',
13
13
  'docs/codex-0.135-compat.md',
14
14
  'docs/codex-cli-compat.md',
15
+ 'docs/codex-app.md',
15
16
  'docs/official-docs-compat.md',
16
17
  'docs/hooks-pat.md',
17
18
  'docs/known-gaps.md',
@@ -24,8 +25,9 @@ const required = {
24
25
  'docs/codex-lb.md': ['durable_env_file', 'durable_keychain', 'shell_profile', 'process_only_ephemeral', 'base URL only'],
25
26
  'docs/codex-0.136-compat.md': ['rust-v0.136.0', 'codex:0.136-compat', 'codex archive', 'codex app-server --stdio', 'CODEX_API_KEY', 'server tokens'],
26
27
  'docs/codex-0.135-compat.md': ['rust-v0.135.0', 'codex:0.135-compat', 'named permission profiles'],
27
- 'docs/codex-cli-compat.md': ['rust-v0.136.0', 'session_archive_restore', 'profile_primary_selector', 'managed_network_proxy_env', 'goals_default_enabled', 'permission_profiles_requirements', 'SubagentStart', 'sks_zero_warning_disallowed', 'strict subset'],
28
- 'docs/official-docs-compat.md': ['official-docs:compat', 'rust-v0.136.0', 'gpt-image-2', 'input_fidelity', 'additionalProperties:false'],
28
+ 'docs/codex-cli-compat.md': ['rust-v0.144.1', 'sks codex 0.144', 'Inherited Codex 0.136 Capabilities', 'session_archive_restore', 'profile_primary_selector', 'managed_network_proxy_env', 'goals_default_enabled', 'permission_profiles_requirements', 'SubagentStart', 'sks_zero_warning_disallowed', 'strict subset'],
29
+ 'docs/codex-app.md': ['rust-v0.144.1', 'sks codex 0.144', 'App Server v2', 'Codex Chrome Extension', 'gpt-image-2'],
30
+ 'docs/official-docs-compat.md': ['official-docs-compat-report.js', 'rust-v0.144.1', 'gpt-image-2', 'input_fidelity', 'additionalProperties:false'],
29
31
  'docs/hooks-pat.md': ['SubagentStop', 'strict subset', 'zero-warning'],
30
32
  'docs/known-gaps.md': ['No P0', 'P1'],
31
33
  'docs/release-readiness.md': ['sks.release-readiness.v1', 'release:readiness', 'official-docs:compat']
@@ -15,24 +15,17 @@ const codexHome = path.join(tmp, 'codex-home');
15
15
  await fs.mkdir(path.join(tmp, '.codex', 'agents'), { recursive: true });
16
16
  await fs.mkdir(path.join(codexHome, 'agents'), { recursive: true });
17
17
  const staleConfig = [
18
- 'model = "gpt-5.5"',
18
+ '# SKS managed Codex config fixture',
19
+ 'model = "gpt-5.6-terra"',
19
20
  '',
20
21
  '[agents.analysis_scout]',
21
22
  'description = "Read-only SKS scout."',
22
23
  'config_file = "/Users/alfredo/.codex/agents/analysis-scout.toml"',
23
24
  'nickname_candidates = ["Scout", "Mapper"]',
24
25
  '',
25
- '[agents.analysis_scout]',
26
- 'description = "SKS scout with bounded write capability."',
27
- 'config_file = "./agents/analysis-scout.toml"',
28
- 'nickname_candidates = ["Scout", "Mapper"]',
29
- '',
30
26
  '[mcp_servers.context7]',
31
27
  'url = "https://custom.context7.example/mcp"',
32
28
  '',
33
- '[mcp_servers.context7]',
34
- 'url = "https://mcp.context7.com/mcp"',
35
- '',
36
29
  '[mcp_servers.node_repl]',
37
30
  'command = "/definitely/missing/node_repl"',
38
31
  'args = []',
@@ -60,20 +53,19 @@ await writeTextAtomic(path.join(codexHome, 'agents', 'sks-checker.toml'), [
60
53
  ''
61
54
  ].join('\n'));
62
55
  const planned = await mod.runDoctorCodexStartupRepair({ root: tmp, codexHome, fix: false });
63
- assertGate(planned.configs.every((entry) => entry.warnings.some((warning) => warning.includes('agent_config_file_stale'))), 'dry inspect must detect stale agent config_file paths', planned);
56
+ assertGate(planned.configs.every((entry) => !entry.warnings.some((warning) => warning.includes('agent_config_file_stale'))), 'structural startup inspection must ignore preserved legacy agent config_file paths', planned);
64
57
  const repaired = await mod.runDoctorCodexStartupRepair({ root: tmp, codexHome, fix: true, includeDefaultNodeReplCandidates: false });
65
58
  const projectText = await fs.readFile(path.join(tmp, '.codex', 'config.toml'), 'utf8');
66
59
  const globalText = await fs.readFile(path.join(codexHome, 'config.toml'), 'utf8');
67
60
  const checkerText = await fs.readFile(path.join(codexHome, 'agents', 'sks-checker.toml'), 'utf8');
68
- const projectScoutText = await fs.readFile(path.join(tmp, '.codex', 'agents', 'analysis-scout.toml'), 'utf8');
69
- const globalScoutText = await fs.readFile(path.join(codexHome, 'agents', 'analysis-scout.toml'), 'utf8');
70
- for (const [scope, text, expectedDir] of [
71
- ['project', projectText, path.join(tmp, '.codex', 'agents')],
72
- ['global', globalText, path.join(codexHome, 'agents')]
61
+ const projectScoutPresent = await fs.stat(path.join(tmp, '.codex', 'agents', 'analysis-scout.toml')).then(() => true).catch(() => false);
62
+ const globalScoutPresent = await fs.stat(path.join(codexHome, 'agents', 'analysis-scout.toml')).then(() => true).catch(() => false);
63
+ for (const [scope, text] of [
64
+ ['project', projectText],
65
+ ['global', globalText]
73
66
  ]) {
74
- assertGate(!text.includes('/Users/alfredo/'), `${scope} config must drop stale home path`, text);
75
- assertGate(text.includes(`config_file = "${path.join(expectedDir, 'analysis-scout.toml').replace(/\\/g, '\\\\')}"`), `${scope} config_file must point at an existing absolute role file`, text);
76
- assertGate(text.includes('description = "SKS scout with bounded write capability."'), `${scope} managed agent description must be write-capable`, text);
67
+ assertGate(text.includes('/Users/alfredo/.codex/agents/analysis-scout.toml'), `${scope} legacy config_file must be preserved`, text);
68
+ assertGate(text.includes('description = "Read-only SKS scout."'), `${scope} legacy agent description must be preserved`, text);
77
69
  assertGate(!text.includes('[mcp_servers.node_repl]'), `${scope} stale node_repl MCP block must be removed`, text);
78
70
  assertGate(!text.includes('[mcp_servers.node_repl.env]'), `${scope} stale node_repl child MCP block must be removed`, text);
79
71
  assertGate((text.match(/\[mcp_servers\.context7\]/g) || []).length === 1, `${scope} duplicate context7 MCP block must be deduped`, text);
@@ -81,16 +73,45 @@ for (const [scope, text, expectedDir] of [
81
73
  assertGate(text.includes('[mcp_servers.supabase_sauron]'), `${scope} optional sauron MCP block must be preserved`, text);
82
74
  assertGate(text.includes('[features]') && text.includes('hooks = true'), `${scope} unrelated tables must be preserved`, text);
83
75
  }
84
- for (const [scope, text] of [['project', projectScoutText], ['global', globalScoutText]]) {
85
- assertGate(text.includes('sandbox_mode = "workspace-write"'), `${scope} agent role file must be workspace-write`, text);
86
- assertGate(!text.includes('Do not edit files.'), `${scope} agent role file must not preserve stale read-only instruction`, text);
87
- }
88
- assertGate(!checkerText.includes('message_role_prefix'), 'managed directive agent role must remove unsupported message_role_prefix', checkerText);
76
+ assertGate(projectScoutPresent === false && globalScoutPresent === false, 'structural startup repair must not synthesize legacy role TOMLs', { projectScoutPresent, globalScoutPresent });
77
+ assertGate(checkerText.includes('message_role_prefix'), 'legacy directive role TOMLs must be preserved byte-for-byte', checkerText);
89
78
  assertGate(repaired.ok === true, 'startup repair must pass when only optional sauron remains', repaired);
90
79
  assertGate(repaired.configs.every((entry) => entry.changed === true && entry.backup_path), 'startup repair must back up changed configs', repaired);
91
- assertGate(repaired.agent_role_files.created.length >= 10, 'startup repair must create missing project/global role configs', repaired);
80
+ assertGate(repaired.agent_role_files.created.length === 0 && repaired.agent_role_files.sanitized.length === 0, 'startup repair must leave project/global agent role files untouched', repaired);
81
+ assertGate(repaired.configs.every((entry) => entry.agent_config_files_repaired.length === 0), 'startup repair must not rewrite legacy agent config_file references', repaired);
92
82
  assertGate(repaired.configs.every((entry) => !entry.warnings.some((warning) => warning.includes('agent_config_file_stale'))), 'startup repair must not keep stale agent config warnings after repair', repaired);
93
- assertGate(repaired.configs.every((entry) => entry.duplicate_toml_blocks_removed.includes('agents.analysis_scout') && entry.duplicate_toml_blocks_removed.includes('mcp_servers.context7')), 'startup repair must record duplicate managed/external table dedupe without rewriting preserved MCP values', repaired);
83
+ assertGate(repaired.configs.every((entry) => entry.duplicate_toml_blocks_removed.length === 0), 'valid startup repair fixture must not claim duplicate-invalid TOML repair', repaired);
84
+ const tmpInvalid = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-codex-startup-invalid-'));
85
+ const codexHomeInvalid = path.join(tmpInvalid, 'codex-home');
86
+ await fs.mkdir(path.join(tmpInvalid, '.codex'), { recursive: true });
87
+ await fs.mkdir(codexHomeInvalid, { recursive: true });
88
+ const duplicateInvalidConfig = [
89
+ '# SKS managed Codex config fixture',
90
+ '[agents.analysis_scout]',
91
+ 'description = "Read-only SKS scout."',
92
+ 'config_file = "/Users/alfredo/.codex/agents/analysis-scout.toml"',
93
+ '',
94
+ '[agents.analysis_scout]',
95
+ 'description = "SKS scout with bounded write capability."',
96
+ 'config_file = "./agents/analysis-scout.toml"',
97
+ ''
98
+ ].join('\n');
99
+ const invalidConfigPath = path.join(tmpInvalid, '.codex', 'config.toml');
100
+ await writeTextAtomic(invalidConfigPath, duplicateInvalidConfig);
101
+ const invalidRepair = await mod.runDoctorCodexStartupRepair({
102
+ root: tmpInvalid,
103
+ codexHome: codexHomeInvalid,
104
+ fix: true,
105
+ includeDefaultNodeReplCandidates: false
106
+ });
107
+ const invalidEntry = invalidRepair.configs.find((entry) => entry.scope === 'project');
108
+ const invalidAfter = await fs.readFile(invalidConfigPath, 'utf8');
109
+ assertGate(invalidRepair.ok === false, 'duplicate-invalid TOML must fail closed instead of being reported repaired', invalidRepair);
110
+ assertGate(invalidAfter === duplicateInvalidConfig, 'duplicate-invalid TOML must remain byte-for-byte unchanged', { before: duplicateInvalidConfig, after: invalidAfter });
111
+ assertGate(invalidEntry?.changed === false, 'guarded refusal must not report the invalid config as changed', invalidEntry);
112
+ assertGate(Boolean(invalidEntry?.backup_path), 'guarded refusal must back up duplicate-invalid TOML', invalidEntry);
113
+ assertGate(invalidEntry?.blockers.includes('config_write_guard:unparseable_config_preserved'), 'guarded refusal status must be a startup repair blocker', invalidEntry);
114
+ assertGate(invalidEntry?.duplicate_toml_blocks_removed.length === 0, 'guarded refusal must not claim duplicate table removal', invalidEntry);
94
115
  const tmpCandidate = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-codex-startup-node-repl-'));
95
116
  const codexHomeCandidate = path.join(tmpCandidate, 'codex-home');
96
117
  const fakeNodeRepl = path.join(tmpCandidate, 'Codex.app', 'Contents', 'Resources', 'cua_node', 'bin', 'node_repl');
@@ -99,6 +120,7 @@ await writeTextAtomic(fakeNodeRepl, '#!/bin/sh\n');
99
120
  await fs.mkdir(path.join(tmpCandidate, '.codex'), { recursive: true });
100
121
  await fs.mkdir(codexHomeCandidate, { recursive: true });
101
122
  const missingNodeReplConfig = [
123
+ '# SKS managed Codex config fixture',
102
124
  '[mcp_servers.node_repl]',
103
125
  'command = "/definitely/missing/node_repl"',
104
126
  'args = []',
@@ -15,7 +15,8 @@ const codexHome = path.join(tmp, 'codex-home');
15
15
  await fs.mkdir(path.join(tmp, '.codex'), { recursive: true });
16
16
  await fs.mkdir(codexHome, { recursive: true });
17
17
  const localBlock = [
18
- 'model = "gpt-5.5"',
18
+ '# SKS managed fixture',
19
+ 'model = "gpt-5.6-terra"',
19
20
  '',
20
21
  '[mcp_servers.context7]',
21
22
  'command = "npx"',
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env node
2
+ import fs from 'node:fs/promises';
2
3
  import path from 'node:path';
4
+ import { parse } from 'smol-toml';
3
5
  import { assertGate, emitGate, makeTempRoot, writeText } from './sks-3-1-8-check-lib.js';
4
6
  import { repairCodexStartupConfig } from '../core/doctor/codex-startup-config-repair.js';
5
7
  import { repairContext7Mcp } from '../core/doctor/context7-mcp-repair.js';
@@ -7,8 +9,16 @@ import { repairSupabaseMcp } from '../core/doctor/supabase-mcp-repair.js';
7
9
  import { runDoctorFixTransaction } from '../core/doctor/doctor-transaction.js';
8
10
  import { doctorRepairPostcheck } from '../core/doctor/doctor-repair-postcheck.js';
9
11
  const root = await makeTempRoot('sks-doctor-production-');
10
- await writeText(path.join(root, '.codex', 'config.toml'), '[mcp_servers.context7]\ncommand = "npx"\n\n[mcp_servers.supabase]\nurl = "https://supabase.example/mcp"\nread_only = true\n\n[agents.analysis_scout]\nconfig_file = ".codex/agents/stale.toml"\nmessage_role_prefix = "legacy"\n');
11
- const startup = await repairCodexStartupConfig({ root, apply: true });
12
+ await writeText(path.join(root, '.codex', 'config.toml'), '# SKS-MANAGED-CODEX-CONFIG\n[mcp_servers.context7]\ncommand = "npx"\n\n[mcp_servers.supabase]\nurl = "https://supabase.example/mcp"\nread_only = true\n\n[agents.analysis_scout]\nconfig_file = ".codex/agents/stale.toml"\nmessage_role_prefix = "legacy"\n');
13
+ const startup = await repairCodexStartupConfig({ root, apply: true, home: path.join(root, 'home'), codexHome: path.join(root, 'codex-home') });
14
+ const startupText = await fs.readFile(path.join(root, '.codex', 'config.toml'), 'utf8');
15
+ const startupConfig = parse(startupText);
16
+ const startupAgents = startupConfig.agents || {};
17
+ const startupAgentFiles = (await fs.readdir(path.join(root, '.codex', 'agents'))).sort();
18
+ assertGate(startup.ok === true, 'doctor production startup repair must pass', startup);
19
+ assertGate(startupAgents.max_threads === 12 && startupAgents.max_depth === 1 && startupAgents.job_max_runtime_seconds === 1200 && startupAgents.interrupt_message === true, 'doctor production startup repair must write official config defaults', startupAgents);
20
+ assertGate(startupAgentFiles.join(',') === 'expert.toml,worker.toml', 'doctor production startup repair must create only official worker/expert TOMLs', startupAgentFiles);
21
+ assertGate(startupText.includes('[agents.analysis_scout]') && startupText.includes('config_file = ".codex/agents/stale.toml"'), 'doctor production startup repair must preserve legacy config tables', startupText);
12
22
  const context7 = await repairContext7Mcp({ root, apply: true });
13
23
  const supabase = await repairSupabaseMcp({ root, apply: true });
14
24
  const tx = await runDoctorFixTransaction({ root, phases: [
@@ -1,28 +1,39 @@
1
1
  #!/usr/bin/env node
2
2
  import fs from 'node:fs/promises';
3
+ import syncFs from 'node:fs';
3
4
  import os from 'node:os';
4
5
  import path from 'node:path';
5
6
  import { repairCodexAppFastUi } from '../core/codex-app/codex-app-fast-ui-repair.js';
7
+ const tempRoots = new Set();
8
+ process.once('exit', cleanupTempRoots);
6
9
  const root = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-doctor-fast-ui-'));
10
+ tempRoots.add(root);
7
11
  const codexHome = path.join(root, 'home', '.codex');
8
12
  await fs.mkdir(path.join(root, '.codex'), { recursive: true });
9
13
  await fs.mkdir(codexHome, { recursive: true });
10
14
  await fs.writeFile(path.join(root, '.codex', 'config.toml'), 'model = "future-codex-model"\nmodel_reasoning_effort = "medium"\nmodel_provider = "codex-lb"\n');
11
15
  await fs.writeFile(path.join(codexHome, 'config.toml'), '# SKS forced fast UI during legacy install\nmodel = "legacy-sks-model"\nmodel_reasoning_effort = "xhigh"\nmodel_provider = "codex-lb"\nservice_tier = "fast"\n[features]\nfast_mode = false # user disabled, must remain untouched\n\n[profiles.sks-fast-high]\nmodel = "legacy-profile-model"\nservice_tier = "fast"\n\n[model_providers.codex-lb]\nname = "openai"\nbase_url = "https://lb.example.test/backend-api/codex"\nwire_api = "responses"\nenv_key = "CODEX_LB_API_KEY"\nsupports_websockets = true\nrequires_openai_auth = true\n');
12
- const plan = await repairCodexAppFastUi(root, { codexHome, apply: false });
13
- const repaired = await repairCodexAppFastUi(root, { codexHome, apply: true });
16
+ // Keep this hermetic: selected codex-lb readiness must not inherit the release
17
+ // runner's machine credentials or perform a real model-catalog lookup.
18
+ const fixtureEnv = {};
19
+ const plan = await repairCodexAppFastUi(root, { codexHome, apply: false, env: fixtureEnv });
20
+ const repaired = await repairCodexAppFastUi(root, { codexHome, apply: true, env: fixtureEnv });
14
21
  const projectAfter = await fs.readFile(path.join(root, '.codex', 'config.toml'), 'utf8');
15
22
  const homeAfter = await fs.readFile(path.join(codexHome, 'config.toml'), 'utf8');
16
23
  const homeTopLevel = homeAfter.split(/\n\s*\[/)[0] || '';
17
24
  const backups = repaired.actions.filter((action) => action.changed).map((action) => action.backup_path).filter(Boolean);
18
25
  const unsafeRoot = await fs.mkdtemp(path.join(os.tmpdir(), 'sks-doctor-fast-ui-unsafe-'));
26
+ tempRoots.add(unsafeRoot);
19
27
  const unsafeCodexHome = path.join(unsafeRoot, 'home', '.codex');
20
28
  await fs.mkdir(path.join(unsafeRoot, '.codex'), { recursive: true });
21
29
  await fs.mkdir(unsafeCodexHome, { recursive: true });
22
30
  await fs.writeFile(path.join(unsafeCodexHome, 'config.toml'), 'service_tier = "standard"\n');
23
- const unsafePlan = await repairCodexAppFastUi(unsafeRoot, { codexHome: unsafeCodexHome, apply: false });
31
+ const unsafePlan = await repairCodexAppFastUi(unsafeRoot, { codexHome: unsafeCodexHome, apply: false, env: fixtureEnv });
32
+ const unsafeAfter = await fs.readFile(path.join(unsafeCodexHome, 'config.toml'), 'utf8');
24
33
  const ok = plan.fast_selector === 'manual_action_required'
25
34
  && plan.provider_selector === 'manual_action_required'
35
+ && plan.selected_provider_blockers.includes('codex_lb_api_key_missing')
36
+ && plan.selected_provider_blockers.includes('codex_lb_base_url_missing')
26
37
  && plan.provider_actions.includes('sks codex-app set-openrouter-key --api-key-stdin')
27
38
  && plan.provider_actions.includes('sks codex-lb setup --host <domain> --api-key-stdin --yes')
28
39
  && plan.safe_auto_apply === true
@@ -35,18 +46,34 @@ const ok = plan.fast_selector === 'manual_action_required'
35
46
  && !/^model\s*=/m.test(homeTopLevel)
36
47
  && !/^model_reasoning_effort\s*=/m.test(homeTopLevel)
37
48
  && /model_provider\s*=\s*"codex-lb"/.test(projectAfter)
38
- && !/service_tier\s*=/.test(homeTopLevel)
49
+ && /^service_tier\s*=\s*"fast"$/m.test(homeTopLevel)
39
50
  && /fast_mode = false/.test(homeAfter)
40
51
  && /model_provider = "codex-lb"/.test(homeAfter)
41
52
  && !/\[user\.fast_mode\]/.test(homeAfter)
42
53
  && !/\[profiles\.sks-fast-high\]/.test(homeAfter)
43
54
  && /\[model_providers\.codex-lb\]/.test(homeAfter)
44
- && unsafePlan.requires_confirmation === true
45
- && unsafePlan.safe_auto_apply === false;
46
- emit({ schema: 'sks.doctor-fixes-codex-app-fast-ui-check.v1', ok, plan, repaired, unsafe_plan: unsafePlan, project_after: projectAfter, home_after: homeAfter, blockers: ok ? [] : ['doctor_fixes_codex_app_fast_ui_check_failed'] });
55
+ && unsafePlan.requires_confirmation === false
56
+ && unsafePlan.safe_auto_apply === false
57
+ && unsafePlan.actions.every((action) => action.changed === false)
58
+ && unsafeAfter === 'service_tier = "standard"\n';
59
+ await Promise.all([
60
+ fs.rm(root, { recursive: true, force: true }),
61
+ fs.rm(unsafeRoot, { recursive: true, force: true })
62
+ ]);
63
+ tempRoots.clear();
64
+ process.removeListener('exit', cleanupTempRoots);
65
+ emit({ schema: 'sks.doctor-fixes-codex-app-fast-ui-check.v1', ok, plan, repaired, unsafe_plan: unsafePlan, project_after: projectAfter, home_after: homeAfter, unsafe_after: unsafeAfter, blockers: ok ? [] : ['doctor_fixes_codex_app_fast_ui_check_failed'] });
47
66
  function emit(report) {
48
67
  console.log(JSON.stringify(report, null, 2));
49
68
  if (!report.ok)
50
69
  process.exitCode = 1;
51
70
  }
71
+ function cleanupTempRoots() {
72
+ for (const candidate of tempRoots) {
73
+ try {
74
+ syncFs.rmSync(candidate, { recursive: true, force: true });
75
+ }
76
+ catch { }
77
+ }
78
+ }
52
79
  //# sourceMappingURL=doctor-fixes-codex-app-fast-ui-check.js.map
@@ -44,20 +44,30 @@ const report = await repairCodexImagegen({
44
44
  const reportFile = JSON.parse(await fs.readFile(reportPath, 'utf8'));
45
45
  const ok = report.schema === 'sks.doctor-imagegen-repair.v1'
46
46
  && report.attempted === true
47
- && report.recovered === true
47
+ && report.recovered === false
48
+ && report.capability_ready === true
49
+ && report.configuration_recovered === true
50
+ && report.route_ready === false
51
+ && report.real_generation_verified === false
48
52
  && report.after?.core_ready === true
49
53
  && report.steps?.some((step) => step.id === 'image_generation_feature_enable' && step.ok === true)
50
54
  && report.communication_test?.level === 'flag_level'
51
- && report.communication_test?.ok === true
55
+ && report.communication_test?.ok === false
52
56
  && report.communication_test?.real_generation_round_trip_performed === false
53
- && reportFile.recovered === true
54
- && reportFile.communication_test?.level === 'flag_level';
57
+ && report.blockers?.includes('codex_imagegen_real_output_unverified')
58
+ && reportFile.recovered === false
59
+ && reportFile.route_ready === false
60
+ && reportFile.communication_test?.level === 'flag_level'
61
+ && reportFile.communication_test?.ok === false;
55
62
  console.log(JSON.stringify({
56
63
  schema: 'sks.doctor-imagegen-repair-check.v1',
57
64
  ok,
58
65
  repair_schema: report.schema,
59
66
  attempted: report.attempted,
60
67
  recovered: report.recovered,
68
+ capability_ready: report.capability_ready,
69
+ route_ready: report.route_ready,
70
+ real_generation_verified: report.real_generation_verified,
61
71
  after_core_ready: report.after?.core_ready === true,
62
72
  communication_test_level: report.communication_test?.level,
63
73
  report_path: reportPath
@@ -3,11 +3,17 @@ import fs from 'node:fs/promises';
3
3
  import path from 'node:path';
4
4
  import { assertGate, emitGate, makeTempRoot, writeText } from './sks-3-1-8-check-lib.js';
5
5
  import { repairCodexStartupConfig } from '../core/doctor/codex-startup-config-repair.js';
6
+ import { parse } from 'smol-toml';
6
7
  const root = await makeTempRoot('sks-startup-config-blackbox-');
7
- await writeText(path.join(root, '.codex', 'config.toml'), '[agents.analysis_scout]\nconfig_file = ".codex/agents/stale.toml"\nmessage_role_prefix = "legacy"\n');
8
- const report = await repairCodexStartupConfig({ root, apply: true });
8
+ await writeText(path.join(root, '.codex', 'config.toml'), '# SKS managed Codex config fixture\n[agents.analysis_scout]\nconfig_file = ".codex/agents/stale.toml"\nmessage_role_prefix = "legacy"\n');
9
+ const report = await repairCodexStartupConfig({ root, apply: true, home: path.join(root, 'home'), codexHome: path.join(root, 'codex-home') });
9
10
  const text = await fs.readFile(path.join(root, '.codex', 'config.toml'), 'utf8');
11
+ const parsed = parse(text);
12
+ const agents = parsed.agents || {};
13
+ const files = (await fs.readdir(path.join(root, '.codex', 'agents'))).sort();
10
14
  assertGate(report.ok === true, 'startup config blackbox must pass postcheck', report);
11
- assertGate(!text.includes('message_role_prefix') && /config_file = "\//.test(text), 'startup config blackbox must rewrite to absolute config paths and remove unsupported fields', { text });
15
+ assertGate(agents.max_threads === 12 && agents.max_depth === 1 && agents.job_max_runtime_seconds === 1200 && agents.interrupt_message === true, 'startup config blackbox must persist official settings', agents);
16
+ assertGate(files.join(',') === 'expert.toml,worker.toml', 'startup config blackbox must create only official worker/expert TOMLs', files);
17
+ assertGate(text.includes('config_file = ".codex/agents/stale.toml"') && text.includes('message_role_prefix = "legacy"'), 'startup config blackbox must preserve legacy compatibility tables', { text });
12
18
  emitGate('doctor:startup-config-repair-blackbox');
13
19
  //# sourceMappingURL=doctor-startup-config-repair-blackbox.js.map
@@ -1,10 +1,20 @@
1
1
  #!/usr/bin/env node
2
2
  import { assertGate, emitGate, makeTempRoot, writeText } from './sks-3-1-8-check-lib.js';
3
3
  import { repairCodexStartupConfig } from '../core/doctor/codex-startup-config-repair.js';
4
+ import fs from 'node:fs/promises';
4
5
  import path from 'node:path';
6
+ import { parse } from 'smol-toml';
5
7
  const root = await makeTempRoot('sks-startup-config-');
6
- await writeText(path.join(root, '.codex', 'config.toml'), '[agents.analysis_scout]\nconfig_file = ".codex/agents/missing.toml"\nmessage_role_prefix = "legacy"\n');
7
- const report = await repairCodexStartupConfig({ root, apply: true });
8
- assertGate(report.ok === true, 'startup config repair must repair stale config_file paths and unsupported fields', report);
8
+ await writeText(path.join(root, '.codex', 'config.toml'), '# SKS managed Codex config fixture\n[agents.analysis_scout]\nconfig_file = ".codex/agents/missing.toml"\nmessage_role_prefix = "legacy"\n');
9
+ const codexHome = path.join(root, 'codex-home');
10
+ const report = await repairCodexStartupConfig({ root, apply: true, home: path.join(root, 'home'), codexHome });
11
+ const text = await fs.readFile(path.join(root, '.codex', 'config.toml'), 'utf8');
12
+ const parsed = parse(text);
13
+ const agents = parsed.agents || {};
14
+ const files = (await fs.readdir(path.join(root, '.codex', 'agents'))).sort();
15
+ assertGate(report.ok === true, 'startup config repair must install the official project config and agent files', report);
16
+ assertGate(agents.max_threads === 12 && agents.max_depth === 1 && agents.job_max_runtime_seconds === 1200 && agents.interrupt_message === true, 'startup config repair must write official [agents] defaults', agents);
17
+ assertGate(files.length === 2 && files[0] === 'expert.toml' && files[1] === 'worker.toml', 'startup config repair must create only worker/expert TOMLs', files);
18
+ assertGate(text.includes('[agents.analysis_scout]') && text.includes('config_file = ".codex/agents/missing.toml"') && text.includes('message_role_prefix = "legacy"'), 'legacy agent config must be preserved without synthesizing its TOML', text);
9
19
  emitGate('doctor:startup-config-repair');
10
20
  //# sourceMappingURL=doctor-startup-config-repair-check.js.map
@@ -29,6 +29,9 @@ const results = [];
29
29
  '',
30
30
  '[mcp_servers.custom]',
31
31
  'command = "npx"',
32
+ '',
33
+ '[agents]',
34
+ 'max_threads = 20',
32
35
  ''
33
36
  ].join('\n');
34
37
  await fs.writeFile(cfg, userConfig);
@@ -41,6 +44,7 @@ const results = [];
41
44
  /^model_reasoning_effort = "high"/m.test(after) && // user effort NOT stripped
42
45
  /# my hand-tuned Codex config/.test(after) && // user comment preserved
43
46
  /\[mcp_servers\.custom\]/.test(after) && // user table preserved
47
+ /\[agents\][\s\S]*max_threads = 20/.test(after) && // user concurrency preserved
44
48
  !/\[profiles\.sks-fast-high\]/.test(after) && // legacy profile table stripped
45
49
  !/\[user\.fast_mode\]/.test(after) && // legacy fast UI table stripped
46
50
  backups.length >= 1 && // backup created
@@ -59,7 +63,8 @@ const results = [];
59
63
  && !/^model\s*=/m.test(topLevel)
60
64
  && !/^model_reasoning_effort\s*=/m.test(topLevel)
61
65
  && !/^service_tier = "fast"/m.test(topLevel)
62
- && /\[features\]/.test(after);
66
+ && /\[features\]/.test(after)
67
+ && !/^max_threads\s*=/m.test(after);
63
68
  results.push({ case: 'fresh_config_seeds_defaults', ok, status: res.status });
64
69
  }
65
70
  // --- Case 3: unparseable config is preserved + backed up, NOT overwritten ---
@@ -68,7 +73,7 @@ const results = [];
68
73
  const codexDir = path.join(dir, '.codex');
69
74
  await fs.mkdir(codexDir, { recursive: true });
70
75
  const cfg = path.join(codexDir, 'config.toml');
71
- const broken = 'model = "gpt-5.5"\n[features\nhooks = true\n'; // malformed table header
76
+ const broken = 'model = "gpt-5.6-terra"\n[features\nhooks = true\n'; // malformed table header
72
77
  await fs.writeFile(cfg, broken);
73
78
  const res = await helpers.ensureGlobalCodexFastModeDuringInstall({ home: dir, configPath: cfg });
74
79
  const after = await fs.readFile(cfg, 'utf8');
@@ -1,7 +1,9 @@
1
1
  import { assertGate, emitGate, readJson, readText } from './sks-1-18-gate-lib.js';
2
2
  const gates = (readJson('release-gates.v2.json').gates || []);
3
3
  const migration = readText('docs/sks-4-migration.md');
4
- const allowlist = parseAllowlist(migration);
4
+ const currentVersion = String(readJson('package.json').version || '');
5
+ assertGate(/^\d+\.\d+\.\d+(?:[-+].*)?$/.test(currentVersion), 'package version must be valid before evaluating legacy allowlist expiry', { currentVersion });
6
+ const allowlist = parseAllowlist(migration, currentVersion);
5
7
  const legacy = gates
6
8
  .filter((gate) => gate.preset?.includes('release'))
7
9
  .filter((gate) => removableLegacy(gate.id, gate.command))
@@ -19,7 +21,7 @@ function removableLegacy(id, command) {
19
21
  || /codex[:.-]?0139/.test(id)
20
22
  || /codex-0139/.test(command);
21
23
  }
22
- function parseAllowlist(text) {
24
+ function parseAllowlist(text, currentVersion) {
23
25
  return [...text.matchAll(/<!--\s*sks-legacy-allowlist\s*([\s\S]*?)-->/g)].map((match) => {
24
26
  const body = match[1] || '';
25
27
  return {
@@ -28,7 +30,7 @@ function parseAllowlist(text) {
28
30
  owner: field(body, 'owner'),
29
31
  expires: field(body, 'expires')
30
32
  };
31
- }).filter((row) => row.id && row.reason && row.owner && compareVersion(row.expires, '4.0.2') > 0);
33
+ }).filter((row) => row.id && row.reason && row.owner && compareVersion(row.expires, currentVersion) > 0);
32
34
  }
33
35
  function isAllowed(id, allowlist) {
34
36
  return allowlist.some((row) => row.id.endsWith('*') ? id.startsWith(row.id.slice(0, -1)) : row.id === id);
@@ -37,8 +39,8 @@ function field(body, name) {
37
39
  return body.match(new RegExp(`^${name}:\\s*(.+)$`, 'm'))?.[1]?.trim() || '';
38
40
  }
39
41
  function compareVersion(a, b) {
40
- const left = a.split('.').map(Number);
41
- const right = b.split('.').map(Number);
42
+ const left = (a.split(/[+-]/, 1)[0] || '').split('.').map(Number);
43
+ const right = (b.split(/[+-]/, 1)[0] || '').split('.').map(Number);
42
44
  for (let i = 0; i < Math.max(left.length, right.length); i += 1) {
43
45
  const delta = (left[i] || 0) - (right[i] || 0);
44
46
  if (delta !== 0)