open-multi-agent-kit 0.96.2 → 0.98.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 (368) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +43 -9
  3. package/dist/cli/args.d.ts +2 -3
  4. package/dist/cli/args.d.ts.map +1 -1
  5. package/dist/cli/args.js +13 -189
  6. package/dist/cli/args.js.map +1 -1
  7. package/dist/cli/help.d.ts +3 -0
  8. package/dist/cli/help.d.ts.map +1 -0
  9. package/dist/cli/help.js +194 -0
  10. package/dist/cli/help.js.map +1 -0
  11. package/dist/cli/initial-message.d.ts.map +1 -1
  12. package/dist/cli/initial-message.js +2 -1
  13. package/dist/cli/initial-message.js.map +1 -1
  14. package/dist/cli/resource-paths.d.ts +4 -0
  15. package/dist/cli/resource-paths.d.ts.map +1 -0
  16. package/dist/cli/resource-paths.js +59 -0
  17. package/dist/cli/resource-paths.js.map +1 -0
  18. package/dist/commands/adaptorch-doctor-cli.d.ts +13 -0
  19. package/dist/commands/adaptorch-doctor-cli.d.ts.map +1 -0
  20. package/dist/commands/adaptorch-doctor-cli.js +115 -0
  21. package/dist/commands/adaptorch-doctor-cli.js.map +1 -0
  22. package/dist/commands/resource-doctor-cli.d.ts +4 -0
  23. package/dist/commands/resource-doctor-cli.d.ts.map +1 -1
  24. package/dist/commands/resource-doctor-cli.js +35 -5
  25. package/dist/commands/resource-doctor-cli.js.map +1 -1
  26. package/dist/core/adaptorch-bridge.d.ts +11 -13
  27. package/dist/core/adaptorch-bridge.d.ts.map +1 -1
  28. package/dist/core/adaptorch-bridge.js +11 -13
  29. package/dist/core/adaptorch-bridge.js.map +1 -1
  30. package/dist/core/agent-session-snapshot.d.ts +16 -0
  31. package/dist/core/agent-session-snapshot.d.ts.map +1 -0
  32. package/dist/core/agent-session-snapshot.js +111 -0
  33. package/dist/core/agent-session-snapshot.js.map +1 -0
  34. package/dist/core/agent-session.d.ts +14 -10
  35. package/dist/core/agent-session.d.ts.map +1 -1
  36. package/dist/core/agent-session.js +102 -217
  37. package/dist/core/agent-session.js.map +1 -1
  38. package/dist/core/agent-tool-settings.d.ts +10 -0
  39. package/dist/core/agent-tool-settings.d.ts.map +1 -1
  40. package/dist/core/agent-tool-settings.js +10 -1
  41. package/dist/core/agent-tool-settings.js.map +1 -1
  42. package/dist/core/attachment-store.d.ts +39 -0
  43. package/dist/core/attachment-store.d.ts.map +1 -0
  44. package/dist/core/attachment-store.js +81 -0
  45. package/dist/core/attachment-store.js.map +1 -0
  46. package/dist/core/command-safety.d.ts +8 -0
  47. package/dist/core/command-safety.d.ts.map +1 -1
  48. package/dist/core/command-safety.js +140 -14
  49. package/dist/core/command-safety.js.map +1 -1
  50. package/dist/core/compaction/compaction.d.ts +13 -1
  51. package/dist/core/compaction/compaction.d.ts.map +1 -1
  52. package/dist/core/compaction/compaction.js +60 -62
  53. package/dist/core/compaction/compaction.js.map +1 -1
  54. package/dist/core/compaction/index.d.ts +1 -0
  55. package/dist/core/compaction/index.d.ts.map +1 -1
  56. package/dist/core/compaction/index.js +1 -0
  57. package/dist/core/compaction/index.js.map +1 -1
  58. package/dist/core/compaction/knowledge-triage-format.d.ts +9 -0
  59. package/dist/core/compaction/knowledge-triage-format.d.ts.map +1 -0
  60. package/dist/core/compaction/knowledge-triage-format.js +71 -0
  61. package/dist/core/compaction/knowledge-triage-format.js.map +1 -0
  62. package/dist/core/compaction/knowledge-triage-types.d.ts +7 -0
  63. package/dist/core/compaction/knowledge-triage-types.d.ts.map +1 -0
  64. package/dist/core/compaction/knowledge-triage-types.js +2 -0
  65. package/dist/core/compaction/knowledge-triage-types.js.map +1 -0
  66. package/dist/core/compaction/knowledge-triage.d.ts +29 -0
  67. package/dist/core/compaction/knowledge-triage.d.ts.map +1 -0
  68. package/dist/core/compaction/knowledge-triage.js +189 -0
  69. package/dist/core/compaction/knowledge-triage.js.map +1 -0
  70. package/dist/core/compaction/transaction.d.ts.map +1 -1
  71. package/dist/core/compaction/transaction.js +1 -1
  72. package/dist/core/compaction/transaction.js.map +1 -1
  73. package/dist/core/compaction/utils.d.ts +4 -0
  74. package/dist/core/compaction/utils.d.ts.map +1 -1
  75. package/dist/core/compaction/utils.js +37 -0
  76. package/dist/core/compaction/utils.js.map +1 -1
  77. package/dist/core/completion-sound-io.d.ts +14 -0
  78. package/dist/core/completion-sound-io.d.ts.map +1 -0
  79. package/dist/core/completion-sound-io.js +64 -0
  80. package/dist/core/completion-sound-io.js.map +1 -0
  81. package/dist/core/completion-sound.d.ts +4 -10
  82. package/dist/core/completion-sound.d.ts.map +1 -1
  83. package/dist/core/completion-sound.js +28 -58
  84. package/dist/core/completion-sound.js.map +1 -1
  85. package/dist/core/context-budget-governor-v2.d.ts +1 -1
  86. package/dist/core/context-budget-governor-v2.d.ts.map +1 -1
  87. package/dist/core/context-budget-governor-v2.js +1 -1
  88. package/dist/core/context-budget-governor-v2.js.map +1 -1
  89. package/dist/core/context-budget-relevance.d.ts +15 -2
  90. package/dist/core/context-budget-relevance.d.ts.map +1 -1
  91. package/dist/core/context-budget-relevance.js +21 -9
  92. package/dist/core/context-budget-relevance.js.map +1 -1
  93. package/dist/core/context-budget-system-prompt-items.d.ts +1 -1
  94. package/dist/core/context-budget-system-prompt-items.d.ts.map +1 -1
  95. package/dist/core/context-budget-system-prompt-items.js.map +1 -1
  96. package/dist/core/context-budget-system-prompt.d.ts +1 -1
  97. package/dist/core/context-budget-system-prompt.d.ts.map +1 -1
  98. package/dist/core/context-budget-system-prompt.js.map +1 -1
  99. package/dist/core/context-budget-v2-cache-keys.d.ts +3 -0
  100. package/dist/core/context-budget-v2-cache-keys.d.ts.map +1 -1
  101. package/dist/core/context-budget-v2-cache-keys.js +2 -0
  102. package/dist/core/context-budget-v2-cache-keys.js.map +1 -1
  103. package/dist/core/context-budget-v2-plan-cache-keys.d.ts.map +1 -1
  104. package/dist/core/context-budget-v2-plan-cache-keys.js +3 -0
  105. package/dist/core/context-budget-v2-plan-cache-keys.js.map +1 -1
  106. package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
  107. package/dist/core/context-budget-v2-planner.js +2 -1
  108. package/dist/core/context-budget-v2-planner.js.map +1 -1
  109. package/dist/core/context-budget-v2-scoring.d.ts +17 -0
  110. package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
  111. package/dist/core/context-budget-v2-scoring.js +25 -8
  112. package/dist/core/context-budget-v2-scoring.js.map +1 -1
  113. package/dist/core/context-budget-v2-selection.d.ts +2 -2
  114. package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
  115. package/dist/core/context-budget-v2-selection.js +18 -1
  116. package/dist/core/context-budget-v2-selection.js.map +1 -1
  117. package/dist/core/context-budget-v2-types.d.ts +17 -0
  118. package/dist/core/context-budget-v2-types.d.ts.map +1 -1
  119. package/dist/core/context-budget-v2-types.js +15 -0
  120. package/dist/core/context-budget-v2-types.js.map +1 -1
  121. package/dist/core/context-file.d.ts +23 -0
  122. package/dist/core/context-file.d.ts.map +1 -0
  123. package/dist/core/context-file.js +17 -0
  124. package/dist/core/context-file.js.map +1 -0
  125. package/dist/core/extensions/builtin/command-safety-gate.d.ts +3 -1
  126. package/dist/core/extensions/builtin/command-safety-gate.d.ts.map +1 -1
  127. package/dist/core/extensions/builtin/command-safety-gate.js +7 -0
  128. package/dist/core/extensions/builtin/command-safety-gate.js.map +1 -1
  129. package/dist/core/extensions/types.d.ts +12 -1
  130. package/dist/core/extensions/types.d.ts.map +1 -1
  131. package/dist/core/extensions/types.js.map +1 -1
  132. package/dist/core/keybindings.d.ts +1 -1
  133. package/dist/core/keybindings.d.ts.map +1 -1
  134. package/dist/core/keybindings.js +6 -1
  135. package/dist/core/keybindings.js.map +1 -1
  136. package/dist/core/model-prompt-policy.d.ts +1 -1
  137. package/dist/core/model-prompt-policy.d.ts.map +1 -1
  138. package/dist/core/model-prompt-policy.js.map +1 -1
  139. package/dist/core/model-registry.d.ts +8 -3
  140. package/dist/core/model-registry.d.ts.map +1 -1
  141. package/dist/core/model-registry.js +71 -1
  142. package/dist/core/model-registry.js.map +1 -1
  143. package/dist/core/package-doctor-source-scan.d.ts +9 -0
  144. package/dist/core/package-doctor-source-scan.d.ts.map +1 -1
  145. package/dist/core/package-doctor-source-scan.js +77 -4
  146. package/dist/core/package-doctor-source-scan.js.map +1 -1
  147. package/dist/core/prompt-attachment.d.ts +51 -0
  148. package/dist/core/prompt-attachment.d.ts.map +1 -0
  149. package/dist/core/prompt-attachment.js +186 -0
  150. package/dist/core/prompt-attachment.js.map +1 -0
  151. package/dist/core/prompt-settlement.d.ts +6 -3
  152. package/dist/core/prompt-settlement.d.ts.map +1 -1
  153. package/dist/core/prompt-settlement.js +10 -14
  154. package/dist/core/prompt-settlement.js.map +1 -1
  155. package/dist/core/provider-resilience.d.ts +28 -0
  156. package/dist/core/provider-resilience.d.ts.map +1 -1
  157. package/dist/core/provider-resilience.js +50 -0
  158. package/dist/core/provider-resilience.js.map +1 -1
  159. package/dist/core/provider-retry.d.ts +1 -1
  160. package/dist/core/provider-retry.d.ts.map +1 -1
  161. package/dist/core/provider-retry.js +1 -1
  162. package/dist/core/provider-retry.js.map +1 -1
  163. package/dist/core/provider-usage.d.ts.map +1 -1
  164. package/dist/core/provider-usage.js +68 -2
  165. package/dist/core/provider-usage.js.map +1 -1
  166. package/dist/core/reasoning-router-promotion.d.ts +124 -0
  167. package/dist/core/reasoning-router-promotion.d.ts.map +1 -0
  168. package/dist/core/reasoning-router-promotion.js +121 -0
  169. package/dist/core/reasoning-router-promotion.js.map +1 -0
  170. package/dist/core/reasoning-router-replay-stability.d.ts +65 -0
  171. package/dist/core/reasoning-router-replay-stability.d.ts.map +1 -0
  172. package/dist/core/reasoning-router-replay-stability.js +67 -0
  173. package/dist/core/reasoning-router-replay-stability.js.map +1 -0
  174. package/dist/core/reasoning-router-v4-weights.d.ts +6 -6
  175. package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -1
  176. package/dist/core/reasoning-router-v4-weights.js +3 -3
  177. package/dist/core/reasoning-router-v4-weights.js.map +1 -1
  178. package/dist/core/reasoning-router-v4.d.ts.map +1 -1
  179. package/dist/core/reasoning-router-v4.js +6 -6
  180. package/dist/core/reasoning-router-v4.js.map +1 -1
  181. package/dist/core/redaction.d.ts.map +1 -1
  182. package/dist/core/redaction.js +1 -1
  183. package/dist/core/redaction.js.map +1 -1
  184. package/dist/core/resource-admission.d.ts +2 -1
  185. package/dist/core/resource-admission.d.ts.map +1 -1
  186. package/dist/core/resource-admission.js +11 -0
  187. package/dist/core/resource-admission.js.map +1 -1
  188. package/dist/core/resource-governor-format.d.ts +1 -1
  189. package/dist/core/resource-governor-format.d.ts.map +1 -1
  190. package/dist/core/resource-governor-format.js.map +1 -1
  191. package/dist/core/resource-governor-settings.d.ts +6 -12
  192. package/dist/core/resource-governor-settings.d.ts.map +1 -1
  193. package/dist/core/resource-governor-settings.js.map +1 -1
  194. package/dist/core/resource-governor-types.d.ts +24 -0
  195. package/dist/core/resource-governor-types.d.ts.map +1 -0
  196. package/dist/core/resource-governor-types.js +15 -0
  197. package/dist/core/resource-governor-types.js.map +1 -0
  198. package/dist/core/resource-loader.d.ts +1 -7
  199. package/dist/core/resource-loader.d.ts.map +1 -1
  200. package/dist/core/resource-loader.js.map +1 -1
  201. package/dist/core/resource-observation-journal.d.ts +2 -1
  202. package/dist/core/resource-observation-journal.d.ts.map +1 -1
  203. package/dist/core/resource-observation-journal.js +4 -3
  204. package/dist/core/resource-observation-journal.js.map +1 -1
  205. package/dist/core/resource-observation-report-reader.d.ts +7 -0
  206. package/dist/core/resource-observation-report-reader.d.ts.map +1 -0
  207. package/dist/core/resource-observation-report-reader.js +157 -0
  208. package/dist/core/resource-observation-report-reader.js.map +1 -0
  209. package/dist/core/resource-observation-report.d.ts +24 -0
  210. package/dist/core/resource-observation-report.d.ts.map +1 -0
  211. package/dist/core/resource-observation-report.js +101 -0
  212. package/dist/core/resource-observation-report.js.map +1 -0
  213. package/dist/core/router-feedback-collector.d.ts +1 -1
  214. package/dist/core/router-feedback-collector.d.ts.map +1 -1
  215. package/dist/core/router-feedback-collector.js.map +1 -1
  216. package/dist/core/session-bash-service.d.ts.map +1 -1
  217. package/dist/core/session-bash-service.js +4 -3
  218. package/dist/core/session-bash-service.js.map +1 -1
  219. package/dist/core/session-failure-cause.d.ts +33 -0
  220. package/dist/core/session-failure-cause.d.ts.map +1 -0
  221. package/dist/core/session-failure-cause.js +141 -0
  222. package/dist/core/session-failure-cause.js.map +1 -0
  223. package/dist/core/session-system-prompt.d.ts +1 -1
  224. package/dist/core/session-system-prompt.d.ts.map +1 -1
  225. package/dist/core/session-system-prompt.js.map +1 -1
  226. package/dist/core/session-termination.d.ts +1 -1
  227. package/dist/core/session-termination.d.ts.map +1 -1
  228. package/dist/core/session-termination.js +11 -2
  229. package/dist/core/session-termination.js.map +1 -1
  230. package/dist/core/settings-manager.d.ts +1 -1
  231. package/dist/core/settings-manager.d.ts.map +1 -1
  232. package/dist/core/settings-manager.js.map +1 -1
  233. package/dist/core/system-prompt.d.ts +1 -1
  234. package/dist/core/system-prompt.d.ts.map +1 -1
  235. package/dist/core/system-prompt.js.map +1 -1
  236. package/dist/core/tools/bash.d.ts.map +1 -1
  237. package/dist/core/tools/bash.js +10 -14
  238. package/dist/core/tools/bash.js.map +1 -1
  239. package/dist/core/tools/grep.d.ts.map +1 -1
  240. package/dist/core/tools/grep.js +13 -48
  241. package/dist/core/tools/grep.js.map +1 -1
  242. package/dist/core/tools/read.d.ts.map +1 -1
  243. package/dist/core/tools/read.js +1 -34
  244. package/dist/core/tools/read.js.map +1 -1
  245. package/dist/core/workload-classifier.d.ts +2 -10
  246. package/dist/core/workload-classifier.d.ts.map +1 -1
  247. package/dist/core/workload-classifier.js +17 -0
  248. package/dist/core/workload-classifier.js.map +1 -1
  249. package/dist/core/workload-family-matcher.d.ts +1 -1
  250. package/dist/core/workload-family-matcher.d.ts.map +1 -1
  251. package/dist/core/workload-family-matcher.js.map +1 -1
  252. package/dist/core/workload-shard-execution-types.d.ts +40 -0
  253. package/dist/core/workload-shard-execution-types.d.ts.map +1 -0
  254. package/dist/core/workload-shard-execution-types.js +14 -0
  255. package/dist/core/workload-shard-execution-types.js.map +1 -0
  256. package/dist/core/workload-shard-executor.d.ts +3 -27
  257. package/dist/core/workload-shard-executor.d.ts.map +1 -1
  258. package/dist/core/workload-shard-executor.js.map +1 -1
  259. package/dist/core/workload-shard-runner.d.ts +1 -1
  260. package/dist/core/workload-shard-runner.d.ts.map +1 -1
  261. package/dist/core/workload-shard-runner.js.map +1 -1
  262. package/dist/core/workload-types.d.ts +24 -0
  263. package/dist/core/workload-types.d.ts.map +1 -0
  264. package/dist/core/workload-types.js +15 -0
  265. package/dist/core/workload-types.js.map +1 -0
  266. package/dist/index.d.ts +1 -1
  267. package/dist/index.d.ts.map +1 -1
  268. package/dist/index.js +1 -1
  269. package/dist/index.js.map +1 -1
  270. package/dist/main.d.ts +2 -0
  271. package/dist/main.d.ts.map +1 -1
  272. package/dist/main.js +27 -47
  273. package/dist/main.js.map +1 -1
  274. package/dist/modes/interactive/components/attachment-strip.d.ts +21 -0
  275. package/dist/modes/interactive/components/attachment-strip.d.ts.map +1 -0
  276. package/dist/modes/interactive/components/attachment-strip.js +136 -0
  277. package/dist/modes/interactive/components/attachment-strip.js.map +1 -0
  278. package/dist/modes/interactive/components/footer.d.ts +6 -0
  279. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/footer.js +26 -1
  281. package/dist/modes/interactive/components/footer.js.map +1 -1
  282. package/dist/modes/interactive/components/status-sidebar.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/status-sidebar.js +12 -1
  284. package/dist/modes/interactive/components/status-sidebar.js.map +1 -1
  285. package/dist/modes/interactive/interactive-mode.d.ts +23 -4
  286. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  287. package/dist/modes/interactive/interactive-mode.js +174 -53
  288. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  289. package/dist/modes/interactive/theme/omk-control-panel.json +1 -1
  290. package/dist/utils/clipboard-image.d.ts.map +1 -1
  291. package/dist/utils/clipboard-image.js +42 -33
  292. package/dist/utils/clipboard-image.js.map +1 -1
  293. package/dist/utils/clipboard.d.ts.map +1 -1
  294. package/dist/utils/clipboard.js +14 -2
  295. package/dist/utils/clipboard.js.map +1 -1
  296. package/docs/adaptorch-preview-spec.md +20 -18
  297. package/docs/adaptorch-preview.md +9 -9
  298. package/docs/compaction.md +25 -4
  299. package/docs/correctness-wall.md +10 -10
  300. package/docs/docs.json +12 -0
  301. package/docs/environment-variables.md +9 -2
  302. package/docs/extensions.md +12 -3
  303. package/docs/index.md +7 -1
  304. package/docs/metrics.md +74 -2
  305. package/docs/provider-resilience.md +11 -0
  306. package/docs/runtime-algorithms.md +359 -0
  307. package/docs/sdk.md +2 -2
  308. package/docs/settings.md +11 -10
  309. package/docs/usage.md +19 -3
  310. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  311. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  312. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  313. package/examples/extensions/gondolin/package-lock.json +2 -2
  314. package/examples/extensions/gondolin/package.json +1 -1
  315. package/examples/extensions/sandbox/package-lock.json +2 -2
  316. package/examples/extensions/sandbox/package.json +1 -1
  317. package/examples/extensions/with-deps/package-lock.json +2 -2
  318. package/examples/extensions/with-deps/package.json +1 -1
  319. package/npm-shrinkwrap.json +18 -18
  320. package/package.json +7 -7
  321. package/dist/core/context-budget-governor.d.ts +0 -67
  322. package/dist/core/context-budget-governor.d.ts.map +0 -1
  323. package/dist/core/context-budget-governor.js +0 -224
  324. package/dist/core/context-budget-governor.js.map +0 -1
  325. package/dist/core/lean-ctx.d.ts +0 -99
  326. package/dist/core/lean-ctx.d.ts.map +0 -1
  327. package/dist/core/lean-ctx.js +0 -225
  328. package/dist/core/lean-ctx.js.map +0 -1
  329. package/dist/core/read-anchors.d.ts +0 -110
  330. package/dist/core/read-anchors.d.ts.map +0 -1
  331. package/dist/core/read-anchors.js +0 -193
  332. package/dist/core/read-anchors.js.map +0 -1
  333. package/dist/core/recovery-checkpoint.d.ts +0 -196
  334. package/dist/core/recovery-checkpoint.d.ts.map +0 -1
  335. package/dist/core/recovery-checkpoint.js +0 -382
  336. package/dist/core/recovery-checkpoint.js.map +0 -1
  337. package/dist/core/sandbox-policy-v2.d.ts +0 -49
  338. package/dist/core/sandbox-policy-v2.d.ts.map +0 -1
  339. package/dist/core/sandbox-policy-v2.js +0 -368
  340. package/dist/core/sandbox-policy-v2.js.map +0 -1
  341. package/dist/core/tools/omp-pure-seams.d.ts +0 -41
  342. package/dist/core/tools/omp-pure-seams.d.ts.map +0 -1
  343. package/dist/core/tools/omp-pure-seams.js +0 -142
  344. package/dist/core/tools/omp-pure-seams.js.map +0 -1
  345. package/dist/core/tools/omp-seam-runtime.d.ts +0 -100
  346. package/dist/core/tools/omp-seam-runtime.d.ts.map +0 -1
  347. package/dist/core/tools/omp-seam-runtime.js +0 -40
  348. package/dist/core/tools/omp-seam-runtime.js.map +0 -1
  349. package/dist/guardrails/audit-logger.d.ts +0 -4
  350. package/dist/guardrails/audit-logger.d.ts.map +0 -1
  351. package/dist/guardrails/audit-logger.js +0 -28
  352. package/dist/guardrails/audit-logger.js.map +0 -1
  353. package/dist/guardrails/freedomd-adapter.d.ts +0 -16
  354. package/dist/guardrails/freedomd-adapter.d.ts.map +0 -1
  355. package/dist/guardrails/freedomd-adapter.js +0 -87
  356. package/dist/guardrails/freedomd-adapter.js.map +0 -1
  357. package/dist/orchestration/lane-grant-auditor.d.ts +0 -4
  358. package/dist/orchestration/lane-grant-auditor.d.ts.map +0 -1
  359. package/dist/orchestration/lane-grant-auditor.js +0 -87
  360. package/dist/orchestration/lane-grant-auditor.js.map +0 -1
  361. package/dist/types/guardrails.d.ts +0 -61
  362. package/dist/types/guardrails.d.ts.map +0 -1
  363. package/dist/types/guardrails.js +0 -9
  364. package/dist/types/guardrails.js.map +0 -1
  365. package/dist/types/lane-grant.d.ts +0 -58
  366. package/dist/types/lane-grant.d.ts.map +0 -1
  367. package/dist/types/lane-grant.js +0 -9
  368. package/dist/types/lane-grant.js.map +0 -1
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Promotion gate for learned reasoning-router weights.
3
+ *
4
+ * The router already produces a feedback ledger (`router-feedback-collector.ts`)
5
+ * and an offline calibration stack (`scripts/reasoning-router/`: calibration,
6
+ * held-out evaluation, golden diffing, and McNemar's exact test). What was
7
+ * missing is the decision policy that makes automatic promotion trustworthy:
8
+ * without it the loop is open and every weight change is a judgement call.
9
+ *
10
+ * This module is that policy, as a pure total function. It deliberately refuses
11
+ * to promote on anything short of unanimous evidence:
12
+ *
13
+ * - outcomes that survived a two-run replay, so a flipped measurement is never
14
+ * credited as a win (see `reasoning-router-replay-stability.ts`);
15
+ * - a comparison against the frozen reference policy rather than an opponent
16
+ * the caller picked, which is what stops baseline shopping;
17
+ * - a statistically significant win on the held-in gold set (McNemar's exact
18
+ * test), computed by the caller and passed in;
19
+ * - enough discordant pairs for that test to mean anything;
20
+ * - the candidate — not the baseline — winning those pairs;
21
+ * - no accuracy regression on a held-out split the calibration never saw;
22
+ * - no unreviewed behavior changes surfaced by golden diffing; and
23
+ * - an explicit human approval.
24
+ *
25
+ * "The agent tried again" is not the same as "the harness improved", so a
26
+ * candidate that merely fails to be worse is rejected, and malformed evidence
27
+ * fails closed rather than defaulting to promotion.
28
+ */
29
+ /**
30
+ * Conservative defaults. `minDiscordant` of 20 keeps McNemar from ruling on a
31
+ * handful of pairs; `maxGoldenChanges` of 0 means a reviewer accepts behavior
32
+ * changes by regenerating the golden set, never by tolerating drift.
33
+ *
34
+ * `minHoldout` is 40 because the router gold set freezes 42 holdout rows (6 per
35
+ * class × 7 classes). A higher bar would be unsatisfiable rather than strict,
36
+ * and a gate that can never pass is a gate nobody runs.
37
+ *
38
+ * `minReplays` of 2 is the two-run rule: one observation cannot be checked for
39
+ * stability at all. `maxUnstable` of 0 follows from what instability means here
40
+ * — the routing path is deterministic, so a single disagreeing row is a defect
41
+ * in the measurement, not an acceptable error rate to average over.
42
+ */
43
+ export const DEFAULT_ROUTER_PROMOTION_POLICY = {
44
+ maxGoldenChanges: 0,
45
+ maxUnstable: 0,
46
+ minDiscordant: 20,
47
+ minHoldout: 40,
48
+ minReplays: 2,
49
+ requireFrozenBaseline: true,
50
+ requireHumanApproval: true,
51
+ };
52
+ function isCount(value) {
53
+ return Number.isFinite(value) && value >= 0;
54
+ }
55
+ function isMalformed(evidence) {
56
+ const { goldenChanges, heldIn, holdout, stability } = evidence;
57
+ if (!isCount(heldIn.baselineWins) || !isCount(heldIn.candidateWins))
58
+ return true;
59
+ if (!Number.isFinite(heldIn.pValue) || heldIn.pValue < 0 || heldIn.pValue > 1)
60
+ return true;
61
+ if (!isCount(holdout.baselineCorrect) || !isCount(holdout.candidateCorrect) || !isCount(holdout.total))
62
+ return true;
63
+ if (holdout.baselineCorrect > holdout.total || holdout.candidateCorrect > holdout.total)
64
+ return true;
65
+ if (!isCount(stability.evaluated) || !isCount(stability.unstable) || !isCount(stability.replays))
66
+ return true;
67
+ if (stability.unstable > stability.evaluated)
68
+ return true;
69
+ return !isCount(goldenChanges);
70
+ }
71
+ /**
72
+ * Decide whether a candidate weight set may replace the active one.
73
+ *
74
+ * Returns every independent blocker rather than the first, so one calibration
75
+ * run reports the full distance to promotion instead of revealing it one
76
+ * rejection at a time. Malformed evidence short-circuits: the gate never
77
+ * reasons about numbers it cannot trust.
78
+ *
79
+ * Evidence-integrity blockers are reported ahead of statistical ones. A p-value
80
+ * computed over unstable rows or against the wrong opponent is not a weaker
81
+ * result, it is a result about nothing, and the report should say so first.
82
+ */
83
+ export function evaluateRouterPromotion(evidence, policy = DEFAULT_ROUTER_PROMOTION_POLICY) {
84
+ if (isMalformed(evidence)) {
85
+ return { blockers: ["malformed_evidence"], promote: false };
86
+ }
87
+ const { baselineKind, goldenChanges, heldIn, holdout, humanApproved, stability } = evidence;
88
+ const blockers = [];
89
+ if (stability.replays < policy.minReplays) {
90
+ blockers.push("insufficient_replays");
91
+ }
92
+ if (stability.unstable > policy.maxUnstable) {
93
+ blockers.push("unstable_evidence");
94
+ }
95
+ if (policy.requireFrozenBaseline && baselineKind !== "frozen_reference") {
96
+ blockers.push("baseline_not_frozen");
97
+ }
98
+ if (heldIn.baselineWins + heldIn.candidateWins < policy.minDiscordant) {
99
+ blockers.push("insufficient_discordant_pairs");
100
+ }
101
+ if (!heldIn.significant) {
102
+ blockers.push("mcnemar_not_significant");
103
+ }
104
+ if (heldIn.candidateWins <= heldIn.baselineWins) {
105
+ blockers.push("candidate_not_favored");
106
+ }
107
+ if (holdout.total < policy.minHoldout) {
108
+ blockers.push("insufficient_holdout");
109
+ }
110
+ if (holdout.candidateCorrect < holdout.baselineCorrect) {
111
+ blockers.push("holdout_regression");
112
+ }
113
+ if (goldenChanges > policy.maxGoldenChanges) {
114
+ blockers.push("unreviewed_behavior_changes");
115
+ }
116
+ if (policy.requireHumanApproval && !humanApproved) {
117
+ blockers.push("human_approval_missing");
118
+ }
119
+ return { blockers, promote: blockers.length === 0 };
120
+ }
121
+ //# sourceMappingURL=reasoning-router-promotion.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning-router-promotion.js","sourceRoot":"","sources":["../../src/core/reasoning-router-promotion.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAwFH;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAA0B;IACrE,gBAAgB,EAAE,CAAC;IACnB,WAAW,EAAE,CAAC;IACd,aAAa,EAAE,EAAE;IACjB,UAAU,EAAE,EAAE;IACd,UAAU,EAAE,CAAC;IACb,qBAAqB,EAAE,IAAI;IAC3B,oBAAoB,EAAE,IAAI;CAC1B,CAAC;AAEF,SAAS,OAAO,CAAC,KAAa,EAAW;IACxC,OAAO,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAAA,CAC5C;AAED,SAAS,WAAW,CAAC,QAAiC,EAAW;IAChE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;IAC/D,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC;QAAE,OAAO,IAAI,CAAC;IACjF,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3F,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACpH,IAAI,OAAO,CAAC,eAAe,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,gBAAgB,GAAG,OAAO,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACrG,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9G,IAAI,SAAS,CAAC,QAAQ,GAAG,SAAS,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC1D,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;AAAA,CAC/B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,uBAAuB,CACtC,QAAiC,EACjC,MAAM,GAA0B,+BAA+B,EACtC;IACzB,IAAI,WAAW,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,QAAQ,EAAE,CAAC,oBAAoB,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC7D,CAAC;IAED,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,GAAG,QAAQ,CAAC;IAC5F,MAAM,QAAQ,GAA6B,EAAE,CAAC;IAE9C,IAAI,SAAS,CAAC,OAAO,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAC3C,QAAQ,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,SAAS,CAAC,QAAQ,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,MAAM,CAAC,qBAAqB,IAAI,YAAY,KAAK,kBAAkB,EAAE,CAAC;QACzE,QAAQ,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACtC,CAAC;IACD,IAAI,MAAM,CAAC,YAAY,GAAG,MAAM,CAAC,aAAa,GAAG,MAAM,CAAC,aAAa,EAAE,CAAC;QACvE,QAAQ,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAChD,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC;QACzB,QAAQ,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAC1C,CAAC;IACD,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;QACjD,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;IACxC,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QACvC,QAAQ,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACvC,CAAC;IACD,IAAI,OAAO,CAAC,gBAAgB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;QACxD,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACrC,CAAC;IACD,IAAI,aAAa,GAAG,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC7C,QAAQ,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,MAAM,CAAC,oBAAoB,IAAI,CAAC,aAAa,EAAE,CAAC;QACnD,QAAQ,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;AAAA,CACpD","sourcesContent":["/**\n * Promotion gate for learned reasoning-router weights.\n *\n * The router already produces a feedback ledger (`router-feedback-collector.ts`)\n * and an offline calibration stack (`scripts/reasoning-router/`: calibration,\n * held-out evaluation, golden diffing, and McNemar's exact test). What was\n * missing is the decision policy that makes automatic promotion trustworthy:\n * without it the loop is open and every weight change is a judgement call.\n *\n * This module is that policy, as a pure total function. It deliberately refuses\n * to promote on anything short of unanimous evidence:\n *\n * - outcomes that survived a two-run replay, so a flipped measurement is never\n * credited as a win (see `reasoning-router-replay-stability.ts`);\n * - a comparison against the frozen reference policy rather than an opponent\n * the caller picked, which is what stops baseline shopping;\n * - a statistically significant win on the held-in gold set (McNemar's exact\n * test), computed by the caller and passed in;\n * - enough discordant pairs for that test to mean anything;\n * - the candidate — not the baseline — winning those pairs;\n * - no accuracy regression on a held-out split the calibration never saw;\n * - no unreviewed behavior changes surfaced by golden diffing; and\n * - an explicit human approval.\n *\n * \"The agent tried again\" is not the same as \"the harness improved\", so a\n * candidate that merely fails to be worse is rejected, and malformed evidence\n * fails closed rather than defaulting to promotion.\n */\n\n/** Held-in McNemar outcome. Wins are counted in discordant pairs only. */\nexport interface RouterHeldInEvidence {\n\t/** Rows the baseline classified correctly and the candidate got wrong. */\n\treadonly baselineWins: number;\n\t/** Rows the candidate classified correctly and the baseline got wrong. */\n\treadonly candidateWins: number;\n\treadonly pValue: number;\n\treadonly significant: boolean;\n}\n\n/** Accuracy on a split withheld from calibration. */\nexport interface RouterHoldoutEvidence {\n\treadonly baselineCorrect: number;\n\treadonly candidateCorrect: number;\n\treadonly total: number;\n}\n\n/** How much of the evidence survived repeated identical replays. */\nexport interface RouterStabilityEvidence {\n\t/** Rows replayed under both policies, whatever bucket they landed in. */\n\treadonly evaluated: number;\n\t/** Rows withheld because repeated observations disagreed. */\n\treadonly unstable: number;\n\t/** Independent observations per row behind the credited outcomes. */\n\treadonly replays: number;\n}\n\n/**\n * What the candidate was measured against.\n *\n * `frozen_reference` is the shipped policy that learning never updates. A\n * candidate that only beats an opponent the caller chose has demonstrated\n * nothing, so the gate refuses to reason about `ad_hoc` comparisons.\n */\nexport type RouterBaselineKind = \"frozen_reference\" | \"ad_hoc\";\n\n/** Everything the gate is allowed to consider. */\nexport interface RouterPromotionEvidence {\n\treadonly heldIn: RouterHeldInEvidence;\n\treadonly holdout: RouterHoldoutEvidence;\n\t/** Replay agreement behind every credited outcome. */\n\treadonly stability: RouterStabilityEvidence;\n\t/** Which opponent produced `heldIn` and `holdout`. */\n\treadonly baselineKind: RouterBaselineKind;\n\t/** Golden-diff changes still unreviewed at decision time. */\n\treadonly goldenChanges: number;\n\t/** True only when a human explicitly approved this exact candidate. */\n\treadonly humanApproved: boolean;\n}\n\n/** Tunable thresholds. Loosening these can never authorize a regression. */\nexport interface RouterPromotionPolicy {\n\t/** Minimum discordant pairs before McNemar's verdict is trusted. */\n\treadonly minDiscordant: number;\n\t/** Minimum held-out rows before \"no regression\" is meaningful. */\n\treadonly minHoldout: number;\n\t/** Maximum unreviewed golden-diff changes tolerated. */\n\treadonly maxGoldenChanges: number;\n\t/** Independent replays required per row before any outcome carries credit. */\n\treadonly minReplays: number;\n\t/** Maximum rows allowed to disagree across replays. */\n\treadonly maxUnstable: number;\n\t/** Require the frozen reference policy as the comparison opponent. */\n\treadonly requireFrozenBaseline: boolean;\n\treadonly requireHumanApproval: boolean;\n}\n\nexport type RouterPromotionBlocker =\n\t| \"malformed_evidence\"\n\t| \"insufficient_replays\"\n\t| \"unstable_evidence\"\n\t| \"baseline_not_frozen\"\n\t| \"insufficient_discordant_pairs\"\n\t| \"mcnemar_not_significant\"\n\t| \"candidate_not_favored\"\n\t| \"holdout_regression\"\n\t| \"insufficient_holdout\"\n\t| \"unreviewed_behavior_changes\"\n\t| \"human_approval_missing\";\n\nexport interface RouterPromotionVerdict {\n\treadonly promote: boolean;\n\t/** Every independent reason promotion was refused, in evaluation order. */\n\treadonly blockers: readonly RouterPromotionBlocker[];\n}\n\n/**\n * Conservative defaults. `minDiscordant` of 20 keeps McNemar from ruling on a\n * handful of pairs; `maxGoldenChanges` of 0 means a reviewer accepts behavior\n * changes by regenerating the golden set, never by tolerating drift.\n *\n * `minHoldout` is 40 because the router gold set freezes 42 holdout rows (6 per\n * class × 7 classes). A higher bar would be unsatisfiable rather than strict,\n * and a gate that can never pass is a gate nobody runs.\n *\n * `minReplays` of 2 is the two-run rule: one observation cannot be checked for\n * stability at all. `maxUnstable` of 0 follows from what instability means here\n * — the routing path is deterministic, so a single disagreeing row is a defect\n * in the measurement, not an acceptable error rate to average over.\n */\nexport const DEFAULT_ROUTER_PROMOTION_POLICY: RouterPromotionPolicy = {\n\tmaxGoldenChanges: 0,\n\tmaxUnstable: 0,\n\tminDiscordant: 20,\n\tminHoldout: 40,\n\tminReplays: 2,\n\trequireFrozenBaseline: true,\n\trequireHumanApproval: true,\n};\n\nfunction isCount(value: number): boolean {\n\treturn Number.isFinite(value) && value >= 0;\n}\n\nfunction isMalformed(evidence: RouterPromotionEvidence): boolean {\n\tconst { goldenChanges, heldIn, holdout, stability } = evidence;\n\tif (!isCount(heldIn.baselineWins) || !isCount(heldIn.candidateWins)) return true;\n\tif (!Number.isFinite(heldIn.pValue) || heldIn.pValue < 0 || heldIn.pValue > 1) return true;\n\tif (!isCount(holdout.baselineCorrect) || !isCount(holdout.candidateCorrect) || !isCount(holdout.total)) return true;\n\tif (holdout.baselineCorrect > holdout.total || holdout.candidateCorrect > holdout.total) return true;\n\tif (!isCount(stability.evaluated) || !isCount(stability.unstable) || !isCount(stability.replays)) return true;\n\tif (stability.unstable > stability.evaluated) return true;\n\treturn !isCount(goldenChanges);\n}\n\n/**\n * Decide whether a candidate weight set may replace the active one.\n *\n * Returns every independent blocker rather than the first, so one calibration\n * run reports the full distance to promotion instead of revealing it one\n * rejection at a time. Malformed evidence short-circuits: the gate never\n * reasons about numbers it cannot trust.\n *\n * Evidence-integrity blockers are reported ahead of statistical ones. A p-value\n * computed over unstable rows or against the wrong opponent is not a weaker\n * result, it is a result about nothing, and the report should say so first.\n */\nexport function evaluateRouterPromotion(\n\tevidence: RouterPromotionEvidence,\n\tpolicy: RouterPromotionPolicy = DEFAULT_ROUTER_PROMOTION_POLICY,\n): RouterPromotionVerdict {\n\tif (isMalformed(evidence)) {\n\t\treturn { blockers: [\"malformed_evidence\"], promote: false };\n\t}\n\n\tconst { baselineKind, goldenChanges, heldIn, holdout, humanApproved, stability } = evidence;\n\tconst blockers: RouterPromotionBlocker[] = [];\n\n\tif (stability.replays < policy.minReplays) {\n\t\tblockers.push(\"insufficient_replays\");\n\t}\n\tif (stability.unstable > policy.maxUnstable) {\n\t\tblockers.push(\"unstable_evidence\");\n\t}\n\tif (policy.requireFrozenBaseline && baselineKind !== \"frozen_reference\") {\n\t\tblockers.push(\"baseline_not_frozen\");\n\t}\n\tif (heldIn.baselineWins + heldIn.candidateWins < policy.minDiscordant) {\n\t\tblockers.push(\"insufficient_discordant_pairs\");\n\t}\n\tif (!heldIn.significant) {\n\t\tblockers.push(\"mcnemar_not_significant\");\n\t}\n\tif (heldIn.candidateWins <= heldIn.baselineWins) {\n\t\tblockers.push(\"candidate_not_favored\");\n\t}\n\tif (holdout.total < policy.minHoldout) {\n\t\tblockers.push(\"insufficient_holdout\");\n\t}\n\tif (holdout.candidateCorrect < holdout.baselineCorrect) {\n\t\tblockers.push(\"holdout_regression\");\n\t}\n\tif (goldenChanges > policy.maxGoldenChanges) {\n\t\tblockers.push(\"unreviewed_behavior_changes\");\n\t}\n\tif (policy.requireHumanApproval && !humanApproved) {\n\t\tblockers.push(\"human_approval_missing\");\n\t}\n\n\treturn { blockers, promote: blockers.length === 0 };\n}\n"]}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Two-run stability filter for reasoning-router promotion evidence.
3
+ *
4
+ * A promotion gate is only as trustworthy as the outcomes it credits. Routing
5
+ * evaluations are paired comparisons, and paired comparisons are cheap to fool:
6
+ * if the measured outcome of a row can flip between two identical replays, then
7
+ * a "win" on that row may be measurement noise rather than a better policy.
8
+ * Published routing evaluations report exactly this — a non-trivial share of
9
+ * model/question pairs score differently when the identical matrix is re-run —
10
+ * so a credit rule that ignores rerun disagreement will happily promote noise.
11
+ *
12
+ * This module implements the rule that closes that hole: a row carries credit
13
+ * only when it was observed at least `minReplays` times under each policy and
14
+ * every one of those observations agreed. Rows that disagree are withheld, not
15
+ * majority-voted — a flipped observation means the measurement is unreliable,
16
+ * not that the majority is the truth.
17
+ *
18
+ * For a deterministic classifier every row is stable by construction, so the
19
+ * filter is also a determinism attestation: if nondeterminism ever leaks into
20
+ * the routing path (iteration order, clock, randomness), rows start landing in
21
+ * the unstable bucket and the gate refuses to promote instead of crediting a
22
+ * coin flip.
23
+ *
24
+ * Pure and total: no I/O, no global state, no prompt text.
25
+ */
26
+ /** Independent observations required per side before a row may carry credit. */
27
+ export declare const DEFAULT_REPLAY_MIN = 2;
28
+ /** One evaluated row, replayed independently under each policy. */
29
+ export interface RouterReplayRow {
30
+ readonly rowId: string;
31
+ /** True when the row belongs to the frozen held-out split. */
32
+ readonly holdout: boolean;
33
+ /** Correctness observed on each independent replay under the baseline. */
34
+ readonly baselineReplays: readonly boolean[];
35
+ /** Correctness observed on each independent replay under the candidate. */
36
+ readonly candidateReplays: readonly boolean[];
37
+ }
38
+ /** A row whose replays agreed, so its outcome may carry promotion credit. */
39
+ export interface RouterStableOutcome {
40
+ readonly rowId: string;
41
+ readonly holdout: boolean;
42
+ readonly baselineCorrect: boolean;
43
+ readonly candidateCorrect: boolean;
44
+ }
45
+ /** Credit-eligible outcomes plus why every other row was withheld. */
46
+ export interface RouterReplayStability {
47
+ readonly stable: readonly RouterStableOutcome[];
48
+ /** Rows considered, whatever bucket they landed in. */
49
+ readonly evaluated: number;
50
+ /** Rows withheld because repeated observations disagreed. */
51
+ readonly unstable: number;
52
+ /** Rows withheld because one side was observed too few times to judge. */
53
+ readonly insufficientReplays: number;
54
+ readonly minReplays: number;
55
+ }
56
+ /**
57
+ * Partition replayed rows into credit-eligible outcomes and withheld rows.
58
+ *
59
+ * Insufficient replays outrank disagreement: a row observed once is not stable
60
+ * evidence that happens to agree with itself, it is evidence that was never
61
+ * tested for stability at all. Reporting the two buckets separately keeps that
62
+ * distinction visible to the gate, which fails closed on either.
63
+ */
64
+ export declare function summarizeReplayStability(rows: readonly RouterReplayRow[], minReplays?: number): RouterReplayStability;
65
+ //# sourceMappingURL=reasoning-router-replay-stability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning-router-replay-stability.d.ts","sourceRoot":"","sources":["../../src/core/reasoning-router-replay-stability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,mEAAmE;AACnE,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,eAAe,EAAE,SAAS,OAAO,EAAE,CAAC;IAC7C,2EAA2E;IAC3E,QAAQ,CAAC,gBAAgB,EAAE,SAAS,OAAO,EAAE,CAAC;CAC9C;AAED,6EAA6E;AAC7E,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,gBAAgB,EAAE,OAAO,CAAC;CACnC;AAED,sEAAsE;AACtE,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,MAAM,EAAE,SAAS,mBAAmB,EAAE,CAAC;IAChD,uDAAuD;IACvD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,0EAA0E;IAC1E,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC5B;AAgBD;;;;;;;GAOG;AACH,wBAAgB,wBAAwB,CACvC,IAAI,EAAE,SAAS,eAAe,EAAE,EAChC,UAAU,GAAE,MAA2B,GACrC,qBAAqB,CA2BvB","sourcesContent":["/**\n * Two-run stability filter for reasoning-router promotion evidence.\n *\n * A promotion gate is only as trustworthy as the outcomes it credits. Routing\n * evaluations are paired comparisons, and paired comparisons are cheap to fool:\n * if the measured outcome of a row can flip between two identical replays, then\n * a \"win\" on that row may be measurement noise rather than a better policy.\n * Published routing evaluations report exactly this — a non-trivial share of\n * model/question pairs score differently when the identical matrix is re-run —\n * so a credit rule that ignores rerun disagreement will happily promote noise.\n *\n * This module implements the rule that closes that hole: a row carries credit\n * only when it was observed at least `minReplays` times under each policy and\n * every one of those observations agreed. Rows that disagree are withheld, not\n * majority-voted — a flipped observation means the measurement is unreliable,\n * not that the majority is the truth.\n *\n * For a deterministic classifier every row is stable by construction, so the\n * filter is also a determinism attestation: if nondeterminism ever leaks into\n * the routing path (iteration order, clock, randomness), rows start landing in\n * the unstable bucket and the gate refuses to promote instead of crediting a\n * coin flip.\n *\n * Pure and total: no I/O, no global state, no prompt text.\n */\n\n/** Independent observations required per side before a row may carry credit. */\nexport const DEFAULT_REPLAY_MIN = 2;\n\n/** One evaluated row, replayed independently under each policy. */\nexport interface RouterReplayRow {\n\treadonly rowId: string;\n\t/** True when the row belongs to the frozen held-out split. */\n\treadonly holdout: boolean;\n\t/** Correctness observed on each independent replay under the baseline. */\n\treadonly baselineReplays: readonly boolean[];\n\t/** Correctness observed on each independent replay under the candidate. */\n\treadonly candidateReplays: readonly boolean[];\n}\n\n/** A row whose replays agreed, so its outcome may carry promotion credit. */\nexport interface RouterStableOutcome {\n\treadonly rowId: string;\n\treadonly holdout: boolean;\n\treadonly baselineCorrect: boolean;\n\treadonly candidateCorrect: boolean;\n}\n\n/** Credit-eligible outcomes plus why every other row was withheld. */\nexport interface RouterReplayStability {\n\treadonly stable: readonly RouterStableOutcome[];\n\t/** Rows considered, whatever bucket they landed in. */\n\treadonly evaluated: number;\n\t/** Rows withheld because repeated observations disagreed. */\n\treadonly unstable: number;\n\t/** Rows withheld because one side was observed too few times to judge. */\n\treadonly insufficientReplays: number;\n\treadonly minReplays: number;\n}\n\n/** Verdict for one side of one row. */\ntype ReplayVerdict =\n\t| { readonly kind: \"agreed\"; readonly correct: boolean }\n\t| { readonly kind: \"disagreed\" }\n\t| { readonly kind: \"insufficient\" };\n\nfunction judgeReplays(replays: readonly boolean[], minReplays: number): ReplayVerdict {\n\tconst [first, ...rest] = replays;\n\tif (first === undefined || replays.length < minReplays) {\n\t\treturn { kind: \"insufficient\" };\n\t}\n\treturn rest.every((replay) => replay === first) ? { correct: first, kind: \"agreed\" } : { kind: \"disagreed\" };\n}\n\n/**\n * Partition replayed rows into credit-eligible outcomes and withheld rows.\n *\n * Insufficient replays outrank disagreement: a row observed once is not stable\n * evidence that happens to agree with itself, it is evidence that was never\n * tested for stability at all. Reporting the two buckets separately keeps that\n * distinction visible to the gate, which fails closed on either.\n */\nexport function summarizeReplayStability(\n\trows: readonly RouterReplayRow[],\n\tminReplays: number = DEFAULT_REPLAY_MIN,\n): RouterReplayStability {\n\tconst stable: RouterStableOutcome[] = [];\n\tlet unstable = 0;\n\tlet insufficientReplays = 0;\n\n\tfor (const row of rows) {\n\t\tconst baseline = judgeReplays(row.baselineReplays, minReplays);\n\t\tconst candidate = judgeReplays(row.candidateReplays, minReplays);\n\n\t\tif (baseline.kind === \"insufficient\" || candidate.kind === \"insufficient\") {\n\t\t\tinsufficientReplays++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (baseline.kind === \"disagreed\" || candidate.kind === \"disagreed\") {\n\t\t\tunstable++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tstable.push({\n\t\t\tbaselineCorrect: baseline.correct,\n\t\t\tcandidateCorrect: candidate.correct,\n\t\t\tholdout: row.holdout,\n\t\t\trowId: row.rowId,\n\t\t});\n\t}\n\n\treturn { evaluated: rows.length, insufficientReplays, minReplays, stable, unstable };\n}\n"]}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Two-run stability filter for reasoning-router promotion evidence.
3
+ *
4
+ * A promotion gate is only as trustworthy as the outcomes it credits. Routing
5
+ * evaluations are paired comparisons, and paired comparisons are cheap to fool:
6
+ * if the measured outcome of a row can flip between two identical replays, then
7
+ * a "win" on that row may be measurement noise rather than a better policy.
8
+ * Published routing evaluations report exactly this — a non-trivial share of
9
+ * model/question pairs score differently when the identical matrix is re-run —
10
+ * so a credit rule that ignores rerun disagreement will happily promote noise.
11
+ *
12
+ * This module implements the rule that closes that hole: a row carries credit
13
+ * only when it was observed at least `minReplays` times under each policy and
14
+ * every one of those observations agreed. Rows that disagree are withheld, not
15
+ * majority-voted — a flipped observation means the measurement is unreliable,
16
+ * not that the majority is the truth.
17
+ *
18
+ * For a deterministic classifier every row is stable by construction, so the
19
+ * filter is also a determinism attestation: if nondeterminism ever leaks into
20
+ * the routing path (iteration order, clock, randomness), rows start landing in
21
+ * the unstable bucket and the gate refuses to promote instead of crediting a
22
+ * coin flip.
23
+ *
24
+ * Pure and total: no I/O, no global state, no prompt text.
25
+ */
26
+ /** Independent observations required per side before a row may carry credit. */
27
+ export const DEFAULT_REPLAY_MIN = 2;
28
+ function judgeReplays(replays, minReplays) {
29
+ const [first, ...rest] = replays;
30
+ if (first === undefined || replays.length < minReplays) {
31
+ return { kind: "insufficient" };
32
+ }
33
+ return rest.every((replay) => replay === first) ? { correct: first, kind: "agreed" } : { kind: "disagreed" };
34
+ }
35
+ /**
36
+ * Partition replayed rows into credit-eligible outcomes and withheld rows.
37
+ *
38
+ * Insufficient replays outrank disagreement: a row observed once is not stable
39
+ * evidence that happens to agree with itself, it is evidence that was never
40
+ * tested for stability at all. Reporting the two buckets separately keeps that
41
+ * distinction visible to the gate, which fails closed on either.
42
+ */
43
+ export function summarizeReplayStability(rows, minReplays = DEFAULT_REPLAY_MIN) {
44
+ const stable = [];
45
+ let unstable = 0;
46
+ let insufficientReplays = 0;
47
+ for (const row of rows) {
48
+ const baseline = judgeReplays(row.baselineReplays, minReplays);
49
+ const candidate = judgeReplays(row.candidateReplays, minReplays);
50
+ if (baseline.kind === "insufficient" || candidate.kind === "insufficient") {
51
+ insufficientReplays++;
52
+ continue;
53
+ }
54
+ if (baseline.kind === "disagreed" || candidate.kind === "disagreed") {
55
+ unstable++;
56
+ continue;
57
+ }
58
+ stable.push({
59
+ baselineCorrect: baseline.correct,
60
+ candidateCorrect: candidate.correct,
61
+ holdout: row.holdout,
62
+ rowId: row.rowId,
63
+ });
64
+ }
65
+ return { evaluated: rows.length, insufficientReplays, minReplays, stable, unstable };
66
+ }
67
+ //# sourceMappingURL=reasoning-router-replay-stability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reasoning-router-replay-stability.js","sourceRoot":"","sources":["../../src/core/reasoning-router-replay-stability.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,gFAAgF;AAChF,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAuCpC,SAAS,YAAY,CAAC,OAA2B,EAAE,UAAkB,EAAiB;IACrF,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,UAAU,EAAE,CAAC;QACxD,OAAO,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IACjC,CAAC;IACD,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;AAAA,CAC7G;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,wBAAwB,CACvC,IAAgC,EAChC,UAAU,GAAW,kBAAkB,EACf;IACxB,MAAM,MAAM,GAA0B,EAAE,CAAC;IACzC,IAAI,QAAQ,GAAG,CAAC,CAAC;IACjB,IAAI,mBAAmB,GAAG,CAAC,CAAC;IAE5B,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACxB,MAAM,QAAQ,GAAG,YAAY,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;QAEjE,IAAI,QAAQ,CAAC,IAAI,KAAK,cAAc,IAAI,SAAS,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YAC3E,mBAAmB,EAAE,CAAC;YACtB,SAAS;QACV,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,KAAK,WAAW,IAAI,SAAS,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACrE,QAAQ,EAAE,CAAC;YACX,SAAS;QACV,CAAC;QAED,MAAM,CAAC,IAAI,CAAC;YACX,eAAe,EAAE,QAAQ,CAAC,OAAO;YACjC,gBAAgB,EAAE,SAAS,CAAC,OAAO;YACnC,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,KAAK,EAAE,GAAG,CAAC,KAAK;SAChB,CAAC,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AAAA,CACrF","sourcesContent":["/**\n * Two-run stability filter for reasoning-router promotion evidence.\n *\n * A promotion gate is only as trustworthy as the outcomes it credits. Routing\n * evaluations are paired comparisons, and paired comparisons are cheap to fool:\n * if the measured outcome of a row can flip between two identical replays, then\n * a \"win\" on that row may be measurement noise rather than a better policy.\n * Published routing evaluations report exactly this — a non-trivial share of\n * model/question pairs score differently when the identical matrix is re-run —\n * so a credit rule that ignores rerun disagreement will happily promote noise.\n *\n * This module implements the rule that closes that hole: a row carries credit\n * only when it was observed at least `minReplays` times under each policy and\n * every one of those observations agreed. Rows that disagree are withheld, not\n * majority-voted — a flipped observation means the measurement is unreliable,\n * not that the majority is the truth.\n *\n * For a deterministic classifier every row is stable by construction, so the\n * filter is also a determinism attestation: if nondeterminism ever leaks into\n * the routing path (iteration order, clock, randomness), rows start landing in\n * the unstable bucket and the gate refuses to promote instead of crediting a\n * coin flip.\n *\n * Pure and total: no I/O, no global state, no prompt text.\n */\n\n/** Independent observations required per side before a row may carry credit. */\nexport const DEFAULT_REPLAY_MIN = 2;\n\n/** One evaluated row, replayed independently under each policy. */\nexport interface RouterReplayRow {\n\treadonly rowId: string;\n\t/** True when the row belongs to the frozen held-out split. */\n\treadonly holdout: boolean;\n\t/** Correctness observed on each independent replay under the baseline. */\n\treadonly baselineReplays: readonly boolean[];\n\t/** Correctness observed on each independent replay under the candidate. */\n\treadonly candidateReplays: readonly boolean[];\n}\n\n/** A row whose replays agreed, so its outcome may carry promotion credit. */\nexport interface RouterStableOutcome {\n\treadonly rowId: string;\n\treadonly holdout: boolean;\n\treadonly baselineCorrect: boolean;\n\treadonly candidateCorrect: boolean;\n}\n\n/** Credit-eligible outcomes plus why every other row was withheld. */\nexport interface RouterReplayStability {\n\treadonly stable: readonly RouterStableOutcome[];\n\t/** Rows considered, whatever bucket they landed in. */\n\treadonly evaluated: number;\n\t/** Rows withheld because repeated observations disagreed. */\n\treadonly unstable: number;\n\t/** Rows withheld because one side was observed too few times to judge. */\n\treadonly insufficientReplays: number;\n\treadonly minReplays: number;\n}\n\n/** Verdict for one side of one row. */\ntype ReplayVerdict =\n\t| { readonly kind: \"agreed\"; readonly correct: boolean }\n\t| { readonly kind: \"disagreed\" }\n\t| { readonly kind: \"insufficient\" };\n\nfunction judgeReplays(replays: readonly boolean[], minReplays: number): ReplayVerdict {\n\tconst [first, ...rest] = replays;\n\tif (first === undefined || replays.length < minReplays) {\n\t\treturn { kind: \"insufficient\" };\n\t}\n\treturn rest.every((replay) => replay === first) ? { correct: first, kind: \"agreed\" } : { kind: \"disagreed\" };\n}\n\n/**\n * Partition replayed rows into credit-eligible outcomes and withheld rows.\n *\n * Insufficient replays outrank disagreement: a row observed once is not stable\n * evidence that happens to agree with itself, it is evidence that was never\n * tested for stability at all. Reporting the two buckets separately keeps that\n * distinction visible to the gate, which fails closed on either.\n */\nexport function summarizeReplayStability(\n\trows: readonly RouterReplayRow[],\n\tminReplays: number = DEFAULT_REPLAY_MIN,\n): RouterReplayStability {\n\tconst stable: RouterStableOutcome[] = [];\n\tlet unstable = 0;\n\tlet insufficientReplays = 0;\n\n\tfor (const row of rows) {\n\t\tconst baseline = judgeReplays(row.baselineReplays, minReplays);\n\t\tconst candidate = judgeReplays(row.candidateReplays, minReplays);\n\n\t\tif (baseline.kind === \"insufficient\" || candidate.kind === \"insufficient\") {\n\t\t\tinsufficientReplays++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (baseline.kind === \"disagreed\" || candidate.kind === \"disagreed\") {\n\t\t\tunstable++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tstable.push({\n\t\t\tbaselineCorrect: baseline.correct,\n\t\t\tcandidateCorrect: candidate.correct,\n\t\t\tholdout: row.holdout,\n\t\t\trowId: row.rowId,\n\t\t});\n\t}\n\n\treturn { evaluated: rows.length, insufficientReplays, minReplays, stable, unstable };\n}\n"]}
@@ -64,11 +64,11 @@ export interface RouterWeightsV4 {
64
64
  readonly intentSkeleton: number;
65
65
  /** Bump to "code-gen" for a bare "add" keyword, gated by !localEdit. */
66
66
  readonly addKeyword: number;
67
- /** Bump to the class matching `history[0]`, if supplied (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */
67
+ /** Bump to the class matching `history[0]`, if supplied (default 2; gated on existing prompt evidence). */
68
68
  readonly multiTurnPrior: number;
69
- /** Linear per-bucket bump applied to debug/review/plan under context pressure (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */
69
+ /** Linear per-bucket bump applied to debug/review/plan under context pressure (default 1). */
70
70
  readonly pressureBucket: number;
71
- /** Bump to the class matching an externally supplied judge vote, if any (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */
71
+ /** Bump to an externally supplied judge vote, if any (default 2; gated on existing prompt evidence). */
72
72
  readonly judgeVote: number;
73
73
  /** Bounded look-back window (characters) for negation-cue gating, never crossing a .,;!? boundary. */
74
74
  readonly negationWindowChars: number;
@@ -80,9 +80,9 @@ export interface RouterWeightsV4 {
80
80
  /**
81
81
  * Calibrated default preset. The named weights below are the production v4
82
82
  * scorer configuration covered by
83
- * test/suite/regressions/013-reasoning-router-v4-accuracy.test.ts. Extension
84
- * fields (`multiTurnPrior`, `pressureBucket`, `judgeVote`) are wired but inert
85
- * until a future calibration changes them.
83
+ * test/suite/regressions/013-reasoning-router-v4-accuracy.test.ts. The bounded
84
+ * extension fields (`multiTurnPrior`, `pressureBucket`, `judgeVote`) are active
85
+ * only after the base scorer finds prompt evidence; zero-score fallbacks ignore them.
86
86
  */
87
87
  export declare const DEFAULT_WEIGHTS_V4: RouterWeightsV4;
88
88
  //# sourceMappingURL=reasoning-router-v4-weights.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"reasoning-router-v4-weights.d.ts","sourceRoot":"","sources":["../../src/core/reasoning-router-v4-weights.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,qCAAqC;AACrC,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5G,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAExG,yIAAyI;AACzI,eAAO,MAAM,eAAe,EAAE,SAAS,WAAW,EAQjD,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,6HAA6H;IAC7H,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4GAA4G;IAC5G,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,uFAAuF;IACvF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,6GAA6G;IAC7G,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,kHAAkH;IAClH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D,iGAAiG;IACjG,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,wGAAwG;IACxG,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,yHAAyH;IACzH,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,+IAA+I;IAC/I,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,yIAAyI;IACzI,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sGAAsG;IACtG,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,4GAA4G;IAC5G,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,gDAAgD;IAChD,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;CACzC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAqChC,CAAC","sourcesContent":["/**\n * Reasoning-router v4 — frozen types and calibratable weight schema.\n *\n * Pure, side-effect-free, erasable TypeScript. No runtime imports. This file\n * owns the closed task/lane unions, named scorer weights, and calibrated default\n * preset used by `/think auto`.\n *\n * `keywordFamily` is the class -> weight table for whole-prompt keyword-family\n * patterns (see reasoning-router-v4.ts). `trivial` carries weight 0 because it\n * is reached only via the zero-score fallback cascade.\n *\n * `secondClauseIntent` applies a bounded bonus when a second, distinct leading\n * verb is found after a short-range conjunction split. `negationWindowChars`\n * bounds negation gating so a nearby \"don't/skip/without/no need\" cue can\n * suppress a whole-prompt signal without crossing a clause boundary.\n *\n * `lowConfidenceThreshold` / `highConfidenceThreshold` bound the confidence\n * bands (`ClassifierVerdictV4.confidenceBand`) computed from score separation\n * plus absolute evidence strength in reasoning-router-v4.ts. They are\n * metadata-only: they never change `taskClass`, only how\n * `resolveThinkingLevelV4WithUncertainty` treats an already-decided class.\n */\n\n/** Closed set of v4 task classes. */\nexport type TaskClassV4 = \"trivial\" | \"simple-edit\" | \"code-gen\" | \"debug\" | \"refactor\" | \"review\" | \"plan\";\n\n/** Subagent lane types recognized by the v4 classifier and resolvers. */\nexport type ReasoningLaneTypeV4 = \"planner\" | \"security\" | \"explorer\" | \"coder\" | \"reviewer\" | \"tester\";\n\n/** Fixed iteration order over TaskClassV4 (matches the type-declaration order; also v4's argmax tie-break precedence, highest first). */\nexport const TASK_CLASSES_V4: readonly TaskClassV4[] = [\n\t\"debug\",\n\t\"refactor\",\n\t\"review\",\n\t\"plan\",\n\t\"simple-edit\",\n\t\"code-gen\",\n\t\"trivial\",\n];\n\n/**\n * Named weight schema for the v4 scorer (reasoning-router-v4.ts). Every field\n * is a plain, deterministic integer/ratio; there is no clock, randomness, or\n * I/O anywhere in this file or its consumer.\n */\nexport interface RouterWeightsV4 {\n\t/** Bump to \"code-gen\" when a code fence or diff hunk is present. */\n\treadonly codeFenceOrDiff: number;\n\t/** Bump to the primary leading-clause intent class, if any. */\n\treadonly leadingIntent: number;\n\t/** Bump to a distinct second-clause intent class in a detected compound prompt (v4-new; default half of `leadingIntent`). */\n\treadonly secondClauseIntent: number;\n\t/** Bump to \"simple-edit\" when the composite local-edit feature fires. */\n\treadonly localEdit: number;\n\t/** Bump to \"debug\" when the composite diagnostic-evidence feature fires. */\n\treadonly diagnosticEvidence: number;\n\t/** Bump to \"review\" when the composite review-scope feature fires. */\n\treadonly reviewScope: number;\n\t/** Bump to \"plan\" when the composite plan-brief feature fires. */\n\treadonly planBrief: number;\n\t/** Bump to \"plan\" for release-bound operational runbooks (commit/push/tag/publish/changelog/CI bundles). */\n\treadonly operationalRunbook: number;\n\t/** Bump to \"refactor\" when the refactor-cue pattern matches anywhere in the prompt. */\n\treadonly refactorCue: number;\n\t/** Bump to \"code-gen\" when an implementation-object noun is present. */\n\treadonly implementationObject: number;\n\t/** Bump to \"code-gen\" when a first-person request names a code artifact (for example, \"I need a script\"). */\n\treadonly codeGenArtifactRequest: number;\n\t/** Bump to \"review\" when a leading review request names an evaluative object such as holes/regressions/issues. */\n\treadonly evaluativeReviewObject: number;\n\t/** Per-class whole-prompt keyword-family bump; trivial has no family, 0. */\n\treadonly keywordFamily: Readonly<Record<TaskClassV4, number>>;\n\t/** Bump to a class when normalized seed->cluster anchors match (medium generalized evidence). */\n\treadonly normalizedIntentCluster: number;\n\t/** Bump to a class when the bounded intent-skeleton extractor matches (medium generalized evidence). */\n\treadonly intentSkeleton: number;\n\t/** Bump to \"code-gen\" for a bare \"add\" keyword, gated by !localEdit. */\n\treadonly addKeyword: number;\n\t/** Bump to the class matching `history[0]`, if supplied (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */\n\treadonly multiTurnPrior: number;\n\t/** Linear per-bucket bump applied to debug/review/plan under context pressure (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */\n\treadonly pressureBucket: number;\n\t/** Bump to the class matching an externally supplied judge vote, if any (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */\n\treadonly judgeVote: number;\n\t/** Bounded look-back window (characters) for negation-cue gating, never crossing a .,;!? boundary. */\n\treadonly negationWindowChars: number;\n\t/** confidence <= this value bands as \"low\" (confidence combines score separation and evidence strength). */\n\treadonly lowConfidenceThreshold: number;\n\t/** confidence >= this value bands as \"high\". */\n\treadonly highConfidenceThreshold: number;\n}\n\n/**\n * Calibrated default preset. The named weights below are the production v4\n * scorer configuration covered by\n * test/suite/regressions/013-reasoning-router-v4-accuracy.test.ts. Extension\n * fields (`multiTurnPrior`, `pressureBucket`, `judgeVote`) are wired but inert\n * until a future calibration changes them.\n */\nexport const DEFAULT_WEIGHTS_V4: RouterWeightsV4 = {\n\tcodeFenceOrDiff: 4,\n\tleadingIntent: 8,\n\tsecondClauseIntent: 4,\n\tlocalEdit: 7,\n\tdiagnosticEvidence: 7,\n\treviewScope: 3,\n\tplanBrief: 8,\n\toperationalRunbook: 8,\n\trefactorCue: 6,\n\timplementationObject: 3,\n\tcodeGenArtifactRequest: 5,\n\tevaluativeReviewObject: 3,\n\tkeywordFamily: {\n\t\ttrivial: 0,\n\t\t\"simple-edit\": 4,\n\t\t\"code-gen\": 4,\n\t\tdebug: 4,\n\t\trefactor: 4,\n\t\treview: 4,\n\t\tplan: 4,\n\t},\n\tnormalizedIntentCluster: 4,\n\tintentSkeleton: 5,\n\taddKeyword: 1,\n\t// Goal 016/L2 calibration (scripts/reasoning-router/calibrate-inert-weights.ts):\n\t// adversarial bounds on the frozen gold set after the topScore>0 vote gate —\n\t// multiTurnPrior/judgeVote flip at 4 (gold-0066), pressureBucket at 2.\n\t// multiTurnPrior=2 / judgeVote=2 sit one step below the bound; pressureBucket=1\n\t// is provably safe because the runtime bucket is hard-clamped to <= 3, so the\n\t// max possible bump (+3) stays under the flip threshold (+6).\n\tmultiTurnPrior: 2,\n\tpressureBucket: 1,\n\tjudgeVote: 2,\n\tnegationWindowChars: 24,\n\tlowConfidenceThreshold: 0.35,\n\thighConfidenceThreshold: 0.7,\n};\n"]}
1
+ {"version":3,"file":"reasoning-router-v4-weights.d.ts","sourceRoot":"","sources":["../../src/core/reasoning-router-v4-weights.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,qCAAqC;AACrC,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE5G,yEAAyE;AACzE,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,UAAU,GAAG,UAAU,GAAG,OAAO,GAAG,UAAU,GAAG,QAAQ,CAAC;AAExG,yIAAyI;AACzI,eAAO,MAAM,eAAe,EAAE,SAAS,WAAW,EAQjD,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC/B,oEAAoE;IACpE,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,+DAA+D;IAC/D,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,6HAA6H;IAC7H,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,kEAAkE;IAClE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,4GAA4G;IAC5G,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;IACpC,uFAAuF;IACvF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,wEAAwE;IACxE,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC;IACtC,6GAA6G;IAC7G,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,kHAAkH;IAClH,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,4EAA4E;IAC5E,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;IAC9D,iGAAiG;IACjG,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;IACzC,wGAAwG;IACxG,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,wEAAwE;IACxE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,2GAA2G;IAC3G,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,8FAA8F;IAC9F,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,wGAAwG;IACxG,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,sGAAsG;IACtG,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,4GAA4G;IAC5G,QAAQ,CAAC,sBAAsB,EAAE,MAAM,CAAC;IACxC,gDAAgD;IAChD,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;CACzC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,eAqChC,CAAC","sourcesContent":["/**\n * Reasoning-router v4 — frozen types and calibratable weight schema.\n *\n * Pure, side-effect-free, erasable TypeScript. No runtime imports. This file\n * owns the closed task/lane unions, named scorer weights, and calibrated default\n * preset used by `/think auto`.\n *\n * `keywordFamily` is the class -> weight table for whole-prompt keyword-family\n * patterns (see reasoning-router-v4.ts). `trivial` carries weight 0 because it\n * is reached only via the zero-score fallback cascade.\n *\n * `secondClauseIntent` applies a bounded bonus when a second, distinct leading\n * verb is found after a short-range conjunction split. `negationWindowChars`\n * bounds negation gating so a nearby \"don't/skip/without/no need\" cue can\n * suppress a whole-prompt signal without crossing a clause boundary.\n *\n * `lowConfidenceThreshold` / `highConfidenceThreshold` bound the confidence\n * bands (`ClassifierVerdictV4.confidenceBand`) computed from score separation\n * plus absolute evidence strength in reasoning-router-v4.ts. They are\n * metadata-only: they never change `taskClass`, only how\n * `resolveThinkingLevelV4WithUncertainty` treats an already-decided class.\n */\n\n/** Closed set of v4 task classes. */\nexport type TaskClassV4 = \"trivial\" | \"simple-edit\" | \"code-gen\" | \"debug\" | \"refactor\" | \"review\" | \"plan\";\n\n/** Subagent lane types recognized by the v4 classifier and resolvers. */\nexport type ReasoningLaneTypeV4 = \"planner\" | \"security\" | \"explorer\" | \"coder\" | \"reviewer\" | \"tester\";\n\n/** Fixed iteration order over TaskClassV4 (matches the type-declaration order; also v4's argmax tie-break precedence, highest first). */\nexport const TASK_CLASSES_V4: readonly TaskClassV4[] = [\n\t\"debug\",\n\t\"refactor\",\n\t\"review\",\n\t\"plan\",\n\t\"simple-edit\",\n\t\"code-gen\",\n\t\"trivial\",\n];\n\n/**\n * Named weight schema for the v4 scorer (reasoning-router-v4.ts). Every field\n * is a plain, deterministic integer/ratio; there is no clock, randomness, or\n * I/O anywhere in this file or its consumer.\n */\nexport interface RouterWeightsV4 {\n\t/** Bump to \"code-gen\" when a code fence or diff hunk is present. */\n\treadonly codeFenceOrDiff: number;\n\t/** Bump to the primary leading-clause intent class, if any. */\n\treadonly leadingIntent: number;\n\t/** Bump to a distinct second-clause intent class in a detected compound prompt (v4-new; default half of `leadingIntent`). */\n\treadonly secondClauseIntent: number;\n\t/** Bump to \"simple-edit\" when the composite local-edit feature fires. */\n\treadonly localEdit: number;\n\t/** Bump to \"debug\" when the composite diagnostic-evidence feature fires. */\n\treadonly diagnosticEvidence: number;\n\t/** Bump to \"review\" when the composite review-scope feature fires. */\n\treadonly reviewScope: number;\n\t/** Bump to \"plan\" when the composite plan-brief feature fires. */\n\treadonly planBrief: number;\n\t/** Bump to \"plan\" for release-bound operational runbooks (commit/push/tag/publish/changelog/CI bundles). */\n\treadonly operationalRunbook: number;\n\t/** Bump to \"refactor\" when the refactor-cue pattern matches anywhere in the prompt. */\n\treadonly refactorCue: number;\n\t/** Bump to \"code-gen\" when an implementation-object noun is present. */\n\treadonly implementationObject: number;\n\t/** Bump to \"code-gen\" when a first-person request names a code artifact (for example, \"I need a script\"). */\n\treadonly codeGenArtifactRequest: number;\n\t/** Bump to \"review\" when a leading review request names an evaluative object such as holes/regressions/issues. */\n\treadonly evaluativeReviewObject: number;\n\t/** Per-class whole-prompt keyword-family bump; trivial has no family, 0. */\n\treadonly keywordFamily: Readonly<Record<TaskClassV4, number>>;\n\t/** Bump to a class when normalized seed->cluster anchors match (medium generalized evidence). */\n\treadonly normalizedIntentCluster: number;\n\t/** Bump to a class when the bounded intent-skeleton extractor matches (medium generalized evidence). */\n\treadonly intentSkeleton: number;\n\t/** Bump to \"code-gen\" for a bare \"add\" keyword, gated by !localEdit. */\n\treadonly addKeyword: number;\n\t/** Bump to the class matching `history[0]`, if supplied (default 2; gated on existing prompt evidence). */\n\treadonly multiTurnPrior: number;\n\t/** Linear per-bucket bump applied to debug/review/plan under context pressure (default 1). */\n\treadonly pressureBucket: number;\n\t/** Bump to an externally supplied judge vote, if any (default 2; gated on existing prompt evidence). */\n\treadonly judgeVote: number;\n\t/** Bounded look-back window (characters) for negation-cue gating, never crossing a .,;!? boundary. */\n\treadonly negationWindowChars: number;\n\t/** confidence <= this value bands as \"low\" (confidence combines score separation and evidence strength). */\n\treadonly lowConfidenceThreshold: number;\n\t/** confidence >= this value bands as \"high\". */\n\treadonly highConfidenceThreshold: number;\n}\n\n/**\n * Calibrated default preset. The named weights below are the production v4\n * scorer configuration covered by\n * test/suite/regressions/013-reasoning-router-v4-accuracy.test.ts. The bounded\n * extension fields (`multiTurnPrior`, `pressureBucket`, `judgeVote`) are active\n * only after the base scorer finds prompt evidence; zero-score fallbacks ignore them.\n */\nexport const DEFAULT_WEIGHTS_V4: RouterWeightsV4 = {\n\tcodeFenceOrDiff: 4,\n\tleadingIntent: 8,\n\tsecondClauseIntent: 4,\n\tlocalEdit: 7,\n\tdiagnosticEvidence: 7,\n\treviewScope: 3,\n\tplanBrief: 8,\n\toperationalRunbook: 8,\n\trefactorCue: 6,\n\timplementationObject: 3,\n\tcodeGenArtifactRequest: 5,\n\tevaluativeReviewObject: 3,\n\tkeywordFamily: {\n\t\ttrivial: 0,\n\t\t\"simple-edit\": 4,\n\t\t\"code-gen\": 4,\n\t\tdebug: 4,\n\t\trefactor: 4,\n\t\treview: 4,\n\t\tplan: 4,\n\t},\n\tnormalizedIntentCluster: 4,\n\tintentSkeleton: 5,\n\taddKeyword: 1,\n\t// Goal 016/L2 calibration (scripts/reasoning-router/calibrate-inert-weights.ts):\n\t// adversarial bounds on the frozen gold set after the topScore>0 vote gate —\n\t// multiTurnPrior/judgeVote flip at 4 (gold-0066), pressureBucket at 2.\n\t// multiTurnPrior=2 / judgeVote=2 sit one step below the bound; pressureBucket=1\n\t// is provably safe because the runtime bucket is hard-clamped to <= 3, so the\n\t// max possible bump (+3) stays under the flip threshold (+6).\n\tmultiTurnPrior: 2,\n\tpressureBucket: 1,\n\tjudgeVote: 2,\n\tnegationWindowChars: 24,\n\tlowConfidenceThreshold: 0.35,\n\thighConfidenceThreshold: 0.7,\n};\n"]}
@@ -33,9 +33,9 @@ export const TASK_CLASSES_V4 = [
33
33
  /**
34
34
  * Calibrated default preset. The named weights below are the production v4
35
35
  * scorer configuration covered by
36
- * test/suite/regressions/013-reasoning-router-v4-accuracy.test.ts. Extension
37
- * fields (`multiTurnPrior`, `pressureBucket`, `judgeVote`) are wired but inert
38
- * until a future calibration changes them.
36
+ * test/suite/regressions/013-reasoning-router-v4-accuracy.test.ts. The bounded
37
+ * extension fields (`multiTurnPrior`, `pressureBucket`, `judgeVote`) are active
38
+ * only after the base scorer finds prompt evidence; zero-score fallbacks ignore them.
39
39
  */
40
40
  export const DEFAULT_WEIGHTS_V4 = {
41
41
  codeFenceOrDiff: 4,
@@ -1 +1 @@
1
- {"version":3,"file":"reasoning-router-v4-weights.js","sourceRoot":"","sources":["../../src/core/reasoning-router-v4-weights.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,yIAAyI;AACzI,MAAM,CAAC,MAAM,eAAe,GAA2B;IACtD,OAAO;IACP,UAAU;IACV,QAAQ;IACR,MAAM;IACN,aAAa;IACb,UAAU;IACV,SAAS;CACT,CAAC;AAsDF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAoB;IAClD,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC;IAChB,kBAAkB,EAAE,CAAC;IACrB,SAAS,EAAE,CAAC;IACZ,kBAAkB,EAAE,CAAC;IACrB,WAAW,EAAE,CAAC;IACd,SAAS,EAAE,CAAC;IACZ,kBAAkB,EAAE,CAAC;IACrB,WAAW,EAAE,CAAC;IACd,oBAAoB,EAAE,CAAC;IACvB,sBAAsB,EAAE,CAAC;IACzB,sBAAsB,EAAE,CAAC;IACzB,aAAa,EAAE;QACd,OAAO,EAAE,CAAC;QACV,aAAa,EAAE,CAAC;QAChB,UAAU,EAAE,CAAC;QACb,KAAK,EAAE,CAAC;QACR,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE,CAAC;QACT,IAAI,EAAE,CAAC;KACP;IACD,uBAAuB,EAAE,CAAC;IAC1B,cAAc,EAAE,CAAC;IACjB,UAAU,EAAE,CAAC;IACb,iFAAiF;IACjF,+EAA6E;IAC7E,uEAAuE;IACvE,gFAAgF;IAChF,8EAA8E;IAC9E,8DAA8D;IAC9D,cAAc,EAAE,CAAC;IACjB,cAAc,EAAE,CAAC;IACjB,SAAS,EAAE,CAAC;IACZ,mBAAmB,EAAE,EAAE;IACvB,sBAAsB,EAAE,IAAI;IAC5B,uBAAuB,EAAE,GAAG;CAC5B,CAAC","sourcesContent":["/**\n * Reasoning-router v4 — frozen types and calibratable weight schema.\n *\n * Pure, side-effect-free, erasable TypeScript. No runtime imports. This file\n * owns the closed task/lane unions, named scorer weights, and calibrated default\n * preset used by `/think auto`.\n *\n * `keywordFamily` is the class -> weight table for whole-prompt keyword-family\n * patterns (see reasoning-router-v4.ts). `trivial` carries weight 0 because it\n * is reached only via the zero-score fallback cascade.\n *\n * `secondClauseIntent` applies a bounded bonus when a second, distinct leading\n * verb is found after a short-range conjunction split. `negationWindowChars`\n * bounds negation gating so a nearby \"don't/skip/without/no need\" cue can\n * suppress a whole-prompt signal without crossing a clause boundary.\n *\n * `lowConfidenceThreshold` / `highConfidenceThreshold` bound the confidence\n * bands (`ClassifierVerdictV4.confidenceBand`) computed from score separation\n * plus absolute evidence strength in reasoning-router-v4.ts. They are\n * metadata-only: they never change `taskClass`, only how\n * `resolveThinkingLevelV4WithUncertainty` treats an already-decided class.\n */\n\n/** Closed set of v4 task classes. */\nexport type TaskClassV4 = \"trivial\" | \"simple-edit\" | \"code-gen\" | \"debug\" | \"refactor\" | \"review\" | \"plan\";\n\n/** Subagent lane types recognized by the v4 classifier and resolvers. */\nexport type ReasoningLaneTypeV4 = \"planner\" | \"security\" | \"explorer\" | \"coder\" | \"reviewer\" | \"tester\";\n\n/** Fixed iteration order over TaskClassV4 (matches the type-declaration order; also v4's argmax tie-break precedence, highest first). */\nexport const TASK_CLASSES_V4: readonly TaskClassV4[] = [\n\t\"debug\",\n\t\"refactor\",\n\t\"review\",\n\t\"plan\",\n\t\"simple-edit\",\n\t\"code-gen\",\n\t\"trivial\",\n];\n\n/**\n * Named weight schema for the v4 scorer (reasoning-router-v4.ts). Every field\n * is a plain, deterministic integer/ratio; there is no clock, randomness, or\n * I/O anywhere in this file or its consumer.\n */\nexport interface RouterWeightsV4 {\n\t/** Bump to \"code-gen\" when a code fence or diff hunk is present. */\n\treadonly codeFenceOrDiff: number;\n\t/** Bump to the primary leading-clause intent class, if any. */\n\treadonly leadingIntent: number;\n\t/** Bump to a distinct second-clause intent class in a detected compound prompt (v4-new; default half of `leadingIntent`). */\n\treadonly secondClauseIntent: number;\n\t/** Bump to \"simple-edit\" when the composite local-edit feature fires. */\n\treadonly localEdit: number;\n\t/** Bump to \"debug\" when the composite diagnostic-evidence feature fires. */\n\treadonly diagnosticEvidence: number;\n\t/** Bump to \"review\" when the composite review-scope feature fires. */\n\treadonly reviewScope: number;\n\t/** Bump to \"plan\" when the composite plan-brief feature fires. */\n\treadonly planBrief: number;\n\t/** Bump to \"plan\" for release-bound operational runbooks (commit/push/tag/publish/changelog/CI bundles). */\n\treadonly operationalRunbook: number;\n\t/** Bump to \"refactor\" when the refactor-cue pattern matches anywhere in the prompt. */\n\treadonly refactorCue: number;\n\t/** Bump to \"code-gen\" when an implementation-object noun is present. */\n\treadonly implementationObject: number;\n\t/** Bump to \"code-gen\" when a first-person request names a code artifact (for example, \"I need a script\"). */\n\treadonly codeGenArtifactRequest: number;\n\t/** Bump to \"review\" when a leading review request names an evaluative object such as holes/regressions/issues. */\n\treadonly evaluativeReviewObject: number;\n\t/** Per-class whole-prompt keyword-family bump; trivial has no family, 0. */\n\treadonly keywordFamily: Readonly<Record<TaskClassV4, number>>;\n\t/** Bump to a class when normalized seed->cluster anchors match (medium generalized evidence). */\n\treadonly normalizedIntentCluster: number;\n\t/** Bump to a class when the bounded intent-skeleton extractor matches (medium generalized evidence). */\n\treadonly intentSkeleton: number;\n\t/** Bump to \"code-gen\" for a bare \"add\" keyword, gated by !localEdit. */\n\treadonly addKeyword: number;\n\t/** Bump to the class matching `history[0]`, if supplied (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */\n\treadonly multiTurnPrior: number;\n\t/** Linear per-bucket bump applied to debug/review/plan under context pressure (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */\n\treadonly pressureBucket: number;\n\t/** Bump to the class matching an externally supplied judge vote, if any (v4-new; 0 under DEFAULT_WEIGHTS_V4, inert until calibrated). */\n\treadonly judgeVote: number;\n\t/** Bounded look-back window (characters) for negation-cue gating, never crossing a .,;!? boundary. */\n\treadonly negationWindowChars: number;\n\t/** confidence <= this value bands as \"low\" (confidence combines score separation and evidence strength). */\n\treadonly lowConfidenceThreshold: number;\n\t/** confidence >= this value bands as \"high\". */\n\treadonly highConfidenceThreshold: number;\n}\n\n/**\n * Calibrated default preset. The named weights below are the production v4\n * scorer configuration covered by\n * test/suite/regressions/013-reasoning-router-v4-accuracy.test.ts. Extension\n * fields (`multiTurnPrior`, `pressureBucket`, `judgeVote`) are wired but inert\n * until a future calibration changes them.\n */\nexport const DEFAULT_WEIGHTS_V4: RouterWeightsV4 = {\n\tcodeFenceOrDiff: 4,\n\tleadingIntent: 8,\n\tsecondClauseIntent: 4,\n\tlocalEdit: 7,\n\tdiagnosticEvidence: 7,\n\treviewScope: 3,\n\tplanBrief: 8,\n\toperationalRunbook: 8,\n\trefactorCue: 6,\n\timplementationObject: 3,\n\tcodeGenArtifactRequest: 5,\n\tevaluativeReviewObject: 3,\n\tkeywordFamily: {\n\t\ttrivial: 0,\n\t\t\"simple-edit\": 4,\n\t\t\"code-gen\": 4,\n\t\tdebug: 4,\n\t\trefactor: 4,\n\t\treview: 4,\n\t\tplan: 4,\n\t},\n\tnormalizedIntentCluster: 4,\n\tintentSkeleton: 5,\n\taddKeyword: 1,\n\t// Goal 016/L2 calibration (scripts/reasoning-router/calibrate-inert-weights.ts):\n\t// adversarial bounds on the frozen gold set after the topScore>0 vote gate —\n\t// multiTurnPrior/judgeVote flip at 4 (gold-0066), pressureBucket at 2.\n\t// multiTurnPrior=2 / judgeVote=2 sit one step below the bound; pressureBucket=1\n\t// is provably safe because the runtime bucket is hard-clamped to <= 3, so the\n\t// max possible bump (+3) stays under the flip threshold (+6).\n\tmultiTurnPrior: 2,\n\tpressureBucket: 1,\n\tjudgeVote: 2,\n\tnegationWindowChars: 24,\n\tlowConfidenceThreshold: 0.35,\n\thighConfidenceThreshold: 0.7,\n};\n"]}
1
+ {"version":3,"file":"reasoning-router-v4-weights.js","sourceRoot":"","sources":["../../src/core/reasoning-router-v4-weights.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAQH,yIAAyI;AACzI,MAAM,CAAC,MAAM,eAAe,GAA2B;IACtD,OAAO;IACP,UAAU;IACV,QAAQ;IACR,MAAM;IACN,aAAa;IACb,UAAU;IACV,SAAS;CACT,CAAC;AAsDF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAoB;IAClD,eAAe,EAAE,CAAC;IAClB,aAAa,EAAE,CAAC;IAChB,kBAAkB,EAAE,CAAC;IACrB,SAAS,EAAE,CAAC;IACZ,kBAAkB,EAAE,CAAC;IACrB,WAAW,EAAE,CAAC;IACd,SAAS,EAAE,CAAC;IACZ,kBAAkB,EAAE,CAAC;IACrB,WAAW,EAAE,CAAC;IACd,oBAAoB,EAAE,CAAC;IACvB,sBAAsB,EAAE,CAAC;IACzB,sBAAsB,EAAE,CAAC;IACzB,aAAa,EAAE;QACd,OAAO,EAAE,CAAC;QACV,aAAa,EAAE,CAAC;QAChB,UAAU,EAAE,CAAC;QACb,KAAK,EAAE,CAAC;QACR,QAAQ,EAAE,CAAC;QACX,MAAM,EAAE,CAAC;QACT,IAAI,EAAE,CAAC;KACP;IACD,uBAAuB,EAAE,CAAC;IAC1B,cAAc,EAAE,CAAC;IACjB,UAAU,EAAE,CAAC;IACb,iFAAiF;IACjF,+EAA6E;IAC7E,uEAAuE;IACvE,gFAAgF;IAChF,8EAA8E;IAC9E,8DAA8D;IAC9D,cAAc,EAAE,CAAC;IACjB,cAAc,EAAE,CAAC;IACjB,SAAS,EAAE,CAAC;IACZ,mBAAmB,EAAE,EAAE;IACvB,sBAAsB,EAAE,IAAI;IAC5B,uBAAuB,EAAE,GAAG;CAC5B,CAAC","sourcesContent":["/**\n * Reasoning-router v4 — frozen types and calibratable weight schema.\n *\n * Pure, side-effect-free, erasable TypeScript. No runtime imports. This file\n * owns the closed task/lane unions, named scorer weights, and calibrated default\n * preset used by `/think auto`.\n *\n * `keywordFamily` is the class -> weight table for whole-prompt keyword-family\n * patterns (see reasoning-router-v4.ts). `trivial` carries weight 0 because it\n * is reached only via the zero-score fallback cascade.\n *\n * `secondClauseIntent` applies a bounded bonus when a second, distinct leading\n * verb is found after a short-range conjunction split. `negationWindowChars`\n * bounds negation gating so a nearby \"don't/skip/without/no need\" cue can\n * suppress a whole-prompt signal without crossing a clause boundary.\n *\n * `lowConfidenceThreshold` / `highConfidenceThreshold` bound the confidence\n * bands (`ClassifierVerdictV4.confidenceBand`) computed from score separation\n * plus absolute evidence strength in reasoning-router-v4.ts. They are\n * metadata-only: they never change `taskClass`, only how\n * `resolveThinkingLevelV4WithUncertainty` treats an already-decided class.\n */\n\n/** Closed set of v4 task classes. */\nexport type TaskClassV4 = \"trivial\" | \"simple-edit\" | \"code-gen\" | \"debug\" | \"refactor\" | \"review\" | \"plan\";\n\n/** Subagent lane types recognized by the v4 classifier and resolvers. */\nexport type ReasoningLaneTypeV4 = \"planner\" | \"security\" | \"explorer\" | \"coder\" | \"reviewer\" | \"tester\";\n\n/** Fixed iteration order over TaskClassV4 (matches the type-declaration order; also v4's argmax tie-break precedence, highest first). */\nexport const TASK_CLASSES_V4: readonly TaskClassV4[] = [\n\t\"debug\",\n\t\"refactor\",\n\t\"review\",\n\t\"plan\",\n\t\"simple-edit\",\n\t\"code-gen\",\n\t\"trivial\",\n];\n\n/**\n * Named weight schema for the v4 scorer (reasoning-router-v4.ts). Every field\n * is a plain, deterministic integer/ratio; there is no clock, randomness, or\n * I/O anywhere in this file or its consumer.\n */\nexport interface RouterWeightsV4 {\n\t/** Bump to \"code-gen\" when a code fence or diff hunk is present. */\n\treadonly codeFenceOrDiff: number;\n\t/** Bump to the primary leading-clause intent class, if any. */\n\treadonly leadingIntent: number;\n\t/** Bump to a distinct second-clause intent class in a detected compound prompt (v4-new; default half of `leadingIntent`). */\n\treadonly secondClauseIntent: number;\n\t/** Bump to \"simple-edit\" when the composite local-edit feature fires. */\n\treadonly localEdit: number;\n\t/** Bump to \"debug\" when the composite diagnostic-evidence feature fires. */\n\treadonly diagnosticEvidence: number;\n\t/** Bump to \"review\" when the composite review-scope feature fires. */\n\treadonly reviewScope: number;\n\t/** Bump to \"plan\" when the composite plan-brief feature fires. */\n\treadonly planBrief: number;\n\t/** Bump to \"plan\" for release-bound operational runbooks (commit/push/tag/publish/changelog/CI bundles). */\n\treadonly operationalRunbook: number;\n\t/** Bump to \"refactor\" when the refactor-cue pattern matches anywhere in the prompt. */\n\treadonly refactorCue: number;\n\t/** Bump to \"code-gen\" when an implementation-object noun is present. */\n\treadonly implementationObject: number;\n\t/** Bump to \"code-gen\" when a first-person request names a code artifact (for example, \"I need a script\"). */\n\treadonly codeGenArtifactRequest: number;\n\t/** Bump to \"review\" when a leading review request names an evaluative object such as holes/regressions/issues. */\n\treadonly evaluativeReviewObject: number;\n\t/** Per-class whole-prompt keyword-family bump; trivial has no family, 0. */\n\treadonly keywordFamily: Readonly<Record<TaskClassV4, number>>;\n\t/** Bump to a class when normalized seed->cluster anchors match (medium generalized evidence). */\n\treadonly normalizedIntentCluster: number;\n\t/** Bump to a class when the bounded intent-skeleton extractor matches (medium generalized evidence). */\n\treadonly intentSkeleton: number;\n\t/** Bump to \"code-gen\" for a bare \"add\" keyword, gated by !localEdit. */\n\treadonly addKeyword: number;\n\t/** Bump to the class matching `history[0]`, if supplied (default 2; gated on existing prompt evidence). */\n\treadonly multiTurnPrior: number;\n\t/** Linear per-bucket bump applied to debug/review/plan under context pressure (default 1). */\n\treadonly pressureBucket: number;\n\t/** Bump to an externally supplied judge vote, if any (default 2; gated on existing prompt evidence). */\n\treadonly judgeVote: number;\n\t/** Bounded look-back window (characters) for negation-cue gating, never crossing a .,;!? boundary. */\n\treadonly negationWindowChars: number;\n\t/** confidence <= this value bands as \"low\" (confidence combines score separation and evidence strength). */\n\treadonly lowConfidenceThreshold: number;\n\t/** confidence >= this value bands as \"high\". */\n\treadonly highConfidenceThreshold: number;\n}\n\n/**\n * Calibrated default preset. The named weights below are the production v4\n * scorer configuration covered by\n * test/suite/regressions/013-reasoning-router-v4-accuracy.test.ts. The bounded\n * extension fields (`multiTurnPrior`, `pressureBucket`, `judgeVote`) are active\n * only after the base scorer finds prompt evidence; zero-score fallbacks ignore them.\n */\nexport const DEFAULT_WEIGHTS_V4: RouterWeightsV4 = {\n\tcodeFenceOrDiff: 4,\n\tleadingIntent: 8,\n\tsecondClauseIntent: 4,\n\tlocalEdit: 7,\n\tdiagnosticEvidence: 7,\n\treviewScope: 3,\n\tplanBrief: 8,\n\toperationalRunbook: 8,\n\trefactorCue: 6,\n\timplementationObject: 3,\n\tcodeGenArtifactRequest: 5,\n\tevaluativeReviewObject: 3,\n\tkeywordFamily: {\n\t\ttrivial: 0,\n\t\t\"simple-edit\": 4,\n\t\t\"code-gen\": 4,\n\t\tdebug: 4,\n\t\trefactor: 4,\n\t\treview: 4,\n\t\tplan: 4,\n\t},\n\tnormalizedIntentCluster: 4,\n\tintentSkeleton: 5,\n\taddKeyword: 1,\n\t// Goal 016/L2 calibration (scripts/reasoning-router/calibrate-inert-weights.ts):\n\t// adversarial bounds on the frozen gold set after the topScore>0 vote gate —\n\t// multiTurnPrior/judgeVote flip at 4 (gold-0066), pressureBucket at 2.\n\t// multiTurnPrior=2 / judgeVote=2 sit one step below the bound; pressureBucket=1\n\t// is provably safe because the runtime bucket is hard-clamped to <= 3, so the\n\t// max possible bump (+3) stays under the flip threshold (+6).\n\tmultiTurnPrior: 2,\n\tpressureBucket: 1,\n\tjudgeVote: 2,\n\tnegationWindowChars: 24,\n\tlowConfidenceThreshold: 0.35,\n\thighConfidenceThreshold: 0.7,\n};\n"]}