sneakoscope 7.1.0 → 7.3.0

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 (534) hide show
  1. package/README.md +9 -1
  2. package/config/architecture-budgets.v1.json +1 -8
  3. package/crates/sks-core/Cargo.lock +225 -1
  4. package/crates/sks-core/Cargo.toml +8 -1
  5. package/crates/sks-core/src/main.rs +7 -1
  6. package/crates/sks-core/src/search/files.rs +114 -0
  7. package/crates/sks-core/src/search/mod.rs +274 -0
  8. package/crates/sks-core/src/search/text.rs +175 -0
  9. package/dist/bin/sks-dispatch.js +4 -3
  10. package/dist/cli/command-manifest-lite.js +177 -6
  11. package/dist/cli/command-registry.js +42 -8
  12. package/dist/cli/help.js +30 -0
  13. package/dist/cli/install-helpers-codex-lb-config.js +9 -6
  14. package/dist/cli/install-helpers-codex-lb-selftest-chain.js +1 -1
  15. package/dist/cli/install-helpers-install-support.js +1 -1
  16. package/dist/cli/install-helpers.js +19 -9
  17. package/dist/cli/router.js +16 -3
  18. package/dist/commands/codex-app.js +40 -5
  19. package/dist/commands/doctor-profile.js +78 -0
  20. package/dist/commands/doctor.js +29 -69
  21. package/dist/commands/search.js +4 -0
  22. package/dist/config/skills-manifest.json +53 -60
  23. package/dist/core/agent-bridge/agent-manifest.js +22 -26
  24. package/dist/core/agent-bridge/host-capability-policy.js +109 -8
  25. package/dist/core/agent-bridge/host-capability-runtime.js +178 -50
  26. package/dist/core/agent-guidance/directive-registry.js +123 -0
  27. package/dist/core/agents/agent-effort-policy.js +45 -6
  28. package/dist/core/agents/agent-worker-pipeline.js +1 -3
  29. package/dist/core/agents/native-worker-backend-router.js +43 -19
  30. package/dist/core/auto-review.js +1 -3
  31. package/dist/core/code-structure.js +282 -19
  32. package/dist/core/codex/codex-config-guard.js +14 -4
  33. package/dist/core/codex/codex-config-toml.js +1 -3
  34. package/dist/core/codex-app/codex-agent-role-sync.js +1 -3
  35. package/dist/core/codex-app/codex-app-fast-ui-repair.js +14 -1
  36. package/dist/core/codex-app/codex-app-types.js +2 -3
  37. package/dist/core/codex-app/codex-desktop-routing-ownership.js +91 -0
  38. package/dist/core/codex-app/codex-hook-approval-probe.js +1 -3
  39. package/dist/core/codex-app/codex-hook-lifecycle.js +1 -3
  40. package/dist/core/codex-app/codex-init-deep.js +22 -10
  41. package/dist/core/codex-app/codex-model-catalog.js +384 -0
  42. package/dist/core/codex-app/codex-models-cache.js +160 -0
  43. package/dist/core/codex-app/desktop-routing-snapshot.js +233 -0
  44. package/dist/core/codex-app/glm-profile-installer.js +1 -3
  45. package/dist/core/codex-app/mcp-manager.js +1 -3
  46. package/dist/core/codex-app/menubar/constants.js +3 -0
  47. package/dist/core/codex-app/menubar/installer.js +11 -1
  48. package/dist/core/codex-app/multi-provider-router-support.js +202 -0
  49. package/dist/core/codex-app/multi-provider-router.js +379 -0
  50. package/dist/core/codex-app/openrouter-activate.js +189 -26
  51. package/dist/core/codex-app/openrouter-base-instructions.js +1 -0
  52. package/dist/core/codex-app/openrouter-model-catalog.js +217 -0
  53. package/dist/core/codex-app/role-model-catalog-priority.js +61 -0
  54. package/dist/core/codex-app.js +30 -6
  55. package/dist/core/codex-compat/codex-hook-semantic-validator.js +1 -3
  56. package/dist/core/codex-control/codex-app-server-v2-client.js +39 -2
  57. package/dist/core/codex-lb/codex-lb-env.js +1 -3
  58. package/dist/core/codex-lb/codex-lb-tool-catalog.js +6 -1
  59. package/dist/core/codex-native/codex-native-feature-broker.js +2 -6
  60. package/dist/core/codex-native/codex-native-interop-policy.js +1 -3
  61. package/dist/core/codex-native/codex-native-reference-cache.js +1 -3
  62. package/dist/core/codex-native/codex-native-reference-source.js +1 -3
  63. package/dist/core/codex-native/codex-native-repair-transaction.js +1 -3
  64. package/dist/core/codex-native/core-skill-manifest.js +3 -2
  65. package/dist/core/codex-native/native-capability-repair-matrix.js +1 -3
  66. package/dist/core/codex-plugins/codex-plugin-repair.js +1 -3
  67. package/dist/core/codex-runtime/codex-desktop-config-policy.js +4 -4
  68. package/dist/core/commands/agent-bridge-command.js +24 -3
  69. package/dist/core/commands/image-ux-review-command.js +5 -11
  70. package/dist/core/commands/menubar-command.js +1 -1
  71. package/dist/core/commands/naruto-command.js +40 -13
  72. package/dist/core/commands/pipeline-command.js +5 -2
  73. package/dist/core/commands/release-command.js +63 -1
  74. package/dist/core/commands/remote-command.js +18 -0
  75. package/dist/core/commands/search-command.js +151 -0
  76. package/dist/core/commands/telegram-command.js +251 -108
  77. package/dist/core/commands/uninstall-command.js +1 -1
  78. package/dist/core/config/secret-preservation.js +1 -3
  79. package/dist/core/context7-client.js +2 -1
  80. package/dist/core/db-review.js +704 -0
  81. package/dist/core/db-safety.js +17 -23
  82. package/dist/core/doctor/browser-use-repair.js +1 -3
  83. package/dist/core/doctor/codex-startup-config-repair.js +1 -3
  84. package/dist/core/doctor/computer-use-repair.js +1 -3
  85. package/dist/core/doctor/context7-mcp-repair.js +1 -3
  86. package/dist/core/doctor/current-project-guidance.js +1 -3
  87. package/dist/core/doctor/doctor-codex-startup-repair.js +1 -3
  88. package/dist/core/doctor/doctor-dirty-planner.js +2 -2
  89. package/dist/core/doctor/doctor-native-capability-repair.js +1 -3
  90. package/dist/core/doctor/doctor-transaction.js +1 -3
  91. package/dist/core/doctor/imagegen-repair.js +1 -3
  92. package/dist/core/doctor/legacy-global-hook-cleanup.js +1 -3
  93. package/dist/core/doctor/mcp-transport-collision-repair.js +1 -3
  94. package/dist/core/doctor/retired-managed-residue-private.js +1 -3
  95. package/dist/core/doctor/supabase-mcp-repair.js +1 -3
  96. package/dist/core/engineering-sanity-review.js +186 -0
  97. package/dist/core/errors/message.js +3 -0
  98. package/dist/core/evidence/evidence-schema.js +1 -3
  99. package/dist/core/feature-fixtures.js +1 -0
  100. package/dist/core/feature-registry.js +1 -3
  101. package/dist/core/fsx.js +13 -0
  102. package/dist/core/git-hygiene/shared-memory-publish.js +1 -3
  103. package/dist/core/git-hygiene/validators.js +1 -3
  104. package/dist/core/harness-guard.js +21 -3
  105. package/dist/core/hooks-runtime/hook-context.js +2 -2
  106. package/dist/core/image-ux-review/imagegen-adapter.js +52 -56
  107. package/dist/core/image-ux-review/real-callout-extractor.js +6 -1
  108. package/dist/core/image-ux-review.js +3 -5
  109. package/dist/core/imagegen/codex-lb-imagegen-target.js +70 -0
  110. package/dist/core/imagegen/imagegen-capability.js +11 -11
  111. package/dist/core/imagegen/imagegen-evidence.js +32 -0
  112. package/dist/core/init/skills.js +9 -11
  113. package/dist/core/init.js +4 -6
  114. package/dist/core/json/records.js +9 -0
  115. package/dist/core/json-schema-validator.js +1 -3
  116. package/dist/core/lean-engineering-policy.js +54 -0
  117. package/dist/core/loops/loop-continuation-enforcer.js +1 -3
  118. package/dist/core/mad-sks/sql-plane/mcp-executor.js +2 -1
  119. package/dist/core/mad-sks/sql-plane/policy.js +2 -1
  120. package/dist/core/managed-assets/managed-assets-manifest.js +4 -3
  121. package/dist/core/mcp-config/codex-cli-adapter.js +1 -3
  122. package/dist/core/mcp-config/config-reader.js +2 -3
  123. package/dist/core/mcp-config/guarded-patch.js +1 -1
  124. package/dist/core/mcp-config/health-check.js +2 -1
  125. package/dist/core/mcp-config/mutation.js +1 -1
  126. package/dist/core/mcp-config/restore.js +1 -1
  127. package/dist/core/mcp-config/secret-policy.js +1 -3
  128. package/dist/core/migration/migration-transaction-journal.js +3 -3
  129. package/dist/core/naruto/naruto-concurrency-governor.js +2 -2
  130. package/dist/core/perf/import-graph-budget.js +91 -1
  131. package/dist/core/pipeline/pipeline-plan-writer.js +1 -1
  132. package/dist/core/pipeline-internals/runtime-core.js +121 -23
  133. package/dist/core/pipeline-internals/runtime-gates.js +193 -4
  134. package/dist/core/pipeline.js +1 -1
  135. package/dist/core/ppt-review/slide-imagegen-review.js +7 -7
  136. package/dist/core/ppt.js +3 -3
  137. package/dist/core/product-design-app-server.js +2 -1
  138. package/dist/core/proof/fake-real-proof-policy.js +1 -3
  139. package/dist/core/proof/root-cause-policy.js +1 -3
  140. package/dist/core/proof/validation.js +1 -3
  141. package/dist/core/provider/model-router.js +4 -0
  142. package/dist/core/provider/provider-context.js +1 -3
  143. package/dist/core/providers/openrouter/openrouter-account.js +1 -3
  144. package/dist/core/quality/helper-dedup.js +0 -0
  145. package/dist/core/recallpulse.js +1 -1
  146. package/dist/core/release/file-ownership.js +26 -17
  147. package/dist/core/release/macos-menubar-proof.js +59 -1
  148. package/dist/core/release/main-push-guard.js +288 -24
  149. package/dist/core/release/main-push-receipt.js +10 -45
  150. package/dist/core/release/package-size-budget.js +1 -1
  151. package/dist/core/release/release-gate-contract.js +2 -0
  152. package/dist/core/release/release-pack-receipt.js +1 -1
  153. package/dist/core/release/release-proof-io.js +33 -0
  154. package/dist/core/release/release-upgrade-baseline.js +9 -0
  155. package/dist/core/release/runtime-script-pack-closure.js +153 -4
  156. package/dist/core/release/stage-publish.js +194 -0
  157. package/dist/core/remote/index.js +2 -0
  158. package/dist/core/remote/local-worker-client.js +35 -0
  159. package/dist/core/remote/machine-registry.js +18 -13
  160. package/dist/core/remote/owner-proof.js +1 -3
  161. package/dist/core/remote/protocol.js +1 -3
  162. package/dist/core/remote/readiness.js +1 -3
  163. package/dist/core/remote/session-binding.js +153 -0
  164. package/dist/core/remote/session-index.js +1 -3
  165. package/dist/core/remote/types.js +1 -0
  166. package/dist/core/remote/worker.js +228 -14
  167. package/dist/core/responses-stream.js +151 -0
  168. package/dist/core/routes/dollar-manifest-lite.js +1 -1
  169. package/dist/core/routes.js +8 -8
  170. package/dist/core/rust-accelerator.js +12 -2
  171. package/dist/core/safety/ssot-guard.js +1 -3
  172. package/dist/core/search/benchmark.js +358 -0
  173. package/dist/core/search/cache.js +65 -0
  174. package/dist/core/search/context.js +144 -0
  175. package/dist/core/search/doctor.js +74 -0
  176. package/dist/core/search/files.js +192 -0
  177. package/dist/core/search/index.js +5 -0
  178. package/dist/core/search/ipc.js +64 -0
  179. package/dist/core/search/provider.js +142 -0
  180. package/dist/core/search/rust-bridge.js +24 -0
  181. package/dist/core/search/structure.js +230 -0
  182. package/dist/core/search/symbol.js +272 -0
  183. package/dist/core/search/text.js +146 -0
  184. package/dist/core/search/types.js +22 -0
  185. package/dist/core/search/typescript-ls.js +215 -0
  186. package/dist/core/search-visibility/discovery.js +1 -3
  187. package/dist/core/skill-forge.js +1 -1
  188. package/dist/core/stop-gate/gate-evaluator.js +3 -3
  189. package/dist/core/stop-gate/stop-gate-check.js +1 -3
  190. package/dist/core/structured-output-adapter.js +62 -2
  191. package/dist/core/subagents/agent-catalog.js +56 -43
  192. package/dist/core/subagents/model-policy.js +17 -7
  193. package/dist/core/subagents/naruto-proof-projection.js +2 -6
  194. package/dist/core/subagents/official-subagent-config.js +1 -3
  195. package/dist/core/subagents/official-subagent-preparation.js +73 -10
  196. package/dist/core/subagents/official-subagent-prompt.js +85 -18
  197. package/dist/core/subagents/official-subagent-runner.js +10 -5
  198. package/dist/core/subagents/role-model-preferences.js +202 -44
  199. package/dist/core/subagents/subagent-evidence.js +1 -3
  200. package/dist/core/subagents/thread-budget.js +1 -1
  201. package/dist/core/subagents/triwiki-attention.js +1 -5
  202. package/dist/core/telegram/config.js +29 -12
  203. package/dist/core/telegram/hub.js +8 -2
  204. package/dist/core/telegram/index.js +2 -0
  205. package/dist/core/telegram/messages.js +8 -2
  206. package/dist/core/telegram/runtime-projection.js +8 -5
  207. package/dist/core/telegram/runtime.js +19 -9
  208. package/dist/core/telegram/service.js +181 -0
  209. package/dist/core/telegram/setup.js +220 -0
  210. package/dist/core/text/regex.js +3 -0
  211. package/dist/core/text/strings.js +6 -0
  212. package/dist/core/triwiki-wrongness/image-wrongness.js +1 -3
  213. package/dist/core/triwiki-wrongness/wrongness-ledger.js +1 -3
  214. package/dist/core/triwiki-wrongness/wrongness-proof-linker.js +1 -3
  215. package/dist/core/triwiki-wrongness/wrongness-retrieval.js +1 -3
  216. package/dist/core/triwiki-wrongness/wrongness-schema.js +1 -3
  217. package/dist/core/triwiki-wrongness/wrongness-trust-policy.js +1 -3
  218. package/dist/core/trust-kernel/completion-contract.js +1 -3
  219. package/dist/core/trust-kernel/route-contract.js +1 -3
  220. package/dist/core/update/update-migration-state.js +1 -3
  221. package/dist/core/update-check.js +20 -6
  222. package/dist/core/verification/diff-quality.js +3 -4
  223. package/dist/core/verification/impact-scan.js +36 -89
  224. package/dist/core/verification/mistake-rule-compiler.js +17 -4
  225. package/dist/core/version-manager.js +3 -20
  226. package/dist/core/version.js +1 -1
  227. package/dist/native/sks-menubar/Sources/ControlCenterWindowController.swift +23 -3
  228. package/dist/native/sks-menubar/Sources/ControlKit.swift +102 -0
  229. package/dist/native/sks-menubar/Sources/DiagnosticsViewController.swift +23 -11
  230. package/dist/native/sks-menubar/Sources/MCPServersViewController.swift +7 -3
  231. package/dist/native/sks-menubar/Sources/OperationCoordinator.swift +17 -1
  232. package/dist/native/sks-menubar/Sources/OverviewViewController.swift +22 -15
  233. package/dist/native/sks-menubar/Sources/ProcessClient.swift +15 -5
  234. package/dist/native/sks-menubar/Sources/ProvidersMultiProvider.swift +324 -0
  235. package/dist/native/sks-menubar/Sources/ProvidersOpenRouter.swift +154 -214
  236. package/dist/native/sks-menubar/Sources/ProvidersRoleModels.swift +252 -0
  237. package/dist/native/sks-menubar/Sources/ProvidersViewController.swift +77 -71
  238. package/dist/native/sks-menubar/Sources/RemoteTelegramViewController.swift +167 -51
  239. package/dist/native/sks-menubar/Sources/SettingsViewController.swift +14 -5
  240. package/dist/native/sks-menubar/Sources/SidebarItem.swift +15 -1
  241. package/dist/native/sks-menubar/Sources/StatusItemController.swift +2 -2
  242. package/dist/native/sks-menubar/Sources/UpdatesViewController.swift +16 -12
  243. package/dist/scripts/agent-guidance-dedup-check.js +23 -0
  244. package/dist/scripts/agent-message-bus-reader-check.js +1 -1
  245. package/dist/scripts/all-feature-deep-completion-check.js +1 -1
  246. package/dist/scripts/appshots-thread-attachment-discovery-check.js +1 -1
  247. package/dist/scripts/architecture-guard-check.js +1 -2
  248. package/dist/scripts/certificate-sla-check.js +1 -1
  249. package/dist/scripts/cli-output-consistency-check.js +1 -1
  250. package/dist/scripts/codex-0-134-runner-truth-check.js +1 -1
  251. package/dist/scripts/codex-0138-capability-artifact-check.js +1 -1
  252. package/dist/scripts/codex-0138-capability-check.js +1 -1
  253. package/dist/scripts/codex-0138-doctor-check.js +1 -1
  254. package/dist/scripts/codex-0138-feature-probes-check.js +1 -1
  255. package/dist/scripts/codex-0144-app-server-v2-check.js +1 -1
  256. package/dist/scripts/codex-0144-binary-identity-check.js +1 -1
  257. package/dist/scripts/codex-0144-capability-check.js +1 -1
  258. package/dist/scripts/codex-0144-core-real-probes-check.js +1 -1
  259. package/dist/scripts/codex-0144-manifest-check.js +1 -1
  260. package/dist/scripts/codex-0144-policy-check.js +1 -1
  261. package/dist/scripts/codex-0144-thread-store-check.js +1 -1
  262. package/dist/scripts/codex-agent-role-rich-content-check.js +2 -2
  263. package/dist/scripts/codex-agent-role-sync-check.js +2 -2
  264. package/dist/scripts/codex-agent-type-routing-check.js +2 -2
  265. package/dist/scripts/codex-app-execution-profile-check.js +2 -2
  266. package/dist/scripts/codex-app-handoff-check.js +1 -1
  267. package/dist/scripts/codex-app-handoff-launch-check.js +1 -1
  268. package/dist/scripts/codex-control-tool-output-continuity-audit-check.js +1 -1
  269. package/dist/scripts/codex-lb-fast-ui-preservation-check.js +1 -3
  270. package/dist/scripts/codex-native-feature-broker-blackbox.js +2 -2
  271. package/dist/scripts/codex-native-feature-broker-check.js +2 -2
  272. package/dist/scripts/{sks-3-1-6-directive-check-lib.js → codex-native-gate-lib.js} +5 -5
  273. package/dist/scripts/codex-native-harness-compat-check.js +2 -2
  274. package/dist/scripts/codex-native-hook-lifecycle-proof-check.js +2 -2
  275. package/dist/scripts/codex-plugin-app-template-policy-check.js +1 -1
  276. package/dist/scripts/codex-sdk-backend-router-check.js +1 -1
  277. package/dist/scripts/codex-sdk-capability-check.js +1 -1
  278. package/dist/scripts/context7-evidence-dedupe-check.js +1 -1
  279. package/dist/scripts/core-skill-card-schema-check.js +1 -1
  280. package/dist/scripts/core-skill-deployment-snapshot-check.js +1 -1
  281. package/dist/scripts/core-skill-heldout-validation-check.js +1 -1
  282. package/dist/scripts/core-skill-no-inference-optimizer-check.js +1 -1
  283. package/dist/scripts/core-skill-patch-check.js +1 -1
  284. package/dist/scripts/core-skill-route-runtime-integration-check.js +1 -1
  285. package/dist/scripts/current-command-surface-check.js +1 -1
  286. package/dist/scripts/current-surface-update-e2e-check.js +4 -1
  287. package/dist/scripts/current-upgrade-matrix-check.js +1 -1
  288. package/dist/scripts/dfix-fixture-check.js +1 -1
  289. package/dist/scripts/dfix-patch-handoff-check.js +1 -1
  290. package/dist/scripts/dfix-verification-check.js +1 -1
  291. package/dist/scripts/dfix-verification-recommendation-check.js +1 -1
  292. package/dist/scripts/docs-truthfulness-check.js +16 -3
  293. package/dist/scripts/doctor-codex-app-harness-check.js +2 -2
  294. package/dist/scripts/evidence-flagship-coverage-check.js +1 -1
  295. package/dist/scripts/{sks-1-18-gate-lib.js → gate-lib.js} +1 -1
  296. package/dist/scripts/gate-policy-audit-check.js +4 -1
  297. package/dist/scripts/git-worktree-checkpoint-check.js +1 -1
  298. package/dist/scripts/git-worktree-cross-rebase-check.js +1 -1
  299. package/dist/scripts/git-worktree-diff-envelope-check.js +1 -1
  300. package/dist/scripts/git-worktree-dirty-lock-check.js +1 -1
  301. package/dist/scripts/git-worktree-dirty-main-detection-check.js +1 -1
  302. package/dist/scripts/git-worktree-integration-primary-check.js +1 -1
  303. package/dist/scripts/git-worktree-manifest-append-check.js +1 -1
  304. package/dist/scripts/git-worktree-untracked-diff-check.js +1 -1
  305. package/dist/scripts/harness-benchmark-check.js +1 -1
  306. package/dist/scripts/helper-dedup-check.js +62 -0
  307. package/dist/scripts/hook-latency-budget-check.js +1 -1
  308. package/dist/scripts/image-artifact-path-contract-check.js +1 -1
  309. package/dist/scripts/imagegen-real-smoke-check.js +2 -5
  310. package/dist/scripts/installed-package-smoke-check.js +1 -1
  311. package/dist/scripts/legacy-gate-inventory-check.js +1 -1
  312. package/dist/scripts/legacy-gate-purge-check.js +1 -1
  313. package/dist/scripts/legacy-strong-inventory-check.js +1 -1
  314. package/dist/scripts/lib/codex-sdk-gate-lib.js +1 -1
  315. package/dist/scripts/mad-sks-launch-sql-plane-boundary-check.js +1 -1
  316. package/dist/scripts/mad-sks-sql-plane-capability-check.js +1 -1
  317. package/dist/scripts/mad-sks-sql-plane-lifecycle-hook-decision-check.js +1 -1
  318. package/dist/scripts/mad-sks-sql-plane-result-lifecycle-check.js +1 -1
  319. package/dist/scripts/managed-config-merge-check.js +1 -1
  320. package/dist/scripts/mcp-plugin-inventory-check.js +1 -1
  321. package/dist/scripts/model-call-concurrency-check.js +1 -1
  322. package/dist/scripts/mutation-callsite-coverage-check.js +1 -1
  323. package/dist/scripts/naruto-ssot-gate-aliases-check.js +1 -1
  324. package/dist/scripts/naruto-ssot-pipeline-default-check.js +1 -1
  325. package/dist/scripts/naruto-ssot-route-normalization-check.js +1 -1
  326. package/dist/scripts/naruto-ssot-routing-check.js +1 -1
  327. package/dist/scripts/naruto-worktree-coding-blackbox.js +1 -1
  328. package/dist/scripts/native-capability-repair-matrix-check.js +1 -1
  329. package/dist/scripts/native-image-generation-repair-check.js +1 -1
  330. package/dist/scripts/official-subagent-workflow-check.js +3 -3
  331. package/dist/scripts/package-published-contract-check.js +37 -4
  332. package/dist/scripts/packlist-performance-check.js +17 -1
  333. package/dist/scripts/pipeline-codex-native-doctor-mad-routing-real-blackbox.js +1 -3
  334. package/dist/scripts/ppt-real-export-adapter-check.js +1 -1
  335. package/dist/scripts/ppt-real-imagegen-wiring-check.js +1 -1
  336. package/dist/scripts/ppt-reexport-rereview-check.js +1 -1
  337. package/dist/scripts/prepublish-fast-check.js +1 -1
  338. package/dist/scripts/probe-memoization-check.js +2 -2
  339. package/dist/scripts/prompt-placeholder-guard-check.js +1 -1
  340. package/dist/scripts/qa-loop-app-handoff-capability-check.js +1 -1
  341. package/dist/scripts/qa-loop-app-handoff-check.js +1 -1
  342. package/dist/scripts/qa-loop-app-handoff-cli-check.js +1 -1
  343. package/dist/scripts/qa-loop-app-handoff-confirmation-check.js +1 -1
  344. package/dist/scripts/qa-loop-app-handoff-gate-lifecycle-check.js +1 -1
  345. package/dist/scripts/qa-loop-app-handoff-launch-check.js +1 -1
  346. package/dist/scripts/qa-loop-app-handoff-status-lifecycle-check.js +1 -1
  347. package/dist/scripts/qa-loop-budget-policy-check.js +1 -1
  348. package/dist/scripts/qa-loop-effort-escalation-check.js +1 -1
  349. package/dist/scripts/qa-loop-execution-profile-routing-check.js +2 -2
  350. package/dist/scripts/qa-loop-image-path-exposure-check.js +1 -1
  351. package/dist/scripts/qa-loop-image-path-prompt-injection-check.js +1 -1
  352. package/dist/scripts/{sks-1-12-real-execution-check-lib.js → real-execution-check-lib.js} +1 -1
  353. package/dist/scripts/release-affected-selector-check.js +1 -1
  354. package/dist/scripts/release-aggressive-resource-governor-check.js +1 -1
  355. package/dist/scripts/release-cache-glob-hashing-check.js +1 -1
  356. package/dist/scripts/release-cache-input-classifier-check.js +1 -1
  357. package/dist/scripts/release-cache-neutralization-report-check.js +1 -1
  358. package/dist/scripts/release-cache-version-neutral-fixture-check.js +1 -1
  359. package/dist/scripts/release-dynamic-presets-check.js +2 -2
  360. package/dist/scripts/release-full-parallelism-blackbox.js +1 -1
  361. package/dist/scripts/release-gate-batch-runner-check.js +1 -1
  362. package/dist/scripts/release-gate-budget-check.js +1 -1
  363. package/dist/scripts/release-gate-dag-runner-check.js +1 -1
  364. package/dist/scripts/release-latency-slo-check.js +1 -1
  365. package/dist/scripts/release-metadata-check.js +256 -2
  366. package/dist/scripts/release-parallel-speed-budget-check.js +1 -1
  367. package/dist/scripts/release-proof-truth-check.js +1 -1
  368. package/dist/scripts/release-provenance-check.js +4 -2
  369. package/dist/scripts/release-runtime-truth-matrix-check.js +1 -1
  370. package/dist/scripts/research-blueprint-densifier-check.js +1 -1
  371. package/dist/scripts/research-claim-builder-check.js +1 -1
  372. package/dist/scripts/research-complete-package-fixture-check.js +1 -1
  373. package/dist/scripts/research-execution-profile-routing-check.js +2 -2
  374. package/dist/scripts/research-final-reviewer-blackbox.js +1 -1
  375. package/dist/scripts/{sks-3-1-4-directive-check-lib.js → runtime-domain-gate-lib.js} +2 -2
  376. package/dist/scripts/runtime-proof-summary-check.js +1 -1
  377. package/dist/scripts/runtime-script-pack-closure-check.js +7 -1
  378. package/dist/scripts/scheduler-batch-dispatch-check.js +1 -1
  379. package/dist/scripts/scheduler-parallel-proof-consistency-check.js +1 -1
  380. package/dist/scripts/scheduler-utilization-integral-check.js +1 -1
  381. package/dist/scripts/search-visibility-gate-lib.js +1 -1
  382. package/dist/scripts/secret-preservation-check.js +1 -1
  383. package/dist/scripts/seo-geo-geo-disambiguation-check.js +1 -1
  384. package/dist/scripts/seo-geo-skill-rich-content-check.js +1 -1
  385. package/dist/scripts/side-effect-runtime-report-check.js +1 -1
  386. package/dist/scripts/{sks-3-1-8-check-lib.js → skill-fixture-check-lib.js} +1 -1
  387. package/dist/scripts/skill-name-canonicalizer-check.js +1 -1
  388. package/dist/scripts/skills-manifest-continuity-check.js +1 -1
  389. package/dist/scripts/sks-uninstall-regression-check.js +1 -1
  390. package/dist/scripts/sksd-daemon-check.js +1 -1
  391. package/dist/scripts/super-search-provider-interface-check.js +1 -1
  392. package/dist/scripts/triwiki-cache-key-check.js +1 -1
  393. package/dist/scripts/triwiki-proof-bank-blackbox.js +2 -2
  394. package/dist/scripts/triwiki-proof-bank-check.js +1 -1
  395. package/dist/scripts/triwiki-proof-card-check.js +1 -1
  396. package/dist/scripts/type-surface-codex-app-check.js +2 -2
  397. package/dist/scripts/{sks-3-1-5-directive-check-lib.js → typed-routing-gate-lib.js} +2 -2
  398. package/dist/scripts/ultra-router-auto-router-check.js +1 -1
  399. package/dist/scripts/ux-review-extract-wires-real-extractor-check.js +1 -1
  400. package/dist/scripts/ux-review-patch-diff-recheck-check.js +1 -1
  401. package/dist/scripts/ux-review-run-wires-imagegen-check.js +9 -2
  402. package/package.json +5 -7
  403. package/release-gates.v2.json +66 -11
  404. package/runtime-required-scripts.json +138 -14
  405. package/config/bench-baseline.json +0 -7
  406. package/dist/core/codex-app/sks-menubar.js +0 -1
  407. package/dist/core/release/release-closure-contract.js +0 -30
  408. package/dist/core/release/release-closure-helpers.js +0 -293
  409. package/dist/core/release/release-closure-validation.js +0 -284
  410. package/dist/core/release/release-closure.js +0 -163
  411. package/dist/scripts/build-dist.js +0 -124
  412. package/dist/scripts/build-once-runner-check.js +0 -6
  413. package/dist/scripts/canonical-test-runner.js +0 -234
  414. package/dist/scripts/changelog-check.js +0 -45
  415. package/dist/scripts/check-architecture.js +0 -295
  416. package/dist/scripts/check-cli-entrypoint.js +0 -41
  417. package/dist/scripts/check-command-module-budget.js +0 -77
  418. package/dist/scripts/check-feature-quality.js +0 -51
  419. package/dist/scripts/check-legacy-free.js +0 -64
  420. package/dist/scripts/check-pipeline-budget.js +0 -49
  421. package/dist/scripts/check-pipeline-runtime.js +0 -16
  422. package/dist/scripts/check-publish-tag.js +0 -56
  423. package/dist/scripts/check-route-modularity.js +0 -72
  424. package/dist/scripts/codex-0140-capability-check.js +0 -14
  425. package/dist/scripts/codex-0140-feature-probes-check.js +0 -23
  426. package/dist/scripts/codex-permission-profiles-check.js +0 -34
  427. package/dist/scripts/codex-project-config-policy-splitter-check.js +0 -49
  428. package/dist/scripts/competitor-scorecard-check.js +0 -24
  429. package/dist/scripts/core-skill-no-drift-check.js +0 -23
  430. package/dist/scripts/db-route-materialization-check.js +0 -32
  431. package/dist/scripts/doctor-context7-mcp-repair-blackbox.js +0 -15
  432. package/dist/scripts/doctor-fastpath-check.js +0 -25
  433. package/dist/scripts/doctor-fix-production-blackbox.js +0 -35
  434. package/dist/scripts/doctor-idempotence-check.js +0 -6
  435. package/dist/scripts/doctor-ops-semantics-check.js +0 -83
  436. package/dist/scripts/doctor-startup-config-repair-blackbox.js +0 -18
  437. package/dist/scripts/doctor-supabase-mcp-repair-blackbox.js +0 -13
  438. package/dist/scripts/ensure-bin-executable.js +0 -16
  439. package/dist/scripts/fsx-hotpath-check.js +0 -9
  440. package/dist/scripts/high-risk-contracts-check.js +0 -183
  441. package/dist/scripts/hook-latency-quantum-check.js +0 -120
  442. package/dist/scripts/import-graph-budget-check.js +0 -9
  443. package/dist/scripts/mcp-tool-naming-parity-check.js +0 -14
  444. package/dist/scripts/naruto-codex-e2e-check.js +0 -105
  445. package/dist/scripts/naruto-write-e2e-check.js +0 -31
  446. package/dist/scripts/native-capability-postcheck-check.js +0 -16
  447. package/dist/scripts/ops-diagnostics-bundle-check.js +0 -11
  448. package/dist/scripts/parallel-production-smoke-check.js +0 -20
  449. package/dist/scripts/perf-budget-check.js +0 -12
  450. package/dist/scripts/project-skill-dedupe-blackbox.js +0 -62
  451. package/dist/scripts/release-dag-full-coverage-check.js +0 -98
  452. package/dist/scripts/release-dist-freshness-check.js +0 -6
  453. package/dist/scripts/release-file-ownership-check.js +0 -35
  454. package/dist/scripts/release-gate-script-parity-check.js +0 -148
  455. package/dist/scripts/release-macos-menubar-proof.js +0 -167
  456. package/dist/scripts/release-main-push-guard.js +0 -37
  457. package/dist/scripts/release-main-push-receipt.js +0 -43
  458. package/dist/scripts/release-metadata-1-19-check.js +0 -257
  459. package/dist/scripts/release-version-truth-check.js +0 -138
  460. package/dist/scripts/retention-apply-smoke-check.js +0 -19
  461. package/dist/scripts/retention-budget-check.js +0 -6
  462. package/dist/scripts/retention-dry-run-check.js +0 -8
  463. package/dist/scripts/rollback-recovery-smoke-check.js +0 -70
  464. package/dist/scripts/route-intent-regression-check.js +0 -42
  465. package/dist/scripts/runtime-current-terminal-check.js +0 -108
  466. package/dist/scripts/runtime-dist-parity-check.js +0 -76
  467. package/dist/scripts/runtime-no-src-mjs-check.js +0 -30
  468. package/dist/scripts/runtime-ts-rust-boundary-check.js +0 -58
  469. package/dist/scripts/runtime-ts-source-of-truth-check.js +0 -53
  470. package/dist/scripts/secret-preservation-guard-check.js +0 -36
  471. package/dist/scripts/seo-marketing-truthfulness-check.js +0 -98
  472. package/dist/scripts/seo-metadata-sync-check.js +0 -60
  473. package/dist/scripts/sizecheck.js +0 -148
  474. package/dist/scripts/sks-menubar-install-check.js +0 -333
  475. package/dist/scripts/supabase-secret-preservation-blackbox.js +0 -28
  476. package/dist/scripts/super-search-live-smoke-check.js +0 -115
  477. package/dist/scripts/super-search-local-http-smoke-check.js +0 -16
  478. package/dist/scripts/super-search-offline-contract-check.js +0 -43
  479. package/dist/scripts/update-fastpath-check.js +0 -28
  480. package/dist/scripts/update-preserves-supabase-keys-blackbox.js +0 -26
  481. package/dist/scripts/upgrade-migration-matrix-check.js +0 -351
  482. package/dist/scripts/write-build-manifest.js +0 -70
  483. package/dist/scripts/zellij-capability-check.js +0 -13
  484. package/dist/scripts/zellij-developer-controls-check.js +0 -16
  485. package/dist/scripts/zellij-doctor-readiness-check.js +0 -49
  486. package/dist/scripts/zellij-dynamic-pane-lifecycle-check.js +0 -19
  487. package/dist/scripts/zellij-fake-adapter-check.js +0 -31
  488. package/dist/scripts/zellij-first-slot-down-stack-check.js +0 -20
  489. package/dist/scripts/zellij-first-slot-down-stack-real-check.js +0 -348
  490. package/dist/scripts/zellij-homebrew-policy-check.js +0 -3
  491. package/dist/scripts/zellij-initial-main-only-blackbox.js +0 -21
  492. package/dist/scripts/zellij-lane-renderer-check.js +0 -78
  493. package/dist/scripts/zellij-launch-command-truth-check.js +0 -62
  494. package/dist/scripts/zellij-layout-valid-check.js +0 -120
  495. package/dist/scripts/zellij-pane-creation-lock-metrics-check.js +0 -10
  496. package/dist/scripts/zellij-pane-lock-concurrency-blackbox.js +0 -78
  497. package/dist/scripts/zellij-pane-lock-does-not-block-worker-check.js +0 -12
  498. package/dist/scripts/zellij-pane-lock-open-worker-integration-blackbox.js +0 -134
  499. package/dist/scripts/zellij-qa-app-handoff-status-check.js +0 -7
  500. package/dist/scripts/zellij-right-column-geometry-proof.js +0 -158
  501. package/dist/scripts/zellij-right-column-headless-overflow-check.js +0 -20
  502. package/dist/scripts/zellij-right-column-manager-check.js +0 -24
  503. package/dist/scripts/zellij-self-heal-check.js +0 -3
  504. package/dist/scripts/zellij-self-heal-dry-run-check.js +0 -3
  505. package/dist/scripts/zellij-self-heal-status-contract-check.js +0 -3
  506. package/dist/scripts/zellij-self-heal-typed-blackbox.js +0 -3
  507. package/dist/scripts/zellij-slot-column-anchor-check.js +0 -65
  508. package/dist/scripts/zellij-slot-column-anchor-telemetry-check.js +0 -8
  509. package/dist/scripts/zellij-slot-only-ui-check.js +0 -29
  510. package/dist/scripts/zellij-slot-pane-renderer-check.js +0 -149
  511. package/dist/scripts/zellij-slot-pane-stale-detection-check.js +0 -65
  512. package/dist/scripts/zellij-slot-pane-telemetry-renderer-check.js +0 -11
  513. package/dist/scripts/zellij-slot-renderer-proof-semantics-check.js +0 -58
  514. package/dist/scripts/zellij-slot-telemetry-check.js +0 -38
  515. package/dist/scripts/zellij-slot-telemetry-incremental-check.js +0 -46
  516. package/dist/scripts/zellij-slot-telemetry-live-flush-check.js +0 -55
  517. package/dist/scripts/zellij-slot-telemetry-performance-check.js +0 -32
  518. package/dist/scripts/zellij-slot-telemetry-real-blackbox.js +0 -19
  519. package/dist/scripts/zellij-slot-telemetry-renderer-check.js +0 -11
  520. package/dist/scripts/zellij-slot-telemetry-runtime-check.js +0 -23
  521. package/dist/scripts/zellij-spawn-on-demand-layout-check.js +0 -45
  522. package/dist/scripts/zellij-stacked-capability-routing-check.js +0 -9
  523. package/dist/scripts/zellij-stacked-fallback-integration-blackbox.js +0 -78
  524. package/dist/scripts/zellij-stacked-version-matrix-check.js +0 -29
  525. package/dist/scripts/zellij-stacked-version-parser-check.js +0 -19
  526. package/dist/scripts/zellij-ui-design-check.js +0 -92
  527. package/dist/scripts/zellij-update-missing-self-heal-check.js +0 -3
  528. package/dist/scripts/zellij-update-prompt-matrix-check.js +0 -16
  529. package/dist/scripts/zellij-update-prompt-mode-check.js +0 -18
  530. package/dist/scripts/zellij-update-prompt-safety-check.js +0 -8
  531. package/dist/scripts/zellij-worker-pane-manager-check.js +0 -108
  532. package/dist/scripts/zellij-worker-pane-manager-single-owner-check.js +0 -47
  533. package/dist/scripts/zellij-worker-pane-real-ui-blackbox.js +0 -199
  534. /package/dist/scripts/{sks-1-11-gate-lib.js → sks-cli-gate-lib.js} +0 -0
@@ -3,12 +3,17 @@ import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import { writeTextAtomic } from '../fsx.js';
5
5
  import { MANAGED_OFFICIAL_SUBAGENT_ROLES, managedOfficialSubagentRoleByName } from '../managed-assets/managed-assets-manifest.js';
6
- export const ROLE_MODEL_PREFERENCES_SCHEMA = 'sks.role-model-preferences.v1';
6
+ import { inferProviderFromModel, normalizeCodexModelId, normalizeCodexReasoningEffort, readConfiguredCodexModelRoutingContext } from '../codex-app/codex-model-catalog.js';
7
+ import { childInheritsActiveMainModel } from '../provider/model-router.js';
8
+ import { isRecord } from '../json/records.js';
9
+ export const ROLE_MODEL_PREFERENCES_SCHEMA = 'sks.role-model-preferences.v2';
10
+ const LEGACY_ROLE_MODEL_PREFERENCES_SCHEMA = 'sks.role-model-preferences.v1';
11
+ const ROLE_MODEL_PROFILE_PRESENTATION_LIMIT = 1_000;
7
12
  export const SUPPORTED_ROLE_MODEL_PROFILES = Object.freeze([
8
- Object.freeze({ model: 'gpt-5.6-luna', reasoning_effort: 'max' }),
9
- Object.freeze({ model: 'gpt-5.6-terra', reasoning_effort: 'medium' }),
10
- Object.freeze({ model: 'gpt-5.6-sol', reasoning_effort: 'high' }),
11
- Object.freeze({ model: 'gpt-5.6-sol', reasoning_effort: 'max' })
13
+ Object.freeze({ provider: 'openai', model: 'gpt-5.6-luna', reasoning_effort: 'max', source: 'managed-default' }),
14
+ Object.freeze({ provider: 'openai', model: 'gpt-5.6-terra', reasoning_effort: 'medium', source: 'managed-default' }),
15
+ Object.freeze({ provider: 'openai', model: 'gpt-5.6-sol', reasoning_effort: 'high', source: 'managed-default' }),
16
+ Object.freeze({ provider: 'openai', model: 'gpt-5.6-sol', reasoning_effort: 'max', source: 'managed-default' })
12
17
  ]);
13
18
  export function roleModelPreferencesPath(env = process.env) {
14
19
  const sksHome = path.resolve(env.SKS_HOME || path.join(env.HOME || os.homedir(), '.sneakoscope'));
@@ -18,7 +23,9 @@ export async function readRoleModelPreferences(input = {}) {
18
23
  const filePath = input.filePath || roleModelPreferencesPath(input.env || process.env);
19
24
  try {
20
25
  const parsed = JSON.parse(await fs.readFile(filePath, 'utf8'));
21
- if (parsed.schema !== ROLE_MODEL_PREFERENCES_SCHEMA || parsed.version !== 1 || !isRecord(parsed.roles)) {
26
+ const legacy = parsed.schema === LEGACY_ROLE_MODEL_PREFERENCES_SCHEMA && parsed.version === 1;
27
+ const current = parsed.schema === ROLE_MODEL_PREFERENCES_SCHEMA && parsed.version === 2;
28
+ if ((!legacy && !current) || !isRecord(parsed.roles)) {
22
29
  return { store: emptyStore(), path: filePath, blockers: ['role_model_preferences_invalid_schema'] };
23
30
  }
24
31
  const roles = {};
@@ -29,23 +36,25 @@ export async function readRoleModelPreferences(input = {}) {
29
36
  blockers.push(`role_model_preference_invalid_role:${rawRole}`);
30
37
  continue;
31
38
  }
32
- const model = String(rawPreference.model || '');
33
- const reasoning = String(rawPreference.reasoning_effort || '');
34
- const profile = supportedRoleModelProfile(model, reasoning);
35
- if (!profile) {
39
+ const model = normalizeCodexModelId(rawPreference.model);
40
+ const reasoning = normalizeCodexReasoningEffort(rawPreference.reasoning_effort);
41
+ const provider = normalizeRoleProvider(rawPreference.provider)
42
+ || (model ? inferProviderFromModel(model) : null);
43
+ if (!model || !reasoning || !provider) {
36
44
  blockers.push(`role_model_preference_invalid_profile:${role.codex_name}`);
37
45
  continue;
38
46
  }
39
47
  roles[role.codex_name] = {
40
- model: profile.model,
41
- reasoning_effort: profile.reasoning_effort,
48
+ provider,
49
+ model,
50
+ reasoning_effort: reasoning,
42
51
  updated_at: String(rawPreference.updated_at || parsed.updated_at || '')
43
52
  };
44
53
  }
45
54
  return {
46
55
  store: {
47
56
  schema: ROLE_MODEL_PREFERENCES_SCHEMA,
48
- version: 1,
57
+ version: 2,
49
58
  updated_at: String(parsed.updated_at || ''),
50
59
  roles
51
60
  },
@@ -60,37 +69,167 @@ export async function readRoleModelPreferences(input = {}) {
60
69
  }
61
70
  }
62
71
  export async function roleModelPreferencesStatus(input = {}) {
72
+ const env = input.env || process.env;
63
73
  const read = await readRoleModelPreferences(input);
74
+ const routing = await readConfiguredCodexModelRoutingContext({
75
+ env,
76
+ ...(input.home ? { home: input.home } : {}),
77
+ ...(input.configPath ? { configPath: input.configPath } : {})
78
+ });
79
+ const catalog = routing.catalog;
80
+ const routerSelected = routing.selected_provider === 'sks-router';
81
+ const activeMainModel = routing.selected_provider && routing.selected_model
82
+ ? {
83
+ provider: routing.selected_provider,
84
+ model: routing.selected_model
85
+ }
86
+ : null;
87
+ const preferenceBlockers = Object.entries(read.store.roles).flatMap(([role, preference]) => {
88
+ const routed = preference.provider !== 'openai' || preference.model.includes('/');
89
+ if (!routed) {
90
+ return isSupportedRoleModelProfile(preference.model, preference.reasoning_effort)
91
+ ? []
92
+ : [`role_model_preference_not_managed:${role}`];
93
+ }
94
+ if (!routerSelected)
95
+ return [`role_model_router_not_selected:${role}`];
96
+ const entry = catalog.models.find((model) => model.model === preference.model);
97
+ if (!catalog.ok || !entry)
98
+ return [`role_model_preference_not_in_active_catalog:${role}`];
99
+ if (!entry.reasoning_efforts.includes(preference.reasoning_effort)) {
100
+ return [`role_model_preference_reasoning_not_in_active_catalog:${role}`];
101
+ }
102
+ return entry.multi_agent_version === 'v2'
103
+ ? []
104
+ : [`role_model_preference_multi_agent_v2_required:${role}`];
105
+ });
106
+ const catalogProfiles = (routerSelected ? catalog.models : [])
107
+ .filter((entry) => entry.multi_agent_version === 'v2')
108
+ .flatMap((entry) => (entry.reasoning_efforts.map((reasoning) => ({
109
+ provider: entry.provider,
110
+ model: entry.model,
111
+ reasoning_effort: reasoning,
112
+ source: 'codex-model-catalog'
113
+ }))));
114
+ const allProfiles = dedupeProfiles([
115
+ ...SUPPORTED_ROLE_MODEL_PROFILES,
116
+ ...catalogProfiles
117
+ ]);
118
+ const supportedProfiles = allProfiles.slice(0, ROLE_MODEL_PROFILE_PRESENTATION_LIMIT);
64
119
  const roles = MANAGED_OFFICIAL_SUBAGENT_ROLES.map((role) => {
65
120
  const override = read.store.roles[role.codex_name] || null;
121
+ const inheritActiveMain = childInheritsActiveMainModel(activeMainModel?.model);
122
+ const effectiveProvider = override?.provider
123
+ || (inheritActiveMain ? activeMainModel?.provider : null)
124
+ || inferProviderFromModel(role.model);
125
+ const effectiveModel = override?.model
126
+ || (inheritActiveMain ? activeMainModel?.model : null)
127
+ || role.model;
128
+ const effectiveReasoning = override?.reasoning_effort || role.model_reasoning_effort;
66
129
  return {
67
130
  role: role.codex_name,
68
131
  description: role.description,
132
+ default_provider: inferProviderFromModel(role.model),
69
133
  default_model: role.model,
70
134
  default_reasoning_effort: role.model_reasoning_effort,
71
135
  override,
72
- effective_model: override?.model || role.model,
73
- effective_reasoning_effort: override?.reasoning_effort || role.model_reasoning_effort
136
+ effective_provider: effectiveProvider,
137
+ effective_model: effectiveModel,
138
+ effective_reasoning_effort: effectiveReasoning,
139
+ effective_source: override
140
+ ? 'role-override'
141
+ : inheritActiveMain
142
+ ? 'selected-main-model'
143
+ : 'managed-default'
74
144
  };
75
145
  });
76
146
  return {
77
- schema: 'sks.role-model-preferences-status.v1',
78
- ok: read.blockers.length === 0,
147
+ schema: 'sks.role-model-preferences-status.v2',
148
+ ok: read.blockers.length === 0 && preferenceBlockers.length === 0,
79
149
  path: read.path,
80
150
  owner_only: true,
81
- supported_profiles: SUPPORTED_ROLE_MODEL_PROFILES,
151
+ supported_profiles: supportedProfiles,
152
+ supported_profile_count: allProfiles.length,
153
+ supported_profiles_truncated: allProfiles.length > supportedProfiles.length,
154
+ routing: {
155
+ selected_provider: routing.selected_provider,
156
+ selected_model: routing.selected_model,
157
+ active_main_model_inherited: childInheritsActiveMainModel(activeMainModel?.model),
158
+ router_selected: routerSelected,
159
+ runtime_verified: false
160
+ },
161
+ catalog: {
162
+ configured: catalog.configured,
163
+ ok: catalog.ok,
164
+ path: catalog.path,
165
+ model_count: catalog.model_count,
166
+ total_model_count: catalog.total_model_count,
167
+ truncated: catalog.truncated,
168
+ blockers: catalog.blockers
169
+ },
82
170
  roles,
83
- blockers: read.blockers,
84
- warnings: []
171
+ store_readable: read.blockers.length === 0,
172
+ store_blockers: [...read.blockers],
173
+ preference_blockers: [...preferenceBlockers],
174
+ blockers: [...read.blockers, ...preferenceBlockers],
175
+ warnings: [
176
+ ...catalog.warnings,
177
+ ...(catalog.configured && !catalog.ok
178
+ ? catalog.blockers.map((blocker) => `role_model_catalog:${blocker}`)
179
+ : []),
180
+ ...(catalog.configured && catalog.ok && !routerSelected
181
+ ? ['role_model_router_not_selected']
182
+ : []),
183
+ ...(allProfiles.length > supportedProfiles.length
184
+ ? [`role_model_supported_profiles_truncated:${allProfiles.length}:${supportedProfiles.length}`]
185
+ : [])
186
+ ]
85
187
  };
86
188
  }
87
189
  export async function setRoleModelPreference(input) {
88
190
  const role = managedOfficialSubagentRoleByName(String(input.role || '').trim());
89
191
  if (!role)
90
192
  return mutationBlocked('role_model_role_invalid');
91
- const profile = supportedRoleModelProfile(input.model, input.reasoning);
92
- if (!profile) {
93
- return mutationBlocked('role_model_profile_unsupported');
193
+ const model = normalizeCodexModelId(input.model);
194
+ const reasoning = normalizeCodexReasoningEffort(input.reasoning);
195
+ if (!model || !reasoning)
196
+ return mutationBlocked('role_model_profile_invalid');
197
+ const env = input.env || process.env;
198
+ const routing = await readConfiguredCodexModelRoutingContext({
199
+ env,
200
+ ...(input.home ? { home: input.home } : {}),
201
+ ...(input.configPath ? { configPath: input.configPath } : {})
202
+ });
203
+ const catalog = routing.catalog;
204
+ const catalogEntry = catalog.models.find((entry) => entry.model === model) || null;
205
+ const requestedProvider = normalizeRoleProvider(input.provider);
206
+ if (input.provider && !requestedProvider)
207
+ return mutationBlocked('role_model_provider_invalid');
208
+ if (requestedProvider && catalogEntry && requestedProvider !== catalogEntry.provider) {
209
+ return mutationBlocked('role_model_provider_mismatch');
210
+ }
211
+ const provider = requestedProvider || catalogEntry?.provider || inferProviderFromModel(model);
212
+ const routedModel = provider !== 'openai' || model.includes('/');
213
+ const managedProfile = SUPPORTED_ROLE_MODEL_PROFILES.some((profile) => (profile.provider === provider
214
+ && profile.model === model
215
+ && profile.reasoning_effort === reasoning));
216
+ if (!routedModel && !managedProfile) {
217
+ return mutationBlocked('role_model_profile_not_managed');
218
+ }
219
+ if (routedModel && routing.selected_provider !== 'sks-router') {
220
+ return mutationBlocked('role_model_router_not_selected');
221
+ }
222
+ if (routedModel && !catalog.ok) {
223
+ return mutationBlocked('role_model_catalog_required_for_routed_model', ...catalog.blockers);
224
+ }
225
+ if (routedModel && !catalogEntry) {
226
+ return mutationBlocked('role_model_not_in_active_catalog');
227
+ }
228
+ if (catalogEntry && !catalogEntry.reasoning_efforts.includes(reasoning)) {
229
+ return mutationBlocked('role_model_reasoning_not_in_catalog');
230
+ }
231
+ if (routedModel && catalogEntry?.multi_agent_version !== 'v2') {
232
+ return mutationBlocked('role_model_multi_agent_v2_required');
94
233
  }
95
234
  const read = await readRoleModelPreferences(input);
96
235
  if (read.blockers.length)
@@ -98,28 +237,35 @@ export async function setRoleModelPreference(input) {
98
237
  const timestamp = (input.now || (() => new Date().toISOString()))();
99
238
  const store = {
100
239
  schema: ROLE_MODEL_PREFERENCES_SCHEMA,
101
- version: 1,
240
+ version: 2,
102
241
  updated_at: timestamp,
103
242
  roles: {
104
243
  ...read.store.roles,
105
244
  [role.codex_name]: {
106
- model: profile.model,
107
- reasoning_effort: profile.reasoning_effort,
245
+ provider,
246
+ model,
247
+ reasoning_effort: reasoning,
108
248
  updated_at: timestamp
109
249
  }
110
250
  }
111
251
  };
112
252
  await writeOwnerOnlyStore(read.path, store);
113
253
  return {
114
- schema: 'sks.role-model-preference-mutation.v1',
254
+ schema: 'sks.role-model-preference-mutation.v2',
115
255
  ok: true,
116
256
  status: 'set',
117
257
  role: role.codex_name,
118
- model: profile.model,
119
- reasoning_effort: profile.reasoning_effort,
258
+ provider,
259
+ model,
260
+ reasoning_effort: reasoning,
261
+ catalog_verified: Boolean(catalogEntry),
262
+ catalog_path: catalog.path,
263
+ selected_model_provider: routing.selected_provider,
264
+ multi_agent_version: catalogEntry?.multi_agent_version || null,
265
+ runtime_verified: false,
120
266
  path: read.path,
121
267
  blockers: [],
122
- warnings: []
268
+ warnings: catalog.warnings
123
269
  };
124
270
  }
125
271
  export async function resetRoleModelPreference(input) {
@@ -133,13 +279,13 @@ export async function resetRoleModelPreference(input) {
133
279
  delete roles[role.codex_name];
134
280
  const store = {
135
281
  schema: ROLE_MODEL_PREFERENCES_SCHEMA,
136
- version: 1,
282
+ version: 2,
137
283
  updated_at: (input.now || (() => new Date().toISOString()))(),
138
284
  roles
139
285
  };
140
286
  await writeOwnerOnlyStore(read.path, store);
141
287
  return {
142
- schema: 'sks.role-model-preference-mutation.v1',
288
+ schema: 'sks.role-model-preference-mutation.v2',
143
289
  ok: true,
144
290
  status: 'reset',
145
291
  role: role.codex_name,
@@ -149,13 +295,10 @@ export async function resetRoleModelPreference(input) {
149
295
  };
150
296
  }
151
297
  export function isSupportedRoleModelProfile(model, reasoning) {
152
- return supportedRoleModelProfile(model, reasoning) !== null;
153
- }
154
- function supportedRoleModelProfile(model, reasoning) {
155
- const normalizedModel = String(model || '').trim();
156
- const normalizedReasoning = String(reasoning || '').trim();
157
- const profile = SUPPORTED_ROLE_MODEL_PROFILES.find((profile) => (profile.model === normalizedModel && profile.reasoning_effort === normalizedReasoning));
158
- return profile ? { model: profile.model, reasoning_effort: profile.reasoning_effort } : null;
298
+ const normalizedModel = normalizeCodexModelId(model);
299
+ const normalizedReasoning = normalizeCodexReasoningEffort(reasoning);
300
+ return SUPPORTED_ROLE_MODEL_PROFILES.some((profile) => (profile.model === normalizedModel
301
+ && profile.reasoning_effort === normalizedReasoning));
159
302
  }
160
303
  async function writeOwnerOnlyStore(filePath, store) {
161
304
  const dir = path.dirname(filePath);
@@ -163,17 +306,32 @@ async function writeOwnerOnlyStore(filePath, store) {
163
306
  await writeTextAtomic(filePath, `${JSON.stringify(store, null, 2)}\n`, { mode: 0o600 });
164
307
  }
165
308
  function emptyStore() {
166
- return { schema: ROLE_MODEL_PREFERENCES_SCHEMA, version: 1, updated_at: '', roles: {} };
309
+ return { schema: ROLE_MODEL_PREFERENCES_SCHEMA, version: 2, updated_at: '', roles: {} };
167
310
  }
168
311
  function mutationBlocked(...blockers) {
169
312
  return {
170
- schema: 'sks.role-model-preference-mutation.v1',
313
+ schema: 'sks.role-model-preference-mutation.v2',
171
314
  ok: false,
172
315
  status: 'blocked',
173
- blockers,
316
+ blockers: [...new Set(blockers.filter(Boolean))],
174
317
  warnings: []
175
318
  };
176
319
  }
177
- function isRecord(value) {
178
- return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
320
+ function normalizeRoleProvider(value) {
321
+ const provider = String(value || '').trim().toLowerCase();
322
+ if (!provider || provider.length > 80)
323
+ return null;
324
+ return /^[a-z0-9][a-z0-9._-]*$/.test(provider) ? provider : null;
325
+ }
326
+ function dedupeProfiles(profiles) {
327
+ const seen = new Set();
328
+ const out = [];
329
+ for (const profile of profiles) {
330
+ const key = `${profile.model}\u0000${profile.reasoning_effort}`;
331
+ if (seen.has(key))
332
+ continue;
333
+ seen.add(key);
334
+ out.push(profile);
335
+ }
336
+ return out;
179
337
  }
@@ -3,6 +3,7 @@ import path from 'node:path';
3
3
  import { appendJsonlBounded, nowIso, sha256, writeJsonAtomic } from '../fsx.js';
4
4
  import { HOST_CAPABILITY_DESCRIPTORS, hostCapabilityDigest } from '../agent-bridge/agent-manifest.js';
5
5
  import { HOST_CAPABILITY_EVIDENCE_SCHEMA, HOST_CAPABILITY_RUNTIME_SCHEMA } from '../agent-bridge/host-capability-runtime.js';
6
+ import { isRecord } from '../json/records.js';
6
7
  export const SUBAGENT_EVIDENCE_SCHEMA = 'sks.subagent-evidence.v1';
7
8
  export const SUBAGENT_EVENT_SCHEMA = 'sks.subagent-event.v1';
8
9
  export const SUBAGENT_PARENT_SUMMARY_SCHEMA = 'sks.subagent-parent-summary.v1';
@@ -1050,9 +1051,6 @@ function hasMeaningfulSummary(value) {
1050
1051
  function eventSourceOrder(a, b) {
1051
1052
  return (a === 'SubagentStart' ? 0 : 1) - (b === 'SubagentStart' ? 0 : 1);
1052
1053
  }
1053
- function isRecord(value) {
1054
- return Boolean(value) && typeof value === 'object' && !Array.isArray(value);
1055
- }
1056
1054
  function recordId(value) {
1057
1055
  return isRecord(value) ? value.id : undefined;
1058
1056
  }
@@ -1,6 +1,6 @@
1
1
  export const DEFAULT_NARUTO_MAX_THREADS = 12;
2
2
  export const HARD_NARUTO_MAX_THREADS = 32;
3
- export const DEFAULT_NARUTO_REQUESTED_SUBAGENTS = 2;
3
+ export const DEFAULT_NARUTO_REQUESTED_SUBAGENTS = 4;
4
4
  export const DEFAULT_NARUTO_PARENT_THREAD_RESERVATION = 1;
5
5
  export const DEFAULT_NARUTO_REVIEWER_THREAD_RESERVATION = 0;
6
6
  export function resolveSubagentThreadBudget(input = {}) {
@@ -1,5 +1,6 @@
1
1
  import path from 'node:path';
2
2
  import { readJson } from '../fsx.js';
3
+ import { asRecordOrEmpty as asRecord } from '../json/records.js';
3
4
  export const BOUNDED_TRIWIKI_ATTENTION_SCHEMA = 'sks.subagent-triwiki-attention.v1';
4
5
  export const DEFAULT_TRIWIKI_ATTENTION_ANCHOR_LIMIT = 8;
5
6
  export async function readBoundedTriwikiAttention(root, limit = DEFAULT_TRIWIKI_ATTENTION_ANCHOR_LIMIT, query = '') {
@@ -153,11 +154,6 @@ function normalizeLimit(value) {
153
154
  return DEFAULT_TRIWIKI_ATTENTION_ANCHOR_LIMIT;
154
155
  return Math.max(1, Math.min(16, Math.floor(parsed)));
155
156
  }
156
- function asRecord(value) {
157
- return value && typeof value === 'object' && !Array.isArray(value)
158
- ? value
159
- : {};
160
- }
161
157
  function text(value) {
162
158
  return typeof value === 'string' ? value.trim() : '';
163
159
  }
@@ -1,9 +1,7 @@
1
1
  import fsp from 'node:fs/promises';
2
2
  import path from 'node:path';
3
3
  import { runProcess, sha256 } from '../fsx.js';
4
- function isRecord(value) {
5
- return typeof value === 'object' && value !== null && !Array.isArray(value);
6
- }
4
+ import { isRecord } from '../json/records.js';
7
5
  export function validateTelegramConfig(value) {
8
6
  const issues = [];
9
7
  if (!isRecord(value))
@@ -24,10 +22,7 @@ export function validateTelegramConfig(value) {
24
22
  if (!nonEmpty(secret.path) || !path.isAbsolute(String(secret.path)))
25
23
  issues.push('external_secret_path_must_be_absolute');
26
24
  }
27
- if (!stringIdArray(value.paired_chat_ids))
28
- issues.push('paired_chat_ids');
29
- if (!stringIdArray(value.paired_user_ids))
30
- issues.push('paired_user_ids');
25
+ issues.push(...validateTelegramPrivatePairing(value).issues);
31
26
  if (typeof value.long_poll_timeout_sec === 'number' && (value.long_poll_timeout_sec < 1 || value.long_poll_timeout_sec > 50))
32
27
  issues.push('long_poll_timeout_sec');
33
28
  if (typeof value.owner_stale_ms === 'number' && value.owner_stale_ms < 5_000)
@@ -59,7 +54,7 @@ export async function resolveTelegramBotToken(ref, options = {}) {
59
54
  ], { timeoutMs: 5_000, maxOutputBytes: 8 * 1024 });
60
55
  if (result.code !== 0 || result.timedOut)
61
56
  throw new Error('telegram_keychain_lookup_failed');
62
- return validateTokenValue(result.stdout.trim());
57
+ return validateTelegramBotToken(result.stdout.trim());
63
58
  }
64
59
  if (!ref.path || !path.isAbsolute(ref.path))
65
60
  throw new Error('telegram_external_secret_path_invalid');
@@ -70,19 +65,41 @@ export async function resolveTelegramBotToken(ref, options = {}) {
70
65
  throw new Error('telegram_external_secret_not_file');
71
66
  if ((stat.mode & 0o077) !== 0)
72
67
  throw new Error('telegram_external_secret_permissions_must_be_0600');
73
- return validateTokenValue((await fsp.readFile(ref.path, 'utf8')).trim());
68
+ return validateTelegramBotToken((await fsp.readFile(ref.path, 'utf8')).trim());
74
69
  }
75
70
  export function telegramTokenFingerprint(token) {
76
71
  return `sha256:${sha256(token)}`;
77
72
  }
78
- function validateTokenValue(token) {
73
+ export function validateTelegramBotToken(token) {
79
74
  if (!/^\d{5,}:[A-Za-z0-9_-]{20,}$/.test(token))
80
75
  throw new Error('telegram_bot_token_format_invalid');
81
76
  return token;
82
77
  }
78
+ export function isPositiveTelegramId(value) {
79
+ return typeof value === 'string' && /^[1-9]\d*$/.test(value);
80
+ }
81
+ export function validateTelegramPrivatePairing(value) {
82
+ if (!isRecord(value)) {
83
+ return {
84
+ ok: false,
85
+ missing: true,
86
+ issues: ['paired_chat_ids', 'paired_user_ids']
87
+ };
88
+ }
89
+ const issues = [];
90
+ if (!positiveStringIdArray(value.paired_chat_ids))
91
+ issues.push('paired_chat_ids');
92
+ if (!positiveStringIdArray(value.paired_user_ids))
93
+ issues.push('paired_user_ids');
94
+ const missing = pairingFieldMissing(value, 'paired_chat_ids') || pairingFieldMissing(value, 'paired_user_ids');
95
+ return { ok: issues.length === 0, missing, issues };
96
+ }
83
97
  function nonEmpty(value) {
84
98
  return typeof value === 'string' && value.trim().length > 0;
85
99
  }
86
- function stringIdArray(value) {
87
- return Array.isArray(value) && value.length > 0 && value.every((entry) => /^-?\d+$/.test(String(entry)));
100
+ function positiveStringIdArray(value) {
101
+ return Array.isArray(value) && value.length > 0 && value.every(isPositiveTelegramId);
102
+ }
103
+ function pairingFieldMissing(value, field) {
104
+ return !(field in value) || (Array.isArray(value[field]) && value[field].length === 0);
88
105
  }
@@ -70,11 +70,13 @@ export class TelegramHubRouter {
70
70
  const text = staticUiAction?.command ?? message?.text?.trim() ?? '';
71
71
  const command = text.startsWith('/') ? text.split(/\s+/, 1)[0]?.toLowerCase() ?? '' : '';
72
72
  const policy = staticUiAction ?? COMMAND_POLICY[command];
73
- if (actor.topicId === null) {
73
+ const route = actor.topicId === null
74
+ ? await this.onlyRouteForPrivateChat(actor.chatId)
75
+ : await this.options.topics.findByTopic(actor.chatId, actor.topicId);
76
+ if (actor.topicId === null && !route) {
74
77
  await this.audit(update, actor.chatId, null, null, command || 'free_text', 'rejected', 'session_picker_required');
75
78
  return { ...result(false, 'session_picker_required'), session_picker: true };
76
79
  }
77
- const route = await this.options.topics.findByTopic(actor.chatId, actor.topicId);
78
80
  if (!route)
79
81
  return this.reject(update, actor, command || 'free_text', 'wrong_topic');
80
82
  if (policy) {
@@ -108,6 +110,10 @@ export class TelegramHubRouter {
108
110
  && this.options.config.paired_chat_ids.includes(chatId)
109
111
  && this.options.config.paired_user_ids.includes(userId);
110
112
  }
113
+ async onlyRouteForPrivateChat(chatId) {
114
+ const routes = (await this.options.topics.list()).filter((route) => route.chat_id === chatId);
115
+ return routes.length === 1 && routes[0]?.message_thread_id === 0 ? routes[0] : null;
116
+ }
111
117
  async reject(update, actor, command, reason) {
112
118
  await this.audit(update, actor.chatId, actor.topicId, null, command, 'rejected', reason);
113
119
  return result(false, reason);
@@ -6,3 +6,5 @@ export * from './bot-api.js';
6
6
  export * from './messages.js';
7
7
  export * from './hub.js';
8
8
  export * from './runtime.js';
9
+ export * from './setup.js';
10
+ export * from './service.js';
@@ -85,7 +85,7 @@ export class TelegramMessageProjector {
85
85
  });
86
86
  }
87
87
  async sendFinal(input) {
88
- const text = publicSafeText(input.text);
88
+ const text = telegramMessageText(input.text);
89
89
  let method = this.capabilities.rich_message ? 'sendRichMessage' : 'sendMessage';
90
90
  let result;
91
91
  try {
@@ -110,7 +110,7 @@ export class TelegramMessageProjector {
110
110
  async sendFlat(input) {
111
111
  const result = await this.api.call('sendMessage', {
112
112
  chat_id: input.chatId,
113
- text: publicSafeText(input.text),
113
+ text: telegramMessageText(input.text),
114
114
  protect_content: this.options.protectContent !== false,
115
115
  disable_notification: this.options.silent === true,
116
116
  ...(input.replyMarkup ? { reply_markup: input.replyMarkup } : {})
@@ -287,6 +287,12 @@ export function publicSafeText(value) {
287
287
  .replace(/\u0000/g, '')
288
288
  .slice(0, 16_000);
289
289
  }
290
+ function telegramMessageText(value) {
291
+ const text = publicSafeText(value);
292
+ if (text.length <= 4_000)
293
+ return text;
294
+ return `${text.slice(0, 3_920).trimEnd()}\n\n[Response truncated for Telegram. Ask Codex to continue with the remaining details.]`;
295
+ }
290
296
  async function sleep(ms) {
291
297
  await new Promise((resolve) => setTimeout(resolve, ms));
292
298
  }
@@ -1,6 +1,8 @@
1
1
  import crypto from 'node:crypto';
2
2
  import { buildTelegramTopicName } from './ledgers.js';
3
3
  import { publicSafeText } from './messages.js';
4
+ import { asRecordOrNull as asRecord } from '../json/records.js';
5
+ export { asRecord };
4
6
  export function pickerAction(route, now) {
5
7
  return {
6
8
  schema: 'sks.remote-action.v1',
@@ -49,8 +51,12 @@ export function snapshotSummary(snapshot) {
49
51
  ].join('\n'));
50
52
  }
51
53
  export function successSummary(action, data) {
52
- if (action.kind === 'input')
53
- return 'Follow-up input was accepted by the exact active Codex turn.';
54
+ if (action.kind === 'input') {
55
+ const response = typeof data?.final_response === 'string' ? data.final_response.trim() : '';
56
+ return response
57
+ ? publicSafeText(response)
58
+ : 'Codex completed the Telegram turn, but no public final response was available.';
59
+ }
54
60
  if (action.kind === 'cancel')
55
61
  return 'Cancellation completed with owner-proof and one-time approval receipts.';
56
62
  if (action.kind === 'verify')
@@ -83,6 +89,3 @@ export function boundedIdentifier(value) {
83
89
  const text = typeof value === 'string' ? value : '';
84
90
  return /^[A-Za-z0-9][A-Za-z0-9._:-]{0,159}$/.test(text) ? text : null;
85
91
  }
86
- export function asRecord(value) {
87
- return value !== null && typeof value === 'object' && !Array.isArray(value) ? value : null;
88
- }
@@ -1,4 +1,4 @@
1
- import { REMOTE_COMMAND_SCHEMA, REMOTE_R2_APPROVAL_SCHEMA, REMOTE_WORKER_REQUEST_SCHEMA, RemoteSshClientError, RemoteSshWorkerClient, findRemoteMachine, findRemoteSessionTarget } from '../remote/index.js';
1
+ import { REMOTE_COMMAND_SCHEMA, REMOTE_R2_APPROVAL_SCHEMA, REMOTE_WORKER_REQUEST_SCHEMA, RemoteLocalWorkerClient, RemoteSshClientError, RemoteSshWorkerClient, findRemoteMachine, findRemoteSessionTarget } from '../remote/index.js';
2
2
  import { nowIso, readJson, sha256, writeJsonAtomic } from '../fsx.js';
3
3
  import { TelegramActionBroker, TelegramAuditLedger, TelegramTopicRegistry } from './ledgers.js';
4
4
  import { TelegramBotApiError } from './bot-api.js';
@@ -86,9 +86,12 @@ export class TelegramHubRuntime {
86
86
  warnings.push(`target_unavailable:${target.machine_id}:${target.project_id}`);
87
87
  continue;
88
88
  }
89
- const rows = Array.isArray(asRecord(listed.data)?.sessions) ? asRecord(listed.data)?.sessions : [];
90
- for (const raw of rows) {
91
- const session = asRecord(raw);
89
+ const rawRows = Array.isArray(asRecord(listed.data)?.sessions)
90
+ ? asRecord(listed.data)?.sessions
91
+ : [];
92
+ const rows = rawRows.map(asRecord).filter((row) => Boolean(row));
93
+ const dedicatedRows = rows.filter((row) => row.dedicated_telegram_thread === true);
94
+ for (const session of dedicatedRows.length ? dedicatedRows : rows) {
92
95
  const sessionId = boundedIdentifier(session?.session_id);
93
96
  if (!sessionId)
94
97
  continue;
@@ -346,11 +349,18 @@ export class TelegramHubRuntime {
346
349
  const existing = this.clients.get(key);
347
350
  if (existing)
348
351
  return existing;
349
- const created = this.options.clientFactory?.(target) ?? new RemoteSshWorkerClient({
350
- machine: findRemoteMachine(this.options.machineRegistry, target.machine_id),
351
- projectRoot: target.project_root,
352
- projectId: target.project_id
353
- });
352
+ const machine = findRemoteMachine(this.options.machineRegistry, target.machine_id);
353
+ const created = this.options.clientFactory?.(target) ?? (machine.transport === 'local'
354
+ ? new RemoteLocalWorkerClient({
355
+ machine,
356
+ projectRoot: target.project_root,
357
+ projectId: target.project_id
358
+ })
359
+ : new RemoteSshWorkerClient({
360
+ machine,
361
+ projectRoot: target.project_root,
362
+ projectId: target.project_id
363
+ }));
354
364
  this.clients.set(key, created);
355
365
  return created;
356
366
  }