sneakoscope 8.0.2 → 8.0.4

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 (376) hide show
  1. package/README.md +150 -37
  2. package/config/skills-hash-ledger.v1.json +1 -1
  3. package/crates/sks-core/Cargo.lock +1 -1
  4. package/crates/sks-core/Cargo.toml +1 -1
  5. package/dist/bin/fast-inline.js +55 -27
  6. package/dist/bin/install.js +6 -32
  7. package/dist/bin/sks-dispatch.js +1 -1
  8. package/dist/cli/args.js +0 -2
  9. package/dist/cli/cli-theme.js +18 -9
  10. package/dist/cli/command-manifest-lite.js +6 -6
  11. package/dist/cli/command-registry.js +6 -6
  12. package/dist/cli/feature-commands.js +9 -7
  13. package/dist/cli/install-helpers-codex-lb-chain.js +198 -7
  14. package/dist/cli/install-helpers-codex-lb-config.js +78 -10
  15. package/dist/cli/install-helpers-install-support.js +9 -6
  16. package/dist/cli/install-helpers.js +101 -49
  17. package/dist/cli/install-tool-helpers.js +2 -82
  18. package/dist/cli/output.js +6 -1
  19. package/dist/cli/router.js +101 -2
  20. package/dist/commands/codex-lb.js +119 -19
  21. package/dist/commands/doctor-profile.js +1 -1
  22. package/dist/commands/doctor.js +727 -144
  23. package/dist/commands/mad-sks.js +1 -5
  24. package/dist/config/skills-manifest.json +4 -2
  25. package/dist/core/agents/agent-codex-cockpit.js +0 -3
  26. package/dist/core/agents/agent-effort-policy.js +5 -5
  27. package/dist/core/agents/agent-janitor.js +0 -20
  28. package/dist/core/agents/agent-orchestrator.js +9 -56
  29. package/dist/core/agents/agent-output-validator.js +2 -3
  30. package/dist/core/agents/agent-patch-schema.js +2 -2
  31. package/dist/core/agents/agent-proof-evidence.js +0 -65
  32. package/dist/core/agents/agent-recursion-guard.js +1 -1
  33. package/dist/core/agents/agent-runner-codex-exec.js +5 -3
  34. package/dist/core/agents/agent-scheduler.js +327 -85
  35. package/dist/core/agents/agent-schema.js +1 -1
  36. package/dist/core/agents/agent-trust-report.js +0 -36
  37. package/dist/core/agents/agent-worker-pipeline.js +0 -1
  38. package/dist/core/agents/fast-mode-policy.js +1 -3
  39. package/dist/core/agents/native-cli-worker-runtime-proof.js +1 -1
  40. package/dist/core/agents/native-cli-worker-runtime.js +69 -647
  41. package/dist/core/agents/native-cli-worker.js +6 -7
  42. package/dist/core/agents/native-worker-backend-router.js +2 -32
  43. package/dist/core/agents/no-subagent-scaling-policy.js +1 -1
  44. package/dist/core/agents/parallel-runtime-proof.js +1 -6
  45. package/dist/core/agents/runtime-proof-summary.js +1 -35
  46. package/dist/core/architecture-hardening/contracts/contracts.js +193 -0
  47. package/dist/core/architecture-hardening/migration/migration.js +111 -0
  48. package/dist/core/architecture-hardening/state/state-service.js +155 -0
  49. package/dist/core/artifact-schemas.js +0 -3
  50. package/dist/core/codex/codex-config-guard.js +238 -52
  51. package/dist/core/codex-adapter.js +5 -3
  52. package/dist/core/codex-app/auxiliary-oauth-policy.js +36 -0
  53. package/dist/core/codex-app/catalog-compat/catalog-service.js +104 -0
  54. package/dist/core/codex-app/child-policy/child-policy.js +35 -0
  55. package/dist/core/codex-app/codex-app-handoff.js +0 -1
  56. package/dist/core/codex-app/codex-hook-lifecycle.js +1 -1
  57. package/dist/core/codex-app/codex-init-deep.js +1 -1
  58. package/dist/core/codex-app/menubar/app-bundle.js +2 -0
  59. package/dist/core/codex-app/menubar/constants.js +14 -1
  60. package/dist/core/codex-app/menubar/global-install.js +288 -0
  61. package/dist/core/codex-app/menubar/installer.js +79 -14
  62. package/dist/core/codex-app/menubar/launch-agent.js +267 -45
  63. package/dist/core/codex-app/menubar/paths.js +3 -0
  64. package/dist/core/codex-app/menubar/rollback.js +55 -7
  65. package/dist/core/codex-app/menubar/status.js +75 -4
  66. package/dist/core/codex-app/provider-child-policy.js +64 -0
  67. package/dist/core/codex-app/provider-mode.js +91 -0
  68. package/dist/core/codex-app/provider-operation-stages.js +20 -0
  69. package/dist/core/codex-app/provider-session-policy.js +85 -0
  70. package/dist/core/codex-app/session-policy/session-pinning.js +68 -0
  71. package/dist/core/codex-app.js +3 -2
  72. package/dist/core/codex-control/codex-0139-image-path-real-probe.js +3 -1
  73. package/dist/core/codex-control/codex-0139-web-search-probe.js +3 -1
  74. package/dist/core/codex-control/codex-app-server-runtime-env.js +13 -4
  75. package/dist/core/codex-control/codex-app-server-v2-client.js +3 -3
  76. package/dist/core/codex-control/codex-control-proof.js +0 -1
  77. package/dist/core/codex-control/codex-task-runner.js +1 -4
  78. package/dist/core/codex-exec-output-schema.js +4 -1
  79. package/dist/core/codex-lb/codex-lb-env.js +63 -72
  80. package/dist/core/codex-lb/codex-lb-setup.js +15 -2
  81. package/dist/core/codex-lb/desktop-bridge/header-policy.js +6 -0
  82. package/dist/core/codex-lb/desktop-bridge/http-forward.js +48 -6
  83. package/dist/core/codex-lb/desktop-bridge/security.js +134 -0
  84. package/dist/core/codex-lb/desktop-bridge/server.js +9 -3
  85. package/dist/core/codex-lb/desktop-bridge/state.js +26 -6
  86. package/dist/core/codex-lb/desktop-bridge/types.js +1 -0
  87. package/dist/core/codex-lb/desktop-center-credentials.js +517 -58
  88. package/dist/core/codex-lb/desktop-controller.js +177 -56
  89. package/dist/core/codex-lb/desktop-service.js +179 -40
  90. package/dist/core/codex-lb/legacy-migration.js +1 -3
  91. package/dist/core/codex-lb/native-openai-transport/transport.js +68 -0
  92. package/dist/core/codex-lb/probes/cli-image-tool-probe.js +1 -1
  93. package/dist/core/codex-lb/provider-routing/provider-router.js +58 -0
  94. package/dist/core/codex-lb/routing-truth.js +327 -0
  95. package/dist/core/codex-native/codex-native-feature-broker.js +4 -0
  96. package/dist/core/codex-native/codex-native-pattern-analysis.js +1 -2
  97. package/dist/core/codex-native/core-skill-manifest.js +1 -1
  98. package/dist/core/codex-plugins/codex-plugin-json.js +26 -6
  99. package/dist/core/codex-plugins/codex-plugin-repair.js +32 -6
  100. package/dist/core/commands/basic-cli.js +9 -7
  101. package/dist/core/commands/computer-use-command.js +1 -1
  102. package/dist/core/commands/image-ux-review-command.js +16 -9
  103. package/dist/core/commands/install-package-command.js +105 -0
  104. package/dist/core/commands/intent-normalization/normalizer.js +96 -0
  105. package/dist/core/commands/mad-sks-command.js +23 -274
  106. package/dist/core/commands/mad-sks-headless.js +11 -30
  107. package/dist/core/commands/naruto-command.js +0 -25
  108. package/dist/core/commands/qa-loop-command.js +104 -22
  109. package/dist/core/commands/remote-command.js +2 -2
  110. package/dist/core/commands/research-command.js +10 -5
  111. package/dist/core/commands/telegram-command.js +407 -0
  112. package/dist/core/config-adopt/config-adopt-command.js +35 -0
  113. package/dist/core/config-adopt/config-adopt.js +346 -0
  114. package/dist/core/config-adopt/index.js +3 -0
  115. package/dist/core/doctor/command-alias-cleanup.js +4 -1
  116. package/dist/core/doctor/current-project-guidance-nested.js +37 -6
  117. package/dist/core/doctor/current-project-guidance.js +15 -9
  118. package/dist/core/doctor/doctor-dirty-planner.js +1 -4
  119. package/dist/core/doctor/doctor-readiness-matrix.js +15 -18
  120. package/dist/core/doctor/retired-managed-residue-private.js +4 -3
  121. package/dist/core/doctor/retired-managed-residue-runtime.js +2 -2
  122. package/dist/core/doctor/skill-legacy-surface.js +11 -10
  123. package/dist/core/doctor/sks-menubar-doctor.js +4 -0
  124. package/dist/core/evaluation.js +0 -19
  125. package/dist/core/evidence/v2/evidence-key.js +105 -0
  126. package/dist/core/feature-fixtures.js +12 -7
  127. package/dist/core/feature-registry.js +52 -21
  128. package/dist/core/hooks-runtime/hook-context.js +9 -0
  129. package/dist/core/hooks-runtime/managed-skill-admission.js +54 -4
  130. package/dist/core/hooks-runtime/official-subagent-lifecycle.js +69 -52
  131. package/dist/core/hooks-runtime/stop-finalization.js +226 -0
  132. package/dist/core/hooks-runtime/stop-repeat-guard.js +21 -2
  133. package/dist/core/hooks-runtime/subagent-skill-availability-contract.js +2 -2
  134. package/dist/core/hooks-runtime/subagent-skill-availability-evidence.js +3 -3
  135. package/dist/core/hooks-runtime/subagent-skill-availability-guards.js +43 -5
  136. package/dist/core/hooks-runtime/subagent-skill-availability.js +64 -30
  137. package/dist/core/hooks-runtime/subagent-stop-hook.js +15 -2
  138. package/dist/core/hooks-runtime.js +179 -212
  139. package/dist/core/image/reference-evidence/reference-registry.js +145 -0
  140. package/dist/core/image-ux-review/imagegen-adapter.js +21 -9
  141. package/dist/core/image-ux-review/reference-policy/reference-policy.js +9 -0
  142. package/dist/core/imagegen/codex-lb-imagegen-target.js +8 -0
  143. package/dist/core/imagegen/imagegen-capability.js +59 -2
  144. package/dist/core/imagegen/require-imagegen.js +2 -2
  145. package/dist/core/init/skills.js +17 -3
  146. package/dist/core/init.js +3 -3
  147. package/dist/core/install/installed-package-smoke.js +23 -5
  148. package/dist/core/json/canonical.js +9 -0
  149. package/dist/core/locks/file-lock.js +0 -1
  150. package/dist/core/loops/loop-continuation-enforcer.js +65 -7
  151. package/dist/core/loops/loop-decomposer.js +0 -1
  152. package/dist/core/loops/loop-gate-runner.js +65 -4
  153. package/dist/core/loops/loop-gate-selector.js +0 -2
  154. package/dist/core/loops/loop-proof-validation.js +38 -0
  155. package/dist/core/loops/loop-risk-classifier.js +1 -1
  156. package/dist/core/loops/loop-runtime.js +14 -2
  157. package/dist/core/loops/loop-scheduler.js +7 -2
  158. package/dist/core/loops/loop-worker-runtime.js +0 -15
  159. package/dist/core/loops/loop-worktree-runtime.js +52 -4
  160. package/dist/core/managed-assets/managed-assets-manifest.js +14 -14
  161. package/dist/core/naruto/hardware-capacity-probe.js +9 -6
  162. package/dist/core/naruto/naruto-active-pool.js +2 -14
  163. package/dist/core/naruto/naruto-concurrency-governor.js +71 -31
  164. package/dist/core/naruto/naruto-loop-worker-router.js +0 -2
  165. package/dist/core/naruto/naruto-verification-dag.js +0 -1
  166. package/dist/core/naruto/naruto-write-e2e.js +1 -2
  167. package/dist/core/naruto/resource-pressure-monitor.js +0 -4
  168. package/dist/core/observability/architecture-hardening/safe-projection.js +65 -0
  169. package/dist/core/perf/import-graph-budget.js +0 -1
  170. package/dist/core/perf/release-latency-slo.js +3 -2
  171. package/dist/core/preflight/parallel-preflight-engine.js +2 -15
  172. package/dist/core/product-design-app-server.js +13 -1
  173. package/dist/core/proof/fake-real-proof-policy.js +2 -17
  174. package/dist/core/proof/route-proof-gate.js +2 -10
  175. package/dist/core/proof/route-proof-policy.js +1 -1
  176. package/dist/core/proof/runtime-evidence-policy.js +185 -0
  177. package/dist/core/proof/runtime-truth-matrix.js +64 -39
  178. package/dist/core/proof/validation.js +27 -11
  179. package/dist/core/provider/provider-context.js +18 -2
  180. package/dist/core/providers/openrouter/openrouter-account.js +3 -2
  181. package/dist/core/python-tools/python-tool-runner.js +1 -1
  182. package/dist/core/qa-loop/qa-execution-control.js +57 -0
  183. package/dist/core/questions.js +1 -1
  184. package/dist/core/release/extreme-parallel-scheduler.js +0 -3
  185. package/dist/core/release/gate-manifest.js +3 -7
  186. package/dist/core/release/gate-pack-manifest.js +3 -7
  187. package/dist/core/release/package-size-budget.js +2 -2
  188. package/dist/core/release/physical-release-gates.js +189 -0
  189. package/dist/core/release/publish-preflight.js +113 -0
  190. package/dist/core/release/release-gate-affected-selector.js +0 -2
  191. package/dist/core/release/release-gate-batch-runner.js +1 -1
  192. package/dist/core/release/release-gate-node.js +0 -1
  193. package/dist/core/release/release-gate-resource-governor.js +0 -1
  194. package/dist/core/release/release-pack-receipt.js +5 -8
  195. package/dist/core/release/release-real-contract.js +0 -6
  196. package/dist/core/release/resource-class-budget.js +0 -1
  197. package/dist/core/release/stage-publish.js +178 -36
  198. package/dist/core/research/research-adversarial-review.js +103 -9
  199. package/dist/core/research.js +1 -1
  200. package/dist/core/retention.js +0 -1
  201. package/dist/core/routes/constants.js +1 -1
  202. package/dist/core/routes/diagnostic-allowlist.js +0 -1
  203. package/dist/core/routes/dollar-manifest-lite.js +1 -1
  204. package/dist/core/routes.js +46 -15
  205. package/dist/core/runtime/execution-control.js +226 -0
  206. package/dist/core/runtime/progress-recovery/progress-recovery.js +89 -0
  207. package/dist/core/runtime/task-profile.js +10 -4
  208. package/dist/core/runtime/verification-budget.js +10 -1
  209. package/dist/core/safety/intent-contract/intent-contract.js +94 -0
  210. package/dist/core/safety/mutation-guard.js +0 -2
  211. package/dist/core/safety/mutation-ledger.js +0 -2
  212. package/dist/core/safety/requested-scope-contract.js +0 -0
  213. package/dist/core/search-visibility/discovery.js +1 -1
  214. package/dist/core/search-visibility/index.js +12 -0
  215. package/dist/core/search-visibility/verifier.js +112 -3
  216. package/dist/core/security/private-credential-file.js +209 -0
  217. package/dist/core/session/project-namespace.js +0 -5
  218. package/dist/core/skills/skill-agent-metadata.js +1 -3
  219. package/dist/core/strategy/adhd-orchestrating-gate.js +0 -1
  220. package/dist/core/subagents/agent-catalog.js +19 -34
  221. package/dist/core/subagents/model-policy.js +65 -24
  222. package/dist/core/subagents/naruto-help-contract.js +8 -8
  223. package/dist/core/subagents/naruto-host-credentials.js +13 -0
  224. package/dist/core/subagents/official-subagent-config.js +16 -6
  225. package/dist/core/subagents/official-subagent-preparation.js +35 -16
  226. package/dist/core/subagents/official-subagent-prompt.js +7 -7
  227. package/dist/core/subagents/official-subagent-runner.js +27 -4
  228. package/dist/core/subagents/role-model-preferences.js +1 -1
  229. package/dist/core/subagents/thread-budget.js +19 -12
  230. package/dist/core/subagents/wave-lifecycle.js +18 -6
  231. package/dist/core/telegram/access.js +58 -0
  232. package/dist/core/telegram/client.js +157 -0
  233. package/dist/core/telegram/confirmation.js +37 -0
  234. package/dist/core/telegram/doctor.js +154 -0
  235. package/dist/core/telegram/index.js +9 -0
  236. package/dist/core/telegram/keychain.js +317 -0
  237. package/dist/core/telegram/liveness.js +118 -0
  238. package/dist/core/telegram/poller.js +90 -0
  239. package/dist/core/telegram/redaction.js +15 -0
  240. package/dist/core/telegram/state-lock.js +416 -0
  241. package/dist/core/telegram/types.js +1 -0
  242. package/dist/core/text/strings.js +3 -0
  243. package/dist/core/triwiki/context-graph/store/evidence-write-lock.js +29 -0
  244. package/dist/core/triwiki/context-graph/store/fragment-cache.js +24 -0
  245. package/dist/core/triwiki/context-graph/store/snapshot-store.js +69 -21
  246. package/dist/core/triwiki/triwiki-gate-impact-map.js +2 -2
  247. package/dist/core/triwiki/triwiki-module-card.js +1 -2
  248. package/dist/core/update/installed-cli-resolution.js +170 -0
  249. package/dist/core/update/update-diagnostics.js +52 -0
  250. package/dist/core/update/update-migration-state.js +30 -12
  251. package/dist/core/update/update-operation.js +2 -1
  252. package/dist/core/update/update-stage-diagnostics.js +38 -0
  253. package/dist/core/update/update-status.js +2 -9
  254. package/dist/core/update-check.js +279 -91
  255. package/dist/core/version.js +1 -1
  256. package/dist/native/sks-menubar/Sources/AppDelegate.swift +19 -1
  257. package/dist/native/sks-menubar/Sources/AppIdentity.swift +7 -0
  258. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +6 -2
  259. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +159 -92
  260. package/dist/native/sks-menubar/Sources/OperationModels.swift +389 -0
  261. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +57 -0
  262. package/dist/native/sks-menubar/Sources/ProcessClient.swift +3 -1
  263. package/dist/native/sks-menubar/Sources/ProvidersConnectTest.swift +115 -0
  264. package/dist/native/sks-menubar/Sources/ProvidersFastMode.swift +17 -0
  265. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +3 -0
  266. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +58 -17
  267. package/dist/native/sks-menubar/Sources/ProvidersReliability.swift +302 -0
  268. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +5 -0
  269. package/dist/native/sks-menubar/Sources/ProvidersRoutingTruth.swift +190 -0
  270. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +158 -126
  271. package/dist/native/sks-menubar/Sources/RemoteCodingViewController.swift +462 -26
  272. package/dist/native/sks-menubar/Sources/SKSKeychainStore.swift +344 -0
  273. package/dist/native/sks-menubar/Sources/SecureProcessEnvelope.swift +27 -0
  274. package/dist/native/sks-menubar/Sources/SingletonInstanceGuard.swift +328 -0
  275. package/dist/native/sks-menubar/Sources/StatusItemController.swift +10 -2
  276. package/dist/native/sks-menubar/Sources/TelegramPrivateFileStore.swift +498 -0
  277. package/dist/native/sks-menubar/Sources/TelegramPrivateFileSupport.swift +236 -0
  278. package/dist/native/sks-menubar/Sources/TelegramProcessGateway.swift +454 -0
  279. package/dist/native/sks-menubar/Sources/TelegramRuntimeSupport.swift +56 -0
  280. package/dist/native/sks-menubar/Sources/TelegramStateLock.swift +448 -0
  281. package/dist/native/sks-menubar/Sources/TelegramSupport.swift +187 -0
  282. package/dist/native/sks-menubar/Sources/TelegramTransport.swift +499 -0
  283. package/dist/native/sks-menubar/Sources/main.swift +15 -1
  284. package/dist/scripts/all-feature-deep-completion-check.js +5 -1
  285. package/dist/scripts/check-publish-tag.js +56 -0
  286. package/dist/scripts/codex-lb-fast-mode-truth-check.js +10 -3
  287. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +12 -3
  288. package/dist/scripts/codex-lb-gpt56-fast-profile-check.js +4 -2
  289. package/dist/scripts/codex-native-agent-role-content-check.js +3 -3
  290. package/dist/scripts/codex-native-gate-lib.js +14 -7
  291. package/dist/scripts/current-command-surface-check.js +7 -7
  292. package/dist/scripts/current-surface-update-e2e-check.js +4 -3
  293. package/dist/scripts/current-upgrade-matrix-check.js +5 -24
  294. package/dist/scripts/docs-truthfulness-check.js +17 -13
  295. package/dist/scripts/gate-lib.js +0 -2
  296. package/dist/scripts/gate-policy-audit-check.js +3 -2
  297. package/dist/scripts/harness-benchmark-check.js +1 -1
  298. package/dist/scripts/init-deep-backup-retention-check.js +1 -1
  299. package/dist/scripts/lib/codex-sdk-gate-lib.js +1 -2
  300. package/dist/scripts/loop-directive-check-lib.js +28 -38
  301. package/dist/scripts/mad-sks-app-ui-no-mutation-check.js +14 -180
  302. package/dist/scripts/mad-sks-launch-sql-plane-boundary-check.js +2 -11
  303. package/dist/scripts/official-subagent-workflow-check.js +1 -1
  304. package/dist/scripts/packlist-performance-check.js +1 -2
  305. package/dist/scripts/prepublish-release-check-or-fast.js +32 -0
  306. package/dist/scripts/publish-preflight.js +12 -0
  307. package/dist/scripts/release-affected-selector-check.js +2 -2
  308. package/dist/scripts/release-gate-batch-runner-check.js +2 -2
  309. package/dist/scripts/release-metadata-check.js +8 -12
  310. package/dist/scripts/release-real-check.js +2 -54
  311. package/dist/scripts/runtime-domain-gate-lib.js +2 -96
  312. package/dist/scripts/runtime-proof-summary-check.js +2 -6
  313. package/dist/scripts/search-visibility-gate-lib.js +0 -1
  314. package/dist/scripts/sks-cli-gate-lib.js +1 -1
  315. package/dist/scripts/typed-routing-gate-lib.js +7 -59
  316. package/docs/demo.tape +1 -1
  317. package/infra-harness-gates.json +1 -1456
  318. package/package.json +10 -7
  319. package/release-gates.v2.json +0 -1
  320. package/schemas/agents/parallel-runtime-proof.schema.json +0 -2
  321. package/schemas/codex/agent-result.schema.json +0 -6
  322. package/schemas/naruto/naruto-concurrency-governor.schema.json +1 -3
  323. package/schemas/release/release-gate-node.schema.json +1 -1
  324. package/dist/commands/zellij-lane.js +0 -22
  325. package/dist/commands/zellij-monitor-pane.js +0 -26
  326. package/dist/commands/zellij-slot-column-anchor.js +0 -22
  327. package/dist/commands/zellij-slot-pane.js +0 -80
  328. package/dist/commands/zellij-viewport-pane.js +0 -57
  329. package/dist/commands/zellij.js +0 -422
  330. package/dist/core/agents/agent-runner-zellij.js +0 -164
  331. package/dist/core/agents/agent-slot-pane-binding-proof.js +0 -96
  332. package/dist/core/agents/parallel-write-fixture.js +0 -305
  333. package/dist/core/agents/worker-pane-communication-contract.js +0 -100
  334. package/dist/core/agents/zellij-lane-supervisor.js +0 -428
  335. package/dist/core/agents/zellij-right-lane-cockpit.js +0 -66
  336. package/dist/core/doctor/doctor-zellij-repair.js +0 -40
  337. package/dist/core/ops/upgrade-migration-fixtures.js +0 -119
  338. package/dist/core/proof/route-finalizer-fixtures.js +0 -21
  339. package/dist/core/zellij/homebrew-policy.js +0 -43
  340. package/dist/core/zellij/zellij-capability.js +0 -126
  341. package/dist/core/zellij/zellij-clipboard-config.js +0 -52
  342. package/dist/core/zellij/zellij-command.js +0 -149
  343. package/dist/core/zellij/zellij-fake-adapter.js +0 -186
  344. package/dist/core/zellij/zellij-lane-renderer.js +0 -706
  345. package/dist/core/zellij/zellij-lane-runtime.js +0 -189
  346. package/dist/core/zellij/zellij-launcher.js +0 -268
  347. package/dist/core/zellij/zellij-layout-builder.js +0 -191
  348. package/dist/core/zellij/zellij-monitor-renderer.js +0 -52
  349. package/dist/core/zellij/zellij-official-subagent-activity.js +0 -526
  350. package/dist/core/zellij/zellij-official-subagent-telemetry.js +0 -258
  351. package/dist/core/zellij/zellij-pane-proof.js +0 -226
  352. package/dist/core/zellij/zellij-right-column-manager.js +0 -308
  353. package/dist/core/zellij/zellij-screen-proof.js +0 -120
  354. package/dist/core/zellij/zellij-self-heal-types.js +0 -44
  355. package/dist/core/zellij/zellij-self-heal.js +0 -408
  356. package/dist/core/zellij/zellij-slot-column-anchor.js +0 -304
  357. package/dist/core/zellij/zellij-slot-pane-renderer.js +0 -521
  358. package/dist/core/zellij/zellij-slot-telemetry.js +0 -384
  359. package/dist/core/zellij/zellij-theme.js +0 -66
  360. package/dist/core/zellij/zellij-ui-mode.js +0 -34
  361. package/dist/core/zellij/zellij-update.js +0 -348
  362. package/dist/core/zellij/zellij-viewport-binder.js +0 -61
  363. package/dist/core/zellij/zellij-worker-pane-manager.js +0 -881
  364. package/dist/core/zellij/zellij-worker-pane-summary.js +0 -64
  365. package/dist/native/sks-menubar/Tests/AppRuntimeTestSupport.swift +0 -26
  366. package/dist/native/sks-menubar/Tests/OperationCoordinatorTests.swift +0 -174
  367. package/dist/native/sks-menubar/Tests/ProcessClientTests.swift +0 -20
  368. package/dist/native/sks-menubar/Tests/ProvidersViewControllerTests.swift +0 -142
  369. package/dist/scripts/zellij-pane-proof-check.js +0 -88
  370. package/dist/scripts/zellij-real-session-cleanup-check.js +0 -139
  371. package/dist/scripts/zellij-real-session-launch-check.js +0 -126
  372. package/dist/scripts/zellij-screen-proof-check.js +0 -43
  373. package/schemas/zellij/zellij-right-column-state.schema.json +0 -40
  374. package/schemas/zellij/zellij-slot-telemetry.schema.json +0 -89
  375. package/schemas/zellij/zellij-worker-pane.schema.json +0 -53
  376. package/scripts/build-clean-atomic.mjs +0 -323
@@ -5,7 +5,7 @@ import { CODEX_APP_IMAGE_GENERATION_DOC_URL, CODEX_COMPUTER_USE_ONLY_POLICY, COD
5
5
  import { getdesignReferencePolicyText, imageUxReviewPipelinePolicyText } from './routes/design-policy.js';
6
6
  import { PPT_PIPELINE_SKILL_ALLOWLIST, pptPipelineAllowlistPolicyText } from './routes/ppt-policy.js';
7
7
  import { normalizeDollarSkillName, prefixKnownSksDollarReferences, sksPrefixedDollarCommand, sksPrefixedSkillName, unprefixedSksSkillName } from './routes/dollar-prefix.js';
8
- import { classifyTaskProfile, looksLikeDatabaseWorkRequest } from './runtime/task-profile.js';
8
+ import { classifyTaskProfile, isTaskProfile, looksLikeDatabaseWorkRequest } from './runtime/task-profile.js';
9
9
  import { legacyCoreSkillNames } from './codex-native/core-skill-manifest.js';
10
10
  export * from './routes/constants.js';
11
11
  export * from './routes/design-policy.js';
@@ -249,7 +249,7 @@ export const ROUTES = [
249
249
  command: '$Naruto',
250
250
  mode: 'NARUTO',
251
251
  route: 'Codex official subagent workflow',
252
- description: '$Naruto prepares a lightweight Codex official subagent workflow. The Sol Max parent owns decomposition, delegates only defensible direct-child slices, reuses bounded query-aware TriWiki attention anchors, waits for every requested thread, integrates the results, and reports scoped verification. Automatic fan-out starts at four for bounded work, six for explicit parallel work, eight for large-scale work, and sixteen for mass cheap-model fan-out on the Luna/Terra lanes; normal expansion is capped at twelve, while the mass lane may expand to sixty-four. The default max_threads of twelve remains a frame budget (cap), never a target; the absolute hard frame cap is two hundred fifty-six, and multi-wave scheduling reuses capacity for requested counts beyond the first wave. Luna Max handles tiny mechanical shards, Terra Medium handles broad search and exploration shards, and Sol handles implementation and judgment; explicit --agents remains authoritative.',
252
+ description: '$Naruto prepares a lightweight Codex official subagent workflow. The Sol Max parent owns decomposition, delegates only defensible direct-child slices, reuses bounded query-aware TriWiki attention anchors, waits for every requested thread, integrates the results, and reports scoped verification. Automatic fan-out starts at four for bounded work, six for explicit parallel work, eight for large-scale work, and sixteen for mass cheap-model fan-out on the Luna/Terra lanes; normal expansion is capped at twelve, while the mass lane may expand to sixty-four. The default max_threads of twelve remains a frame budget (cap), never a target; the absolute hard frame cap is two hundred fifty-six, and multi-wave scheduling reuses capacity for requested counts beyond the first wave. Luna Max handles tiny mechanical shards, Terra Max handles broad search and exploration shards, and Sol handles implementation and judgment; explicit --agents remains authoritative.',
253
253
  requiredSkills: ['naruto', 'pipeline-runner', 'prompt-pipeline', 'honest-mode'],
254
254
  dollarAliases: ['$Work'],
255
255
  appSkillAliases: ['work', 'from-chat-img'],
@@ -640,20 +640,19 @@ export const COMMAND_CATALOG = [
640
640
  { name: 'review', usage: 'sks review [--staged|--diff <ref>] [--fix] [--json]', description: 'Review a diff with machine-evidence findings sorted above LLM review notes.' },
641
641
  { name: 'usage', usage: `sks usage [${USAGE_TOPICS}]`, description: 'Print copy-ready workflows for common tasks.' },
642
642
  { name: 'quickstart', usage: 'sks quickstart', description: 'Show the shortest safe setup and verification flow.' },
643
- { name: 'bootstrap', usage: 'sks bootstrap [--install-scope global|project] [--local-only] [--json]', description: 'Initialize the current project, install SKS Codex App files/skills, check Context7/Codex App/Zellij, and print ready true/false.' },
643
+ { name: 'bootstrap', usage: 'sks bootstrap [--install-scope global|project] [--local-only] [--json]', description: 'Initialize the current project, install SKS Codex App files/skills, check Context7/Codex App/Codex CLI, and print ready true/false.' },
644
644
  { name: 'root', usage: 'sks root [--json]', description: 'Show whether SKS is using a project root or the per-user global SKS runtime root.' },
645
645
  { name: 'update', usage: 'sks update status|check|review|now|rollback [--refresh] [--version <version>] [--json] [--dry-run]', description: 'Inspect update-status.v3, review the exact staged operation, update the global package, or run guarded rollback.' },
646
646
  { name: 'uninstall', usage: 'sks uninstall [--dry-run] [--yes] [--keep-config] [--keep-data] [--purge-projects] [--json]', description: 'Remove SKS global skills, hooks, menu bar, state, temp files, and optional project residue while preserving user-owned content by default.' },
647
- { name: 'deps', usage: 'sks deps check [--json] [--yes]', description: 'Check Node/npm, Codex CLI, and Zellij readiness; pass --yes to repair missing Codex CLI/Zellij tooling when supported.' },
647
+ { name: 'deps', usage: 'sks deps check [--json] [--yes]', description: 'Check Node/npm and Codex CLI readiness; pass --yes to repair missing Codex CLI tooling when supported.' },
648
648
  { name: 'codex', usage: 'sks codex compatibility|version|update-status [--refresh]|update|doctor|schema|0.144 [--json]', description: 'Check Codex CLI compatibility/version/update status, run the official `codex update`, and inspect current manifest, capability, and hook-schema evidence.' },
649
649
  { name: 'codex-app', usage: 'sks codex-app [check|set-openrouter-key --api-key-stdin|use-openrouter --model <id>|openrouter-status|product-design|chrome-extension|pat status|remote-control]', description: 'Check Codex App install, OpenRouter provider activation, codex-lb key-entry guidance, Product Design plugin readiness, Codex Chrome Extension web verification readiness, PAT-safe status, first-party MCP/plugin readiness, and Codex CLI remote-control availability.' },
650
650
  { name: 'codex-native', usage: 'sks codex-native status|feature-broker|invocation-plan|init-deep [--json]', description: 'Inspect Codex Native feature broker readiness, invocation routing, pattern evidence, and managed memory setup.' },
651
651
  { name: 'hooks', usage: 'sks hooks explain|status|trust-report|replay|codex-validate|warning-check ... [--json]', description: 'Explain Codex hook events, validate vendored latest 10-event output schemas, replay fixtures, and enforce warning-zero SKS hook policies under the 0.134 compatibility matrix.' },
652
- { name: 'codex-lb', usage: 'sks codex-lb status|health|metrics|doctor|circuit|repair|setup ...', description: 'Configure, health-check, repair, and record circuit evidence for codex-lb provider auth without confusing ChatGPT OAuth and proxy keys.' },
652
+ { name: 'codex-lb', usage: 'sks codex-lb status|connect-test|health|metrics|doctor|circuit|repair|setup ...', description: 'Configure, run a one-request connection proof, health-check, repair, and record circuit evidence for codex-lb provider auth without confusing ChatGPT OAuth and proxy keys.' },
653
653
  { name: 'remote', usage: 'sks remote readiness|machines|worker ... [--json]', description: 'Inspect official Codex Remote readiness and the allowlisted proof-aware SSH stdio worker surface.' },
654
- { name: 'zellij', usage: 'sks zellij status|repair [--json] | sks --mad', description: 'Inspect Zellij runtime status, explain repair (no auto-install), and open the SKS Zellij runtime used by MAD. Zellij panes are not official Naruto subagent evidence.' },
655
- { name: 'mad-sks', usage: 'sks mad-sks plan|run|apply|sql|apply-migration|status|close|rollback-apply ... | sks --mad [--high]', description: 'Open or inspect MAD-SKS scoped permission workflows, merged SQL-plane execution, and the Zellij permission launcher.' },
656
- { name: 'auto-review', usage: 'sks auto-review status|enable|start [--high] | sks --Auto-review --high', description: 'Enable Codex automatic approval review and launch SKS Zellij with the auto-review profile.' },
654
+ { name: 'mad-sks', usage: 'sks mad-sks plan|run|apply|sql|apply-migration|status|close|rollback-apply ... | sks --mad [--high]', description: 'Open or inspect MAD-SKS scoped permission workflows, merged SQL-plane execution, and the native Codex permission launcher.' },
655
+ { name: 'auto-review', usage: 'sks auto-review status|enable|start [--high] | sks --Auto-review --high', description: 'Enable Codex automatic approval review and launch the native Codex session with the auto-review profile.' },
657
656
  { name: 'dollar-commands', usage: 'sks dollar-commands [--json]', description: 'List Codex App $ commands such as $sks-dfix and $sks-naruto.' },
658
657
  { name: 'fast-mode', usage: 'sks fast-mode on|off|status|clear [--project] [--json]', description: 'Toggle the global Codex Desktop GPT-5.6 Fast default used by $sks-fast-on/$sks-fast-off and keep project worker preference in sync; pass --project for project-local only.' },
659
658
  { name: 'with-local-llm', usage: 'sks with-local-llm on|off|status|set-model [--json]', description: 'Toggle the optional local Ollama worker backend used by $sks-with-local-llm-on/$sks-with-local-llm-off and eligible simple worker slices.' },
@@ -688,7 +687,7 @@ export const COMMAND_CATALOG = [
688
687
  { name: 'seo-geo-optimizer', usage: 'sks seo-geo-optimizer [seo|geo] doctor|audit|research|strategy|plan|apply|verify|status|rollback|fixture [mission|latest] [--mode seo|geo] [--target auto|website|docs|package] [--include-marketing] [--json]', description: 'Run the unified SEO/GEO optimizer on the shared search-visibility kernel with mode-specific gates, marketing research/strategy, safe apply, and proof.' },
689
688
  { name: 'research', usage: 'sks research prepare|run|status ...', description: 'Run long-form real research missions with xhigh agent Eureka ideas, debate, layered sources, paper, novelty, and falsification gates.' },
690
689
  { name: 'eval', usage: 'sks eval run|compare|thresholds ...', description: 'Run deterministic context-quality and performance evidence checks.' },
691
- { name: 'harness', usage: 'sks harness fixture|review [--json]', description: 'Run Harness Growth Factory fixtures for forgetting, skills, experiments, tool taxonomy, permissions, MultiAgentV2, and Zellij views.' },
690
+ { name: 'harness', usage: 'sks harness fixture|review [--json]', description: 'Run Harness Growth Factory fixtures for forgetting, skills, experiments, tool taxonomy, permissions, and MultiAgentV2.' },
692
691
  { name: 'perf', usage: 'sks perf run|workflow|cold-start [--json] [--iterations N]', description: 'Measure structured GPT-5.6/SKS performance budgets, including cold-start, Proof Field workflow decisions, and fast-lane evidence.' },
693
692
  { name: 'bench', usage: 'sks bench core|route-fixtures|blackbox|trust-kernel [--json]', description: 'Measure core trust-kernel hot paths and write performance budget artifacts.' },
694
693
  { name: 'proof', usage: 'sks proof show|latest|validate|export|smoke [--json|--md]', description: 'Show, validate, export, or smoke-write the unified Completion Proof Engine surface.' },
@@ -702,7 +701,7 @@ export const COMMAND_CATALOG = [
702
701
  { name: 'wiki', usage: 'sks wiki coords|pack|refresh|publish|rebuild-index|validate|validate-shared|wrongness ...', description: 'Build, refresh, publish shared shards, rebuild ignored indexes, validate, and attach wrongness-memory context to RGBA/trig LLM Wiki packs with attention.use_first and attention.hydrate_first for compact recall plus source hydration.' },
703
702
  { name: 'memory', usage: 'sks memory build [--json] | sks memory gc [--dry-run]', description: 'Project TriWiki context-pack memory into managed AGENTS.md blocks or run bounded memory cleanup.' },
704
703
  { name: 'hproof', usage: 'sks hproof check [mission-id|latest]', description: 'Evaluate the H-Proof done gate for a mission.' },
705
- { name: 'naruto', usage: 'sks naruto run \"task\" [--agents N] [--max-threads N] [--trusted-project] [--json] | sks naruto status|subagents|proof [latest|M-...] [--json] | sks naruto parent-summary --mission M-... --stdin [--json]', description: 'Run or inspect the Codex official subagent workflow with a Sol Max parent and fixed Luna Max mechanical, Sol High implementation, Sol Max judgment, and Terra Medium long-context/tool profiles, max_depth=1, and structured parent-thread completion evidence.' },
704
+ { name: 'naruto', usage: 'sks naruto run \"task\" [--agents N] [--max-threads N] [--trusted-project] [--json] | sks naruto status|subagents|proof [latest|M-...] [--json] | sks naruto parent-summary --mission M-... --stdin [--json]', description: 'Run or inspect the Codex official subagent workflow with a Sol Max parent and fixed Luna Max mechanical, Sol High implementation, Sol Max judgment, and Terra Max long-context/tool profiles, max_depth=1, and structured parent-thread completion evidence.' },
706
705
  { name: 'reasoning', usage: 'sks reasoning ["prompt"] [--json]', description: 'Show SKS temporary reasoning-effort routing: medium for simple tasks, high for logic, xhigh for research.' },
707
706
  { name: 'gx', usage: 'sks gx init|render|validate|drift|snapshot [name]', description: 'Create and verify deterministic SVG/HTML visual context cartridges.' },
708
707
  { name: 'profile', usage: 'sks profile show|set <model>', description: 'Inspect or set the current SKS model profile metadata.' },
@@ -1213,7 +1212,10 @@ export function narutoDecisionForRoute(route, prompt = '', profile = classifyTas
1213
1212
  if (profile === 'passthrough' || profile === 'answer' || profile === 'tiny-change') {
1214
1213
  return narutoRouteDecision('none', routeId, profile, `task_profile_${profile}_bypass`, true);
1215
1214
  }
1216
- if (profile === 'bounded-work' || profile === 'parallel-read' || profile === 'parallel-write' || profile === 'high-risk') {
1215
+ if (profile === 'bounded-work') {
1216
+ return narutoRouteDecision('none', routeId, profile, 'task_profile_bounded_work_parent_owned', false);
1217
+ }
1218
+ if (profile === 'parallel-read' || profile === 'parallel-write' || profile === 'high-risk') {
1217
1219
  return narutoRouteDecision('generic_naruto', routeId, profile, `task_profile_${profile}_default_parallel`, false);
1218
1220
  }
1219
1221
  return narutoRouteDecision('none', routeId, profile, `task_profile_${profile}_bypass`, true);
@@ -1262,6 +1264,24 @@ export function looksLikeCodeChangingWork(prompt = '') {
1262
1264
  return /\b(implement|build|make|add|edit|modify|change|fix|refactor|rewrite|migrate|create|delete|remove|rename|update|patch)\b/i.test(text)
1263
1265
  || /(코드|구현|개발|수정|변경|추가|삭제|해결|고쳐|바꿔|리팩터|마이그레이션)/i.test(text);
1264
1266
  }
1267
+ export function classifyPromptExecutionEffect(prompt = '') {
1268
+ const text = String(prompt || '').trim();
1269
+ const action = /(해줘|해라|진행|실행|적용|바꿔|수정|설치|삭제|배포|인증|로그인)/i.test(text)
1270
+ || /\b(configure|execute|apply|change|modify|install|delete|remove|deploy|publish|authenticate)\b|\blog\s*in\b|\bsign\s*in\b/i.test(text);
1271
+ if (!action)
1272
+ return 'read';
1273
+ if (/(삭제|제거|지워|delete|remove|uninstall|purge)/i.test(text))
1274
+ return 'delete';
1275
+ if (/(배포|출시|게시|deploy|publish|release)/i.test(text))
1276
+ return 'deploy';
1277
+ if (/(인증|로그인|로그아웃|재연결|authenticate|log\s*(?:in|out)|sign\s*(?:in|out)|reconnect)/i.test(text))
1278
+ return 'auth';
1279
+ if (/(보안|권한|서명|키\s*회전|security|permission|signing|rotate\s+key)/i.test(text))
1280
+ return 'security';
1281
+ if (/(설치|업그레이드|의존성|install|upgrade|dependenc)/i.test(text))
1282
+ return 'dependency';
1283
+ return 'write';
1284
+ }
1265
1285
  export function looksLikeExecutionWork(prompt = '') {
1266
1286
  const text = String(prompt || '');
1267
1287
  return looksLikeCodeChangingWork(text)
@@ -1284,7 +1304,7 @@ export function subagentExecutionPolicyText(route, prompt = '') {
1284
1304
  return [
1285
1305
  'Codex subagent workflow: required for this explicit Naruto or parallel task.',
1286
1306
  'The parent agent owns decomposition, integration, scoped verification, and the final answer.',
1287
- 'Delegate only genuinely independent slices. Use Luna Max only for tiny short-context mechanical work, Sol High for ordinary implementation, Sol Max for review/debug/planning/architecture/integration/risk judgment, and Terra Medium for long-context or Computer Use, Browser/Chrome, and image-generation execution.',
1307
+ 'Delegate only genuinely independent slices. Use Luna Max only for tiny short-context mechanical work, Sol High for ordinary implementation, Sol Max for review/debug/planning/architecture/integration/risk judgment, and Terra Max for long-context or Computer Use, Browser/Chrome, and image-generation execution.',
1288
1308
  'Parallel writes require disjoint paths; serialize overlapping paths, prohibit nested delegation, avoid duplicate work, wait for all requested agent threads, and close completed threads after collecting results.',
1289
1309
  'Completion evidence comes from official SubagentStart/SubagentStop events plus the parent integration summary, not process counts or PID evidence.'
1290
1310
  ].join(' ');
@@ -1297,7 +1317,7 @@ export function routeReasoning(route, prompt = '') {
1297
1317
  if (/(?:^|\s)sks\s+--mad\b|(?:^|\s)--mad\b|\$MAD-SKS\b|\bmad-sks\b|\bmadsks\b/i.test(text))
1298
1318
  return reasoning('xhigh', 'mad_sks_or_mad_launch_default');
1299
1319
  if (route?.id === 'Naruto')
1300
- return narutoRouteReasoning(text);
1320
+ return narutoRouteReasoning(route, text);
1301
1321
  if (route?.id === 'Research' || route?.id === 'AutoResearch')
1302
1322
  return reasoning('xhigh', 'research_or_experiment_route');
1303
1323
  if (route?.id === 'SuperSearch')
@@ -1316,8 +1336,19 @@ export function routeReasoning(route, prompt = '') {
1316
1336
  return reasoning('low', 'route_policy_low');
1317
1337
  return reasoning('medium', 'simple_fulfillment');
1318
1338
  }
1319
- function narutoRouteReasoning(_text = '') {
1320
- return reasoning('max', 'naruto_parent_sol_max');
1339
+ function narutoRouteReasoning(route, text = '') {
1340
+ if (route?.explicit_invocation !== false)
1341
+ return reasoning('max', 'explicit_naruto_parent_sol_max');
1342
+ const profile = isTaskProfile(route?.task_profile)
1343
+ ? route.task_profile
1344
+ : classifyTaskProfile(text);
1345
+ if (profile === 'parallel-read' || profile === 'parallel-write' || profile === 'high-risk') {
1346
+ return reasoning('max', `implicit_naruto_${profile}_sol_max`);
1347
+ }
1348
+ if (profile === 'tiny-change' || profile === 'passthrough' || profile === 'answer') {
1349
+ return reasoning('low', `implicit_naruto_${profile}_lightweight`);
1350
+ }
1351
+ return reasoning('medium', 'implicit_naruto_bounded_parent_medium');
1321
1352
  }
1322
1353
  export function reasoningProfileName(effort) {
1323
1354
  if (effort === 'low')
@@ -0,0 +1,226 @@
1
+ import { nowIso, sha256 } from '../fsx.js';
2
+ export const EXECUTION_CONTROL_SCHEMA = 'sks.execution-control.v1';
3
+ const MAX_TRACKED_IDEMPOTENCY_KEYS = 128;
4
+ export function normalizeExecutionControlBudget(input = {}) {
5
+ return {
6
+ max_attempts: boundedInteger(input.max_attempts, 1, 10_000, 1),
7
+ max_elapsed_ms: boundedInteger(input.max_elapsed_ms, 1, 7 * 24 * 60 * 60 * 1000, 30 * 60 * 1000),
8
+ max_tool_calls: nullableBoundedInteger(input.max_tool_calls, 1, 1_000_000),
9
+ max_tokens: nullableBoundedInteger(input.max_tokens, 1, Number.MAX_SAFE_INTEGER),
10
+ max_no_progress: boundedInteger(input.max_no_progress, 1, 100, 2)
11
+ };
12
+ }
13
+ export function normalizeExecutionControlState(value, at = nowIso()) {
14
+ const row = record(value);
15
+ if (row?.schema !== EXECUTION_CONTROL_SCHEMA)
16
+ return newExecutionControlState(at);
17
+ const status = row.status === 'completed' || row.status === 'stopped' ? row.status : 'running';
18
+ const stopReason = isExecutionStopReason(row.stop_reason) ? row.stop_reason : null;
19
+ return {
20
+ schema: EXECUTION_CONTROL_SCHEMA,
21
+ status,
22
+ stop_reason: status === 'running' ? null : stopReason,
23
+ stop_detail: status === 'running' ? null : nonEmptyString(row.stop_detail),
24
+ created_at: nonEmptyString(row.created_at) || at,
25
+ updated_at: nonEmptyString(row.updated_at) || at,
26
+ attempts: nonNegativeInteger(row.attempts),
27
+ elapsed_ms: nonNegativeInteger(row.elapsed_ms),
28
+ tool_calls: nonNegativeInteger(row.tool_calls),
29
+ tokens: nonNegativeInteger(row.tokens),
30
+ no_progress_streak: nonNegativeInteger(row.no_progress_streak),
31
+ last_progress_fingerprint: nonEmptyString(row.last_progress_fingerprint),
32
+ seen_idempotency_keys: uniqueStrings(row.seen_idempotency_keys).slice(-MAX_TRACKED_IDEMPOTENCY_KEYS)
33
+ };
34
+ }
35
+ export function preflightExecutionControl(current, rawBudget, at = nowIso()) {
36
+ const budget = normalizeExecutionControlBudget(rawBudget);
37
+ let state = normalizeExecutionControlState(current, at);
38
+ if (state.status !== 'running')
39
+ return decision(false, state, budget);
40
+ if (state.elapsed_ms >= budget.max_elapsed_ms)
41
+ state = stopExecutionControl(state, 'time_budget_exhausted', null, at);
42
+ else if (budget.max_tool_calls !== null && state.tool_calls >= budget.max_tool_calls)
43
+ state = stopExecutionControl(state, 'tool_budget_exhausted', null, at);
44
+ else if (budget.max_tokens !== null && state.tokens >= budget.max_tokens)
45
+ state = stopExecutionControl(state, 'token_budget_exhausted', null, at);
46
+ else if (state.attempts >= budget.max_attempts)
47
+ state = stopExecutionControl(state, 'attempt_budget_exhausted', null, at);
48
+ return decision(state.status === 'running', state, budget);
49
+ }
50
+ export function recordExecutionObservation(current, rawBudget, observation, at = nowIso()) {
51
+ const budget = normalizeExecutionControlBudget(rawBudget);
52
+ const state = normalizeExecutionControlState(current, at);
53
+ if (state.status !== 'running')
54
+ return state;
55
+ const fingerprint = executionProgressFingerprint(observation.fingerprint);
56
+ const idempotencyKey = nonEmptyString(observation.idempotencyKey);
57
+ const duplicate = Boolean(idempotencyKey && state.seen_idempotency_keys.includes(idempotencyKey));
58
+ const fingerprintChanged = state.last_progress_fingerprint === null || state.last_progress_fingerprint !== fingerprint;
59
+ const madeProgress = observation.madeProgress === true
60
+ || (observation.madeProgress !== false && fingerprintChanged && !duplicate);
61
+ const noProgressStreak = madeProgress ? 0 : state.no_progress_streak + 1;
62
+ const seenIdempotencyKeys = idempotencyKey && !duplicate
63
+ ? [...state.seen_idempotency_keys, idempotencyKey].slice(-MAX_TRACKED_IDEMPOTENCY_KEYS)
64
+ : [...state.seen_idempotency_keys];
65
+ let next = {
66
+ ...state,
67
+ updated_at: at,
68
+ attempts: state.attempts + (observation.countAttempt === false ? 0 : 1),
69
+ elapsed_ms: state.elapsed_ms + nonNegativeInteger(observation.elapsedMs),
70
+ tool_calls: state.tool_calls + nonNegativeInteger(observation.toolCalls),
71
+ tokens: state.tokens + nonNegativeInteger(observation.tokens),
72
+ no_progress_streak: noProgressStreak,
73
+ last_progress_fingerprint: fingerprint,
74
+ seen_idempotency_keys: seenIdempotencyKeys
75
+ };
76
+ if (observation.userInputRequired === true) {
77
+ return stopExecutionControl(next, 'user_input_required', 'execution cannot advance without user input', at);
78
+ }
79
+ if (next.no_progress_streak >= budget.max_no_progress) {
80
+ return stopExecutionControl(next, 'no_progress', `same semantic result repeated ${next.no_progress_streak} time(s)`, at);
81
+ }
82
+ if (next.elapsed_ms >= budget.max_elapsed_ms)
83
+ return stopExecutionControl(next, 'time_budget_exhausted', null, at);
84
+ if (budget.max_tool_calls !== null && next.tool_calls >= budget.max_tool_calls)
85
+ return stopExecutionControl(next, 'tool_budget_exhausted', null, at);
86
+ if (budget.max_tokens !== null && next.tokens >= budget.max_tokens)
87
+ return stopExecutionControl(next, 'token_budget_exhausted', null, at);
88
+ if (next.attempts >= budget.max_attempts)
89
+ return stopExecutionControl(next, 'attempt_budget_exhausted', null, at);
90
+ return next;
91
+ }
92
+ export function completeExecutionControl(current, verified, detail = null, at = nowIso()) {
93
+ const state = normalizeExecutionControlState(current, at);
94
+ if (!verified)
95
+ return stopExecutionControl(state, 'unverified_completion', detail || 'completion lacked applicable runtime proof', at);
96
+ return {
97
+ ...state,
98
+ status: 'completed',
99
+ stop_reason: 'completed',
100
+ stop_detail: detail,
101
+ no_progress_streak: 0,
102
+ updated_at: at
103
+ };
104
+ }
105
+ export function stopExecutionControl(current, reason, detail = null, at = nowIso()) {
106
+ const state = normalizeExecutionControlState(current, at);
107
+ return {
108
+ ...state,
109
+ status: reason === 'completed' ? 'completed' : 'stopped',
110
+ stop_reason: reason,
111
+ stop_detail: detail,
112
+ updated_at: at
113
+ };
114
+ }
115
+ export function resumeExecutionControl(current, rawBudget, currentFingerprint, at = nowIso()) {
116
+ const budget = normalizeExecutionControlBudget(rawBudget);
117
+ const state = normalizeExecutionControlState(current, at);
118
+ if (state.status === 'completed')
119
+ return state;
120
+ const hasBudget = state.attempts < budget.max_attempts
121
+ && state.elapsed_ms < budget.max_elapsed_ms
122
+ && (budget.max_tool_calls === null || state.tool_calls < budget.max_tool_calls)
123
+ && (budget.max_tokens === null || state.tokens < budget.max_tokens);
124
+ if (!hasBudget)
125
+ return state;
126
+ const fingerprintChanged = state.last_progress_fingerprint !== executionProgressFingerprint(currentFingerprint);
127
+ const budgetExpanded = ['attempt_budget_exhausted', 'tool_budget_exhausted', 'token_budget_exhausted'].includes(String(state.stop_reason || ''));
128
+ if (!fingerprintChanged && !budgetExpanded)
129
+ return state;
130
+ return {
131
+ ...state,
132
+ status: 'running',
133
+ stop_reason: null,
134
+ stop_detail: null,
135
+ no_progress_streak: fingerprintChanged ? 0 : state.no_progress_streak,
136
+ updated_at: at
137
+ };
138
+ }
139
+ export function executionProgressFingerprint(value) {
140
+ return `sha256:${sha256(stableJson(value))}`;
141
+ }
142
+ function newExecutionControlState(at) {
143
+ return {
144
+ schema: EXECUTION_CONTROL_SCHEMA,
145
+ status: 'running',
146
+ stop_reason: null,
147
+ stop_detail: null,
148
+ created_at: at,
149
+ updated_at: at,
150
+ attempts: 0,
151
+ elapsed_ms: 0,
152
+ tool_calls: 0,
153
+ tokens: 0,
154
+ no_progress_streak: 0,
155
+ last_progress_fingerprint: null,
156
+ seen_idempotency_keys: []
157
+ };
158
+ }
159
+ function decision(allowed, state, budget) {
160
+ return {
161
+ allowed,
162
+ state,
163
+ stop_reason: state.stop_reason,
164
+ remaining_time_ms: Math.max(0, budget.max_elapsed_ms - state.elapsed_ms),
165
+ remaining_attempts: Math.max(0, budget.max_attempts - state.attempts)
166
+ };
167
+ }
168
+ function stableJson(value) {
169
+ if (value === undefined)
170
+ return '"__undefined__"';
171
+ if (typeof value === 'number' && !Number.isFinite(value))
172
+ return JSON.stringify(String(value));
173
+ if (Array.isArray(value))
174
+ return `[${value.map(stableJson).join(',')}]`;
175
+ if (value && typeof value === 'object') {
176
+ const row = value;
177
+ return `{${Object.keys(row).sort().map((key) => `${JSON.stringify(key)}:${stableJson(row[key])}`).join(',')}}`;
178
+ }
179
+ const encoded = JSON.stringify(value);
180
+ return encoded === undefined ? '"__unserializable__"' : encoded;
181
+ }
182
+ function record(value) {
183
+ return value && typeof value === 'object' && !Array.isArray(value) ? value : null;
184
+ }
185
+ function nonNegativeInteger(value) {
186
+ const parsed = Number(value);
187
+ if (!Number.isFinite(parsed) || parsed <= 0)
188
+ return 0;
189
+ return Math.min(Number.MAX_SAFE_INTEGER, Math.floor(parsed));
190
+ }
191
+ function boundedInteger(value, min, max, fallback) {
192
+ const parsed = Number(value);
193
+ if (!Number.isFinite(parsed))
194
+ return fallback;
195
+ return Math.max(min, Math.min(max, Math.floor(parsed)));
196
+ }
197
+ function nullableBoundedInteger(value, min, max) {
198
+ if (value === null || value === undefined || value === '')
199
+ return null;
200
+ const parsed = Number(value);
201
+ if (!Number.isFinite(parsed))
202
+ return null;
203
+ return Math.max(min, Math.min(max, Math.floor(parsed)));
204
+ }
205
+ function nonEmptyString(value) {
206
+ const text = String(value || '').trim();
207
+ return text || null;
208
+ }
209
+ function uniqueStrings(value) {
210
+ if (!Array.isArray(value))
211
+ return [];
212
+ return [...new Set(value.map(nonEmptyString).filter((item) => Boolean(item)))];
213
+ }
214
+ function isExecutionStopReason(value) {
215
+ return new Set([
216
+ 'completed',
217
+ 'attempt_budget_exhausted',
218
+ 'time_budget_exhausted',
219
+ 'tool_budget_exhausted',
220
+ 'token_budget_exhausted',
221
+ 'no_progress',
222
+ 'user_input_required',
223
+ 'unverified_completion',
224
+ 'explicit_stop'
225
+ ]).has(String(value || ''));
226
+ }
@@ -0,0 +1,89 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { sha256 } from '../../fsx.js';
3
+ export function initialProgressRecoveryState(integritySnapshotHash) {
4
+ if (!/^[a-f0-9]{64}$/.test(integritySnapshotHash))
5
+ throw new Error('progress_integrity_snapshot_invalid');
6
+ return {
7
+ schema: 'sks.progress-recovery-state.v1', status: 'running', progress: [], last_progress_at: null,
8
+ warning_time_budget_exceeded: false, pause_cause: null, pause_reason: null, retry_count: 0,
9
+ integrity_snapshot_hash: integritySnapshotHash, resume_token_hash: null
10
+ };
11
+ }
12
+ export function recordProgress(state, signal) {
13
+ if (state.status !== 'running')
14
+ throw new Error('progress_signal_requires_running_state');
15
+ if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/.test(signal.id))
16
+ throw new Error('progress_signal_id_invalid');
17
+ if (!/^[a-f0-9]{64}$/.test(signal.digest) || !Number.isFinite(Date.parse(signal.observed_at)))
18
+ throw new Error('progress_signal_invalid');
19
+ const byIdentity = new Map(state.progress.map((entry) => [`${entry.kind}:${entry.id}:${entry.digest}`, entry]));
20
+ byIdentity.set(`${signal.kind}:${signal.id}:${signal.digest}`, signal);
21
+ return { ...state, progress: [...byIdentity.values()], last_progress_at: signal.observed_at };
22
+ }
23
+ export function applyTimeBudgetWarning(state, input) {
24
+ if (input.budgetMs <= 0)
25
+ throw new Error('progress_time_budget_invalid');
26
+ return { ...state, warning_time_budget_exceeded: input.nowMs - input.startedAtMs > input.budgetMs };
27
+ }
28
+ export function classifyRecoveryCause(error) {
29
+ const code = safeCode(error);
30
+ if (/^(?:econnreset|econnrefused|etimedout|enotfound|network_|upstream_network_)/.test(code))
31
+ return { cause: 'network', reason: code };
32
+ if (/^(?:auth_|credential_|unauthorized|forbidden)/.test(code))
33
+ return { cause: 'auth', reason: code };
34
+ if (/^mode_/.test(code))
35
+ return { cause: 'mode', reason: code };
36
+ if (/^account_/.test(code))
37
+ return { cause: 'account', reason: code };
38
+ if (/^(?:external_config_|catalog_)/.test(code))
39
+ return { cause: 'external-config', reason: code };
40
+ if (/^integrity_/.test(code))
41
+ return { cause: 'integrity', reason: code };
42
+ return { cause: 'unknown', reason: 'unknown_failure' };
43
+ }
44
+ export async function runWithProgressRecovery(input) {
45
+ const maxRetries = Math.max(0, Math.min(2, input.maxNetworkRetries ?? 2));
46
+ let state = input.state;
47
+ let firstNetworkReason = null;
48
+ for (let attempt = 0; attempt <= maxRetries; attempt += 1) {
49
+ try {
50
+ const value = await input.port.run(attempt);
51
+ return { value, state: { ...state, status: 'completed', pause_cause: null, pause_reason: null, resume_token_hash: null } };
52
+ }
53
+ catch (error) {
54
+ const failure = input.port.classify(error);
55
+ const sameNetworkCause = failure.cause === 'network' && (firstNetworkReason === null || firstNetworkReason === failure.reason);
56
+ if (failure.cause === 'network' && firstNetworkReason === null)
57
+ firstNetworkReason = failure.reason;
58
+ if (sameNetworkCause && attempt < maxRetries) {
59
+ state = { ...state, retry_count: attempt + 1 };
60
+ continue;
61
+ }
62
+ return { value: null, state: pauseState(state, failure.cause, failure.reason, attempt) };
63
+ }
64
+ }
65
+ return { value: null, state: pauseState(state, 'unknown', 'retry_loop_exhausted', maxRetries) };
66
+ }
67
+ export function issueManualResume(state) {
68
+ if (state.status !== 'paused')
69
+ throw new Error('progress_resume_requires_paused_state');
70
+ const token = randomBytes(24).toString('base64url');
71
+ return { state: { ...state, resume_token_hash: sha256(token) }, token };
72
+ }
73
+ export function confirmManualResume(state, token) {
74
+ if (state.status !== 'paused' || !state.resume_token_hash || sha256(token) !== state.resume_token_hash) {
75
+ throw new Error('progress_resume_token_invalid');
76
+ }
77
+ return { ...state, status: 'running', pause_cause: null, pause_reason: null, resume_token_hash: null };
78
+ }
79
+ function pauseState(state, cause, reason, retryCount) {
80
+ return { ...state, status: 'paused', pause_cause: cause, pause_reason: safeReason(reason), retry_count: retryCount, resume_token_hash: null };
81
+ }
82
+ function safeCode(error) {
83
+ const raw = error instanceof Error ? error.message : String(error || '');
84
+ const normalized = raw.trim().toLowerCase();
85
+ return /^[a-z][a-z0-9_]{1,99}$/.test(normalized) ? normalized : 'unknown_failure';
86
+ }
87
+ function safeReason(value) {
88
+ return /^[a-z][a-z0-9_]{1,99}$/.test(value) ? value : 'unknown_failure';
89
+ }
@@ -15,9 +15,11 @@ const STRONG_DATABASE_DOMAIN_RE = /\b(?:SQL|Supabase|Postgres|PostgreSQL|RLS|Pri
15
15
  const GENERIC_DATABASE_DOMAIN_RE = /\bDB\b|디비/i;
16
16
  const DATABASE_WORK_RE = /\b(?:apply|execute|run|fix|change|modify|migrate|audit|review|inspect|analy[sz]e|query|seed|backfill|optimi[sz]e|create|alter|drop|truncate|update|delete|repair)\b|적용|실행|수정|변경|검수|검토|점검|분석|조회|쿼리|시드|백필|최적화|생성|추가|삭제|복구|만들어/i;
17
17
  const DATABASE_CONTROL_SURFACE_META_RE = /\bsks\s+db\b|\b(?:db|database|migrate|migrations?)\b[\s\S]{0,48}\b(?:command|cli|route|routing|parser|classifier|regex|help|usage|topic|docs?|documentation|constant|keyword|alias)\b|\b(?:command|cli|route|routing|parser|classifier|regex|help|usage|topic|docs?|documentation|constant|keyword|alias)\b[\s\S]{0,48}\b(?:db|database|migrate|migrations?)\b|(?:db|디비|데이터베이스|migration|migrate|마이그레이션)\s*(?:커맨드|명령|명령어|CLI|라우트|라우팅|파서|분류기|정규식|도움말|헬프|사용법|토픽|문서|상수|키워드|별칭)|(?:커맨드|명령|명령어|CLI|라우트|라우팅|파서|분류기|정규식|도움말|헬프|사용법|토픽|문서|상수|키워드|별칭)[\s\S]{0,32}(?:db|디비|데이터베이스|migration|migrate|마이그레이션)/i;
18
- const PARALLEL_CUE_RE = /\b(parallel|subagents?|one agent per|fan out|multiple files|audit all|all files|independent slices?|naruto|runtime)\b|병렬|하위\s*에이전트|서브\s*에이전트|여러\s*파일|모든\s*파일|전체\s*검토|나루토|분담/i;
18
+ const PARALLEL_CUE_RE = /\b(parallel|subagents?|one agent per|fan out|independent slices?|naruto)\b|병렬|하위\s*에이전트|서브\s*에이전트|나루토|분담/i;
19
19
  const CHANGE_RE = /\b(fix|implement|implementation|change|edit|add|remove|delete|drop|modify|refactor|build|create|write|update|rename|rewrite|patch|apply|execute|repair|resolve|solve|publish|release|deploy|migrate)\b|\bwork\s+on\b|고쳐|고치|수정|변경|추가|삭제|구현|리팩터|작성|생성|만들어|업데이트|적용|실행|해결|이름\s*변경|배포|출시|마이그레이션/i;
20
+ const BOUNDED_READ_WORK_RE = /\b(audit|review|inspect|analy[sz]e|diagnose|trace|map|verify|test|check|investigate|evaluate)\b|감사|검토|점검|분석|진단|추적|매핑|검증|테스트|조사|평가/i;
20
21
  const TINY_CHANGE_RE = /\b(typo|copy|wording|label|spacing|whitespace|punctuation|spelling|one[-\s]?line|single[-\s]?(?:line|word)|rename only)\b|오타|문구|라벨|띄어쓰기|공백|맞춤법|구두점|한\s*줄|단어\s*하나|이름만\s*변경/i;
22
+ const NON_RUNTIME_TINY_SURFACE_RE = /\b(copy|wording|label|spacing|whitespace|punctuation|spelling|readme|docs?|documentation|comment)\b|문구|라벨|띄어쓰기|공백|맞춤법|구두점|문서|주석/i;
21
23
  const EXPLANATION_QUESTION_RE = /^(how\s+(?:do|can|should|would)\s+(?:i|we|you)\b|what\b|why\b|when\b|where\b|which\b|explain\b|tell me how\b)|(?:어떻게|무엇|뭐가|왜|언제|어디|방법|설명)(?:.*(?:인가요|일까요|하나요|해요|할까|\?))?$/i;
22
24
  const DIRECT_REQUEST_RE = /^(please\s+|can you\s+|could you\s+|would you\s+)|(?:해줘|해주세요|해\s*주세요|바꿔줘|고쳐줘|수정해줘|구현해줘)/i;
23
25
  const EXPLANATION_REQUEST_RE = /^(?:can|could|would) you explain\b|(?:설명|알려)\s*(?:해\s*줘|해\s*주세요|해달라|줘)\s*[.!?]*$/i;
@@ -27,7 +29,11 @@ export function classifyTaskProfile(prompt) {
27
29
  return 'passthrough';
28
30
  if (looksLikeExplanationQuestion(text))
29
31
  return 'answer';
30
- if (looksLikeDatabaseWorkRequest(text) || (CHANGE_RE.test(text) && NON_DATABASE_HIGH_RISK_RE.test(text)))
32
+ const databaseWork = looksLikeDatabaseWorkRequest(text);
33
+ const highRiskMutation = databaseWork || (CHANGE_RE.test(text) && NON_DATABASE_HIGH_RISK_RE.test(text));
34
+ if (looksLikeTinyChange(text) && (!highRiskMutation || NON_RUNTIME_TINY_SURFACE_RE.test(text)))
35
+ return 'tiny-change';
36
+ if (highRiskMutation)
31
37
  return 'high-risk';
32
38
  if (PARALLEL_CUE_RE.test(text) && CHANGE_RE.test(text))
33
39
  return 'parallel-write';
@@ -35,10 +41,10 @@ export function classifyTaskProfile(prompt) {
35
41
  return 'parallel-read';
36
42
  if (DATABASE_CONTROL_SURFACE_META_RE.test(text) && DATABASE_WORK_RE.test(text))
37
43
  return 'bounded-work';
38
- if (looksLikeTinyChange(text))
39
- return 'tiny-change';
40
44
  if (CHANGE_RE.test(text))
41
45
  return 'bounded-work';
46
+ if (BOUNDED_READ_WORK_RE.test(text))
47
+ return 'bounded-work';
42
48
  return 'answer';
43
49
  }
44
50
  export function gateProfileForTask(profileOrPrompt) {
@@ -1,11 +1,20 @@
1
1
  export function chooseVerificationBudget(input) {
2
+ const changedFiles = input.changedFiles.map((file) => String(file || '').replace(/\\/g, '/'));
3
+ const failedChecks = (input.failedChecks || []).filter(Boolean);
4
+ const releaseSurface = changedFiles.some((file) => /(?:^|\/)(?:package(?:-lock)?\.json|CHANGELOG\.md|\.github\/workflows\/|src\/core\/release\/|src\/scripts\/(?:prepublish|publish|release))/.test(file));
2
5
  if (input.taskProfile === 'passthrough')
3
6
  return 'none';
4
7
  if (input.taskProfile === 'answer')
5
8
  return 'none';
9
+ if (releaseSurface)
10
+ return 'release';
11
+ if (failedChecks.length > 0)
12
+ return input.taskProfile === 'high-risk' ? 'release' : 'confidence';
6
13
  if (input.taskProfile === 'tiny-change')
7
- return 'single-check';
14
+ return changedFiles.length > 1 ? 'affected' : 'single-check';
8
15
  if (input.taskProfile === 'high-risk')
9
16
  return 'confidence';
17
+ if (changedFiles.length >= 8)
18
+ return 'confidence';
10
19
  return 'affected';
11
20
  }
@@ -0,0 +1,94 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { canonicalJson } from '../../json/canonical.js';
3
+ export function buildIntentContract(input) {
4
+ const highRiskEffect = ['auth', 'security', 'delete', 'deploy', 'dependency'].includes(input.effect);
5
+ let risk = highRiskEffect ? 'HEAVY' : 'FAST';
6
+ if (input.requestedRisk === 'HEAVY')
7
+ risk = 'HEAVY';
8
+ if (input.requestedRisk === 'ULTRA') {
9
+ if (!input.explicitUltraOptIn)
10
+ throw new Error('intent_ultra_requires_explicit_opt_in');
11
+ risk = 'ULTRA';
12
+ }
13
+ const base = {
14
+ schema: 'sks.intent-contract.v1',
15
+ natural_language_effect: normalizeEffectText(input.naturalLanguageEffect),
16
+ effect: input.effect,
17
+ observed_changed_paths: [...new Set((input.observedChangedPaths || []).map(normalizeRelativePath))].sort(),
18
+ canonical_command: normalizeCommand(input.canonicalCommand),
19
+ target_hashes: [...new Set(input.targetHashes)].sort(),
20
+ policy_version: safeIdentifier(input.policyVersion, 'intent_policy_version_invalid'),
21
+ mode_snapshot: input.modeSnapshot,
22
+ evidence_state: input.evidenceState,
23
+ retry_budget: Math.max(0, Math.min(2, input.retryBudget ?? 0)),
24
+ risk,
25
+ risk_reason: highRiskEffect ? `effect_${input.effect}_requires_heavy` : risk === 'FAST' ? 'effect_is_fast_eligible' : 'user_requested_risk_raise',
26
+ force: input.force === true
27
+ };
28
+ if (!base.target_hashes.length || base.target_hashes.some((hash) => !/^[a-f0-9]{64}$/.test(hash)))
29
+ throw new Error('intent_target_hash_invalid');
30
+ const contract = { ...base, contract_hash: stableHash(base) };
31
+ return deepFreeze(contract);
32
+ }
33
+ export function decideIntentReplay(previous, current) {
34
+ const reasons = [];
35
+ if (previous.policy_version !== current.policy_version)
36
+ reasons.push('policy_version_changed');
37
+ if (previous.mode_snapshot !== current.mode_snapshot)
38
+ reasons.push('mode_snapshot_changed');
39
+ if (JSON.stringify(previous.target_hashes) !== JSON.stringify(current.target_hashes))
40
+ reasons.push('target_hash_changed');
41
+ if (previous.effect !== current.effect || previous.canonical_command !== current.canonical_command)
42
+ reasons.push('intent_effect_changed');
43
+ if (reasons.length)
44
+ return { action: 'replan', reasons };
45
+ if (current.evidence_state !== 'valid') {
46
+ if (current.risk === 'FAST')
47
+ return { action: 'refresh_direct_evidence', reasons: ['evidence_expired_or_missing'] };
48
+ return { action: 'blocked', reasons: ['heavy_evidence_required'] };
49
+ }
50
+ return { action: 'reuse', reasons: [] };
51
+ }
52
+ export function terminalStateForVerification(input) {
53
+ if (input.paused)
54
+ return 'paused';
55
+ if (!input.executionOk)
56
+ return 'failed';
57
+ if (input.verificationOk !== true)
58
+ return 'unverified';
59
+ return 'completed';
60
+ }
61
+ function normalizeEffectText(value) {
62
+ const text = String(value || '').trim().replace(/\s+/g, ' ');
63
+ if (!text || text.length > 1000)
64
+ throw new Error('intent_effect_text_invalid');
65
+ return text;
66
+ }
67
+ function normalizeRelativePath(value) {
68
+ const normalized = String(value || '').replace(/\\/g, '/').replace(/^\.\//, '');
69
+ if (!normalized || normalized.startsWith('/') || normalized.split('/').includes('..'))
70
+ throw new Error('intent_changed_path_invalid');
71
+ return normalized;
72
+ }
73
+ function normalizeCommand(value) {
74
+ const command = String(value || '').trim().replace(/\s+/g, ' ');
75
+ if (!/^sks(?:\s|$)/.test(command))
76
+ throw new Error('intent_canonical_command_invalid');
77
+ return command;
78
+ }
79
+ function safeIdentifier(value, code) {
80
+ if (!/^[A-Za-z0-9][A-Za-z0-9._:-]{0,199}$/.test(String(value || '')))
81
+ throw new Error(code);
82
+ return value;
83
+ }
84
+ function stableHash(value) {
85
+ return createHash('sha256').update(canonicalJson(value)).digest('hex');
86
+ }
87
+ function deepFreeze(value) {
88
+ if (value && typeof value === 'object' && !Object.isFrozen(value)) {
89
+ Object.freeze(value);
90
+ for (const child of Object.values(value))
91
+ deepFreeze(child);
92
+ }
93
+ return value;
94
+ }
@@ -63,8 +63,6 @@ function scopeForKind(kind) {
63
63
  return 'codex_app_process';
64
64
  case 'codex_lb_auth_change':
65
65
  return 'codex_lb_auth';
66
- case 'zellij_install':
67
- return 'zellij_install';
68
66
  case 'skill_snapshot_promotion':
69
67
  return 'skill_snapshot_promotion';
70
68
  default: