sneakoscope 4.8.6 → 5.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (390) hide show
  1. package/README.md +51 -726
  2. package/bench/tasks/t01-off-by-one/repo/package.json +9 -0
  3. package/bench/tasks/t01-off-by-one/repo/src/pagination.js +5 -0
  4. package/bench/tasks/t01-off-by-one/repo/test.js +5 -0
  5. package/bench/tasks/t01-off-by-one/task.json +13 -0
  6. package/bench/tasks/t02-signature-cochange/repo/package.json +9 -0
  7. package/bench/tasks/t02-signature-cochange/repo/src/admin.js +5 -0
  8. package/bench/tasks/t02-signature-cochange/repo/src/audit.js +5 -0
  9. package/bench/tasks/t02-signature-cochange/repo/src/labels.js +3 -0
  10. package/bench/tasks/t02-signature-cochange/repo/src/profile.js +5 -0
  11. package/bench/tasks/t02-signature-cochange/repo/test.js +9 -0
  12. package/bench/tasks/t02-signature-cochange/task.json +12 -0
  13. package/bench/tasks/t03-type-puzzle/repo/package.json +9 -0
  14. package/bench/tasks/t03-type-puzzle/repo/src/config.js +4 -0
  15. package/bench/tasks/t03-type-puzzle/repo/test.js +6 -0
  16. package/bench/tasks/t03-type-puzzle/task.json +13 -0
  17. package/bench/tasks/t04-refactor-preserve/repo/package.json +9 -0
  18. package/bench/tasks/t04-refactor-preserve/repo/src/cart.js +8 -0
  19. package/bench/tasks/t04-refactor-preserve/repo/test.js +4 -0
  20. package/bench/tasks/t04-refactor-preserve/task.json +12 -0
  21. package/bench/tasks/t05-performance/repo/package.json +9 -0
  22. package/bench/tasks/t05-performance/repo/src/pairs.js +9 -0
  23. package/bench/tasks/t05-performance/repo/test.js +11 -0
  24. package/bench/tasks/t05-performance/task.json +12 -0
  25. package/bench/tasks/t06-mistake-rule/repo/package.json +9 -0
  26. package/bench/tasks/t06-mistake-rule/repo/src/loader.js +6 -0
  27. package/bench/tasks/t06-mistake-rule/repo/test.js +7 -0
  28. package/bench/tasks/t06-mistake-rule/task.json +12 -0
  29. package/config/bench-baseline.json +7 -0
  30. package/crates/sks-core/Cargo.lock +1 -1
  31. package/crates/sks-core/Cargo.toml +1 -1
  32. package/crates/sks-core/src/main.rs +1 -1
  33. package/dist/bin/install.js +35 -0
  34. package/dist/bin/sks.js +1 -1
  35. package/dist/cli/cli-theme.js +51 -0
  36. package/dist/cli/command-registry.js +75 -42
  37. package/dist/cli/help-fast.js +18 -8
  38. package/dist/cli/insane-search-command.js +36 -8
  39. package/dist/cli/install-helpers.js +147 -47
  40. package/dist/cli/router.js +58 -2
  41. package/dist/commands/codex-lb.js +6 -4
  42. package/dist/commands/doctor.js +146 -8
  43. package/dist/commands/proof.js +6 -3
  44. package/dist/commands/zellij-monitor-pane.js +25 -0
  45. package/dist/commands/zellij-slot-pane.js +39 -2
  46. package/dist/commands/zellij-viewport-pane.js +56 -0
  47. package/dist/commands/zellij.js +55 -2
  48. package/dist/config/skills-manifest.json +493 -0
  49. package/dist/core/agents/agent-conflict-graph.js +5 -0
  50. package/dist/core/agents/agent-lease.js +5 -0
  51. package/dist/core/agents/agent-ledger-schemas.js +1 -0
  52. package/dist/core/agents/agent-lifecycle.js +86 -35
  53. package/dist/core/agents/agent-orchestrator.js +287 -72
  54. package/dist/core/agents/agent-output-validator.js +14 -3
  55. package/dist/core/agents/agent-patch-queue-store.js +108 -4
  56. package/dist/core/agents/agent-patch-queue.js +10 -3
  57. package/dist/core/agents/agent-patch-schema.js +13 -0
  58. package/dist/core/agents/agent-proof-evidence.js +6 -1
  59. package/dist/core/agents/agent-runner-fake.js +40 -0
  60. package/dist/core/agents/agent-scheduler.js +2 -3
  61. package/dist/core/agents/agent-worker-pipeline.js +36 -2
  62. package/dist/core/agents/codex-exec-worker-adapter.js +2 -0
  63. package/dist/core/agents/native-cli-session-swarm.js +30 -13
  64. package/dist/core/agents/native-cli-worker.js +2 -1
  65. package/dist/core/agents/native-worker-backend-router.js +58 -1
  66. package/dist/core/auto-review.js +25 -4
  67. package/dist/core/codex/agent-config-file-repair.js +15 -2
  68. package/dist/core/codex/codex-config-eperm-repair.js +8 -2
  69. package/dist/core/codex/codex-config-guard.js +289 -0
  70. package/dist/core/codex/codex-config-toml.js +122 -0
  71. package/dist/core/codex/codex-project-config-policy.js +59 -7
  72. package/dist/core/codex-app/sks-menubar.js +780 -122
  73. package/dist/core/codex-app.js +1 -0
  74. package/dist/core/codex-control/codex-fake-sdk-adapter.js +6 -4
  75. package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
  76. package/dist/core/codex-control/codex-sdk-env-policy.js +1 -1
  77. package/dist/core/codex-control/codex-task-runner.js +32 -14
  78. package/dist/core/codex-control/python-codex-sdk-adapter.js +4 -1
  79. package/dist/core/codex-control/schemas/agent-worker-result.schema.js +12 -3
  80. package/dist/core/codex-hooks/codex-hook-managed-install.js +5 -0
  81. package/dist/core/codex-hooks/codex-hook-state-writer.js +70 -11
  82. package/dist/core/codex-hooks/codex-hook-trust-doctor.js +2 -2
  83. package/dist/core/codex-lb/codex-lb-env.js +20 -1
  84. package/dist/core/codex-lb/codex-lb-setup.js +2 -5
  85. package/dist/core/codex-native/skill-registry-ledger.js +24 -5
  86. package/dist/core/commands/basic-cli.js +21 -2
  87. package/dist/core/commands/check-command.js +37 -5
  88. package/dist/core/commands/command-utils.js +22 -2
  89. package/dist/core/commands/computer-use-command.js +62 -7
  90. package/dist/core/commands/db-command.js +31 -5
  91. package/dist/core/commands/fast-mode-command.js +39 -11
  92. package/dist/core/commands/gate-result-contract.js +43 -0
  93. package/dist/core/commands/gates-command.js +6 -1
  94. package/dist/core/commands/gc-command.js +29 -2
  95. package/dist/core/commands/goal-command.js +9 -2
  96. package/dist/core/commands/gx-command.js +79 -7
  97. package/dist/core/commands/image-ux-review-command.js +188 -13
  98. package/dist/core/commands/mad-db-command.js +85 -176
  99. package/dist/core/commands/mad-sks-command.js +248 -34
  100. package/dist/core/commands/menubar-command.js +146 -0
  101. package/dist/core/commands/naruto-command.js +64 -10
  102. package/dist/core/commands/pipeline-command.js +21 -2
  103. package/dist/core/commands/plan-command.js +76 -0
  104. package/dist/core/commands/ppt-command.js +159 -24
  105. package/dist/core/commands/qa-loop-command.js +6 -2
  106. package/dist/core/commands/release-command.js +55 -2
  107. package/dist/core/commands/research-command.js +1 -1
  108. package/dist/core/commands/review-command.js +217 -0
  109. package/dist/core/commands/route-command.js +62 -0
  110. package/dist/core/commands/route-success-helpers.js +59 -0
  111. package/dist/core/commands/run-command.js +19 -7
  112. package/dist/core/commands/seo-command.js +49 -1
  113. package/dist/core/commands/status-command.js +21 -1
  114. package/dist/core/commands/team-legacy-observe-command.js +221 -3
  115. package/dist/core/commands/ui-command.js +161 -0
  116. package/dist/core/commands/uninstall-command.js +312 -0
  117. package/dist/core/db-safety.js +7 -3
  118. package/dist/core/doctor/codex-startup-config-repair.js +14 -3
  119. package/dist/core/doctor/confirm-repair.js +27 -0
  120. package/dist/core/doctor/context7-mcp-repair.js +35 -7
  121. package/dist/core/doctor/doctor-codex-startup-repair.js +10 -3
  122. package/dist/core/doctor/doctor-context7-repair.js +17 -4
  123. package/dist/core/doctor/doctor-dirty-planner.js +27 -9
  124. package/dist/core/doctor/doctor-native-capability-repair.js +12 -2
  125. package/dist/core/doctor/doctor-readiness-matrix.js +27 -2
  126. package/dist/core/doctor/doctor-repair-postcheck.js +4 -0
  127. package/dist/core/doctor/doctor-transaction.js +21 -5
  128. package/dist/core/doctor/doctor-zellij-repair.js +1 -0
  129. package/dist/core/doctor/imagegen-repair.js +161 -0
  130. package/dist/core/doctor/supabase-mcp-repair.js +23 -5
  131. package/dist/core/feature-fixture-runner.js +2 -2
  132. package/dist/core/feature-fixtures.js +65 -37
  133. package/dist/core/feature-registry.js +106 -3
  134. package/dist/core/fsx.js +91 -2
  135. package/dist/core/hooks-runtime/skill-reconcile-preflight.js +43 -0
  136. package/dist/core/hooks-runtime.js +86 -46
  137. package/dist/core/image-ux-review/imagegen-adapter.js +48 -11
  138. package/dist/core/image-ux-review.js +16 -0
  139. package/dist/core/imagegen/imagegen-capability.js +11 -5
  140. package/dist/core/imagegen/require-imagegen.js +57 -0
  141. package/dist/core/init/skills.js +271 -14
  142. package/dist/core/init.js +13 -10
  143. package/dist/core/mad-db/mad-db-coordinator.js +96 -20
  144. package/dist/core/mad-db/mad-db-policy.js +12 -10
  145. package/dist/core/mad-sks/executors/executor-base.js +8 -2
  146. package/dist/core/mad-sks/executors/index.js +4 -0
  147. package/dist/core/mad-sks/executors/sql-plane-executor.js +194 -0
  148. package/dist/core/mission.js +138 -5
  149. package/dist/core/naruto/naruto-active-pool.js +84 -30
  150. package/dist/core/naruto/naruto-backpressure.js +5 -1
  151. package/dist/core/naruto/naruto-real-worker-child.js +10 -0
  152. package/dist/core/naruto/naruto-real-worker-runtime.js +9 -7
  153. package/dist/core/naruto/naruto-role-policy.js +3 -0
  154. package/dist/core/naruto/naruto-task-hints.js +10 -0
  155. package/dist/core/naruto/naruto-work-graph.js +8 -2
  156. package/dist/core/naruto/naruto-work-item.js +6 -0
  157. package/dist/core/naruto/resource-pressure-monitor.js +33 -15
  158. package/dist/core/naruto/solution-tournament.js +101 -0
  159. package/dist/core/permission-gates.js +30 -0
  160. package/dist/core/pipeline-internals/runtime-core.js +72 -222
  161. package/dist/core/pipeline-internals/runtime-gates.js +140 -24
  162. package/dist/core/ppt-review/index.js +6 -1
  163. package/dist/core/ppt-review/slide-imagegen-review.js +75 -10
  164. package/dist/core/ppt.js +70 -2
  165. package/dist/core/proof/auto-finalize.js +70 -11
  166. package/dist/core/proof/proof-schema.js +2 -0
  167. package/dist/core/proof/route-adapter.js +5 -1
  168. package/dist/core/proof/route-finalizer.js +8 -5
  169. package/dist/core/proof/selftest-proof-fixtures.js +18 -5
  170. package/dist/core/proof/validation.js +2 -0
  171. package/dist/core/provider/model-router.js +53 -0
  172. package/dist/core/questions.js +1 -1
  173. package/dist/core/recallpulse.js +1 -1
  174. package/dist/core/release/gate-manifest.js +2 -2
  175. package/dist/core/release/release-gate-affected-selector.js +3 -10
  176. package/dist/core/release/release-gate-batch-runner.js +4 -2
  177. package/dist/core/release/release-gate-cache-v2.js +27 -14
  178. package/dist/core/release/release-gate-dag.js +6 -1
  179. package/dist/core/release/release-gate-hermetic-env.js +10 -0
  180. package/dist/core/release/release-gate-node.js +3 -0
  181. package/dist/core/release/release-gate-resource-governor.js +1 -0
  182. package/dist/core/retention.js +89 -4
  183. package/dist/core/routes/constants.js +1 -1
  184. package/dist/core/routes/diagnostic-allowlist.js +55 -0
  185. package/dist/core/routes.js +83 -33
  186. package/dist/core/safety/mutation-guard.js +5 -1
  187. package/dist/core/skill-forge.js +9 -4
  188. package/dist/core/stop-gate/gate-evaluator.js +102 -0
  189. package/dist/core/stop-gate/stop-gate-check.js +26 -4
  190. package/dist/core/stop-gate/stop-gate-resolver.js +19 -3
  191. package/dist/core/stop-gate/stop-gate-writer.js +20 -1
  192. package/dist/core/team-dag.js +12 -465
  193. package/dist/core/team-dashboard-renderer.js +13 -94
  194. package/dist/core/team-live.js +68 -804
  195. package/dist/core/triwiki/agents-md-projector.js +184 -0
  196. package/dist/core/triwiki-wrongness/wrongness-schema.js +3 -1
  197. package/dist/core/trust-kernel/trust-kernel-schema.js +1 -0
  198. package/dist/core/trust-kernel/trust-report.js +1 -1
  199. package/dist/core/trust-kernel/trust-status.js +2 -0
  200. package/dist/core/ui/dashboard-html.js +111 -0
  201. package/dist/core/update/update-migration-state.js +383 -42
  202. package/dist/core/update-check.js +201 -78
  203. package/dist/core/verification/diff-quality.js +100 -0
  204. package/dist/core/verification/impact-scan.js +164 -0
  205. package/dist/core/verification/machine-feedback.js +146 -0
  206. package/dist/core/verification/mistake-rule-compiler.js +195 -0
  207. package/dist/core/version.js +1 -1
  208. package/dist/core/zellij/zellij-layout-builder.js +44 -16
  209. package/dist/core/zellij/zellij-monitor-renderer.js +53 -0
  210. package/dist/core/zellij/zellij-self-heal.js +27 -32
  211. package/dist/core/zellij/zellij-slot-pane-renderer.js +162 -153
  212. package/dist/core/zellij/zellij-slot-telemetry.js +2 -0
  213. package/dist/core/zellij/zellij-theme.js +67 -0
  214. package/dist/core/zellij/zellij-ui-mode.js +16 -0
  215. package/dist/core/zellij/zellij-viewport-binder.js +59 -0
  216. package/dist/core/zellij/zellij-worker-pane-manager.js +53 -5
  217. package/dist/scripts/agent-patch-swarm-gate-lib.js +2 -2
  218. package/dist/scripts/build-dist.js +8 -0
  219. package/dist/scripts/check-feature-quality.js +2 -2
  220. package/dist/scripts/cli-output-consistency-check.js +57 -0
  221. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +106 -0
  222. package/dist/scripts/codex-lb-gpt55-fast-profile-check.js +105 -0
  223. package/dist/scripts/codex-lb-missing-env-regression.js +2 -3
  224. package/dist/scripts/codex-project-config-policy-merge-regression.js +3 -3
  225. package/dist/scripts/coding-bench-check.js +136 -0
  226. package/dist/scripts/concurrent-session-collision-check.js +67 -0
  227. package/dist/scripts/docs-truthfulness-check.js +1 -1
  228. package/dist/scripts/doctor-imagegen-repair-check.js +62 -0
  229. package/dist/scripts/ensure-bin-executable.js +11 -3
  230. package/dist/scripts/gate-policy-audit-check.js +130 -0
  231. package/dist/scripts/harness-benchmark-check.js +104 -0
  232. package/dist/scripts/hook-latency-budget-check.js +45 -0
  233. package/dist/scripts/legacy-update-e2e-check.js +228 -0
  234. package/dist/scripts/lib/codex-sdk-gate-lib.js +2 -2
  235. package/dist/scripts/lib/real-codex-parallel-gate.js +2 -2
  236. package/dist/scripts/loop-directive-check-lib.js +1 -1
  237. package/dist/scripts/mad-db-command-check.js +11 -8
  238. package/dist/scripts/mad-db-real-supabase-e2e.js +2 -2
  239. package/dist/scripts/mad-db-route-identity-check.js +8 -6
  240. package/dist/scripts/mad-db-safety-conflict-matrix-check.js +31 -8
  241. package/dist/scripts/mad-db-skill-policy-snapshot-check.js +4 -5
  242. package/dist/scripts/mad-sks-zellij-default-pane-worker-check.js +3 -2
  243. package/dist/scripts/mad-sks-zellij-launch-check.js +1 -1
  244. package/dist/scripts/naruto-zellij-dynamic-right-column-check.js +7 -7
  245. package/dist/scripts/parallel-claim-enforcement-check.js +14 -5
  246. package/dist/scripts/ppt-real-imagegen-wiring-check.js +5 -1
  247. package/dist/scripts/project-skill-dedupe-check.js +23 -5
  248. package/dist/scripts/proof-root-cause-policy-check.js +2 -0
  249. package/dist/scripts/release-affected-selector-check.js +2 -2
  250. package/dist/scripts/release-cache-glob-hashing-check.js +1 -0
  251. package/dist/scripts/release-dag-full-coverage-check.js +13 -4
  252. package/dist/scripts/release-gate-dag-runner-check.js +10 -2
  253. package/dist/scripts/release-gate-dag-runner.js +22 -0
  254. package/dist/scripts/release-gate-existence-audit.js +2 -1
  255. package/dist/scripts/release-gate-planner.js +2 -1
  256. package/dist/scripts/release-gate-script-parity-check.js +1 -1
  257. package/dist/scripts/release-metadata-1-19-check.js +2 -1
  258. package/dist/scripts/release-readiness-report.js +38 -7
  259. package/dist/scripts/release-stability-report-check.js +12 -8
  260. package/dist/scripts/search-visibility-gate-lib.js +2 -2
  261. package/dist/scripts/seo-geo-feature-fixture-quality-check.js +1 -1
  262. package/dist/scripts/skills-manifest-continuity-check.js +46 -0
  263. package/dist/scripts/sks-1-11-gate-lib.js +8 -6
  264. package/dist/scripts/sks-menubar-install-check.js +87 -21
  265. package/dist/scripts/sks-uninstall-regression-check.js +54 -0
  266. package/dist/scripts/uninstall-inventory-check.js +3 -0
  267. package/dist/scripts/ux-review-real-loop-fixture-check.js +9 -4
  268. package/dist/scripts/ux-review-run-wires-imagegen-check.js +4 -0
  269. package/dist/scripts/zellij-layout-valid-check.js +18 -11
  270. package/dist/scripts/zellij-right-column-geometry-proof.js +2 -4
  271. package/dist/scripts/zellij-slot-pane-renderer-check.js +9 -9
  272. package/dist/scripts/zellij-slot-pane-stale-detection-check.js +3 -4
  273. package/dist/scripts/zellij-slot-pane-telemetry-renderer-check.js +3 -2
  274. package/dist/scripts/zellij-slot-telemetry-renderer-check.js +4 -2
  275. package/dist/scripts/zellij-spawn-on-demand-layout-check.js +8 -2
  276. package/dist/scripts/zellij-viewport-binder-check.js +9 -0
  277. package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
  278. package/docs/demo.tape +28 -0
  279. package/package.json +70 -3
  280. package/schemas/codex/completion-proof.schema.json +3 -2
  281. package/schemas/release/release-gate-node.schema.json +2 -1
  282. package/dist/scripts/agent-backfill-route-blackbox.js +0 -5
  283. package/dist/scripts/agent-dynamic-pool-route-blackbox.js +0 -5
  284. package/dist/scripts/agent-parallel-write-blackbox.js +0 -56
  285. package/dist/scripts/agent-patch-swarm-route-blackbox.js +0 -10
  286. package/dist/scripts/agent-route-blackbox-lib.js +0 -132
  287. package/dist/scripts/blackbox-command-import-smoke.js +0 -143
  288. package/dist/scripts/blackbox-global-shim.js +0 -77
  289. package/dist/scripts/blackbox-matrix.js +0 -70
  290. package/dist/scripts/blackbox-npx-one-shot.js +0 -69
  291. package/dist/scripts/blackbox-pack-install.js +0 -174
  292. package/dist/scripts/brand-neutrality-zero-leakage-blackbox.js +0 -4
  293. package/dist/scripts/build-once-runner-blackbox.js +0 -34
  294. package/dist/scripts/codex-0140-integration-blackbox.js +0 -13
  295. package/dist/scripts/codex-agent-type-blackbox.js +0 -4
  296. package/dist/scripts/codex-app-harness-blackbox.js +0 -4
  297. package/dist/scripts/codex-app-skill-agent-blackbox.js +0 -4
  298. package/dist/scripts/codex-hook-approval-blackbox.js +0 -4
  299. package/dist/scripts/codex-init-deep-directory-local-blackbox.js +0 -4
  300. package/dist/scripts/codex-native-feature-broker-blackbox.js +0 -4
  301. package/dist/scripts/codex-native-pattern-analysis-blackbox.js +0 -4
  302. package/dist/scripts/codex-native-read-repair-split-blackbox.js +0 -55
  303. package/dist/scripts/codex-native-reference-cache-blackbox.js +0 -41
  304. package/dist/scripts/core-skill-integrity-blackbox.js +0 -33
  305. package/dist/scripts/dfix-fast-blackbox-check.js +0 -37
  306. package/dist/scripts/dfix-parallel-write-blackbox.js +0 -48
  307. package/dist/scripts/dfix-patch-swarm-route-blackbox.js +0 -10
  308. package/dist/scripts/doctor-context7-mcp-repair-blackbox.js +0 -16
  309. package/dist/scripts/doctor-dirty-repair-blackbox.js +0 -22
  310. package/dist/scripts/doctor-dirty-semantic-blackbox.js +0 -8
  311. package/dist/scripts/doctor-fix-production-blackbox.js +0 -26
  312. package/dist/scripts/doctor-native-capability-repair-blackbox.js +0 -39
  313. package/dist/scripts/doctor-startup-config-repair-blackbox.js +0 -13
  314. package/dist/scripts/doctor-supabase-mcp-repair-blackbox.js +0 -14
  315. package/dist/scripts/doctor-transaction-engine-blackbox.js +0 -28
  316. package/dist/scripts/doctor-zellij-fix-blackbox.js +0 -4
  317. package/dist/scripts/doctor-zellij-no-homebrew-blackbox.js +0 -4
  318. package/dist/scripts/doctor-zellij-upgrade-blackbox.js +0 -4
  319. package/dist/scripts/gate-pack-runner-blackbox.js +0 -27
  320. package/dist/scripts/gate-pack-v2-blackbox.js +0 -18
  321. package/dist/scripts/geo-cli-blackbox-check.js +0 -18
  322. package/dist/scripts/loop-collision-blackbox.js +0 -3
  323. package/dist/scripts/loop-concurrency-oversubscription-blackbox.js +0 -3
  324. package/dist/scripts/loop-fixture-production-misuse-blackbox.js +0 -3
  325. package/dist/scripts/loop-kill-interrupt-real-blackbox.js +0 -3
  326. package/dist/scripts/loop-merge-strategy-blackbox.js +0 -3
  327. package/dist/scripts/loop-mesh-production-e2e-blackbox.js +0 -3
  328. package/dist/scripts/loop-side-effect-blackbox.js +0 -3
  329. package/dist/scripts/mad-db-operation-lifecycle-blackbox.js +0 -29
  330. package/dist/scripts/mad-sks-actual-executor-blackbox.js +0 -5
  331. package/dist/scripts/mad-zellij-headless-fallback-blackbox.js +0 -4
  332. package/dist/scripts/mad-zellij-self-heal-blackbox.js +0 -4
  333. package/dist/scripts/naruto-loop-mesh-blackbox.js +0 -3
  334. package/dist/scripts/naruto-real-parallelism-blackbox.js +0 -307
  335. package/dist/scripts/naruto-worktree-coding-blackbox.js +0 -29
  336. package/dist/scripts/parallel-runtime-real-blackbox.js +0 -44
  337. package/dist/scripts/pipeline-codex-native-doctor-mad-routing-real-blackbox.js +0 -77
  338. package/dist/scripts/pipeline-codex-native-e2e-blackbox.js +0 -13
  339. package/dist/scripts/pipeline-codex-native-image-routing-real-blackbox.js +0 -50
  340. package/dist/scripts/pipeline-codex-native-loop-routing-real-blackbox.js +0 -74
  341. package/dist/scripts/pipeline-codex-native-qa-routing-real-blackbox.js +0 -51
  342. package/dist/scripts/pipeline-codex-native-research-routing-real-blackbox.js +0 -45
  343. package/dist/scripts/pipeline-execution-profile-routing-blackbox.js +0 -4
  344. package/dist/scripts/postinstall-global-doctor-blackbox.js +0 -12
  345. package/dist/scripts/ppt-full-e2e-blackbox-check.js +0 -109
  346. package/dist/scripts/ppt-imagegen-blackbox-check.js +0 -46
  347. package/dist/scripts/project-skill-dedupe-blackbox.js +0 -36
  348. package/dist/scripts/qa-backfill-route-blackbox.js +0 -5
  349. package/dist/scripts/qa-patch-swarm-route-blackbox.js +0 -10
  350. package/dist/scripts/release-full-parallelism-blackbox.js +0 -41
  351. package/dist/scripts/release-triwiki-first-runner-blackbox.js +0 -48
  352. package/dist/scripts/release-wiring-3110-blackbox.js +0 -27
  353. package/dist/scripts/release-wiring-3112-blackbox.js +0 -17
  354. package/dist/scripts/release-wiring-3113-blackbox.js +0 -17
  355. package/dist/scripts/research-backfill-route-blackbox.js +0 -5
  356. package/dist/scripts/research-final-reviewer-blackbox.js +0 -70
  357. package/dist/scripts/research-stage-cycle-runtime-blackbox.js +0 -40
  358. package/dist/scripts/research-synthesis-writer-blackbox.js +0 -24
  359. package/dist/scripts/route-blackbox-realism-check.js +0 -21
  360. package/dist/scripts/scheduler-resource-claim-blackbox.js +0 -24
  361. package/dist/scripts/seo-cli-blackbox-check.js +0 -18
  362. package/dist/scripts/sks-3110-all-feature-regression-blackbox.js +0 -116
  363. package/dist/scripts/sks-3112-all-feature-regression-blackbox.js +0 -29
  364. package/dist/scripts/sks-3113-all-feature-regression-blackbox.js +0 -17
  365. package/dist/scripts/sks-400-all-feature-regression-blackbox.js +0 -21
  366. package/dist/scripts/sks-400-extreme-parallel-blackbox.js +0 -8
  367. package/dist/scripts/sks-400-five-minute-blackbox.js +0 -9
  368. package/dist/scripts/sks-400-legacy-purge-blackbox.js +0 -8
  369. package/dist/scripts/sks-401-all-feature-regression-blackbox.js +0 -46
  370. package/dist/scripts/sks-401-five-minute-actual-blackbox.js +0 -23
  371. package/dist/scripts/sks-402-all-feature-regression-blackbox.js +0 -9
  372. package/dist/scripts/sks-402-five-minute-real-blackbox.js +0 -22
  373. package/dist/scripts/sksd-warm-cache-blackbox.js +0 -12
  374. package/dist/scripts/supabase-secret-preservation-blackbox.js +0 -29
  375. package/dist/scripts/team-backfill-route-blackbox.js +0 -5
  376. package/dist/scripts/team-parallel-write-blackbox.js +0 -55
  377. package/dist/scripts/team-patch-swarm-route-blackbox.js +0 -10
  378. package/dist/scripts/triwiki-affected-graph-blackbox.js +0 -28
  379. package/dist/scripts/triwiki-proof-bank-blackbox.js +0 -30
  380. package/dist/scripts/triwiki-proof-bank-lock-blackbox.js +0 -7
  381. package/dist/scripts/update-preserves-supabase-keys-blackbox.js +0 -27
  382. package/dist/scripts/ux-patch-swarm-route-blackbox.js +0 -10
  383. package/dist/scripts/ux-review-imagegen-blackbox-check.js +0 -67
  384. package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -28
  385. package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -80
  386. package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -137
  387. package/dist/scripts/zellij-self-heal-typed-blackbox.js +0 -4
  388. package/dist/scripts/zellij-slot-telemetry-real-blackbox.js +0 -20
  389. package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -81
  390. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -202
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path';
2
2
  import { projectRoot, readJson, readText, writeJsonAtomic, appendJsonl, readStdin, nowIso, runProcess, sha256, packageRoot, tmpdir } from './fsx.js';
3
3
  import { looksInteractiveCommand, interactiveCommandReason } from './no-question-guard.js';
4
- import { missionDir, setCurrent, stateFile } from './mission.js';
4
+ import { loadStateForSession, missionDir, setCurrent } from './mission.js';
5
5
  import { checkDbOperation, dbBlockReason, handleMadSksUserConfirmation } from './db-safety.js';
6
6
  import { maybeRecordMadDbToolResultFromToolUse } from './mad-db/mad-db-result-lifecycle.js';
7
7
  import { checkHarnessModification, harnessGuardBlockReason, isHarnessSourceProject } from './harness-guard.js';
@@ -16,6 +16,8 @@ import { leanEngineeringCompactText } from './lean-engineering-policy.js';
16
16
  import { appendMissionStatus } from './recallpulse.js';
17
17
  import { scanAgentTextForRecursion } from './agents/agent-recursion-guard.js';
18
18
  import { evaluateLoopContinuation } from './loops/loop-continuation-enforcer.js';
19
+ import { diagnosticPromptAllowedDuringNoQuestions } from './routes/diagnostic-allowlist.js';
20
+ import { maybeReconcileProjectSkillsPreflight } from './hooks-runtime/skill-reconcile-preflight.js';
19
21
  import { buildCompactContinue, buildPermissionRequestAllow, buildPermissionRequestDeny, buildPostToolUseBlock, buildPostToolUseContinue, buildPreToolUseContinue, buildPreToolUseDeny, buildSessionStartContinue, buildStopBlock, buildStopContinue, buildSubagentStartContinue, buildSubagentStopBlock, buildSubagentStopContinue, buildUserPromptSubmitBlock, buildUserPromptSubmitContinue } from './codex-compat/codex-hook-output-builders.js';
20
22
  import { joinSystemMessages, teamLiveDigest } from './hooks-runtime/team-digest.js';
21
23
  const STOP_REPEAT_GUARD_ARTIFACT = 'stop-hook-repeat-guard.json';
@@ -38,8 +40,8 @@ async function loadHookPayload() {
38
40
  return { raw };
39
41
  }
40
42
  }
41
- async function loadState(root) {
42
- return readJson(stateFile(root), {});
43
+ async function loadState(root, payload = {}) {
44
+ return loadStateForSession(root, conversationId(payload));
43
45
  }
44
46
  function isNoQuestionRunning(state) {
45
47
  return (state.mode === 'RESEARCH' && state.phase === 'RESEARCH_RUNNING_NO_QUESTIONS')
@@ -61,6 +63,9 @@ function extractUserPrompt(payload) {
61
63
  function conversationId(payload) {
62
64
  return String(payload.conversation_id || payload.thread_id || payload.session_id || payload.chat_id || payload.cwd || 'default');
63
65
  }
66
+ function explicitConversationId(payload = {}) {
67
+ return payload.conversation_id || payload.thread_id || payload.session_id || payload.chat_id || null;
68
+ }
64
69
  function extractCommand(payload) {
65
70
  return payload.command || payload.tool_input?.command || payload.toolInput?.command || payload.input?.command || payload.tool?.input?.command || '';
66
71
  }
@@ -176,27 +181,39 @@ export async function hookMain(name) {
176
181
  }
177
182
  export async function evaluateHookPayload(name, payload = {}, opts = {}) {
178
183
  const root = opts.root || await projectRoot(payload.cwd || process.cwd());
179
- const state = opts.state || payload.state || await loadState(root);
184
+ const sessionKey = conversationId(payload);
185
+ if (!explicitConversationId(payload)) {
186
+ await appendJsonl(path.join(root, '.sneakoscope', 'state', 'session-id-fallback-warning.jsonl'), {
187
+ ts: nowIso(),
188
+ warning: 'hook_payload_missing_explicit_session_id',
189
+ conversation_id: sessionKey,
190
+ cwd_hash: sha256(String(payload.cwd || root)).slice(0, 12),
191
+ hook: name
192
+ }).catch(() => null);
193
+ }
194
+ const loadedState = opts.state || payload.state || await loadState(root, payload);
195
+ const state = { ...loadedState, _session_key: loadedState?._session_key || sessionKey };
180
196
  const noQuestion = isNoQuestionRunning(state);
181
197
  if (name === 'user-prompt-submit') {
182
198
  const modelBlock = blockForbiddenClientModel(payload);
183
199
  if (modelBlock)
184
200
  return modelBlock;
185
- return hookUserPrompt(root, state, payload, noQuestion);
201
+ return hookUserPrompt(root, state, payload, noQuestion, sessionKey);
186
202
  }
187
203
  if (name === 'pre-tool')
188
- return hookPreTool(root, state, payload, noQuestion);
204
+ return hookPreTool(root, state, payload, noQuestion, sessionKey);
189
205
  if (name === 'post-tool')
190
- return hookPostTool(root, state, payload, noQuestion);
206
+ return hookPostTool(root, state, payload, noQuestion, sessionKey);
191
207
  if (name === 'permission-request')
192
- return hookPermission(root, state, payload, noQuestion);
208
+ return hookPermission(root, state, payload, noQuestion, sessionKey);
193
209
  if (name === 'stop')
194
- return hookStop(root, state, payload, noQuestion);
210
+ return hookStop(root, state, payload, noQuestion, sessionKey);
195
211
  if (name === 'subagent-start')
196
- return hookSubagentStart(root, state);
212
+ return hookSubagentStart(root, state, sessionKey);
197
213
  return { continue: true };
198
214
  }
199
- async function hookSubagentStart(root, state) {
215
+ async function hookSubagentStart(root, state, sessionKey = null) {
216
+ void sessionKey;
200
217
  const active = await activeRouteContext(root, state).catch(() => '');
201
218
  const additionalContext = [leanEngineeringCompactText(), active].filter(Boolean).join('\n\n');
202
219
  return { continue: true, additionalContext };
@@ -265,7 +282,7 @@ function clientModelCandidates(value, depth = 0) {
265
282
  }
266
283
  return out;
267
284
  }
268
- async function hookUserPrompt(root, state, payload, noQuestion) {
285
+ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = null) {
269
286
  if (looksLikeCodexGitAction(payload)) {
270
287
  await armCodexGitActionStopBypass(root, payload).catch(() => null);
271
288
  return {
@@ -279,6 +296,7 @@ async function hookUserPrompt(root, state, payload, noQuestion) {
279
296
  systemMessage: 'SKS: Codex App settings/profile event ignored; route gates unchanged.'
280
297
  };
281
298
  }
299
+ await maybeReconcileProjectSkillsPreflight(root).catch(() => null);
282
300
  if (!noQuestion) {
283
301
  const prompt = stripVisibleDecisionAnswerBlocks(extractUserPrompt(payload));
284
302
  const madSksConfirmation = await handleMadSksUserConfirmation(root, state, prompt);
@@ -311,12 +329,13 @@ async function hookUserPrompt(root, state, payload, noQuestion) {
311
329
  return { continue: true, additionalContext, systemMessage: joinSystemMessages(visibleHookMessage('user-prompt-submit', additionalContext), teamDigest?.system) };
312
330
  }
313
331
  const teamDigest = (bypassActiveRoute || command || prepareFreshRoute) ? null : await teamLiveDigest(root, state);
314
- const activeContext = await activeRouteContext(root, state);
332
+ const shouldLoadActiveContext = !command && !bypassActiveRoute && !goalOverlay && !prepareFreshRoute;
333
+ const activeContext = shouldLoadActiveContext ? await activeRouteContext(root, state) : '';
315
334
  const contexts = [updateContext];
316
- if (activeContext && !command && !bypassActiveRoute && !goalOverlay && !prepareFreshRoute)
335
+ if (activeContext && shouldLoadActiveContext)
317
336
  contexts.push(routePipelineContext(prompt), activeContext);
318
337
  else
319
- contexts.push((await prepareRoute(root, prompt, state)).additionalContext);
338
+ contexts.push((await prepareRoute(root, prompt, state, { sessionKey })).additionalContext);
320
339
  if (goalOverlay)
321
340
  contexts.push(goalOverlay);
322
341
  if (teamDigest?.context)
@@ -324,6 +343,13 @@ async function hookUserPrompt(root, state, payload, noQuestion) {
324
343
  const additionalContext = contexts.filter(Boolean).join('\n\n');
325
344
  return { continue: true, additionalContext, systemMessage: joinSystemMessages(visibleHookMessage('user-prompt-submit', additionalContext), teamDigest?.system) };
326
345
  }
346
+ const prompt = stripVisibleDecisionAnswerBlocks(extractUserPrompt(payload));
347
+ if (diagnosticPromptAllowedDuringNoQuestions(prompt)) {
348
+ return {
349
+ continue: true,
350
+ systemMessage: 'SKS: diagnostic command allowed during no-question mode by command registry contract.'
351
+ };
352
+ }
327
353
  const id = state.mission_id;
328
354
  if (id)
329
355
  await appendJsonl(path.join(missionDir(root, id), 'user_queue.jsonl'), { ts: nowIso(), payload });
@@ -380,18 +406,21 @@ function activeGoalOverlayContext(state = {}, route = null) {
380
406
  `Goal artifact: .sneakoscope/missions/${state.mission_id}/goal-workflow.json. Use Codex native /goal controls only if the user explicitly returns to $Goal.`
381
407
  ].join('\n');
382
408
  }
383
- async function hookPreTool(root, state, payload, noQuestion) {
384
- const madSksImmutableDecision = await checkMadSksImmutableModification(root, state, payload);
385
- if (madSksImmutableDecision.action === 'block') {
386
- return { decision: 'block', permissionDecision: 'deny', reason: madSksImmutableBlockReason(madSksImmutableDecision) };
387
- }
388
- const harnessDecision = await checkHarnessModification(root, payload, { phase: 'pre-tool' });
389
- if (harnessDecision.action === 'block') {
390
- return { decision: 'block', permissionDecision: 'deny', reason: harnessGuardBlockReason(harnessDecision) };
391
- }
392
- const dbDecision = await checkDbOperation(root, state, payload, { duringNoQuestion: noQuestion });
393
- if (dbDecision.action === 'block' || dbDecision.action === 'confirm') {
394
- return { decision: 'block', permissionDecision: 'deny', reason: dbBlockReason(dbDecision) };
409
+ async function hookPreTool(root, state, payload, noQuestion, sessionKey = null) {
410
+ void sessionKey;
411
+ if (needsMutationSafetyCheck(payload)) {
412
+ const madSksImmutableDecision = await checkMadSksImmutableModification(root, state, payload);
413
+ if (madSksImmutableDecision.action === 'block') {
414
+ return { decision: 'block', permissionDecision: 'deny', reason: madSksImmutableBlockReason(madSksImmutableDecision) };
415
+ }
416
+ const harnessDecision = await checkHarnessModification(root, payload, { phase: 'pre-tool' });
417
+ if (harnessDecision.action === 'block') {
418
+ return { decision: 'block', permissionDecision: 'deny', reason: harnessGuardBlockReason(harnessDecision) };
419
+ }
420
+ const dbDecision = await checkDbOperation(root, state, payload, { duringNoQuestion: noQuestion });
421
+ if (dbDecision.action === 'block' || dbDecision.action === 'confirm') {
422
+ return { decision: 'block', permissionDecision: 'deny', reason: dbBlockReason(dbDecision) };
423
+ }
395
424
  }
396
425
  if (clarificationGateLocked(state) && !clarificationAnswerToolAllowed(payload)) {
397
426
  return { decision: 'block', permissionDecision: 'deny', reason: clarificationPauseBlockReason(state) };
@@ -430,12 +459,14 @@ function agentWorkerHookContext(state = {}, payload = {}) {
430
459
  || payload.agent_worker === true
431
460
  || payload.agentWorker === true);
432
461
  }
433
- async function hookPostTool(root, state, payload, noQuestion) {
434
- await recordMadDbPostToolLifecycle(root, state, payload).catch(() => null);
435
- await recordContext7Evidence(root, state, payload).catch(() => null);
436
- await recordSubagentEvidence(root, state, payload).catch(() => null);
437
- if (toolFailed(payload))
438
- await recordToolErrorTaxonomy(root, state, payload).catch(() => null);
462
+ async function hookPostTool(root, state, payload, noQuestion, sessionKey = null) {
463
+ state = { ...state, _session_key: state?._session_key || sessionKey };
464
+ await Promise.all([
465
+ recordMadDbPostToolLifecycle(root, state, payload).catch(() => null),
466
+ recordContext7Evidence(root, state, payload).catch(() => null),
467
+ recordSubagentEvidence(root, state, payload).catch(() => null),
468
+ toolFailed(payload) ? recordToolErrorTaxonomy(root, state, payload).catch(() => null) : Promise.resolve(null)
469
+ ]);
439
470
  const teamDigest = await teamLiveDigest(root, state);
440
471
  if (!noQuestion) {
441
472
  return teamDigest?.context
@@ -455,6 +486,17 @@ async function hookPostTool(root, state, payload, noQuestion) {
455
486
  ? { continue: true, additionalContext: teamDigest.context, systemMessage: joinSystemMessages(visibleHookMessage('post-tool'), teamDigest.system) }
456
487
  : { continue: true };
457
488
  }
489
+ function needsMutationSafetyCheck(payload = {}) {
490
+ const toolName = String(payload.tool_name || payload.toolName || payload.name || payload.tool?.name || '');
491
+ const knownReadOnly = /^(Read|Grep|Glob|LS|TodoRead|WebFetch|WebSearch|BashOutput|NotebookRead|ListMcpResources|ReadMcpResource)$/i;
492
+ if (knownReadOnly.test(toolName))
493
+ return /\b(sql|supabase|db|migration)\b/i.test(JSON.stringify(payload || {}));
494
+ if (/^(Edit|Write|MultiEdit|NotebookEdit|Bash|Shell|ApplyPatch)$/i.test(toolName))
495
+ return true;
496
+ if (/\b(sql|supabase|db|migration)\b/i.test(toolName))
497
+ return true;
498
+ return true;
499
+ }
458
500
  async function recordMadDbPostToolLifecycle(root, state = {}, payload = {}) {
459
501
  if (!state?.mission_id)
460
502
  return null;
@@ -508,7 +550,8 @@ async function recordToolErrorTaxonomy(root, state = {}, payload = {}) {
508
550
  await appendJsonl(path.join(missionDir(root, state.mission_id), 'tool-errors.jsonl'), record);
509
551
  return record;
510
552
  }
511
- async function hookPermission(root, state, payload, noQuestion) {
553
+ async function hookPermission(root, state, payload, noQuestion, sessionKey = null) {
554
+ void sessionKey;
512
555
  const madSksImmutableDecision = await checkMadSksImmutableModification(root, state, payload);
513
556
  if (madSksImmutableDecision.action === 'block') {
514
557
  return { decision: 'deny', permissionDecision: 'deny', reason: madSksImmutableBlockReason(madSksImmutableDecision) };
@@ -610,7 +653,7 @@ function clarificationPauseBlockReason(state = {}) {
610
653
  const route = state.route_command || state.route || state.mode || 'route';
611
654
  return `SKS ${route} ambiguity gate is paused and waiting for explicit user answers. Do not run implementation, tests, route materialization, or unrelated tools yet. The only allowed action is sealing the user's reply with "sks pipeline answer ${id} --stdin"; elapsed time or repeated hook resumes never count as answers.`;
612
655
  }
613
- async function hookStop(root, state, payload, noQuestion) {
656
+ async function hookStop(root, state, payload, noQuestion, sessionKey = null) {
614
657
  const last = extractLastMessage(payload);
615
658
  if (state?.mode === 'LOOP' || state?.route === 'Loop' || state?.route_command === '$Loop') {
616
659
  const missionId = state?.mission_id;
@@ -664,14 +707,14 @@ async function hookStop(root, state, payload, noQuestion) {
664
707
  };
665
708
  }
666
709
  if (shouldLoopBackAfterHonestMode(state) && hasHonestModeUnresolvedGap(last)) {
667
- const loopback = await recordHonestModeLoopback(root, state, last);
710
+ const loopback = await recordHonestModeLoopback(root, state, last, sessionKey);
668
711
  return {
669
712
  decision: 'block',
670
713
  reason: `${localizedFinalizationReason('honest_loopback', languageBasis)} Loopback: ${loopback.relative_file}`
671
714
  };
672
715
  }
673
716
  if (state?.honest_loop_required)
674
- await resolveHonestModeLoopback(root, state);
717
+ await resolveHonestModeLoopback(root, state, sessionKey);
675
718
  return { continue: true };
676
719
  }
677
720
  return {
@@ -691,7 +734,7 @@ async function consumeLightRouteStop(root, payload = {}) {
691
734
  if (!Number.isFinite(expiresMs) || expiresMs < nowMs)
692
735
  return false;
693
736
  const currentConversation = conversationId(payload);
694
- if (record.conversation_id && explicitConversationId(payload) && record.conversation_id !== currentConversation)
737
+ if (record.conversation_id && record.conversation_id !== currentConversation)
695
738
  return false;
696
739
  await writeJsonAtomic(file, {
697
740
  ...record,
@@ -712,9 +755,6 @@ function hasDfixLightCompletion(text) {
712
755
  const gap = /(미검증|남은|문제|gap|remaining|not verified|not run|blocker|차단|불가|없음|none)/i.test(s);
713
756
  return verification && gap;
714
757
  }
715
- function explicitConversationId(payload = {}) {
716
- return payload.conversation_id || payload.thread_id || payload.session_id || payload.chat_id || null;
717
- }
718
758
  function looksLikeCodexGitAction(payload = {}) {
719
759
  const prompt = stripVisibleDecisionAnswerBlocks(extractUserPrompt(payload));
720
760
  const metadataText = codexGitActionMetadataText(payload);
@@ -824,7 +864,7 @@ async function consumeCodexGitActionStopBypass(root, payload = {}) {
824
864
  if (!Number.isFinite(expiresMs) || expiresMs < Date.now())
825
865
  return false;
826
866
  const currentConversation = conversationId(payload);
827
- if (record.conversation_id && explicitConversationId(payload) && record.conversation_id !== currentConversation)
867
+ if (record.conversation_id && record.conversation_id !== currentConversation)
828
868
  return false;
829
869
  await writeJsonAtomic(file, {
830
870
  ...record,
@@ -971,7 +1011,7 @@ function shouldLoopBackAfterHonestMode(state = {}) {
971
1011
  return false;
972
1012
  return Boolean(state.ambiguity_gate_passed || state.clarification_passed || /CONTRACT_SEALED|HONEST_LOOPBACK/i.test(String(state.phase || '')));
973
1013
  }
974
- async function recordHonestModeLoopback(root, state = {}, lastMessage = '') {
1014
+ async function recordHonestModeLoopback(root, state = {}, lastMessage = '', sessionKey = null) {
975
1015
  const id = state.mission_id;
976
1016
  const dir = missionDir(root, id);
977
1017
  const previousPhase = state.phase || null;
@@ -999,10 +1039,10 @@ async function recordHonestModeLoopback(root, state = {}, lastMessage = '') {
999
1039
  questions_allowed: false,
1000
1040
  ambiguity_gate_required: true,
1001
1041
  ambiguity_gate_passed: true
1002
- });
1042
+ }, { sessionKey: sessionKey || state._session_key });
1003
1043
  return { file, relative_file: path.relative(root, file).split(path.sep).join('/') };
1004
1044
  }
1005
- async function resolveHonestModeLoopback(root, state = {}) {
1045
+ async function resolveHonestModeLoopback(root, state = {}, sessionKey = null) {
1006
1046
  const id = state.mission_id;
1007
1047
  const mode = String(state.mode || state.route || 'SKS').toUpperCase();
1008
1048
  if (id)
@@ -1012,7 +1052,7 @@ async function resolveHonestModeLoopback(root, state = {}) {
1012
1052
  honest_loop_required: false,
1013
1053
  honest_loop_resolved_at: nowIso(),
1014
1054
  questions_allowed: true
1015
- });
1055
+ }, { sessionKey: sessionKey || state._session_key });
1016
1056
  }
1017
1057
  export async function emitHook(name) {
1018
1058
  const result = await hookMain(name);
@@ -107,6 +107,7 @@ export function createCodexAppImagegenAdapter(opts = {}) {
107
107
  schema: 'sks.image-ux-gpt-image-2-response.v1',
108
108
  created_at: nowIso(),
109
109
  provider: 'codex_app_imagegen',
110
+ evidence_class: 'codex_app_imagegen',
110
111
  model: 'gpt-image-2',
111
112
  ok: false,
112
113
  status: 'blocked',
@@ -131,11 +132,13 @@ export function createCodexAppImagegenAdapter(opts = {}) {
131
132
  schema: 'sks.image-ux-gpt-image-2-response.v1',
132
133
  created_at: nowIso(),
133
134
  provider: 'codex_app_imagegen',
135
+ evidence_class: 'codex_app_imagegen',
134
136
  model: 'gpt-image-2',
135
137
  ok: true,
136
138
  status: 'generated',
137
139
  output_image_path: dest,
138
140
  output_image_sha256: meta.sha256,
141
+ output_sha256: meta.sha256,
139
142
  output_id: meta.output_id,
140
143
  output_source: outputSource,
141
144
  image_artifact_path_contract: imageContract?.artifact_path || null,
@@ -161,6 +164,7 @@ export function createCodexAppImagegenAdapter(opts = {}) {
161
164
  schema: 'sks.image-ux-gpt-image-2-response.v1',
162
165
  created_at: nowIso(),
163
166
  provider: 'codex_app_imagegen',
167
+ evidence_class: 'codex_app_imagegen',
164
168
  model: 'gpt-image-2',
165
169
  ok: false,
166
170
  status: 'blocked',
@@ -196,6 +200,22 @@ export function createFakeImagegenAdapter(opts = {}) {
196
200
  await ensureDir(input.output_dir);
197
201
  const requestArtifact = path.join(input.output_dir, 'image-ux-gpt-image-2-request.json');
198
202
  const responseArtifact = path.join(input.output_dir, 'image-ux-gpt-image-2-response.json');
203
+ if (!imagegenMockContext(opts)) {
204
+ await writeJsonAtomic(responseArtifact, {
205
+ schema: 'sks.image-ux-gpt-image-2-response.v1',
206
+ created_at: nowIso(),
207
+ provider: 'fake_imagegen_adapter',
208
+ fake_adapter: true,
209
+ execution_class: 'mock_fixture',
210
+ evidence_class: 'mock_fixture',
211
+ model: 'gpt-image-2',
212
+ ok: false,
213
+ status: 'blocked',
214
+ blocker: 'fake_imagegen_requires_test_or_mock_context',
215
+ local_only: true
216
+ });
217
+ return { ok: false, status: 'blocked', generated_image_path: null, output_id: null, blocker: 'fake_imagegen_requires_test_or_mock_context', provider: 'fake_imagegen_adapter', request_artifact: null, response_artifact: responseArtifact, latency_ms: Date.now() - started };
218
+ }
199
219
  const validation = await validateGptImage2Request({
200
220
  provider: 'fake_imagegen_adapter',
201
221
  endpoint: 'local hermetic fixture',
@@ -227,6 +247,9 @@ export function createFakeImagegenAdapter(opts = {}) {
227
247
  schema: 'sks.image-ux-gpt-image-2-response.v1',
228
248
  created_at: nowIso(),
229
249
  provider: 'fake_imagegen_adapter',
250
+ fake_adapter: true,
251
+ execution_class: 'mock_fixture',
252
+ evidence_class: 'mock_fixture',
230
253
  model: 'gpt-image-2',
231
254
  ok: false,
232
255
  status: 'blocked',
@@ -251,16 +274,20 @@ export function createFakeImagegenAdapter(opts = {}) {
251
274
  schema: 'sks.image-ux-gpt-image-2-response.v1',
252
275
  created_at: nowIso(),
253
276
  provider: 'fake_imagegen_adapter',
277
+ fake_adapter: true,
278
+ execution_class: 'mock_fixture',
279
+ evidence_class: 'mock_fixture',
254
280
  model: 'gpt-image-2',
255
281
  ok: true,
256
282
  status: 'generated',
257
283
  output_image_path: out,
258
284
  output_image_sha256: meta.sha256,
285
+ output_sha256: meta.sha256,
259
286
  output_id: meta.output_id,
287
+ output_source: 'mock_fixture',
260
288
  image_artifact_path_contract: imageContract?.artifact_path || null,
261
289
  dimensions: { width: meta.width, height: meta.height, format: meta.format },
262
290
  latency_ms: Date.now() - started,
263
- fake_adapter: true,
264
291
  source: 'mock_like_fixture',
265
292
  real_generated: false,
266
293
  mock: true,
@@ -320,6 +347,7 @@ export function createOpenAIImagesApiAdapter(opts = {}) {
320
347
  schema: 'sks.image-ux-gpt-image-2-response.v1',
321
348
  created_at: nowIso(),
322
349
  provider: 'openai_images_api',
350
+ evidence_class: 'non_codex_api_fallback',
323
351
  model: 'gpt-image-2',
324
352
  ok: false,
325
353
  status: 'blocked',
@@ -334,6 +362,7 @@ export function createOpenAIImagesApiAdapter(opts = {}) {
334
362
  schema: 'sks.image-ux-gpt-image-2-response.v1',
335
363
  created_at: nowIso(),
336
364
  provider: 'openai_images_api',
365
+ evidence_class: 'non_codex_api_fallback',
337
366
  model: 'gpt-image-2',
338
367
  ok: false,
339
368
  status: 'blocked',
@@ -397,6 +426,7 @@ export function createOpenAIImagesApiAdapter(opts = {}) {
397
426
  schema: 'sks.image-ux-gpt-image-2-response.v1',
398
427
  created_at: nowIso(),
399
428
  provider: 'openai_responses_image_generation',
429
+ evidence_class: 'non_codex_api_fallback',
400
430
  model: 'gpt-image-2',
401
431
  responses_model: responsesImagegenModel(opts),
402
432
  auth_source: auth.auth_source,
@@ -404,6 +434,7 @@ export function createOpenAIImagesApiAdapter(opts = {}) {
404
434
  status: 'generated',
405
435
  output_image_path: out,
406
436
  output_image_sha256: meta.sha256,
437
+ output_sha256: meta.sha256,
407
438
  output_id: meta.output_id,
408
439
  image_artifact_path_contract: imageContract?.artifact_path || null,
409
440
  dimensions: { width: meta.width, height: meta.height, format: meta.format },
@@ -454,12 +485,14 @@ export function createOpenAIImagesApiAdapter(opts = {}) {
454
485
  schema: 'sks.image-ux-gpt-image-2-response.v1',
455
486
  created_at: nowIso(),
456
487
  provider: 'openai_images_api',
488
+ evidence_class: 'non_codex_api_fallback',
457
489
  model: 'gpt-image-2',
458
490
  auth_source: auth.auth_source,
459
491
  ok: true,
460
492
  status: 'generated',
461
493
  output_image_path: out,
462
494
  output_image_sha256: meta.sha256,
495
+ output_sha256: meta.sha256,
463
496
  output_id: meta.output_id,
464
497
  image_artifact_path_contract: imageContract?.artifact_path || null,
465
498
  dimensions: { width: meta.width, height: meta.height, format: meta.format },
@@ -511,24 +544,17 @@ async function resolveImageArtifactRoot(input) {
511
544
  return projectRoot(input.output_dir || process.cwd()).catch(() => cwdRoot);
512
545
  }
513
546
  export async function generateGptImage2CalloutReview(input, opts = {}) {
514
- if (opts.fake === true || process.env.SKS_TEST_FAKE_IMAGEGEN === '1') {
515
- return createFakeImagegenAdapter(opts.fakeAdapter || {}).generateCalloutReview(input);
547
+ if ((opts.fake === true || process.env.SKS_TEST_FAKE_IMAGEGEN === '1') && imagegenMockContext(opts)) {
548
+ return createFakeImagegenAdapter({ ...(opts.fakeAdapter || {}), mockContext: true }).generateCalloutReview(input);
516
549
  }
517
550
  const capability = await detectImagegenCapability(opts.capability || {}).catch(() => null);
518
- // Auto-enable the OpenAI direct-key API fallback whenever an OPENAI_API_KEY is
519
- // available, so a missing/failed Codex App $imagegen surface still produces a
520
- // real image instead of a hard block. Explicit opt-out wins: pass
521
- // allowApiFallback:false or SKS_IMAGEGEN_ALLOW_API_FALLBACK=0.
522
- const openAiKeyPresent = Boolean(opts.openai?.apiKey || process.env.OPENAI_API_KEY);
523
- const explicitDisableApiFallback = opts.allowApiFallback === false || process.env.SKS_IMAGEGEN_ALLOW_API_FALLBACK === '0';
524
551
  // codex-lb imagegen is a direct API fallback, not Codex App imagegen evidence.
525
552
  // It must be explicitly enabled by the caller or environment.
526
553
  const explicitDisableCodexLbFallback = opts.allowCodexLbApiFallback === false || process.env.SKS_IMAGEGEN_ALLOW_CODEX_LB_API_FALLBACK === '0';
527
554
  const allowCodexLbApiFallback = !explicitDisableCodexLbFallback && (opts.allowCodexLbApiFallback === true
528
555
  || process.env.SKS_IMAGEGEN_ALLOW_CODEX_LB_API_FALLBACK === '1');
529
- const allowApiFallback = !explicitDisableApiFallback && (opts.allowApiFallback === true
556
+ const allowApiFallback = (opts.allowApiFallback === true
530
557
  || process.env.SKS_IMAGEGEN_ALLOW_API_FALLBACK === '1'
531
- || openAiKeyPresent
532
558
  || allowCodexLbApiFallback);
533
559
  const openaiOptions = {
534
560
  ...(opts.openai || {}),
@@ -544,6 +570,13 @@ export async function generateGptImage2CalloutReview(input, opts = {}) {
544
570
  return codexResult;
545
571
  return createOpenAIImagesApiAdapter(openaiOptions).generateCalloutReview(input);
546
572
  }
573
+ function imagegenMockContext(opts = {}) {
574
+ return opts.mockContext === true
575
+ || opts.testContext === true
576
+ || process.env.NODE_ENV === 'test'
577
+ || process.env.SKS_SELFTEST_MOCK === '1'
578
+ || process.env.SKS_MOCK === '1';
579
+ }
547
580
  export function imagegenCapabilityBlocker(surface = 'Codex App $imagegen') {
548
581
  return {
549
582
  schema: 'sks.image-ux-imagegen-blocker.v1',
@@ -705,6 +738,9 @@ export async function generatedImageMetadata(root, imagePath, opts = {}) {
705
738
  source_screen_id: opts.source_screen_id || null,
706
739
  provider_model: 'gpt-image-2',
707
740
  provider_surface: opts.provider_surface || 'codex_app_imagegen',
741
+ evidence_class: opts.evidence_class || (opts.mock ? 'mock_fixture' : 'codex_app_imagegen'),
742
+ output_source: opts.output_source || (opts.mock ? 'mock_fixture' : 'manual_attach'),
743
+ output_sha256: opts.output_sha256 || await sha256File(absolute),
708
744
  requested_fidelity: 'high_fidelity_automatic',
709
745
  image_input_fidelity_note: 'high_fidelity_automatic',
710
746
  privacy: 'local-only',
@@ -729,6 +765,7 @@ function redactedImagegenResponse(payload, ok, latencyMs, provider = 'openai_ima
729
765
  schema: 'sks.image-ux-gpt-image-2-response.v1',
730
766
  created_at: nowIso(),
731
767
  provider,
768
+ evidence_class: provider === 'codex_app_imagegen' ? 'codex_app_imagegen' : 'non_codex_api_fallback',
732
769
  model: 'gpt-image-2',
733
770
  ok,
734
771
  status: ok ? 'generated' : 'blocked',
@@ -790,11 +790,14 @@ function buildImagegenResponseArtifact(generatedReviewLedger = {}) {
790
790
  schema: 'sks.image-ux-gpt-image-2-response.v1',
791
791
  created_at: nowIso(),
792
792
  provider: image?.provider_surface || generatedReviewLedger.provider?.preferred_surface || 'none',
793
+ evidence_class: image?.evidence_class || (image?.mock ? 'mock_fixture' : image?.real_generated ? 'codex_app_imagegen' : null),
793
794
  model: 'gpt-image-2',
794
795
  ok: generatedReviewLedger.passed === true,
795
796
  status: generatedReviewLedger.passed === true ? 'generated' : 'blocked_or_pending',
796
797
  output_image_path: image?.path || null,
797
798
  output_image_sha256: image?.sha256 || null,
799
+ output_sha256: image?.output_sha256 || image?.sha256 || null,
800
+ output_source: image?.output_source || (image?.mock ? 'mock_fixture' : image?.real_generated ? 'manual_attach' : null),
798
801
  output_id: image?.output_id || null,
799
802
  dimensions: image ? { width: image.width || null, height: image.height || null, format: image.format || null } : null,
800
803
  latency_ms: image?.latency_ms || null,
@@ -863,6 +866,19 @@ function generatedImageEvidenceBlockers(image = {}, evidence = {}) {
863
866
  if (image.real_generated !== true || image.mock === true || image.source === 'mock_fixture')
864
867
  return [];
865
868
  const blockers = [];
869
+ const evidenceClass = String(image.evidence_class || '');
870
+ const outputSource = String(image.output_source || '');
871
+ const outputSha = String(image.output_sha256 || image.output_image_sha256 || '');
872
+ if (!evidenceClass)
873
+ blockers.push('generated_review_image_evidence_class_missing');
874
+ else if (evidenceClass !== 'codex_app_imagegen')
875
+ blockers.push(`generated_review_image_evidence_class_not_codex_app:${evidenceClass}`);
876
+ if (outputSource && !['manual_attach', 'auto_discovered_generated_images'].includes(outputSource))
877
+ blockers.push(`generated_review_image_output_source_invalid:${outputSource}`);
878
+ if (!outputSha)
879
+ blockers.push('generated_review_image_output_sha256_missing');
880
+ else if (evidence.sha256 && outputSha !== evidence.sha256)
881
+ blockers.push('generated_review_image_output_sha256_mismatch');
866
882
  if (!image.path)
867
883
  blockers.push('generated_review_image_missing');
868
884
  if (!evidence.sha256)
@@ -18,8 +18,13 @@ export async function detectImagegenCapability(opts = {}) {
18
18
  }).catch(() => null);
19
19
  const apiFallbackAvailable = openaiApiKeyPresent;
20
20
  const fakeAdapterEnabled = opts.fake === true || env.SKS_TEST_FAKE_IMAGEGEN === '1';
21
- const realGenerationAvailable = codexAppBuiltInAvailable || apiFallbackAvailable;
22
- const routeGenerationAvailable = realGenerationAvailable || fakeAdapterEnabled;
21
+ const fakeAdapterAcceptedForRoute = fakeAdapterEnabled && (opts.mockContext === true
22
+ || opts.testContext === true
23
+ || env.NODE_ENV === 'test'
24
+ || env.SKS_SELFTEST_MOCK === '1'
25
+ || env.SKS_MOCK === '1');
26
+ const realGenerationAvailable = codexAppBuiltInAvailable;
27
+ const routeGenerationAvailable = codexAppBuiltInAvailable || fakeAdapterAcceptedForRoute;
23
28
  const coreReady = codexAppBuiltInAvailable;
24
29
  const coreBlockers = coreReady ? [] : ['codex_app_builtin_imagegen_capability_missing'];
25
30
  const routeGenerationBlockers = routeGenerationAvailable ? [] : ['imagegen_capability_missing'];
@@ -68,16 +73,17 @@ export async function detectImagegenCapability(opts = {}) {
68
73
  },
69
74
  fake_adapter: {
70
75
  available: fakeAdapterEnabled,
76
+ accepted_for_route_readiness: fakeAdapterAcceptedForRoute,
71
77
  env: 'SKS_TEST_FAKE_IMAGEGEN=1',
72
78
  source: 'mock_like_fixture',
73
79
  real_generation_claim_allowed: false
74
80
  },
75
- supports_reference_image: codexAppBuiltInAvailable || apiFallbackAvailable || fakeAdapterEnabled,
81
+ supports_reference_image: codexAppBuiltInAvailable || fakeAdapterAcceptedForRoute,
76
82
  gpt_image_2_input_fidelity_automatic: true,
77
83
  input_fidelity_must_be_omitted: true,
78
84
  supported_workflows: {
79
- ux_review_callouts: codexAppBuiltInAvailable || apiFallbackAvailable || fakeAdapterEnabled,
80
- ppt_slide_callouts: codexAppBuiltInAvailable || apiFallbackAvailable || fakeAdapterEnabled,
85
+ ux_review_callouts: codexAppBuiltInAvailable || fakeAdapterAcceptedForRoute,
86
+ ppt_slide_callouts: codexAppBuiltInAvailable || fakeAdapterAcceptedForRoute,
81
87
  structured_extraction_required_after_generation: true,
82
88
  full_verification_requires_codex_app_output: true
83
89
  },
@@ -0,0 +1,57 @@
1
+ import { detectImagegenCapability } from './imagegen-capability.js';
2
+ import { repairCodexImagegen } from '../doctor/imagegen-repair.js';
3
+ export async function requireCodexImagegen(root, opts = {}) {
4
+ const capability = await detectImagegenCapability({
5
+ codexBin: opts.codexBin || undefined,
6
+ timeoutMs: opts.timeoutMs || 5000
7
+ }).catch((err) => ({
8
+ ok: false,
9
+ core_ready: false,
10
+ blockers: [err instanceof Error ? err.message : String(err)]
11
+ }));
12
+ if (capability.core_ready === true) {
13
+ return { ok: true, capability, repair: null, blocker: null, blockers: [] };
14
+ }
15
+ const repair = opts.autoRepair === true
16
+ ? await repairCodexImagegen({
17
+ root,
18
+ apply: opts.applyRepair === true,
19
+ codexBin: opts.codexBin || null,
20
+ timeoutMs: opts.timeoutMs || 5000
21
+ }).catch((err) => ({
22
+ ok: false,
23
+ recovered: false,
24
+ blockers: [err instanceof Error ? err.message : String(err)]
25
+ }))
26
+ : null;
27
+ const finalCapability = repair
28
+ ? repair.after || capability
29
+ : capability;
30
+ const ok = finalCapability.core_ready === true || repair?.recovered === true;
31
+ const blockers = ok ? [] : [
32
+ ...new Set([
33
+ ...((finalCapability?.core_blockers || []).map(String)),
34
+ ...((finalCapability?.blockers || []).map(String)),
35
+ ...((repair?.blockers || []).map(String)),
36
+ 'codex_imagegen_unavailable'
37
+ ])
38
+ ];
39
+ return {
40
+ ok,
41
+ capability: finalCapability,
42
+ repair,
43
+ blocker: ok ? null : {
44
+ schema: 'sks.codex-imagegen-required-blocker.v1',
45
+ blocker: 'codex_imagegen_unavailable',
46
+ status: 'blocked',
47
+ blockers,
48
+ next_actions: repair?.manual_actions || [
49
+ 'Install/update Codex CLI: npm i -g @openai/codex@latest',
50
+ 'Open Codex App settings and enable image_generation / $imagegen.',
51
+ 'Verify with: codex features list --json'
52
+ ]
53
+ },
54
+ blockers
55
+ };
56
+ }
57
+ //# sourceMappingURL=require-imagegen.js.map