sneakoscope 7.0.2 → 7.0.5

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 (598) hide show
  1. package/README.md +9 -7
  2. package/config/codex-releases/{rust-v0.144.5.json → rust-v0.145.0.json} +14 -8
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/bin/sks-dispatch.js +0 -3
  6. package/dist/cli/command-manifest-lite.js +1 -2
  7. package/dist/cli/command-registry.js +0 -4
  8. package/dist/cli/global-mode-router.js +5 -12
  9. package/dist/cli/install-helpers-codex-lb-chain.js +24 -2
  10. package/dist/cli/install-helpers-codex-lb-config.js +10 -25
  11. package/dist/cli/install-helpers-codex-lb-selftest-chain.js +0 -3
  12. package/dist/cli/install-helpers-codex-lb-selftest.js +0 -17
  13. package/dist/cli/install-helpers-install-support.js +1 -2
  14. package/dist/cli/install-helpers.js +83 -99
  15. package/dist/cli/router.js +22 -31
  16. package/dist/commands/codex-app.js +20 -2
  17. package/dist/commands/codex-lb.js +176 -22
  18. package/dist/commands/codex.js +3 -8
  19. package/dist/commands/conflicts.js +26 -3
  20. package/dist/commands/doctor.js +26 -31
  21. package/dist/commands/perf.js +5 -1
  22. package/dist/commands/zellij-slot-column-anchor.js +0 -2
  23. package/dist/commands/zellij-slot-pane.js +0 -7
  24. package/dist/commands/zellij.js +0 -2
  25. package/dist/config/skills-manifest.json +52 -52
  26. package/dist/core/agent-bridge/agent-manifest.js +192 -1
  27. package/dist/core/agent-bridge/agent-mode.js +0 -5
  28. package/dist/core/agent-bridge/host-capability-policy.js +189 -0
  29. package/dist/core/agent-bridge/host-capability-runtime.js +1395 -0
  30. package/dist/core/agent-bridge/mcp-server.js +1 -11
  31. package/dist/core/agents/agent-effort-policy.js +7 -10
  32. package/dist/core/agents/agent-orchestrator.js +0 -4
  33. package/dist/core/agents/agent-proof-evidence.js +0 -2
  34. package/dist/core/agents/agent-roster.js +6 -5
  35. package/dist/core/agents/agent-runner-ollama.js +0 -3
  36. package/dist/core/agents/agent-scheduler.js +7 -10
  37. package/dist/core/agents/agent-schema.js +3 -1
  38. package/dist/core/agents/agent-task-graph.js +4 -1
  39. package/dist/core/agents/agent-work-partition.js +4 -2
  40. package/dist/core/agents/native-cli-worker-runtime.js +5 -17
  41. package/dist/core/agents/work-partition/repo-inventory.js +0 -2
  42. package/dist/core/auto-review.js +8 -14
  43. package/dist/core/bench.js +0 -14
  44. package/dist/core/code-structure.js +0 -3
  45. package/dist/core/codex/agent-config-file-repair.js +0 -8
  46. package/dist/core/codex/codex-cli-update.js +122 -20
  47. package/dist/core/codex/codex-config-eperm-repair.js +0 -4
  48. package/dist/core/codex/codex-config-guard.js +0 -3
  49. package/dist/core/codex/codex-config-readability.js +0 -13
  50. package/dist/core/codex/codex-project-config-policy.js +0 -33
  51. package/dist/core/codex/codex-startup-config-postcheck.js +5 -0
  52. package/dist/core/codex/official-goal-mode.js +0 -2
  53. package/dist/core/codex-app/codex-agent-type-probe.js +31 -24
  54. package/dist/core/codex-app/codex-app-fast-ui-repair.js +5 -7
  55. package/dist/core/codex-app/codex-app-ui-state-snapshot.js +44 -7
  56. package/dist/core/codex-app/glm-model-profile.js +1 -1
  57. package/dist/core/codex-app/glm-profile-installer.js +40 -41
  58. package/dist/core/codex-app/glm-profile-schema.js +7 -11
  59. package/dist/core/codex-app/menubar/constants.js +1 -0
  60. package/dist/core/codex-app/menubar/launch-agent.js +37 -1
  61. package/dist/core/codex-app/openrouter-activate.js +152 -0
  62. package/dist/core/codex-app/openrouter-provider.js +82 -0
  63. package/dist/core/codex-app/sks-menubar.js +0 -1
  64. package/dist/core/codex-app.js +14 -32
  65. package/dist/core/codex-compat/codex-capability-matrix.js +208 -0
  66. package/dist/core/codex-compat/codex-hook-output-builders.js +9 -1
  67. package/dist/core/codex-compat/codex-hook-output-normalizer.js +1 -1
  68. package/dist/core/codex-compat/codex-hook-semantic-validator.js +3 -2
  69. package/dist/core/codex-compat/codex-hook-warning-detector.js +10 -2
  70. package/dist/core/codex-compat/codex-release-manifest.js +15 -8
  71. package/dist/core/codex-compat/codex-version-policy.js +77 -15
  72. package/dist/core/codex-control/codex-0144-capability.js +1 -1
  73. package/dist/core/codex-control/codex-lb-launch-recovery.js +0 -3
  74. package/dist/core/codex-control/codex-reliability-shield.js +0 -8
  75. package/dist/core/codex-control/codex-sdk-adapter.js +0 -3
  76. package/dist/core/codex-control/codex-sdk-config-policy.js +0 -2
  77. package/dist/core/codex-control/codex-sdk-env-policy.js +61 -16
  78. package/dist/core/codex-control/codex-task-runner.js +0 -7
  79. package/dist/core/codex-control/codex-thread-registry.js +0 -4
  80. package/dist/core/codex-lb/codex-lb-env.js +133 -24
  81. package/dist/core/codex-lb/codex-lb-tool-catalog.js +0 -4
  82. package/dist/core/codex-lb/codex-lb-tool-output-recovery.js +1 -1
  83. package/dist/core/codex-model-guard.js +0 -14
  84. package/dist/core/codex-native/codex-native-feature-broker.js +67 -22
  85. package/dist/core/codex-native/codex-native-interop-policy.js +81 -9
  86. package/dist/core/codex-native/confined-report-writer.js +21 -0
  87. package/dist/core/codex-native/core-skill-integrity.js +169 -20
  88. package/dist/core/codex-native/project-skill-dedupe.js +55 -13
  89. package/dist/core/codex-native/skill-registry-ledger.js +137 -16
  90. package/dist/core/codex-native/sks-skill-paths.js +185 -0
  91. package/dist/core/codex-runtime/codex-desktop-config-policy.js +3 -3
  92. package/dist/core/commands/agent-bridge-command.js +28 -8
  93. package/dist/core/commands/basic-cli.js +89 -42
  94. package/dist/core/commands/bench-command.js +5 -1
  95. package/dist/core/commands/command-utils.js +0 -5
  96. package/dist/core/commands/image-ux-review-command.js +0 -9
  97. package/dist/core/commands/mad-sks-command.js +55 -208
  98. package/dist/core/commands/naruto-command.js +55 -21
  99. package/dist/core/commands/ppt-command.js +0 -9
  100. package/dist/core/commands/run-command.js +8 -2
  101. package/dist/core/commands/seo-command.js +0 -6
  102. package/dist/core/commands/wiki-command.js +0 -14
  103. package/dist/core/computer-use-live-evidence.js +0 -5
  104. package/dist/core/config/secret-preservation.js +0 -11
  105. package/dist/core/daemon/sksd-hook-daemon-entrypoint.js +0 -2
  106. package/dist/core/daemon/sksd-hook-daemon.js +1 -29
  107. package/dist/core/daemon/sksd-hook-dispatch.js +0 -17
  108. package/dist/core/db-safety.js +0 -7
  109. package/dist/core/doctor/browser-use-repair.js +0 -2
  110. package/dist/core/doctor/command-alias-cleanup.js +37 -9
  111. package/dist/core/doctor/current-project-guidance.js +6 -3
  112. package/dist/core/doctor/doctor-codex-startup-repair.js +0 -3
  113. package/dist/core/doctor/doctor-dirty-planner.js +1 -1
  114. package/dist/core/doctor/doctor-readiness-matrix.js +12 -0
  115. package/dist/core/doctor/doctor-skill-reconcile.js +32 -0
  116. package/dist/core/doctor/imagegen-repair.js +0 -2
  117. package/dist/core/doctor/mcp-transport-collision-repair.js +0 -3
  118. package/dist/core/doctor/retired-auto-review-config.js +9 -1
  119. package/dist/core/doctor/retired-managed-residue-private.js +5 -4
  120. package/dist/core/doctor/retired-managed-residue-runtime.js +9 -1
  121. package/dist/core/doctor/skill-legacy-surface.js +351 -0
  122. package/dist/core/doctor/supabase-mcp-repair.js +0 -11
  123. package/dist/core/evaluation.js +3 -0
  124. package/dist/core/feature-fixture-executor.js +0 -48
  125. package/dist/core/feature-fixtures.js +0 -6
  126. package/dist/core/fsx.js +11 -12
  127. package/dist/core/harness-conflicts.js +177 -18
  128. package/dist/core/hooks-runtime/code-pack-freshness-preflight.js +0 -5
  129. package/dist/core/hooks-runtime/hook-context.js +202 -0
  130. package/dist/core/hooks-runtime/hook-io.js +1 -12
  131. package/dist/core/hooks-runtime/light-turn.js +0 -2
  132. package/dist/core/hooks-runtime/naruto-decision-gate.js +4 -1
  133. package/dist/core/hooks-runtime/naruto-terminal-finalization.js +91 -0
  134. package/dist/core/hooks-runtime/official-subagent-lifecycle.js +369 -0
  135. package/dist/core/hooks-runtime/standalone-parent-host-capability.js +98 -0
  136. package/dist/core/hooks-runtime/subagent-context.js +59 -0
  137. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +29 -0
  138. package/dist/core/hooks-runtime/subagent-skill-availability-evidence.js +195 -0
  139. package/dist/core/hooks-runtime/subagent-skill-availability-guards.js +316 -0
  140. package/dist/core/hooks-runtime/subagent-skill-availability.js +217 -0
  141. package/dist/core/hooks-runtime.js +275 -540
  142. package/dist/core/image-ux-review/codex-app-generated-image-discovery.js +0 -17
  143. package/dist/core/image-ux-review/imagegen-adapter.js +0 -14
  144. package/dist/core/imagegen/imagegen-auth-readiness.js +0 -9
  145. package/dist/core/imagegen/imagegen-capability.js +0 -3
  146. package/dist/core/init/managed-skill-install.js +42 -0
  147. package/dist/core/init/skills.js +248 -75
  148. package/dist/core/init.js +19 -45
  149. package/dist/core/lean-engineering-policy.js +0 -2
  150. package/dist/core/locks/file-lock.js +0 -21
  151. package/dist/core/loops/loop-planner.js +0 -6
  152. package/dist/core/loops/loop-runtime.js +0 -1
  153. package/dist/core/loops/loop-worker-runtime.js +0 -19
  154. package/dist/core/mad-sks/executors/db-write-executor.js +0 -4
  155. package/dist/core/mad-sks/executors/executor-base.js +0 -10
  156. package/dist/core/mad-sks/immutable-harness-guard.js +0 -5
  157. package/dist/core/mad-sks/sql-plane/coordinator.js +0 -5
  158. package/dist/core/mad-sks/sql-plane/ledger.js +0 -4
  159. package/dist/core/mad-sks/sql-plane/lock.js +0 -4
  160. package/dist/core/mad-sks/sql-plane/mcp-executor.js +0 -9
  161. package/dist/core/mad-sks/sql-plane/policy-resolver.js +0 -2
  162. package/dist/core/mad-sks/sql-plane/postconditions.js +0 -4
  163. package/dist/core/mad-sks/sql-plane/recovery.js +0 -2
  164. package/dist/core/mad-sks/sql-plane/runtime-profile.js +0 -8
  165. package/dist/core/managed-assets/managed-assets-manifest.js +1 -7
  166. package/dist/core/mcp-config/health-check.js +10 -3
  167. package/dist/core/migration/migration-transaction-journal.js +0 -8
  168. package/dist/core/mission.js +0 -2
  169. package/dist/core/naruto/naruto-active-pool.js +0 -2
  170. package/dist/core/naruto/naruto-concurrency-governor.js +18 -11
  171. package/dist/core/naruto/naruto-real-write-proof.js +0 -4
  172. package/dist/core/naruto/naruto-write-e2e.js +0 -1
  173. package/dist/core/perf/perf-budget.js +0 -5
  174. package/dist/core/permission-gates.js +0 -2
  175. package/dist/core/pipeline-internals/runtime-core.js +15 -5
  176. package/dist/core/pipeline-internals/runtime-gates.js +7 -19
  177. package/dist/core/preflight/parallel-preflight-engine.js +1 -12
  178. package/dist/core/proof/evidence-collector.js +0 -2
  179. package/dist/core/proof/route-finalizer.js +0 -1
  180. package/dist/core/proof/selftest-proof-fixtures.js +0 -5
  181. package/dist/core/providers/openrouter/openrouter-client.js +2 -2
  182. package/dist/core/providers/openrouter/openrouter-provider-health.js +1 -1
  183. package/dist/core/providers/{glm/glm-request-cache.js → openrouter/openrouter-request-cache.js} +5 -6
  184. package/dist/core/providers/openrouter/openrouter-secret-store.js +0 -1
  185. package/dist/core/providers/openrouter/openrouter-stream.js +2 -4
  186. package/dist/core/questions.js +3 -3
  187. package/dist/core/release/gate-manifest.js +0 -5
  188. package/dist/core/release/package-size-budget.js +2 -2
  189. package/dist/core/release/release-gate-batch-runner.js +11 -2
  190. package/dist/core/release/release-gate-cache-v2.js +0 -4
  191. package/dist/core/release/release-gate-contract.js +0 -7
  192. package/dist/core/release/release-gate-hermetic-env.js +0 -5
  193. package/dist/core/release/release-pack-receipt.js +1 -0
  194. package/dist/core/release-parallel-full-coverage.js +0 -2
  195. package/dist/core/remote/ssh-worker-client.js +0 -3
  196. package/dist/core/research/research-adversarial-review.js +6 -2
  197. package/dist/core/responses-retry-policy.js +0 -10
  198. package/dist/core/retention.js +0 -7
  199. package/dist/core/routes/constants.js +0 -3
  200. package/dist/core/routes/model-mode-router.js +10 -19
  201. package/dist/core/routes.js +91 -17
  202. package/dist/core/safety/command-contract/contracts.js +2 -0
  203. package/dist/core/safety/mutation-guard.js +0 -25
  204. package/dist/core/safety/mutation-ledger.js +0 -9
  205. package/dist/core/safety/requested-scope-contract.js +0 -0
  206. package/dist/core/security/high-risk-contracts.js +0 -1
  207. package/dist/core/skills/core-skill-card.js +0 -0
  208. package/dist/core/skills/core-skill-deployment.js +0 -13
  209. package/dist/core/skills/core-skill-epoch.js +0 -11
  210. package/dist/core/skills/core-skill-meta-update.js +0 -6
  211. package/dist/core/skills/core-skill-patch-apply.js +0 -7
  212. package/dist/core/skills/core-skill-patch.js +0 -8
  213. package/dist/core/skills/core-skill-reflection.js +0 -16
  214. package/dist/core/skills/core-skill-runtime.js +0 -6
  215. package/dist/core/skills/core-skill-scorer.js +0 -7
  216. package/dist/core/skills/core-skill-trainer.js +0 -11
  217. package/dist/core/skills/core-skill-types.js +0 -9
  218. package/dist/core/skills/core-skill-validation.js +0 -5
  219. package/dist/core/skills/rejected-skill-patch-buffer.js +0 -2
  220. package/dist/core/stop-gate/stop-gate-check.js +0 -8
  221. package/dist/core/stop-gate/stop-gate-resolver.js +0 -7
  222. package/dist/core/stop-gate/stop-gate-writer.js +0 -5
  223. package/dist/core/subagents/model-policy.js +0 -7
  224. package/dist/core/subagents/naruto-help-contract.js +3 -2
  225. package/dist/core/subagents/naruto-proof-projection.js +580 -12
  226. package/dist/core/subagents/official-subagent-config.js +256 -40
  227. package/dist/core/subagents/official-subagent-preparation.js +11 -7
  228. package/dist/core/subagents/official-subagent-prompt.js +29 -0
  229. package/dist/core/subagents/official-subagent-runner.js +379 -39
  230. package/dist/core/subagents/subagent-evidence.js +378 -9
  231. package/dist/core/subagents/terminology.js +11 -6
  232. package/dist/core/subagents/thread-budget.js +6 -3
  233. package/dist/core/subagents/triwiki-attention.js +0 -4
  234. package/dist/core/subagents/wave-parent-guidance.js +54 -9
  235. package/dist/core/telegram/runtime.js +0 -1
  236. package/dist/core/triwiki/code-index-scanner.js +0 -3
  237. package/dist/core/triwiki/code-pack-head-freshness.js +0 -10
  238. package/dist/core/triwiki/code-pack.js +0 -2
  239. package/dist/core/triwiki/triwiki-cache-key.js +0 -1
  240. package/dist/core/triwiki/triwiki-proof-bank.js +0 -1
  241. package/dist/core/triwiki-attention.js +0 -10
  242. package/dist/core/triwiki-provenance.js +0 -5
  243. package/dist/core/triwiki-runtime.js +0 -12
  244. package/dist/core/triwiki-wrongness/wrongness-ledger.js +0 -7
  245. package/dist/core/triwiki-wrongness/wrongness-schema.js +0 -3
  246. package/dist/core/trust-kernel/trust-report.js +0 -7
  247. package/dist/core/update/update-migration-state.js +113 -61
  248. package/dist/core/update-check.js +2 -14
  249. package/dist/core/version-manager.js +43 -4
  250. package/dist/core/version.js +1 -1
  251. package/dist/core/work-order-ledger.js +0 -17
  252. package/dist/core/zellij/zellij-clipboard-config.js +0 -18
  253. package/dist/core/zellij/zellij-fake-adapter.js +16 -0
  254. package/dist/core/zellij/zellij-lane-renderer.js +5 -46
  255. package/dist/core/zellij/zellij-lane-runtime.js +0 -1
  256. package/dist/core/zellij/zellij-launcher.js +35 -35
  257. package/dist/core/zellij/zellij-official-subagent-activity.js +0 -5
  258. package/dist/core/zellij/zellij-official-subagent-telemetry.js +0 -5
  259. package/dist/core/zellij/zellij-pane-proof.js +3 -3
  260. package/dist/core/zellij/zellij-screen-proof.js +0 -7
  261. package/dist/core/zellij/zellij-slot-column-anchor.js +0 -1
  262. package/dist/core/zellij/zellij-slot-pane-renderer.js +0 -9
  263. package/dist/core/zellij/zellij-slot-telemetry.js +6 -16
  264. package/dist/core/zellij/zellij-ui-mode.js +0 -7
  265. package/dist/core/zellij/zellij-update.js +0 -29
  266. package/dist/core/zellij/zellij-worker-pane-manager.js +0 -39
  267. package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +61 -2
  268. package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +10 -3
  269. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +55 -3
  270. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +76 -0
  271. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +273 -54
  272. package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +5 -1
  273. package/dist/native/sks-menubar/Sources/SettingsViewController.swift +2 -2
  274. package/dist/native/sks-menubar/Sources/StatusItemController.swift +28 -2
  275. package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +96 -13
  276. package/dist/scripts/agent-message-bus-reader-check.js +0 -1
  277. package/dist/scripts/all-feature-deep-completion-check.js +0 -1
  278. package/dist/scripts/appshots-thread-attachment-discovery-check.js +0 -1
  279. package/dist/scripts/architecture-guard-check.js +0 -1
  280. package/dist/scripts/build-dist.js +0 -1
  281. package/dist/scripts/build-once-runner-check.js +0 -1
  282. package/dist/scripts/canonical-test-runner.js +0 -2
  283. package/dist/scripts/certificate-sla-check.js +0 -1
  284. package/dist/scripts/changelog-check.js +0 -1
  285. package/dist/scripts/check-cli-entrypoint.js +0 -1
  286. package/dist/scripts/check-command-module-budget.js +0 -7
  287. package/dist/scripts/check-feature-quality.js +0 -1
  288. package/dist/scripts/check-legacy-free.js +0 -1
  289. package/dist/scripts/check-pipeline-runtime.js +0 -1
  290. package/dist/scripts/check-runtime-schemas.js +0 -1
  291. package/dist/scripts/codex-0-134-runner-truth-check.js +0 -1
  292. package/dist/scripts/codex-0-137-compat-check.js +0 -1
  293. package/dist/scripts/codex-0138-capability-artifact-check.js +0 -1
  294. package/dist/scripts/codex-0138-capability-check.js +0 -1
  295. package/dist/scripts/codex-0138-doctor-check.js +0 -1
  296. package/dist/scripts/codex-0138-feature-probes-check.js +0 -1
  297. package/dist/scripts/codex-0144-app-server-v2-check.js +5 -5
  298. package/dist/scripts/codex-0144-core-real-probes-check.js +0 -1
  299. package/dist/scripts/codex-app-handoff-check.js +0 -1
  300. package/dist/scripts/codex-app-handoff-launch-check.js +0 -1
  301. package/dist/scripts/codex-config-load-probe.js +0 -5
  302. package/dist/scripts/codex-control-all-pipelines-check.js +0 -1
  303. package/dist/scripts/codex-control-event-stream-ledger-check.js +0 -1
  304. package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +0 -1
  305. package/dist/scripts/codex-permission-profiles-check.js +0 -1
  306. package/dist/scripts/codex-plugin-app-template-policy-check.js +0 -1
  307. package/dist/scripts/codex-project-config-policy-splitter-check.js +0 -1
  308. package/dist/scripts/codex-sdk-all-pipelines-check.js +0 -1
  309. package/dist/scripts/codex-sdk-backend-router-check.js +0 -1
  310. package/dist/scripts/codex-sdk-capability-check.js +0 -1
  311. package/dist/scripts/codex-sdk-event-stream-ledger-check.js +0 -1
  312. package/dist/scripts/codex-sdk-real-smoke-check.js +0 -1
  313. package/dist/scripts/concurrent-session-collision-check.js +9 -0
  314. package/dist/scripts/context7-evidence-dedupe-check.js +0 -1
  315. package/dist/scripts/core-skill-card-schema-check.js +0 -11
  316. package/dist/scripts/core-skill-deployment-snapshot-check.js +0 -10
  317. package/dist/scripts/core-skill-heldout-validation-check.js +0 -11
  318. package/dist/scripts/core-skill-no-inference-optimizer-check.js +0 -11
  319. package/dist/scripts/core-skill-patch-check.js +0 -11
  320. package/dist/scripts/core-skill-route-runtime-integration-check.js +0 -11
  321. package/dist/scripts/current-command-surface-check.js +1 -1
  322. package/dist/scripts/current-surface-update-e2e-check.js +2 -4
  323. package/dist/scripts/current-upgrade-matrix-check.js +0 -1
  324. package/dist/scripts/dfix-fixture-check.js +0 -1
  325. package/dist/scripts/dfix-patch-handoff-check.js +0 -1
  326. package/dist/scripts/dfix-verification-check.js +0 -1
  327. package/dist/scripts/dfix-verification-recommendation-check.js +0 -1
  328. package/dist/scripts/docs-truthfulness-check.js +7 -7
  329. package/dist/scripts/doctor-fastpath-check.js +0 -1
  330. package/dist/scripts/doctor-fix-production-blackbox.js +1 -1
  331. package/dist/scripts/doctor-fix-proves-codex-read-check.js +0 -11
  332. package/dist/scripts/doctor-fixes-codex-app-fast-ui-check.js +0 -4
  333. package/dist/scripts/doctor-idempotence-check.js +0 -1
  334. package/dist/scripts/doctor-ops-semantics-check.js +0 -1
  335. package/dist/scripts/doctor-startup-config-repair-blackbox.js +1 -1
  336. package/dist/scripts/ensure-bin-executable.js +0 -1
  337. package/dist/scripts/evidence-flagship-coverage-check.js +0 -1
  338. package/dist/scripts/fast-codex-service-tier-proof-check.js +0 -1
  339. package/dist/scripts/fixtures/fake-codex-config-loader.js +0 -5
  340. package/dist/scripts/fsx-hotpath-check.js +0 -1
  341. package/dist/scripts/gate-policy-audit-check.js +1 -1
  342. package/dist/scripts/geo-claim-evidence-check.js +0 -1
  343. package/dist/scripts/geo-cli-blackbox-check.js +0 -1
  344. package/dist/scripts/geo-crawler-policy-check.js +0 -1
  345. package/dist/scripts/git-worktree-diff-envelope-check.js +0 -1
  346. package/dist/scripts/git-worktree-dirty-lock-check.js +0 -1
  347. package/dist/scripts/git-worktree-dirty-main-detection-check.js +0 -1
  348. package/dist/scripts/git-worktree-integration-primary-check.js +0 -1
  349. package/dist/scripts/git-worktree-manifest-append-check.js +0 -1
  350. package/dist/scripts/git-worktree-untracked-diff-check.js +0 -1
  351. package/dist/scripts/high-risk-contracts-check.js +0 -1
  352. package/dist/scripts/hook-latency-budget-check.js +0 -1
  353. package/dist/scripts/hook-latency-quantum-check.js +0 -1
  354. package/dist/scripts/image-artifact-path-contract-check.js +0 -1
  355. package/dist/scripts/imagegen-real-smoke-check.js +0 -1
  356. package/dist/scripts/import-graph-budget-check.js +0 -1
  357. package/dist/scripts/installed-package-smoke-check.js +0 -1
  358. package/dist/scripts/legacy-gate-purge-check.js +0 -1
  359. package/dist/scripts/lib/codex-sdk-gate-lib.js +0 -3
  360. package/dist/scripts/lib/ensure-dist-fresh.js +0 -1
  361. package/dist/scripts/lib/valid-png-fixture.js +0 -1
  362. package/dist/scripts/local-collab-all-pipelines-final-gpt-check.js +0 -1
  363. package/dist/scripts/loop-directive-check-lib.js +0 -1
  364. package/dist/scripts/loop-worker-fixture-child.js +0 -1
  365. package/dist/scripts/mad-preflight-blocks-unreadable-config-check.js +0 -10
  366. package/dist/scripts/mad-sks-sql-plane-lifecycle-hook-decision-check.js +0 -1
  367. package/dist/scripts/mad-sks-sql-plane-result-lifecycle-check.js +0 -1
  368. package/dist/scripts/mcp-plugin-inventory-check.js +0 -1
  369. package/dist/scripts/mcp-tool-naming-parity-check.js +0 -1
  370. package/dist/scripts/model-call-concurrency-check.js +0 -1
  371. package/dist/scripts/mutation-callsite-coverage-check.js +0 -5
  372. package/dist/scripts/naruto-codex-e2e-check.js +0 -1
  373. package/dist/scripts/naruto-worktree-coding-blackbox.js +0 -1
  374. package/dist/scripts/official-subagent-workflow-check.js +4 -2
  375. package/dist/scripts/ops-diagnostics-bundle-check.js +0 -1
  376. package/dist/scripts/packlist-performance-check.js +1 -3
  377. package/dist/scripts/perf-budget-check.js +0 -1
  378. package/dist/scripts/ppt-full-e2e-blackbox-check.js +0 -1
  379. package/dist/scripts/ppt-real-export-adapter-check.js +0 -1
  380. package/dist/scripts/ppt-real-imagegen-smoke-check.js +0 -1
  381. package/dist/scripts/ppt-real-imagegen-wiring-check.js +0 -1
  382. package/dist/scripts/ppt-reexport-rereview-check.js +0 -1
  383. package/dist/scripts/prepublish-fast-check.js +0 -23
  384. package/dist/scripts/prepublish-release-check-or-fast.js +0 -7
  385. package/dist/scripts/probe-memoization-check.js +0 -1
  386. package/dist/scripts/product-design-plugin-routing-check.js +0 -1
  387. package/dist/scripts/project-skill-dedupe-blackbox.js +36 -9
  388. package/dist/scripts/prompt-placeholder-guard-check.js +0 -1
  389. package/dist/scripts/python-codex-sdk-all-pipelines-check.js +0 -3
  390. package/dist/scripts/qa-loop-app-handoff-capability-check.js +0 -1
  391. package/dist/scripts/qa-loop-app-handoff-check.js +0 -1
  392. package/dist/scripts/qa-loop-app-handoff-cli-check.js +0 -1
  393. package/dist/scripts/qa-loop-app-handoff-confirmation-check.js +0 -1
  394. package/dist/scripts/qa-loop-app-handoff-gate-lifecycle-check.js +0 -1
  395. package/dist/scripts/qa-loop-app-handoff-launch-check.js +0 -1
  396. package/dist/scripts/qa-loop-app-handoff-status-lifecycle-check.js +0 -1
  397. package/dist/scripts/qa-loop-budget-policy-check.js +0 -1
  398. package/dist/scripts/qa-loop-effort-escalation-check.js +0 -1
  399. package/dist/scripts/qa-loop-image-path-exposure-check.js +0 -1
  400. package/dist/scripts/qa-loop-image-path-prompt-injection-check.js +0 -1
  401. package/dist/scripts/release-cache-glob-hashing-check.js +0 -1
  402. package/dist/scripts/release-cache-input-classifier-check.js +0 -1
  403. package/dist/scripts/release-cache-neutralization-report-check.js +0 -1
  404. package/dist/scripts/release-cache-version-neutral-fixture-check.js +0 -1
  405. package/dist/scripts/release-check-stamp.js +0 -4
  406. package/dist/scripts/release-dist-freshness-check.js +0 -1
  407. package/dist/scripts/release-full-parallelism-blackbox.js +3 -3
  408. package/dist/scripts/release-gate-batch-runner-check.js +22 -0
  409. package/dist/scripts/release-gate-budget-check.js +0 -6
  410. package/dist/scripts/release-gate-dag-runner-check.js +0 -1
  411. package/dist/scripts/release-latency-slo-check.js +0 -1
  412. package/dist/scripts/release-metadata-1-19-check.js +0 -2
  413. package/dist/scripts/release-metadata-check.js +0 -3
  414. package/dist/scripts/release-parallel-speed-budget-check.js +0 -5
  415. package/dist/scripts/release-proof-truth-check.js +0 -1
  416. package/dist/scripts/release-provenance-check.js +0 -1
  417. package/dist/scripts/release-real-check.js +0 -1
  418. package/dist/scripts/release-runtime-truth-matrix-check.js +0 -1
  419. package/dist/scripts/release-version-truth-check.js +0 -1
  420. package/dist/scripts/research-blueprint-densifier-check.js +0 -1
  421. package/dist/scripts/research-claim-builder-check.js +0 -1
  422. package/dist/scripts/research-complete-package-fixture-check.js +0 -1
  423. package/dist/scripts/research-final-reviewer-blackbox.js +0 -1
  424. package/dist/scripts/responses-retry-policy-centralized-check.js +0 -1
  425. package/dist/scripts/retention-apply-smoke-check.js +0 -1
  426. package/dist/scripts/retention-budget-check.js +0 -1
  427. package/dist/scripts/retention-dry-run-check.js +0 -1
  428. package/dist/scripts/rollback-recovery-smoke-check.js +0 -1
  429. package/dist/scripts/route-intent-regression-check.js +0 -1
  430. package/dist/scripts/runtime-current-terminal-check.js +0 -1
  431. package/dist/scripts/runtime-dist-parity-check.js +0 -1
  432. package/dist/scripts/runtime-no-src-mjs-check.js +0 -1
  433. package/dist/scripts/runtime-proof-summary-check.js +0 -1
  434. package/dist/scripts/runtime-ts-rust-boundary-check.js +0 -15
  435. package/dist/scripts/runtime-ts-source-of-truth-check.js +0 -1
  436. package/dist/scripts/scheduler-batch-dispatch-check.js +0 -1
  437. package/dist/scripts/scheduler-parallel-proof-consistency-check.js +0 -1
  438. package/dist/scripts/scheduler-utilization-integral-check.js +0 -1
  439. package/dist/scripts/search-visibility-gate-lib.js +0 -1
  440. package/dist/scripts/seo-audit-fixture-check.js +0 -1
  441. package/dist/scripts/seo-cli-blackbox-check.js +0 -1
  442. package/dist/scripts/seo-geo-geo-disambiguation-check.js +0 -1
  443. package/dist/scripts/seo-geo-route-identity-check.js +0 -1
  444. package/dist/scripts/seo-geo-skill-rich-content-check.js +0 -1
  445. package/dist/scripts/seo-marketing-truthfulness-check.js +0 -1
  446. package/dist/scripts/seo-metadata-sync-check.js +0 -1
  447. package/dist/scripts/seo-no-mutation-by-default-check.js +0 -1
  448. package/dist/scripts/shared-memory-fixture-check.js +0 -1
  449. package/dist/scripts/side-effect-runtime-report-check.js +0 -1
  450. package/dist/scripts/sizecheck.js +2 -3
  451. package/dist/scripts/sks-1-11-gate-lib.js +0 -1
  452. package/dist/scripts/sks-1-12-real-execution-check-lib.js +0 -1
  453. package/dist/scripts/sks-1-18-gate-lib.js +0 -1
  454. package/dist/scripts/sks-menubar-install-check.js +0 -3
  455. package/dist/scripts/sksd-daemon-check.js +0 -1
  456. package/dist/scripts/super-search-live-smoke-check.js +0 -1
  457. package/dist/scripts/super-search-local-http-smoke-check.js +0 -1
  458. package/dist/scripts/super-search-offline-contract-check.js +0 -1
  459. package/dist/scripts/super-search-provider-interface-check.js +0 -1
  460. package/dist/scripts/triwiki-cache-key-check.js +0 -1
  461. package/dist/scripts/triwiki-proof-bank-blackbox.js +0 -1
  462. package/dist/scripts/triwiki-proof-bank-check.js +0 -1
  463. package/dist/scripts/triwiki-proof-card-check.js +0 -1
  464. package/dist/scripts/trust-fixture-check.js +0 -1
  465. package/dist/scripts/ultra-router-auto-router-check.js +0 -1
  466. package/dist/scripts/update-fastpath-check.js +0 -1
  467. package/dist/scripts/upgrade-migration-matrix-check.js +0 -1
  468. package/dist/scripts/ux-review-extract-wires-real-extractor-check.js +0 -1
  469. package/dist/scripts/ux-review-imagegen-blackbox-check.js +0 -1
  470. package/dist/scripts/ux-review-patch-diff-recheck-check.js +0 -1
  471. package/dist/scripts/ux-review-real-imagegen-smoke-check.js +0 -1
  472. package/dist/scripts/ux-review-run-wires-imagegen-check.js +0 -1
  473. package/dist/scripts/write-build-manifest.js +0 -1
  474. package/dist/scripts/wrongness-fixture-check.js +0 -1
  475. package/dist/scripts/zellij-capability-check.js +0 -1
  476. package/dist/scripts/zellij-developer-controls-check.js +0 -1
  477. package/dist/scripts/zellij-doctor-readiness-check.js +0 -13
  478. package/dist/scripts/zellij-dynamic-pane-lifecycle-check.js +0 -1
  479. package/dist/scripts/zellij-fake-adapter-check.js +0 -1
  480. package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -1
  481. package/dist/scripts/zellij-lane-renderer-check.js +0 -1
  482. package/dist/scripts/zellij-launch-command-truth-check.js +0 -12
  483. package/dist/scripts/zellij-layout-valid-check.js +0 -1
  484. package/dist/scripts/zellij-pane-creation-lock-metrics-check.js +0 -1
  485. package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -1
  486. package/dist/scripts/zellij-pane-lock-does-not-block-worker-check.js +0 -1
  487. package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -1
  488. package/dist/scripts/zellij-pane-proof-check.js +0 -1
  489. package/dist/scripts/zellij-qa-app-handoff-status-check.js +0 -1
  490. package/dist/scripts/zellij-real-session-cleanup-check.js +0 -1
  491. package/dist/scripts/zellij-real-session-launch-check.js +0 -1
  492. package/dist/scripts/zellij-right-column-geometry-proof.js +0 -1
  493. package/dist/scripts/zellij-right-column-headless-overflow-check.js +0 -1
  494. package/dist/scripts/zellij-right-column-manager-check.js +0 -1
  495. package/dist/scripts/zellij-screen-proof-check.js +0 -1
  496. package/dist/scripts/zellij-slot-only-ui-check.js +0 -1
  497. package/dist/scripts/zellij-slot-pane-renderer-check.js +0 -1
  498. package/dist/scripts/zellij-slot-pane-stale-detection-check.js +0 -7
  499. package/dist/scripts/zellij-slot-telemetry-incremental-check.js +0 -1
  500. package/dist/scripts/zellij-slot-telemetry-live-flush-check.js +0 -1
  501. package/dist/scripts/zellij-slot-telemetry-performance-check.js +0 -1
  502. package/dist/scripts/zellij-stacked-capability-routing-check.js +0 -1
  503. package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -1
  504. package/dist/scripts/zellij-stacked-version-matrix-check.js +0 -1
  505. package/dist/scripts/zellij-stacked-version-parser-check.js +0 -1
  506. package/dist/scripts/zellij-ui-design-check.js +0 -12
  507. package/dist/scripts/zellij-update-prompt-matrix-check.js +0 -1
  508. package/dist/scripts/zellij-update-prompt-mode-check.js +0 -1
  509. package/dist/scripts/zellij-update-prompt-safety-check.js +0 -1
  510. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -2
  511. package/package.json +6 -7
  512. package/release-gates.v2.json +426 -93
  513. package/schemas/codex/app-server-0.145/codex_app_server_protocol.v2.schemas.json +19611 -0
  514. package/dist/core/commands/glm-command.js +0 -93
  515. package/dist/core/providers/glm/bench/glm-bench-comparison.js +0 -47
  516. package/dist/core/providers/glm/bench/glm-bench-fixture.js +0 -64
  517. package/dist/core/providers/glm/bench/glm-bench-model-lock-proof.js +0 -52
  518. package/dist/core/providers/glm/bench/glm-bench-report.js +0 -74
  519. package/dist/core/providers/glm/bench/glm-benchmark-runner.js +0 -243
  520. package/dist/core/providers/glm/bench/glm-benchmark-types.js +0 -1
  521. package/dist/core/providers/glm/bench/glm-direct-bench-runner.js +0 -72
  522. package/dist/core/providers/glm/glm-52-profile.js +0 -82
  523. package/dist/core/providers/glm/glm-52-request.js +0 -73
  524. package/dist/core/providers/glm/glm-52-response-guard.js +0 -32
  525. package/dist/core/providers/glm/glm-52-settings.js +0 -67
  526. package/dist/core/providers/glm/glm-context-budget.js +0 -14
  527. package/dist/core/providers/glm/glm-context-cache.js +0 -8
  528. package/dist/core/providers/glm/glm-direct-run.js +0 -140
  529. package/dist/core/providers/glm/glm-interactive-launch.js +0 -4
  530. package/dist/core/providers/glm/glm-latency-trace.js +0 -39
  531. package/dist/core/providers/glm/glm-loop-guard.js +0 -30
  532. package/dist/core/providers/glm/glm-mad-launch.js +0 -128
  533. package/dist/core/providers/glm/glm-mad-mode.js +0 -269
  534. package/dist/core/providers/glm/glm-model-meta-cache.js +0 -18
  535. package/dist/core/providers/glm/glm-patch-apply.js +0 -72
  536. package/dist/core/providers/glm/glm-patch-parser.js +0 -18
  537. package/dist/core/providers/glm/glm-profile-resolver.js +0 -168
  538. package/dist/core/providers/glm/glm-readiness.js +0 -4
  539. package/dist/core/providers/glm/glm-reasoning-policy.js +0 -14
  540. package/dist/core/providers/glm/glm-run-controller.js +0 -65
  541. package/dist/core/providers/glm/glm-run-state.js +0 -10
  542. package/dist/core/providers/glm/glm-run-timeout.js +0 -30
  543. package/dist/core/providers/glm/glm-speed-context.js +0 -81
  544. package/dist/core/providers/glm/glm-speed-gate.js +0 -39
  545. package/dist/core/providers/glm/glm-speed-output-parser.js +0 -39
  546. package/dist/core/providers/glm/glm-tool-schema-cache.js +0 -18
  547. package/dist/core/providers/glm/naruto/glm-naruto-apply-transaction.js +0 -135
  548. package/dist/core/providers/glm/naruto/glm-naruto-artifacts.js +0 -1
  549. package/dist/core/providers/glm/naruto/glm-naruto-bench.js +0 -6
  550. package/dist/core/providers/glm/naruto/glm-naruto-budget.js +0 -44
  551. package/dist/core/providers/glm/naruto/glm-naruto-combined-patch.js +0 -48
  552. package/dist/core/providers/glm/naruto/glm-naruto-command.js +0 -101
  553. package/dist/core/providers/glm/naruto/glm-naruto-concurrency-governor.js +0 -37
  554. package/dist/core/providers/glm/naruto/glm-naruto-conflict-graph.js +0 -79
  555. package/dist/core/providers/glm/naruto/glm-naruto-critical-path.js +0 -50
  556. package/dist/core/providers/glm/naruto/glm-naruto-decomposer.js +0 -148
  557. package/dist/core/providers/glm/naruto/glm-naruto-file-lease.js +0 -22
  558. package/dist/core/providers/glm/naruto/glm-naruto-final-seal.js +0 -81
  559. package/dist/core/providers/glm/naruto/glm-naruto-finalizer.js +0 -22
  560. package/dist/core/providers/glm/naruto/glm-naruto-hunk-conflict.js +0 -15
  561. package/dist/core/providers/glm/naruto/glm-naruto-hunk-parser.js +0 -35
  562. package/dist/core/providers/glm/naruto/glm-naruto-isolation-policy.js +0 -37
  563. package/dist/core/providers/glm/naruto/glm-naruto-judge.js +0 -83
  564. package/dist/core/providers/glm/naruto/glm-naruto-merge-planner.js +0 -61
  565. package/dist/core/providers/glm/naruto/glm-naruto-metrics.js +0 -33
  566. package/dist/core/providers/glm/naruto/glm-naruto-orchestrator.js +0 -486
  567. package/dist/core/providers/glm/naruto/glm-naruto-parallelism-summary.js +0 -54
  568. package/dist/core/providers/glm/naruto/glm-naruto-patch-candidate-gate.js +0 -41
  569. package/dist/core/providers/glm/naruto/glm-naruto-patch-candidate-parser.js +0 -61
  570. package/dist/core/providers/glm/naruto/glm-naruto-patch-envelope.js +0 -54
  571. package/dist/core/providers/glm/naruto/glm-naruto-quorum.js +0 -36
  572. package/dist/core/providers/glm/naruto/glm-naruto-rate-limiter.js +0 -17
  573. package/dist/core/providers/glm/naruto/glm-naruto-repair-wave.js +0 -20
  574. package/dist/core/providers/glm/naruto/glm-naruto-requirement-coverage.js +0 -108
  575. package/dist/core/providers/glm/naruto/glm-naruto-requirement-ledger.js +0 -57
  576. package/dist/core/providers/glm/naruto/glm-naruto-scoreboard.js +0 -74
  577. package/dist/core/providers/glm/naruto/glm-naruto-secret-audit.js +0 -90
  578. package/dist/core/providers/glm/naruto/glm-naruto-session-id.js +0 -9
  579. package/dist/core/providers/glm/naruto/glm-naruto-shard-planner.js +0 -31
  580. package/dist/core/providers/glm/naruto/glm-naruto-stage-scheduler.js +0 -84
  581. package/dist/core/providers/glm/naruto/glm-naruto-targeted-checks.js +0 -75
  582. package/dist/core/providers/glm/naruto/glm-naruto-task-size-classifier.js +0 -11
  583. package/dist/core/providers/glm/naruto/glm-naruto-terminal.js +0 -43
  584. package/dist/core/providers/glm/naruto/glm-naruto-trace.js +0 -173
  585. package/dist/core/providers/glm/naruto/glm-naruto-types.js +0 -36
  586. package/dist/core/providers/glm/naruto/glm-naruto-usage-extractor.js +0 -30
  587. package/dist/core/providers/glm/naruto/glm-naruto-verifier-output.js +0 -30
  588. package/dist/core/providers/glm/naruto/glm-naruto-work-graph.js +0 -1
  589. package/dist/core/providers/glm/naruto/glm-naruto-worker-artifacts.js +0 -55
  590. package/dist/core/providers/glm/naruto/glm-naruto-worker-pool.js +0 -275
  591. package/dist/core/providers/glm/naruto/glm-naruto-worker-runtime.js +0 -421
  592. package/dist/core/providers/glm/naruto/glm-naruto-worker-scheduler.js +0 -177
  593. package/dist/core/providers/glm/naruto/glm-naruto-worker.js +0 -1
  594. package/dist/core/providers/glm/naruto/glm-naruto-worktree-cleanup.js +0 -19
  595. package/dist/core/providers/glm/naruto/glm-naruto-worktree-manager.js +0 -71
  596. package/dist/core/providers/glm/naruto/glm-naruto-worktree-worker.js +0 -73
  597. package/dist/core/providers/glm/naruto/glm-naruto-worktree.js +0 -62
  598. package/schemas/codex/app-server-0.144/codex_app_server_protocol.v2.schemas.json +0 -1
@@ -1,7 +1,7 @@
1
1
  import path from 'node:path';
2
- import { projectRoot, readJson, readText, writeJsonAtomic, appendJsonl, nowIso, runProcess, sha256, packageRoot, tmpdir } from './fsx.js';
2
+ import { projectRoot, readJson, writeJsonAtomic, appendJsonl, nowIso, runProcess, sha256, packageRoot, tmpdir } from './fsx.js';
3
3
  import { looksInteractiveCommand, interactiveCommandReason } from './no-question-guard.js';
4
- import { loadStateForSession, missionDir, setCurrent, updateCurrentIfMissionAndRun } from './mission.js';
4
+ import { loadStateForSession, missionDir, sessionStateKey, setCurrent, stateFileForSession } from './mission.js';
5
5
  import { checkDbOperation, dbBlockReason, handleMadSksUserConfirmation } from './db-safety.js';
6
6
  import { maybeRecordMadSksSqlPlaneToolResultFromToolUse } from './mad-sks/sql-plane/result-lifecycle.js';
7
7
  import { checkHarnessModification, harnessGuardBlockReason, isHarnessSourceProject } from './harness-guard.js';
@@ -10,46 +10,45 @@ import { classifyMadSksShellCommand } from './mad-sks/write-guard.js';
10
10
  import { activeRouteContext, evaluateStop, prepareRoute, promptPipelineContext as routePipelineContext, recordContext7Evidence, recordSubagentEvidence, routePrompt } from './pipeline.js';
11
11
  import { localizedFinalizationReason } from './language-preference.js';
12
12
  import { classifyToolError } from './evaluation.js';
13
- import { dollarCommand, routeRequiresSubagents, stripVisibleDecisionAnswerBlocks } from './routes.js';
13
+ import { dollarCommand, managedSkillNamesForPrompt, stripVisibleDecisionAnswerBlocks } from './routes.js';
14
14
  import { coreEngineeringDirectiveReferenceText } from './lean-engineering-policy.js';
15
15
  import { scanAgentTextForRecursion } from './agents/agent-recursion-guard.js';
16
16
  import { evaluateLoopContinuation } from './loops/loop-continuation-enforcer.js';
17
17
  import { diagnosticPromptAllowedDuringNoQuestions } from './routes/diagnostic-allowlist.js';
18
- import { closeWorkOrderLedgerForRouteResult } from './work-order-ledger.js';
19
- import { maybeFinalizeRoute } from './proof/auto-finalize.js';
20
- import { validateRouteCompletionProof } from './proof/route-proof-gate.js';
21
18
  import { maybeReconcileProjectSkillsPreflight } from './hooks-runtime/skill-reconcile-preflight.js';
22
19
  import { codePackFreshnessNote } from './hooks-runtime/code-pack-freshness-preflight.js';
23
20
  import { claimHookInvocation } from './hooks-runtime/hook-invocation-dedupe.js';
24
21
  import { armLightTurnStopBypass, clearLightTurnStopBypass, consumeLightTurnStopBypass, hasMatchingLightTurnStopBypass } from './hooks-runtime/light-turn.js';
25
22
  import { evaluateHookNarutoDecisionGate, looksLikeActiveContinuationPrompt } from './hooks-runtime/naruto-decision-gate.js';
23
+ import { ensureOfficialSubagentArtifactDirConfined, officialSubagentArtifactDir, recordAndRefreshSubagentEvidence, refreshOfficialSubagentCompletionArtifacts } from './hooks-runtime/official-subagent-lifecycle.js';
26
24
  import { finalizationRepeatDecision } from './hooks-runtime/stop-repeat-guard.js';
25
+ import { activeNarutoParentLaunchMissionId, claimStandaloneParentHostCapabilityRuntime } from './hooks-runtime/standalone-parent-host-capability.js';
27
26
  import { classifyTaskProfile } from './runtime/task-profile.js';
28
27
  import { resolveSubagentThreadBudget } from './subagents/thread-budget.js';
29
28
  import { readOfficialSubagentConfig } from './subagents/official-subagent-config.js';
30
29
  import { withFileLock } from './locks/file-lock.js';
31
- import { NARUTO_PARENT_EFFORT, NARUTO_PARENT_MODEL } from './subagents/model-policy.js';
32
- import { officialSubagentRolePlan } from './subagents/agent-catalog.js';
33
- import { recordOfficialSubagentParentOutcomesTelemetry, recordOfficialSubagentZellijTelemetry } from './zellij/zellij-official-subagent-telemetry.js';
34
- import { bindTrustworthySubagentParentSummaryToRun, normalizeSubagentEvent, normalizeSubagentParentSummary, persistOrReuseTrustworthySubagentParentSummary, readSubagentEvents, recordSubagentEvent, SUBAGENT_EVIDENCE_FILENAME, SUBAGENT_PARENT_SUMMARY_FILENAME, writeSubagentEvidence } from './subagents/subagent-evidence.js';
35
- import { officialSubagentPreparationInProgress, withOfficialSubagentLifecycleLock, writeNarutoGate } from './subagents/official-subagent-preparation.js';
36
- import { effectiveSubagentTarget, normalizeLegacySubagentCountFields, refreshSubagentWaveLifecycle, subagentCountContractBlockers } from './subagents/wave-lifecycle.js';
37
- import { buildWaveParentGuidance, renderWaveParentGuidance } from './subagents/wave-parent-guidance.js';
38
- import { managedOfficialSubagentRoleByName } from './managed-assets/managed-assets-manifest.js';
39
- import { SSOT_GUARD_ARTIFACT, validateSsotGuardArtifact } from './safety/ssot-guard.js';
30
+ import { buildBoundWaveParentGuidance, renderWaveParentGuidance } from './subagents/wave-parent-guidance.js';
31
+ import { renderAuthoritativeSksSkillContext, resolveAuthoritativeSksSkillSources } from './codex-native/sks-skill-paths.js';
32
+ import { authoritativeSksSkillResolutionBlockers, clearSubagentSkillAvailabilityGuards, persistSubagentSkillAvailabilityBlocker, renderSubagentSkillAvailabilityHandoff, subagentSkillAvailabilityPreToolBlockReason } from './hooks-runtime/subagent-skill-availability.js';
33
+ import { HOST_CAPABILITY_HOOK_EVIDENCE_FILENAME, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME, HOST_CAPABILITY_HOOK_RUNTIME_FILENAME, acasHostToolName, authorizeAndMergeHostCapabilityPreToolObservation, buildHostCapabilityEvidenceFromHookObservations, explicitlyDeniedHostCapabilityTool, mergeHostCapabilityPostToolObservation, requestHostCapabilities, resolveHostCapabilityHookRuntimeBinding, sanitizeHostCapabilityPostToolUse, sanitizeHostCapabilityPreToolUse } from './agent-bridge/host-capability-runtime.js';
40
34
  const LIGHT_ROUTE_STOP_ARTIFACT = 'light-route-stop.json';
41
35
  const CODEX_GIT_ACTION_STOP_ARTIFACT = 'codex-git-action-stop-bypass.json';
42
36
  const CODEX_GIT_ACTION_STOP_TTL_MS = 15 * 60 * 1000;
43
37
  const UPDATE_CHECK_HOOK_INVOCATION_POLICY = 'function-only:no-runSksUpdateCheck-call-in-hooks';
44
- // Update checks stay function-only in hooks: the policy marker above is checked
45
- // by release readiness so ordinary Codex hook flow cannot grow a hidden update
46
- // prompt path.
47
38
  import { loadHookPayload, normalizeHookResult, visibleHookMessage } from './hooks-runtime/hook-io.js';
48
- import { codexGitActionMetadataSignal, codexGitActionMetadataText, compactAnswerContext, conversationId, explicitConversationId, extractCommand, extractLastMessage, extractUserPrompt, hookTurnId, looksLikeCodexGitAction, looksLikeCodexGitActionStopCompletion, looksLikeCodexUiSettingsEvent, looksLikeMadSksConfirmationPrompt, observedParentModel, observedParentModelMismatch, toolFailed } from './hooks-runtime/payload-signals.js';
39
+ import { codexGitActionMetadataSignal, codexGitActionMetadataText, compactAnswerContext, conversationId, explicitConversationId, extractCommand, extractLastMessage, extractUserPrompt, hookTurnId, looksLikeCodexGitAction, looksLikeCodexGitActionStopCompletion, looksLikeCodexUiSettingsEvent, looksLikeMadSksConfirmationPrompt, observedParentModel, toolFailed } from './hooks-runtime/payload-signals.js';
49
40
  import { interruptedToolOutputRecoveryBlockReason, missingToolOutputCallId, missingToolOutputCallIdFromPayload, quarantineMissingToolOutput, readToolOutputQuarantine } from './hooks-runtime/tool-output-quarantine.js';
41
+ import { activeAuthoritativeSksSkillRefresh, activeGoalOverlayContext, attachAuthoritativeSksSkillContext, authoritativeSksSkillAdmission, hookActiveSkillContextRefresh, isBlockingClarificationAwaiting, looksLikeClarificationCancel, routeBypassesActiveContext, routeIsGitOnly, selectedSksSkillNamesForActiveState, shouldPrepareFreshRouteOnActivePrompt, standaloneParentManagedSkillNames } from './hooks-runtime/hook-context.js';
42
+ import { sealedSubagentRoutingContext, subagentRouteContext } from './hooks-runtime/subagent-context.js';
50
43
  export { loadHookPayload, normalizeHookResult };
44
+ export { refreshOfficialSubagentCompletionArtifacts };
51
45
  async function loadState(root, payload = {}) {
52
- return loadStateForSession(root, conversationId(payload));
46
+ const sessionKey = conversationId(payload);
47
+ if (!explicitConversationId(payload))
48
+ return loadStateForSession(root, sessionKey);
49
+ const hashed = sessionStateKey(sessionKey);
50
+ const sessionState = await readJson(stateFileForSession(root, sessionKey), null).catch(() => null);
51
+ return sessionState ? { ...sessionState, _session_key: sessionState._session_key || hashed } : {};
53
52
  }
54
53
  function isNoQuestionRunning(state) {
55
54
  return (state.mode === 'RESEARCH' && state.phase === 'RESEARCH_RUNNING_NO_QUESTIONS')
@@ -96,10 +95,6 @@ export async function evaluateHookPayload(name, payload = {}, opts = {}) {
96
95
  hook: name
97
96
  }).catch(() => null);
98
97
  }
99
- // Hook decisions use persisted session state. Codex hook payloads do not
100
- // define a trusted `state` field; accepting a partial/spoofed value can hide
101
- // an active mission or bypass route gates. Explicit opts.state remains for
102
- // internal replay and focused tests.
103
98
  const loadedState = opts.state || await loadState(root, payload);
104
99
  const state = { ...loadedState, _session_key: loadedState?._session_key || sessionKey };
105
100
  const noQuestion = isNoQuestionRunning(state);
@@ -114,7 +109,11 @@ export async function evaluateHookPayload(name, payload = {}, opts = {}) {
114
109
  });
115
110
  const withNarutoDecision = (result) => ({ ...result, sksNarutoDecision });
116
111
  if (name === 'user-prompt-submit') {
117
- return withNarutoDecision(await hookUserPrompt(root, state, payload, noQuestion, sessionKey));
112
+ const result = await hookUserPrompt(root, state, payload, noQuestion, sessionKey);
113
+ return withNarutoDecision(await attachAuthoritativeSksSkillContext(root, state, payload, result));
114
+ }
115
+ if (name === 'session-start' || name === 'pre-compact' || name === 'post-compact') {
116
+ return withNarutoDecision(await hookActiveSkillContextRefresh(root, state, name));
118
117
  }
119
118
  if (name === 'pre-tool')
120
119
  return withNarutoDecision(await hookPreTool(root, state, payload, noQuestion, sessionKey));
@@ -132,192 +131,68 @@ export async function evaluateHookPayload(name, payload = {}, opts = {}) {
132
131
  }
133
132
  async function hookSubagentStart(root, state, payload = {}, sessionKey = null) {
134
133
  const artifactDir = officialSubagentArtifactDir(root, state, sessionKey);
135
- await recordAndRefreshSubagentEvidence(root, artifactDir, state, payload, 'SubagentStart').catch(() => null);
134
+ const sessionArtifactDir = officialSubagentArtifactDir(root, {}, sessionKey);
135
+ const artifactDirBlockers = [];
136
+ const artifactDirSafe = await ensureOfficialSubagentArtifactDirConfined(root, artifactDir)
137
+ .then(() => true)
138
+ .catch(() => false);
139
+ if (!artifactDirSafe)
140
+ artifactDirBlockers.push('subagent_skill_availability_artifact_dir_unsafe');
141
+ await clearSubagentSkillAvailabilityGuards(root, payload, artifactDir).catch(() => null);
136
142
  const config = await readOfficialSubagentConfig(root);
137
143
  const budget = resolveSubagentThreadBudget({ configuredMaxThreads: config.maxThreads });
138
144
  const active = subagentRouteContext(state);
139
- const routingContext = await sealedSubagentRoutingContext(artifactDir, payload);
145
+ const routingContext = artifactDirSafe ? await sealedSubagentRoutingContext(artifactDir, payload) : '';
140
146
  const resourceGuard = [
141
- `SKS subagent policy: Codex [agents].max_threads is ${budget.maxThreads}.`,
142
- 'Use max_depth=1. Subagents must not spawn subagents.',
147
+ `SKS Naruto policy: max_threads frame budget is ${budget.maxThreads} (cap, not a spawn target).`,
148
+ 'GPT-5.6 four profiles are routing lanes, not an agent-count cap.',
149
+ 'Use max_depth=1. Naruto children must not spawn children.',
143
150
  'Do not duplicate an already assigned slice.',
144
151
  'Parallel writes require disjoint paths; serialize overlapping paths.',
145
- 'Finish only your assigned slice, return a concise result, then stop so the root parent can close this thread.'
152
+ 'Finish only your assigned slice, return a concise result, then stop so the Naruto parent can close this thread.'
146
153
  ].join(' ');
147
- const additionalContext = [coreEngineeringDirectiveReferenceText(), resourceGuard, routingContext, active].filter(Boolean).join('\n\n');
148
- return { continue: true, additionalContext };
149
- }
150
- async function sealedSubagentRoutingContext(artifactDir, payload = {}) {
151
- const plan = await readJson(path.join(artifactDir, 'subagent-plan.json'), null).catch(() => null);
152
- if (!plan || plan.workflow !== 'official_codex_subagent')
153
- return '';
154
- const agentName = extractSubagentAgentName(payload);
155
- const agents = plan.agents && typeof plan.agents === 'object' ? plan.agents : {};
156
- const planned = agentName && agents[agentName] ? agents[agentName] : null;
157
- const role = agentName ? managedOfficialSubagentRoleByName(agentName) : null;
158
- const model = String(planned?.routed_model || planned?.model || role?.model || '').trim();
159
- const effort = String(planned?.routed_model_reasoning_effort || planned?.model_reasoning_effort || role?.model_reasoning_effort || '').trim();
160
- if (!agentName && !model)
161
- return '';
162
- return [
163
- 'SKS sealed child routing:',
164
- agentName ? `- custom agent: ${agentName}` : null,
165
- model ? `- model: ${model}` : null,
166
- effort ? `- model_reasoning_effort: ${effort}` : null,
167
- '- keep this sealed profile; do not retarget model/effort or spawn nested agents'
168
- ].filter(Boolean).join('\n');
169
- }
170
- function extractSubagentAgentName(payload = {}) {
171
- const candidates = [
172
- payload.agent_type,
173
- payload.agentType,
174
- payload.subagent_type,
175
- payload.subagentType,
176
- payload.agent_name,
177
- payload.agentName,
178
- payload.agent,
179
- payload.role,
180
- payload.payload?.agent_type,
181
- payload.payload?.agentType,
182
- payload.payload?.subagent_type,
183
- payload.data?.agent_type,
184
- payload.input?.agent_type
154
+ const skillNames = selectedSksSkillNamesForActiveState(state);
155
+ const resolution = skillNames.length
156
+ ? await resolveAuthoritativeSksSkillSources({ root, skillNames }).catch(() => null)
157
+ : null;
158
+ const skillBlockers = [
159
+ ...artifactDirBlockers,
160
+ ...(skillNames.length ? authoritativeSksSkillResolutionBlockers(resolution) : [])
185
161
  ];
186
- for (const value of candidates) {
187
- const name = String(value || '').trim();
188
- if (name)
189
- return name;
162
+ try {
163
+ await persistSubagentSkillAvailabilityBlocker({
164
+ root,
165
+ artifactDir,
166
+ sessionArtifactDir,
167
+ state,
168
+ payload,
169
+ blockers: skillBlockers
170
+ });
190
171
  }
191
- return '';
192
- }
193
- function subagentRouteContext(state = {}) {
194
- if (!state?.route && !state?.mode)
195
- return '';
196
- const route = state.route_command || state.route || state.mode;
197
- const mission = state.mission_id ? ` for mission ${state.mission_id}` : '';
198
- const artifacts = state.mission_id
199
- ? ` Read only the route artifacts relevant to your assigned slice under .sneakoscope/missions/${state.mission_id}/.`
200
- : '';
201
- const databaseBoundary = String(state.mode || state.route || '').toUpperCase() === 'DB'
202
- ? ' Keep database inspection read-only unless the parent supplied a separately sealed mutation contract.'
203
- : '';
204
- return `You are a child thread on ${route}${mission}. Execute only the slice assigned by the parent.${artifacts} Do not spawn or delegate other agents, wait for sibling threads, integrate sibling results, close the parent route, or author the sks.subagent-parent-summary.v1 parent result. Return a concise slice result to the parent.${databaseBoundary}`;
172
+ catch (error) {
173
+ const blocker = error instanceof Error
174
+ && error.message === 'subagent_skill_availability_blocker_artifact_write_failed'
175
+ ? 'subagent_skill_availability_blocker_artifact_write_failed'
176
+ : 'subagent_skill_availability_guard_persistence_failed';
177
+ skillBlockers.push(blocker);
178
+ }
179
+ if (artifactDirSafe) {
180
+ await recordAndRefreshSubagentEvidence(root, state, payload, 'SubagentStart', sessionKey).catch(() => null);
181
+ }
182
+ const skillContext = skillBlockers.length
183
+ ? renderSubagentSkillAvailabilityHandoff(skillBlockers)
184
+ : resolution
185
+ ? renderAuthoritativeSksSkillContext(resolution)
186
+ : '';
187
+ const additionalContext = [coreEngineeringDirectiveReferenceText(), resourceGuard, routingContext, active, skillContext].filter(Boolean).join('\n\n');
188
+ return { continue: true, additionalContext, ...(skillBlockers.length ? { silent: true } : {}) };
205
189
  }
206
190
  async function hookSubagentStop(root, state, payload = {}, sessionKey = null) {
207
- const artifactDir = officialSubagentArtifactDir(root, state, sessionKey);
208
- await recordAndRefreshSubagentEvidence(root, artifactDir, state, payload, 'SubagentStop').catch(() => null);
209
- // SubagentStop is evidence collection only. It must never reuse the parent
210
- // Stop hook's route gate or block a child thread from returning its result.
191
+ await recordAndRefreshSubagentEvidence(root, state, payload, 'SubagentStop', sessionKey).catch(() => null);
192
+ await clearSubagentSkillAvailabilityGuards(root, payload, officialSubagentArtifactDir(root, state, sessionKey)).catch(() => null);
211
193
  return { continue: true, silent: true };
212
194
  }
213
- function officialSubagentArtifactDir(root, state = {}, sessionKey = null) {
214
- if (state?.mission_id)
215
- return missionDir(root, state.mission_id);
216
- return path.join(root, '.sneakoscope', 'state', 'subagents', sha256(String(sessionKey || 'default')).slice(0, 32));
217
- }
218
- async function recordAndRefreshSubagentEvidence(root, artifactDir, state, payload, eventName) {
219
- return withOfficialSubagentLifecycleLock(artifactDir, async () => {
220
- if (await officialSubagentPreparationInProgress(artifactDir))
221
- return null;
222
- const plan = await readJson(path.join(artifactDir, 'subagent-plan.json'), {});
223
- const workflowRunId = String(plan?.workflow_run_id || state?.official_subagent_run_id || '').trim();
224
- const stateRunId = String(state?.official_subagent_run_id || '').trim();
225
- if (!workflowRunId || (stateRunId && stateRunId !== workflowRunId))
226
- return null;
227
- const terminalGate = plan?.workflow === 'official_codex_subagent'
228
- ? await readJson(path.join(artifactDir, 'naruto-gate.json'), null).catch(() => null)
229
- : null;
230
- const terminalRunId = String(terminalGate?.workflow_run_id || '').trim();
231
- if (workflowRunId
232
- && terminalRunId === workflowRunId
233
- && terminalGate?.passed === true
234
- && terminalGate?.terminal === true) {
235
- return null;
236
- }
237
- const normalizedInputEvent = normalizeSubagentEvent(payload, eventName);
238
- const explicitRunId = normalizedInputEvent?.run_id || null;
239
- if (explicitRunId && explicitRunId !== workflowRunId)
240
- return null;
241
- let boundRunId = explicitRunId;
242
- if (!boundRunId && eventName === 'SubagentStop' && normalizedInputEvent?.thread_id) {
243
- const priorEvents = await readSubagentEvents(artifactDir);
244
- const matchingStartRuns = [...new Set(priorEvents
245
- .filter((row) => row.event_name === 'SubagentStart'
246
- && row.thread_id === normalizedInputEvent.thread_id
247
- && Boolean(row.run_id))
248
- .map((row) => row.run_id))];
249
- boundRunId = matchingStartRuns.length === 1
250
- ? matchingStartRuns[0] || null
251
- : null;
252
- if (!boundRunId)
253
- return null;
254
- }
255
- else if (!boundRunId) {
256
- boundRunId = workflowRunId || null;
257
- }
258
- const eventPayload = boundRunId && payload && typeof payload === 'object' && !Array.isArray(payload)
259
- ? { ...payload, workflow_run_id: boundRunId }
260
- : payload;
261
- const event = await recordSubagentEvent(artifactDir, eventPayload, eventName);
262
- if (!event)
263
- return null;
264
- const zellijTelemetry = await recordOfficialSubagentZellijTelemetry({
265
- root,
266
- routeMissionId: plan?.mission_id || state?.mission_id || null,
267
- event,
268
- payload: eventPayload,
269
- plan
270
- }).catch(async (error) => {
271
- await appendJsonl(path.join(artifactDir, 'zellij-telemetry-warnings.jsonl'), {
272
- ts: nowIso(),
273
- warning: 'official_subagent_zellij_telemetry_failed',
274
- event_name: eventName,
275
- thread_id: event.thread_id,
276
- error: String(error?.message || error)
277
- }).catch(() => null);
278
- return null;
279
- });
280
- if (zellijTelemetry?.blocker) {
281
- await appendJsonl(path.join(artifactDir, 'zellij-telemetry-warnings.jsonl'), {
282
- ts: nowIso(),
283
- warning: 'official_subagent_zellij_telemetry_incomplete',
284
- event_name: eventName,
285
- thread_id: event.thread_id,
286
- blocker: zellijTelemetry.blocker,
287
- failed_mission_ids: 'failed_mission_ids' in zellijTelemetry ? zellijTelemetry.failed_mission_ids : []
288
- }).catch(() => null);
289
- }
290
- const lifecycle = await refreshSubagentWaveLifecycle(artifactDir, { plan, event }).catch(() => null);
291
- const refreshedPlan = lifecycle ? { ...plan, wave_lifecycle: lifecycle } : plan;
292
- const existing = await readJson(path.join(artifactDir, SUBAGENT_EVIDENCE_FILENAME), {});
293
- const parentSummary = await readJson(path.join(artifactDir, SUBAGENT_PARENT_SUMMARY_FILENAME), null);
294
- const countTarget = effectiveSubagentTarget(refreshedPlan, lifecycle?.cumulative_started || 0);
295
- const requestedSubagents = countTarget.requestedSubagents
296
- || Number(state?.requested_subagents || existing?.requested_subagents || 0);
297
- if (!Number.isFinite(requestedSubagents) || requestedSubagents < 1)
298
- return event;
299
- const evidence = await writeSubagentEvidence(artifactDir, {
300
- requestedSubagents,
301
- countPolicy: countTarget.countPolicy,
302
- targetSubagents: countTarget.targetSubagents,
303
- parentSummary,
304
- parentSummaryPresent: parentSummary !== null,
305
- workflowStatus: 'running',
306
- preparationOnly: false,
307
- runId: workflowRunId || null,
308
- additionalBlockers: Array.isArray(plan?.config_blockers)
309
- ? [
310
- ...plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`),
311
- ...subagentCountContractBlockers(refreshedPlan, lifecycle?.cumulative_started || 0)
312
- ]
313
- : subagentCountContractBlockers(refreshedPlan, lifecycle?.cumulative_started || 0)
314
- });
315
- return event;
316
- });
317
- }
318
195
  async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = null) {
319
- // A receipt is scoped to exactly one submitted turn. Every later prompt,
320
- // including Codex App git/settings events, invalidates it before returning.
321
196
  await clearLightTurnStopBypass(root, { sessionKey }).catch(() => undefined);
322
197
  const submittedPrompt = stripVisibleDecisionAnswerBlocks(extractUserPrompt(payload));
323
198
  const explicitSession = explicitConversationId(payload);
@@ -346,6 +221,23 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
346
221
  }
347
222
  const parentLaunchMissionId = activeNarutoParentLaunchMissionId();
348
223
  if (parentLaunchMissionId) {
224
+ const parentSkillNames = await standaloneParentManagedSkillNames(root, parentLaunchMissionId, state);
225
+ const skillAdmission = await authoritativeSksSkillAdmission(root, parentSkillNames);
226
+ if (skillAdmission.blocked)
227
+ return skillAdmission.blocked;
228
+ const parentHostCapability = await claimStandaloneParentHostCapabilityRuntime({
229
+ root,
230
+ missionId: parentLaunchMissionId,
231
+ sessionScope: sessionKey,
232
+ explicitSession
233
+ });
234
+ if (parentHostCapability.blocker) {
235
+ return {
236
+ decision: 'block',
237
+ permissionDecision: 'deny',
238
+ reason: `SKS blocked the standalone Naruto parent before host tool execution: ${parentHostCapability.blocker}`
239
+ };
240
+ }
349
241
  const attachedState = {
350
242
  ...state,
351
243
  mission_id: parentLaunchMissionId,
@@ -353,8 +245,11 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
353
245
  route: 'Naruto',
354
246
  route_command: '$Naruto',
355
247
  route_closed: false,
248
+ required_skills: parentSkillNames,
356
249
  subagents_required: true,
357
- native_sessions_required: false
250
+ native_sessions_required: false,
251
+ official_subagent_run_id: parentHostCapability.workflowRunId || state?.official_subagent_run_id || null,
252
+ session_scope: sessionKey
358
253
  };
359
254
  await setCurrent(root, attachedState, { sessionKey, replace: true });
360
255
  const activeContext = await activeRouteContext(root, attachedState);
@@ -400,6 +295,9 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
400
295
  return { continue: true, silent: true, sksTaskProfile: taskProfile };
401
296
  }
402
297
  if (!explicitCommand && !clarificationPending && !madConfirmationPrompt && !activeContinuation && lightRoute?.id === 'Answer') {
298
+ const skillAdmission = await authoritativeSksSkillAdmission(root, lightRoute.requiredSkills || ['answer', 'honest-mode']);
299
+ if (skillAdmission.blocked)
300
+ return skillAdmission.blocked;
403
301
  const turnId = hookTurnId(payload);
404
302
  if (turnId) {
405
303
  await armLightTurnStopBypass(root, {
@@ -428,7 +326,6 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
428
326
  systemMessage: visibleHookMessage('user-prompt-submit', activeContext)
429
327
  };
430
328
  }
431
- await maybeReconcileProjectSkillsPreflight(root).catch(() => null);
432
329
  const updateContext = '';
433
330
  const command = dollarCommand(prompt);
434
331
  const route = routePrompt(prompt);
@@ -439,6 +336,10 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
439
336
  systemMessage: `SKS: ${route.command} git action bypassed pipeline route gates.`
440
337
  };
441
338
  }
339
+ const skillAdmission = await authoritativeSksSkillAdmission(root, managedSkillNamesForPrompt(route, prompt));
340
+ if (skillAdmission.blocked)
341
+ return skillAdmission.blocked;
342
+ await maybeReconcileProjectSkillsPreflight(root).catch(() => null);
442
343
  const bypassActiveRoute = routeBypassesActiveContext(route);
443
344
  const goalOverlay = activeGoalOverlayContext(state, route);
444
345
  const prepareFreshRoute = shouldPrepareFreshRouteOnActivePrompt(prompt, route, {
@@ -484,54 +385,28 @@ async function hookUserPrompt(root, state, payload, noQuestion, sessionKey = nul
484
385
  reason: 'SKS no-question/no-interruption mode is active. User prompt has been queued until the run completes.'
485
386
  };
486
387
  }
487
- function routeBypassesActiveContext(route = null) {
488
- return ['DFix', 'Answer', 'Commit', 'CommitAndPush', 'Wiki', 'ComputerUse'].includes(String(route?.id || ''));
489
- }
490
- function routeIsGitOnly(route = null) {
491
- return ['Commit', 'CommitAndPush'].includes(String(route?.id || ''));
492
- }
493
- function shouldPrepareFreshRouteOnActivePrompt(prompt, route = null, opts = {}) {
494
- if (!route || opts.command || opts.bypassActiveRoute || opts.goalOverlay)
495
- return false;
496
- if (looksLikeActiveContinuationPrompt(prompt))
497
- return false;
498
- return routeRequiresSubagents(route, prompt);
499
- }
500
- function isClarificationAwaiting(state = {}) {
501
- const phase = String(state.phase || '');
502
- const stopGate = String(state.stop_gate || '');
503
- const gateAwaiting = phase.includes('CLARIFICATION_AWAITING_ANSWERS') || stopGate === 'clarification-gate';
504
- if (!gateAwaiting)
505
- return false;
506
- if (!state?.mission_id)
507
- return false;
508
- if (state.ambiguity_gate_required !== true || state.ambiguity_gate_passed === true)
509
- return false;
510
- return Boolean(state.clarification_required || state.implementation_allowed === false);
511
- }
512
- function activeNarutoParentLaunchMissionId() {
513
- return process.env.SKS_NARUTO_PARENT_LAUNCH === '1'
514
- ? String(process.env.SKS_NARUTO_PARENT_MISSION_ID || '').trim()
515
- : '';
516
- }
517
- function isBlockingClarificationAwaiting(state = {}) {
518
- return isClarificationAwaiting(state);
519
- }
520
- function looksLikeClarificationCancel(prompt = '') {
521
- return /^(cancel|reset|restart|new mission|새로|취소|중단|리셋|다시 시작)\b/i.test(String(prompt || '').trim());
522
- }
523
- function activeGoalOverlayContext(state = {}, route = null) {
524
- if (state.mode !== 'GOAL' || !state.mission_id)
525
- return '';
526
- if (!route || route.id === 'Goal' || route.id === 'DFix' || route.id === 'Answer')
527
- return '';
528
- return [
529
- `Legacy SKS Goal state ${state.mission_id} is non-authoritative and must not be updated.`,
530
- `Do not let it hijack this new ${route.command || '$SKS'} prompt. The newly prepared route mission and gate are authoritative for this turn.`,
531
- 'Codex native Goal is the only persisted Goal owner; use native controls only when the user explicitly returns to Goal.'
532
- ].join('\n');
533
- }
534
388
  async function hookPreTool(root, state, payload, noQuestion, sessionKey = null) {
389
+ const skillAvailabilityBlock = await subagentSkillAvailabilityPreToolBlockReason(root, payload, officialSubagentArtifactDir(root, state, sessionKey), {
390
+ missionId: state?.mission_id,
391
+ workflowRunId: state?.official_subagent_run_id
392
+ }).catch((error) => {
393
+ const code = error instanceof Error && error.message === 'subagent_skill_availability_guard_invalid'
394
+ ? 'subagent_skill_availability_guard_invalid'
395
+ : 'subagent_skill_availability_guard_check_failed';
396
+ return `SKS blocked this child tool call because managed skill availability failed (${code}). Return the blocker to the root parent without using tools.`;
397
+ });
398
+ if (skillAvailabilityBlock) {
399
+ return { decision: 'block', permissionDecision: 'deny', reason: skillAvailabilityBlock };
400
+ }
401
+ const skillRefresh = await activeAuthoritativeSksSkillRefresh(root, state);
402
+ if (skillRefresh.blocked) {
403
+ return {
404
+ decision: 'block',
405
+ permissionDecision: 'deny',
406
+ reason: skillRefresh.blocked.reason,
407
+ systemMessage: skillRefresh.blocked.systemMessage
408
+ };
409
+ }
535
410
  if (needsMutationSafetyCheck(payload)) {
536
411
  const madSksImmutableDecision = await checkMadSksImmutableModification(root, state, payload);
537
412
  if (madSksImmutableDecision.action === 'block') {
@@ -555,12 +430,18 @@ async function hookPreTool(root, state, payload, noQuestion, sessionKey = null)
555
430
  return agentRecursionDecision;
556
431
  if (noQuestion && looksInteractiveCommand(command))
557
432
  return { decision: 'block', reason: interactiveCommandReason(command) };
433
+ const hostCapabilityDecision = await enforceHostCapabilityPreTool(root, state, payload, sessionKey);
434
+ if (hostCapabilityDecision && hostCapabilityDecision.continue !== true)
435
+ return hostCapabilityDecision;
558
436
  const waveGuidance = await parentWaveGuidanceContext(root, state, sessionKey).catch(() => '');
559
- if (waveGuidance) {
437
+ const additionalContext = [skillRefresh.context, waveGuidance].filter(Boolean).join('\n\n');
438
+ if (additionalContext) {
560
439
  return {
561
440
  continue: true,
562
- additionalContext: waveGuidance,
563
- systemMessage: visibleHookMessage('pre-tool', 'SKS Naruto wave lifecycle requires root-parent follow-up.')
441
+ additionalContext,
442
+ ...(waveGuidance
443
+ ? { systemMessage: visibleHookMessage('pre-tool', 'SKS Naruto wave lifecycle requires root-parent follow-up.') }
444
+ : { silent: true })
564
445
  };
565
446
  }
566
447
  return { continue: true };
@@ -573,15 +454,14 @@ async function parentWaveGuidanceContext(root, state = {}, sessionKey = null) {
573
454
  || state?.subagents_required === true;
574
455
  if (!isNaruto)
575
456
  return '';
576
- // Child worker hooks must not receive parent wave spawn instructions.
577
457
  if (agentWorkerHookContext(state, {}))
578
458
  return '';
579
459
  const artifactDir = officialSubagentArtifactDir(root, state, sessionKey);
580
460
  const plan = await readJson(path.join(artifactDir, 'subagent-plan.json'), null).catch(() => null);
581
- if (!plan || plan.workflow !== 'official_codex_subagent')
582
- return '';
583
- const lifecycle = plan.wave_lifecycle || null;
584
- const guidance = lifecycle?.parent_guidance || buildWaveParentGuidance(lifecycle);
461
+ const guidance = buildBoundWaveParentGuidance(plan, {
462
+ missionId: state?.mission_id,
463
+ workflowRunId: state?.official_subagent_run_id
464
+ });
585
465
  if (!guidance?.required)
586
466
  return '';
587
467
  return renderWaveParentGuidance(guidance);
@@ -615,6 +495,7 @@ function agentWorkerHookContext(state = {}, payload = {}) {
615
495
  async function hookPostTool(root, state, payload, noQuestion, sessionKey = null) {
616
496
  state = { ...state, _session_key: state?._session_key || sessionKey };
617
497
  await Promise.all([
498
+ recordHostCapabilityPostTool(root, state, payload, sessionKey).catch(() => null),
618
499
  recordMadSksSqlPlanePostToolLifecycle(root, state, payload).catch(() => null),
619
500
  recordContext7Evidence(root, state, payload).catch(() => null),
620
501
  recordSubagentEvidence(root, state, payload).catch(() => null),
@@ -630,6 +511,134 @@ async function hookPostTool(root, state, payload, noQuestion, sessionKey = null)
630
511
  }
631
512
  return { continue: true };
632
513
  }
514
+ async function enforceHostCapabilityPreTool(root, state = {}, payload = {}, sessionKey = null) {
515
+ const tool = acasHostToolName(payload.tool_name);
516
+ if (!tool)
517
+ return null;
518
+ if (explicitlyDeniedHostCapabilityTool(tool)) {
519
+ return {
520
+ decision: 'block',
521
+ permissionDecision: 'deny',
522
+ reason: `SKS denied acas-tools.${tool}; this tool is explicitly denied for model execution.`
523
+ };
524
+ }
525
+ const context = await loadHostCapabilityHookContext(root, state, payload, sessionKey);
526
+ if (!context) {
527
+ return {
528
+ decision: 'block',
529
+ permissionDecision: 'deny',
530
+ reason: 'SKS denied this acas-tools call because it has no valid task-scoped Naruto mission, run, and session context.'
531
+ };
532
+ }
533
+ if (!context.binding) {
534
+ return {
535
+ decision: 'block',
536
+ permissionDecision: 'deny',
537
+ reason: `SKS denied this acas-tools call because the current Naruto mission has no valid task-scoped host capability runtime: ${context.blocker}`
538
+ };
539
+ }
540
+ const observation = sanitizeHostCapabilityPreToolUse(context.binding.runtime, payload);
541
+ if (!observation) {
542
+ return {
543
+ decision: 'block',
544
+ permissionDecision: 'deny',
545
+ reason: 'SKS denied this acas-tools call because its official PreToolUse identity fields are invalid.'
546
+ };
547
+ }
548
+ let authorization = {
549
+ decision: observation.decision,
550
+ blocker: observation.blocker
551
+ };
552
+ try {
553
+ await withFileLock({
554
+ lockPath: path.join(context.dir, '.host-capability-hooks.lock'),
555
+ timeoutMs: 5_000,
556
+ staleMs: 60_000
557
+ }, async () => {
558
+ const current = await readJson(path.join(context.dir, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME), null).catch(() => null);
559
+ const result = authorizeAndMergeHostCapabilityPreToolObservation({
560
+ binding: context.binding,
561
+ current,
562
+ observation
563
+ });
564
+ authorization = result;
565
+ await writeJsonAtomic(path.join(context.dir, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME), result.observations);
566
+ });
567
+ }
568
+ catch {
569
+ return {
570
+ decision: 'block',
571
+ permissionDecision: 'deny',
572
+ reason: 'SKS denied this acas-tools call because its bounded PreToolUse evidence could not be persisted.'
573
+ };
574
+ }
575
+ if (authorization.decision === 'denied') {
576
+ return {
577
+ decision: 'block',
578
+ permissionDecision: 'deny',
579
+ reason: authorization.blocker
580
+ ? `SKS denied acas-tools.${observation.tool}; ${authorization.blocker}.`
581
+ : `SKS denied acas-tools.${observation.tool}; it is outside runtime.allowed_tool_names for this mission, run, and session.`
582
+ };
583
+ }
584
+ return { continue: true };
585
+ }
586
+ async function recordHostCapabilityPostTool(root, state = {}, payload = {}, sessionKey = null) {
587
+ if (!acasHostToolName(payload.tool_name))
588
+ return null;
589
+ const context = await loadHostCapabilityHookContext(root, state, payload, sessionKey);
590
+ if (!context?.binding)
591
+ return null;
592
+ const observation = sanitizeHostCapabilityPostToolUse(payload);
593
+ if (!observation)
594
+ return null;
595
+ return withFileLock({
596
+ lockPath: path.join(context.dir, '.host-capability-hooks.lock'),
597
+ timeoutMs: 5_000,
598
+ staleMs: 60_000
599
+ }, async () => {
600
+ const current = await readJson(path.join(context.dir, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME), null).catch(() => null);
601
+ const next = mergeHostCapabilityPostToolObservation({
602
+ binding: context.binding,
603
+ current,
604
+ observation
605
+ });
606
+ const evidence = buildHostCapabilityEvidenceFromHookObservations({
607
+ binding: context.binding,
608
+ observations: next
609
+ });
610
+ await Promise.all([
611
+ writeJsonAtomic(path.join(context.dir, HOST_CAPABILITY_HOOK_OBSERVATIONS_FILENAME), next),
612
+ writeJsonAtomic(path.join(context.dir, HOST_CAPABILITY_HOOK_EVIDENCE_FILENAME), evidence)
613
+ ]);
614
+ return evidence;
615
+ });
616
+ }
617
+ async function loadHostCapabilityHookContext(root, state = {}, payload = {}, sessionKey = null) {
618
+ const missionId = String(state?.mission_id || '').trim();
619
+ const workflowRunId = String(state?.official_subagent_run_id || '').trim();
620
+ const payloadSession = String(payload?.session_id || '').trim();
621
+ const expectedSession = String(state?.session_scope || sessionKey || '').trim();
622
+ const isNaruto = String(state?.mode || '').toUpperCase() === 'NARUTO'
623
+ || String(state?.route || state?.route_command || '').replace(/^\$/, '').toUpperCase() === 'NARUTO'
624
+ || state?.subagents_required === true;
625
+ if (!isNaruto || !missionId || !workflowRunId || !payloadSession || !expectedSession)
626
+ return null;
627
+ if (payloadSession !== expectedSession || (sessionKey && String(sessionKey) !== payloadSession))
628
+ return null;
629
+ const dir = missionDir(root, missionId);
630
+ const [raw, plan] = await Promise.all([
631
+ readJson(path.join(dir, HOST_CAPABILITY_HOOK_RUNTIME_FILENAME), null).catch(() => null),
632
+ readJson(path.join(dir, 'subagent-plan.json'), null).catch(() => null)
633
+ ]);
634
+ const request = requestHostCapabilities(plan?.goal || state?.prompt || '');
635
+ return { dir, ...resolveHostCapabilityHookRuntimeBinding(raw, {
636
+ missionId,
637
+ workflowRunId,
638
+ sessionScope: payloadSession,
639
+ request
640
+ }) };
641
+ }
633
642
  function needsMutationSafetyCheck(payload = {}) {
634
643
  const toolName = String(payload.tool_name || payload.toolName || payload.name || payload.tool?.name || '');
635
644
  const knownReadOnly = /^(Read|Grep|Glob|LS|TodoRead|WebFetch|WebSearch|BashOutput|NotebookRead|ListMcpResources|ReadMcpResource)$/i;
@@ -874,290 +883,6 @@ async function hookStop(root, state, payload, noQuestion, sessionKey = null) {
874
883
  reason: 'SKS no-question run is not done. Continue autonomously, fix failing checks, update the active gate file, and do not ask the user.'
875
884
  };
876
885
  }
877
- export async function refreshOfficialSubagentCompletionArtifacts(root, state = {}, parentSummary = '', sessionKey = null) {
878
- const id = state?.mission_id;
879
- if (!id)
880
- return null;
881
- const dir = missionDir(root, id);
882
- const snapshot = await withOfficialSubagentLifecycleLock(dir, () => refreshOfficialSubagentCompletionArtifactsLocked(root, state, parentSummary, sessionKey, dir));
883
- if (snapshot?.terminal?.passed === true) {
884
- await finalizeNarutoTerminalProof(root, state, sessionKey, dir, snapshot.terminal);
885
- }
886
- return snapshot?.evidence ?? snapshot;
887
- }
888
- async function refreshOfficialSubagentCompletionArtifactsLocked(root, state, parentSummary, sessionKey, dir) {
889
- if (await officialSubagentPreparationInProgress(dir))
890
- return null;
891
- const id = state?.mission_id;
892
- const plan = await readJson(path.join(dir, 'subagent-plan.json'), null).catch(() => null);
893
- if (plan?.workflow !== 'official_codex_subagent')
894
- return null;
895
- const workflowRunId = String(plan.workflow_run_id || state.official_subagent_run_id || '').trim();
896
- if (!workflowRunId || String(state.official_subagent_run_id || '').trim() !== workflowRunId)
897
- return null;
898
- const [existingGate, existingSummary, rawExistingEvidence, existingParentSummary] = await Promise.all([
899
- readJson(path.join(dir, 'naruto-gate.json'), null).catch(() => null),
900
- readJson(path.join(dir, 'naruto-summary.json'), null).catch(() => null),
901
- readJson(path.join(dir, SUBAGENT_EVIDENCE_FILENAME), null).catch(() => null),
902
- readJson(path.join(dir, SUBAGENT_PARENT_SUMMARY_FILENAME), null).catch(() => null)
903
- ]);
904
- const existingEvidence = normalizeLegacySubagentCountFields(rawExistingEvidence, plan);
905
- if (completeNarutoTerminalBundle({
906
- workflowRunId,
907
- gate: existingGate,
908
- summary: existingSummary,
909
- evidence: existingEvidence,
910
- parentSummary: existingParentSummary
911
- })) {
912
- return {
913
- evidence: existingEvidence,
914
- terminal: { passed: true, missionId: state.mission_id, workflowRunId, gate: existingGate }
915
- };
916
- }
917
- const events = await readSubagentEvents(dir);
918
- const lifecycle = await refreshSubagentWaveLifecycle(dir, { plan }).catch(() => plan.wave_lifecycle || null);
919
- const refreshedPlan = lifecycle ? { ...plan, wave_lifecycle: lifecycle } : plan;
920
- const countTarget = effectiveSubagentTarget(refreshedPlan, lifecycle?.cumulative_started || 0);
921
- const requestedSubagents = countTarget.requestedSubagents || Number(state.requested_subagents || 0);
922
- const runBoundParentSummary = bindTrustworthySubagentParentSummaryToRun(parentSummary, workflowRunId);
923
- const effectiveParentSummary = await persistOrReuseTrustworthySubagentParentSummary(dir, runBoundParentSummary, {
924
- workflowStatus: 'parent_completed',
925
- runId: workflowRunId || null
926
- });
927
- const structuredParentSummary = normalizeSubagentParentSummary(effectiveParentSummary);
928
- const evidence = await writeSubagentEvidence(dir, {
929
- requestedSubagents,
930
- countPolicy: countTarget.countPolicy,
931
- targetSubagents: countTarget.targetSubagents,
932
- events,
933
- parentSummary: effectiveParentSummary,
934
- workflowStatus: 'parent_completed',
935
- preparationOnly: false,
936
- runId: workflowRunId || null,
937
- additionalBlockers: Array.isArray(plan.config_blockers)
938
- ? [
939
- ...plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`),
940
- ...subagentCountContractBlockers(refreshedPlan, lifecycle?.cumulative_started || 0)
941
- ]
942
- : subagentCountContractBlockers(refreshedPlan, lifecycle?.cumulative_started || 0)
943
- });
944
- if (structuredParentSummary.trustworthy) {
945
- const parentTelemetry = await recordOfficialSubagentParentOutcomesTelemetry({
946
- root,
947
- routeMissionId: id,
948
- parentSummary: structuredParentSummary.raw,
949
- plan: refreshedPlan
950
- }).catch(async (error) => {
951
- await appendJsonl(path.join(dir, 'zellij-telemetry-warnings.jsonl'), {
952
- ts: nowIso(),
953
- warning: 'official_subagent_parent_outcome_telemetry_failed',
954
- error: String(error?.message || error)
955
- }).catch(() => null);
956
- return null;
957
- });
958
- if (parentTelemetry?.blocker) {
959
- await appendJsonl(path.join(dir, 'zellij-telemetry-warnings.jsonl'), {
960
- ts: nowIso(),
961
- warning: 'official_subagent_parent_outcome_telemetry_incomplete',
962
- blocker: parentTelemetry.blocker,
963
- failed_mission_ids: 'failed_mission_ids' in parentTelemetry ? parentTelemetry.failed_mission_ids : [],
964
- skipped_thread_ids: 'skipped_thread_ids' in parentTelemetry ? parentTelemetry.skipped_thread_ids : []
965
- }).catch(() => null);
966
- }
967
- }
968
- const isNaruto = String(state?.mode || '').toUpperCase() === 'NARUTO'
969
- || String(state?.route || state?.route_command || '').replace(/^\$/, '').toUpperCase() === 'NARUTO';
970
- if (!isNaruto) {
971
- await updateCurrentIfMissionAndRun(root, id, workflowRunId, {
972
- subagents_spawned: evidence.started_threads > 0,
973
- subagents_reported: evidence.completed_threads > 0,
974
- subagents_verified: evidence.ok,
975
- subagent_evidence_file: SUBAGENT_EVIDENCE_FILENAME,
976
- parent_summary_present: evidence.parent_summary_present
977
- }, { sessionKey: sessionKey || state._session_key });
978
- return { evidence, terminal: null };
979
- }
980
- const previousGate = existingGate || {};
981
- const parentModel = plan.observed_parent_model || state.observed_parent_model || null;
982
- const parentModelMismatch = previousGate.parent_model_match === false || observedParentModelMismatch(parentModel, NARUTO_PARENT_MODEL);
983
- const blockers = [...new Set([
984
- ...evidence.blockers,
985
- ...(Array.isArray(previousGate.config_blockers) ? previousGate.config_blockers.map(String) : []),
986
- ...(Array.isArray(plan.config_blockers) ? plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`) : []),
987
- ...(parentModelMismatch ? [`parent_model_mismatch:${String(parentModel || 'unknown')}`] : [])
988
- ])];
989
- const ssotValidation = validateSsotGuardArtifact(await readJson(path.join(dir, SSOT_GUARD_ARTIFACT), null).catch(() => null));
990
- blockers.push(...ssotValidation.issues.map((issue) => `${SSOT_GUARD_ARTIFACT}:${issue}`));
991
- const uniqueBlockers = [...new Set(blockers)];
992
- const passed = evidence.ok === true && ssotValidation.ok && uniqueBlockers.length === 0;
993
- const updatedAt = nowIso();
994
- const summary = {
995
- schema: 'sks.naruto-subagent-workflow.v1',
996
- ok: passed,
997
- completion_evidence: passed,
998
- workflow: 'official_codex_subagent',
999
- workflow_run_id: workflowRunId || null,
1000
- mission_id: id,
1001
- route: '$Naruto',
1002
- status: passed ? 'completed' : evidence.status,
1003
- parent: {
1004
- model: NARUTO_PARENT_MODEL,
1005
- model_reasoning_effort: NARUTO_PARENT_EFFORT,
1006
- observed_model: parentModel,
1007
- observed_model_match: parentModel ? !parentModelMismatch : null
1008
- },
1009
- requested_subagents: requestedSubagents,
1010
- count_policy: evidence.count_policy,
1011
- target_subagents: evidence.target_subagents,
1012
- wave_lifecycle: lifecycle,
1013
- max_threads: Number(plan.max_threads || state.subagent_max_threads || 0),
1014
- max_depth: 1,
1015
- started_subagents: evidence.started_threads,
1016
- completed_subagents: evidence.completed_threads,
1017
- failed_subagents: evidence.failed_threads,
1018
- agents: officialSubagentRolePlan(),
1019
- verification: {
1020
- budget: plan.verification?.budget || plan.verification_budget || 'affected',
1021
- checks: Array.isArray(plan.verification?.checks)
1022
- ? plan.verification.checks
1023
- : Array.isArray(plan.verification_checks)
1024
- ? plan.verification_checks
1025
- : []
1026
- },
1027
- parent_summary_present: evidence.parent_summary_present,
1028
- parent_summary: structuredParentSummary.summary,
1029
- parent_thread_outcomes: structuredParentSummary.raw?.thread_outcomes || [],
1030
- subagent_evidence: SUBAGENT_EVIDENCE_FILENAME,
1031
- blockers: uniqueBlockers,
1032
- updated_at: updatedAt
1033
- };
1034
- await writeJsonAtomic(path.join(dir, 'naruto-summary.json'), summary);
1035
- const gate = await writeNarutoGate(dir, {
1036
- missionId: id,
1037
- workflowRunId,
1038
- evidence,
1039
- passed,
1040
- blockers: uniqueBlockers,
1041
- configBlockers: [
1042
- ...(Array.isArray(previousGate.config_blockers) ? previousGate.config_blockers.map(String) : []),
1043
- ...(Array.isArray(plan.config_blockers) ? plan.config_blockers.map((item) => `official_subagent_config:${String(item)}`) : [])
1044
- ],
1045
- observedParentModel: parentModel,
1046
- parentModelMatch: parentModel ? !parentModelMismatch : null
1047
- });
1048
- await updateCurrentIfMissionAndRun(root, id, workflowRunId, {
1049
- subagents_spawned: evidence.started_threads > 0,
1050
- subagents_reported: evidence.completed_threads > 0,
1051
- subagents_verified: evidence.ok,
1052
- subagent_evidence_file: SUBAGENT_EVIDENCE_FILENAME,
1053
- parent_summary_present: evidence.parent_summary_present
1054
- }, { sessionKey: sessionKey || state._session_key });
1055
- return {
1056
- evidence,
1057
- terminal: passed ? { passed: true, missionId: id, workflowRunId, gate } : null
1058
- };
1059
- }
1060
- function completeNarutoTerminalBundle(input) {
1061
- const runId = String(input.workflowRunId || '').trim();
1062
- const parent = normalizeSubagentParentSummary(input.parentSummary);
1063
- return Boolean(runId
1064
- && input.gate?.workflow_run_id === runId
1065
- && input.gate?.passed === true
1066
- && input.gate?.terminal === true
1067
- && input.summary?.workflow_run_id === runId
1068
- && input.summary?.ok === true
1069
- && input.summary?.status === 'completed'
1070
- && input.evidence?.run_id === runId
1071
- && input.evidence?.ok === true
1072
- && input.evidence?.status === 'completed'
1073
- && parent.trustworthy
1074
- && parent.status === 'completed'
1075
- && parent.run_id === runId);
1076
- }
1077
- async function finalizeNarutoTerminalProof(root, state, sessionKey, dir, terminal) {
1078
- // Lock order is finalization -> lifecycle -> session state. Preparation starts
1079
- // at lifecycle -> session state and never acquires the finalization lock.
1080
- await withFileLock({
1081
- lockPath: path.join(dir, '.naruto-finalize.lock'),
1082
- timeoutMs: 5_000,
1083
- staleMs: 30_000
1084
- }, () => withOfficialSubagentLifecycleLock(dir, async () => {
1085
- if (await officialSubagentPreparationInProgress(dir))
1086
- return;
1087
- const [currentPlan, currentGate] = await Promise.all([
1088
- readJson(path.join(dir, 'subagent-plan.json'), null).catch(() => null),
1089
- readJson(path.join(dir, 'naruto-gate.json'), null).catch(() => null)
1090
- ]);
1091
- if (String(currentPlan?.workflow_run_id || '').trim() !== terminal.workflowRunId
1092
- || String(currentGate?.workflow_run_id || '').trim() !== terminal.workflowRunId
1093
- || currentGate?.passed !== true
1094
- || currentGate?.terminal !== true)
1095
- return;
1096
- let proofStatus = await currentNarutoProofStatus(root, terminal.missionId, terminal.workflowRunId, state);
1097
- if (!proofStatus.valid) {
1098
- const finalized = await maybeFinalizeRoute(root, {
1099
- missionId: terminal.missionId,
1100
- route: '$Naruto',
1101
- gateFile: 'naruto-gate.json',
1102
- gate: currentGate,
1103
- artifacts: [
1104
- 'subagent-plan.json',
1105
- 'subagent-events.jsonl',
1106
- SUBAGENT_PARENT_SUMMARY_FILENAME,
1107
- SUBAGENT_EVIDENCE_FILENAME,
1108
- 'naruto-summary.json',
1109
- 'naruto-gate.json'
1110
- ],
1111
- claims: [{ id: 'naruto-official-subagent-completion', status: 'supported', evidence: 'naruto-gate.json' }],
1112
- agents: true
1113
- });
1114
- if (finalized?.ok !== true) {
1115
- throw new Error(`naruto_terminal_proof_finalize_failed:${String(finalized?.validation?.issues?.join(',') || finalized?.status || 'unknown')}`);
1116
- }
1117
- proofStatus = await currentNarutoProofStatus(root, terminal.missionId, terminal.workflowRunId, state);
1118
- }
1119
- if (!proofStatus.valid)
1120
- throw new Error('naruto_terminal_proof_invalid_after_finalize');
1121
- await closeWorkOrderLedgerForRouteResult(dir, { ok: true });
1122
- await invalidateReflectionForNarutoProofOnce(root, state, sessionKey, terminal.workflowRunId, proofStatus.digest);
1123
- }));
1124
- }
1125
- async function currentNarutoProofStatus(root, missionId, workflowRunId, state) {
1126
- const validation = await validateRouteCompletionProof(root, {
1127
- missionId,
1128
- route: '$Naruto',
1129
- state: {
1130
- ...state,
1131
- mission_id: missionId,
1132
- subagents_required: true,
1133
- official_subagent_run_id: workflowRunId
1134
- }
1135
- }).catch(() => null);
1136
- const proofRunId = String(validation?.proof?.evidence?.route_gate?.workflow_run_id || '').trim();
1137
- const proofText = await readText(path.join(root, '.sneakoscope', 'missions', missionId, 'completion-proof.json'), '').catch(() => '');
1138
- return {
1139
- valid: validation?.ok === true && proofRunId === workflowRunId,
1140
- proof: validation?.proof || null,
1141
- digest: proofText ? `sha256:${sha256(proofText)}` : null
1142
- };
1143
- }
1144
- async function invalidateReflectionForNarutoProofOnce(root, state, sessionKey, workflowRunId, proofDigest) {
1145
- if (!workflowRunId || !proofDigest)
1146
- return;
1147
- const resolvedSessionKey = sessionKey || state?._session_key;
1148
- await updateCurrentIfMissionAndRun(root, state?.mission_id, workflowRunId, (current) => {
1149
- if (current?.reflection_invalidated_for_workflow_run_id === workflowRunId
1150
- && current?.reflection_invalidated_for_proof_digest === proofDigest)
1151
- return null;
1152
- return {
1153
- reflection_invalidation_required: true,
1154
- reflection_invalidated_at: nowIso(),
1155
- reflection_invalidation_reason: 'naruto_terminal_proof_committed',
1156
- reflection_invalidated_for_workflow_run_id: workflowRunId,
1157
- reflection_invalidated_for_proof_digest: proofDigest
1158
- };
1159
- }, { sessionKey: resolvedSessionKey });
1160
- }
1161
886
  async function consumeLightRouteStop(root, payload = {}) {
1162
887
  const file = path.join(root, '.sneakoscope', 'state', LIGHT_ROUTE_STOP_ARTIFACT);
1163
888
  const record = await readJson(file, null).catch(() => null);
@@ -1280,14 +1005,19 @@ function shouldLoopBackAfterHonestMode(state = {}) {
1280
1005
  const route = String(state.route || state.mode || '').toLowerCase();
1281
1006
  if (['answer', 'dfix', 'wiki'].includes(route))
1282
1007
  return false;
1008
+ const attempts = Number(state.honest_loop_attempt_count || 0);
1009
+ if (Number.isFinite(attempts) && attempts >= MAX_HONEST_LOOPBACK_ATTEMPTS)
1010
+ return false;
1283
1011
  return Boolean(state.ambiguity_gate_passed || state.clarification_passed || /CONTRACT_SEALED|HONEST_LOOPBACK/i.test(String(state.phase || '')));
1284
1012
  }
1013
+ const MAX_HONEST_LOOPBACK_ATTEMPTS = 2;
1285
1014
  async function recordHonestModeLoopback(root, state = {}, lastMessage = '', sessionKey = null) {
1286
1015
  const id = state.mission_id;
1287
1016
  const dir = missionDir(root, id);
1288
1017
  const previousPhase = state.phase || null;
1289
1018
  const mode = String(state.mode || state.route || 'SKS').toUpperCase();
1290
1019
  const phase = `${mode}_HONEST_LOOPBACK_AFTER_CLARIFICATION`;
1020
+ const attempt = Number(state.honest_loop_attempt_count || 0) + 1;
1291
1021
  const artifact = {
1292
1022
  schema_version: 1,
1293
1023
  mission_id: id,
@@ -1295,16 +1025,21 @@ async function recordHonestModeLoopback(root, state = {}, lastMessage = '', sess
1295
1025
  phase,
1296
1026
  created_at: nowIso(),
1297
1027
  reason: 'honest_mode_unresolved_gap',
1028
+ attempt,
1029
+ max_attempts: MAX_HONEST_LOOPBACK_ATTEMPTS,
1298
1030
  issue_lines: honestModeGapLines(lastMessage),
1299
- next_action: 'continue_from_sealed_contract_without_reasking'
1031
+ next_action: attempt >= MAX_HONEST_LOOPBACK_ATTEMPTS
1032
+ ? 'stop_with_terminal_blocker_or_record_hard_blocker'
1033
+ : 'continue_from_sealed_contract_without_reasking'
1300
1034
  };
1301
1035
  const file = path.join(dir, 'honest-loopback.json');
1302
1036
  await writeJsonAtomic(file, artifact);
1303
- await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.honest_mode.loopback', previous_phase: previousPhase, phase, issues: artifact.issue_lines });
1037
+ await appendJsonl(path.join(dir, 'events.jsonl'), { ts: nowIso(), type: 'pipeline.honest_mode.loopback', previous_phase: previousPhase, phase, attempt, issues: artifact.issue_lines });
1304
1038
  await setCurrent(root, {
1305
1039
  phase,
1306
1040
  honest_loop_required: true,
1307
1041
  honest_loop_detected_at: artifact.created_at,
1042
+ honest_loop_attempt_count: attempt,
1308
1043
  implementation_allowed: true,
1309
1044
  clarification_required: false,
1310
1045
  questions_allowed: false,