@caupulican/pi-adaptative 0.80.86 → 0.80.88

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 (337) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/dist/core/agent-session.d.ts +377 -1
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +1791 -41
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/autonomy/approval-gate.d.ts +4 -0
  7. package/dist/core/autonomy/approval-gate.d.ts.map +1 -0
  8. package/dist/core/autonomy/approval-gate.js +27 -0
  9. package/dist/core/autonomy/approval-gate.js.map +1 -0
  10. package/dist/core/autonomy/bounded-completion.d.ts +27 -0
  11. package/dist/core/autonomy/bounded-completion.d.ts.map +1 -0
  12. package/dist/core/autonomy/bounded-completion.js +44 -0
  13. package/dist/core/autonomy/bounded-completion.js.map +1 -0
  14. package/dist/core/autonomy/contracts.d.ts +129 -0
  15. package/dist/core/autonomy/contracts.d.ts.map +1 -0
  16. package/dist/core/autonomy/contracts.js +2 -0
  17. package/dist/core/autonomy/contracts.js.map +1 -0
  18. package/dist/core/autonomy/gates.d.ts +15 -0
  19. package/dist/core/autonomy/gates.d.ts.map +1 -0
  20. package/dist/core/autonomy/gates.js +205 -0
  21. package/dist/core/autonomy/gates.js.map +1 -0
  22. package/dist/core/autonomy/lane-tracker.d.ts +48 -0
  23. package/dist/core/autonomy/lane-tracker.d.ts.map +1 -0
  24. package/dist/core/autonomy/lane-tracker.js +125 -0
  25. package/dist/core/autonomy/lane-tracker.js.map +1 -0
  26. package/dist/core/autonomy/path-scope.d.ts +9 -0
  27. package/dist/core/autonomy/path-scope.d.ts.map +1 -0
  28. package/dist/core/autonomy/path-scope.js +122 -0
  29. package/dist/core/autonomy/path-scope.js.map +1 -0
  30. package/dist/core/autonomy/risk-assessment.d.ts +3 -0
  31. package/dist/core/autonomy/risk-assessment.d.ts.map +1 -0
  32. package/dist/core/autonomy/risk-assessment.js +122 -0
  33. package/dist/core/autonomy/risk-assessment.js.map +1 -0
  34. package/dist/core/autonomy/session-lane-record.d.ts +10 -0
  35. package/dist/core/autonomy/session-lane-record.d.ts.map +1 -0
  36. package/dist/core/autonomy/session-lane-record.js +36 -0
  37. package/dist/core/autonomy/session-lane-record.js.map +1 -0
  38. package/dist/core/autonomy/status.d.ts +40 -0
  39. package/dist/core/autonomy/status.d.ts.map +1 -0
  40. package/dist/core/autonomy/status.js +107 -0
  41. package/dist/core/autonomy/status.js.map +1 -0
  42. package/dist/core/autonomy/subagent-prompt.d.ts +21 -0
  43. package/dist/core/autonomy/subagent-prompt.d.ts.map +1 -0
  44. package/dist/core/autonomy/subagent-prompt.js +28 -0
  45. package/dist/core/autonomy/subagent-prompt.js.map +1 -0
  46. package/dist/core/autonomy/telemetry-events.d.ts +18 -0
  47. package/dist/core/autonomy/telemetry-events.d.ts.map +1 -0
  48. package/dist/core/autonomy/telemetry-events.js +60 -0
  49. package/dist/core/autonomy/telemetry-events.js.map +1 -0
  50. package/dist/core/context/artifact-retrieval.d.ts +49 -0
  51. package/dist/core/context/artifact-retrieval.d.ts.map +1 -0
  52. package/dist/core/context/artifact-retrieval.js +49 -0
  53. package/dist/core/context/artifact-retrieval.js.map +1 -0
  54. package/dist/core/context/context-artifacts.d.ts +94 -0
  55. package/dist/core/context/context-artifacts.d.ts.map +1 -0
  56. package/dist/core/context/context-artifacts.js +307 -0
  57. package/dist/core/context/context-artifacts.js.map +1 -0
  58. package/dist/core/context/context-audit.d.ts +66 -0
  59. package/dist/core/context/context-audit.d.ts.map +1 -0
  60. package/dist/core/context/context-audit.js +173 -0
  61. package/dist/core/context/context-audit.js.map +1 -0
  62. package/dist/core/context/context-item.d.ts +117 -0
  63. package/dist/core/context/context-item.d.ts.map +1 -0
  64. package/dist/core/context/context-item.js +36 -0
  65. package/dist/core/context/context-item.js.map +1 -0
  66. package/dist/core/context/context-prompt-enforcement.d.ts +73 -0
  67. package/dist/core/context/context-prompt-enforcement.d.ts.map +1 -0
  68. package/dist/core/context/context-prompt-enforcement.js +153 -0
  69. package/dist/core/context/context-prompt-enforcement.js.map +1 -0
  70. package/dist/core/context/context-prompt-policy.d.ts +90 -0
  71. package/dist/core/context/context-prompt-policy.d.ts.map +1 -0
  72. package/dist/core/context/context-prompt-policy.js +73 -0
  73. package/dist/core/context/context-prompt-policy.js.map +1 -0
  74. package/dist/core/context/context-retention.d.ts +36 -0
  75. package/dist/core/context/context-retention.d.ts.map +1 -0
  76. package/dist/core/context/context-retention.js +108 -0
  77. package/dist/core/context/context-retention.js.map +1 -0
  78. package/dist/core/context/context-store.d.ts +37 -0
  79. package/dist/core/context/context-store.d.ts.map +1 -0
  80. package/dist/core/context/context-store.js +45 -0
  81. package/dist/core/context/context-store.js.map +1 -0
  82. package/dist/core/context/memory-diagnostics.d.ts +50 -0
  83. package/dist/core/context/memory-diagnostics.d.ts.map +1 -0
  84. package/dist/core/context/memory-diagnostics.js +43 -0
  85. package/dist/core/context/memory-diagnostics.js.map +1 -0
  86. package/dist/core/context/memory-index-store.d.ts +28 -0
  87. package/dist/core/context/memory-index-store.d.ts.map +1 -0
  88. package/dist/core/context/memory-index-store.js +38 -0
  89. package/dist/core/context/memory-index-store.js.map +1 -0
  90. package/dist/core/context/memory-prompt-block.d.ts +34 -0
  91. package/dist/core/context/memory-prompt-block.d.ts.map +1 -0
  92. package/dist/core/context/memory-prompt-block.js +58 -0
  93. package/dist/core/context/memory-prompt-block.js.map +1 -0
  94. package/dist/core/context/memory-provider-contract.d.ts +114 -0
  95. package/dist/core/context/memory-provider-contract.d.ts.map +1 -0
  96. package/dist/core/context/memory-provider-contract.js +121 -0
  97. package/dist/core/context/memory-provider-contract.js.map +1 -0
  98. package/dist/core/context/memory-retrieval.d.ts +27 -0
  99. package/dist/core/context/memory-retrieval.d.ts.map +1 -0
  100. package/dist/core/context/memory-retrieval.js +91 -0
  101. package/dist/core/context/memory-retrieval.js.map +1 -0
  102. package/dist/core/context/okf-memory-provider.d.ts +26 -0
  103. package/dist/core/context/okf-memory-provider.d.ts.map +1 -0
  104. package/dist/core/context/okf-memory-provider.js +154 -0
  105. package/dist/core/context/okf-memory-provider.js.map +1 -0
  106. package/dist/core/context/okf-memory.d.ts +42 -0
  107. package/dist/core/context/okf-memory.d.ts.map +1 -0
  108. package/dist/core/context/okf-memory.js +175 -0
  109. package/dist/core/context/okf-memory.js.map +1 -0
  110. package/dist/core/context/policy-engine.d.ts +66 -0
  111. package/dist/core/context/policy-engine.d.ts.map +1 -0
  112. package/dist/core/context/policy-engine.js +171 -0
  113. package/dist/core/context/policy-engine.js.map +1 -0
  114. package/dist/core/context/policy-types.d.ts +102 -0
  115. package/dist/core/context/policy-types.d.ts.map +1 -0
  116. package/dist/core/context/policy-types.js +7 -0
  117. package/dist/core/context/policy-types.js.map +1 -0
  118. package/dist/core/context/sqlite-runtime-index.d.ts +19 -0
  119. package/dist/core/context/sqlite-runtime-index.d.ts.map +1 -0
  120. package/dist/core/context/sqlite-runtime-index.js +344 -0
  121. package/dist/core/context/sqlite-runtime-index.js.map +1 -0
  122. package/dist/core/context/storage-authority.d.ts +20 -0
  123. package/dist/core/context/storage-authority.d.ts.map +1 -0
  124. package/dist/core/context/storage-authority.js +51 -0
  125. package/dist/core/context/storage-authority.js.map +1 -0
  126. package/dist/core/context/tool-output-packer.d.ts +75 -0
  127. package/dist/core/context/tool-output-packer.d.ts.map +1 -0
  128. package/dist/core/context/tool-output-packer.js +77 -0
  129. package/dist/core/context/tool-output-packer.js.map +1 -0
  130. package/dist/core/cost/session-usage.d.ts +20 -0
  131. package/dist/core/cost/session-usage.d.ts.map +1 -0
  132. package/dist/core/cost/session-usage.js +164 -0
  133. package/dist/core/cost/session-usage.js.map +1 -0
  134. package/dist/core/delegation/session-worker-result.d.ts +10 -0
  135. package/dist/core/delegation/session-worker-result.d.ts.map +1 -0
  136. package/dist/core/delegation/session-worker-result.js +36 -0
  137. package/dist/core/delegation/session-worker-result.js.map +1 -0
  138. package/dist/core/delegation/worker-result.d.ts +9 -0
  139. package/dist/core/delegation/worker-result.d.ts.map +1 -0
  140. package/dist/core/delegation/worker-result.js +152 -0
  141. package/dist/core/delegation/worker-result.js.map +1 -0
  142. package/dist/core/delegation/worker-runner.d.ts +58 -0
  143. package/dist/core/delegation/worker-runner.d.ts.map +1 -0
  144. package/dist/core/delegation/worker-runner.js +188 -0
  145. package/dist/core/delegation/worker-runner.js.map +1 -0
  146. package/dist/core/extensions/builtin.d.ts +5 -1
  147. package/dist/core/extensions/builtin.d.ts.map +1 -1
  148. package/dist/core/extensions/builtin.js +23 -1
  149. package/dist/core/extensions/builtin.js.map +1 -1
  150. package/dist/core/footer-data-provider.d.ts +5 -1
  151. package/dist/core/footer-data-provider.d.ts.map +1 -1
  152. package/dist/core/footer-data-provider.js +13 -0
  153. package/dist/core/footer-data-provider.js.map +1 -1
  154. package/dist/core/goals/goal-continuation-controller.d.ts +22 -0
  155. package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -0
  156. package/dist/core/goals/goal-continuation-controller.js +88 -0
  157. package/dist/core/goals/goal-continuation-controller.js.map +1 -0
  158. package/dist/core/goals/goal-continuation-defaults.d.ts +10 -0
  159. package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -0
  160. package/dist/core/goals/goal-continuation-defaults.js +10 -0
  161. package/dist/core/goals/goal-continuation-defaults.js.map +1 -0
  162. package/dist/core/goals/goal-continuation-prompt.d.ts +18 -0
  163. package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -0
  164. package/dist/core/goals/goal-continuation-prompt.js +141 -0
  165. package/dist/core/goals/goal-continuation-prompt.js.map +1 -0
  166. package/dist/core/goals/goal-runtime-snapshot.d.ts +19 -0
  167. package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -0
  168. package/dist/core/goals/goal-runtime-snapshot.js +23 -0
  169. package/dist/core/goals/goal-runtime-snapshot.js.map +1 -0
  170. package/dist/core/goals/goal-state.d.ts +87 -0
  171. package/dist/core/goals/goal-state.d.ts.map +1 -0
  172. package/dist/core/goals/goal-state.js +259 -0
  173. package/dist/core/goals/goal-state.js.map +1 -0
  174. package/dist/core/goals/goal-tool-core.d.ts +66 -0
  175. package/dist/core/goals/goal-tool-core.d.ts.map +1 -0
  176. package/dist/core/goals/goal-tool-core.js +146 -0
  177. package/dist/core/goals/goal-tool-core.js.map +1 -0
  178. package/dist/core/goals/session-goal-state.d.ts +10 -0
  179. package/dist/core/goals/session-goal-state.d.ts.map +1 -0
  180. package/dist/core/goals/session-goal-state.js +35 -0
  181. package/dist/core/goals/session-goal-state.js.map +1 -0
  182. package/dist/core/learning/learning-audit.d.ts +45 -0
  183. package/dist/core/learning/learning-audit.d.ts.map +1 -0
  184. package/dist/core/learning/learning-audit.js +139 -0
  185. package/dist/core/learning/learning-audit.js.map +1 -0
  186. package/dist/core/learning/learning-gate.d.ts +29 -0
  187. package/dist/core/learning/learning-gate.d.ts.map +1 -0
  188. package/dist/core/learning/learning-gate.js +150 -0
  189. package/dist/core/learning/learning-gate.js.map +1 -0
  190. package/dist/core/learning/session-learning-decision.d.ts +10 -0
  191. package/dist/core/learning/session-learning-decision.d.ts.map +1 -0
  192. package/dist/core/learning/session-learning-decision.js +36 -0
  193. package/dist/core/learning/session-learning-decision.js.map +1 -0
  194. package/dist/core/model-capability.d.ts +41 -0
  195. package/dist/core/model-capability.d.ts.map +1 -0
  196. package/dist/core/model-capability.js +101 -0
  197. package/dist/core/model-capability.js.map +1 -0
  198. package/dist/core/model-router/config-diagnostics.d.ts.map +1 -1
  199. package/dist/core/model-router/config-diagnostics.js +1 -0
  200. package/dist/core/model-router/config-diagnostics.js.map +1 -1
  201. package/dist/core/model-router/intent-classifier.d.ts +2 -0
  202. package/dist/core/model-router/intent-classifier.d.ts.map +1 -1
  203. package/dist/core/model-router/intent-classifier.js +154 -9
  204. package/dist/core/model-router/intent-classifier.js.map +1 -1
  205. package/dist/core/model-router/route-judge.d.ts +54 -0
  206. package/dist/core/model-router/route-judge.d.ts.map +1 -0
  207. package/dist/core/model-router/route-judge.js +128 -0
  208. package/dist/core/model-router/route-judge.js.map +1 -0
  209. package/dist/core/model-router/status.d.ts +4 -1
  210. package/dist/core/model-router/status.d.ts.map +1 -1
  211. package/dist/core/model-router/status.js +30 -6
  212. package/dist/core/model-router/status.js.map +1 -1
  213. package/dist/core/model-router/tool-escalation.d.ts +4 -6
  214. package/dist/core/model-router/tool-escalation.d.ts.map +1 -1
  215. package/dist/core/model-router/tool-escalation.js +1 -1
  216. package/dist/core/model-router/tool-escalation.js.map +1 -1
  217. package/dist/core/models/fitness-store.d.ts +40 -0
  218. package/dist/core/models/fitness-store.d.ts.map +1 -0
  219. package/dist/core/models/fitness-store.js +61 -0
  220. package/dist/core/models/fitness-store.js.map +1 -0
  221. package/dist/core/profile-registry.d.ts.map +1 -1
  222. package/dist/core/profile-registry.js +1 -1
  223. package/dist/core/profile-registry.js.map +1 -1
  224. package/dist/core/prompt-templates.d.ts +2 -0
  225. package/dist/core/prompt-templates.d.ts.map +1 -1
  226. package/dist/core/prompt-templates.js +12 -4
  227. package/dist/core/prompt-templates.js.map +1 -1
  228. package/dist/core/research/automata-provider.d.ts +5 -0
  229. package/dist/core/research/automata-provider.d.ts.map +1 -0
  230. package/dist/core/research/automata-provider.js +15 -0
  231. package/dist/core/research/automata-provider.js.map +1 -0
  232. package/dist/core/research/evidence-bundle.d.ts +10 -0
  233. package/dist/core/research/evidence-bundle.d.ts.map +1 -0
  234. package/dist/core/research/evidence-bundle.js +116 -0
  235. package/dist/core/research/evidence-bundle.js.map +1 -0
  236. package/dist/core/research/model-fitness.d.ts +79 -0
  237. package/dist/core/research/model-fitness.d.ts.map +1 -0
  238. package/dist/core/research/model-fitness.js +257 -0
  239. package/dist/core/research/model-fitness.js.map +1 -0
  240. package/dist/core/research/research-gate.d.ts +11 -0
  241. package/dist/core/research/research-gate.d.ts.map +1 -0
  242. package/dist/core/research/research-gate.js +82 -0
  243. package/dist/core/research/research-gate.js.map +1 -0
  244. package/dist/core/research/research-runner.d.ts +59 -0
  245. package/dist/core/research/research-runner.d.ts.map +1 -0
  246. package/dist/core/research/research-runner.js +155 -0
  247. package/dist/core/research/research-runner.js.map +1 -0
  248. package/dist/core/research/session-evidence-bundle.d.ts +11 -0
  249. package/dist/core/research/session-evidence-bundle.d.ts.map +1 -0
  250. package/dist/core/research/session-evidence-bundle.js +55 -0
  251. package/dist/core/research/session-evidence-bundle.js.map +1 -0
  252. package/dist/core/resource-loader.d.ts.map +1 -1
  253. package/dist/core/resource-loader.js +4 -0
  254. package/dist/core/resource-loader.js.map +1 -1
  255. package/dist/core/settings-manager.d.ts +147 -4
  256. package/dist/core/settings-manager.d.ts.map +1 -1
  257. package/dist/core/settings-manager.js +285 -9
  258. package/dist/core/settings-manager.js.map +1 -1
  259. package/dist/core/skills.d.ts +4 -0
  260. package/dist/core/skills.d.ts.map +1 -1
  261. package/dist/core/skills.js +18 -6
  262. package/dist/core/skills.js.map +1 -1
  263. package/dist/core/slash-commands.d.ts.map +1 -1
  264. package/dist/core/slash-commands.js +4 -0
  265. package/dist/core/slash-commands.js.map +1 -1
  266. package/dist/core/toolkit/script-registry.d.ts +34 -0
  267. package/dist/core/toolkit/script-registry.d.ts.map +1 -0
  268. package/dist/core/toolkit/script-registry.js +71 -0
  269. package/dist/core/toolkit/script-registry.js.map +1 -0
  270. package/dist/core/toolkit/script-runner.d.ts +28 -0
  271. package/dist/core/toolkit/script-runner.d.ts.map +1 -0
  272. package/dist/core/toolkit/script-runner.js +48 -0
  273. package/dist/core/toolkit/script-runner.js.map +1 -0
  274. package/dist/core/tools/artifact-retrieve.d.ts +23 -0
  275. package/dist/core/tools/artifact-retrieve.d.ts.map +1 -0
  276. package/dist/core/tools/artifact-retrieve.js +110 -0
  277. package/dist/core/tools/artifact-retrieve.js.map +1 -0
  278. package/dist/core/tools/delegate.d.ts +32 -0
  279. package/dist/core/tools/delegate.d.ts.map +1 -0
  280. package/dist/core/tools/delegate.js +60 -0
  281. package/dist/core/tools/delegate.js.map +1 -0
  282. package/dist/core/tools/fff-search-backend.d.ts +103 -0
  283. package/dist/core/tools/fff-search-backend.d.ts.map +1 -0
  284. package/dist/core/tools/fff-search-backend.js +151 -0
  285. package/dist/core/tools/fff-search-backend.js.map +1 -0
  286. package/dist/core/tools/find.d.ts +21 -1
  287. package/dist/core/tools/find.d.ts.map +1 -1
  288. package/dist/core/tools/find.js +183 -10
  289. package/dist/core/tools/find.js.map +1 -1
  290. package/dist/core/tools/goal.d.ts +35 -0
  291. package/dist/core/tools/goal.d.ts.map +1 -0
  292. package/dist/core/tools/goal.js +122 -0
  293. package/dist/core/tools/goal.js.map +1 -0
  294. package/dist/core/tools/grep.d.ts +21 -1
  295. package/dist/core/tools/grep.d.ts.map +1 -1
  296. package/dist/core/tools/grep.js +272 -27
  297. package/dist/core/tools/grep.js.map +1 -1
  298. package/dist/core/tools/index.d.ts +4 -1
  299. package/dist/core/tools/index.d.ts.map +1 -1
  300. package/dist/core/tools/index.js +9 -0
  301. package/dist/core/tools/index.js.map +1 -1
  302. package/dist/core/tools/model-fitness.d.ts +30 -0
  303. package/dist/core/tools/model-fitness.d.ts.map +1 -0
  304. package/dist/core/tools/model-fitness.js +38 -0
  305. package/dist/core/tools/model-fitness.js.map +1 -0
  306. package/dist/core/tools/run-toolkit-script.d.ts +24 -0
  307. package/dist/core/tools/run-toolkit-script.d.ts.map +1 -0
  308. package/dist/core/tools/run-toolkit-script.js +103 -0
  309. package/dist/core/tools/run-toolkit-script.js.map +1 -0
  310. package/dist/core/tools/search-router.d.ts +75 -0
  311. package/dist/core/tools/search-router.d.ts.map +1 -0
  312. package/dist/core/tools/search-router.js +85 -0
  313. package/dist/core/tools/search-router.js.map +1 -0
  314. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  315. package/dist/modes/interactive/components/footer.js +18 -16
  316. package/dist/modes/interactive/components/footer.js.map +1 -1
  317. package/dist/modes/interactive/components/settings-selector.d.ts +13 -1
  318. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/settings-selector.js +471 -11
  320. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  321. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  322. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  323. package/dist/modes/interactive/interactive-mode.js +217 -39
  324. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  325. package/dist/utils/tools-manager.d.ts +2 -0
  326. package/dist/utils/tools-manager.d.ts.map +1 -1
  327. package/dist/utils/tools-manager.js +154 -2
  328. package/dist/utils/tools-manager.js.map +1 -1
  329. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  330. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  331. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  332. package/examples/extensions/sandbox/package-lock.json +2 -2
  333. package/examples/extensions/sandbox/package.json +1 -1
  334. package/examples/extensions/with-deps/package-lock.json +2 -2
  335. package/examples/extensions/with-deps/package.json +1 -1
  336. package/npm-shrinkwrap.json +368 -12
  337. package/package.json +5 -4
@@ -0,0 +1,150 @@
1
+ const MAX_DECISION_SUMMARY_LENGTH = 240;
2
+ function boundedDecisionSummary(summary) {
3
+ if (summary.length <= MAX_DECISION_SUMMARY_LENGTH)
4
+ return summary;
5
+ return `${summary.slice(0, MAX_DECISION_SUMMARY_LENGTH - 1)}…`;
6
+ }
7
+ function learningDecision(args) {
8
+ return {
9
+ kind: args.kind,
10
+ reasonCode: args.reasonCode,
11
+ confidence: args.confidence,
12
+ summary: boundedDecisionSummary(args.summary),
13
+ requiresApproval: args.requiresApproval,
14
+ createdAt: args.createdAt,
15
+ };
16
+ }
17
+ export function evaluateLearningDecision(args) {
18
+ const { proposal, confidence, observations, contradictions, settings, now } = args;
19
+ if (!settings.enabled) {
20
+ return learningDecision({
21
+ kind: "no-op",
22
+ reasonCode: "learning_disabled",
23
+ confidence,
24
+ summary: proposal.summary,
25
+ requiresApproval: false,
26
+ createdAt: now,
27
+ });
28
+ }
29
+ if (contradictions > 0) {
30
+ return learningDecision({
31
+ kind: "proposal",
32
+ reasonCode: "contradictions_present",
33
+ confidence,
34
+ summary: proposal.summary,
35
+ requiresApproval: true,
36
+ createdAt: now,
37
+ });
38
+ }
39
+ if (confidence < settings.confidenceThreshold) {
40
+ const hasEvidence = !!(proposal.evidenceIds && proposal.evidenceIds.length > 0);
41
+ return learningDecision({
42
+ kind: hasEvidence ? "proposal" : "no-op",
43
+ reasonCode: "below_confidence_threshold",
44
+ confidence,
45
+ summary: proposal.summary,
46
+ requiresApproval: hasEvidence,
47
+ createdAt: now,
48
+ });
49
+ }
50
+ if (observations < settings.minObservations) {
51
+ return learningDecision({
52
+ kind: "proposal",
53
+ reasonCode: "insufficient_observations",
54
+ confidence,
55
+ summary: proposal.summary,
56
+ requiresApproval: true,
57
+ createdAt: now,
58
+ });
59
+ }
60
+ if (settings.requireEvidence) {
61
+ const hasEvidence = !!(proposal.evidenceIds && proposal.evidenceIds.length > 0);
62
+ if (!hasEvidence) {
63
+ return learningDecision({
64
+ kind: "proposal",
65
+ reasonCode: "missing_evidence",
66
+ confidence,
67
+ summary: proposal.summary,
68
+ requiresApproval: true,
69
+ createdAt: now,
70
+ });
71
+ }
72
+ }
73
+ if (settings.requireRollbackPlan) {
74
+ const hasRollback = proposal.rollbackPlan !== undefined && proposal.rollbackPlan.trim().length > 0;
75
+ if (!hasRollback) {
76
+ return learningDecision({
77
+ kind: "proposal",
78
+ reasonCode: "missing_rollback_plan",
79
+ confidence,
80
+ summary: proposal.summary,
81
+ requiresApproval: true,
82
+ createdAt: now,
83
+ });
84
+ }
85
+ }
86
+ if (!settings.autoApplyEnabled) {
87
+ return learningDecision({
88
+ kind: "proposal",
89
+ reasonCode: "auto_apply_disabled",
90
+ confidence,
91
+ summary: proposal.summary,
92
+ requiresApproval: true,
93
+ createdAt: now,
94
+ });
95
+ }
96
+ const isAllowed = settings.allowedAutoApplyLayers.includes(proposal.layer);
97
+ if (!isAllowed) {
98
+ return learningDecision({
99
+ kind: "proposal",
100
+ reasonCode: "layer_not_allowed_for_auto_apply",
101
+ confidence,
102
+ summary: proposal.summary,
103
+ requiresApproval: true,
104
+ createdAt: now,
105
+ });
106
+ }
107
+ return learningDecision({
108
+ kind: "apply",
109
+ reasonCode: "eligible_auto_apply",
110
+ confidence,
111
+ summary: proposal.summary,
112
+ requiresApproval: false,
113
+ createdAt: now,
114
+ });
115
+ }
116
+ function isPlainRecord(value) {
117
+ if (!value || typeof value !== "object" || Array.isArray(value))
118
+ return false;
119
+ const prototype = Object.getPrototypeOf(value);
120
+ return prototype === Object.prototype || prototype === null;
121
+ }
122
+ export function isLearningDecision(value) {
123
+ if (!isPlainRecord(value))
124
+ return false;
125
+ if (typeof value.kind !== "string" || !["no-op", "proposal", "apply"].includes(value.kind)) {
126
+ return false;
127
+ }
128
+ if (typeof value.reasonCode !== "string")
129
+ return false;
130
+ if (typeof value.confidence !== "number" || !Number.isFinite(value.confidence))
131
+ return false;
132
+ if (typeof value.summary !== "string")
133
+ return false;
134
+ if (typeof value.requiresApproval !== "boolean")
135
+ return false;
136
+ if (value.createdAt !== undefined && typeof value.createdAt !== "string")
137
+ return false;
138
+ return true;
139
+ }
140
+ export function cloneLearningDecisionForStorage(decision) {
141
+ return {
142
+ kind: decision.kind,
143
+ reasonCode: decision.reasonCode,
144
+ confidence: decision.confidence,
145
+ summary: decision.summary,
146
+ requiresApproval: decision.requiresApproval,
147
+ createdAt: decision.createdAt,
148
+ };
149
+ }
150
+ //# sourceMappingURL=learning-gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"learning-gate.js","sourceRoot":"","sources":["../../../src/core/learning/learning-gate.ts"],"names":[],"mappings":"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","sourcesContent":["import type { LearningDecision } from \"../autonomy/contracts.ts\";\n\nexport type DurableChangeLayer =\n\t| \"memory\"\n\t| \"skill\"\n\t| \"prompt\"\n\t| \"extension\"\n\t| \"tool\"\n\t| \"script\"\n\t| \"settings\"\n\t| \"source\";\n\nexport interface DurableChangeProposal {\n\tid: string;\n\tlayer: DurableChangeLayer;\n\tsummary: string;\n\tevidenceIds?: readonly string[];\n\trollbackPlan?: string;\n}\n\nexport interface LearningGateSettings {\n\tenabled: boolean;\n\tautoApplyEnabled: boolean;\n\tconfidenceThreshold: number;\n\tminObservations: number;\n\tallowedAutoApplyLayers: readonly DurableChangeLayer[];\n\trequireRollbackPlan?: boolean;\n\trequireEvidence?: boolean;\n}\n\nconst MAX_DECISION_SUMMARY_LENGTH = 240;\n\nfunction boundedDecisionSummary(summary: string): string {\n\tif (summary.length <= MAX_DECISION_SUMMARY_LENGTH) return summary;\n\treturn `${summary.slice(0, MAX_DECISION_SUMMARY_LENGTH - 1)}…`;\n}\n\nfunction learningDecision(args: {\n\tkind: LearningDecision[\"kind\"];\n\treasonCode: string;\n\tconfidence: number;\n\tsummary: string;\n\trequiresApproval: boolean;\n\tcreatedAt?: string;\n}): LearningDecision {\n\treturn {\n\t\tkind: args.kind,\n\t\treasonCode: args.reasonCode,\n\t\tconfidence: args.confidence,\n\t\tsummary: boundedDecisionSummary(args.summary),\n\t\trequiresApproval: args.requiresApproval,\n\t\tcreatedAt: args.createdAt,\n\t};\n}\n\nexport function evaluateLearningDecision(args: {\n\tproposal: DurableChangeProposal;\n\tconfidence: number;\n\tobservations: number;\n\tcontradictions: number;\n\tsettings: LearningGateSettings;\n\tnow?: string;\n}): LearningDecision {\n\tconst { proposal, confidence, observations, contradictions, settings, now } = args;\n\n\tif (!settings.enabled) {\n\t\treturn learningDecision({\n\t\t\tkind: \"no-op\",\n\t\t\treasonCode: \"learning_disabled\",\n\t\t\tconfidence,\n\t\t\tsummary: proposal.summary,\n\t\t\trequiresApproval: false,\n\t\t\tcreatedAt: now,\n\t\t});\n\t}\n\n\tif (contradictions > 0) {\n\t\treturn learningDecision({\n\t\t\tkind: \"proposal\",\n\t\t\treasonCode: \"contradictions_present\",\n\t\t\tconfidence,\n\t\t\tsummary: proposal.summary,\n\t\t\trequiresApproval: true,\n\t\t\tcreatedAt: now,\n\t\t});\n\t}\n\n\tif (confidence < settings.confidenceThreshold) {\n\t\tconst hasEvidence = !!(proposal.evidenceIds && proposal.evidenceIds.length > 0);\n\t\treturn learningDecision({\n\t\t\tkind: hasEvidence ? \"proposal\" : \"no-op\",\n\t\t\treasonCode: \"below_confidence_threshold\",\n\t\t\tconfidence,\n\t\t\tsummary: proposal.summary,\n\t\t\trequiresApproval: hasEvidence,\n\t\t\tcreatedAt: now,\n\t\t});\n\t}\n\n\tif (observations < settings.minObservations) {\n\t\treturn learningDecision({\n\t\t\tkind: \"proposal\",\n\t\t\treasonCode: \"insufficient_observations\",\n\t\t\tconfidence,\n\t\t\tsummary: proposal.summary,\n\t\t\trequiresApproval: true,\n\t\t\tcreatedAt: now,\n\t\t});\n\t}\n\n\tif (settings.requireEvidence) {\n\t\tconst hasEvidence = !!(proposal.evidenceIds && proposal.evidenceIds.length > 0);\n\t\tif (!hasEvidence) {\n\t\t\treturn learningDecision({\n\t\t\t\tkind: \"proposal\",\n\t\t\t\treasonCode: \"missing_evidence\",\n\t\t\t\tconfidence,\n\t\t\t\tsummary: proposal.summary,\n\t\t\t\trequiresApproval: true,\n\t\t\t\tcreatedAt: now,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (settings.requireRollbackPlan) {\n\t\tconst hasRollback = proposal.rollbackPlan !== undefined && proposal.rollbackPlan.trim().length > 0;\n\t\tif (!hasRollback) {\n\t\t\treturn learningDecision({\n\t\t\t\tkind: \"proposal\",\n\t\t\t\treasonCode: \"missing_rollback_plan\",\n\t\t\t\tconfidence,\n\t\t\t\tsummary: proposal.summary,\n\t\t\t\trequiresApproval: true,\n\t\t\t\tcreatedAt: now,\n\t\t\t});\n\t\t}\n\t}\n\n\tif (!settings.autoApplyEnabled) {\n\t\treturn learningDecision({\n\t\t\tkind: \"proposal\",\n\t\t\treasonCode: \"auto_apply_disabled\",\n\t\t\tconfidence,\n\t\t\tsummary: proposal.summary,\n\t\t\trequiresApproval: true,\n\t\t\tcreatedAt: now,\n\t\t});\n\t}\n\n\tconst isAllowed = settings.allowedAutoApplyLayers.includes(proposal.layer);\n\tif (!isAllowed) {\n\t\treturn learningDecision({\n\t\t\tkind: \"proposal\",\n\t\t\treasonCode: \"layer_not_allowed_for_auto_apply\",\n\t\t\tconfidence,\n\t\t\tsummary: proposal.summary,\n\t\t\trequiresApproval: true,\n\t\t\tcreatedAt: now,\n\t\t});\n\t}\n\n\treturn learningDecision({\n\t\tkind: \"apply\",\n\t\treasonCode: \"eligible_auto_apply\",\n\t\tconfidence,\n\t\tsummary: proposal.summary,\n\t\trequiresApproval: false,\n\t\tcreatedAt: now,\n\t});\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nexport function isLearningDecision(value: unknown): value is LearningDecision {\n\tif (!isPlainRecord(value)) return false;\n\n\tif (typeof value.kind !== \"string\" || ![\"no-op\", \"proposal\", \"apply\"].includes(value.kind)) {\n\t\treturn false;\n\t}\n\n\tif (typeof value.reasonCode !== \"string\") return false;\n\tif (typeof value.confidence !== \"number\" || !Number.isFinite(value.confidence)) return false;\n\tif (typeof value.summary !== \"string\") return false;\n\tif (typeof value.requiresApproval !== \"boolean\") return false;\n\tif (value.createdAt !== undefined && typeof value.createdAt !== \"string\") return false;\n\n\treturn true;\n}\n\nexport function cloneLearningDecisionForStorage(decision: LearningDecision): LearningDecision {\n\treturn {\n\t\tkind: decision.kind,\n\t\treasonCode: decision.reasonCode,\n\t\tconfidence: decision.confidence,\n\t\tsummary: decision.summary,\n\t\trequiresApproval: decision.requiresApproval,\n\t\tcreatedAt: decision.createdAt,\n\t};\n}\n"]}
@@ -0,0 +1,10 @@
1
+ import type { LearningDecision } from "../autonomy/contracts.ts";
2
+ import type { SessionEntry, SessionManager } from "../session-manager.ts";
3
+ export declare const LEARNING_DECISION_CUSTOM_TYPE = "learning_decision";
4
+ export interface LearningDecisionSnapshotPayload {
5
+ version: 1;
6
+ decision: LearningDecision;
7
+ }
8
+ export declare function appendLearningDecisionSnapshot(sessionManager: Pick<SessionManager, "appendCustomEntry">, decision: LearningDecision): string;
9
+ export declare function getLearningDecisionSnapshots(entries: readonly SessionEntry[]): LearningDecision[];
10
+ //# sourceMappingURL=session-learning-decision.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-learning-decision.d.ts","sourceRoot":"","sources":["../../../src/core/learning/session-learning-decision.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AACjE,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAG1E,eAAO,MAAM,6BAA6B,sBAAsB,CAAC;AAEjE,MAAM,WAAW,+BAA+B;IAC/C,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,gBAAgB,CAAC;CAC3B;AAED,wBAAgB,8BAA8B,CAC7C,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,mBAAmB,CAAC,EACzD,QAAQ,EAAE,gBAAgB,GACxB,MAAM,CAMR;AAQD,wBAAgB,4BAA4B,CAAC,OAAO,EAAE,SAAS,YAAY,EAAE,GAAG,gBAAgB,EAAE,CAmBjG","sourcesContent":["import type { LearningDecision } from \"../autonomy/contracts.ts\";\nimport type { SessionEntry, SessionManager } from \"../session-manager.ts\";\nimport { cloneLearningDecisionForStorage, isLearningDecision } from \"./learning-gate.ts\";\n\nexport const LEARNING_DECISION_CUSTOM_TYPE = \"learning_decision\";\n\nexport interface LearningDecisionSnapshotPayload {\n\tversion: 1;\n\tdecision: LearningDecision;\n}\n\nexport function appendLearningDecisionSnapshot(\n\tsessionManager: Pick<SessionManager, \"appendCustomEntry\">,\n\tdecision: LearningDecision,\n): string {\n\tconst payload: LearningDecisionSnapshotPayload = {\n\t\tversion: 1,\n\t\tdecision: cloneLearningDecisionForStorage(decision),\n\t};\n\treturn sessionManager.appendCustomEntry(LEARNING_DECISION_CUSTOM_TYPE, payload);\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nexport function getLearningDecisionSnapshots(entries: readonly SessionEntry[]): LearningDecision[] {\n\tconst results: LearningDecision[] = [];\n\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"custom\" || entry.customType !== LEARNING_DECISION_CUSTOM_TYPE) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst payload = entry.data;\n\t\tif (!isPlainRecord(payload)) continue;\n\t\tif (payload.version !== 1) continue;\n\t\tif (!(\"decision\" in payload)) continue;\n\t\tconst decision = payload.decision;\n\t\tif (isLearningDecision(decision)) {\n\t\t\tresults.push(cloneLearningDecisionForStorage(decision));\n\t\t}\n\t}\n\n\treturn results;\n}\n"]}
@@ -0,0 +1,36 @@
1
+ import { cloneLearningDecisionForStorage, isLearningDecision } from "./learning-gate.js";
2
+ export const LEARNING_DECISION_CUSTOM_TYPE = "learning_decision";
3
+ export function appendLearningDecisionSnapshot(sessionManager, decision) {
4
+ const payload = {
5
+ version: 1,
6
+ decision: cloneLearningDecisionForStorage(decision),
7
+ };
8
+ return sessionManager.appendCustomEntry(LEARNING_DECISION_CUSTOM_TYPE, payload);
9
+ }
10
+ function isPlainRecord(value) {
11
+ if (!value || typeof value !== "object" || Array.isArray(value))
12
+ return false;
13
+ const prototype = Object.getPrototypeOf(value);
14
+ return prototype === Object.prototype || prototype === null;
15
+ }
16
+ export function getLearningDecisionSnapshots(entries) {
17
+ const results = [];
18
+ for (const entry of entries) {
19
+ if (entry.type !== "custom" || entry.customType !== LEARNING_DECISION_CUSTOM_TYPE) {
20
+ continue;
21
+ }
22
+ const payload = entry.data;
23
+ if (!isPlainRecord(payload))
24
+ continue;
25
+ if (payload.version !== 1)
26
+ continue;
27
+ if (!("decision" in payload))
28
+ continue;
29
+ const decision = payload.decision;
30
+ if (isLearningDecision(decision)) {
31
+ results.push(cloneLearningDecisionForStorage(decision));
32
+ }
33
+ }
34
+ return results;
35
+ }
36
+ //# sourceMappingURL=session-learning-decision.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-learning-decision.js","sourceRoot":"","sources":["../../../src/core/learning/session-learning-decision.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,+BAA+B,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAEzF,MAAM,CAAC,MAAM,6BAA6B,GAAG,mBAAmB,CAAC;AAOjE,MAAM,UAAU,8BAA8B,CAC7C,cAAyD,EACzD,QAA0B,EACjB;IACT,MAAM,OAAO,GAAoC;QAChD,OAAO,EAAE,CAAC;QACV,QAAQ,EAAE,+BAA+B,CAAC,QAAQ,CAAC;KACnD,CAAC;IACF,OAAO,cAAc,CAAC,iBAAiB,CAAC,6BAA6B,EAAE,OAAO,CAAC,CAAC;AAAA,CAChF;AAED,SAAS,aAAa,CAAC,KAAc,EAAoC;IACxE,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9E,MAAM,SAAS,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/C,OAAO,SAAS,KAAK,MAAM,CAAC,SAAS,IAAI,SAAS,KAAK,IAAI,CAAC;AAAA,CAC5D;AAED,MAAM,UAAU,4BAA4B,CAAC,OAAgC,EAAsB;IAClG,MAAM,OAAO,GAAuB,EAAE,CAAC;IAEvC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,UAAU,KAAK,6BAA6B,EAAE,CAAC;YACnF,SAAS;QACV,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,CAAC;QAC3B,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YAAE,SAAS;QACtC,IAAI,OAAO,CAAC,OAAO,KAAK,CAAC;YAAE,SAAS;QACpC,IAAI,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC;YAAE,SAAS;QACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,IAAI,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,+BAA+B,CAAC,QAAQ,CAAC,CAAC,CAAC;QACzD,CAAC;IACF,CAAC;IAED,OAAO,OAAO,CAAC;AAAA,CACf","sourcesContent":["import type { LearningDecision } from \"../autonomy/contracts.ts\";\nimport type { SessionEntry, SessionManager } from \"../session-manager.ts\";\nimport { cloneLearningDecisionForStorage, isLearningDecision } from \"./learning-gate.ts\";\n\nexport const LEARNING_DECISION_CUSTOM_TYPE = \"learning_decision\";\n\nexport interface LearningDecisionSnapshotPayload {\n\tversion: 1;\n\tdecision: LearningDecision;\n}\n\nexport function appendLearningDecisionSnapshot(\n\tsessionManager: Pick<SessionManager, \"appendCustomEntry\">,\n\tdecision: LearningDecision,\n): string {\n\tconst payload: LearningDecisionSnapshotPayload = {\n\t\tversion: 1,\n\t\tdecision: cloneLearningDecisionForStorage(decision),\n\t};\n\treturn sessionManager.appendCustomEntry(LEARNING_DECISION_CUSTOM_TYPE, payload);\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n\tif (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n\tconst prototype = Object.getPrototypeOf(value);\n\treturn prototype === Object.prototype || prototype === null;\n}\n\nexport function getLearningDecisionSnapshots(entries: readonly SessionEntry[]): LearningDecision[] {\n\tconst results: LearningDecision[] = [];\n\n\tfor (const entry of entries) {\n\t\tif (entry.type !== \"custom\" || entry.customType !== LEARNING_DECISION_CUSTOM_TYPE) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst payload = entry.data;\n\t\tif (!isPlainRecord(payload)) continue;\n\t\tif (payload.version !== 1) continue;\n\t\tif (!(\"decision\" in payload)) continue;\n\t\tconst decision = payload.decision;\n\t\tif (isLearningDecision(decision)) {\n\t\t\tresults.push(cloneLearningDecisionForStorage(decision));\n\t\t}\n\t}\n\n\treturn results;\n}\n"]}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Model capability auto-detection: derive what the harness may load onto a model FROM the model's
3
+ * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)
4
+ * can still hold a usable chat instead of drowning in tool schemas and background-lane prompts.
5
+ *
6
+ * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero
7
+ * window keeps today's full behavior rather than guessing). Detection can be disabled or forced
8
+ * per class via the `modelCapability.mode` setting.
9
+ */
10
+ export type ModelCapabilityClass = "full" | "lean" | "minimal" | "chat";
11
+ export type ModelCapabilityMode = "auto" | "off" | ModelCapabilityClass;
12
+ export interface ModelCapabilityProfile {
13
+ class: ModelCapabilityClass;
14
+ contextWindow?: number;
15
+ reasonCode: string;
16
+ /** Allow-list; undefined = no allow-list restriction. */
17
+ allowedToolNames?: readonly string[];
18
+ /** Block-list applied after the allow-list; undefined = nothing blocked. */
19
+ blockedToolNames?: readonly string[];
20
+ /** Whether idle background lanes (goal auto-continue, research) may run on this model. */
21
+ backgroundLanesEnabled: boolean;
22
+ /** Output-token cap for lane isolated completions, scaled to the window. */
23
+ laneMaxOutputTokens: number;
24
+ }
25
+ /** Windows at or above this keep the full harness surface. */
26
+ export declare const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32768;
27
+ /** Windows at or above this keep core tools but shed background-autonomy extras. */
28
+ export declare const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16384;
29
+ /** Windows at or above this get the minimal coding set; below is chat-only. */
30
+ export declare const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8192;
31
+ export declare const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[];
32
+ export declare const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[];
33
+ export declare const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[];
34
+ export declare const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;
35
+ export declare function deriveModelCapabilityProfile(args: {
36
+ contextWindow?: number;
37
+ mode?: ModelCapabilityMode;
38
+ }): ModelCapabilityProfile;
39
+ /** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */
40
+ export declare function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[];
41
+ //# sourceMappingURL=model-capability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-capability.d.ts","sourceRoot":"","sources":["../../src/core/model-capability.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,MAAM,oBAAoB,GAAG,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAC;AAExE,MAAM,MAAM,mBAAmB,GAAG,MAAM,GAAG,KAAK,GAAG,oBAAoB,CAAC;AAExE,MAAM,WAAW,sBAAsB;IACtC,KAAK,EAAE,oBAAoB,CAAC;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,0FAA0F;IAC1F,sBAAsB,EAAE,OAAO,CAAC;IAChC,4EAA4E;IAC5E,mBAAmB,EAAE,MAAM,CAAC;CAC5B;AAED,8DAA8D;AAC9D,eAAO,MAAM,iCAAiC,QAAS,CAAC;AACxD,oFAAoF;AACpF,eAAO,MAAM,iCAAiC,QAAS,CAAC;AACxD,+EAA+E;AAC/E,eAAO,MAAM,oCAAoC,OAAQ,CAAC;AAE1D,eAAO,MAAM,mCAAmC,EAAE,SAAS,MAAM,EAAkC,CAAC;AACpG,eAAO,MAAM,sCAAsC,EAAE,SAAS,MAAM,EAOnE,CAAC;AACF,eAAO,MAAM,mCAAmC,EAAE,SAAS,MAAM,EAAO,CAAC;AAEzE,eAAO,MAAM,8BAA8B,OAAO,CAAC;AA0CnD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE;IAClD,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,mBAAmB,CAAC;CAC3B,GAAG,sBAAsB,CA2BzB;AAED,6FAA6F;AAC7F,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,SAAS,MAAM,EAAE,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,EAAE,CAWpH","sourcesContent":["/**\n * Model capability auto-detection: derive what the harness may load onto a model FROM the model's\n * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)\n * can still hold a usable chat instead of drowning in tool schemas and background-lane prompts.\n *\n * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero\n * window keeps today's full behavior rather than guessing). Detection can be disabled or forced\n * per class via the `modelCapability.mode` setting.\n */\n\nexport type ModelCapabilityClass = \"full\" | \"lean\" | \"minimal\" | \"chat\";\n\nexport type ModelCapabilityMode = \"auto\" | \"off\" | ModelCapabilityClass;\n\nexport interface ModelCapabilityProfile {\n\tclass: ModelCapabilityClass;\n\tcontextWindow?: number;\n\treasonCode: string;\n\t/** Allow-list; undefined = no allow-list restriction. */\n\tallowedToolNames?: readonly string[];\n\t/** Block-list applied after the allow-list; undefined = nothing blocked. */\n\tblockedToolNames?: readonly string[];\n\t/** Whether idle background lanes (goal auto-continue, research) may run on this model. */\n\tbackgroundLanesEnabled: boolean;\n\t/** Output-token cap for lane isolated completions, scaled to the window. */\n\tlaneMaxOutputTokens: number;\n}\n\n/** Windows at or above this keep the full harness surface. */\nexport const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;\n/** Windows at or above this keep core tools but shed background-autonomy extras. */\nexport const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;\n/** Windows at or above this get the minimal coding set; below is chat-only. */\nexport const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;\n\nexport const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[] = [\"delegate\", \"context_audit\"];\nexport const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[] = [\n\t\"read\",\n\t\"bash\",\n\t\"edit\",\n\t\"write\",\n\t// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.\n\t\"run_toolkit_script\",\n];\nexport const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[] = [];\n\nexport const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;\nconst MIN_LANE_MAX_OUTPUT_TOKENS = 256;\n\nfunction laneOutputTokensForWindow(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || contextWindow <= 0) return DEFAULT_LANE_MAX_OUTPUT_TOKENS;\n\t// A lane completion may use at most an eighth of the window for output, floored so tiny\n\t// windows still produce something parseable.\n\treturn Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));\n}\n\nfunction profileForClass(\n\tcapabilityClass: ModelCapabilityClass,\n\treasonCode: string,\n\tcontextWindow: number | undefined,\n): ModelCapabilityProfile {\n\tconst base = {\n\t\tclass: capabilityClass,\n\t\treasonCode,\n\t\tbackgroundLanesEnabled: true,\n\t\tlaneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),\n\t\t...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),\n\t};\n\tswitch (capabilityClass) {\n\t\tcase \"full\":\n\t\t\treturn base;\n\t\tcase \"lean\":\n\t\t\treturn { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };\n\t\tcase \"minimal\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t\tcase \"chat\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t}\n}\n\nexport function deriveModelCapabilityProfile(args: {\n\tcontextWindow?: number;\n\tmode?: ModelCapabilityMode;\n}): ModelCapabilityProfile {\n\tconst mode = args.mode ?? \"auto\";\n\tconst contextWindow =\n\t\targs.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0\n\t\t\t? args.contextWindow\n\t\t\t: undefined;\n\tif (mode === \"off\") {\n\t\treturn profileForClass(\"full\", \"detection_disabled\", contextWindow);\n\t}\n\tif (mode !== \"auto\") {\n\t\treturn profileForClass(mode, \"forced_by_setting\", contextWindow);\n\t}\n\n\tif (contextWindow === undefined) {\n\t\t// Metadata missing: defaults, never guesses.\n\t\treturn profileForClass(\"full\", \"unknown_context_window_defaults\", undefined);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"full\", \"large_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {\n\t\treturn profileForClass(\"lean\", \"lean_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"minimal\", \"minimal_context_window\", contextWindow);\n\t}\n\treturn profileForClass(\"chat\", \"chat_only_context_window\", contextWindow);\n}\n\n/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */\nexport function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[] {\n\tlet filtered = [...toolNames];\n\tif (profile.allowedToolNames !== undefined) {\n\t\tconst allowed = new Set(profile.allowedToolNames);\n\t\tfiltered = filtered.filter((name) => allowed.has(name));\n\t}\n\tif (profile.blockedToolNames !== undefined) {\n\t\tconst blocked = new Set(profile.blockedToolNames);\n\t\tfiltered = filtered.filter((name) => !blocked.has(name));\n\t}\n\treturn filtered;\n}\n"]}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * Model capability auto-detection: derive what the harness may load onto a model FROM the model's
3
+ * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)
4
+ * can still hold a usable chat instead of drowning in tool schemas and background-lane prompts.
5
+ *
6
+ * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero
7
+ * window keeps today's full behavior rather than guessing). Detection can be disabled or forced
8
+ * per class via the `modelCapability.mode` setting.
9
+ */
10
+ /** Windows at or above this keep the full harness surface. */
11
+ export const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;
12
+ /** Windows at or above this keep core tools but shed background-autonomy extras. */
13
+ export const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;
14
+ /** Windows at or above this get the minimal coding set; below is chat-only. */
15
+ export const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;
16
+ export const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS = ["delegate", "context_audit"];
17
+ export const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS = [
18
+ "read",
19
+ "bash",
20
+ "edit",
21
+ "write",
22
+ // The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.
23
+ "run_toolkit_script",
24
+ ];
25
+ export const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS = [];
26
+ export const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;
27
+ const MIN_LANE_MAX_OUTPUT_TOKENS = 256;
28
+ function laneOutputTokensForWindow(contextWindow) {
29
+ if (contextWindow === undefined || contextWindow <= 0)
30
+ return DEFAULT_LANE_MAX_OUTPUT_TOKENS;
31
+ // A lane completion may use at most an eighth of the window for output, floored so tiny
32
+ // windows still produce something parseable.
33
+ return Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));
34
+ }
35
+ function profileForClass(capabilityClass, reasonCode, contextWindow) {
36
+ const base = {
37
+ class: capabilityClass,
38
+ reasonCode,
39
+ backgroundLanesEnabled: true,
40
+ laneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),
41
+ ...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),
42
+ };
43
+ switch (capabilityClass) {
44
+ case "full":
45
+ return base;
46
+ case "lean":
47
+ return { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };
48
+ case "minimal":
49
+ return {
50
+ ...base,
51
+ allowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,
52
+ backgroundLanesEnabled: false,
53
+ };
54
+ case "chat":
55
+ return {
56
+ ...base,
57
+ allowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,
58
+ backgroundLanesEnabled: false,
59
+ };
60
+ }
61
+ }
62
+ export function deriveModelCapabilityProfile(args) {
63
+ const mode = args.mode ?? "auto";
64
+ const contextWindow = args.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0
65
+ ? args.contextWindow
66
+ : undefined;
67
+ if (mode === "off") {
68
+ return profileForClass("full", "detection_disabled", contextWindow);
69
+ }
70
+ if (mode !== "auto") {
71
+ return profileForClass(mode, "forced_by_setting", contextWindow);
72
+ }
73
+ if (contextWindow === undefined) {
74
+ // Metadata missing: defaults, never guesses.
75
+ return profileForClass("full", "unknown_context_window_defaults", undefined);
76
+ }
77
+ if (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {
78
+ return profileForClass("full", "large_context_window", contextWindow);
79
+ }
80
+ if (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {
81
+ return profileForClass("lean", "lean_context_window", contextWindow);
82
+ }
83
+ if (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {
84
+ return profileForClass("minimal", "minimal_context_window", contextWindow);
85
+ }
86
+ return profileForClass("chat", "chat_only_context_window", contextWindow);
87
+ }
88
+ /** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */
89
+ export function filterToolNamesForCapability(toolNames, profile) {
90
+ let filtered = [...toolNames];
91
+ if (profile.allowedToolNames !== undefined) {
92
+ const allowed = new Set(profile.allowedToolNames);
93
+ filtered = filtered.filter((name) => allowed.has(name));
94
+ }
95
+ if (profile.blockedToolNames !== undefined) {
96
+ const blocked = new Set(profile.blockedToolNames);
97
+ filtered = filtered.filter((name) => !blocked.has(name));
98
+ }
99
+ return filtered;
100
+ }
101
+ //# sourceMappingURL=model-capability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"model-capability.js","sourceRoot":"","sources":["../../src/core/model-capability.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model capability auto-detection: derive what the harness may load onto a model FROM the model's\n * own metadata (`Model.contextWindow`), so small open models (4k/8k/16k windows, sub-1B params)\n * can still hold a usable chat instead of drowning in tool schemas and background-lane prompts.\n *\n * Derivation is metadata-first; defaults apply only when the metadata is missing (unknown/zero\n * window keeps today's full behavior rather than guessing). Detection can be disabled or forced\n * per class via the `modelCapability.mode` setting.\n */\n\nexport type ModelCapabilityClass = \"full\" | \"lean\" | \"minimal\" | \"chat\";\n\nexport type ModelCapabilityMode = \"auto\" | \"off\" | ModelCapabilityClass;\n\nexport interface ModelCapabilityProfile {\n\tclass: ModelCapabilityClass;\n\tcontextWindow?: number;\n\treasonCode: string;\n\t/** Allow-list; undefined = no allow-list restriction. */\n\tallowedToolNames?: readonly string[];\n\t/** Block-list applied after the allow-list; undefined = nothing blocked. */\n\tblockedToolNames?: readonly string[];\n\t/** Whether idle background lanes (goal auto-continue, research) may run on this model. */\n\tbackgroundLanesEnabled: boolean;\n\t/** Output-token cap for lane isolated completions, scaled to the window. */\n\tlaneMaxOutputTokens: number;\n}\n\n/** Windows at or above this keep the full harness surface. */\nexport const MODEL_CAPABILITY_FULL_MIN_CONTEXT = 32_768;\n/** Windows at or above this keep core tools but shed background-autonomy extras. */\nexport const MODEL_CAPABILITY_LEAN_MIN_CONTEXT = 16_384;\n/** Windows at or above this get the minimal coding set; below is chat-only. */\nexport const MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT = 8_192;\n\nexport const MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS: readonly string[] = [\"delegate\", \"context_audit\"];\nexport const MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS: readonly string[] = [\n\t\"read\",\n\t\"bash\",\n\t\"edit\",\n\t\"write\",\n\t// The executor tool: minimal-class models ARE the daily-ops executors, and its schema is tiny.\n\t\"run_toolkit_script\",\n];\nexport const MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS: readonly string[] = [];\n\nexport const DEFAULT_LANE_MAX_OUTPUT_TOKENS = 2048;\nconst MIN_LANE_MAX_OUTPUT_TOKENS = 256;\n\nfunction laneOutputTokensForWindow(contextWindow: number | undefined): number {\n\tif (contextWindow === undefined || contextWindow <= 0) return DEFAULT_LANE_MAX_OUTPUT_TOKENS;\n\t// A lane completion may use at most an eighth of the window for output, floored so tiny\n\t// windows still produce something parseable.\n\treturn Math.min(DEFAULT_LANE_MAX_OUTPUT_TOKENS, Math.max(MIN_LANE_MAX_OUTPUT_TOKENS, Math.floor(contextWindow / 8)));\n}\n\nfunction profileForClass(\n\tcapabilityClass: ModelCapabilityClass,\n\treasonCode: string,\n\tcontextWindow: number | undefined,\n): ModelCapabilityProfile {\n\tconst base = {\n\t\tclass: capabilityClass,\n\t\treasonCode,\n\t\tbackgroundLanesEnabled: true,\n\t\tlaneMaxOutputTokens: laneOutputTokensForWindow(contextWindow),\n\t\t...(contextWindow !== undefined && contextWindow > 0 ? { contextWindow } : {}),\n\t};\n\tswitch (capabilityClass) {\n\t\tcase \"full\":\n\t\t\treturn base;\n\t\tcase \"lean\":\n\t\t\treturn { ...base, blockedToolNames: MODEL_CAPABILITY_LEAN_BLOCKED_TOOLS };\n\t\tcase \"minimal\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_MINIMAL_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t\tcase \"chat\":\n\t\t\treturn {\n\t\t\t\t...base,\n\t\t\t\tallowedToolNames: MODEL_CAPABILITY_CHAT_ALLOWED_TOOLS,\n\t\t\t\tbackgroundLanesEnabled: false,\n\t\t\t};\n\t}\n}\n\nexport function deriveModelCapabilityProfile(args: {\n\tcontextWindow?: number;\n\tmode?: ModelCapabilityMode;\n}): ModelCapabilityProfile {\n\tconst mode = args.mode ?? \"auto\";\n\tconst contextWindow =\n\t\targs.contextWindow !== undefined && Number.isFinite(args.contextWindow) && args.contextWindow > 0\n\t\t\t? args.contextWindow\n\t\t\t: undefined;\n\tif (mode === \"off\") {\n\t\treturn profileForClass(\"full\", \"detection_disabled\", contextWindow);\n\t}\n\tif (mode !== \"auto\") {\n\t\treturn profileForClass(mode, \"forced_by_setting\", contextWindow);\n\t}\n\n\tif (contextWindow === undefined) {\n\t\t// Metadata missing: defaults, never guesses.\n\t\treturn profileForClass(\"full\", \"unknown_context_window_defaults\", undefined);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_FULL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"full\", \"large_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_LEAN_MIN_CONTEXT) {\n\t\treturn profileForClass(\"lean\", \"lean_context_window\", contextWindow);\n\t}\n\tif (contextWindow >= MODEL_CAPABILITY_MINIMAL_MIN_CONTEXT) {\n\t\treturn profileForClass(\"minimal\", \"minimal_context_window\", contextWindow);\n\t}\n\treturn profileForClass(\"chat\", \"chat_only_context_window\", contextWindow);\n}\n\n/** Apply the profile's allow/block lists to a requested tool-name list, preserving order. */\nexport function filterToolNamesForCapability(toolNames: readonly string[], profile: ModelCapabilityProfile): string[] {\n\tlet filtered = [...toolNames];\n\tif (profile.allowedToolNames !== undefined) {\n\t\tconst allowed = new Set(profile.allowedToolNames);\n\t\tfiltered = filtered.filter((name) => allowed.has(name));\n\t}\n\tif (profile.blockedToolNames !== undefined) {\n\t\tconst blocked = new Set(profile.blockedToolNames);\n\t\tfiltered = filtered.filter((name) => !blocked.has(name));\n\t}\n\treturn filtered;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"config-diagnostics.d.ts","sourceRoot":"","sources":["../../../src/core/model-router/config-diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAyB7D,wBAAgB,mCAAmC,CAClD,QAAQ,EAAE,yBAAyB,EACnC,aAAa,EAAE,aAAa,GAC1B,MAAM,EAAE,CAgBV","sourcesContent":["import type { Model } from \"@caupulican/pi-ai\";\nimport type { ModelRegistry } from \"../model-registry.ts\";\nimport { resolveCliModel } from \"../model-resolver.ts\";\nimport type { ModelRouterStatusSettings } from \"./status.ts\";\n\nfunction formatModel(model: Model<any>): string {\n\treturn `${model.provider}/${model.id}`;\n}\n\nfunction collectModelRouterModelDiagnostics(\n\tlabel: \"cheap model\" | \"expensive model\",\n\tsettingKey: \"modelRouter.cheapModel\" | \"modelRouter.expensiveModel\",\n\tmodelPattern: string | undefined,\n\tmodelRegistry: ModelRegistry,\n): string[] {\n\tif (!modelPattern) {\n\t\treturn [`Model router ${label} is unset; configure ${settingKey} or disable modelRouter.enabled.`];\n\t}\n\tconst resolved = resolveCliModel({ cliModel: modelPattern, modelRegistry });\n\tif (!resolved.model) {\n\t\treturn [`Model router ${label} is unresolved: ${modelPattern}.`];\n\t}\n\tif (!modelRegistry.hasConfiguredAuth(resolved.model)) {\n\t\treturn [`Model router ${label} is missing auth: ${formatModel(resolved.model)}.`];\n\t}\n\treturn [];\n}\n\nexport function collectModelRouterConfigDiagnostics(\n\tsettings: ModelRouterStatusSettings,\n\tmodelRegistry: ModelRegistry,\n): string[] {\n\tif (!settings.enabled) return [];\n\treturn [\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"cheap model\",\n\t\t\t\"modelRouter.cheapModel\",\n\t\t\tsettings.cheapModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"expensive model\",\n\t\t\t\"modelRouter.expensiveModel\",\n\t\t\tsettings.expensiveModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t];\n}\n"]}
1
+ {"version":3,"file":"config-diagnostics.d.ts","sourceRoot":"","sources":["../../../src/core/model-router/config-diagnostics.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAE1D,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,aAAa,CAAC;AAyB7D,wBAAgB,mCAAmC,CAClD,QAAQ,EAAE,yBAAyB,EACnC,aAAa,EAAE,aAAa,GAC1B,MAAM,EAAE,CAsBV","sourcesContent":["import type { Model } from \"@caupulican/pi-ai\";\nimport type { ModelRegistry } from \"../model-registry.ts\";\nimport { resolveCliModel } from \"../model-resolver.ts\";\nimport type { ModelRouterStatusSettings } from \"./status.ts\";\n\nfunction formatModel(model: Model<any>): string {\n\treturn `${model.provider}/${model.id}`;\n}\n\nfunction collectModelRouterModelDiagnostics(\n\tlabel: \"cheap model\" | \"medium model\" | \"expensive model\",\n\tsettingKey: \"modelRouter.cheapModel\" | \"modelRouter.mediumModel\" | \"modelRouter.expensiveModel\",\n\tmodelPattern: string | undefined,\n\tmodelRegistry: ModelRegistry,\n): string[] {\n\tif (!modelPattern) {\n\t\treturn [`Model router ${label} is unset; configure ${settingKey} or disable modelRouter.enabled.`];\n\t}\n\tconst resolved = resolveCliModel({ cliModel: modelPattern, modelRegistry });\n\tif (!resolved.model) {\n\t\treturn [`Model router ${label} is unresolved: ${modelPattern}.`];\n\t}\n\tif (!modelRegistry.hasConfiguredAuth(resolved.model)) {\n\t\treturn [`Model router ${label} is missing auth: ${formatModel(resolved.model)}.`];\n\t}\n\treturn [];\n}\n\nexport function collectModelRouterConfigDiagnostics(\n\tsettings: ModelRouterStatusSettings,\n\tmodelRegistry: ModelRegistry,\n): string[] {\n\tif (!settings.enabled) return [];\n\treturn [\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"cheap model\",\n\t\t\t\"modelRouter.cheapModel\",\n\t\t\tsettings.cheapModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"medium model\",\n\t\t\t\"modelRouter.mediumModel\",\n\t\t\tsettings.mediumModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"expensive model\",\n\t\t\t\"modelRouter.expensiveModel\",\n\t\t\tsettings.expensiveModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t];\n}\n"]}
@@ -20,6 +20,7 @@ export function collectModelRouterConfigDiagnostics(settings, modelRegistry) {
20
20
  return [];
21
21
  return [
22
22
  ...collectModelRouterModelDiagnostics("cheap model", "modelRouter.cheapModel", settings.cheapModel, modelRegistry),
23
+ ...collectModelRouterModelDiagnostics("medium model", "modelRouter.mediumModel", settings.mediumModel, modelRegistry),
23
24
  ...collectModelRouterModelDiagnostics("expensive model", "modelRouter.expensiveModel", settings.expensiveModel, modelRegistry),
24
25
  ];
25
26
  }
@@ -1 +1 @@
1
- {"version":3,"file":"config-diagnostics.js","sourceRoot":"","sources":["../../../src/core/model-router/config-diagnostics.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,SAAS,WAAW,CAAC,KAAiB,EAAU;IAC/C,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;AAAA,CACvC;AAED,SAAS,kCAAkC,CAC1C,KAAwC,EACxC,UAAmE,EACnE,YAAgC,EAChC,aAA4B,EACjB;IACX,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,CAAC,gBAAgB,KAAK,wBAAwB,UAAU,kCAAkC,CAAC,CAAC;IACpG,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC;IAC5E,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,gBAAgB,KAAK,mBAAmB,YAAY,GAAG,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,gBAAgB,KAAK,qBAAqB,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,EAAE,CAAC;AAAA,CACV;AAED,MAAM,UAAU,mCAAmC,CAClD,QAAmC,EACnC,aAA4B,EACjB;IACX,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACjC,OAAO;QACN,GAAG,kCAAkC,CACpC,aAAa,EACb,wBAAwB,EACxB,QAAQ,CAAC,UAAU,EACnB,aAAa,CACb;QACD,GAAG,kCAAkC,CACpC,iBAAiB,EACjB,4BAA4B,EAC5B,QAAQ,CAAC,cAAc,EACvB,aAAa,CACb;KACD,CAAC;AAAA,CACF","sourcesContent":["import type { Model } from \"@caupulican/pi-ai\";\nimport type { ModelRegistry } from \"../model-registry.ts\";\nimport { resolveCliModel } from \"../model-resolver.ts\";\nimport type { ModelRouterStatusSettings } from \"./status.ts\";\n\nfunction formatModel(model: Model<any>): string {\n\treturn `${model.provider}/${model.id}`;\n}\n\nfunction collectModelRouterModelDiagnostics(\n\tlabel: \"cheap model\" | \"expensive model\",\n\tsettingKey: \"modelRouter.cheapModel\" | \"modelRouter.expensiveModel\",\n\tmodelPattern: string | undefined,\n\tmodelRegistry: ModelRegistry,\n): string[] {\n\tif (!modelPattern) {\n\t\treturn [`Model router ${label} is unset; configure ${settingKey} or disable modelRouter.enabled.`];\n\t}\n\tconst resolved = resolveCliModel({ cliModel: modelPattern, modelRegistry });\n\tif (!resolved.model) {\n\t\treturn [`Model router ${label} is unresolved: ${modelPattern}.`];\n\t}\n\tif (!modelRegistry.hasConfiguredAuth(resolved.model)) {\n\t\treturn [`Model router ${label} is missing auth: ${formatModel(resolved.model)}.`];\n\t}\n\treturn [];\n}\n\nexport function collectModelRouterConfigDiagnostics(\n\tsettings: ModelRouterStatusSettings,\n\tmodelRegistry: ModelRegistry,\n): string[] {\n\tif (!settings.enabled) return [];\n\treturn [\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"cheap model\",\n\t\t\t\"modelRouter.cheapModel\",\n\t\t\tsettings.cheapModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"expensive model\",\n\t\t\t\"modelRouter.expensiveModel\",\n\t\t\tsettings.expensiveModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t];\n}\n"]}
1
+ {"version":3,"file":"config-diagnostics.js","sourceRoot":"","sources":["../../../src/core/model-router/config-diagnostics.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAGvD,SAAS,WAAW,CAAC,KAAiB,EAAU;IAC/C,OAAO,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;AAAA,CACvC;AAED,SAAS,kCAAkC,CAC1C,KAAyD,EACzD,UAA+F,EAC/F,YAAgC,EAChC,aAA4B,EACjB;IACX,IAAI,CAAC,YAAY,EAAE,CAAC;QACnB,OAAO,CAAC,gBAAgB,KAAK,wBAAwB,UAAU,kCAAkC,CAAC,CAAC;IACpG,CAAC;IACD,MAAM,QAAQ,GAAG,eAAe,CAAC,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC;IAC5E,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACrB,OAAO,CAAC,gBAAgB,KAAK,mBAAmB,YAAY,GAAG,CAAC,CAAC;IAClE,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,iBAAiB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACtD,OAAO,CAAC,gBAAgB,KAAK,qBAAqB,WAAW,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnF,CAAC;IACD,OAAO,EAAE,CAAC;AAAA,CACV;AAED,MAAM,UAAU,mCAAmC,CAClD,QAAmC,EACnC,aAA4B,EACjB;IACX,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACjC,OAAO;QACN,GAAG,kCAAkC,CACpC,aAAa,EACb,wBAAwB,EACxB,QAAQ,CAAC,UAAU,EACnB,aAAa,CACb;QACD,GAAG,kCAAkC,CACpC,cAAc,EACd,yBAAyB,EACzB,QAAQ,CAAC,WAAW,EACpB,aAAa,CACb;QACD,GAAG,kCAAkC,CACpC,iBAAiB,EACjB,4BAA4B,EAC5B,QAAQ,CAAC,cAAc,EACvB,aAAa,CACb;KACD,CAAC;AAAA,CACF","sourcesContent":["import type { Model } from \"@caupulican/pi-ai\";\nimport type { ModelRegistry } from \"../model-registry.ts\";\nimport { resolveCliModel } from \"../model-resolver.ts\";\nimport type { ModelRouterStatusSettings } from \"./status.ts\";\n\nfunction formatModel(model: Model<any>): string {\n\treturn `${model.provider}/${model.id}`;\n}\n\nfunction collectModelRouterModelDiagnostics(\n\tlabel: \"cheap model\" | \"medium model\" | \"expensive model\",\n\tsettingKey: \"modelRouter.cheapModel\" | \"modelRouter.mediumModel\" | \"modelRouter.expensiveModel\",\n\tmodelPattern: string | undefined,\n\tmodelRegistry: ModelRegistry,\n): string[] {\n\tif (!modelPattern) {\n\t\treturn [`Model router ${label} is unset; configure ${settingKey} or disable modelRouter.enabled.`];\n\t}\n\tconst resolved = resolveCliModel({ cliModel: modelPattern, modelRegistry });\n\tif (!resolved.model) {\n\t\treturn [`Model router ${label} is unresolved: ${modelPattern}.`];\n\t}\n\tif (!modelRegistry.hasConfiguredAuth(resolved.model)) {\n\t\treturn [`Model router ${label} is missing auth: ${formatModel(resolved.model)}.`];\n\t}\n\treturn [];\n}\n\nexport function collectModelRouterConfigDiagnostics(\n\tsettings: ModelRouterStatusSettings,\n\tmodelRegistry: ModelRegistry,\n): string[] {\n\tif (!settings.enabled) return [];\n\treturn [\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"cheap model\",\n\t\t\t\"modelRouter.cheapModel\",\n\t\t\tsettings.cheapModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"medium model\",\n\t\t\t\"modelRouter.mediumModel\",\n\t\t\tsettings.mediumModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t\t...collectModelRouterModelDiagnostics(\n\t\t\t\"expensive model\",\n\t\t\t\"modelRouter.expensiveModel\",\n\t\t\tsettings.expensiveModel,\n\t\t\tmodelRegistry,\n\t\t),\n\t];\n}\n"]}
@@ -1,3 +1,5 @@
1
+ import type { RouteDecision } from "../autonomy/contracts.ts";
1
2
  export type ModelRouterIntent = "research" | "modify";
3
+ export declare function classifyModelRouterRoute(prompt: string): RouteDecision;
2
4
  export declare function classifyModelRouterIntent(prompt: string): ModelRouterIntent;
3
5
  //# sourceMappingURL=intent-classifier.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"intent-classifier.d.ts","sourceRoot":"","sources":["../../../src/core/model-router/intent-classifier.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,QAAQ,CAAC;AAUtD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAK3E","sourcesContent":["export type ModelRouterIntent = \"research\" | \"modify\";\n\nconst MODIFY_INTENT_RE =\n\t/\\b(add|apply|build|change|commit|create|delete|edit|fix|generate|implement|install|modify|patch|refactor|remove|rename|replace|run|test|update|write)\\b|\\b(npm|pnpm|yarn|bun|git|gh|pytest|vitest|tsc|biome)\\b|[;&|]\\s*\\w+/i;\n\nconst EXPLICIT_MODIFY_REQUEST_RE =\n\t/^(?:can you|could you|please|pls|go ahead and|let'?s|i need you to|we need to|you should)\\s+.*\\b(add|apply|build|change|commit|create|delete|edit|fix|generate|implement|install|modify|patch|refactor|remove|rename|replace|run|test|update|write)\\b/i;\n\nconst READ_ONLY_QUESTION_RE = /^(?:how|what|why|when|where|which|who|explain|summarize|compare|describe|list|show)\\b/i;\n\nexport function classifyModelRouterIntent(prompt: string): ModelRouterIntent {\n\tconst text = prompt.trim();\n\tif (EXPLICIT_MODIFY_REQUEST_RE.test(text)) return \"modify\";\n\tif (READ_ONLY_QUESTION_RE.test(text)) return \"research\";\n\treturn MODIFY_INTENT_RE.test(text) ? \"modify\" : \"research\";\n}\n"]}
1
+ {"version":3,"file":"intent-classifier.d.ts","sourceRoot":"","sources":["../../../src/core/model-router/intent-classifier.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,MAAM,MAAM,iBAAiB,GAAG,UAAU,GAAG,QAAQ,CAAC;AAiCtD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,CA0ItE;AAED,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAG3E","sourcesContent":["import type { RouteDecision } from \"../autonomy/contracts.ts\";\n\nexport type ModelRouterIntent = \"research\" | \"modify\";\n\nconst EXPLICIT_MODIFY_REQUEST_RE =\n\t/^(?:can you|could you|please|pls|go ahead and|let'?s|i need you to|we need to|you should)\\s+.*\\b(add|apply|build|change|commit|create|delete|edit|fix|generate|implement|install|modify|patch|refactor|remove|rename|replace|run|test|update|write|publish|release|push|deploy|tag|reset|clean|rewrite)\\b/i;\n\nconst READ_ONLY_QUESTION_RE =\n\t/^(?:(?:can you|could you|please|pls|go ahead and|let'?s|i need you to|we need to|you should)\\s+)?(?:how|what|why|when|where|which|who|explain|summarize|compare|describe|list|show|search|find|view|read|locate)\\b/i;\n\nconst RELEASE_PUBLISH_RE = /\\b(publish|release|push|deploy|tag)\\b/i;\nconst SECURITY_AUTH_RE = /\\b(auth|token|credential|credentials|secret|api[-_]key)\\b/i;\nconst DESTRUCTIVE_RE = /\\b(delete|reset|rm\\s+-rf|clean)\\b/i;\n\nconst SELF_MOD_MUTATE_RE =\n\t/\\b(modify|change|write|update|edit|delete|add|remove)\\s+.*\\b(skills|prompts|settings|tools|behavior)\\b|self[-_]modification/i;\nconst ARCHITECTURE_MUTATE_RE = /\\b(rewrite|redesign|change|modify|rearchitect)\\s+.*\\b(architecture|architect)\\b/i;\n\n// Planning floor: plans steer all downstream work, so planning never routes cheap by default.\n// Only the route judge may downgrade a planning prompt back to cheap (explicit trivial verdict).\n// Core terms are always planning; design/architecture words count only with prospective phrasing,\n// so lookups like \"show me the architecture\" stay cheap.\nconst PLANNING_CORE_RE = /\\b(plan|planning|roadmap|strategy)\\b/i;\nconst PLANNING_DESIGN_WORD_RE = /\\b(design|architect\\w*|structure|approach)\\b/i;\nconst PLANNING_PROSPECTIVE_RE =\n\t/\\b(how (?:should|would|do we|can we)|what(?:'s| is) the best|propose|draft|come up with|figure out|decide (?:on|how))\\b/i;\n\nfunction isPlanningPrompt(text: string): boolean {\n\treturn PLANNING_CORE_RE.test(text) || (PLANNING_DESIGN_WORD_RE.test(text) && PLANNING_PROSPECTIVE_RE.test(text));\n}\n\nconst REFACTOR_RE = /\\b(refactor|refactoring)\\b/i;\nconst TEST_VALIDATION_RE = /\\b(test|testing|validation|lint|vitest|jest|run)\\b/i;\nconst IMPLEMENT_RE = /\\b(implement|fix|apply|change|update|create|write|generate|modify|edit|patch|add)\\b/i;\n\nexport function classifyModelRouterRoute(prompt: string): RouteDecision {\n\tconst text = prompt.trim();\n\n\tif (text.length === 0) {\n\t\treturn {\n\t\t\ttier: \"cheap\",\n\t\t\trisk: \"read-only\",\n\t\t\tconfidence: 0.1,\n\t\t\treasonCode: \"empty_prompt\",\n\t\t\treasons: [\"Empty or whitespace prompt\"],\n\t\t};\n\t}\n\n\t// 1. Explicit read-only questions/lookups dominate (unless prefixed by explicit mutation verb).\n\t// Planning-shaped questions are the exception: a plan steers expensive downstream work, so the\n\t// floor is medium even when phrased as a question.\n\tif (READ_ONLY_QUESTION_RE.test(text) && !EXPLICIT_MODIFY_REQUEST_RE.test(text)) {\n\t\tif (isPlanningPrompt(text)) {\n\t\t\treturn {\n\t\t\t\ttier: \"medium\",\n\t\t\t\trisk: \"read-only\",\n\t\t\t\tconfidence: 0.75,\n\t\t\t\treasonCode: \"planning_min_medium\",\n\t\t\t\treasons: [\"Planning/design prompts never route cheap by default; a judge may deem them trivial\"],\n\t\t\t};\n\t\t}\n\t\treturn {\n\t\t\ttier: \"cheap\",\n\t\t\trisk: \"read-only\",\n\t\t\tconfidence: 0.9,\n\t\t\treasonCode: \"read_only_question\",\n\t\t\treasons: [\"Prompt asks a question or requests an explanation, search, or lookup\"],\n\t\t};\n\t}\n\n\t// Helper function to match patterns and return appropriate decision\n\tfunction matchKeywords(input: string): RouteDecision | null {\n\t\t// A. High-risk / approval-required/expensive signals\n\t\tif (RELEASE_PUBLISH_RE.test(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"expensive\",\n\t\t\t\trisk: \"approval-required\",\n\t\t\t\tconfidence: 0.9,\n\t\t\t\treasonCode: \"release_or_publish\",\n\t\t\t\treasons: [\"Prompt mentions publishing, releasing, pushing, or deploying\"],\n\t\t\t};\n\t\t}\n\t\tif (SECURITY_AUTH_RE.test(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"expensive\",\n\t\t\t\trisk: \"high-impact\",\n\t\t\t\tconfidence: 0.95,\n\t\t\t\treasonCode: \"security_or_auth\",\n\t\t\t\treasons: [\"Prompt mentions credentials, authentication, tokens, or secrets\"],\n\t\t\t};\n\t\t}\n\t\tif (DESTRUCTIVE_RE.test(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"expensive\",\n\t\t\t\trisk: \"approval-required\",\n\t\t\t\tconfidence: 0.85,\n\t\t\t\treasonCode: \"destructive_or_git_history\",\n\t\t\t\treasons: [\"Prompt mentions deleting, resetting, cleaning, or destructive operations\"],\n\t\t\t};\n\t\t}\n\t\tif (SELF_MOD_MUTATE_RE.test(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"expensive\",\n\t\t\t\trisk: \"approval-required\",\n\t\t\t\tconfidence: 0.9,\n\t\t\t\treasonCode: \"settings_or_self_modification\",\n\t\t\t\treasons: [\"Prompt mentions modifying skills, prompts, settings, tools, or self-modification\"],\n\t\t\t};\n\t\t}\n\t\tif (ARCHITECTURE_MUTATE_RE.test(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"expensive\",\n\t\t\t\trisk: \"high-impact\",\n\t\t\t\tconfidence: 0.9,\n\t\t\t\treasonCode: \"architecture_or_ambiguous\",\n\t\t\t\treasons: [\"Prompt mentions core architecture or rewrite\"],\n\t\t\t};\n\t\t}\n\n\t\t// B. Explicit implementation/scoped-write signals route medium\n\t\tif (isPlanningPrompt(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"medium\",\n\t\t\t\trisk: \"read-only\",\n\t\t\t\tconfidence: 0.75,\n\t\t\t\treasonCode: \"planning_min_medium\",\n\t\t\t\treasons: [\"Planning/design prompts never route cheap by default; a judge may deem them trivial\"],\n\t\t\t};\n\t\t}\n\t\tif (REFACTOR_RE.test(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"medium\",\n\t\t\t\trisk: \"scoped-write\",\n\t\t\t\tconfidence: 0.8,\n\t\t\t\treasonCode: \"mechanical_refactor\",\n\t\t\t\treasons: [\"Prompt mentions refactoring code structure\"],\n\t\t\t};\n\t\t}\n\t\tif (TEST_VALIDATION_RE.test(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"medium\",\n\t\t\t\trisk: \"scoped-write\",\n\t\t\t\tconfidence: 0.8,\n\t\t\t\treasonCode: \"test_or_validation\",\n\t\t\t\treasons: [\"Prompt mentions testing, validation, or linting\"],\n\t\t\t};\n\t\t}\n\t\tif (IMPLEMENT_RE.test(input)) {\n\t\t\treturn {\n\t\t\t\ttier: \"medium\",\n\t\t\t\trisk: \"scoped-write\",\n\t\t\t\tconfidence: 0.85,\n\t\t\t\treasonCode: \"normal_implementation\",\n\t\t\t\treasons: [\"Prompt mentions implementing, updating, creating, or modifying code\"],\n\t\t\t};\n\t\t}\n\n\t\treturn null;\n\t}\n\n\tconst match = matchKeywords(text);\n\tif (match) {\n\t\treturn match;\n\t}\n\n\t// 4. Default fallbacks\n\treturn {\n\t\ttier: \"cheap\",\n\t\trisk: \"read-only\",\n\t\tconfidence: 0.5,\n\t\treasonCode: \"default_read_only\",\n\t\treasons: [\"No explicit implementation, destructive, or release patterns detected\"],\n\t};\n}\n\nexport function classifyModelRouterIntent(prompt: string): ModelRouterIntent {\n\tconst decision = classifyModelRouterRoute(prompt);\n\treturn decision.tier === \"cheap\" ? \"research\" : \"modify\";\n}\n"]}