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 { appendJsonl, exists, nowIso, readJson, readText, writeJsonAtomic } from '../fsx.js';
3
3
  import { containsUserQuestion, noQuestionContinuationReason } from '../no-question-guard.js';
4
- import { missionDir } from '../mission.js';
4
+ import { missionDir, setCurrent } from '../mission.js';
5
5
  import { evaluateResearchGate } from '../research.js';
6
6
  import { evaluateQaGate } from '../qa-loop.js';
7
7
  import { PPT_REQUIRED_GATE_FIELDS } from '../ppt.js';
@@ -18,6 +18,7 @@ import { SSOT_GUARD_ARTIFACT, validateSsotGuardArtifact } from '../safety/ssot-g
18
18
  import { validateTeamRuntimeArtifacts } from '../team-dag.js';
19
19
  import { checkStopGate } from '../stop-gate/stop-gate-check.js';
20
20
  import { clarificationStopReason, context7Evidence, hasContext7DocsEvidence, hasSubagentEvidence, subagentEvidence, } from './runtime-core.js';
21
+ import { projectTriwikiToAgentsMd } from '../triwiki/agents-md-projector.js';
21
22
  const REFLECTION_ARTIFACT = 'reflection.md';
22
23
  const REFLECTION_GATE = 'reflection-gate.json';
23
24
  const REFLECTION_MEMORY_PATH = '.sneakoscope/memory/q2_facts/post-route-reflection.md';
@@ -32,14 +33,14 @@ function reflectionRequiredForState(state = {}) {
32
33
  return true;
33
34
  return reflectionRequiredForRoute(state.route || state.mode || state.route_command);
34
35
  }
35
- async function reflectionGateStatus(root, state = {}) {
36
+ async function reflectionGateStatus(root, state = {}, jsonCache) {
36
37
  if (!reflectionRequiredForState(state))
37
38
  return { ok: true, missing: [] };
38
39
  const id = state?.mission_id;
39
40
  if (!id)
40
41
  return { ok: false, missing: ['mission_id'] };
41
42
  const dir = missionDir(root, id);
42
- const gate = await readJson(path.join(dir, REFLECTION_GATE), null);
43
+ const gate = await readJsonCached(jsonCache, path.join(dir, REFLECTION_GATE), null);
43
44
  if (!gate)
44
45
  return { ok: false, missing: [REFLECTION_GATE] };
45
46
  const hasArtifact = gate.reflection_artifact === true && await exists(path.join(dir, REFLECTION_ARTIFACT));
@@ -62,7 +63,16 @@ async function reflectionGateStatus(root, state = {}) {
62
63
  if (gate.wiki_validated !== true)
63
64
  missing.push('wiki_validated');
64
65
  missing.push(...await staleReflectionReasons(root, state, gate));
65
- return { ok: missing.length === 0, missing };
66
+ const ok = missing.length === 0;
67
+ if (ok && state.reflection_invalidation_required === true) {
68
+ await setCurrent(root, {
69
+ reflection_invalidation_required: false,
70
+ reflection_invalidated_at: null,
71
+ reflection_invalidation_reason: null,
72
+ reflection_revalidated_at: nowIso()
73
+ }, { sessionKey: state._session_key });
74
+ }
75
+ return { ok, missing };
66
76
  }
67
77
  async function staleReflectionReasons(root, state = {}, gate = {}) {
68
78
  const created = Date.parse(gate.created_at || gate.updated_at || '');
@@ -73,6 +83,9 @@ async function staleReflectionReasons(root, state = {}, gate = {}) {
73
83
  return [];
74
84
  if (state.reflection_invalidation_required !== true)
75
85
  return [];
86
+ const invalidatedAt = Date.parse(String(state.reflection_invalidated_at || ''));
87
+ if (Number.isFinite(invalidatedAt) && created >= invalidatedAt)
88
+ return [];
76
89
  return ['reflection_invalidation_required'];
77
90
  }
78
91
  function reflectionStopReason(state = {}, status = {}) {
@@ -160,6 +173,7 @@ export async function projectGateStatus(root, state = {}) {
160
173
  }
161
174
  export async function evaluateStop(root, state, payload, opts = {}) {
162
175
  const last = extractLastMessage(payload);
176
+ const jsonCache = new Map();
163
177
  if (clarificationGatePending(state)) {
164
178
  if (await hasVisibleClarificationQuestionBlock(root, state, last))
165
179
  return { continue: true };
@@ -170,28 +184,56 @@ export async function evaluateStop(root, state, payload, opts = {}) {
170
184
  missing: ['explicit_user_answers', 'pipeline_answer']
171
185
  };
172
186
  }
173
- if (state?.context7_required && !(await hasContext7DocsEvidence(root, state))) {
187
+ const route = routeFromState(state);
188
+ const stopGate = String(state?.stop_gate || '');
189
+ const completionProofRequired = state.proof_required === true || routeRequiresCompletionProof(route);
190
+ const reflectionRequired = reflectionRequiredForState(state);
191
+ if (!opts.noQuestion && (stopGate === 'none' || stopGate === 'honest_mode') && !state?.context7_required && !state?.subagents_required && !completionProofRequired && !reflectionRequired) {
192
+ return null;
193
+ }
194
+ const agentIntakeRequired = state?.mission_id && routeRequiresAgentIntake(route, { task: state.prompt, force: state.forceAgents === true, noAgents: state.agents_required === false });
195
+ const context7Promise = state?.context7_required ? hasContext7DocsEvidence(root, state) : Promise.resolve(true);
196
+ const subagentPromise = state?.subagents_required ? hasSubagentEvidence(root, state) : Promise.resolve(true);
197
+ const completionProofPromise = agentIntakeRequired
198
+ ? exists(path.join(missionDir(root, state.mission_id), 'completion-proof.json'))
199
+ : Promise.resolve(true);
200
+ const agentGatePromise = agentIntakeRequired ? readAgentGateStatus(root, state.mission_id) : Promise.resolve({ ok: true, missing: [] });
201
+ const mistakeRecallPromise = mistakeRecallGateStatus(root, state);
202
+ const [context7Ok, subagentOk, completionProofExists, agentGate, mistakeRecall] = await Promise.all([
203
+ context7Promise,
204
+ subagentPromise,
205
+ completionProofPromise,
206
+ agentGatePromise,
207
+ mistakeRecallPromise
208
+ ]);
209
+ if (state?.context7_required && !context7Ok) {
174
210
  return complianceBlock(root, state, `SKS ${state.route_command || state.mode || 'route'} requires Context7 evidence before completion. Use Context7 resolve-library-id, then query-docs (or legacy get-library-docs), so SKS can record context7-evidence.jsonl.`, { gate: 'context7-evidence' });
175
211
  }
176
- if (state?.subagents_required && !(await hasSubagentEvidence(root, state))) {
212
+ if (state?.subagents_required && !subagentOk) {
177
213
  return complianceBlock(root, state, `SKS ${state.route_command || state.mode || 'route'} requires native multi-session evidence before completion. Run worker/reviewer native sessions for disjoint code-changing work, or record explicit evidence that native sessions were unavailable or unsafe to split.`, { gate: 'native-session-evidence' });
178
214
  }
179
- if (state?.mission_id && !(await exists(path.join(missionDir(root, state.mission_id), 'completion-proof.json'))) && routeRequiresAgentIntake(routeFromState(state), { task: state.prompt, force: state.forceAgents === true, noAgents: state.agents_required === false })) {
180
- const agentGate = await readAgentGateStatus(root, state.mission_id);
215
+ if (agentIntakeRequired && !completionProofExists) {
181
216
  if (!agentGate.ok) {
182
217
  return complianceBlock(root, state, `SKS ${state.route_command || state.mode || 'route'} route cannot continue to implementation/finalization: native agent intake gate is missing or blocked. Run: sks agent run latest --mock --json`, { gate: AGENT_INTAKE_STAGE_ID, missing: agentGate.missing || ['agents/agent-proof-evidence.json'] });
183
218
  }
184
219
  }
185
- const mistakeRecall = await mistakeRecallGateStatus(root, state);
186
220
  if (!mistakeRecall.ok) {
187
221
  return complianceBlock(root, state, `SKS ${state.route_command || state.mode || 'route'} found relevant TriWiki mistake memory that is not bound to the decision contract. Re-run pipeline answer or seal the contract so ${MISTAKE_RECALL_ARTIFACT} is consumed before finishing.`, { gate: MISTAKE_RECALL_ARTIFACT, missing: mistakeRecall.missing });
188
222
  }
189
223
  if (opts.noQuestion) {
190
224
  if (containsUserQuestion(last))
191
225
  return complianceBlock(root, state, noQuestionContinuationReason(), { gate: 'no-question' });
192
- const gate = await passedActiveGate(root, state);
226
+ const gate = await passedActiveGate(root, state, jsonCache);
227
+ if (gate.hard_blocked) {
228
+ return {
229
+ continue: true,
230
+ action: 'hard_blocked',
231
+ gate: gate.file || HARD_BLOCKER_ARTIFACT,
232
+ systemMessage: `SKS ${state.route_command || state.mode || 'route'} route hard-blocked: ${gate.reason || 'hard blocker recorded'}`
233
+ };
234
+ }
193
235
  if (gate.ok) {
194
- const reflection = await reflectionGateStatus(root, state);
236
+ const reflection = await reflectionGateStatus(root, state, jsonCache);
195
237
  if (!reflection.ok)
196
238
  await appendHonestModeNote(root, state, `reflection stale: ${(reflection.missing || []).join(', ')}`);
197
239
  return { continue: true };
@@ -210,13 +252,14 @@ export async function evaluateStop(root, state, payload, opts = {}) {
210
252
  route: state.route || state.mode,
211
253
  missionId: state.mission_id,
212
254
  explicitGatePath: typeof state.stop_gate_abs_path === 'string' && state.stop_gate_abs_path ? state.stop_gate_abs_path : undefined,
255
+ allowLatestFallback: opts.allowLatestFallback !== true ? false : true,
213
256
  });
214
257
  if (stopCheck.action === 'allow_stop') {
215
258
  if (narutoFamily)
216
259
  return { continue: true, systemMessage: `SKS: canonical stop-gate passed at ${stopCheck.gate_path}` };
217
260
  }
218
261
  else if (stopCheck.action === 'hard_blocked') {
219
- return { decision: 'block', reason: stopCheck.feedback, action: 'hard_blocked', gate: stopCheck.gate_path };
262
+ return { continue: true, systemMessage: stopCheck.feedback, action: 'hard_blocked', gate: stopCheck.gate_path };
220
263
  }
221
264
  else {
222
265
  const missing = stopCheck.diagnostics.missing_fields?.length ? ` Missing gate fields: ${stopCheck.diagnostics.missing_fields.join(', ')}.` : '';
@@ -225,7 +268,15 @@ export async function evaluateStop(root, state, payload, opts = {}) {
225
268
  }
226
269
  }
227
270
  else {
228
- const gate = await passedActiveGate(root, state);
271
+ const gate = await passedActiveGate(root, state, jsonCache);
272
+ if (gate.hard_blocked) {
273
+ return {
274
+ continue: true,
275
+ action: 'hard_blocked',
276
+ gate: gate.file || HARD_BLOCKER_ARTIFACT,
277
+ systemMessage: `SKS ${state.route_command || state.mode || 'route'} route hard-blocked: ${gate.reason || 'hard blocker recorded'}`
278
+ };
279
+ }
229
280
  if (!gate.ok) {
230
281
  const missing = gate.missing?.length ? ` Missing gate fields: ${gate.missing.join(', ')}.` : '';
231
282
  return complianceBlock(root, state, `SKS ${state.route_command || state.mode} route cannot stop yet. Pass ${gate.file || state.stop_gate} or record a hard blocker with evidence before finishing.${missing}`, { gate: gate.file || state.stop_gate, missing: gate.missing });
@@ -236,11 +287,37 @@ export async function evaluateStop(root, state, payload, opts = {}) {
236
287
  if (!proofGate.ok) {
237
288
  return complianceBlock(root, state, `SKS ${state.route_command || state.mode || 'route'} route cannot finalize without a valid Completion Proof. Missing or invalid proof issues: ${proofGate.issues.join(', ')}.`, { gate: 'completion-proof', missing: proofGate.issues });
238
289
  }
239
- const reflection = await reflectionGateStatus(root, state);
290
+ const reflection = await reflectionGateStatus(root, state, jsonCache);
240
291
  if (!reflection.ok)
241
292
  return complianceBlock(root, state, reflectionStopReason(state, reflection), { gate: 'reflection', missing: reflection.missing });
293
+ fireAndForgetProjectMemory(root, state);
242
294
  return null;
243
295
  }
296
+ function fireAndForgetProjectMemory(root, state = {}) {
297
+ if (!state?.mission_id)
298
+ return;
299
+ void projectTriwikiToAgentsMd(String(root)).then((report) => {
300
+ const id = state.mission_id;
301
+ if (!id)
302
+ return null;
303
+ return appendJsonl(path.join(missionDir(root, id), 'events.jsonl'), {
304
+ ts: nowIso(),
305
+ type: 'triwiki.agents_md_projected',
306
+ ok: report.ok,
307
+ reason: report.reason,
308
+ written: report.written
309
+ });
310
+ }).catch((err) => {
311
+ const id = state.mission_id;
312
+ if (!id)
313
+ return null;
314
+ return appendJsonl(path.join(missionDir(root, id), 'events.jsonl'), {
315
+ ts: nowIso(),
316
+ type: 'triwiki.agents_md_project_failed',
317
+ error: err?.message || String(err)
318
+ }).catch(() => undefined);
319
+ });
320
+ }
244
321
  async function routeProofGateStatus(root, state = {}) {
245
322
  const route = routeFromState(state);
246
323
  const required = state.proof_required === true || routeRequiresCompletionProof(route);
@@ -266,6 +343,7 @@ async function complianceBlock(root, state = {}, reason = '', detail = {}) {
266
343
  if (!state?.mission_id)
267
344
  return { decision: 'block', reason };
268
345
  const dir = missionDir(root, state.mission_id);
346
+ await markReflectionInvalidatedForGateFailure(root, state, detail);
269
347
  const guardPath = path.join(dir, COMPLIANCE_LOOP_GUARD_ARTIFACT);
270
348
  const normalized = normalizeComplianceReason(reason);
271
349
  const previous = await readJson(guardPath, {});
@@ -305,7 +383,20 @@ async function complianceBlock(root, state = {}, reason = '', detail = {}) {
305
383
  ]
306
384
  });
307
385
  await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.compliance_loop_guard.tripped', gate: record.gate, repeat_count: count, limit });
308
- return { decision: 'escalate', reason, gate: detail.gate || state.stop_gate || null, repeat_count: count, message: '동일 사유가 반복됩니다. 사용자 개입이 필요합니다.' };
386
+ return { decision: 'escalate', reason, gate: detail.gate || state.stop_gate || null, repeat_count: count, message: '동일 사유가 반복됩니다. 사용자 개입이 필요합니다.', systemMessage: '동일 사유가 반복됩니다. 사용자 개입이 필요합니다.' };
387
+ }
388
+ async function markReflectionInvalidatedForGateFailure(root, state = {}, detail = {}) {
389
+ const gate = String(detail.gate || state.stop_gate || '');
390
+ if (!reflectionRequiredForState(state))
391
+ return;
392
+ if (!gate || /^(reflection|context7-evidence|native-session-evidence|no-question|clarification)$/i.test(gate))
393
+ return;
394
+ await setCurrent(root, {
395
+ mission_id: state.mission_id,
396
+ reflection_invalidation_required: true,
397
+ reflection_invalidated_at: nowIso(),
398
+ reflection_invalidation_reason: `gate_failed:${gate}`
399
+ }, { sessionKey: state._session_key });
309
400
  }
310
401
  function complianceLoopLimit(gate = '') {
311
402
  const gateKey = String(gate || '').toUpperCase().replace(/[^A-Z0-9]+/g, '_').replace(/^_+|_+$/g, '');
@@ -322,18 +413,26 @@ function normalizeComplianceReason(reason = '') {
322
413
  .trim()
323
414
  .slice(0, 1200);
324
415
  }
325
- async function passedActiveGate(root, state) {
416
+ function readJsonCached(cache, file, fallback) {
417
+ if (!cache)
418
+ return readJson(file, fallback);
419
+ const key = path.resolve(file);
420
+ if (!cache.has(key))
421
+ cache.set(key, readJson(file, fallback));
422
+ return cache.get(key);
423
+ }
424
+ async function passedActiveGate(root, state, jsonCache) {
326
425
  const id = state?.mission_id;
327
426
  if (!id)
328
427
  return { ok: false, file: null };
329
- const hardBlocker = await passedHardBlocker(root, state);
428
+ const hardBlocker = await passedHardBlocker(root, state, jsonCache);
330
429
  if (hardBlocker.ok)
331
430
  return hardBlocker;
332
431
  const files = gateFilesForState(state);
333
432
  for (const file of files) {
334
433
  const p = path.join(missionDir(root, id), file);
335
- if (await exists(p)) {
336
- const gate = await readJson(p, {});
434
+ const gate = await readJsonCached(jsonCache, p, null);
435
+ if (gate) {
337
436
  const missing = [
338
437
  ...missingRequiredGateFields(file, state, gate),
339
438
  ...await missingRequiredGateArtifacts(root, file, state, gate)
@@ -347,16 +446,28 @@ async function passedActiveGate(root, state) {
347
446
  }
348
447
  return { ok: false, file: files[0] || null };
349
448
  }
350
- async function passedHardBlocker(root, state) {
449
+ async function passedHardBlocker(root, state, jsonCache) {
351
450
  if (!state?.mission_id)
352
451
  return { ok: false };
353
452
  const file = 'hard-blocker.json';
354
- const blocker = await readJson(path.join(missionDir(root, state.mission_id), file), null);
453
+ const blocker = await readJsonCached(jsonCache, path.join(missionDir(root, state.mission_id), file), null);
355
454
  if (!blocker)
356
455
  return { ok: false };
357
- if (String(blocker.status || '') === 'hard_blocked')
358
- return { ok: false, file, missing: ['hard_blocked'] };
359
- return { ok: blocker.passed === true && String(blocker.reason || '').trim() && Array.isArray(blocker.evidence) && blocker.evidence.length > 0, file };
456
+ const hasReason = String(blocker.reason || '').trim().length > 0;
457
+ const hasEvidence = Array.isArray(blocker.evidence) && blocker.evidence.length > 0;
458
+ if (String(blocker.status || '') === 'hard_blocked') {
459
+ const missing = [];
460
+ if (blocker.passed === true)
461
+ missing.push('passed_false');
462
+ if (!hasReason)
463
+ missing.push('reason');
464
+ if (!hasEvidence)
465
+ missing.push('evidence');
466
+ return missing.length
467
+ ? { ok: false, file, missing }
468
+ : { ok: true, file, hard_blocked: true, reason: String(blocker.reason || '').trim() };
469
+ }
470
+ return { ok: blocker.passed === true && hasReason && hasEvidence, file };
360
471
  }
361
472
  async function appendHonestModeNote(root, state = {}, message) {
362
473
  if (!state?.mission_id)
@@ -396,6 +507,8 @@ function missingRequiredGateFields(file, state, gate = {}) {
396
507
  'final_arbiter_accepted',
397
508
  'session_cleanup'
398
509
  ];
510
+ if (fromChatImgCoverageRequired(state, gate))
511
+ required.push('from_chat_img_request_coverage');
399
512
  return required.filter((key) => gate[key] !== true);
400
513
  }
401
514
  if (file === 'qa-gate.json' || mode === 'QALOOP') {
@@ -686,6 +799,9 @@ async function missingNarutoArtifacts(root, state = {}, gate = {}) {
686
799
  }
687
800
  if (gate.native_agent_proof === true && !(await exists(path.join(dir, 'agents', 'agent-proof-evidence.json'))))
688
801
  missing.push('agents/agent-proof-evidence.json');
802
+ if (fromChatImgCoverageRequired(state, gate) && gate.from_chat_img_request_coverage === true) {
803
+ missing.push(...await missingFromChatImgCoverageArtifacts(root, state));
804
+ }
689
805
  return missing;
690
806
  }
691
807
  function extractLastMessage(payload) {
@@ -2,7 +2,7 @@ import path from 'node:path';
2
2
  import { nowIso, readJson, writeJsonAtomic } from '../fsx.js';
3
3
  import { addImageRelation, ingestImage } from '../wiki-image/image-voxel-ledger.js';
4
4
  import { exportSlidesToImages, PPT_DECK_INVENTORY_ARTIFACT, PPT_SLIDE_EXPORT_LEDGER_ARTIFACT } from './slide-exporter.js';
5
- import { buildSlideImagegenRequestArtifact, buildSlideImagegenResponseArtifact, generateSlideCalloutReviews, PPT_SLIDE_CALLOUT_LEDGER_ARTIFACT, PPT_SLIDE_IMAGEGEN_REQUEST_ARTIFACT, PPT_SLIDE_IMAGEGEN_RESPONSE_ARTIFACT } from './slide-imagegen-review.js';
5
+ import { buildSlideImagegenRequestArtifact, buildSlideImagegenResponseArtifact, buildSlideImagegenEvidence, generateSlideCalloutReviews, PPT_SLIDE_CALLOUT_LEDGER_ARTIFACT, PPT_SLIDE_IMAGEGEN_REQUEST_ARTIFACT, PPT_SLIDE_IMAGEGEN_RESPONSE_ARTIFACT } from './slide-imagegen-review.js';
6
6
  import { extractSlideIssues, PPT_DECK_ISSUE_LEDGER_ARTIFACT, PPT_SLIDE_EXTRACTION_REPORT_ARTIFACT, PPT_SLIDE_ISSUE_LEDGER_ARTIFACT } from './slide-issue-extraction.js';
7
7
  import { writePptFixTaskPlan, PPT_FIX_TASK_PLAN_ARTIFACT } from './ppt-fix-task-planner.js';
8
8
  import { writePptPatchHandoff, PPT_PATCH_HANDOFF_ARTIFACT, PPT_PATCH_RESULT_ARTIFACT } from './ppt-patch-handoff.js';
@@ -117,6 +117,9 @@ function buildPptImagegenReviewGate(parts = {}) {
117
117
  const p0p1 = Number(parts.deckIssueLedger.p0_p1_count || parts.deckIssueLedger.p0_p1_open_count || 0);
118
118
  const patchRequested = parts.fixRequested || p0p1 > 0 || parts.patchHandoff.result?.re_export_required === true;
119
119
  const changedSlidesRechecked = !patchRequested || parts.recheckReport.status === 'complete' || parts.mock === true;
120
+ const imagegenEvidence = buildSlideImagegenEvidence(parts.calloutLedger);
121
+ if (imagegenEvidence.required && imagegenEvidence.passed !== true)
122
+ blockers.push(...imagegenEvidence.blockers);
120
123
  const gate = {
121
124
  schema: 'sks.ppt-imagegen-review-gate.v1',
122
125
  created_at: nowIso(),
@@ -129,6 +132,7 @@ function buildPptImagegenReviewGate(parts = {}) {
129
132
  patch_requested: patchRequested,
130
133
  changed_slides_rechecked: changedSlidesRechecked,
131
134
  image_voxel_relations_created: parts.imageVoxelRelationsCreated === true,
135
+ imagegen_evidence: imagegenEvidence,
132
136
  wrongness_checked: true,
133
137
  honest_mode_complete: true,
134
138
  mock_fixture: parts.mock === true,
@@ -144,6 +148,7 @@ function buildPptImagegenReviewGate(parts = {}) {
144
148
  && gate.p0_p1_zero_after_fix
145
149
  && gate.changed_slides_rechecked
146
150
  && gate.image_voxel_relations_created
151
+ && gate.imagegen_evidence.passed === true
147
152
  && gate.blockers.length === 0;
148
153
  return gate;
149
154
  }
@@ -1,6 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import fsp from 'node:fs/promises';
3
- import { nowIso } from '../fsx.js';
3
+ import { nowIso, readJson } from '../fsx.js';
4
4
  import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_IMAGEGEN_REQUIRED_POLICY } from '../routes.js';
5
5
  import { sha256File, imageDimensions } from '../wiki-image/image-hash.js';
6
6
  import { generateGptImage2CalloutReview } from '../image-ux-review/imagegen-adapter.js';
@@ -45,6 +45,9 @@ export async function generateSlideCalloutReviews({ root, dir, slideExportLedger
45
45
  ...metadata,
46
46
  status: 'generated',
47
47
  source: 'mock_fixture',
48
+ evidence_class: 'mock_fixture',
49
+ output_source: 'mock_fixture',
50
+ output_sha256: metadata.sha256,
48
51
  callout_extraction_status: 'succeeded',
49
52
  callouts: [{
50
53
  callout_id: 'callout-1',
@@ -62,8 +65,15 @@ export async function generateSlideCalloutReviews({ root, dir, slideExportLedger
62
65
  else if (generatedSlideImage && slides.length > 0) {
63
66
  const slide = slides[0];
64
67
  const generatedPath = await stageGeneratedSlideReview(root, dir, path.resolve(root, generatedSlideImage), path.basename(generatedSlideImage));
68
+ const metadata = await generatedSlideMetadata(root, generatedPath, slide, {
69
+ mock: false,
70
+ realGenerated: true,
71
+ providerSurface: 'codex_app_imagegen',
72
+ evidenceClass: 'codex_app_imagegen',
73
+ outputSource: 'manual_attach'
74
+ });
65
75
  generatedReviewImages.push({
66
- ...await generatedSlideMetadata(root, generatedPath, slide, { mock: false, realGenerated: true }),
76
+ ...metadata,
67
77
  status: 'attached_generated_review',
68
78
  source: 'user_attached_generated_slide_review',
69
79
  callout_extraction_status: 'pending',
@@ -85,15 +95,23 @@ export async function generateSlideCalloutReviews({ root, dir, slideExportLedger
85
95
  blockers.push(generated.blocker || 'ppt_imagegen_callouts_missing');
86
96
  continue;
87
97
  }
88
- const fakeGenerated = generated.provider === 'fake_imagegen_adapter';
98
+ const response = generated.response_artifact ? await readJson(generated.response_artifact, null).catch(() => null) : null;
99
+ const evidenceClass = String(response?.evidence_class || '');
100
+ const fakeGenerated = evidenceClass === 'mock_fixture' || generated.provider === 'fake_imagegen_adapter';
101
+ const codexGenerated = evidenceClass === 'codex_app_imagegen';
102
+ if (!codexGenerated)
103
+ blockers.push(evidenceClass === 'non_codex_api_fallback' ? 'ppt_imagegen_non_codex_api_fallback_not_full_evidence' : fakeGenerated ? 'ppt_imagegen_mock_fixture_not_full_evidence' : 'ppt_imagegen_evidence_class_missing');
89
104
  generatedReviewImages.push({
90
105
  ...await generatedSlideMetadata(root, generated.generated_image_path, slide, {
91
106
  mock: fakeGenerated,
92
- realGenerated: !fakeGenerated,
93
- providerSurface: generated.provider || 'gpt-image-2'
107
+ realGenerated: codexGenerated,
108
+ providerSurface: generated.provider || 'gpt-image-2',
109
+ evidenceClass,
110
+ outputSource: response?.output_source || null,
111
+ outputSha256: response?.output_sha256 || response?.output_image_sha256 || null
94
112
  }),
95
113
  status: 'generated',
96
- source: fakeGenerated ? 'mock_fixture' : 'real_gpt_image_2_callout',
114
+ source: fakeGenerated ? 'mock_fixture' : codexGenerated ? 'real_gpt_image_2_callout' : 'non_codex_api_fallback',
97
115
  callout_extraction_status: fakeGenerated ? 'succeeded' : 'pending',
98
116
  callouts: fakeGenerated ? [{
99
117
  callout_id: 'fake-slide-callout-1',
@@ -159,9 +177,51 @@ export function buildSlideImagegenResponseArtifact(calloutLedger = {}) {
159
177
  schema: 'sks.ppt-slide-imagegen-response.v1',
160
178
  created_at: nowIso(),
161
179
  generated_review_images: calloutLedger.generated_review_images || [],
180
+ imagegen_evidence: buildSlideImagegenEvidence(calloutLedger),
162
181
  blockers: calloutLedger.blockers || []
163
182
  };
164
183
  }
184
+ export function buildSlideImagegenEvidence(calloutLedger = {}) {
185
+ const images = Array.isArray(calloutLedger.generated_review_images) ? calloutLedger.generated_review_images : [];
186
+ const requiredCount = Number(calloutLedger.required_count || images.length || 0);
187
+ const blockers = [];
188
+ for (const image of images) {
189
+ const evidenceClass = String(image.evidence_class || '');
190
+ const outputSource = String(image.output_source || '');
191
+ const outputSha = String(image.output_sha256 || '');
192
+ if (evidenceClass !== 'codex_app_imagegen')
193
+ blockers.push(evidenceClass ? `ppt_slide_imagegen_evidence_class_not_codex_app:${evidenceClass}` : 'ppt_slide_imagegen_evidence_class_missing');
194
+ if (!['manual_attach', 'auto_discovered_generated_images'].includes(outputSource))
195
+ blockers.push(`ppt_slide_imagegen_output_source_invalid:${outputSource || 'missing'}`);
196
+ if (!outputSha)
197
+ blockers.push('ppt_slide_imagegen_output_sha256_missing');
198
+ else if (image.sha256 && image.sha256 !== outputSha)
199
+ blockers.push('ppt_slide_imagegen_output_sha256_mismatch');
200
+ if (image.real_generated !== true)
201
+ blockers.push('ppt_slide_imagegen_not_real_codex_app_output');
202
+ }
203
+ if (requiredCount > 0 && images.length < requiredCount)
204
+ blockers.push('ppt_slide_imagegen_required_outputs_missing');
205
+ return {
206
+ schema: 'sks.ppt-slide-imagegen-evidence.v1',
207
+ required: requiredCount > 0,
208
+ required_count: requiredCount,
209
+ generated_count: images.length,
210
+ codex_app_generated_count: images.filter((image) => image.evidence_class === 'codex_app_imagegen' && image.real_generated === true).length,
211
+ images: images.map((image) => ({
212
+ image_path: image.image_path || image.path || null,
213
+ output_source: image.output_source || null,
214
+ output_sha256: image.output_sha256 || null,
215
+ sha256: image.sha256 || null,
216
+ evidence_class: image.evidence_class || null,
217
+ real_generated: image.real_generated === true,
218
+ mock: image.mock === true,
219
+ response_artifact: image.imagegen_response_artifact || null
220
+ })),
221
+ blockers: [...new Set(blockers)],
222
+ passed: requiredCount > 0 && images.length >= requiredCount && blockers.length === 0
223
+ };
224
+ }
165
225
  async function stageGeneratedSlideReview(root, dir, source, preferredName) {
166
226
  const dest = path.join(dir, 'generated-slide-reviews', preferredName);
167
227
  await fsp.mkdir(path.dirname(dest), { recursive: true });
@@ -170,21 +230,26 @@ async function stageGeneratedSlideReview(root, dir, source, preferredName) {
170
230
  return path.relative(root, dest).split(path.sep).join('/');
171
231
  }
172
232
  async function generatedSlideMetadata(root, relPath, slide, opts = {}) {
173
- const absolute = path.resolve(root, relPath);
233
+ const absolute = path.isAbsolute(relPath) ? relPath : path.resolve(root, relPath);
174
234
  const dims = await imageDimensions(absolute);
235
+ const normalizedPath = path.relative(root, absolute).split(path.sep).join('/');
236
+ const sha = await sha256File(absolute);
175
237
  return {
176
238
  id: opts.mock ? `ppt-generated-review-fixture-${slide.slide_index || 1}` : `ppt-generated-review-${slide.slide_index || 1}`,
177
239
  generated_review_image_id: opts.mock ? `ppt-generated-review-fixture-${slide.slide_index || 1}` : `ppt-generated-review-${slide.slide_index || 1}`,
178
240
  slide_id: slide.slide_id,
179
241
  slide_index: slide.slide_index,
180
242
  source_slide_image_path: slide.image_path,
181
- image_path: relPath,
182
- sha256: await sha256File(absolute),
243
+ image_path: normalizedPath,
244
+ sha256: sha,
245
+ output_sha256: opts.outputSha256 || sha,
246
+ output_source: opts.outputSource || (opts.mock ? 'mock_fixture' : 'manual_attach'),
247
+ evidence_class: opts.evidenceClass || (opts.mock ? 'mock_fixture' : opts.realGenerated ? 'codex_app_imagegen' : 'non_codex_api_fallback'),
183
248
  width: dims.width,
184
249
  height: dims.height,
185
250
  format: dims.format,
186
251
  provider_surface: opts.mock ? 'mock_fixture' : (opts.providerSurface || 'Codex App $imagegen'),
187
- real_generated: opts.realGenerated === true,
252
+ real_generated: opts.realGenerated === true && (opts.evidenceClass || (opts.mock ? 'mock_fixture' : 'codex_app_imagegen')) === 'codex_app_imagegen',
188
253
  mock: opts.mock === true,
189
254
  local_only: true
190
255
  };
package/dist/core/ppt.js CHANGED
@@ -9,6 +9,7 @@ import { buildPptStyleTokens, selectPptDesignReference } from './ppt/style-token
9
9
  export { PPT_DESIGN_REFERENCE_PROFILES, buildPptStyleTokens, selectPptDesignReference } from './ppt/style-tokens.js';
10
10
  import { buildPptHtml } from './ppt/html.js';
11
11
  export { buildPptHtml } from './ppt/html.js';
12
+ import { imageDimensions, sha256File } from './wiki-image/image-hash.js';
12
13
  export const PPT_REQUIRED_GATE_FIELDS = Object.freeze([
13
14
  'clarification_contract_sealed',
14
15
  'audience_strategy_sealed',
@@ -385,12 +386,66 @@ async function existingGeneratedImageAssets(dir, existing = {}) {
385
386
  const target = path.join(dir, asset.output_path);
386
387
  try {
387
388
  const stat = await fsp.stat(target);
388
- checked.push({ ...asset, byte_size: stat.size });
389
+ const sha = await sha256File(target);
390
+ const dims = await imageDimensions(target).catch(() => null);
391
+ const evidenceBlockers = pptImageAssetEvidenceBlockers(asset, { sha });
392
+ checked.push({
393
+ ...asset,
394
+ byte_size: stat.size,
395
+ output_sha256: asset.output_sha256 || sha,
396
+ evidence_class: asset.evidence_class || null,
397
+ output_source: asset.output_source || null,
398
+ dimensions: dims ? { width: dims.width, height: dims.height, format: dims.format } : asset.dimensions || null,
399
+ evidence_blockers: evidenceBlockers,
400
+ evidence_verified: evidenceBlockers.length === 0
401
+ });
389
402
  }
390
403
  catch { }
391
404
  }
392
405
  return checked;
393
406
  }
407
+ function pptImageAssetEvidenceBlockers(asset = {}, evidence = {}) {
408
+ const blockers = [];
409
+ const evidenceClass = String(asset.evidence_class || '');
410
+ const outputSource = String(asset.output_source || '');
411
+ const outputSha = String(asset.output_sha256 || '');
412
+ if (evidenceClass !== 'codex_app_imagegen')
413
+ blockers.push(evidenceClass ? `ppt_image_asset_evidence_class_not_codex_app:${evidenceClass}` : 'ppt_image_asset_evidence_class_missing');
414
+ if (!['manual_attach', 'auto_discovered_generated_images'].includes(outputSource))
415
+ blockers.push(`ppt_image_asset_output_source_invalid:${outputSource || 'missing'}`);
416
+ if (!outputSha)
417
+ blockers.push('ppt_image_asset_output_sha256_missing');
418
+ else if (evidence.sha && outputSha !== evidence.sha)
419
+ blockers.push('ppt_image_asset_output_sha256_mismatch');
420
+ return [...new Set(blockers)];
421
+ }
422
+ function buildPptImagegenEvidence(imageAssetLedger = {}) {
423
+ const assets = Array.isArray(imageAssetLedger.assets) ? imageAssetLedger.assets : [];
424
+ const required = imageAssetLedger.required === true;
425
+ const requiredAssets = assets.filter((asset) => asset.status === 'generated' || required);
426
+ const blockers = [
427
+ ...(imageAssetLedger.blockers || []),
428
+ ...assets.flatMap((asset) => asset.evidence_blockers || [])
429
+ ].map(String);
430
+ return {
431
+ schema: 'sks.ppt-imagegen-evidence.v1',
432
+ required,
433
+ required_count: imageAssetLedger.required_count || 0,
434
+ generated_count: imageAssetLedger.generated_count || 0,
435
+ generated_image_evidence: !required || (imageAssetLedger.generated_count || 0) >= (imageAssetLedger.required_count || 0),
436
+ assets: requiredAssets.map((asset) => ({
437
+ id: asset.id || null,
438
+ output_path: asset.output_path || null,
439
+ output_source: asset.output_source || null,
440
+ output_sha256: asset.output_sha256 || null,
441
+ evidence_class: asset.evidence_class || null,
442
+ evidence_verified: asset.evidence_verified === true,
443
+ blockers: asset.evidence_blockers || []
444
+ })),
445
+ blockers: [...new Set(blockers)],
446
+ passed: !required || ((imageAssetLedger.passed === true) && blockers.length === 0)
447
+ };
448
+ }
394
449
  export async function buildPptImageAssetLedger(dir, contract = {}, storyboard = buildPptStoryboard(contract), styleTokens = buildPptStyleTokens(contract), existing = null) {
395
450
  const required = imageAssetRequired(contract);
396
451
  const plannedAssets = planPptImageAssets(contract, storyboard, styleTokens);
@@ -400,12 +455,15 @@ export async function buildPptImageAssetLedger(dir, contract = {}, storyboard =
400
455
  const imagegenDisabled = /^(0|false|no)$/i.test(String(process.env.SKS_PPT_IMAGEGEN ?? 'auto'));
401
456
  const blockers = [];
402
457
  const generated = [...reused];
458
+ const evidenceBlockers = generated.flatMap((asset) => asset.evidence_blockers || []);
403
459
  if (pending.length > 0 && required && imagegenDisabled) {
404
460
  blockers.push('imagegen_disabled_by_SKS_PPT_IMAGEGEN');
405
461
  }
406
462
  else if (pending.length > 0 && required) {
407
463
  blockers.push('missing_codex_app_imagegen_gpt_image_2_asset_evidence');
408
464
  }
465
+ if (required)
466
+ blockers.push(...evidenceBlockers);
409
467
  const assets = [
410
468
  ...generated,
411
469
  ...pending
@@ -443,6 +501,13 @@ export async function buildPptImageAssetLedger(dir, contract = {}, storyboard =
443
501
  failed_count: 0,
444
502
  blockers,
445
503
  assets,
504
+ imagegen_evidence: buildPptImagegenEvidence({
505
+ required,
506
+ required_count: requiredCount,
507
+ generated_count: generatedCount,
508
+ blockers,
509
+ assets
510
+ }),
446
511
  passed,
447
512
  notes: [
448
513
  required
@@ -943,6 +1008,7 @@ export function defaultPptGate(contract = {}) {
943
1008
  style_tokens_created: false,
944
1009
  image_asset_ledger_created: false,
945
1010
  image_asset_policy_satisfied: false,
1011
+ imagegen_evidence: { schema: 'sks.ppt-imagegen-evidence.v1', required: false, passed: true, blockers: [] },
946
1012
  review_policy_created: false,
947
1013
  review_ledger_created: false,
948
1014
  bounded_iteration_complete: false,
@@ -1040,9 +1106,10 @@ export async function writePptBuildArtifacts(dir, contract = null) {
1040
1106
  parallel_report: async () => writeJsonAtomic(path.join(dir, PPT_PARALLEL_REPORT_ARTIFACT), parallelReport)
1041
1107
  });
1042
1108
  const baseGate = defaultPptGate(sealed);
1109
+ const imagegenEvidence = buildPptImagegenEvidence(imageAssetLedger);
1043
1110
  const gate = {
1044
1111
  ...baseGate,
1045
- passed: report.passed && imageAssetLedger.passed && reviewLedger.passed && iterationReport.passed && cleanupReport.source_html_preserved && cleanupReport.temp_cleanup_completed && parallelReport.passed,
1112
+ passed: report.passed && imageAssetLedger.passed && imagegenEvidence.passed && reviewLedger.passed && iterationReport.passed && cleanupReport.source_html_preserved && cleanupReport.temp_cleanup_completed && parallelReport.passed,
1046
1113
  audience_strategy_sealed: baseGate.audience_strategy_sealed,
1047
1114
  source_ledger_created: true,
1048
1115
  fact_ledger_created: true,
@@ -1051,6 +1118,7 @@ export async function writePptBuildArtifacts(dir, contract = null) {
1051
1118
  style_tokens_created: true,
1052
1119
  image_asset_ledger_created: true,
1053
1120
  image_asset_policy_satisfied: imageAssetLedger.passed,
1121
+ imagegen_evidence: imagegenEvidence,
1054
1122
  review_policy_created: true,
1055
1123
  review_ledger_created: true,
1056
1124
  bounded_iteration_complete: iterationReport.passed,