sneakoscope 6.0.3 → 6.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. package/README.md +29 -12
  2. package/config/codex-releases/{rust-v0.142.0.json → rust-v0.144.1.json} +6 -6
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/bin/fast-inline.js +18 -14
  6. package/dist/bin/sks-dispatch.js +2 -4
  7. package/dist/cli/args.js +2 -0
  8. package/dist/cli/command-manifest-lite.js +2 -3
  9. package/dist/cli/command-registry.js +3 -4
  10. package/dist/cli/help-fast.js +1 -1
  11. package/dist/cli/install-helpers.js +348 -763
  12. package/dist/cli/install-tool-helpers.js +287 -0
  13. package/dist/cli/router.js +91 -6
  14. package/dist/commands/codex-lb.js +188 -53
  15. package/dist/commands/codex.js +44 -5
  16. package/dist/commands/doctor.js +302 -46
  17. package/dist/commands/tmux.js +5 -1
  18. package/dist/commands/versioning.js +7 -0
  19. package/dist/commands/zellij-monitor-pane.js +2 -0
  20. package/dist/commands/zellij-viewport-pane.js +3 -1
  21. package/dist/commands/zellij.js +1 -1
  22. package/dist/config/skills-manifest.json +59 -59
  23. package/dist/core/agent-bridge/agent-manifest.js +48 -0
  24. package/dist/core/agents/agent-central-ledger.js +9 -0
  25. package/dist/core/agents/agent-cleanup-executor.js +334 -41
  26. package/dist/core/agents/agent-cleanup.js +20 -1
  27. package/dist/core/agents/agent-command-surface.js +3 -1
  28. package/dist/core/agents/agent-effort-policy.js +30 -38
  29. package/dist/core/agents/agent-janitor.js +9 -10
  30. package/dist/core/agents/agent-namespace-safety.js +56 -0
  31. package/dist/core/agents/agent-orchestrator.js +25 -3
  32. package/dist/core/agents/agent-output-validator.js +1 -1
  33. package/dist/core/agents/agent-plan.js +100 -21
  34. package/dist/core/agents/agent-role-config.js +43 -49
  35. package/dist/core/agents/agent-runner-codex-exec.js +18 -3
  36. package/dist/core/agents/agent-runner-process.js +1 -0
  37. package/dist/core/agents/agent-schema.js +3 -2
  38. package/dist/core/agents/fast-mode-policy.js +3 -5
  39. package/dist/core/agents/native-cli-session-swarm.js +1 -1
  40. package/dist/core/agents/native-worker-backend-router.js +2 -1
  41. package/dist/core/agents/work-partition/repo-inventory.js +68 -7
  42. package/dist/core/agents/zellij-right-lane-cockpit.js +2 -2
  43. package/dist/core/code-structure.js +5 -4
  44. package/dist/core/codex/agent-config-file-repair.js +94 -193
  45. package/dist/core/codex/codex-cli-update.js +723 -0
  46. package/dist/core/codex/codex-config-guard.js +38 -11
  47. package/dist/core/codex/codex-project-config-policy.js +3 -6
  48. package/dist/core/codex/codex-startup-config-postcheck.js +52 -42
  49. package/dist/core/codex-adapter.js +35 -22
  50. package/dist/core/codex-app/codex-agent-role-sync.js +13 -54
  51. package/dist/core/codex-app/codex-app-fast-ui-repair.js +51 -20
  52. package/dist/core/codex-app/codex-app-launcher.js +48 -17
  53. package/dist/core/codex-app/codex-app-restart.js +23 -2
  54. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +11 -3
  55. package/dist/core/codex-app/sks-menubar.js +136 -5
  56. package/dist/core/codex-app.js +35 -14
  57. package/dist/core/codex-compat/codex-hook-warning-detector.js +10 -1
  58. package/dist/core/codex-compat/codex-release-manifest.js +6 -6
  59. package/dist/core/codex-control/codex-0139-doctor-real-probe.js +7 -1
  60. package/dist/core/codex-control/codex-0139-image-path-real-probe.js +29 -12
  61. package/dist/core/codex-control/codex-0139-probe-runner.js +103 -28
  62. package/dist/core/codex-control/codex-0139-real-probe-summary.js +7 -3
  63. package/dist/core/codex-control/codex-0139-real-probes.js +21 -6
  64. package/dist/core/codex-control/codex-0139-sandbox-real-probe.js +39 -13
  65. package/dist/core/codex-control/codex-0139-web-search-probe.js +28 -14
  66. package/dist/core/codex-control/{codex-0142-capability.js → codex-0144-capability.js} +22 -22
  67. package/dist/core/codex-control/codex-0144-collab-agent-real-probe.js +63 -0
  68. package/dist/core/codex-control/codex-lb-launch-recovery.js +278 -0
  69. package/dist/core/codex-control/codex-multi-agent-event-normalizer.js +5 -1
  70. package/dist/core/codex-control/codex-reliability-shield.js +93 -30
  71. package/dist/core/codex-control/codex-sdk-adapter.js +96 -13
  72. package/dist/core/codex-control/codex-sdk-config-policy.js +2 -1
  73. package/dist/core/codex-control/codex-sdk-sandbox-policy.js +6 -3
  74. package/dist/core/codex-control/codex-task-runner.js +62 -9
  75. package/dist/core/codex-control/python-codex-sdk-adapter.js +30 -3
  76. package/dist/core/codex-exec-output-schema.js +35 -6
  77. package/dist/core/codex-lb/codex-lb-env.js +30 -1
  78. package/dist/core/codex-lb/codex-lb-tool-catalog.js +478 -0
  79. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +291 -0
  80. package/dist/core/codex-native/codex-native-feature-broker.js +31 -38
  81. package/dist/core/codex-native/codex-native-feature-matrix.js +2 -2
  82. package/dist/core/codex-native/codex-native-repair-transaction.js +1 -1
  83. package/dist/core/codex-native/core-skill-manifest.js +8 -4
  84. package/dist/core/codex-native/native-capability-postcheck.js +16 -8
  85. package/dist/core/codex-native/native-capability-repair-matrix.js +76 -27
  86. package/dist/core/codex-plugins/codex-plugin-json.js +67 -21
  87. package/dist/core/codex-plugins/codex-plugin-repair.js +118 -0
  88. package/dist/core/codex-runtime/codex-desktop-config-policy.js +305 -0
  89. package/dist/core/commands/agent-bridge-command.js +23 -2
  90. package/dist/core/commands/agent-command.js +38 -5
  91. package/dist/core/commands/basic-cli.js +77 -30
  92. package/dist/core/commands/command-utils.js +1 -1
  93. package/dist/core/commands/gc-command.js +27 -4
  94. package/dist/core/commands/image-ux-review-command.js +55 -24
  95. package/dist/core/commands/mad-sks-command.js +182 -137
  96. package/dist/core/commands/naruto-command.js +643 -1153
  97. package/dist/core/commands/pipeline-command.js +1 -0
  98. package/dist/core/commands/research-command.js +293 -231
  99. package/dist/core/commands/run-command.js +100 -23
  100. package/dist/core/commands/team-command.js +2 -3
  101. package/dist/core/commands/team-legacy-observe-command.js +94 -359
  102. package/dist/core/commands/wiki-command.js +179 -83
  103. package/dist/core/computer-use-live-evidence.js +166 -3
  104. package/dist/core/computer-use-status.js +5 -2
  105. package/dist/core/daemon/sksd-hook-daemon-entrypoint.js +2 -2
  106. package/dist/core/daemon/sksd-hook-daemon.js +171 -28
  107. package/dist/core/daemon/sksd-hook-dispatch.js +2 -2
  108. package/dist/core/db-safety.js +2 -2
  109. package/dist/core/decision-lattice.js +6 -6
  110. package/dist/core/dfix/verification-selector.js +6 -4
  111. package/dist/core/doctor/browser-use-repair.js +54 -13
  112. package/dist/core/doctor/codex-0139-doctor.js +3 -2
  113. package/dist/core/doctor/codex-startup-config-repair.js +8 -3
  114. package/dist/core/doctor/computer-use-repair.js +28 -39
  115. package/dist/core/doctor/doctor-codex-startup-repair.js +24 -149
  116. package/dist/core/doctor/doctor-context7-repair.js +1 -1
  117. package/dist/core/doctor/doctor-dirty-planner.js +1 -1
  118. package/dist/core/doctor/doctor-native-capability-repair.js +74 -3
  119. package/dist/core/doctor/imagegen-repair.js +47 -12
  120. package/dist/core/doctor/legacy-global-hook-cleanup.js +179 -0
  121. package/dist/core/feature-fixture-executor.js +71 -7
  122. package/dist/core/feature-fixture-runner.js +53 -12
  123. package/dist/core/feature-fixtures.js +47 -14
  124. package/dist/core/feature-registry.js +53 -58
  125. package/dist/core/fsx.js +54 -6
  126. package/dist/core/harness-conflicts.js +19 -10
  127. package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +5 -4
  128. package/dist/core/hooks-runtime/hook-invocation-dedupe.js +147 -0
  129. package/dist/core/hooks-runtime/hook-io.js +14 -4
  130. package/dist/core/hooks-runtime/light-turn.js +70 -0
  131. package/dist/core/hooks-runtime/payload-signals.js +270 -0
  132. package/dist/core/hooks-runtime/team-digest.js +0 -1
  133. package/dist/core/hooks-runtime/tool-output-quarantine.js +93 -0
  134. package/dist/core/hooks-runtime.js +418 -250
  135. package/dist/core/image/image-artifact-path-contract.js +8 -6
  136. package/dist/core/image/image-artifact-registry.js +5 -1
  137. package/dist/core/image-ux-review/imagegen-adapter.js +5 -2
  138. package/dist/core/imagegen/imagegen-capability.js +10 -13
  139. package/dist/core/imagegen/require-imagegen.js +37 -11
  140. package/dist/core/init/skills.js +16 -30
  141. package/dist/core/init.js +144 -36
  142. package/dist/core/managed-assets/managed-assets-manifest.js +417 -14
  143. package/dist/core/mission.js +24 -1
  144. package/dist/core/naruto/naruto-work-graph.js +70 -4
  145. package/dist/core/ops/reporting.js +3 -0
  146. package/dist/core/pipeline-internals/runtime-core.js +578 -180
  147. package/dist/core/pipeline-internals/runtime-gates.js +191 -49
  148. package/dist/core/ppt/style-tokens.js +1 -1
  149. package/dist/core/ppt-review/index.js +1 -1
  150. package/dist/core/ppt-review/slide-exporter.js +23 -17
  151. package/dist/core/ppt-review/slide-imagegen-review.js +1 -1
  152. package/dist/core/ppt-review/slide-issue-extraction.js +4 -2
  153. package/dist/core/preflight/parallel-preflight-engine.js +50 -1
  154. package/dist/core/product-design-plugin.js +2 -2
  155. package/dist/core/proof/route-finalizer.js +1 -1
  156. package/dist/core/proof/route-proof-gate.js +7 -2
  157. package/dist/core/proof-field.js +3 -3
  158. package/dist/core/provider/model-router.js +38 -32
  159. package/dist/core/recallpulse/policy.js +12 -28
  160. package/dist/core/recallpulse.js +11 -6
  161. package/dist/core/release/gate-manifest.js +18 -12
  162. package/dist/core/release/gate-pack-manifest.js +1 -1
  163. package/dist/core/release/npm-pack-proof.js +247 -0
  164. package/dist/core/release/package-dist-snapshot.js +151 -0
  165. package/dist/core/release/package-size-budget.js +5 -0
  166. package/dist/core/release/release-authorization-snapshot.js +115 -0
  167. package/dist/core/release/release-gate-affected-selector.js +15 -3
  168. package/dist/core/release/release-gate-cache-v2.js +30 -0
  169. package/dist/core/release/release-gate-contract.js +161 -0
  170. package/dist/core/release/release-gate-dag.js +44 -3
  171. package/dist/core/release/release-gate-hermetic-env.js +28 -17
  172. package/dist/core/release/release-real-contract.js +496 -0
  173. package/dist/core/release-parallel-full-coverage.js +31 -143
  174. package/dist/core/research/claim-evidence-matrix.js +41 -6
  175. package/dist/core/research/experiment-plan.js +14 -10
  176. package/dist/core/research/falsification.js +9 -2
  177. package/dist/core/research/implementation-blueprint-densifier.js +82 -60
  178. package/dist/core/research/implementation-blueprint.js +32 -26
  179. package/dist/core/research/mock-result.js +122 -11
  180. package/dist/core/research/replication-pack.js +15 -8
  181. package/dist/core/research/research-adversarial-review.js +1068 -0
  182. package/dist/core/research/research-claim-builder.js +69 -17
  183. package/dist/core/research/research-claim-synthesizer.js +343 -0
  184. package/dist/core/research/research-cycle-runner.js +53 -3
  185. package/dist/core/research/research-falsification-runner.js +176 -0
  186. package/dist/core/research/research-final-reviewer.js +44 -125
  187. package/dist/core/research/research-realistic-report.js +14 -6
  188. package/dist/core/research/research-review-artifact-digest.js +66 -0
  189. package/dist/core/research/research-source-evidence.js +144 -0
  190. package/dist/core/research/research-source-layer-catalog.js +68 -0
  191. package/dist/core/research/research-source-ledger-merge.js +250 -12
  192. package/dist/core/research/research-source-shards.js +26 -70
  193. package/dist/core/research/research-stage-runner.js +237 -247
  194. package/dist/core/research/research-super-search.js +184 -0
  195. package/dist/core/research/research-synthesis-prompt.js +20 -1
  196. package/dist/core/research/research-synthesis-writer.js +86 -5
  197. package/dist/core/research/research-work-graph.js +25 -18
  198. package/dist/core/research/source-quality-report.js +21 -0
  199. package/dist/core/research.js +429 -280
  200. package/dist/core/retention/retention-budget.js +25 -6
  201. package/dist/core/retention.js +980 -101
  202. package/dist/core/routes/constants.js +1 -1
  203. package/dist/core/routes/dollar-manifest-lite.js +11 -11
  204. package/dist/core/routes/evidence.js +4 -4
  205. package/dist/core/routes/ppt-policy.js +1 -1
  206. package/dist/core/routes.js +92 -64
  207. package/dist/core/runtime/task-profile.js +66 -0
  208. package/dist/core/runtime/verification-budget.js +12 -0
  209. package/dist/core/secret-redaction.js +4 -0
  210. package/dist/core/security/high-risk-contracts.js +6 -6
  211. package/dist/core/stop-gate/stop-gate-check.js +49 -12
  212. package/dist/core/subagents/agent-catalog.js +215 -0
  213. package/dist/core/subagents/model-policy.js +118 -0
  214. package/dist/core/subagents/naruto-help-contract.js +40 -0
  215. package/dist/core/subagents/official-subagent-config.js +488 -0
  216. package/dist/core/subagents/official-subagent-preparation.js +251 -0
  217. package/dist/core/subagents/official-subagent-prompt.js +137 -0
  218. package/dist/core/subagents/official-subagent-runner.js +129 -0
  219. package/dist/core/subagents/subagent-evidence.js +663 -0
  220. package/dist/core/subagents/terminology.js +16 -0
  221. package/dist/core/subagents/thread-budget.js +21 -0
  222. package/dist/core/subagents/triwiki-attention.js +65 -0
  223. package/dist/core/super-search/runtime-helpers.js +173 -19
  224. package/dist/core/super-search/runtime.js +140 -15
  225. package/dist/core/super-search/source-records.js +49 -8
  226. package/dist/core/team-review-policy.js +15 -0
  227. package/dist/core/triwiki/code-pack.js +8 -2
  228. package/dist/core/triwiki/triwiki-cache-key.js +108 -29
  229. package/dist/core/triwiki/triwiki-module-card.js +1 -1
  230. package/dist/core/triwiki-attention.js +13 -6
  231. package/dist/core/triwiki-provenance.js +274 -0
  232. package/dist/core/triwiki-runtime.js +21 -7
  233. package/dist/core/triwiki-wrongness/wrongness-ledger.js +187 -61
  234. package/dist/core/triwiki-wrongness/wrongness-retrieval.js +11 -2
  235. package/dist/core/triwiki-wrongness/wrongness-trust-policy.js +2 -0
  236. package/dist/core/update-check.js +23 -15
  237. package/dist/core/version-manager.js +51 -1
  238. package/dist/core/version.js +1 -1
  239. package/dist/core/wiki-coordinate.js +128 -12
  240. package/dist/core/work-order-ledger.js +208 -10
  241. package/dist/core/zellij/zellij-command.js +12 -1
  242. package/dist/core/zellij/zellij-dashboard-pane.js +3 -3
  243. package/dist/core/zellij/zellij-fake-adapter.js +3 -1
  244. package/dist/core/zellij/zellij-launcher.js +51 -21
  245. package/dist/core/zellij/zellij-layout-builder.js +14 -5
  246. package/dist/core/zellij/zellij-official-subagent-activity.js +477 -0
  247. package/dist/core/zellij/zellij-official-subagent-telemetry.js +264 -0
  248. package/dist/core/zellij/zellij-pane-proof.js +32 -6
  249. package/dist/core/zellij/zellij-slot-pane-renderer.js +17 -5
  250. package/dist/core/zellij/zellij-slot-telemetry.js +15 -3
  251. package/dist/core/zellij/zellij-ui-mode.js +1 -1
  252. package/dist/core/zellij/zellij-viewport-binder.js +3 -0
  253. package/dist/core/zellij/zellij-worker-pane-manager.js +5 -3
  254. package/dist/scripts/agent-fast-mode-default-check.js +48 -29
  255. package/dist/scripts/agent-role-config-repair-check.js +34 -15
  256. package/dist/scripts/agent-wiki-context-proof-check.js +16 -2
  257. package/dist/scripts/all-feature-deep-completion-check.js +14 -4
  258. package/dist/scripts/architecture-guard-check.js +8 -1
  259. package/dist/scripts/build-dist.js +17 -5
  260. package/dist/scripts/canonical-test-runner.js +188 -0
  261. package/dist/scripts/check-command-module-budget.js +38 -16
  262. package/dist/scripts/check-legacy-free.js +1 -1
  263. package/dist/scripts/check-route-modularity.js +0 -1
  264. package/dist/scripts/check-ts-contracts.js +1 -1
  265. package/dist/scripts/codex-0139-interrupt-agent-check.js +5 -1
  266. package/dist/scripts/{codex-0142-app-server-v2-check.js → codex-0144-app-server-v2-check.js} +11 -10
  267. package/dist/scripts/{codex-0142-binary-identity-check.js → codex-0144-binary-identity-check.js} +4 -4
  268. package/dist/scripts/codex-0144-capability-check.js +21 -0
  269. package/dist/scripts/{codex-0139-real-probes-check.js → codex-0144-core-real-probes-check.js} +19 -5
  270. package/dist/scripts/{codex-0142-doctor-wiring-check.js → codex-0144-doctor-wiring-check.js} +6 -6
  271. package/dist/scripts/{codex-0142-manifest-check.js → codex-0144-manifest-check.js} +11 -3
  272. package/dist/scripts/{codex-0142-policy-check.js → codex-0144-policy-check.js} +2 -2
  273. package/dist/scripts/{codex-0142-thread-store-check.js → codex-0144-thread-store-check.js} +3 -3
  274. package/dist/scripts/codex-app-provider-model-ui-check.js +53 -19
  275. package/dist/scripts/codex-app-ui-preservation-check.js +35 -4
  276. package/dist/scripts/codex-control-all-pipelines-check.js +7 -3
  277. package/dist/scripts/codex-control-side-effect-scope-check.js +2 -2
  278. package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +27 -0
  279. package/dist/scripts/codex-effort-auto-discovery-check.js +1 -1
  280. package/dist/scripts/codex-lb-fast-mode-truth-check.js +1 -0
  281. package/dist/scripts/{codex-lb-gpt55-fast-profile-check.js → codex-lb-gpt56-fast-profile-check.js} +56 -5
  282. package/dist/scripts/codex-model-metadata-check.js +1 -1
  283. package/dist/scripts/codex-native-agent-role-content-check.js +15 -7
  284. package/dist/scripts/codex-native-repair-transaction-check.js +3 -1
  285. package/dist/scripts/codex-sdk-all-pipelines-check.js +7 -4
  286. package/dist/scripts/codex-sdk-research-pipeline-check.js +30 -8
  287. package/dist/scripts/codex-sdk-sandbox-policy-check.js +5 -1
  288. package/dist/scripts/codex-sdk-version-compat-check.js +2 -1
  289. package/dist/scripts/db-route-materialization-check.js +33 -0
  290. package/dist/scripts/dfix-fixture-check.js +1 -1
  291. package/dist/scripts/docs-truthfulness-check.js +4 -2
  292. package/dist/scripts/doctor-codex-startup-repair-check.js +47 -25
  293. package/dist/scripts/doctor-context7-repair-check.js +2 -1
  294. package/dist/scripts/doctor-fix-production-blackbox.js +12 -2
  295. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +34 -7
  296. package/dist/scripts/doctor-imagegen-repair-check.js +14 -4
  297. package/dist/scripts/doctor-startup-config-repair-blackbox.js +9 -3
  298. package/dist/scripts/doctor-startup-config-repair-check.js +13 -3
  299. package/dist/scripts/install-update-preserves-config-check.js +7 -2
  300. package/dist/scripts/legacy-gate-inventory-check.js +7 -5
  301. package/dist/scripts/legacy-strong-inventory-check.js +7 -5
  302. package/dist/scripts/legacy-upgrade-matrix-check.js +4 -4
  303. package/dist/scripts/lib/native-cli-session-swarm-check-lib.js +173 -13
  304. package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +165 -6
  305. package/dist/scripts/managed-role-manifest-parity-check.js +5 -4
  306. package/dist/scripts/mutation-callsite-coverage-check.js +0 -11
  307. package/dist/scripts/naruto-codex-e2e-check.js +14 -7
  308. package/dist/scripts/naruto-shadow-clone-swarm-check.js +4 -201
  309. package/dist/scripts/npm-publish-performance-check.js +20 -12
  310. package/dist/scripts/official-subagent-workflow-check.js +145 -0
  311. package/dist/scripts/package-published-contract-check.js +6 -20
  312. package/dist/scripts/packlist-performance-check.js +17 -3
  313. package/dist/scripts/parallel-verification-engine-check.js +2 -2
  314. package/dist/scripts/postinstall-safe-side-effects-check.js +8 -3
  315. package/dist/scripts/ppt-no-mock-as-real-check.js +3 -1
  316. package/dist/scripts/prepublish-release-check-or-fast.js +23 -86
  317. package/dist/scripts/product-design-plugin-routing-check.js +1 -1
  318. package/dist/scripts/release-affected-selector-check.js +74 -1
  319. package/dist/scripts/release-check-stamp.js +324 -239
  320. package/dist/scripts/release-dag-full-coverage-check.js +7 -15
  321. package/dist/scripts/release-dynamic-presets-check.js +10 -1
  322. package/dist/scripts/release-gate-dag-runner-check.js +3 -3
  323. package/dist/scripts/release-gate-dag-runner.js +35 -11
  324. package/dist/scripts/release-gate-existence-audit.js +1 -2
  325. package/dist/scripts/release-gate-script-parity-check.js +1 -1
  326. package/dist/scripts/release-parallel-full-coverage-check.js +12 -6
  327. package/dist/scripts/release-parallel-speed-budget-check.js +18 -2
  328. package/dist/scripts/release-real-check.js +390 -157
  329. package/dist/scripts/release-registry-check.js +61 -16
  330. package/dist/scripts/release-runtime-truth-matrix-check.js +22 -0
  331. package/dist/scripts/research-blueprint-densifier-check.js +2 -2
  332. package/dist/scripts/research-real-cycle-no-legacy-final-md-check.js +11 -7
  333. package/dist/scripts/route-proof-artifact-structure-check.js +1 -0
  334. package/dist/scripts/search-visibility-gate-lib.js +1 -1
  335. package/dist/scripts/seo-geo-route-identity-check.js +30 -4
  336. package/dist/scripts/sizecheck.js +4 -4
  337. package/dist/scripts/sks-1-11-gate-lib.js +53 -6
  338. package/dist/scripts/sks-3-1-4-directive-check-lib.js +8 -2
  339. package/dist/scripts/sks-3-1-5-directive-check-lib.js +3 -2
  340. package/dist/scripts/sks-3-1-6-directive-check-lib.js +5 -3
  341. package/dist/scripts/sks-menubar-install-check.js +8 -0
  342. package/dist/scripts/sks-uninstall-regression-check.js +1 -1
  343. package/dist/scripts/sksd-daemon-check.js +16 -6
  344. package/dist/scripts/trust-fixture-check.js +32 -10
  345. package/dist/scripts/write-build-manifest.js +2 -1
  346. package/dist/scripts/wrongness-fixture-check.js +1 -1
  347. package/dist/scripts/zellij-layout-valid-check.js +36 -11
  348. package/dist/scripts/zellij-pane-proof-check.js +33 -2
  349. package/dist/scripts/zellij-real-session-cleanup-check.js +122 -2
  350. package/dist/scripts/zellij-real-session-launch-check.js +76 -5
  351. package/dist/scripts/zellij-slot-pane-renderer-check.js +4 -4
  352. package/dist/scripts/zellij-spawn-on-demand-layout-check.js +3 -3
  353. package/docs/demo.tape +1 -1
  354. package/infra-harness-gates.json +1486 -0
  355. package/package.json +32 -19
  356. package/release-gates.v2.json +4060 -0
  357. package/runtime-required-scripts.json +9 -0
  358. package/schemas/codex/{app-server-0.142 → app-server-0.144}/codex_app_server_protocol.v2.schemas.json +1146 -781
  359. package/schemas/codex/codex-0139-real-probe-result.schema.json +39 -5
  360. package/schemas/codex/ppt-slide-issue-ledger.schema.json +2 -1
  361. package/dist/commands/db.js +0 -6
  362. package/dist/core/codex-control/codex-0139-multi-agent-real-probe.js +0 -107
  363. package/dist/core/commands/db-command.js +0 -146
  364. package/dist/core/research/prompt.js +0 -15
  365. package/dist/scripts/agent-native-release-gate.js +0 -274
  366. package/dist/scripts/codex-0142-capability-check.js +0 -21
  367. package/dist/scripts/codex-control-tool-call-sequence-repair-check.js +0 -14
  368. package/dist/scripts/command-performance-scorecard-check.js +0 -204
  369. package/dist/scripts/config-managed-merge-callsite-coverage-check.js +0 -212
  370. package/dist/scripts/dollar-performance-scorecard-check.js +0 -257
  371. package/dist/scripts/gate-timing-check.js +0 -16
  372. package/dist/scripts/ops-maturity-scorecard-check.js +0 -12
  373. package/dist/scripts/performance-baseline-check.js +0 -12
  374. package/dist/scripts/performance-improvement-report-check.js +0 -58
  375. package/dist/scripts/release-parallel-check.js +0 -389
  376. package/dist/scripts/release-runner-efficiency-check.js +0 -15
  377. package/dist/scripts/retention-long-run-smoke-check.js +0 -299
  378. package/docs/assets/sneakoscope-architecture-pipeline.jpg +0 -0
@@ -1,18 +1,18 @@
1
- import fsp from 'node:fs/promises';
2
1
  import path from 'node:path';
3
- import { appendJsonl, exists, nowIso, readJson, readText, writeJsonAtomic, writeTextAtomic } from '../fsx.js';
2
+ import { appendJsonl, exists, nowIso, readJson, readText, writeJsonAtomic } from '../fsx.js';
4
3
  import { containsUserQuestion, noQuestionContinuationReason } from '../no-question-guard.js';
5
- import { createMission, missionDir, setCurrent } from '../mission.js';
4
+ import { createMission, getOrCreateSessionMission, missionDir, sessionStateKey, setCurrent } from '../mission.js';
6
5
  import { buildQuestionSchemaForRoute, buildRequestIntake, REQUEST_INTAKE_ARTIFACT, writeQuestions } from '../questions.js';
7
6
  import { sealContract } from '../decision-contract.js';
8
7
  import { scanDbSafety } from '../db-safety.js';
9
8
  import { GOAL_WORKFLOW_ARTIFACT, writeGoalWorkflow } from '../goal-workflow.js';
9
+ import { createAndWriteWorkOrderLedgerForPrompt } from '../work-order-ledger.js';
10
10
  import { writeCodeStructureReport } from '../code-structure.js';
11
11
  import { writeMemorySweepReport } from '../memory-governor.js';
12
12
  import { writeMistakeMemoryReport } from '../mistake-memory.js';
13
13
  import { MISTAKE_RECALL_ARTIFACT, mistakeRecallGateStatus } from '../mistake-recall.js';
14
14
  import { recordSkillDreamEvent, SKILL_DREAM_POLICY, skillDreamPolicyText, writeSkillForgeReport } from '../skill-forge.js';
15
- import { evaluateResearchGate, writeResearchPlan } from '../research.js';
15
+ import { evaluateResearchGate, researchPaperArtifactForPlan, writeResearchPlan } from '../research.js';
16
16
  import { PPT_REQUIRED_GATE_FIELDS, writePptRouteArtifacts } from '../ppt.js';
17
17
  import { writeQaLoopArtifacts } from '../qa-loop.js';
18
18
  import { IMAGE_UX_REVIEW_GATE_ARTIFACT, IMAGE_UX_REVIEW_POLICY_ARTIFACT, IMAGE_UX_REVIEW_SCREEN_INVENTORY_ARTIFACT, IMAGE_UX_REVIEW_GENERATED_REVIEW_LEDGER_ARTIFACT, IMAGE_UX_REVIEW_ISSUE_LEDGER_ARTIFACT, IMAGE_UX_REVIEW_ITERATION_REPORT_ARTIFACT, IMAGE_UX_REVIEW_REQUIRED_GATE_FIELDS, writeImageUxReviewRouteArtifacts } from '../image-ux-review.js';
@@ -23,13 +23,17 @@ import { validateRouteCompletionProof } from '../proof/route-proof-gate.js';
23
23
  import { routeFromState, routeRequiresCompletionProof } from '../proof/route-proof-policy.js';
24
24
  import { permissionGateSummary } from '../permission-gates.js';
25
25
  import { prepareMadDbMission } from '../mad-db/mad-db-coordinator.js';
26
- import { AGENT_INTAKE_STAGE_ID, AGENT_COUNT } from '../agents/agent-schema.js';
26
+ import { AGENT_INTAKE_STAGE_ID } from '../agents/agent-schema.js';
27
27
  import { normalizeAgentPolicy, routeRequiresAgentIntake, agentPipelineStage } from '../agents/agent-plan.js';
28
28
  import { readAgentGateStatus } from '../agents/agent-gate.js';
29
29
  import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_EVIDENCE_SOURCE, CODEX_COMPUTER_USE_ONLY_POLICY, CODEX_IMAGEGEN_REQUIRED_POLICY, CODEX_WEB_VERIFICATION_POLICY, FROM_CHAT_IMG_CHECKLIST_ARTIFACT, FROM_CHAT_IMG_COVERAGE_ARTIFACT, FROM_CHAT_IMG_QA_LOOP_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_ARTIFACT, FROM_CHAT_IMG_TEMP_TRIWIKI_SESSIONS, SOLUTION_SCOUT_STAGE_ID, chatCaptureIntakeText, context7RequirementText, dollarCommand, evidenceMentionsForbiddenBrowserAutomation, getdesignReferencePolicyText, hasFromChatImgSignal, hasMadSksSignal, imageUxReviewPipelinePolicyText, leanEngineeringCompactText, looksLikeProblemSolvingRequest, pptPipelineAllowlistPolicyText, reflectionRequiredForRoute, reasoningInstruction, routeNeedsContext7, routePrompt, routeReasoning, routeRequiresSubagents, solutionScoutPolicyText, stripDollarCommand, stripMadSksSignal, stripVisibleDecisionAnswerBlocks, subagentExecutionPolicyText, stackCurrentDocsPolicyText, triwikiContextTracking, triwikiContextTrackingText, triwikiStagePolicyText } from '../routes.js';
30
30
  import { normalizeLeanDecision, validateLeanDecision } from '../lean-engineering-policy.js';
31
31
  import { MIN_TEAM_REVIEWER_LANES, MIN_TEAM_REVIEW_POLICY_TEXT } from '../team-review-policy.js';
32
- import { normalizeCodexMultiAgentEventName } from '../codex-control/codex-multi-agent-event-normalizer.js';
32
+ import { classifyTaskProfile, gateProfileForTask } from '../runtime/task-profile.js';
33
+ import { chooseVerificationBudget } from '../runtime/verification-budget.js';
34
+ import { NARUTO_PARENT_MODEL } from '../subagents/model-policy.js';
35
+ import { NARUTO_GATE_FILENAME, NARUTO_SUMMARY_FILENAME, SUBAGENT_PLAN_FILENAME, prepareOfficialSubagentMission } from '../subagents/official-subagent-preparation.js';
36
+ import { buildSubagentEvidence, readSubagentEvents, recordSubagentEvent, SUBAGENT_EVIDENCE_FILENAME, SUBAGENT_EVENT_LOG_FILENAME, SUBAGENT_PARENT_SUMMARY_FILENAME } from '../subagents/subagent-evidence.js';
33
37
  export { routePrompt };
34
38
  export const PIPELINE_PLAN_ARTIFACT = 'pipeline-plan.json';
35
39
  export const PIPELINE_PLAN_SCHEMA_VERSION = 1;
@@ -54,52 +58,79 @@ const DEFAULT_COMPLIANCE_LOOP_LIMIT = 3;
54
58
  const CLARIFICATION_BYPASS_ROUTES = new Set(['Answer', 'DFix', 'Help', 'Wiki', 'ComputerUse', 'Goal']);
55
59
  const QUESTION_GATE_ROUTES = new Set(['QALoop', 'PPT']);
56
60
  const LIGHTWEIGHT_ROUTES = new Set(['Answer', 'DFix', 'Help', 'Wiki']);
57
- const FULL_ROUTE_STAGES = Object.freeze([
58
- 'route_classification',
59
- SOLUTION_SCOUT_STAGE_ID,
60
- 'skill_dream_counter',
61
- 'ambiguity_gate',
62
- 'pipeline_plan',
63
- 'proof_field_scan',
64
- 'triwiki_use_first',
65
- 'ssot_guard',
66
- 'context7_evidence',
67
- AGENT_INTAKE_STAGE_ID,
68
- 'native_agent_intake',
69
- 'planning_debate',
70
- 'route_materialization',
71
- 'fresh_executor_team',
72
- 'broad_route_rework',
73
- 'focused_implementation',
74
- 'listed_verification',
75
- 'triwiki_validate_before_final',
76
- 'reflection',
77
- 'honest_mode'
78
- ]);
61
+ const GATE_PROFILE_STAGES = Object.freeze({
62
+ none: [],
63
+ minimal: ['route_classification', 'listed_verification'],
64
+ scoped: ['route_classification', 'ownership', 'listed_verification', 'honest_summary'],
65
+ full: ['route_classification', 'ambiguity_gate', 'safety_gate', 'ownership', 'listed_verification', 'honest_summary']
66
+ });
67
+ const STAGE_BLOCKING_GATE = Object.freeze({
68
+ ambiguity_gate: 'scope',
69
+ safety_gate: 'safety',
70
+ ssot_guard: 'safety',
71
+ context7_evidence: 'safety',
72
+ mistake_recall: 'safety',
73
+ ownership: 'ownership',
74
+ pipeline_plan: 'ownership',
75
+ focused_implementation: 'ownership',
76
+ [SOLUTION_SCOUT_STAGE_ID]: 'ownership',
77
+ triwiki_use_first: 'ownership',
78
+ subagent_plan: 'ownership',
79
+ official_subagent_execution: 'ownership',
80
+ parent_integration: 'ownership',
81
+ [AGENT_INTAKE_STAGE_ID]: 'ownership',
82
+ route_materialization: 'ownership',
83
+ work_order_coverage: 'ownership',
84
+ listed_verification: 'verification',
85
+ triwiki_validate_before_final: 'verification',
86
+ completion_proof: 'verification',
87
+ reflection: 'verification',
88
+ honest_summary: 'verification'
89
+ });
90
+ const BLOCKING_GATE_LIMITS = Object.freeze({
91
+ passthrough: 0,
92
+ answer: 0,
93
+ 'tiny-change': 1,
94
+ 'bounded-work': 2,
95
+ 'parallel-read': 2,
96
+ 'parallel-write': 3,
97
+ 'high-risk': 4
98
+ });
79
99
  function reflectionInstructionText(commandPrefix = 'sks') {
80
100
  return `Post-route reflection: full routes load \`reflection\` after work/tests and before final; DFix/Answer/Help/Wiki/SKS discovery are exempt. Write ${REFLECTION_ARTIFACT}; record only real misses/gaps, or no_issue_acknowledged. For lessons, append TriWiki claim rows to ${REFLECTION_MEMORY_PATH}. Run "${commandPrefix} wiki refresh" or pack, validate, then pass ${REFLECTION_GATE}.`;
81
101
  }
82
102
  export function buildPipelinePlan(input = {}) {
83
103
  const route = input.route || routePrompt(input.task || '$SKS');
84
104
  const task = String(input.task || '').trim();
105
+ const taskProfile = input.taskProfile || taskProfileForRoute(route, task, classifyTaskProfile(task));
106
+ const gateProfile = gateProfileForTask(taskProfile);
85
107
  const requestIntake = input.requestIntake || null;
86
108
  const executionPrompt = String(requestIntake?.transformed_prompt || task || '').trim();
87
109
  const ambiguity = normalizeAmbiguity(input.ambiguity, route);
88
110
  const proof = normalizeProofField(input.proofField);
89
- const lane = selectPipelineLane(route, task, proof);
90
- const agentPolicy = normalizeAgentPolicy(route, task, input.agents === undefined ? {} : input.agents);
91
- const stages = buildPipelineStages(route, task, ambiguity, lane, Boolean(input.required), agentPolicy);
92
- const verification = planVerification(route, proof);
111
+ const subagentsRequired = routeRequiresSubagents(route, task, taskProfile);
112
+ const lane = selectPipelineLane(route, task, proof, taskProfile);
113
+ const normalizedAgentPolicy = normalizeAgentPolicy(route, task, input.agents === undefined ? {} : input.agents);
114
+ const agentPolicy = subagentsRequired
115
+ ? { ...normalizedAgentPolicy, required: false, subagents_required: false, reason: 'official_codex_subagent_workflow_replaces_legacy_agent_intake' }
116
+ : normalizedAgentPolicy;
117
+ const verificationBudget = input.verificationBudget || chooseVerificationBudget({
118
+ taskProfile,
119
+ changedFiles: Array.isArray(input.changedFiles) ? input.changedFiles : []
120
+ });
121
+ const stages = buildPipelineStages(route, task, taskProfile, gateProfile, ambiguity, lane, Boolean(input.required), agentPolicy);
122
+ const verification = planVerification(route, proof, verificationBudget);
93
123
  const skipped = stages.filter((stage) => stage.status === 'skipped').map((stage) => stage.id);
94
124
  const kept = stages.filter((stage) => stage.status !== 'skipped' && stage.status !== 'not_applicable').map((stage) => stage.id);
95
125
  const routeEconomy = routeEconomyPlan(proof);
96
126
  const leanDecision = normalizeLeanDecision(input.leanDecision, {
97
- selected_rung: ['Answer', 'Help', 'Wiki'].includes(route?.id) ? 'skip' : 'minimal-custom',
98
- task_requires_change: !['Answer', 'Help', 'Wiki'].includes(route?.id),
127
+ selected_rung: gateProfile === 'none' ? 'skip' : 'minimal-custom',
128
+ task_requires_change: !['passthrough', 'answer'].includes(taskProfile),
99
129
  root_cause_target: route?.id ? `${route.id} route selected implementation surface` : null,
100
130
  expected_changed_paths: input.expectedChangedPaths || input.touchedFiles || [],
101
131
  verification_minimum: verification.slice(0, 3).map((item) => String(item || '').trim()).filter(Boolean)
102
132
  });
133
+ const invariants = pipelineInvariants({ taskProfile, gateProfile, stages, verificationBudget });
103
134
  return {
104
135
  schema_version: PIPELINE_PLAN_SCHEMA_VERSION,
105
136
  generated_at: nowIso(),
@@ -111,10 +142,18 @@ export function buildPipelinePlan(input = {}) {
111
142
  stop_gate: route?.stopGate || 'honest_mode',
112
143
  required_skills: route?.requiredSkills || [],
113
144
  context7_required: Boolean(input.required),
114
- subagents_required: false,
115
- native_sessions_required: routeRequiresSubagents(route, task),
145
+ subagents_required: subagentsRequired,
146
+ native_sessions_required: false,
116
147
  reflection_required: reflectionRequiredForRoute(route)
117
148
  },
149
+ task_profile: taskProfile,
150
+ gate_profile: gateProfile,
151
+ gate_budget: {
152
+ blocking_gate_limit: BLOCKING_GATE_LIMITS[taskProfile],
153
+ blocking_gate_count: countBlockingGateStages(stages),
154
+ blocking_stage_count: countBlockingStages(stages),
155
+ blocking_gate_ids: blockingGateIds(stages)
156
+ },
118
157
  task,
119
158
  request_intake: requestIntake ? {
120
159
  artifact: REQUEST_INTAKE_ARTIFACT,
@@ -139,8 +178,9 @@ export function buildPipelinePlan(input = {}) {
139
178
  },
140
179
  skipped_stages: skipped,
141
180
  kept_stages: kept,
181
+ verification_budget: verificationBudget,
142
182
  verification,
143
- invariants: ['no_unrequested_fallback_code', 'ssot_guard', 'listed_verification', 'triwiki_validate_before_final', 'honest_mode'],
183
+ invariants,
144
184
  proof_field: proof,
145
185
  lean_decision: leanDecision,
146
186
  ssot_guard: buildSsotGuard({ route: route?.id || 'SKS', mode: route?.mode || 'SKS', task }),
@@ -148,13 +188,28 @@ export function buildPipelinePlan(input = {}) {
148
188
  agent_intake: agentPolicy,
149
189
  skill_dream: input.skillDream || { attached: false, reason: 'skill dreaming uses cheap counters and only runs inventory at threshold' },
150
190
  goal_continuation: ambientGoalContinuation(),
151
- next_actions: planNextActions(route, task, ambiguity, lane, agentPolicy),
191
+ next_actions: planNextActions(route, task, taskProfile, ambiguity, lane, agentPolicy, input.missionId),
152
192
  no_unrequested_fallback_code: true
153
193
  };
154
194
  }
195
+ function taskProfileForRoute(route, task, classified) {
196
+ if (classified !== 'answer' && classified !== 'passthrough')
197
+ return classified;
198
+ const routeId = String(route?.id || '');
199
+ if (['DB', 'MadDB', 'ReleaseReview'].includes(routeId) && /\b(apply|execute|run|fix|change|migrate|deploy|release|publish)\b|적용|실행|수정|변경|마이그레이션|배포|릴리즈|출시/i.test(task))
200
+ return 'high-risk';
201
+ if (['Research', 'AutoResearch', 'QALoop', 'PPT', 'ImageUXReview', 'GX', 'DB', 'MadDB', 'ReleaseReview'].includes(routeId))
202
+ return 'bounded-work';
203
+ return classified;
204
+ }
155
205
  export async function writePipelinePlan(dir, input = {}) {
206
+ const route = input.route || routePrompt(input.task || '$SKS');
207
+ const taskProfile = input.taskProfile || taskProfileForRoute(route, String(input.task || ''), classifyTaskProfile(input.task || ''));
208
+ if ((taskProfile === 'passthrough' || taskProfile === 'answer') && input.forceLightweightPlan !== true) {
209
+ return buildPipelinePlan({ ...input, taskProfile, requestIntake: input.requestIntake || null });
210
+ }
156
211
  const requestIntake = input.requestIntake || await writeRequestIntakeArtifact(dir, input);
157
- const plan = buildPipelinePlan({ ...input, requestIntake });
212
+ const plan = buildPipelinePlan({ ...input, taskProfile, requestIntake });
158
213
  await writeJsonAtomic(path.join(dir, PIPELINE_PLAN_ARTIFACT), plan);
159
214
  return plan;
160
215
  }
@@ -186,15 +241,38 @@ function rootFromMissionDir(dir) {
186
241
  }
187
242
  export function validatePipelinePlan(plan = {}) {
188
243
  const issues = [];
244
+ const taskProfile = plan.task_profile || classifyTaskProfile(plan.task || '');
245
+ const expectedGateProfile = gateProfileForTask(taskProfile);
246
+ const gateProfile = plan.gate_profile || expectedGateProfile;
247
+ const verificationBudget = plan.verification_budget || chooseVerificationBudget({ taskProfile, changedFiles: [] });
248
+ const expectedBlockingGateLimit = BLOCKING_GATE_LIMITS[taskProfile];
249
+ const declaredBlockingGateLimit = Number(plan.gate_budget?.blocking_gate_limit);
250
+ const actualBlockingGateCount = countBlockingGateStages(plan.stages);
189
251
  if (plan.schema_version !== PIPELINE_PLAN_SCHEMA_VERSION)
190
252
  issues.push('schema_version');
191
253
  if (!plan.route?.id || !plan.route?.command)
192
254
  issues.push('route');
193
255
  if (!plan.runtime_lane?.lane)
194
256
  issues.push('runtime_lane');
195
- if (!Array.isArray(plan.stages) || !plan.stages.length)
257
+ if (gateProfile !== expectedGateProfile)
258
+ issues.push('gate_profile');
259
+ if (!Number.isInteger(declaredBlockingGateLimit) || declaredBlockingGateLimit !== expectedBlockingGateLimit)
260
+ issues.push('gate_budget.blocking_gate_limit');
261
+ if (actualBlockingGateCount > expectedBlockingGateLimit)
262
+ issues.push(`gate_budget.blocking_gate_limit_exceeded:${actualBlockingGateCount}>${expectedBlockingGateLimit}`);
263
+ if (plan.gate_budget?.blocking_gate_count !== undefined && Number(plan.gate_budget.blocking_gate_count) !== actualBlockingGateCount)
264
+ issues.push('gate_budget.blocking_gate_count');
265
+ if (plan.gate_budget?.blocking_stage_count !== undefined && Number(plan.gate_budget.blocking_stage_count) !== countBlockingStages(plan.stages))
266
+ issues.push('gate_budget.blocking_stage_count');
267
+ if (!sameStringArray(plan.gate_budget?.blocking_gate_ids, blockingGateIds(plan.stages)))
268
+ issues.push('gate_budget.blocking_gate_ids');
269
+ if (!Array.isArray(plan.stages) || (gateProfile !== 'none' && !plan.stages.length))
196
270
  issues.push('stages');
197
- if (!Array.isArray(plan.verification) || !plan.verification.length)
271
+ else {
272
+ issues.push(...validateRequiredGateProfileStages(plan, expectedGateProfile));
273
+ issues.push(...validateStageBlockingMetadata(plan.stages));
274
+ }
275
+ if (!Array.isArray(plan.verification) || (verificationBudget !== 'none' && !plan.verification.length))
198
276
  issues.push('verification');
199
277
  if (!plan.route_economy?.mode)
200
278
  issues.push('route_economy');
@@ -206,16 +284,79 @@ export function validatePipelinePlan(plan = {}) {
206
284
  issues.push(...leanDecision.issues.map((issue) => `lean_decision:${issue}`));
207
285
  if (plan.no_unrequested_fallback_code !== true || !plan.invariants?.includes('no_unrequested_fallback_code'))
208
286
  issues.push('fallback_guard');
209
- if (!plan.ssot_guard?.required || !plan.invariants?.includes('ssot_guard'))
210
- issues.push('ssot_guard');
211
- if (!plan.stages?.some((stage) => stage.id === 'ssot_guard' && !['skipped', 'not_applicable'].includes(stage.status)))
212
- issues.push('ssot_guard_stage');
213
- if (!plan.next_actions?.length)
287
+ if (plan.invariants?.includes('ssot_guard')) {
288
+ if (!plan.ssot_guard?.required)
289
+ issues.push('ssot_guard');
290
+ if (!plan.stages?.some((stage) => stage.id === 'ssot_guard' && !['skipped', 'not_applicable'].includes(stage.status)))
291
+ issues.push('ssot_guard_stage');
292
+ }
293
+ if (gateProfile !== 'none' && !plan.next_actions?.length)
214
294
  issues.push('next_actions');
215
- if (plan.agent_intake?.required && !plan.stages?.some((stage) => stage.id === AGENT_INTAKE_STAGE_ID && stage.agent_count === AGENT_COUNT && stage.read_only === false && /bounded workspace-write/i.test(String(stage.write_policy || '')) && /lease/i.test(String(stage.write_policy || ''))))
295
+ if (plan.agent_intake?.required && !plan.stages?.some((stage) => stage.id === AGENT_INTAKE_STAGE_ID
296
+ && stage.workflow === 'official_codex_subagent'
297
+ && Number(stage.requested_subagents || 0) === Number(plan.agent_intake.requested_subagents || 0)
298
+ && Number(stage.requested_subagents || 0) > 0
299
+ && Number(stage.max_threads || 0) > 0
300
+ && Number(stage.max_depth || 0) === 1
301
+ && Array.isArray(stage.outputs)
302
+ && stage.outputs.includes(SUBAGENT_EVIDENCE_FILENAME)))
216
303
  issues.push('agent_intake_stage');
217
304
  return { ok: issues.length === 0, issues };
218
305
  }
306
+ function validateRequiredGateProfileStages(plan, gateProfile) {
307
+ const issues = [];
308
+ const stages = Array.isArray(plan.stages) ? plan.stages : [];
309
+ const activeStatuses = new Set(['keep', 'required', 'passed', 'completed']);
310
+ for (const id of GATE_PROFILE_STAGES[gateProfile]) {
311
+ const matches = stages.filter((stage) => String(stage?.id || '') === id);
312
+ if (matches.length !== 1) {
313
+ issues.push(`stages.required_count:${id}:${matches.length}`);
314
+ continue;
315
+ }
316
+ const status = String(matches[0]?.status || '');
317
+ const validNotApplicable = id === 'ambiguity_gate'
318
+ && plan.ambiguity_gate?.required === false
319
+ && status === 'not_applicable';
320
+ if (!activeStatuses.has(status) && !validNotApplicable) {
321
+ issues.push(`stages.required_inactive:${id}:${status || 'missing'}`);
322
+ }
323
+ }
324
+ return issues;
325
+ }
326
+ function countBlockingGateStages(stages) {
327
+ return blockingGateIds(stages).length;
328
+ }
329
+ function countBlockingStages(stages) {
330
+ if (!Array.isArray(stages))
331
+ return 0;
332
+ return stages.filter((stage) => stage?.blocking === true && !['skipped', 'not_applicable'].includes(String(stage?.status || ''))).length;
333
+ }
334
+ function blockingGateIds(stages) {
335
+ if (!Array.isArray(stages))
336
+ return [];
337
+ return [...new Set(stages
338
+ .filter((stage) => stage?.blocking === true && !['skipped', 'not_applicable'].includes(String(stage?.status || '')))
339
+ .map((stage) => String(stage?.blocking_gate || '').trim())
340
+ .filter(Boolean))].sort();
341
+ }
342
+ function validateStageBlockingMetadata(stages) {
343
+ const issues = [];
344
+ for (const stage of stages) {
345
+ const id = String(stage?.id || 'missing');
346
+ if (typeof stage?.blocking !== 'boolean')
347
+ issues.push(`stages.blocking_metadata_missing:${id}`);
348
+ if (stage?.blocking === true && !String(stage?.blocking_gate || '').trim())
349
+ issues.push(`stages.blocking_gate_missing:${id}`);
350
+ if (stage?.blocking !== true && stage?.blocking_gate != null)
351
+ issues.push(`stages.nonblocking_gate_present:${id}`);
352
+ }
353
+ return issues;
354
+ }
355
+ function sameStringArray(left, right) {
356
+ return Array.isArray(left)
357
+ && left.length === right.length
358
+ && left.every((value, index) => String(value) === right[index]);
359
+ }
219
360
  function validateRouteEconomyDecisionLattice(routeEconomy = {}, proof = {}) {
220
361
  const lattice = routeEconomy.decision_lattice;
221
362
  if (!lattice)
@@ -316,7 +457,7 @@ function routeEconomyPlan(proof = {}) {
316
457
  deletion_policy: 'do_not_delete_or_skip_pipeline_stages_until_report_only_metrics_are_calibrated'
317
458
  };
318
459
  }
319
- function selectPipelineLane(route, task, proof) {
460
+ function selectPipelineLane(route, task, proof, taskProfile = classifyTaskProfile(task)) {
320
461
  if (proof.attached && proof.lane) {
321
462
  return {
322
463
  lane: proof.lane,
@@ -328,65 +469,101 @@ function selectPipelineLane(route, task, proof) {
328
469
  keep: proof.keep || SPEED_LANE_POLICY.always_keep
329
470
  };
330
471
  }
472
+ if (taskProfile === 'passthrough' || taskProfile === 'answer')
473
+ return { lane: 'no_pipeline', source: 'task_profile', fast_lane_allowed: true, reason: 'Light conversation does not create an execution pipeline.', blockers: [], skip_when_fast: [], keep: [] };
331
474
  if (route?.id === 'ComputerUse')
332
475
  return { lane: 'computer_use_fast_lane', source: 'route_policy', fast_lane_allowed: true, reason: 'Computer Use route is intentionally direct and defers wiki/honest checks to closeout.', blockers: [], skip_when_fast: ['native_agent_intake', 'planning_debate', 'fresh_executor_team'], keep: ['focused_implementation', 'triwiki_validate_before_final', 'honest_mode'] };
476
+ if (taskProfile === 'tiny-change')
477
+ return { lane: 'minimal_change_lane', source: 'task_profile', fast_lane_allowed: true, reason: 'Tiny change uses one blocking gate and one focused check at most.', blockers: [], skip_when_fast: SPEED_LANE_POLICY.skip_when_fast, keep: ['listed_verification'] };
333
478
  if (LIGHTWEIGHT_ROUTES.has(route?.id))
334
479
  return { lane: `${String(route.id).toLowerCase()}_lightweight_lane`, source: 'route_policy', fast_lane_allowed: true, reason: 'Lightweight route bypasses full mission orchestration by design.', blockers: [], skip_when_fast: SPEED_LANE_POLICY.skip_when_fast, keep: ['focused_implementation', 'listed_verification', 'honest_mode'] };
335
- if (routeRequiresSubagents(route, task))
336
- return { lane: SPEED_LANE_POLICY.full_lane, source: 'route_policy', fast_lane_allowed: false, reason: 'No Proof Field attached and this route normally requires full Naruto evidence.', blockers: ['proof_field_not_attached'], skip_when_fast: [], keep: SPEED_LANE_POLICY.always_keep };
480
+ if (routeRequiresSubagents(route, task, taskProfile))
481
+ return { lane: 'official_subagent_lane', source: 'task_profile', fast_lane_allowed: false, reason: 'Explicit Naruto or parallel work uses the Codex subagent workflow.', blockers: [], skip_when_fast: [], keep: ['subagent_plan', 'official_subagent_execution', 'parent_integration', 'listed_verification', 'honest_summary'] };
482
+ if (taskProfile === 'high-risk')
483
+ return { lane: SPEED_LANE_POLICY.full_lane, source: 'task_profile', fast_lane_allowed: false, reason: 'High-risk work uses the full risk gate profile.', blockers: [], skip_when_fast: [], keep: SPEED_LANE_POLICY.always_keep };
337
484
  return { lane: SPEED_LANE_POLICY.balanced_lane, source: 'route_policy', fast_lane_allowed: false, reason: 'Balanced parent-owned route until Proof Field proves a narrower lane.', blockers: ['proof_field_not_attached'], skip_when_fast: [], keep: SPEED_LANE_POLICY.always_keep };
338
485
  }
339
- function buildPipelineStages(route, task, ambiguity, lane, context7Required, agentPolicy = normalizeAgentPolicy(route, task, {})) {
340
- return FULL_ROUTE_STAGES.map((id) => {
341
- const optional = optionalStage(route, task, ambiguity, context7Required, id);
342
- const skippedByFast = lane.fast_lane_allowed && SPEED_LANE_POLICY.skip_when_fast.includes(id);
343
- const skipped = skippedByFast || optional.skip;
344
- if (id === AGENT_INTAKE_STAGE_ID) {
345
- if (!agentPolicy.required)
346
- return agentPipelineStage(agentPolicy);
347
- return { ...agentPipelineStage(agentPolicy), status: skipped ? 'skipped' : 'required', reason: skippedByFast ? 'proof_field_fast_lane' : agentPolicy.reason };
348
- }
349
- return {
350
- id,
351
- status: skipped ? (optional.notApplicable ? 'not_applicable' : 'skipped') : (id === 'ambiguity_gate' && ambiguity.passed ? 'passed' : 'keep'),
352
- reason: skippedByFast ? 'proof_field_fast_lane' : optional.reason
353
- };
486
+ function buildPipelineStages(route, task, taskProfile, gateProfile, ambiguity, lane, context7Required, agentPolicy = normalizeAgentPolicy(route, task, {})) {
487
+ if (gateProfile === 'none')
488
+ return [];
489
+ const ids = [...GATE_PROFILE_STAGES[gateProfile]];
490
+ const specializedRoute = Boolean(route?.id && !LIGHTWEIGHT_ROUTES.has(route.id) && route.id !== 'SKS');
491
+ if (looksLikeProblemSolvingRequest(task) && !['Answer', 'Help', 'Wiki'].includes(route?.id))
492
+ ids.push(SOLUTION_SCOUT_STAGE_ID);
493
+ if (gateProfile === 'scoped' || gateProfile === 'full' || specializedRoute)
494
+ ids.push('pipeline_plan', 'focused_implementation');
495
+ if ((gateProfile === 'full' || specializedRoute) && !ids.includes('ssot_guard'))
496
+ ids.push('ssot_guard');
497
+ if (context7Required)
498
+ ids.push('context7_evidence');
499
+ if ((gateProfile === 'scoped' || gateProfile === 'full') && !LIGHTWEIGHT_ROUTES.has(route?.id)) {
500
+ ids.push('triwiki_use_first', 'triwiki_validate_before_final', 'mistake_recall', 'work_order_coverage');
501
+ }
502
+ if (routeRequiresSubagents(route, task, taskProfile))
503
+ ids.push('subagent_plan', 'official_subagent_execution', 'parent_integration');
504
+ if (agentPolicy.required)
505
+ ids.push(AGENT_INTAKE_STAGE_ID);
506
+ if (specializedRoute)
507
+ ids.push('route_materialization');
508
+ if (specializedRoute)
509
+ ids.push('completion_proof');
510
+ if (reflectionRequiredForRoute(route))
511
+ ids.push('reflection');
512
+ return [...new Set(ids)].map((id) => {
513
+ const configuredGate = STAGE_BLOCKING_GATE[id] || null;
514
+ const blockingGate = configuredGate === 'safety' && gateProfile !== 'full'
515
+ ? 'ownership'
516
+ : configuredGate;
517
+ const blocking = Boolean(blockingGate);
518
+ const metadata = { blocking, blocking_gate: blocking ? blockingGate : null };
519
+ if (id === AGENT_INTAKE_STAGE_ID)
520
+ return { ...agentPipelineStage(agentPolicy), status: 'required', reason: agentPolicy.reason, ...metadata };
521
+ if (id === 'ambiguity_gate' && ambiguity?.required === false)
522
+ return { id, status: 'not_applicable', reason: 'ambiguity_gate_not_required_for_entrypoint', ...metadata };
523
+ if (id === 'ambiguity_gate' && ambiguity?.passed)
524
+ return { id, status: 'passed', reason: 'ambiguity_contract_already_sealed', ...metadata };
525
+ return { id, status: 'keep', reason: lane.fast_lane_allowed ? 'task_profile_minimal_lane' : 'required_by_task_and_route_profile', ...metadata };
354
526
  });
355
527
  }
356
- function optionalStage(route, task, ambiguity, context7Required, id) {
357
- if (id === AGENT_INTAKE_STAGE_ID && !routeRequiresAgentIntake(route, { task }))
358
- return { skip: true, notApplicable: true, reason: 'five_agent_intake_not_required_for_route' };
359
- if (id === AGENT_INTAKE_STAGE_ID)
360
- return { skip: false, reason: 'serious_route_requires_five_agent_intake' };
361
- if (id === SOLUTION_SCOUT_STAGE_ID && !looksLikeProblemSolvingRequest(task))
362
- return { skip: true, notApplicable: true, reason: 'no_problem_solving_signal' };
363
- if (id === SOLUTION_SCOUT_STAGE_ID && ['Answer', 'Help', 'Wiki'].includes(route?.id))
364
- return { skip: true, notApplicable: true, reason: 'route_not_code_repair' };
365
- if (id === SOLUTION_SCOUT_STAGE_ID)
366
- return { skip: false, reason: 'problem_solving_request_requires_web_similarity_agent' };
367
- if (id === 'ambiguity_gate' && ambiguity?.required === false)
368
- return { skip: true, notApplicable: true, reason: 'ambiguity_gate_not_required_for_entrypoint' };
369
- if (id === 'ambiguity_gate' && CLARIFICATION_BYPASS_ROUTES.has(route?.id))
370
- return { skip: true, notApplicable: true, reason: 'route_bypasses_clarification' };
371
- if (id === 'context7_evidence' && !context7Required)
372
- return { skip: true, notApplicable: true, reason: 'context7_not_required_by_route' };
373
- if (id === 'reflection' && !reflectionRequiredForRoute(route))
374
- return { skip: true, notApplicable: true, reason: 'reflection_not_required_for_route' };
375
- if (['native_agent_intake', 'planning_debate', 'fresh_executor_team'].includes(id) && !routeRequiresSubagents(route, task))
376
- return { skip: true, notApplicable: true, reason: 'native_session_team_not_required_by_route' };
377
- return { skip: false, reason: 'required_by_lane' };
378
- }
379
- function planVerification(route, proof) {
528
+ function planVerification(route, proof, budget) {
529
+ if (budget === 'none')
530
+ return [];
380
531
  const out = new Set(proof.verification || []);
532
+ if (budget === 'single-check')
533
+ out.add('run one focused check for the changed surface');
534
+ if (budget === 'affected')
535
+ out.add('run affected tests or checks for changed files');
536
+ if (budget === 'confidence') {
537
+ out.add('run the focused build or typecheck for the affected package');
538
+ out.add('run affected regression tests and the risk-specific safety check');
539
+ }
540
+ if (budget === 'release') {
541
+ out.add('npm run packcheck');
542
+ out.add('sks selftest --mock --json');
543
+ }
544
+ if (route?.id === 'Naruto' || route?.id === 'Team')
545
+ out.add('validate official subagent evidence and the parent integration summary');
381
546
  if (route?.id === 'Team')
382
547
  out.add('sks validate-artifacts latest --json');
383
548
  if (reflectionRequiredForRoute(route))
384
549
  out.add('sks wiki validate .sneakoscope/wiki/context-pack.json');
385
- out.add('npm run packcheck');
386
- out.add('npm run selftest -- --mock');
387
550
  return [...out];
388
551
  }
389
- function planNextActions(route, task, ambiguity, lane, agentPolicy = normalizeAgentPolicy(route, task, {})) {
552
+ function pipelineInvariants(input) {
553
+ const out = ['no_unrequested_fallback_code'];
554
+ if (input.verificationBudget !== 'none')
555
+ out.push('listed_verification');
556
+ if (input.stages.some((stage) => stage.id === 'ssot_guard' && stage.status !== 'not_applicable'))
557
+ out.push('ssot_guard');
558
+ if (input.stages.some((stage) => stage.id === 'triwiki_validate_before_final'))
559
+ out.push('triwiki_validate_before_final');
560
+ if (input.gateProfile !== 'none')
561
+ out.push('honest_summary');
562
+ return out;
563
+ }
564
+ function planNextActions(route, task, taskProfile, ambiguity, lane, agentPolicy = normalizeAgentPolicy(route, task, {}), missionId = null) {
565
+ if (taskProfile === 'passthrough' || taskProfile === 'answer')
566
+ return [];
390
567
  if (ambiguity.required && !ambiguity.passed) {
391
568
  return [
392
569
  `read ${REQUEST_INTAKE_ARTIFACT} and preserve its source-order requirements`,
@@ -396,21 +573,29 @@ function planNextActions(route, task, ambiguity, lane, agentPolicy = normalizeAg
396
573
  ];
397
574
  }
398
575
  const actions = [`read ${REQUEST_INTAKE_ARTIFACT} and use its transformed_prompt`, 'read pipeline-plan.json before work', 'execute kept stages only', 'run listed verification'];
399
- if (agentPolicy.required)
400
- actions.splice(1, 0, 'run sks agents run latest --json before implementation');
401
- if (!lane.fast_lane_allowed && routeRequiresSubagents(route, task)) {
576
+ if (agentPolicy.required) {
577
+ const missionArg = String(missionId || '').trim() || '<mission-id>';
578
+ const routeArg = String(route?.command || route?.id || '$Agent');
579
+ actions.splice(1, 0, `run sks agent run --mission ${shellQuote(missionArg)} --route ${shellQuote(routeArg)} --agents ${Number(agentPolicy.requested_subagents || agentPolicy.agent_count || 1)} --json before implementation`);
580
+ }
581
+ if (!lane.fast_lane_allowed && routeRequiresSubagents(route, task, taskProfile)) {
402
582
  actions.splice(1, 0, route?.id === 'Naruto'
403
- ? 'materialize Naruto clone roster, work graph, worker proof, and naruto-gate.json before implementation'
404
- : 'materialize full Team artifacts before implementation');
583
+ ? 'read subagent-plan.json, create independent disjoint slices, run the official Codex subagent workflow, wait for all requested agent threads, and integrate their results'
584
+ : 'materialize the route-specific subagent plan before implementation');
405
585
  }
406
586
  if (looksLikeProblemSolvingRequest(task))
407
587
  actions.splice(1, 0, 'run Solution Scout web search for similar fixes before editing');
408
588
  actions.push('refresh/validate TriWiki when required', 'finish with completion summary and Honest Mode');
409
589
  return actions;
410
590
  }
591
+ function shellQuote(value) {
592
+ return `'${String(value ?? '').replace(/'/g, `'"'"'`)}'`;
593
+ }
411
594
  export function promptPipelineContext(prompt, route = null) {
412
595
  const cleanPrompt = stripVisibleDecisionAnswerBlocks(prompt);
413
596
  route = route || routePrompt(cleanPrompt);
597
+ if (!route)
598
+ return '';
414
599
  const required = routeNeedsContext7(route, cleanPrompt);
415
600
  const reasoning = routeReasoning(route, cleanPrompt);
416
601
  const directFix = route?.id === 'DFix';
@@ -434,7 +619,7 @@ export function promptPipelineContext(prompt, route = null) {
434
619
  'Question-shaped directive policy: before using Answer, decide whether a question is a real information request or an implicit instruction/complaint about broken behavior. Rhetorical bug reports, mandatory-policy statements, and "why is this not happening?" execution complaints must route to Naruto, not Answer.',
435
620
  'Best-practice prompt shape: extract Goal, Context, Constraints, and Done-when before implementation; keep questions compact and only ask for answers that can change scope, safety, user-facing behavior, or acceptance criteria.',
436
621
  chatCaptureIntakeText(),
437
- 'Default execution routing: general implementation/code-changing prompts promote to Naruto so the normal path is shadow-clone fan-out, hardware-safe concurrency, patch envelopes, verification DAG, and GPT final arbitration. Answer, DFix, Help, Wiki maintenance, and safety-specific routes are intentional exceptions.',
622
+ 'Default execution routing: general implementation/code-changing prompts use the profile-selected parent-owned path; explicit Naruto or parallel work uses the Codex subagent workflow with disjoint slices, official agent threads, parent integration, and scoped verification. Answer, DFix, Help, Wiki maintenance, and safety-specific routes remain intentional exceptions.',
438
623
  'Stance: infer the user intent aggressively from rough wording, local context, TriWiki, and conservative defaults; do not surface prequestion sheets before work.',
439
624
  subagentExecutionPolicyText(route, cleanPrompt),
440
625
  solutionScoutPolicyText(cleanPrompt),
@@ -443,7 +628,7 @@ export function promptPipelineContext(prompt, route = null) {
443
628
  skillDreamPolicyText(),
444
629
  route?.id === 'PPT'
445
630
  ? `${pptPipelineAllowlistPolicyText()} ${getdesignReferencePolicyText()}`
446
- : `Design routing: UI/UX uses the Codex App Product Design plugin first for get-context/user-context, research/ideate, prototype/image-to-code/url-to-code, audit/design-qa, and share when available. Treat design.md, design-system-builder, design-ui-editor, design-artifact-expert, and getdesign-reference as compatibility fallback only when the Product Design plugin is unavailable or an existing local design.md must be preserved. Image/logo/raster assets use imagegen, which must prefer Codex App built-in image generation documented at ${CODEX_APP_IMAGE_GENERATION_DOC_URL}. ${CODEX_IMAGEGEN_REQUIRED_POLICY} ${getdesignReferencePolicyText()}`,
631
+ : `Design routing: UI/UX uses the Codex App Product Design plugin first for get-context/user-context, research/ideate, index/image-to-code/url-to-code, audit/design-qa, and share when available. Treat design.md, design-system-builder, design-ui-editor, design-artifact-expert, and getdesign-reference as compatibility fallback only when the Product Design plugin is unavailable or an existing local design.md must be preserved. Image/logo/raster assets use imagegen, which must prefer Codex App built-in image generation documented at ${CODEX_APP_IMAGE_GENERATION_DOC_URL}. ${CODEX_IMAGEGEN_REQUIRED_POLICY} ${getdesignReferencePolicyText()}`,
447
632
  triwikiContextTrackingText(),
448
633
  triwikiStagePolicyText(),
449
634
  stackCurrentDocsPolicyText(),
@@ -455,7 +640,7 @@ export function promptPipelineContext(prompt, route = null) {
455
640
  if (reflectionRequiredForRoute(route))
456
641
  lines.push(reflectionInstructionText());
457
642
  if (route?.id === 'Naruto')
458
- lines.push(`Naruto route: build clone roster, massive work graph, hardware-safe governor, active pool, allocation/rebalance policy, parallel verification DAG, GPT final pack, per-clone proof, session cleanup, reflection, and Honest Mode. $Team is deprecated for new execution missions.`);
643
+ lines.push('Naruto route: prepare subagent-plan.json, delegate independent slices through official Codex worker/expert agent threads, record SubagentStart/SubagentStop events, wait for every requested thread, integrate the parent summary, run scoped verification, and pass naruto-gate.json. Process counts, PID evidence, clone rosters, custom active pools, and verification DAGs are not completion evidence.');
459
644
  if (route?.id === 'Team')
460
645
  lines.push(`Team route is a deprecated compatibility surface; use $Naruto for new execution missions. Existing Team mission observation commands remain available.`);
461
646
  if (route?.id === 'Goal')
@@ -511,50 +696,74 @@ export function answerOnlyContext(prompt, route = routePrompt(prompt)) {
511
696
  export async function prepareRoute(root, prompt, state = {}, opts = {}) {
512
697
  const cleanPrompt = stripVisibleDecisionAnswerBlocks(prompt);
513
698
  const route = routePrompt(cleanPrompt);
514
- const sessionKey = opts.sessionKey || state?._session_key || null;
699
+ const codexThreadId = String(process.env.CODEX_THREAD_ID || '').trim();
700
+ const sessionKey = opts.sessionKey || codexThreadId || state?._session_key || null;
515
701
  const madSksAuthorization = hasMadSksSignal(cleanPrompt);
516
702
  const task = stripDollarCommand(stripMadSksSignal(cleanPrompt)) || stripMadSksSignal(stripDollarCommand(cleanPrompt)) || String(cleanPrompt || '').trim();
517
703
  const explicit = Boolean(dollarCommand(cleanPrompt));
518
704
  if (!route)
519
705
  return { route: null, additionalContext: promptPipelineContext(prompt, null) };
520
706
  const dreamContext = await routeSkillDreamContext(root, route, task);
707
+ const required = routeNeedsContext7(route, cleanPrompt);
708
+ const reasoning = routeReasoning(route, cleanPrompt);
709
+ const subagentsRequired = routeRequiresSubagents(route, cleanPrompt);
710
+ const finish = async (prepared) => {
711
+ const materialized = subagentsRequired && !['Naruto', 'Team', 'Goal'].includes(route.id)
712
+ ? await materializeOfficialSubagentOverlay(root, prepared, route, task, { sessionKey, parentModel: opts.parentModel || null })
713
+ : prepared;
714
+ return withSkillDreamContext(materialized, dreamContext);
715
+ };
521
716
  if (route.id === 'DFix')
522
- return withSkillDreamContext(await prepareDfixQuickRoute(route, task), dreamContext);
717
+ return finish(await prepareDfixQuickRoute(route, task));
523
718
  if (route.id === 'Answer')
524
- return withSkillDreamContext(await prepareAnswerOnlyRoute(route, task), dreamContext);
719
+ return finish(await prepareAnswerOnlyRoute(route, task));
525
720
  if (route.id === 'ComputerUse')
526
- return withSkillDreamContext(await prepareComputerUseFastRoute(route, task), dreamContext);
721
+ return finish(await prepareComputerUseFastRoute(route, task));
527
722
  if (route.id === 'Wiki')
528
- return withSkillDreamContext(await prepareWikiQuickRoute(route, task), dreamContext);
723
+ return finish(await prepareWikiQuickRoute(route, task));
529
724
  if (route.id === 'Goal')
530
- return withSkillDreamContext(await prepareGoal(root, route, task, routeNeedsContext7(route, cleanPrompt), { sessionKey }), dreamContext);
725
+ return finish(await prepareGoal(root, route, task, required, { sessionKey }));
531
726
  if (route.id === 'ImageUXReview')
532
- return withSkillDreamContext(await prepareImageUxReview(root, route, task, routeNeedsContext7(route, cleanPrompt), { sessionKey }), dreamContext);
727
+ return finish(await prepareImageUxReview(root, route, task, required, { sessionKey }));
533
728
  if (route.id === 'MadDB')
534
- return withSkillDreamContext(await prepareMadDb(root, route, task, routeNeedsContext7(route, cleanPrompt), { sessionKey }), dreamContext);
535
- const required = routeNeedsContext7(route, cleanPrompt);
536
- const reasoning = routeReasoning(route, cleanPrompt);
537
- const nativeSessionsRequired = routeRequiresSubagents(route, cleanPrompt);
729
+ return finish(await prepareMadDb(root, route, task, required, { sessionKey }));
538
730
  if (QUESTION_GATE_ROUTES.has(route.id) || route.id === 'MadSKS')
539
- return withSkillDreamContext(await prepareClarificationGate(root, route, task, required, { madSksAuthorization, sessionKey }), dreamContext);
731
+ return finish(await prepareClarificationGate(root, route, task, required, { madSksAuthorization, sessionKey }));
732
+ if (route.id === 'Naruto' && subagentsRequired)
733
+ return finish(await prepareNaruto(root, route, task, required, { madSksAuthorization, sessionKey, parentModel: opts.parentModel || null }));
540
734
  if (route.id === 'Naruto')
541
- return withSkillDreamContext(await prepareNaruto(root, route, task, required, { madSksAuthorization, sessionKey }), dreamContext);
735
+ return finish(await prepareLightRoute(root, parentOwnedProfileRoute(route), task, required, { sessionKey }));
542
736
  if (route.id === 'Team')
543
- return withSkillDreamContext(await prepareNaruto(root, { ...route, id: 'Naruto', command: '$Naruto', mode: 'NARUTO', stopGate: 'naruto-gate.json', requiredSkills: ['naruto', 'pipeline-runner', 'prompt-pipeline', 'honest-mode'] }, task, required, { madSksAuthorization, teamAlias: true, sessionKey }), dreamContext);
737
+ return finish(await prepareNaruto(root, { ...route, id: 'Naruto', command: '$Naruto', mode: 'NARUTO', stopGate: 'naruto-gate.json', requiredSkills: ['naruto', 'pipeline-runner', 'prompt-pipeline', 'honest-mode'] }, task, required, { madSksAuthorization, teamAlias: true, sessionKey, parentModel: opts.parentModel || null }));
544
738
  if (route.id === 'Research')
545
- return withSkillDreamContext(await prepareResearch(root, route, task, required, { sessionKey }), dreamContext);
739
+ return finish(await prepareResearch(root, route, task, required, { sessionKey }));
546
740
  if (route.id === 'AutoResearch')
547
- return withSkillDreamContext(await prepareAutoResearch(root, route, task, required, { sessionKey }), dreamContext);
741
+ return finish(await prepareAutoResearch(root, route, task, required, { sessionKey }));
548
742
  if (route.id === 'DB')
549
- return withSkillDreamContext(await prepareDb(root, route, task, required, { sessionKey }), dreamContext);
743
+ return finish(await prepareDb(root, route, task, required, { sessionKey }));
550
744
  if (route.id === 'GX')
551
- return withSkillDreamContext(await prepareGx(root, route, task, required, { sessionKey }), dreamContext);
745
+ return finish(await prepareGx(root, route, task, required, { sessionKey }));
552
746
  if (explicit || required)
553
- return withSkillDreamContext(await prepareLightRoute(root, route, task, required, { sessionKey }), dreamContext);
554
- return withSkillDreamContext({
747
+ return finish(await prepareLightRoute(root, route, task, required, { sessionKey }));
748
+ return finish({
555
749
  route,
556
- additionalContext: `${promptPipelineContext(prompt, route)}\n\nReasoning: ${reasoning.effort} (${reasoning.reason}); temporary profile ${reasoning.profile}.\nRequired skills: ${route.requiredSkills.join(', ')}.\nNative sessions required: ${nativeSessionsRequired ? 'yes' : 'no'}.`
557
- }, dreamContext);
750
+ additionalContext: `${promptPipelineContext(prompt, route)}\n\nReasoning: ${reasoning.effort} (${reasoning.reason}); temporary profile ${reasoning.profile}.\nRequired skills: ${route.requiredSkills.join(', ')}.\nOfficial subagents required: ${subagentsRequired ? 'yes' : 'no'}.`
751
+ });
752
+ }
753
+ function parentOwnedProfileRoute(route) {
754
+ return {
755
+ ...route,
756
+ id: 'SKS',
757
+ command: '$SKS',
758
+ mode: 'SKS',
759
+ route: 'profiled parent-owned execution',
760
+ description: 'Parent-owned bounded execution selected by the task profile; no subagent workflow is required.',
761
+ requiredSkills: ['pipeline-runner', 'prompt-pipeline', 'honest-mode'],
762
+ lifecycle: ['task_profile', 'ownership', 'focused_implementation', 'listed_verification', 'honest_summary'],
763
+ stopGate: 'honest_mode',
764
+ coverage_required: false,
765
+ explicit_invocation: false
766
+ };
558
767
  }
559
768
  async function routeSkillDreamContext(root, route, task) {
560
769
  try {
@@ -695,14 +904,13 @@ export async function activeRouteContext(root, state) {
695
904
  ? ' Context7 evidence is still required before completion: use resolve-library-id, then query-docs (or legacy get-library-docs).'
696
905
  : '';
697
906
  const roles = state.role_counts ? ` Role counts: ${formatLegacyRoleCounts(state.role_counts)}.` : '';
698
- return `Active Team mission ${state.mission_id || 'latest'} must keep the user-visible live transcript updated. Native session budget: ${state.agent_sessions || MIN_TEAM_REVIEWER_LANES}.${roles} Run native sessions, TriWiki refresh, debate, consensus, fresh development, minimum ${MIN_TEAM_REVIEWER_LANES}-lane review/integration, then close or account for every Team native session and write ${TEAM_SESSION_CLEANUP_ARTIFACT} before reflection/final. ${MIN_TEAM_REVIEW_POLICY_TEXT} After each native-session status/result/handoff, run: sks team event ${state.mission_id || 'latest'} --agent <name> --phase <phase> --message "...". Inspect with sks team log/watch ${state.mission_id || 'latest'}.${reasoningNote}${context7}${planNote}`;
907
+ return `Legacy Team mission ${state.mission_id || 'latest'} must keep its existing live transcript and compatibility artifacts current.${roles} New Team invocations redirect to the Naruto official Codex subagent workflow; this context is only for finishing a pre-6.1.1 Team mission. Preserve its original minimum ${MIN_TEAM_REVIEWER_LANES}-lane review/integration and ${TEAM_SESSION_CLEANUP_ARTIFACT} contract before reflection/final. ${MIN_TEAM_REVIEW_POLICY_TEXT} Inspect with sks team log/watch ${state.mission_id || 'latest'}.${reasoningNote}${context7}${planNote}`;
699
908
  }
700
909
  if (state.mode === 'NARUTO') {
701
- const clones = state.clone_count ? ` Clone count: ${state.clone_count}.` : '';
702
- return `Active Naruto mission ${state.mission_id || 'latest'} must keep clone/worker evidence current.${clones} Use sks naruto status ${state.mission_id || 'latest'} --json, inspect .sneakoscope/missions/${state.mission_id || 'latest'}/naruto-gate.json and agents/agent-proof-evidence.json, then continue until the Naruto gate passes or a hard blocker is recorded.${reasoningNote}${planNote}`;
910
+ return `Active Naruto mission ${state.mission_id || 'latest'} uses the official Codex subagent workflow. Read subagent-plan.json, keep ${SUBAGENT_EVENT_LOG_FILENAME} and ${SUBAGENT_EVIDENCE_FILENAME} current from SubagentStart/SubagentStop, wait for all requested agent threads, then return the exact sks.subagent-parent-summary.v1 JSON result so SKS can persist ${SUBAGENT_PARENT_SUMMARY_FILENAME} and derive naruto-summary.json/naruto-gate.json. Do not substitute process counts, PID evidence, clone artifacts, or a custom active pool.${reasoningNote}${planNote}`;
703
911
  }
704
912
  if (state.subagents_required && !(await hasSubagentEvidence(root, state))) {
705
- return `Active SKS route ${id} requires native multi-session evidence before code-changing work can be considered complete. Run worker/reviewer native sessions for disjoint write scopes, or record explicit unavailable/unsplittable native-session evidence before editing.${reasoningNote}${planNote}`;
913
+ return `Active SKS route ${id} requires official subagent evidence before completion. Delegate independent slices to worker/expert custom agents, record matched SubagentStart/SubagentStop thread ids, wait for every requested agent thread, and provide the parent integration summary.${reasoningNote}${planNote}`;
706
914
  }
707
915
  if (state.mode === 'GOAL')
708
916
  return `Active Goal mission ${state.mission_id || 'latest'} uses Codex native /goal continuation. Inspect .sneakoscope/missions/${state.mission_id || 'latest'}/${GOAL_WORKFLOW_ARTIFACT}, then use /goal create, pause, resume, or clear in the Codex runtime as appropriate.${planNote}`;
@@ -728,7 +936,17 @@ async function prepareGoal(root, route, task, required, opts = {}) {
728
936
  const { id, dir, mission } = await createMission(root, { mode: 'goal', prompt: task, sessionKey: opts.sessionKey });
729
937
  const workflow = await writeGoalWorkflow(dir, mission, { action: 'create', prompt: task });
730
938
  await writeJsonAtomic(path.join(dir, 'route-context.json'), { route: route.id, command: route.command, mode: route.mode, task, required_skills: route.requiredSkills, context7_required: required, native_goal: workflow.native_goal, stop_gate: route.stopGate });
731
- const pipelinePlan = await writePipelinePlan(dir, { missionId: id, route, task, required, ambiguity: { required: false, status: 'not_required' } });
939
+ const pipelinePlan = await writePipelinePlan(dir, {
940
+ missionId: id,
941
+ route,
942
+ task,
943
+ required,
944
+ ambiguity: { required: false, status: 'not_required' },
945
+ // Goal is a lightweight persistence overlay, but its mission still owns the
946
+ // durable request-intake/plan contract. Question-shaped or vague Goal tasks
947
+ // must not be mistaken for answer-only work and skip artifact writes.
948
+ forceLightweightPlan: true
949
+ });
732
950
  const executionRoute = routePrompt(task);
733
951
  const shouldDelegateExecution = routeRequiresSubagents(route, task)
734
952
  && executionRoute
@@ -811,6 +1029,7 @@ async function prepareClarificationGate(root, route, task, required, opts = {})
811
1029
  const materializedLine = materialized.phase ? `\nRoute artifacts were materialized immediately; state advanced to ${materialized.phase}.` : '';
812
1030
  return {
813
1031
  route,
1032
+ mission_id: id,
814
1033
  additionalContext: `${promptPipelineContext(task, route)}
815
1034
 
816
1035
  Route contract auto-sealed for ${route.command}: contract answers were inferred from the prompt, TriWiki/current-code defaults, and conservative SKS safety policy.
@@ -945,10 +1164,10 @@ async function materializeMadSksAuthorization(dir, id, route, routeContext = {},
945
1164
  }
946
1165
  async function prepareResearch(root, route, task, required, opts = {}) {
947
1166
  const { id, dir } = await createMission(root, { mode: 'research', prompt: task, sessionKey: opts.sessionKey });
948
- await writeResearchPlan(dir, task, {});
1167
+ const researchPlan = await writeResearchPlan(dir, task, {});
949
1168
  const pipelinePlan = await writePipelinePlan(dir, { missionId: id, route, task, required, ambiguity: { required: false, status: 'direct_route' } });
950
1169
  await setCurrent(root, routeState(id, route, 'RESEARCH_PREPARED', required, { prompt: task, pipeline_plan_ready: validatePipelinePlan(pipelinePlan).ok, pipeline_plan_path: PIPELINE_PLAN_ARTIFACT }), { sessionKey: opts.sessionKey });
951
- return routeContext(route, id, task, required, 'Run sks research run latest as a real long-running source-gathering pass, never an automatic mock fallback; do not modify repository source code; create research-source-skill.md, maximize layered public source search, require every agent effort=xhigh plus one Eureka! idea, repeat agent/debate/falsification cycles until unanimous_consensus=true for every agent or the explicit safety cap pauses the run, fill source-ledger.json, agent-ledger.json, debate-ledger.json, novelty-ledger.json, falsification-ledger.json, research-report.md, research-paper.md, genius-opinion-summary.md, and pass research-gate.json.');
1170
+ return routeContext(route, id, task, required, `Run sks research run latest as a real long-running source-gathering pass, never an automatic mock fallback; do not modify repository source code. Run layered Super Search first and allow only correlated verified-content rows to support real claims. Then run exactly three independent official research_reviewer threads on GPT-5.6 Sol Max. Any objection requires a mission-local research_synthesizer revision and a fresh three-thread review cycle; do not launch a custom scheduler or debate pool. Treat agent-ledger.json and debate-ledger.json as compatibility projections, write research-report.md and ${researchPaperArtifactForPlan(researchPlan)}, and pass the adversarial convergence, Honest Mode, and research-gate.json checks.`);
952
1171
  }
953
1172
  async function prepareAutoResearch(root, route, task, required, opts = {}) {
954
1173
  const { id, dir } = await createMission(root, { mode: 'autoresearch', prompt: task, sessionKey: opts.sessionKey });
@@ -966,7 +1185,7 @@ async function prepareDb(root, route, task, required, opts = {}) {
966
1185
  await writeJsonAtomic(path.join(dir, 'db-review.json'), { passed: false, scan_ok: scan.ok, destructive_operation_zero: true, safe_mcp_policy: false, context7_evidence: false, notes: [] });
967
1186
  const pipelinePlan = await writePipelinePlan(dir, { missionId: id, route, task, required, ambiguity: { required: false, status: 'direct_route' } });
968
1187
  await setCurrent(root, routeState(id, route, 'DB_REVIEW_REQUIRED', required, { prompt: task, pipeline_plan_ready: validatePipelinePlan(pipelinePlan).ok, pipeline_plan_path: PIPELINE_PLAN_ARTIFACT }), { sessionKey: opts.sessionKey });
969
- return routeContext(route, id, task, required, 'Run sks db policy/scan/check as needed, keep DB operations read-only, record safe MCP policy, and pass db-review.json.');
1188
+ return routeContext(route, id, task, required, 'Inspect the automatically materialized db-safety-scan.json, keep database operations read-only, record safe MCP and current-docs evidence, and pass db-review.json. The legacy sks db CLI is removed; explicitly authorized SQL-plane work uses sks mad-sks.');
970
1189
  }
971
1190
  async function prepareMadDb(root, route, task, required, opts = {}) {
972
1191
  const prepared = await prepareMadDbMission({ root, task, verifyTools: false, sessionKey: opts.sessionKey, route: 'MadSKS', routeCommand: '$MAD-SKS' });
@@ -1018,10 +1237,101 @@ async function prepareLightRoute(root, route, task, required, opts = {}) {
1018
1237
  await setCurrent(root, routeState(id, route, 'ROUTE_CONTEXT_READY', required, { prompt: task, stop_gate: 'none', pipeline_plan_ready: validatePipelinePlan(pipelinePlan).ok, pipeline_plan_path: PIPELINE_PLAN_ARTIFACT }), { sessionKey: opts.sessionKey });
1019
1238
  return routeContext(route, id, task, required, 'Load the route skill context, execute the smallest matching action, and finish with Honest Mode.');
1020
1239
  }
1240
+ async function materializeOfficialSubagentOverlay(root, prepared, route, task, opts = {}) {
1241
+ const id = String(prepared?.mission_id || '').trim();
1242
+ if (!id)
1243
+ throw new Error(`official_subagent_overlay_mission_missing:${route?.id || 'unknown'}`);
1244
+ const dir = missionDir(root, id);
1245
+ const cleanTask = stripDollarCommand(task) || String(task || '').trim();
1246
+ await createAndWriteWorkOrderLedgerForPrompt(dir, {
1247
+ missionId: id,
1248
+ route: route?.command || route?.id || 'official-subagent-overlay',
1249
+ prompt: cleanTask
1250
+ });
1251
+ const requestedSubagents = requestedSubagentsFromTask(cleanTask);
1252
+ const observedParentModel = typeof opts.parentModel === 'string' && opts.parentModel.trim()
1253
+ ? opts.parentModel.trim()
1254
+ : null;
1255
+ const preparation = await prepareOfficialSubagentMission({
1256
+ root,
1257
+ dir,
1258
+ missionId: id,
1259
+ goal: cleanTask,
1260
+ route: route?.command || route?.id || 'specialized-route',
1261
+ sessionScope: opts.sessionKey || null,
1262
+ ...(requestedSubagents === undefined ? {} : { requestedSubagents }),
1263
+ requestedSubagentsExplicit: requestedSubagents !== undefined,
1264
+ mode: 'generic',
1265
+ observedParentModel,
1266
+ preparationOnly: true
1267
+ });
1268
+ const { budget, delegationPrompt, plan } = preparation;
1269
+ await setCurrent(root, {
1270
+ mission_id: id,
1271
+ subagents_required: true,
1272
+ subagents_verified: false,
1273
+ native_sessions_required: false,
1274
+ native_sessions_verified: false,
1275
+ agents_required: false,
1276
+ requested_subagents: budget.requestedSubagents,
1277
+ subagent_max_threads: budget.maxThreads,
1278
+ subagent_max_depth: budget.maxDepth,
1279
+ official_subagent_run_id: plan.workflow_run_id,
1280
+ session_scope: opts.sessionKey || null,
1281
+ subagent_plan_file: SUBAGENT_PLAN_FILENAME,
1282
+ subagent_evidence_file: SUBAGENT_EVIDENCE_FILENAME
1283
+ }, { sessionKey: opts.sessionKey });
1284
+ return {
1285
+ ...prepared,
1286
+ mission_id: id,
1287
+ additionalContext: [
1288
+ prepared.additionalContext,
1289
+ `Official Codex subagent overlay for ${route?.command || route?.id || 'this route'}: use ${SUBAGENT_PLAN_FILENAME}, record matched SubagentStart/SubagentStop events in ${SUBAGENT_EVENT_LOG_FILENAME}, and provide the required structured parent thread-outcome summary before this route's own gate can pass. This generic overlay does not create ${NARUTO_SUMMARY_FILENAME}, ${NARUTO_GATE_FILENAME}, or close the work-order ledger.`,
1290
+ delegationPrompt
1291
+ ].filter(Boolean).join('\n\n')
1292
+ };
1293
+ }
1021
1294
  async function prepareNaruto(root, route, task, required, opts = {}) {
1022
1295
  const cleanTask = stripDollarCommand(task) || String(task || '').trim();
1023
1296
  const fromChatImgRequired = hasFromChatImgSignal(cleanTask);
1024
- const { id, dir } = await createMission(root, { mode: 'naruto', prompt: cleanTask, sessionKey: opts.sessionKey });
1297
+ const requestedSubagents = requestedSubagentsFromTask(cleanTask);
1298
+ const observedParentModel = typeof opts.parentModel === 'string' && opts.parentModel.trim()
1299
+ ? opts.parentModel.trim()
1300
+ : null;
1301
+ const mission = opts.sessionKey
1302
+ ? await getOrCreateSessionMission(root, {
1303
+ mode: 'naruto',
1304
+ prompt: cleanTask,
1305
+ sessionKey: opts.sessionKey,
1306
+ selectMissionId: (state) => {
1307
+ const activeRoute = String(state?.route || state?.route_command || state?.mode || '').replace(/^\$/, '').toUpperCase();
1308
+ const sessionMatches = state?._session_key === sessionStateKey(opts.sessionKey);
1309
+ return sessionMatches && state?.mission_id && state?.route_closed !== true && activeRoute === 'NARUTO'
1310
+ ? String(state.mission_id)
1311
+ : null;
1312
+ }
1313
+ })
1314
+ : await createMission(root, { mode: 'naruto', prompt: cleanTask, sessionKey: opts.sessionKey });
1315
+ const { id, dir } = mission;
1316
+ await createAndWriteWorkOrderLedgerForPrompt(dir, {
1317
+ missionId: id,
1318
+ route: 'Naruto',
1319
+ prompt: cleanTask
1320
+ });
1321
+ const preparation = await prepareOfficialSubagentMission({
1322
+ root,
1323
+ dir,
1324
+ missionId: id,
1325
+ goal: cleanTask,
1326
+ route: '$Naruto',
1327
+ sessionScope: opts.sessionKey || null,
1328
+ ...(requestedSubagents === undefined ? {} : { requestedSubagents }),
1329
+ requestedSubagentsExplicit: requestedSubagents !== undefined,
1330
+ mode: 'naruto',
1331
+ observedParentModel,
1332
+ preparationOnly: true
1333
+ });
1334
+ const { budget, delegationPrompt, workflowRunId, taskProfile, officialConfig, triwikiAttention, parentModelMatch } = preparation;
1025
1335
  const routeContextPayload = {
1026
1336
  route: 'Naruto',
1027
1337
  command: '$Naruto',
@@ -1030,34 +1340,34 @@ async function prepareNaruto(root, route, task, required, opts = {}) {
1030
1340
  required_skills: route.requiredSkills || ['naruto', 'pipeline-runner', 'prompt-pipeline', 'honest-mode'],
1031
1341
  context7_required: required,
1032
1342
  context_tracking: triwikiContextTracking(),
1033
- stop_gate: 'naruto-gate.json',
1343
+ stop_gate: NARUTO_GATE_FILENAME,
1344
+ workflow: 'official_codex_subagent',
1345
+ workflow_run_id: workflowRunId,
1346
+ session_scope: opts.sessionKey || null,
1347
+ requested_subagents: budget.requestedSubagents,
1348
+ requested_subagents_explicit: requestedSubagents !== undefined,
1349
+ max_threads: budget.maxThreads,
1350
+ max_depth: budget.maxDepth,
1351
+ parent_model_policy: NARUTO_PARENT_MODEL,
1352
+ observed_parent_model: observedParentModel,
1353
+ parent_model_match: parentModelMatch,
1354
+ config_sources: officialConfig.sources,
1355
+ config_blockers: officialConfig.blockers,
1356
+ triwiki_attention: triwikiAttention,
1034
1357
  team_alias: opts.teamAlias === true,
1035
1358
  from_chat_img_required: fromChatImgRequired,
1036
1359
  mad_sks_authorization: Boolean(opts.madSksAuthorization)
1037
1360
  };
1038
1361
  await writeJsonAtomic(path.join(dir, 'route-context.json'), routeContextPayload);
1039
- await writeJsonAtomic(path.join(dir, 'naruto-gate.json'), {
1040
- schema: 'sks.naruto-gate.v1',
1041
- passed: false,
1042
- mission_id: id,
1043
- clone_roster_built: false,
1044
- work_graph_ready: false,
1045
- role_distribution_ready: false,
1046
- allocation_ready: false,
1047
- rebalance_ready: false,
1048
- concurrency_governor_ready: false,
1049
- active_pool_ready: false,
1050
- verification_dag_ready: false,
1051
- gpt_final_pack_ready: false,
1052
- zellij_dashboard_ready: false,
1053
- native_agent_proof: false,
1054
- final_arbiter_accepted: false,
1055
- session_cleanup: false,
1056
- ...(fromChatImgRequired ? { from_chat_img_required: true, from_chat_img_request_coverage: false } : {}),
1057
- blockers: ['naruto_run_not_started'],
1058
- updated_at: nowIso()
1059
- });
1060
- const pipelinePlan = await writePipelinePlan(dir, { missionId: id, route, task: cleanTask, required, ambiguity: { required: false, status: opts.teamAlias ? 'team_alias_to_naruto' : 'direct_naruto' } });
1362
+ if (fromChatImgRequired) {
1363
+ const gate = await readJson(path.join(dir, NARUTO_GATE_FILENAME), {});
1364
+ await writeJsonAtomic(path.join(dir, NARUTO_GATE_FILENAME), {
1365
+ ...gate,
1366
+ from_chat_img_required: true,
1367
+ from_chat_img_request_coverage: false
1368
+ });
1369
+ }
1370
+ const pipelinePlan = await writePipelinePlan(dir, { missionId: id, route, task: cleanTask, taskProfile, required, ambiguity: { required: false, status: opts.teamAlias ? 'team_alias_to_naruto' : 'direct_naruto' } });
1061
1371
  await setCurrent(root, routeState(id, route, 'NARUTO_READY', required, {
1062
1372
  prompt: cleanTask,
1063
1373
  route: 'Naruto',
@@ -1066,26 +1376,45 @@ async function prepareNaruto(root, route, task, required, opts = {}) {
1066
1376
  implementation_allowed: true,
1067
1377
  ambiguity_gate_required: false,
1068
1378
  ambiguity_gate_passed: true,
1069
- stop_gate: 'naruto-gate.json',
1379
+ stop_gate: NARUTO_GATE_FILENAME,
1070
1380
  required_skills: routeContextPayload.required_skills,
1071
1381
  subagents_required: true,
1072
- native_sessions_required: true,
1382
+ native_sessions_required: false,
1383
+ agents_required: false,
1384
+ requested_subagents: budget.requestedSubagents,
1385
+ subagent_max_threads: budget.maxThreads,
1386
+ subagent_max_depth: budget.maxDepth,
1387
+ subagent_plan_file: SUBAGENT_PLAN_FILENAME,
1388
+ subagent_evidence_file: SUBAGENT_EVIDENCE_FILENAME,
1389
+ official_subagent_run_id: workflowRunId,
1390
+ session_scope: opts.sessionKey || null,
1391
+ observed_parent_model: observedParentModel,
1392
+ parent_model_match: parentModelMatch,
1073
1393
  from_chat_img_required: fromChatImgRequired,
1074
- naruto_gate_file: 'naruto-gate.json',
1394
+ naruto_gate_file: NARUTO_GATE_FILENAME,
1075
1395
  pipeline_plan_ready: validatePipelinePlan(pipelinePlan).ok,
1076
1396
  pipeline_plan_path: PIPELINE_PLAN_ARTIFACT
1077
1397
  }), { sessionKey: opts.sessionKey });
1078
- return routeContext(route, id, cleanTask, required, `Run sks naruto run ${JSON.stringify(cleanTask)} --json (or continue with Codex native workers for the same mission), then update naruto-gate.json from the worker proof and verification DAG.`);
1398
+ return routeContext(route, id, cleanTask, required, `Use the delegation context below in the current Codex parent session. First replace parent_required with a defensible independent/disjoint decomposition, then spawn and wait for every requested agent thread. Record official events and integrate the parent summary before passing ${NARUTO_GATE_FILENAME}.\n\n${delegationPrompt}`);
1399
+ }
1400
+ function requestedSubagentsFromTask(task) {
1401
+ const text = String(task || '');
1402
+ const value = text.match(/(?:^|\s)--agents(?:=|\s+)(\d+)\b/i)?.[1];
1403
+ if (!value)
1404
+ return undefined;
1405
+ const parsed = Number.parseInt(value, 10);
1406
+ return Number.isFinite(parsed) ? parsed : undefined;
1079
1407
  }
1080
1408
  function routeState(id, route, phase, context7Required, extra = {}) {
1081
1409
  const reasoning = routeReasoning(route, extra.prompt || '');
1082
- const nativeSessionsRequired = routeRequiresSubagents(route, extra.prompt || '');
1083
- return { mission_id: id, route: route.id, route_command: route.command, mode: route.mode, phase, context7_required: context7Required, context7_verified: false, subagents_required: false, subagents_verified: true, native_sessions_required: nativeSessionsRequired, native_sessions_verified: false, agents_required: routeRequiresAgentIntake(route, { task: extra.prompt }), agent_count: AGENT_COUNT, reflection_required: reflectionRequiredForRoute(route), visible_progress_required: true, context_tracking: 'triwiki', required_skills: route.requiredSkills, stop_gate: route.stopGate, reasoning_effort: reasoning.effort, reasoning_profile: reasoning.profile, reasoning_temporary: true, goal_continuation: ambientGoalContinuation(), ...extra };
1410
+ const subagentsRequired = routeRequiresSubagents(route, extra.prompt || '');
1411
+ return { mission_id: id, route: route.id, route_command: route.command, mode: route.mode, phase, context7_required: context7Required, context7_verified: false, subagents_required: subagentsRequired, subagents_verified: !subagentsRequired, native_sessions_required: false, native_sessions_verified: false, agents_required: subagentsRequired ? false : routeRequiresAgentIntake(route, { task: extra.prompt }), reflection_required: reflectionRequiredForRoute(route), visible_progress_required: true, context_tracking: 'triwiki', required_skills: route.requiredSkills, stop_gate: route.stopGate, reasoning_effort: reasoning.effort, reasoning_profile: reasoning.profile, reasoning_temporary: true, goal_continuation: ambientGoalContinuation(), ...extra };
1084
1412
  }
1085
1413
  function routeContext(route, id, task, required, next) {
1086
1414
  const visibleTask = stripVisibleDecisionAnswerBlocks(task);
1087
1415
  return {
1088
1416
  route,
1417
+ mission_id: id,
1089
1418
  additionalContext: `${promptPipelineContext(visibleTask, route)}
1090
1419
 
1091
1420
  ${route.command} route prepared.
@@ -1096,7 +1425,7 @@ Execution prompt: request-intake.transformed_prompt
1096
1425
  Pipeline plan: .sneakoscope/missions/${id}/${PIPELINE_PLAN_ARTIFACT}
1097
1426
  Required skills: ${route.requiredSkills.join(', ')}
1098
1427
  Stop gate: ${route.stopGate}
1099
- Native sessions: ${routeRequiresSubagents(route, visibleTask) ? 'required before code-changing execution; run parallel workers/reviewers with disjoint ownership or record explicit unavailable/unsplittable evidence.' : 'optional'}
1428
+ Official subagents: ${routeRequiresSubagents(route, visibleTask) ? 'required for this explicit Naruto/parallel task; use independent disjoint slices, official agent threads, matched SubagentStart/SubagentStop events, and a parent integration summary.' : 'not required by this task profile; keep the work parent-owned unless a concrete independent decomposition emerges.'}
1100
1429
  TriWiki: use only the latest coordinate+voxel-overlay context pack before each route phase, hydrate low-trust claims during the phase, refresh after new findings or artifact changes, and validate before handoffs/final claims. Coordinate-only legacy packs are invalid and must be refreshed before pipeline decisions.
1101
1430
  Final closeout: every pipeline final answer must summarize what was done, what changed for the user/repo, what was verified, and any remaining gaps.
1102
1431
  ${reflectionRequiredForRoute(route) ? `Reflection: ${reflectionInstructionText()}` : 'Reflection: not required for this lightweight route.'}
@@ -1175,19 +1504,26 @@ export async function recordContext7Evidence(root, state, payload) {
1175
1504
  return record;
1176
1505
  }
1177
1506
  export async function recordSubagentEvidence(root, state, payload) {
1178
- const stage = subagentStage(payload);
1179
- if (!stage)
1180
- return null;
1181
1507
  if (!await shouldWritePipelineEvidence(root, state))
1182
1508
  return null;
1183
- const record = { ts: nowIso(), stage, tool: subagentToolName(payload), payload_keys: Object.keys(payload || {}).sort() };
1184
1509
  const id = state?.mission_id;
1185
- const file = id ? path.join(missionDir(root, id), 'subagent-evidence.jsonl') : path.join(root, '.sneakoscope', 'state', 'subagent-evidence.jsonl');
1186
- await appendJsonl(file, record);
1187
- if (id) {
1188
- const evidence = await subagentEvidence(root, state);
1189
- await setCurrent(root, { subagents_spawned: evidence.spawn, subagents_reported: evidence.result, subagents_verified: evidence.ok }, { sessionKey: state._session_key });
1190
- }
1510
+ const dir = id ? missionDir(root, id) : path.join(root, '.sneakoscope', 'state', 'subagents');
1511
+ const explicitEventName = payload?.hook_event_name
1512
+ || payload?.hookEventName
1513
+ || payload?.event_name
1514
+ || payload?.eventName
1515
+ || payload?.event
1516
+ || null;
1517
+ const officialEvent = await recordSubagentEvent(dir, payload, explicitEventName);
1518
+ if (officialEvent)
1519
+ return officialEvent;
1520
+ if (!legacySubagentWorkflowEnabled(state))
1521
+ return null;
1522
+ const stage = legacySubagentStage(payload);
1523
+ if (!stage)
1524
+ return null;
1525
+ const record = { ts: nowIso(), stage, tool: legacySubagentToolName(payload), payload_keys: Object.keys(payload || {}).sort(), workflow: 'legacy_process_swarm' };
1526
+ await appendJsonl(path.join(dir, 'subagent-evidence.jsonl'), record);
1191
1527
  return record;
1192
1528
  }
1193
1529
  async function shouldWritePipelineEvidence(root, state = {}) {
@@ -1195,11 +1531,11 @@ async function shouldWritePipelineEvidence(root, state = {}) {
1195
1531
  return exists(missionDir(root, state.mission_id));
1196
1532
  return exists(path.join(root, '.sneakoscope', 'state', 'current.json'));
1197
1533
  }
1198
- function subagentToolName(payload) {
1534
+ function legacySubagentToolName(payload) {
1199
1535
  const obj = payload || {};
1200
1536
  return String(obj.tool_name || obj.name || obj.tool?.name || obj.mcp_tool || obj.command || obj.type || '');
1201
1537
  }
1202
- function subagentStage(payload) {
1538
+ function legacySubagentStage(payload) {
1203
1539
  const hay = JSON.stringify(payload || {});
1204
1540
  // Codex 0.139 renamed multi-agent v2 `close_agent` to `interrupt_agent`;
1205
1541
  // accept both so cockpit evidence keeps classifying on newer CLIs.
@@ -1209,10 +1545,8 @@ function subagentStage(payload) {
1209
1545
  return 'exception';
1210
1546
  if (/spawn_agent/i.test(hay))
1211
1547
  return 'spawn_agent';
1212
- for (const name of ['interrupt_agent', 'close_agent']) {
1213
- if (hay.includes(name) && normalizeCodexMultiAgentEventName(name).stage === 'result')
1214
- return 'result';
1215
- }
1548
+ if (/interrupt_agent|close_agent/i.test(hay))
1549
+ return 'result';
1216
1550
  if (/wait_agent|completed|final/i.test(hay))
1217
1551
  return 'result';
1218
1552
  return 'subagent';
@@ -1220,8 +1554,44 @@ function subagentStage(payload) {
1220
1554
  export async function subagentEvidence(root, state) {
1221
1555
  const id = state?.mission_id;
1222
1556
  if (!id)
1223
- return { spawn: false, result: false, exception: false, ok: false, count: 0 };
1224
- const text = await readText(path.join(missionDir(root, id), 'subagent-evidence.jsonl'), '');
1557
+ return { spawn: false, result: false, exception: false, ok: false, count: 0, workflow: 'official_codex_subagent' };
1558
+ const dir = missionDir(root, id);
1559
+ const plan = await readJson(path.join(dir, 'subagent-plan.json'), null).catch(() => null);
1560
+ if (plan?.workflow === 'official_codex_subagent') {
1561
+ const [events, persistedParentSummary, summary, canonical] = await Promise.all([
1562
+ readSubagentEvents(dir),
1563
+ readJson(path.join(dir, SUBAGENT_PARENT_SUMMARY_FILENAME), null).catch(() => null),
1564
+ readJson(path.join(dir, 'naruto-summary.json'), null).catch(() => null),
1565
+ readJson(path.join(dir, SUBAGENT_EVIDENCE_FILENAME), null).catch(() => null)
1566
+ ]);
1567
+ const evidence = buildSubagentEvidence({
1568
+ requestedSubagents: Number(plan.requested_subagents || 0),
1569
+ events,
1570
+ parentSummary: persistedParentSummary,
1571
+ workflowStatus: summary?.status || null,
1572
+ preparationOnly: summary?.status === 'delegation_context_ready' || canonical?.preparation_only === true,
1573
+ additionalBlockers: Array.isArray(plan.config_blockers)
1574
+ ? plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`)
1575
+ : []
1576
+ });
1577
+ const canonicalMismatch = canonicalEvidenceMismatch(canonical, evidence);
1578
+ const blockers = [...new Set([
1579
+ ...(Array.isArray(evidence.blockers) ? evidence.blockers : []),
1580
+ ...(canonicalMismatch ? [canonicalMismatch] : [])
1581
+ ])];
1582
+ return {
1583
+ ...evidence,
1584
+ ok: evidence.ok === true && blockers.length === 0,
1585
+ blockers,
1586
+ spawn: evidence.started_threads > 0,
1587
+ result: evidence.completed_threads > 0,
1588
+ exception: evidence.failed_threads > 0,
1589
+ count: events.length
1590
+ };
1591
+ }
1592
+ if (!legacySubagentWorkflowEnabled(state))
1593
+ return { spawn: false, result: false, exception: false, ok: false, count: 0, workflow: 'official_codex_subagent' };
1594
+ const text = await readText(path.join(dir, 'subagent-evidence.jsonl'), '');
1225
1595
  const lines = text.split(/\n/).filter(Boolean);
1226
1596
  let spawn = false;
1227
1597
  let result = false;
@@ -1238,11 +1608,39 @@ export async function subagentEvidence(root, state) {
1238
1608
  }
1239
1609
  catch { }
1240
1610
  }
1241
- return { spawn, result, exception, ok: spawn || exception, count: lines.length };
1611
+ return { spawn, result, exception, ok: spawn || exception, count: lines.length, workflow: 'legacy_process_swarm' };
1612
+ }
1613
+ function canonicalEvidenceMismatch(canonical, recomputed) {
1614
+ if (canonical?.schema !== 'sks.subagent-evidence.v1' || canonical?.workflow !== 'official_codex_subagent') {
1615
+ return 'persisted_subagent_evidence_schema_invalid';
1616
+ }
1617
+ const scalarKeys = [
1618
+ 'requested_subagents', 'started_threads', 'completed_threads', 'failed_threads',
1619
+ 'parent_summary_present', 'parent_summary_trustworthy', 'parent_summary_status',
1620
+ 'preparation_only', 'status', 'ok'
1621
+ ];
1622
+ for (const key of scalarKeys) {
1623
+ if (canonical?.[key] !== recomputed?.[key])
1624
+ return `persisted_subagent_evidence_mismatch:${key}`;
1625
+ }
1626
+ const arrayKeys = [
1627
+ 'started_thread_ids', 'completed_thread_ids', 'failed_thread_ids', 'open_thread_ids',
1628
+ 'unmatched_stop_thread_ids', 'ambiguous_stop_thread_ids', 'event_sources', 'blockers'
1629
+ ];
1630
+ for (const key of arrayKeys) {
1631
+ if (JSON.stringify(canonical?.[key] || []) !== JSON.stringify(recomputed?.[key] || [])) {
1632
+ return `persisted_subagent_evidence_mismatch:${key}`;
1633
+ }
1634
+ }
1635
+ return null;
1242
1636
  }
1243
1637
  export async function hasSubagentEvidence(root, state) {
1244
1638
  return (await subagentEvidence(root, state)).ok;
1245
1639
  }
1640
+ function legacySubagentWorkflowEnabled(state = {}) {
1641
+ return state?.legacy_subagent_workflow === true
1642
+ || state?.workflow === 'legacy_process_swarm';
1643
+ }
1246
1644
  function context7ToolName(payload) {
1247
1645
  const obj = payload || {};
1248
1646
  return String(obj.tool_name || obj.name || obj.tool?.name || obj.mcp_tool || obj.command || obj.type || '');