agent-nuvira 3.3.12 → 3.3.14

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 (458) hide show
  1. package/README.md +67 -1
  2. package/dist/agents/agents/planner.d.ts.map +1 -1
  3. package/dist/agents/agents/planner.js +9 -0
  4. package/dist/agents/agents/planner.js.map +1 -1
  5. package/dist/agents/agents/reasoner.d.ts.map +1 -1
  6. package/dist/agents/agents/reasoner.js +13 -0
  7. package/dist/agents/agents/reasoner.js.map +1 -1
  8. package/dist/agents/orchestrator.d.ts +31 -0
  9. package/dist/agents/orchestrator.d.ts.map +1 -1
  10. package/dist/agents/orchestrator.js +103 -135
  11. package/dist/agents/orchestrator.js.map +1 -1
  12. package/dist/cli/chat.d.ts +89 -0
  13. package/dist/cli/chat.d.ts.map +1 -1
  14. package/dist/cli/chat.js +798 -39
  15. package/dist/cli/chat.js.map +1 -1
  16. package/dist/cli/cli-program.d.ts.map +1 -1
  17. package/dist/cli/cli-program.js +20 -0
  18. package/dist/cli/cli-program.js.map +1 -1
  19. package/dist/cli/config.d.ts +12 -0
  20. package/dist/cli/config.d.ts.map +1 -1
  21. package/dist/cli/config.js +107 -3
  22. package/dist/cli/config.js.map +1 -1
  23. package/dist/cli/decisions.d.ts +28 -0
  24. package/dist/cli/decisions.d.ts.map +1 -0
  25. package/dist/cli/decisions.js +140 -0
  26. package/dist/cli/decisions.js.map +1 -0
  27. package/dist/cli/doctor.d.ts +6 -0
  28. package/dist/cli/doctor.d.ts.map +1 -1
  29. package/dist/cli/doctor.js +46 -0
  30. package/dist/cli/doctor.js.map +1 -1
  31. package/dist/cli/execute.d.ts.map +1 -1
  32. package/dist/cli/execute.js +6 -0
  33. package/dist/cli/execute.js.map +1 -1
  34. package/dist/cli/failover-runner.d.ts.map +1 -1
  35. package/dist/cli/failover-runner.js +19 -1
  36. package/dist/cli/failover-runner.js.map +1 -1
  37. package/dist/cli/feedback.d.ts.map +1 -1
  38. package/dist/cli/feedback.js +5 -1
  39. package/dist/cli/feedback.js.map +1 -1
  40. package/dist/cli/hooks.d.ts +30 -0
  41. package/dist/cli/hooks.d.ts.map +1 -0
  42. package/dist/cli/hooks.js +224 -0
  43. package/dist/cli/hooks.js.map +1 -0
  44. package/dist/cli/knowledge.d.ts +31 -0
  45. package/dist/cli/knowledge.d.ts.map +1 -0
  46. package/dist/cli/knowledge.js +223 -0
  47. package/dist/cli/knowledge.js.map +1 -0
  48. package/dist/cli/loop-executor.d.ts.map +1 -1
  49. package/dist/cli/loop-executor.js +92 -18
  50. package/dist/cli/loop-executor.js.map +1 -1
  51. package/dist/cli/model.d.ts +20 -0
  52. package/dist/cli/model.d.ts.map +1 -1
  53. package/dist/cli/model.js +294 -14
  54. package/dist/cli/model.js.map +1 -1
  55. package/dist/cli/omniroute-control.d.ts +88 -0
  56. package/dist/cli/omniroute-control.d.ts.map +1 -0
  57. package/dist/cli/omniroute-control.js +179 -0
  58. package/dist/cli/omniroute-control.js.map +1 -0
  59. package/dist/cli/omniroute.d.ts +21 -0
  60. package/dist/cli/omniroute.d.ts.map +1 -0
  61. package/dist/cli/omniroute.js +67 -0
  62. package/dist/cli/omniroute.js.map +1 -0
  63. package/dist/cli/rate.d.ts +78 -0
  64. package/dist/cli/rate.d.ts.map +1 -0
  65. package/dist/cli/rate.js +294 -0
  66. package/dist/cli/rate.js.map +1 -0
  67. package/dist/config/process-env.d.ts.map +1 -1
  68. package/dist/config/process-env.js +10 -0
  69. package/dist/config/process-env.js.map +1 -1
  70. package/dist/config/types.d.ts +8 -0
  71. package/dist/config/types.d.ts.map +1 -1
  72. package/dist/context/history.d.ts +21 -0
  73. package/dist/context/history.d.ts.map +1 -1
  74. package/dist/context/history.js +50 -0
  75. package/dist/context/history.js.map +1 -1
  76. package/dist/enterprise/vault.d.ts.map +1 -1
  77. package/dist/enterprise/vault.js +5 -21
  78. package/dist/enterprise/vault.js.map +1 -1
  79. package/dist/gateway/hook-contract.d.ts +206 -0
  80. package/dist/gateway/hook-contract.d.ts.map +1 -0
  81. package/dist/gateway/hook-contract.js +449 -0
  82. package/dist/gateway/hook-contract.js.map +1 -0
  83. package/dist/gateway/hooks.d.ts.map +1 -1
  84. package/dist/gateway/hooks.js +14 -0
  85. package/dist/gateway/hooks.js.map +1 -1
  86. package/dist/inference/gemini-adapter.d.ts.map +1 -1
  87. package/dist/inference/gemini-adapter.js +4 -0
  88. package/dist/inference/gemini-adapter.js.map +1 -1
  89. package/dist/inference/interface.d.ts +54 -0
  90. package/dist/inference/interface.d.ts.map +1 -1
  91. package/dist/inference/model-id-validation.d.ts +57 -0
  92. package/dist/inference/model-id-validation.d.ts.map +1 -0
  93. package/dist/inference/model-id-validation.js +127 -0
  94. package/dist/inference/model-id-validation.js.map +1 -0
  95. package/dist/inference/native-tools.d.ts +16 -1
  96. package/dist/inference/native-tools.d.ts.map +1 -1
  97. package/dist/inference/native-tools.js +34 -10
  98. package/dist/inference/native-tools.js.map +1 -1
  99. package/dist/inference/openai-compat-adapter.d.ts.map +1 -1
  100. package/dist/inference/openai-compat-adapter.js +12 -1
  101. package/dist/inference/openai-compat-adapter.js.map +1 -1
  102. package/dist/inference/provider-catalog.d.ts +11 -0
  103. package/dist/inference/provider-catalog.d.ts.map +1 -1
  104. package/dist/inference/provider-catalog.js +80 -0
  105. package/dist/inference/provider-catalog.js.map +1 -1
  106. package/dist/inference/route-resolver.d.ts +32 -8
  107. package/dist/inference/route-resolver.d.ts.map +1 -1
  108. package/dist/inference/route-resolver.js +175 -1
  109. package/dist/inference/route-resolver.js.map +1 -1
  110. package/dist/inference/tool-call-utils.d.ts.map +1 -1
  111. package/dist/inference/tool-call-utils.js +10 -8
  112. package/dist/inference/tool-call-utils.js.map +1 -1
  113. package/dist/inference/tools.d.ts +17 -1
  114. package/dist/inference/tools.d.ts.map +1 -1
  115. package/dist/inference/tools.js +69 -19
  116. package/dist/inference/tools.js.map +1 -1
  117. package/dist/learning/acceptance-model.d.ts +247 -0
  118. package/dist/learning/acceptance-model.d.ts.map +1 -0
  119. package/dist/learning/acceptance-model.js +708 -0
  120. package/dist/learning/acceptance-model.js.map +1 -0
  121. package/dist/learning/auto-router.d.ts +121 -24
  122. package/dist/learning/auto-router.d.ts.map +1 -1
  123. package/dist/learning/auto-router.js +374 -96
  124. package/dist/learning/auto-router.js.map +1 -1
  125. package/dist/learning/autonomy-policy.d.ts +12 -16
  126. package/dist/learning/autonomy-policy.d.ts.map +1 -1
  127. package/dist/learning/autonomy-policy.js +50 -48
  128. package/dist/learning/autonomy-policy.js.map +1 -1
  129. package/dist/learning/behavioural-labels.d.ts +86 -0
  130. package/dist/learning/behavioural-labels.d.ts.map +1 -0
  131. package/dist/learning/behavioural-labels.js +166 -0
  132. package/dist/learning/behavioural-labels.js.map +1 -0
  133. package/dist/learning/capability-evidence.d.ts +167 -0
  134. package/dist/learning/capability-evidence.d.ts.map +1 -0
  135. package/dist/learning/capability-evidence.js +210 -0
  136. package/dist/learning/capability-evidence.js.map +1 -0
  137. package/dist/learning/capability-readiness.d.ts +64 -0
  138. package/dist/learning/capability-readiness.d.ts.map +1 -0
  139. package/dist/learning/capability-readiness.js +74 -0
  140. package/dist/learning/capability-readiness.js.map +1 -0
  141. package/dist/learning/capability-types.d.ts +169 -0
  142. package/dist/learning/capability-types.d.ts.map +1 -0
  143. package/dist/learning/capability-types.js +20 -0
  144. package/dist/learning/capability-types.js.map +1 -0
  145. package/dist/learning/catalog-feed.d.ts +89 -0
  146. package/dist/learning/catalog-feed.d.ts.map +1 -0
  147. package/dist/learning/catalog-feed.js +211 -0
  148. package/dist/learning/catalog-feed.js.map +1 -0
  149. package/dist/learning/cli-intent-effects.d.ts +60 -0
  150. package/dist/learning/cli-intent-effects.d.ts.map +1 -0
  151. package/dist/learning/cli-intent-effects.js +153 -0
  152. package/dist/learning/cli-intent-effects.js.map +1 -0
  153. package/dist/learning/command-adaptation.d.ts +41 -0
  154. package/dist/learning/command-adaptation.d.ts.map +1 -0
  155. package/dist/learning/command-adaptation.js +122 -0
  156. package/dist/learning/command-adaptation.js.map +1 -0
  157. package/dist/learning/consent-picture.d.ts +42 -0
  158. package/dist/learning/consent-picture.d.ts.map +1 -0
  159. package/dist/learning/consent-picture.js +53 -0
  160. package/dist/learning/consent-picture.js.map +1 -0
  161. package/dist/learning/context-budget.d.ts +37 -6
  162. package/dist/learning/context-budget.d.ts.map +1 -1
  163. package/dist/learning/context-budget.js +38 -9
  164. package/dist/learning/context-budget.js.map +1 -1
  165. package/dist/learning/decision-log.d.ts +114 -0
  166. package/dist/learning/decision-log.d.ts.map +1 -0
  167. package/dist/learning/decision-log.js +296 -0
  168. package/dist/learning/decision-log.js.map +1 -0
  169. package/dist/learning/deliverable-class.d.ts.map +1 -1
  170. package/dist/learning/deliverable-class.js +19 -0
  171. package/dist/learning/deliverable-class.js.map +1 -1
  172. package/dist/learning/deliverable-corpus.d.ts +117 -0
  173. package/dist/learning/deliverable-corpus.d.ts.map +1 -0
  174. package/dist/learning/deliverable-corpus.js +176 -0
  175. package/dist/learning/deliverable-corpus.js.map +1 -0
  176. package/dist/learning/error-repair.d.ts +45 -2
  177. package/dist/learning/error-repair.d.ts.map +1 -1
  178. package/dist/learning/error-repair.js +95 -0
  179. package/dist/learning/error-repair.js.map +1 -1
  180. package/dist/learning/exhaustion-report.d.ts +136 -0
  181. package/dist/learning/exhaustion-report.d.ts.map +1 -0
  182. package/dist/learning/exhaustion-report.js +239 -0
  183. package/dist/learning/exhaustion-report.js.map +1 -0
  184. package/dist/learning/failure-bookkeeping.d.ts +16 -0
  185. package/dist/learning/failure-bookkeeping.d.ts.map +1 -1
  186. package/dist/learning/failure-bookkeeping.js +51 -5
  187. package/dist/learning/failure-bookkeeping.js.map +1 -1
  188. package/dist/learning/gate-friction.d.ts +39 -0
  189. package/dist/learning/gate-friction.d.ts.map +1 -0
  190. package/dist/learning/gate-friction.js +91 -0
  191. package/dist/learning/gate-friction.js.map +1 -0
  192. package/dist/learning/harness-narration.d.ts +34 -0
  193. package/dist/learning/harness-narration.d.ts.map +1 -0
  194. package/dist/learning/harness-narration.js +58 -0
  195. package/dist/learning/harness-narration.js.map +1 -0
  196. package/dist/learning/hub-skill-catalog.d.ts.map +1 -1
  197. package/dist/learning/hub-skill-catalog.js +1 -2
  198. package/dist/learning/hub-skill-catalog.js.map +1 -1
  199. package/dist/learning/hybrid-router.d.ts +65 -0
  200. package/dist/learning/hybrid-router.d.ts.map +1 -1
  201. package/dist/learning/hybrid-router.js +186 -0
  202. package/dist/learning/hybrid-router.js.map +1 -1
  203. package/dist/learning/knowledge-base.d.ts +350 -0
  204. package/dist/learning/knowledge-base.d.ts.map +1 -0
  205. package/dist/learning/knowledge-base.js +906 -0
  206. package/dist/learning/knowledge-base.js.map +1 -0
  207. package/dist/learning/knowledge-eval.d.ts +171 -0
  208. package/dist/learning/knowledge-eval.d.ts.map +1 -0
  209. package/dist/learning/knowledge-eval.js +196 -0
  210. package/dist/learning/knowledge-eval.js.map +1 -0
  211. package/dist/learning/knowledge-turn.d.ts +92 -0
  212. package/dist/learning/knowledge-turn.d.ts.map +1 -0
  213. package/dist/learning/knowledge-turn.js +190 -0
  214. package/dist/learning/knowledge-turn.js.map +1 -0
  215. package/dist/learning/learned-commands.d.ts +64 -0
  216. package/dist/learning/learned-commands.d.ts.map +1 -0
  217. package/dist/learning/learned-commands.js +108 -0
  218. package/dist/learning/learned-commands.js.map +1 -0
  219. package/dist/learning/lexical-search.d.ts +50 -0
  220. package/dist/learning/lexical-search.d.ts.map +1 -0
  221. package/dist/learning/lexical-search.js +111 -0
  222. package/dist/learning/lexical-search.js.map +1 -0
  223. package/dist/learning/machine-facts.d.ts +71 -0
  224. package/dist/learning/machine-facts.d.ts.map +1 -0
  225. package/dist/learning/machine-facts.js +164 -0
  226. package/dist/learning/machine-facts.js.map +1 -0
  227. package/dist/learning/markdown-outline.d.ts +73 -0
  228. package/dist/learning/markdown-outline.d.ts.map +1 -0
  229. package/dist/learning/markdown-outline.js +136 -0
  230. package/dist/learning/markdown-outline.js.map +1 -0
  231. package/dist/learning/model-first-router.d.ts +33 -1
  232. package/dist/learning/model-first-router.d.ts.map +1 -1
  233. package/dist/learning/model-first-router.js +123 -9
  234. package/dist/learning/model-first-router.js.map +1 -1
  235. package/dist/learning/model-identity.d.ts +80 -0
  236. package/dist/learning/model-identity.d.ts.map +1 -0
  237. package/dist/learning/model-identity.js +115 -0
  238. package/dist/learning/model-identity.js.map +1 -0
  239. package/dist/learning/model-registry.d.ts +141 -2
  240. package/dist/learning/model-registry.d.ts.map +1 -1
  241. package/dist/learning/model-registry.js +324 -38
  242. package/dist/learning/model-registry.js.map +1 -1
  243. package/dist/learning/model-scoring.d.ts.map +1 -1
  244. package/dist/learning/model-scoring.js +8 -1
  245. package/dist/learning/model-scoring.js.map +1 -1
  246. package/dist/learning/model-selection.d.ts +2 -1
  247. package/dist/learning/model-selection.d.ts.map +1 -1
  248. package/dist/learning/model-selection.js +76 -2
  249. package/dist/learning/model-selection.js.map +1 -1
  250. package/dist/learning/outcome-observation.d.ts +49 -0
  251. package/dist/learning/outcome-observation.d.ts.map +1 -0
  252. package/dist/learning/outcome-observation.js +95 -0
  253. package/dist/learning/outcome-observation.js.map +1 -0
  254. package/dist/learning/pair-entitlement.d.ts +184 -0
  255. package/dist/learning/pair-entitlement.d.ts.map +1 -0
  256. package/dist/learning/pair-entitlement.js +214 -0
  257. package/dist/learning/pair-entitlement.js.map +1 -0
  258. package/dist/learning/project-docs.d.ts +83 -0
  259. package/dist/learning/project-docs.d.ts.map +1 -0
  260. package/dist/learning/project-docs.js +132 -0
  261. package/dist/learning/project-docs.js.map +1 -0
  262. package/dist/learning/provider-fallback.d.ts +23 -1
  263. package/dist/learning/provider-fallback.d.ts.map +1 -1
  264. package/dist/learning/provider-fallback.js +24 -0
  265. package/dist/learning/provider-fallback.js.map +1 -1
  266. package/dist/learning/quota-ledger.d.ts +13 -0
  267. package/dist/learning/quota-ledger.d.ts.map +1 -1
  268. package/dist/learning/quota-ledger.js +28 -0
  269. package/dist/learning/quota-ledger.js.map +1 -1
  270. package/dist/learning/reasoning-trace.d.ts +65 -1
  271. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  272. package/dist/learning/reasoning-trace.js +123 -1
  273. package/dist/learning/reasoning-trace.js.map +1 -1
  274. package/dist/learning/requirement-probe.d.ts +55 -0
  275. package/dist/learning/requirement-probe.d.ts.map +1 -0
  276. package/dist/learning/requirement-probe.js +77 -0
  277. package/dist/learning/requirement-probe.js.map +1 -0
  278. package/dist/learning/resilient-call.d.ts +20 -1
  279. package/dist/learning/resilient-call.d.ts.map +1 -1
  280. package/dist/learning/resilient-call.js +42 -4
  281. package/dist/learning/resilient-call.js.map +1 -1
  282. package/dist/learning/response-usability.d.ts +85 -0
  283. package/dist/learning/response-usability.d.ts.map +1 -0
  284. package/dist/learning/response-usability.js +135 -0
  285. package/dist/learning/response-usability.js.map +1 -0
  286. package/dist/learning/router-bandit.d.ts +132 -0
  287. package/dist/learning/router-bandit.d.ts.map +1 -1
  288. package/dist/learning/router-bandit.js +253 -0
  289. package/dist/learning/router-bandit.js.map +1 -1
  290. package/dist/learning/routing-history.d.ts +41 -2
  291. package/dist/learning/routing-history.d.ts.map +1 -1
  292. package/dist/learning/routing-history.js.map +1 -1
  293. package/dist/learning/run-trace.d.ts +21 -0
  294. package/dist/learning/run-trace.d.ts.map +1 -1
  295. package/dist/learning/run-trace.js +38 -0
  296. package/dist/learning/run-trace.js.map +1 -1
  297. package/dist/learning/seeded-benchmark.d.ts +14 -0
  298. package/dist/learning/seeded-benchmark.d.ts.map +1 -1
  299. package/dist/learning/seeded-benchmark.js +43 -4
  300. package/dist/learning/seeded-benchmark.js.map +1 -1
  301. package/dist/learning/session-grant.d.ts +75 -0
  302. package/dist/learning/session-grant.d.ts.map +1 -0
  303. package/dist/learning/session-grant.js +112 -0
  304. package/dist/learning/session-grant.js.map +1 -0
  305. package/dist/learning/task-model-continuity.d.ts +73 -0
  306. package/dist/learning/task-model-continuity.d.ts.map +1 -0
  307. package/dist/learning/task-model-continuity.js +87 -0
  308. package/dist/learning/task-model-continuity.js.map +1 -0
  309. package/dist/learning/turn-feedback.d.ts +93 -0
  310. package/dist/learning/turn-feedback.d.ts.map +1 -0
  311. package/dist/learning/turn-feedback.js +127 -0
  312. package/dist/learning/turn-feedback.js.map +1 -0
  313. package/dist/learning/turn-report.d.ts +104 -2
  314. package/dist/learning/turn-report.d.ts.map +1 -1
  315. package/dist/learning/turn-report.js +161 -6
  316. package/dist/learning/turn-report.js.map +1 -1
  317. package/dist/learning/verdict-routing.d.ts +51 -0
  318. package/dist/learning/verdict-routing.d.ts.map +1 -0
  319. package/dist/learning/verdict-routing.js +122 -0
  320. package/dist/learning/verdict-routing.js.map +1 -0
  321. package/dist/mcp/client.d.ts.map +1 -1
  322. package/dist/mcp/client.js +5 -0
  323. package/dist/mcp/client.js.map +1 -1
  324. package/dist/mcp/manager.d.ts +10 -0
  325. package/dist/mcp/manager.d.ts.map +1 -1
  326. package/dist/mcp/manager.js +20 -0
  327. package/dist/mcp/manager.js.map +1 -1
  328. package/dist/mcp/mcp-discovery.d.ts +34 -0
  329. package/dist/mcp/mcp-discovery.d.ts.map +1 -0
  330. package/dist/mcp/mcp-discovery.js +71 -0
  331. package/dist/mcp/mcp-discovery.js.map +1 -0
  332. package/dist/mcp/mcp-schema-cache.d.ts +17 -0
  333. package/dist/mcp/mcp-schema-cache.d.ts.map +1 -1
  334. package/dist/mcp/mcp-schema-cache.js +47 -3
  335. package/dist/mcp/mcp-schema-cache.js.map +1 -1
  336. package/dist/mcp/types.d.ts +28 -0
  337. package/dist/mcp/types.d.ts.map +1 -1
  338. package/dist/mcp/types.js.map +1 -1
  339. package/dist/security/secret-scan.d.ts +156 -0
  340. package/dist/security/secret-scan.d.ts.map +1 -0
  341. package/dist/security/secret-scan.js +525 -0
  342. package/dist/security/secret-scan.js.map +1 -0
  343. package/dist/tools/ask-user.d.ts.map +1 -1
  344. package/dist/tools/ask-user.js +4 -0
  345. package/dist/tools/ask-user.js.map +1 -1
  346. package/dist/tools/capability-registry.d.ts +150 -0
  347. package/dist/tools/capability-registry.d.ts.map +1 -0
  348. package/dist/tools/capability-registry.js +400 -0
  349. package/dist/tools/capability-registry.js.map +1 -0
  350. package/dist/tools/child-agent-runtime.d.ts.map +1 -1
  351. package/dist/tools/child-agent-runtime.js +19 -5
  352. package/dist/tools/child-agent-runtime.js.map +1 -1
  353. package/dist/tools/coding-tools.d.ts +17 -5
  354. package/dist/tools/coding-tools.d.ts.map +1 -1
  355. package/dist/tools/coding-tools.js +80 -11
  356. package/dist/tools/coding-tools.js.map +1 -1
  357. package/dist/tools/command-memo.d.ts +116 -0
  358. package/dist/tools/command-memo.d.ts.map +1 -0
  359. package/dist/tools/command-memo.js +202 -0
  360. package/dist/tools/command-memo.js.map +1 -0
  361. package/dist/tools/git-tool.d.ts.map +1 -1
  362. package/dist/tools/git-tool.js +13 -3
  363. package/dist/tools/git-tool.js.map +1 -1
  364. package/dist/tools/harness-directive.d.ts +42 -0
  365. package/dist/tools/harness-directive.d.ts.map +1 -0
  366. package/dist/tools/harness-directive.js +45 -0
  367. package/dist/tools/harness-directive.js.map +1 -0
  368. package/dist/tools/loop-skill-hint.d.ts +74 -174
  369. package/dist/tools/loop-skill-hint.d.ts.map +1 -1
  370. package/dist/tools/loop-skill-hint.js +110 -536
  371. package/dist/tools/loop-skill-hint.js.map +1 -1
  372. package/dist/tools/mcp-client-tool.d.ts +2 -0
  373. package/dist/tools/mcp-client-tool.d.ts.map +1 -1
  374. package/dist/tools/mcp-client-tool.js +3 -0
  375. package/dist/tools/mcp-client-tool.js.map +1 -1
  376. package/dist/tools/modality/shared.d.ts +1 -4
  377. package/dist/tools/modality/shared.d.ts.map +1 -1
  378. package/dist/tools/modality/shared.js +7 -22
  379. package/dist/tools/modality/shared.js.map +1 -1
  380. package/dist/tools/plan-store.d.ts +44 -4
  381. package/dist/tools/plan-store.d.ts.map +1 -1
  382. package/dist/tools/plan-store.js +93 -9
  383. package/dist/tools/plan-store.js.map +1 -1
  384. package/dist/tools/registry.d.ts +76 -3
  385. package/dist/tools/registry.d.ts.map +1 -1
  386. package/dist/tools/registry.js +623 -15
  387. package/dist/tools/registry.js.map +1 -1
  388. package/dist/tools/remediation-ladder.d.ts +91 -0
  389. package/dist/tools/remediation-ladder.d.ts.map +1 -0
  390. package/dist/tools/remediation-ladder.js +316 -0
  391. package/dist/tools/remediation-ladder.js.map +1 -0
  392. package/dist/tools/run-cli.d.ts.map +1 -1
  393. package/dist/tools/run-cli.js +29 -4
  394. package/dist/tools/run-cli.js.map +1 -1
  395. package/dist/tools/run-terminal.d.ts +11 -0
  396. package/dist/tools/run-terminal.d.ts.map +1 -1
  397. package/dist/tools/run-terminal.js +289 -10
  398. package/dist/tools/run-terminal.js.map +1 -1
  399. package/dist/tools/skills-hub.d.ts +7 -0
  400. package/dist/tools/skills-hub.d.ts.map +1 -1
  401. package/dist/tools/skills-hub.js +11 -2
  402. package/dist/tools/skills-hub.js.map +1 -1
  403. package/dist/tools/step-artifact.d.ts +35 -0
  404. package/dist/tools/step-artifact.d.ts.map +1 -0
  405. package/dist/tools/step-artifact.js +154 -0
  406. package/dist/tools/step-artifact.js.map +1 -0
  407. package/dist/tools/tool-loop.d.ts +327 -13
  408. package/dist/tools/tool-loop.d.ts.map +1 -1
  409. package/dist/tools/tool-loop.js +891 -66
  410. package/dist/tools/tool-loop.js.map +1 -1
  411. package/dist/tools/toolsets.js +4 -4
  412. package/dist/tools/toolsets.js.map +1 -1
  413. package/dist/tools/worktree.d.ts +11 -2
  414. package/dist/tools/worktree.d.ts.map +1 -1
  415. package/dist/tools/worktree.js +11 -2
  416. package/dist/tools/worktree.js.map +1 -1
  417. package/dist/utils/atomic-store.d.ts +53 -0
  418. package/dist/utils/atomic-store.d.ts.map +1 -0
  419. package/dist/utils/atomic-store.js +178 -0
  420. package/dist/utils/atomic-store.js.map +1 -0
  421. package/dist/utils/binary-probe.d.ts +25 -0
  422. package/dist/utils/binary-probe.d.ts.map +1 -0
  423. package/dist/utils/binary-probe.js +48 -0
  424. package/dist/utils/binary-probe.js.map +1 -0
  425. package/dist/utils/workspace-path.d.ts +50 -0
  426. package/dist/utils/workspace-path.d.ts.map +1 -0
  427. package/dist/utils/workspace-path.js +86 -0
  428. package/dist/utils/workspace-path.js.map +1 -0
  429. package/dist/web-dashboard/chat-console.d.ts +24 -0
  430. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  431. package/dist/web-dashboard/chat-console.js +38 -0
  432. package/dist/web-dashboard/chat-console.js.map +1 -1
  433. package/dist/web-dashboard/project-context.d.ts +27 -2
  434. package/dist/web-dashboard/project-context.d.ts.map +1 -1
  435. package/dist/web-dashboard/project-context.js +32 -2
  436. package/dist/web-dashboard/project-context.js.map +1 -1
  437. package/dist/web-dashboard/server.d.ts +40 -0
  438. package/dist/web-dashboard/server.d.ts.map +1 -1
  439. package/dist/web-dashboard/server.js +733 -15
  440. package/dist/web-dashboard/server.js.map +1 -1
  441. package/dist/web-dashboard/src/types.d.ts +236 -1
  442. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  443. package/dist/web-dashboard/workspace-guard.d.ts +18 -2
  444. package/dist/web-dashboard/workspace-guard.d.ts.map +1 -1
  445. package/dist/web-dashboard/workspace-guard.js +94 -12
  446. package/dist/web-dashboard/workspace-guard.js.map +1 -1
  447. package/dist/web-dashboard/workspace-resolution.d.ts +87 -0
  448. package/dist/web-dashboard/workspace-resolution.d.ts.map +1 -0
  449. package/dist/web-dashboard/workspace-resolution.js +105 -0
  450. package/dist/web-dashboard/workspace-resolution.js.map +1 -0
  451. package/package.json +1 -1
  452. package/src/web-dashboard/public/assets/index-tK8Y2qHB.css +1 -0
  453. package/src/web-dashboard/public/assets/index-zjbdJnO-.js +210 -0
  454. package/src/web-dashboard/public/assets/index-zjbdJnO-.js.map +1 -0
  455. package/src/web-dashboard/public/index.html +2 -2
  456. package/src/web-dashboard/public/assets/index-BrZcYhy6.js +0 -207
  457. package/src/web-dashboard/public/assets/index-BrZcYhy6.js.map +0 -1
  458. package/src/web-dashboard/public/assets/index-DsWczTa6.css +0 -1
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Turn outcome → router learning signal.
3
+ *
4
+ * WHY THIS EXISTS. `RouterBandit` has always carried a measured-quality reward model — `testPassed`,
5
+ * `userAccepted`, `verificationPassed`, `qualityScore` — with arms for the provider AND the concrete
6
+ * model, and `applyReward` already folds all four into the reward. But nothing on the real path ever
7
+ * filled it in: `AutoModelRouter.recordOutcome` forwarded `undefined` to every arm, so the reward was
8
+ * a cost-adjusted coin flip on "the agent did not throw". That is the D2 defect one layer down — a
9
+ * response that was empty or useless still counted as a success for the purpose of learning.
10
+ *
11
+ * The harness ALREADY derives the honest signal: `TurnReport.verification` is built from recorded tool
12
+ * and plan evidence and can never be talked up by the model's narration. This module is the single
13
+ * pure translation between that verdict and the learning payload, so the mapping is ONE reviewable
14
+ * decision instead of a payload assembled ad hoc at each call site.
15
+ *
16
+ * WHAT IT DELIBERATELY DOES NOT DO.
17
+ * - It records NOTHING when the report carries no verdict about the model. A plain answer with no
18
+ * plan and no changes is not evidence of quality, and inventing a neutral sample for it would
19
+ * dilute the samples that are real.
20
+ * - It never GUESSES a `qualityScore`. It now carries one — but only from the FITTED
21
+ * acceptance model (`acceptance-model.ts`), which is a measured scale built from the user's own
22
+ * verdicts and which refuses to fit below its sample floor. On a machine with too few ratings the
23
+ * field is absent, exactly as before: a made-up number written into a learning record is worse
24
+ * than a missing one, because the record outlives whoever knows it was fabricated.
25
+ * (`NUVIRA_BANDIT_QUALITY=off` disables it outright.)
26
+ * - It never attributes an environmental failure to the model: a `blocked` turn is a wall the run hit,
27
+ * not a capability verdict.
28
+ */
29
+ import { cachedAcceptanceFit, featuresFromReport, predictAcceptance, } from './acceptance-model.js';
30
+ import { envBuff } from '../config/paths.js';
31
+ /**
32
+ * The Q off-switch. Unset/empty = ON; an explicit OFF word disables the measured
33
+ * quality score so the router falls back to the derived signals it always had.
34
+ * (`NUVIRA_BANDIT_QUALITY=off`.)
35
+ */
36
+ const OFF_WORDS = new Set(['0', 'false', 'off', 'no']);
37
+ export function banditQualityEnabled() {
38
+ const v = envBuff('BANDIT_QUALITY');
39
+ if (v === undefined || v === '')
40
+ return true;
41
+ return !OFF_WORDS.has(v.toLowerCase());
42
+ }
43
+ /**
44
+ * The measured `qualityScore` for a turn, or `undefined`.
45
+ *
46
+ * `undefined` is the honest default: the fitted acceptance model refuses below
47
+ * its sample floor, so on a machine with too few ratings the router learns
48
+ * exactly what it learned before. A number is written ONLY when a trained model
49
+ * exists — never a guessed constant (see `DESIGN_CAPABILITY_BY_MEASUREMENT.md`).
50
+ */
51
+ function qualityScoreForTurn(report, opts) {
52
+ const features = featuresFromReport(report);
53
+ if (opts.qualityScoreFor)
54
+ return opts.qualityScoreFor(features);
55
+ if (!banditQualityEnabled())
56
+ return undefined;
57
+ const fit = cachedAcceptanceFit();
58
+ return fit.ok ? predictAcceptance(fit.model, features) : undefined;
59
+ }
60
+ /**
61
+ * Map a turn's verification verdict to what the router should learn from it.
62
+ * Returns `null` when the turn carries no evidence about the model.
63
+ */
64
+ export function turnOutcomeObservation(report, opts = {}) {
65
+ if (!report)
66
+ return null;
67
+ // ACCURACY EVIDENCE — the turn's own checks, when it ran any. `checksPassed` is
68
+ // tri-state precisely so that "nobody checked" contributes no `testPassed` sample:
69
+ // a plain question and a failing test suite must not teach the same lesson.
70
+ const checkData = report.checksPassed === undefined ? {} : { testPassed: report.checksPassed };
71
+ // MEASURED QUALITY — the one input derived signals cannot supply (was the work
72
+ // WANTED, not just "did it verify"). Present only when the acceptance model has
73
+ // trained on enough of the user's own verdicts; otherwise omitted entirely.
74
+ const quality = qualityScoreForTurn(report, opts);
75
+ const qualityData = quality === undefined ? {} : { qualityScore: quality };
76
+ switch (report.verification) {
77
+ case 'verified':
78
+ // A change was made and an observation followed it.
79
+ return { outcome: 'success', outcomeData: { verificationPassed: true, ...checkData, ...qualityData } };
80
+ case 'unverified':
81
+ // The turn ran, and its work could not be confirmed (an edit with no
82
+ // observation, an honesty flag, or an unobserved mutation). Booked as a
83
+ // success WITH `verificationPassed: false` rather than as a hard failure:
84
+ // the model DID answer, and the reward model's own penalty for an
85
+ // unverified success is the calibrated weight for exactly this shape.
86
+ // Calling it a failure outright would double-penalise one event.
87
+ return { outcome: 'success', outcomeData: { verificationPassed: false, ...checkData, ...qualityData } };
88
+ default:
89
+ // 'blocked' — a step could not complete (often environmental, not the
90
+ // model's doing). 'not-applicable' — nothing checkable happened. Neither
91
+ // is evidence about the model, so neither is recorded.
92
+ return null;
93
+ }
94
+ }
95
+ //# sourceMappingURL=outcome-observation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outcome-observation.js","sourceRoot":"","sources":["../../src/learning/outcome-observation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAIH,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,GAElB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAO7C;;;;GAIG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;AAEvD,MAAM,UAAU,oBAAoB;IAClC,MAAM,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK,SAAS,IAAI,CAAC,KAAK,EAAE;QAAE,OAAO,IAAI,CAAC;IAC7C,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AACzC,CAAC;AAUD;;;;;;;GAOG;AACH,SAAS,mBAAmB,CAC1B,MAAkB,EAClB,IAA4B;IAE5B,MAAM,QAAQ,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAC5C,IAAI,IAAI,CAAC,eAAe;QAAE,OAAO,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC;IAChE,IAAI,CAAC,oBAAoB,EAAE;QAAE,OAAO,SAAS,CAAC;IAC9C,MAAM,GAAG,GAAG,mBAAmB,EAAE,CAAC;IAClC,OAAO,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACrE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CACpC,MAAqC,EACrC,OAA+B,EAAE;IAEjC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,gFAAgF;IAChF,mFAAmF;IACnF,4EAA4E;IAC5E,MAAM,SAAS,GAAG,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC;IAC/F,+EAA+E;IAC/E,gFAAgF;IAChF,4EAA4E;IAC5E,MAAM,OAAO,GAAG,mBAAmB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAClD,MAAM,WAAW,GAAG,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC;IAC3E,QAAQ,MAAM,CAAC,YAAY,EAAE,CAAC;QAC5B,KAAK,UAAU;YACb,oDAAoD;YACpD,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,kBAAkB,EAAE,IAAI,EAAE,GAAG,SAAS,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;QACzG,KAAK,YAAY;YACf,qEAAqE;YACrE,wEAAwE;YACxE,0EAA0E;YAC1E,kEAAkE;YAClE,sEAAsE;YACtE,iEAAiE;YACjE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,EAAE,kBAAkB,EAAE,KAAK,EAAE,GAAG,SAAS,EAAE,GAAG,WAAW,EAAE,EAAE,CAAC;QAC1G;YACE,sEAAsE;YACtE,yEAAyE;YACzE,uDAAuD;YACvD,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,184 @@
1
+ /**
2
+ * PAIR ENTITLEMENT — of two providers that both list the same model, which one
3
+ * can actually serve it RIGHT NOW?
4
+ *
5
+ * THE DEFECT THIS CLOSES (reported 2026-10-07). Four providers list a DeepSeek
6
+ * model. One key genuinely has access to it; on the others the account has no
7
+ * model access and no free tokens. Ranking is per MODEL, so all four twins
8
+ * present the same capability rank — and the router, ordering on rank (and, on
9
+ * a tie, on whichever provider it happened to score first), could spend the
10
+ * turn's first call on a pair the registry had ALREADY recorded as refused:
11
+ * a `402 Insufficient credits` / `403` / `credit-exhausted` round trip, then a
12
+ * failover, then the turn finally starts. Measured in run D of this programme:
13
+ * a strict pin at `openrouter/deepseek/deepseek-v4.1-flash` failed in 6 SECONDS
14
+ * with `402 Insufficient credits` — while `deepseek/deepseek-flash`, the same
15
+ * model on a funded account, sat in the pool.
16
+ *
17
+ * The registry already knew. `ModelRegistryEntry` carries `status`,
18
+ * `lastError`, `deadPair` and `quotaParkedUntil` for every provider × model
19
+ * pair, and two predicates in `model-registry.ts` interpret them
20
+ * (`isEntitlementFailure`, `isNonexistentPair`). What did not exist was a single
21
+ * answer to "may the router call THIS PAIR", asked before the call instead of
22
+ * after it.
23
+ *
24
+ * ─── DOCTRINE (read before changing the order below) ───────────────────────
25
+ *
26
+ * 1. **The verdict is per PAIR, never per model.** `openrouter`'s exhausted
27
+ * credit balance and `deepseek`'s funded account are facts about two
28
+ * different ACCOUNTS. Two twins may share a canonical model id and still
29
+ * have opposite verdicts, and each verdict is read from ITS OWN registry row.
30
+ * Nothing here ever infers "this provider is funded because its twin is" —
31
+ * that is the F6 defect (an availability verdict erased by unrelated
32
+ * evidence) wearing a new hat.
33
+ * 2. **A refusal is a NO, and it is FINAL while a funded alternative exists.**
34
+ * `refused` means the account cannot serve this pairing: no credits, no
35
+ * billing, a rejected key, or the id does not exist on that endpoint. None
36
+ * of those are repaired by retrying, so a refused pair is never picked while
37
+ * anything else can be. `stalled` (a quota park, or proof that aged out) is
38
+ * the opposite: it clears by itself, so it stays eligible and simply sinks.
39
+ * 3. **Never dead-end.** This module never REMOVES a candidate — it orders them
40
+ * (`orderByEntitlement` is a stable partition). If every provider refuses the
41
+ * model, the refused pairs are still there, in their old relative order, and
42
+ * the router can still try them. "Use every model we can actually call;
43
+ * reject only when nothing is left" survives.
44
+ * 4. **Ties go to the funded twin.** The user's rule, verbatim: "the rank of a
45
+ * model can be the same across providers, but the agent should only pick the
46
+ * one which has genuine token budget available". Because the ordering is a
47
+ * partition applied AFTER scoring, a funded twin outranks a refused twin even
48
+ * when the refused twin scored higher — a rank advantage cannot buy a call
49
+ * that is certain to fail.
50
+ *
51
+ * The labels below are printed (`model explain`, the fallback chain), so an
52
+ * operator can see WHY a twin was passed over instead of having to guess.
53
+ */
54
+ /**
55
+ * What the registry says about ONE provider × model pair's right to be called.
56
+ *
57
+ * Four states, not a boolean, because they need OPPOSITE handling and a
58
+ * two-valued answer would flatten them into one: `refused` is a permanent no
59
+ * (skip it), `stalled` is a temporary no (it may recover, so keep it), `unknown`
60
+ * is not a failure at all (never tried), and `funded` is a proven yes.
61
+ */
62
+ export type PairEntitlement =
63
+ /** Verified and usable right now — a real call proved THIS ACCOUNT serves THIS model. */
64
+ 'funded'
65
+ /** No entry, or an unverified one. Nothing has ever been tried: an unknown, not a failure. */
66
+ | 'unknown'
67
+ /** Provably served before, but not right now, for a reason that clears by itself (quota park, stale proof, a transient failure). */
68
+ | 'stalled'
69
+ /** The account was REFUSED this pairing: credit-exhausted / auth / billing / 40x, or the id does not exist on that endpoint. */
70
+ | 'refused';
71
+ /** The fields of a registry row this classifier reads. Deliberately minimal. */
72
+ export interface EntitlementInput {
73
+ status?: string;
74
+ lastError?: string;
75
+ deadPair?: boolean;
76
+ quotaParkedUntil?: number;
77
+ providerParked?: boolean;
78
+ lastVerifiedAt?: number;
79
+ }
80
+ /**
81
+ * Classify one pair. Pure and total — never throws, never returns undefined.
82
+ *
83
+ * CLAUSE ORDER IS LOAD-BEARING, and `status` comes FIRST — exactly as in
84
+ * `classifyReachability`. That is not cosmetic; getting it backwards creates a
85
+ * brand-new false refusal:
86
+ *
87
+ * - `verified` is a LATCH. Two different writes can leave a row `verified`
88
+ * while an old refusal still sits in `lastError`: `markVerified`
89
+ * deliberately PRESERVES `lastError` across a success (it rebuilds the entry
90
+ * field by field and keeps `existing?.lastError`), and `recordCall` succeeds
91
+ * through `markVerified`. So after a user tops up their credits and the next
92
+ * call works, the row is `verified` + `"credit-exhausted (…)"` — the model is
93
+ * being served RIGHT NOW.
94
+ * - Checking `isEntitlementFailure(lastError)` before `status` would call that
95
+ * pair refused and skip the funded account we just proved works. It is the
96
+ * same mistake in the other direction (a stale verdict outranking fresh
97
+ * evidence), so an entitlement refusal only counts while the entry is still
98
+ * sitting in the state that refusal produced — the registry's own guard,
99
+ * `existing?.status === 'unavailable' && isEntitlementFailure(...)` in
100
+ * `markListed`.
101
+ *
102
+ * The clauses:
103
+ *
104
+ * 1. A NONEXISTENT pair is refused whatever the status says: `deadPair` is an
105
+ * explicit "this id does not exist on this endpoint" and the provider's own
106
+ * model list is what clears it. (`isNonexistentPair` also covers an
107
+ * `unavailable` row whose recorded reason is a not-found — legacy data.)
108
+ * 2. `unverified` / absent is `unknown` — never a failure. Most of any registry
109
+ * is here, and treating "never tried" as "cannot work" would empty the pool.
110
+ * 3. `unavailable` + an entitlement reason is `refused` (credit-exhausted /
111
+ * auth / billing / 40x — what run D hit). Any other `unavailable` reason is
112
+ * `stalled`: rate limits, timeouts and 5xx are transient by the registry's
113
+ * own doctrine and must not be treated as a permanent no.
114
+ * 4. A `verified` entry is `funded` unless a MODEL-level park or a stale proof
115
+ * holds it back. A PROVIDER-level park does not count — that is the Gemini
116
+ * parking bug, and `isUsable()` skips it for proven models too.
117
+ */
118
+ export declare function classifyPairEntitlement(entry: EntitlementInput | undefined, now?: number): PairEntitlement;
119
+ /**
120
+ * The pick order: funded, then never-tried, then stalled, then refused.
121
+ *
122
+ * `unknown` deliberately outranks `stalled`: `stalled` is "no budget right
123
+ * now" (the exact thing this module exists to avoid spending a round on), while
124
+ * `unknown` may simply work. This also matches how the model scorer already
125
+ * weights the two (`quotaAvailability` 0.6 for unverified vs 0.0 for parked).
126
+ */
127
+ export declare const ENTITLEMENT_ORDER: Record<PairEntitlement, number>;
128
+ /**
129
+ * Stable partition of candidates by entitlement — funded pairs first, refused
130
+ * pairs last, everything else untouched inside its group (and the input array
131
+ * never mutated). A PARTITION and not a filter: see doctrine 3 (never dead-end).
132
+ */
133
+ export declare function orderByEntitlement<T>(items: readonly T[], of: (item: T) => PairEntitlement): T[];
134
+ /** Short chip for a verdict — CLI/dashboard labels. */
135
+ export declare const ENTITLEMENT_LABEL: Record<PairEntitlement, string>;
136
+ /**
137
+ * One sentence naming the EVIDENCE, not just the verdict — an operator reading
138
+ * `model explain` has to be able to tell a refused account from an untried one.
139
+ */
140
+ export declare function entitlementNote(entitlement: PairEntitlement, entry?: EntitlementInput): string;
141
+ /**
142
+ * The model id two rows must share before they are treated as the same model
143
+ * offered by different providers — the "twins" the user's rule is about.
144
+ *
145
+ * A1 (2026-10-07): the rule is now `learning/model-identity.ts` — an EXACT
146
+ * comparison against a bare or `vendor/`-prefixed id, WIDENED by the DECLARED
147
+ * alias table and never by similarity. That widening is what relates
148
+ * `openrouter/deepseek/deepseek-v4.1-flash` to `deepseek/deepseek-flash` (the two
149
+ * rows a run-D 402 pin needed related), while `deepseek-flash` and
150
+ * `deepseek-v4-flash` stay separate because no declaration relates them.
151
+ *
152
+ * Grouping is the only thing identity does here. A verdict is still read from
153
+ * each twin's OWN row — see the doctrine at the top of this file.
154
+ */
155
+ export declare function twinKey(model: string): string;
156
+ /** Do these two model ids name the same model served by different providers? */
157
+ export declare function areTwins(a: string, b: string): boolean;
158
+ /** One twin in a same-model group, with the verdict read from ITS OWN row. */
159
+ export interface TwinVerdict<T> {
160
+ item: T;
161
+ provider: string;
162
+ model: string;
163
+ entitlement: PairEntitlement;
164
+ note: string;
165
+ }
166
+ /**
167
+ * Resolve a group of SAME-MODEL twins to the one the router may call, and say
168
+ * what was passed over and why.
169
+ *
170
+ * This is the user's requirement as a function: identical ranks, one funded
171
+ * twin, so the funded twin is the only acceptable pick — and each twin's verdict
172
+ * comes from its own registry row (doctrine 1). The refused ones come back in
173
+ * `passedOver` so the caller can PRINT them ("`openrouter` refuses this model —
174
+ * credit-exhausted") instead of silently pretending they were never there.
175
+ *
176
+ * Never returns nothing when the group is non-empty: if EVERY twin is refused,
177
+ * the first is still chosen (doctrine 3 — a certain failure beats no attempt at
178
+ * all only when there is genuinely nothing else, and the caller decides).
179
+ */
180
+ export declare function resolveFundedTwin<T>(twins: readonly TwinVerdict<T>[]): {
181
+ chosen?: TwinVerdict<T>;
182
+ passedOver: TwinVerdict<T>[];
183
+ };
184
+ //# sourceMappingURL=pair-entitlement.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pair-entitlement.d.ts","sourceRoot":"","sources":["../../src/learning/pair-entitlement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AAKH;;;;;;;GAOG;AACH,MAAM,MAAM,eAAe;AACzB,yFAAyF;AACvF,QAAQ;AACV,8FAA8F;GAC5F,SAAS;AACX,oIAAoI;GAClI,SAAS;AACX,gIAAgI;GAC9H,SAAS,CAAC;AAEd,gFAAgF;AAChF,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,gBAAgB,GAAG,SAAS,EACnC,GAAG,GAAE,MAAmB,GACvB,eAAe,CAgBjB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAK7D,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,IAAI,EAAE,CAAC,KAAK,eAAe,GAAG,CAAC,EAAE,CAIhG;AAED,uDAAuD;AACvD,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,eAAe,EAAE,MAAM,CAK7D,CAAC;AAEF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,WAAW,EAAE,eAAe,EAAE,KAAK,CAAC,EAAE,gBAAgB,GAAG,MAAM,CAmB9F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAE7C;AAED,gFAAgF;AAChF,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED,8EAA8E;AAC9E,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,eAAe,CAAC;IAC7B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EACjC,KAAK,EAAE,SAAS,WAAW,CAAC,CAAC,CAAC,EAAE,GAC/B;IAAE,MAAM,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;IAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,CAAA;CAAE,CAO3D"}
@@ -0,0 +1,214 @@
1
+ /**
2
+ * PAIR ENTITLEMENT — of two providers that both list the same model, which one
3
+ * can actually serve it RIGHT NOW?
4
+ *
5
+ * THE DEFECT THIS CLOSES (reported 2026-10-07). Four providers list a DeepSeek
6
+ * model. One key genuinely has access to it; on the others the account has no
7
+ * model access and no free tokens. Ranking is per MODEL, so all four twins
8
+ * present the same capability rank — and the router, ordering on rank (and, on
9
+ * a tie, on whichever provider it happened to score first), could spend the
10
+ * turn's first call on a pair the registry had ALREADY recorded as refused:
11
+ * a `402 Insufficient credits` / `403` / `credit-exhausted` round trip, then a
12
+ * failover, then the turn finally starts. Measured in run D of this programme:
13
+ * a strict pin at `openrouter/deepseek/deepseek-v4.1-flash` failed in 6 SECONDS
14
+ * with `402 Insufficient credits` — while `deepseek/deepseek-flash`, the same
15
+ * model on a funded account, sat in the pool.
16
+ *
17
+ * The registry already knew. `ModelRegistryEntry` carries `status`,
18
+ * `lastError`, `deadPair` and `quotaParkedUntil` for every provider × model
19
+ * pair, and two predicates in `model-registry.ts` interpret them
20
+ * (`isEntitlementFailure`, `isNonexistentPair`). What did not exist was a single
21
+ * answer to "may the router call THIS PAIR", asked before the call instead of
22
+ * after it.
23
+ *
24
+ * ─── DOCTRINE (read before changing the order below) ───────────────────────
25
+ *
26
+ * 1. **The verdict is per PAIR, never per model.** `openrouter`'s exhausted
27
+ * credit balance and `deepseek`'s funded account are facts about two
28
+ * different ACCOUNTS. Two twins may share a canonical model id and still
29
+ * have opposite verdicts, and each verdict is read from ITS OWN registry row.
30
+ * Nothing here ever infers "this provider is funded because its twin is" —
31
+ * that is the F6 defect (an availability verdict erased by unrelated
32
+ * evidence) wearing a new hat.
33
+ * 2. **A refusal is a NO, and it is FINAL while a funded alternative exists.**
34
+ * `refused` means the account cannot serve this pairing: no credits, no
35
+ * billing, a rejected key, or the id does not exist on that endpoint. None
36
+ * of those are repaired by retrying, so a refused pair is never picked while
37
+ * anything else can be. `stalled` (a quota park, or proof that aged out) is
38
+ * the opposite: it clears by itself, so it stays eligible and simply sinks.
39
+ * 3. **Never dead-end.** This module never REMOVES a candidate — it orders them
40
+ * (`orderByEntitlement` is a stable partition). If every provider refuses the
41
+ * model, the refused pairs are still there, in their old relative order, and
42
+ * the router can still try them. "Use every model we can actually call;
43
+ * reject only when nothing is left" survives.
44
+ * 4. **Ties go to the funded twin.** The user's rule, verbatim: "the rank of a
45
+ * model can be the same across providers, but the agent should only pick the
46
+ * one which has genuine token budget available". Because the ordering is a
47
+ * partition applied AFTER scoring, a funded twin outranks a refused twin even
48
+ * when the refused twin scored higher — a rank advantage cannot buy a call
49
+ * that is certain to fail.
50
+ *
51
+ * The labels below are printed (`model explain`, the fallback chain), so an
52
+ * operator can see WHY a twin was passed over instead of having to guess.
53
+ */
54
+ import { DEFAULT_STALE_MS, isEntitlementFailure, isNonexistentPair } from './model-registry.js';
55
+ import { identityKey, sameModel } from './model-identity.js';
56
+ /**
57
+ * Classify one pair. Pure and total — never throws, never returns undefined.
58
+ *
59
+ * CLAUSE ORDER IS LOAD-BEARING, and `status` comes FIRST — exactly as in
60
+ * `classifyReachability`. That is not cosmetic; getting it backwards creates a
61
+ * brand-new false refusal:
62
+ *
63
+ * - `verified` is a LATCH. Two different writes can leave a row `verified`
64
+ * while an old refusal still sits in `lastError`: `markVerified`
65
+ * deliberately PRESERVES `lastError` across a success (it rebuilds the entry
66
+ * field by field and keeps `existing?.lastError`), and `recordCall` succeeds
67
+ * through `markVerified`. So after a user tops up their credits and the next
68
+ * call works, the row is `verified` + `"credit-exhausted (…)"` — the model is
69
+ * being served RIGHT NOW.
70
+ * - Checking `isEntitlementFailure(lastError)` before `status` would call that
71
+ * pair refused and skip the funded account we just proved works. It is the
72
+ * same mistake in the other direction (a stale verdict outranking fresh
73
+ * evidence), so an entitlement refusal only counts while the entry is still
74
+ * sitting in the state that refusal produced — the registry's own guard,
75
+ * `existing?.status === 'unavailable' && isEntitlementFailure(...)` in
76
+ * `markListed`.
77
+ *
78
+ * The clauses:
79
+ *
80
+ * 1. A NONEXISTENT pair is refused whatever the status says: `deadPair` is an
81
+ * explicit "this id does not exist on this endpoint" and the provider's own
82
+ * model list is what clears it. (`isNonexistentPair` also covers an
83
+ * `unavailable` row whose recorded reason is a not-found — legacy data.)
84
+ * 2. `unverified` / absent is `unknown` — never a failure. Most of any registry
85
+ * is here, and treating "never tried" as "cannot work" would empty the pool.
86
+ * 3. `unavailable` + an entitlement reason is `refused` (credit-exhausted /
87
+ * auth / billing / 40x — what run D hit). Any other `unavailable` reason is
88
+ * `stalled`: rate limits, timeouts and 5xx are transient by the registry's
89
+ * own doctrine and must not be treated as a permanent no.
90
+ * 4. A `verified` entry is `funded` unless a MODEL-level park or a stale proof
91
+ * holds it back. A PROVIDER-level park does not count — that is the Gemini
92
+ * parking bug, and `isUsable()` skips it for proven models too.
93
+ */
94
+ export function classifyPairEntitlement(entry, now = Date.now()) {
95
+ if (!entry)
96
+ return 'unknown';
97
+ // 1. "This model does not exist here" — provider-declared, status-independent.
98
+ if (isNonexistentPair(entry))
99
+ return 'refused';
100
+ const status = entry.status ?? 'unverified';
101
+ // 2. Never tried — an unknown, not a refusal.
102
+ if (status === 'unverified')
103
+ return 'unknown';
104
+ // 3. Unavailable: refused if the ACCOUNT was refused, otherwise a no for now.
105
+ if (status !== 'verified') {
106
+ return isEntitlementFailure(entry.lastError) ? 'refused' : 'stalled';
107
+ }
108
+ // 4. Verified: only a MODEL-level park or an aged-out proof holds it back.
109
+ const parkedUntil = entry.quotaParkedUntil ?? 0;
110
+ if (parkedUntil > now && entry.providerParked === false)
111
+ return 'stalled';
112
+ if (now - (entry.lastVerifiedAt ?? 0) > DEFAULT_STALE_MS)
113
+ return 'stalled';
114
+ return 'funded';
115
+ }
116
+ /**
117
+ * The pick order: funded, then never-tried, then stalled, then refused.
118
+ *
119
+ * `unknown` deliberately outranks `stalled`: `stalled` is "no budget right
120
+ * now" (the exact thing this module exists to avoid spending a round on), while
121
+ * `unknown` may simply work. This also matches how the model scorer already
122
+ * weights the two (`quotaAvailability` 0.6 for unverified vs 0.0 for parked).
123
+ */
124
+ export const ENTITLEMENT_ORDER = {
125
+ funded: 0,
126
+ unknown: 1,
127
+ stalled: 2,
128
+ refused: 3,
129
+ };
130
+ /**
131
+ * Stable partition of candidates by entitlement — funded pairs first, refused
132
+ * pairs last, everything else untouched inside its group (and the input array
133
+ * never mutated). A PARTITION and not a filter: see doctrine 3 (never dead-end).
134
+ */
135
+ export function orderByEntitlement(items, of) {
136
+ const buckets = { funded: [], unknown: [], stalled: [], refused: [] };
137
+ for (const item of items)
138
+ buckets[of(item)].push(item);
139
+ return [...buckets.funded, ...buckets.unknown, ...buckets.stalled, ...buckets.refused];
140
+ }
141
+ /** Short chip for a verdict — CLI/dashboard labels. */
142
+ export const ENTITLEMENT_LABEL = {
143
+ funded: '✅ funded',
144
+ unknown: '❔ untried',
145
+ stalled: '⏸ stalled',
146
+ refused: '⛔ refused',
147
+ };
148
+ /**
149
+ * One sentence naming the EVIDENCE, not just the verdict — an operator reading
150
+ * `model explain` has to be able to tell a refused account from an untried one.
151
+ */
152
+ export function entitlementNote(entitlement, entry) {
153
+ switch (entitlement) {
154
+ case 'funded':
155
+ return 'proven to work on this account, and nothing is blocking it right now';
156
+ case 'unknown':
157
+ return 'never tried on this provider — no evidence either way (not a failure)';
158
+ case 'stalled': {
159
+ const parkedUntil = entry?.quotaParkedUntil ?? 0;
160
+ if (parkedUntil > Date.now()) {
161
+ const mins = Math.max(1, Math.round((parkedUntil - Date.now()) / 60_000));
162
+ return `proven to work, but parked on its own quota window — free again in ~${mins}m`;
163
+ }
164
+ return 'proven to work once, but not provably servable right now (stale proof or a transient failure)';
165
+ }
166
+ case 'refused':
167
+ return isNonexistentPair(entry ?? {})
168
+ ? 'the provider says this model does not exist on this endpoint'
169
+ : `this account was refused: ${entry?.lastError ?? 'no reason recorded'}`;
170
+ }
171
+ }
172
+ /**
173
+ * The model id two rows must share before they are treated as the same model
174
+ * offered by different providers — the "twins" the user's rule is about.
175
+ *
176
+ * A1 (2026-10-07): the rule is now `learning/model-identity.ts` — an EXACT
177
+ * comparison against a bare or `vendor/`-prefixed id, WIDENED by the DECLARED
178
+ * alias table and never by similarity. That widening is what relates
179
+ * `openrouter/deepseek/deepseek-v4.1-flash` to `deepseek/deepseek-flash` (the two
180
+ * rows a run-D 402 pin needed related), while `deepseek-flash` and
181
+ * `deepseek-v4-flash` stay separate because no declaration relates them.
182
+ *
183
+ * Grouping is the only thing identity does here. A verdict is still read from
184
+ * each twin's OWN row — see the doctrine at the top of this file.
185
+ */
186
+ export function twinKey(model) {
187
+ return identityKey(model);
188
+ }
189
+ /** Do these two model ids name the same model served by different providers? */
190
+ export function areTwins(a, b) {
191
+ return sameModel(a, b);
192
+ }
193
+ /**
194
+ * Resolve a group of SAME-MODEL twins to the one the router may call, and say
195
+ * what was passed over and why.
196
+ *
197
+ * This is the user's requirement as a function: identical ranks, one funded
198
+ * twin, so the funded twin is the only acceptable pick — and each twin's verdict
199
+ * comes from its own registry row (doctrine 1). The refused ones come back in
200
+ * `passedOver` so the caller can PRINT them ("`openrouter` refuses this model —
201
+ * credit-exhausted") instead of silently pretending they were never there.
202
+ *
203
+ * Never returns nothing when the group is non-empty: if EVERY twin is refused,
204
+ * the first is still chosen (doctrine 3 — a certain failure beats no attempt at
205
+ * all only when there is genuinely nothing else, and the caller decides).
206
+ */
207
+ export function resolveFundedTwin(twins) {
208
+ if (twins.length === 0)
209
+ return { passedOver: [] };
210
+ const ordered = [...twins].sort((a, b) => ENTITLEMENT_ORDER[a.entitlement] - ENTITLEMENT_ORDER[b.entitlement]);
211
+ const [chosen, ...passedOver] = ordered;
212
+ return { chosen, passedOver };
213
+ }
214
+ //# sourceMappingURL=pair-entitlement.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pair-entitlement.js","sourceRoot":"","sources":["../../src/learning/pair-entitlement.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * PROJECT DOCUMENTATION (software deliverables).
3
+ *
4
+ * The gap this closes: a software build produced CODE and stopped. The
5
+ * documents a real project ships — a README, a changelog that grows with each
6
+ * change, a short architecture note with a diagram, and (for a library/service)
7
+ * usage + API docs — were only produced when the user named them, which is
8
+ * exactly backwards: a user should not have to ask a "world-class developer" to
9
+ * write down what it built.
10
+ *
11
+ * Two rules keep this from becoming noise:
12
+ *
13
+ * 1. **Software only.** This module is consulted ONLY for a `code` deliverable
14
+ * that is not authored (`deliverable-class.ts` already separates a poem
15
+ * from a program). Nobody wants a README and an ARCHITECTURE.md for
16
+ * "write me a poem about rain" — the classifier decides, and this guidance
17
+ * is never appended to an authored ask.
18
+ * 2. **Proportionate.** A README and a CHANGELOG are expected of every
19
+ * software deliverable; the heavier documents (architecture, API reference,
20
+ * contributing guide) are asked for only when the shape warrants them —
21
+ * a multi-component or library/service build, or an explicit request for
22
+ * docs. A one-file script still gets a README; it is not asked to invent an
23
+ * architecture diagram.
24
+ *
25
+ * It also encodes the maintenance rule the user cares about: an EXISTING
26
+ * document is UPDATED in place (CHANGELOG gets a new entry at the top), never
27
+ * shadowed by a second file — a project with two changelogs is worse than one
28
+ * with none.
29
+ *
30
+ * Pure and side-effect free: every input is data, so it is unit-testable and can
31
+ * be appended to any prompt without touching the filesystem.
32
+ */
33
+ /** The canonical documents a software project ships, in priority order. */
34
+ export interface ProjectDocArtifact {
35
+ /** Project-relative path the document lives at. */
36
+ path: string;
37
+ /** What it is FOR — handed to the model so the document has a job. */
38
+ purpose: string;
39
+ /** Required of every software deliverable (README, CHANGELOG). */
40
+ always: boolean;
41
+ }
42
+ export declare const PROJECT_DOC_ARTIFACTS: readonly ProjectDocArtifact[];
43
+ /** What we know about the deliverable, from the goal + project assessment. */
44
+ export interface ProjectDocShape {
45
+ /**
46
+ * True when the workspace has no project yet (a scaffold). A greenfield build
47
+ * gets the full proportionate set rather than only the always-on pair.
48
+ */
49
+ greenfield?: boolean;
50
+ /**
51
+ * A library, package, SDK or service — a thing other code CONSUMES — rather
52
+ * than an end-user app. Its public surface must be documented.
53
+ */
54
+ isLibraryOrService?: boolean;
55
+ /** The project already exposes tests (or the agent is expected to write them). */
56
+ hasTests?: boolean;
57
+ /** Names the user explicitly asked for docs ("with documentation", "API docs"). */
58
+ docsRequested?: boolean;
59
+ /**
60
+ * Documents that ALREADY exist in the workspace (project-relative paths).
61
+ * These are UPDATED in place, never duplicated.
62
+ */
63
+ existingDocs?: readonly string[];
64
+ }
65
+ /** The always-on pair, plus the heavier docs a bigger build warrants. */
66
+ export declare function requiredProjectDocs(shape?: ProjectDocShape): string[];
67
+ /**
68
+ * Does the goal name something other code CONSUMES (a library, package, SDK,
69
+ * CLI, service, plugin) rather than an end-user app? A consumed surface has a
70
+ * public API worth documenting; an app does not need an API reference.
71
+ */
72
+ export declare function looksLikeLibraryOrService(goal: string): boolean;
73
+ /** The required docs that do NOT yet exist on disk (the ones to CREATE). */
74
+ export declare function missingProjectDocs(shape?: ProjectDocShape): string[];
75
+ /** The required docs that already exist (the ones to UPDATE, not recreate). */
76
+ export declare function existingProjectDocs(shape?: ProjectDocShape): string[];
77
+ /**
78
+ * The instruction appended to the reasoner/planner prompt for a SOFTWARE
79
+ * deliverable. Returns `''` for a non-software (authored) ask, so callers can
80
+ * append it unconditionally without a poem ever being asked for a CHANGELOG.
81
+ */
82
+ export declare function softwareProjectGuidance(verdictClass: string, authored: boolean, shape?: ProjectDocShape): string;
83
+ //# sourceMappingURL=project-docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"project-docs.d.ts","sourceRoot":"","sources":["../../src/learning/project-docs.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,2EAA2E;AAC3E,MAAM,WAAW,kBAAkB;IACjC,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,eAAO,MAAM,qBAAqB,EAAE,SAAS,kBAAkB,EAqC9D,CAAC;AAEF,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;OAGG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,mFAAmF;IACnF,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;OAGG;IACH,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,yEAAyE;AACzE,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,eAAoB,GAAG,MAAM,EAAE,CAOzE;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAU/D;AAED,4EAA4E;AAC5E,wBAAgB,kBAAkB,CAAC,KAAK,GAAE,eAAoB,GAAG,MAAM,EAAE,CAGxE;AAED,+EAA+E;AAC/E,wBAAgB,mBAAmB,CAAC,KAAK,GAAE,eAAoB,GAAG,MAAM,EAAE,CAGzE;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,YAAY,EAAE,MAAM,EACpB,QAAQ,EAAE,OAAO,EACjB,KAAK,GAAE,eAAoB,GAC1B,MAAM,CAmCR"}