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
@@ -1,212 +1,45 @@
1
1
  /**
2
- * Loop skill hint (`src/tools/loop-skill-hint.ts`) — AGENTIC_CAPABILITY_ASSESSMENT
3
- * Addendum v4 Phase 3.2: "The loop never hears about the orchestrator's skill
4
- * layer: the pipeline consults SkillStore.findMatch + the hub catalog before
5
- * planning and injects the matched methodology, but a chat/execute-loop goal
6
- * starts with zero knowledge that a first-party playbook exists."
7
- *
8
- * This module closes that parity gap DETERMINISTICALLY (no LLM call): given
9
- * the user's goal, it finds the best available skill the SAME way the
10
- * orchestrator does —
11
- *
12
- * 1. compiled SkillStore.findMatch (the first-party capability batch),
13
- * 2. the hub catalog (findHubSkillMatch — installed SKILL.md skills),
14
- *
15
- * then returns a system-prompt block that hands the model the skill's
16
- * methodology with an EXPLICIT escape hatch ("this is a recommendation —
17
- * ignore it when it does not fit") and the exact load syntax
18
- * (`skill` tool, {"skill":"<name>"}).
19
- *
20
- * Why an evidence filter on top of findMatch: the compiled store's threshold
21
- * is intentionally low (score >= 1, "manual discovery") and its scoring adds
22
- * a quality/usage bonus to EVERY skill — so a goal merely containing a generic
23
- * pattern word ("goal", "task") can false-positive. The chat loop runs on
24
- * EVERY message (not just pipeline goals), so the loop hint requires REAL
25
- * goal evidence: a name-word or tag hit, or two pattern-word hits. The
26
- * orchestrator does not need this (its planner only sees pipeline goals); the
27
- * hub catalog's own scoring is keyword-based and needs no filter.
28
- *
29
- * Safety rails (mirroring the orchestrator's injection contract):
30
- * - skills.disabled[] gate — a dashboard/CLI-disabled skill is NEVER
31
- * injected (the same "the toggle is never cosmetic" rule the match gates
32
- * enforce elsewhere).
33
- * - Website-deploy activation gate — the orchestrator requires
34
- * hosting-specific intent before injecting website methodology; the loop
35
- * hint applies the identical regex so "deploy the API" does not drag in
36
- * static-site deployment steps.
37
- * - Side-effect-free matching: the match itself marks nothing; usage is
38
- * marked ONCE via markLoopSkillUsed by the caller (skillView()'s internal
39
- * markUsed is deliberately avoided so the hint builder is idempotent).
40
- * - Bounded injection: at most ONE methodology block per prompt, and the
41
- * methodology text itself is capped (compiled: 8 steps; hub: 2000 chars)
42
- * so a crowded catalog cannot balloon the system prompt.
43
- * - Best-effort by construction: any store/catalog failure returns '' /
44
- * null and the turn proceeds exactly as before (a hint must never break
45
- * a turn).
46
- *
47
- * Consumers: chat's runChatAnswer (system prompt) and the execute loop's
48
- * runLoopExecutor — the two runToolLoop callers that had no skill knowledge.
49
- */
50
- /**
51
- * Website-deploy activation gate — IDENTICAL to the orchestrator's
52
- * (src/agents/orchestrator.ts §3c): a website-deployment skill (bundled OR
53
- * hub-installed) is only injected when the goal carries hosting-specific
54
- * intent. A generic "deploy the API" goal does NOT get website methodology.
55
- */
56
- const WEBSITE_DEPLOY_ID = /website[-_ ]?deploy/i;
57
- const HOSTING_INTENT = /cloudflare|netlify|vercel|github\s*pages|hosting|pages\.dev|web\s*site|website|static\s*site|landing\s*page/i;
58
- /**
59
- * Meta-words that appear in generic goalPatterns but carry NO goal evidence
60
- * ("compile a plan for this goal"). Excluded from pattern-word matching so a
61
- * goal containing only meta-vocabulary can never match a skill.
62
- */
63
- const PATTERN_STOPWORDS = new Set([
64
- 'goal', 'goals', 'task', 'tasks', 'skill', 'skills', 'step', 'steps',
65
- 'plan', 'plans', 'planning', 'when', 'with', 'this', 'that', 'from',
66
- 'into', 'user', 'users', 'want', 'wants', 'need', 'needs', 'request',
67
- 'requests', 'help', 'make', 'using', 'used', 'work', 'works', 'some',
68
- 'onto', 'over', 'your', 'their', 'them', 'then', 'also', 'each',
69
- // Generic document nouns/verbs — no domain evidence on their own.
70
- //
71
- // The docx skill's DESCRIPTION is long prose ("create, read, edit, or
72
- // manipulate Word **documents**… produce professional **documents** with
73
- // … **page** numbers"), so its generic words cleared the two-distinct-word
74
- // bar for any goal that merely mentioned a document. Measured live
75
- // (2026-10-03): the hub docx skill matched "Read the health report PDF …
76
- // produce a thorough assessment" on exactly `documents` + `produce` + `page`
77
- // — none of which names a document FORMAT.
78
- 'document', 'documents', 'produce', 'produces', 'page', 'pages',
79
- // Generic document/analysis verbs — no domain evidence on their own.
80
- //
81
- // Measured live (2026-10-03): "read my health report - blood test report
82
- // and share me findings which are concerning and what changes i should do"
83
- // activated the **docx** skill and injected its whole "a .docx is a ZIP
84
- // archive of XML files / read with pandoc / unzip → edit word/document.xml"
85
- // methodology into a PDF lab-report turn — the model then reported the PDF
86
- // as a .docx with blank tables. The two "domain" words that cleared the
87
- // two-word bar were `read` (from the docx goalPattern) and `changes` (from
88
- // the description's "tracked changes"); neither names a document FORMAT.
89
- //
90
- // A FORMAT skill must match on its format NAME or a domain TAG, never on the
91
- // generic act of reading or on the noun "changes". Deliberately narrow: only
92
- // the two words observed in the false positive are excluded, so skills whose
93
- // real evidence is `create`/`build`/`edit`/`convert` are unaffected.
94
- 'read', 'reads', 'reading', 'changes', 'changed', 'changing',
95
- ]);
96
- /**
97
- * Skill-NAME words that are too generic to be evidence on their own.
98
- *
99
- * A skill's name is normally its strongest evidence — `wsl-setup` fires on
100
- * "wsl", `docker-config` on "docker". But a handful of skill names are built
101
- * from ordinary English words that carry a DIFFERENT meaning outside software:
102
- * `test` is also a medical/chemical noun (a blood test), a school noun, a
103
- * quality noun. Measured live (2026-10-03): the goal "read my health report -
104
- * blood test report and share me findings…" matched the **test-strategy**
105
- * skill on the single name word `test` and would have injected a
106
- * unit/integration/e2e software-testing methodology into a lab-report turn.
107
- *
108
- * A generic name word is NOT thrown away — it is DEMOTED: it counts as
109
- * evidence only when the goal uses it as the action (a leading/verb use, e.g.
110
- * "test the project") or when the skill's own domain vocabulary corroborates
111
- * it (see {@link isCompoundNounUse} and {@link hasRealGoalEvidence}).
112
- *
113
- * Deliberately tiny. Domain-ish names (`api`, `code`, `docx`, `docker`, `game`)
114
- * stay strong on their own: `REST API` and `code review` ARE the domain, so
115
- * excluding them would trade this false positive for a worse one. Only words
116
- * whose NON-software sense is common enough to appear in everyday requests
117
- * belong here.
118
- */
119
- const GENERIC_SKILL_NAME_WORDS = new Set([
120
- 'test', 'tests', 'testing',
121
- ]);
122
- /**
123
- * Words that do NOT make a following token a compound-noun modifier.
124
- *
125
- * Used by {@link isCompoundNounUse} to tell `blood test report` (the generic
126
- * word is a noun modifier, so it names no domain) from `please test the build`
127
- * (the generic word is the verb, so it IS the action). Determiners, pronouns,
128
- * prepositions, conjunctions, politeness and auxiliaries — the words a verb
129
- * can legitimately follow.
130
- */
131
- const VERB_PRECEDER_STOPWORDS = new Set([
132
- ...PATTERN_STOPWORDS,
133
- 'the', 'a', 'an', 'and', 'or', 'of', 'to', 'for', 'in', 'on', 'at', 'by',
134
- 'my', 'our', 'your', 'their', 'its', 'his', 'her', 'me', 'us', 'them', 'him',
135
- 'please', 'can', 'could', 'would', 'will', 'should', 'do', 'does', 'did',
136
- 'is', 'are', 'be', 'been', 'was', 'were', 'have', 'has', 'had', 'not',
137
- 'no', 'if', 'as', 'it', 'i', 'you', 'we', 'they', 'so', 'up', 'out',
138
- 'all', 'any', 'some', 'this', 'that', 'these', 'those', 'then', 'also',
139
- 'just', 'now', 'new', 'again', 'here', 'there',
140
- ]);
141
- /**
142
- * Is `word` used as a COMPOUND-NOUN modifier in the goal — i.e. immediately
143
- * preceded by another content word?
144
- *
145
- * "blood test report" → `test` follows the content word `blood`, so it is a
146
- * noun modifier and names no software domain. "test the project" / "please
147
- * test the build" → `test` follows nothing or a determiner/auxiliary, so it is
148
- * the verb and IS the action. Deterministic, no LLM.
149
- */
150
- function isCompoundNounUse(goal, word) {
151
- const tokens = (goal || '')
152
- .toLowerCase()
153
- .split(/[^a-z0-9]+/)
154
- .filter((w) => w.length > 0);
155
- for (let i = 1; i < tokens.length; i++) {
156
- if (tokens[i] !== word)
157
- continue;
158
- const prev = tokens[i - 1];
159
- if (prev.length > 3 && !VERB_PRECEDER_STOPWORDS.has(prev))
160
- return true;
161
- }
162
- return false;
163
- }
164
- /**
165
- * Is this word, for THIS goal, a generic word being used as a compound-noun
166
- * modifier rather than as its own domain term?
167
- *
168
- * The single rule every evidence loop consults: a generic name word (`test`) is
169
- * dropped when the goal only uses it as a noun modifier ("blood test report"),
170
- * because there it names a different domain than the skill's. Applied to name,
171
- * tag and pattern evidence alike so the three can never disagree.
172
- */
173
- function isDemotedGenericUse(goal, word) {
174
- return GENERIC_SKILL_NAME_WORDS.has(word) && isCompoundNounUse(goal, word);
175
- }
176
- /**
177
- * Meta-vocabulary that is ALSO excluded from TAG hits.
178
- *
179
- * Why tag hits need this too (live, 2026-09-20): `technical-roadmap` carries the
180
- * tags `roadmap`/`planning`, so the prompt "…how should i plan…" matched on the
181
- * single generic tag word `planning` and injected the skill's whole phased-
182
- * migration methodology into a TRAVEL-ITINERARY turn — irrelevant context that
183
- * pushed the model toward planning meta-talk and grew the prompt. The evidence
184
- * filter already excluded these words from goalPattern matching for exactly this
185
- * reason; a tag hit is the same kind of evidence and gets the same treatment.
186
- *
187
- * Deliberately narrow — process/meta nouns that name how work is done rather
188
- * than a domain. Domain tags (`deploy`, `testing`, `search`, `payments`) still
189
- * match, and a name-word hit is unaffected.
2
+ * Skill hint (`src/tools/loop-skill-hint.ts`) — model-driven skill selection.
3
+ *
4
+ * HISTORY (why the keyword scorer is gone). This module used to decide, in code,
5
+ * WHICH skill a goal wanted: `findLoopSkillMatch` scored the compiled store and
6
+ * the hub catalog, then a hand-written evidence filter (`hasRealGoalEvidence`)
7
+ * pulled back the false positives with stopword lists, generic-name-word lists,
8
+ * generic-tag lists and platform-host lists. Every one of those lists was a bug
9
+ * report: "blood test report" matched the software `test-strategy` skill,
10
+ * "Windows and Linux" matched `wsl-setup`, "packaging" matched `electron-app`.
11
+ * A word list cannot decide what a goal MEANS, and each word added to force one
12
+ * case right made some real match wrong.
13
+ *
14
+ * THE REPLACEMENT. Selection is the MODEL's job now. The harness no longer
15
+ * guesses; it hands the model the discovery path and gets out of the way:
16
+ *
17
+ * - default (`pointer`) — a few lines saying skills exist and HOW to find one:
18
+ * the `skill` tool (list / load) and the capability search (`tool_search`,
19
+ * whose hits include `kind:"skill"` capabilities). Near-zero prompt cost,
20
+ * no false positives, no maintenance.
21
+ * - `catalog` / `names` (OPT-IN) — the full name+description catalog, or the
22
+ * names-only list, for a user who wants everything in-context.
23
+ * - `off` — inject nothing.
24
+ *
25
+ * The old default was the ~24.5K-char catalog, which buried the task on every
26
+ * turn (3.3.11 regression, see tests/release/agent-contracts.test.ts); the
27
+ * pointer keeps the small-prompt property while still being model-driven.
28
+ *
29
+ * The pipeline arm consumes the SAME catalog builder (see the orchestrator's
30
+ * `skillCatalog` injection): the planner is a model too, so it is handed the
31
+ * list instead of a keyword-selected skill.
32
+ *
33
+ * Best-effort by construction: any store/catalog failure returns '' and the turn
34
+ * proceeds byte-identically (a hint must never break a turn).
190
35
  */
191
- const GENERIC_SKILL_TAGS = new Set([
192
- 'planning', 'roadmap', 'assessment', 'audit', 'quality', 'review',
193
- 'analysis', 'process', 'workflow', 'recommendations', 'gaps', 'strategy',
194
- 'methodology', 'checklist', 'template', 'guide', 'framework', 'report',
195
- // C4 — `packaging` is how work is DELIVERED, not a domain. Measured live
196
- // (2026-10-02): the goal "Fix the macOS hotkey permission and packaging
197
- // defects … changing app behavior" matched `electron-app` on its `packaging`
198
- // tag ALONE and injected Electron methodology into a PyQt6 bundle fix. The
199
- // skill's real domain (`electron`) is unaffected: a goal that actually names
200
- // Electron still matches on the name word.
201
- 'packaging',
202
- ]);
203
- /** Cap on hub SKILL.md body text injected into the prompt (chars). */
204
- const HUB_BODY_CAP = 2000;
205
- /** Cap on compiled methodology steps injected into the prompt. */
206
- const COMPILED_STEP_CAP = 8;
207
36
  /** Cap on any single description line (chars). */
208
37
  const LINE_CAP = 400;
209
- /** The skills.disabled[] gate: a disabled skill is never injected. */
38
+ function cap(text, max = LINE_CAP) {
39
+ const t = text.trim();
40
+ return t.length > max ? t.slice(0, max - 1) + '…' : t;
41
+ }
42
+ /** The skills.disabled[] gate: a disabled skill is never listed. */
210
43
  function isDisabled(id, cm) {
211
44
  try {
212
45
  const cfg = cm?.getAll?.();
@@ -214,332 +47,94 @@ function isDisabled(id, cm) {
214
47
  return Array.isArray(disabled) && disabled.includes(id);
215
48
  }
216
49
  catch {
217
- return false; // config failure must not block matching (the injection is advisory)
218
- }
219
- }
220
- /**
221
- * HOST/PLATFORM names — where something runs, not what the user wants done.
222
- *
223
- * Observed live (2026-09-21): the goal "…a multiple screen calculator and unit
224
- * converter, it should be GUI and cross platform for Windows and Linux"
225
- * activated `wsl-setup` (tags `wsl, windows, linux, development, gpu`) and
226
- * injected its WSL/Distro/GPU-passthrough methodology into a Flutter app plan.
227
- * Both tag hits and both pattern hits came from the platform names alone:
228
- * "Windows" and "Linux" were read as intent to configure the machine they run
229
- * on. A target platform is a CONSTRAINT on the work, never evidence for a
230
- * methodology, so these words contribute no evidence anywhere in this file.
231
- *
232
- * Deliberately narrow — only HOSTS. Tooling and cloud domains stay evidence
233
- * (`docker`, `kubernetes`, `aws`, `postgres`, `redis`, …): "deploy to AWS" IS
234
- * a request for deployment methodology, while "cross platform for Windows" is
235
- * not a request for WSL setup.
236
- */
237
- const PLATFORM_HOST_NAMES = new Set([
238
- 'windows', 'win32', 'win64', 'windows10', 'windows11',
239
- 'linux', 'unix', 'gnu', 'ubuntu', 'debian', 'fedora', 'centos', 'rhel',
240
- 'alpine', 'arch', 'suse', 'freebsd', 'openbsd',
241
- 'macos', 'macosx', 'mac', 'osx', 'darwin', 'apple',
242
- 'android', 'ios', 'ipados', 'watchos', 'tvos',
243
- 'wsl', 'wsl2', 'cygwin', 'mingw', 'msys',
244
- 'crossplatform', 'cross-platform',
245
- 'x64', 'x86', 'arm64', 'aarch64', 'amd64',
246
- ]);
247
- /** Is this token a host/platform name (never goal evidence)? */
248
- export function isPlatformName(word) {
249
- return PLATFORM_HOST_NAMES.has(word.trim().toLowerCase());
250
- }
251
- /**
252
- * Did the goal show REAL evidence for this skill — a name-word hit, a tag hit,
253
- * or two DISTINCT pattern/description words (meta-words and platform names
254
- * excluded)? Guards the compiled store's intentionally loose threshold:
255
- * findMatch adds a quality/usage bonus to every skill, so a generic word like
256
- * "goal" alone must never inject methodology into a chat turn.
257
- *
258
- * Also the HUB path's only filter: `findHubSkillMatch` scores name words and
259
- * DESCRIPTION keywords and returns the top scorer with no evidence gate at all,
260
- * so an installed skill whose description merely names the target platform
261
- * scored on that alone. A hub match carries no tags/goalPattern, so its
262
- * description words are the pattern-level evidence (the caller passes it here).
263
- *
264
- * MATCHING IS BY WHOLE WORD, never substring. `q.includes(word)` matched
265
- * "kill" inside "s**kill**" — measured: `feature-flags` (goalPattern “…kill
266
- * switch…”) matched "no **skill** covers alpaca husbandry whatsoever", and the
267
- * same class makes `mac` match "machine" and `arch` match "search". The goal is
268
- * tokenized once into a word set and skills are matched against tokens.
269
- *
270
- * Deterministic, no LLM.
271
- */
272
- export function hasRealGoalEvidence(goal, skill) {
273
- const tokens = wordSet(goal);
274
- if (tokens.size === 0)
275
- return false;
276
- let nameHits = 0;
277
- for (const word of skill.name.toLowerCase().split(/[^a-z0-9]+/)) {
278
- if (word.length <= 3 || isPlatformName(word) || !tokens.has(word))
279
- continue;
280
- // A GENERIC name word (see GENERIC_SKILL_NAME_WORDS) is evidence only when
281
- // the goal uses it as the action, not as a compound-noun modifier. A
282
- // count alone did the wrong thing: the single word `test` in "blood test
283
- // report" cleared `nameHits >= 1` and activated the software-testing
284
- // skill on a lab-report turn. `please test the project` still counts (a
285
- // verb use), and `run the unit tests` counts below via its domain words.
286
- if (isDemotedGenericUse(goal, word))
287
- continue;
288
- nameHits++;
289
- }
290
- let tagHits = 0;
291
- for (const tag of skill.tags ?? []) {
292
- const t = tag.toLowerCase().trim();
293
- // Generic process vocabulary is not goal evidence (see GENERIC_SKILL_TAGS),
294
- // and a generic word used only as a noun modifier is not either.
295
- if (t.length > 3 && !GENERIC_SKILL_TAGS.has(t) && !isPlatformName(t) && !isDemotedGenericUse(goal, t) && tokens.has(t))
296
- tagHits++;
50
+ return false; // config failure must not block discovery (the hint is advisory)
297
51
  }
298
- // Pattern-level evidence: the skill's own goalPattern words, plus (for a hub
299
- // skill, which has no goalPattern) its description keywords. Two DISTINCT
300
- // domain words are required — one shared word is not enough to inject a
301
- // whole methodology into a turn.
302
- //
303
- // DISTINCT is the whole point, and a plain counter got it wrong: the evidence
304
- // text is `goalPattern + description`, so ONE word that a skill repeats in
305
- // both fields counted twice and satisfied the "two words" rule on its own.
306
- // Measured live (2026-09-21): "Create a book which teaches math's division
307
- // for class 4 student" activated `game-development`, whose ONLY overlap is
308
- // the word `create` — present in its goalPattern (`game create build …`) and
309
- // again in its description ("Use when the goal asks to create, build, or
310
- // develop a game"). `create` is also a generic action verb, so the match was
311
- // noise in both senses.
312
- const patternHits = new Set();
313
- const evidenceText = `${skill.goalPattern ?? ''} ${skill.description ?? ''}`;
314
- for (const word of evidenceText.toLowerCase().split(/[^a-z0-9]+/)) {
315
- const w = word.trim();
316
- if (w.length > 3 && !PATTERN_STOPWORDS.has(w) && !GENERIC_SKILL_TAGS.has(w) && !isPlatformName(w) && !isDemotedGenericUse(goal, w) && tokens.has(w)) {
317
- patternHits.add(w);
318
- }
319
- }
320
- return nameHits >= 1 || tagHits >= 1 || patternHits.size >= 2;
321
- }
322
- /** Whole-word token set for a goal (word-boundary matching, never substring). */
323
- function wordSet(text) {
324
- return new Set((text || '')
325
- .toLowerCase()
326
- .split(/[^a-z0-9]+/)
327
- .filter((w) => w.length > 0));
328
- }
329
- /**
330
- * THE skill-activation gate — the single decision every injection path makes.
331
- *
332
- * Composes (1) the website-deploy activation rule: website methodology needs
333
- * HOSTING intent, so a generic "deploy the API" goal never gets it; and (2) the
334
- * evidence rule above.
335
- *
336
- * Before this existed the gate was implemented three times with different
337
- * strength: the chat/execute loop applied the evidence filter to COMPILED
338
- * matches but trusted hub matches raw, and the ORCHESTRATOR applied neither
339
- * (only the website-deploy rule) — so the pipeline was the most exposed
340
- * surface. One predicate, consumed by all of them.
341
- */
342
- export function isSkillActivated(goal, skill) {
343
- const label = `${skill.id ?? ''} ${skill.name}`;
344
- if (WEBSITE_DEPLOY_ID.test(label) && !HOSTING_INTENT.test(goal))
345
- return false;
346
- return hasRealGoalEvidence(goal, skill);
347
52
  }
348
53
  /**
349
- * Find the best skill for the goal across BOTH sources the orchestrator
350
- * consults, honoring the disabled + website-deploy activation gates (+ the
351
- * compiled evidence filter). Compiled wins ties (its id is the deterministic
352
- * seed id). Returns null when nothing matches (never a forced match).
54
+ * Every skill the model may pick from — compiled first-party + installed hub
55
+ * (SKILL.md) skills, deduped by name, with the disabled gate applied. Best-effort:
56
+ * a store/catalog failure contributes nothing rather than throwing.
353
57
  */
354
- export async function findLoopSkillMatch(goal, cm) {
355
- const q = (goal || '').trim();
356
- if (!q)
357
- return null;
358
- // 1. Compiled store (the first-party capability batch).
58
+ export async function collectSkillEntries(cm) {
59
+ const entries = [];
359
60
  try {
360
61
  const { getSkillStore } = await import('../learning/skill-store.js');
361
- const match = getSkillStore().findMatch(q);
362
- if (match && !isDisabled(match.id, cm) && isSkillActivated(q, match)) {
363
- return { name: match.name, id: match.id, source: 'compiled' };
62
+ for (const skill of getSkillStore().getAll()) {
63
+ if (isDisabled(skill.id, cm))
64
+ continue;
65
+ entries.push({ name: skill.name, description: skill.description ?? '' });
364
66
  }
365
67
  }
366
68
  catch {
367
- // Fall through to the hub catalog — a store failure must not block it.
69
+ // Best-effort — a store failure must not remove the hub half.
368
70
  }
369
- // 2. Hub catalog (installed SKILL.md skills — first-class runtime
370
- // capabilities; a fresh `nuvira skills install` is matchable with zero
371
- // recompilation, exactly like the orchestrator's fallback path).
372
- //
373
- // Its scoring is NOT evidence: `findHubSkillMatch` counts name words and
374
- // DESCRIPTION keywords and returns the top scorer, so a skill whose
375
- // description merely names the target platform ("…a Linux development
376
- // environment on Windows") scored on those two words alone. The same
377
- // evidence gate the compiled path uses is applied here now.
378
71
  try {
379
- const { findHubSkillMatch } = await import('../learning/hub-skill-catalog.js');
380
- const hub = findHubSkillMatch(q, cm);
381
- // A hub match carries only id/name/description — its description words are
382
- // the pattern-level evidence — and the platform/word-boundary rules above
383
- // decide. A skill named `wsl-setup` therefore needs actual domain words
384
- // (networking, development, subsystem), not merely the platforms it targets.
385
- if (hub && !isDisabled(hub.id, cm) && isSkillActivated(q, hub)) {
386
- return { name: hub.name, id: hub.id, source: 'hub' };
72
+ const { listMatchableHubSkills } = await import('../learning/hub-skill-catalog.js');
73
+ for (const skill of listMatchableHubSkills(cm)) {
74
+ if (isDisabled(skill.id, cm))
75
+ continue;
76
+ if (entries.some((e) => e.name === skill.name))
77
+ continue;
78
+ entries.push({ name: skill.name, description: skill.description ?? '' });
387
79
  }
388
80
  }
389
81
  catch {
390
- // Best-effort — a catalog failure leaves no hint.
391
- }
392
- return null;
393
- }
394
- /**
395
- * Bounded, side-effect-free methodology text for a compiled skill (the full
396
- * Skill shape is fetched via the public get(); step descriptions carry the
397
- * Level-2 methodology). Deliberately NOT store.skillView() — that marks the
398
- * skill used as a side effect and renders reference-doc/quality sections the
399
- * prompt block does not need.
400
- */
401
- function formatCompiledMethodology(skill) {
402
- const lines = [];
403
- if (skill.description)
404
- lines.push(cap(skill.description));
405
- if (skill.parameters.length > 0) {
406
- lines.push('Parameters: ' +
407
- skill.parameters
408
- .map((p) => `${p.name}${p.required ? '' : ' (optional)'}`)
409
- .join(', '));
410
- }
411
- const steps = skill.steps.slice(0, COMPILED_STEP_CAP);
412
- steps.forEach((s, i) => {
413
- lines.push(`Step ${i + 1} [${s.agentType}]: ${cap(s.description)}`);
414
- });
415
- if (skill.steps.length > steps.length) {
416
- lines.push(`(+${skill.steps.length - steps.length} more steps — load the skill for the full methodology)`);
82
+ // Best-effort — a catalog failure leaves the compiled half.
417
83
  }
418
- return lines.join('\n');
84
+ return entries;
419
85
  }
420
- function cap(text, max = LINE_CAP) {
421
- const t = text.trim();
422
- return t.length > max ? t.slice(0, max - 1) + '…' : t;
86
+ function loadTail(loadHint) {
87
+ return loadHint === 'skill-view'
88
+ ? 'Name the skill in the step that needs it; the writer agent can call skill_view(name) to load its full methodology.'
89
+ : 'Load one with the skill tool, e.g. {"skill":"<name>"} (or call it with no name to list every skill).';
423
90
  }
424
91
  /**
425
- * Build the system-prompt block for a matched skill, or '' when there is no
426
- * match. The block follows the orchestrator's injection contract:
92
+ * The DEFAULT hint — a bounded discovery pointer, not a recommendation.
427
93
  *
428
- * - the skill is a RECOMMENDATION, the model still owns the plan (the
429
- * orchestrator's "model-selected activation" phrasing),
430
- * - the methodology rides in as Level-2 content (progressive disclosure —
431
- * the model sees the steps without paying a tool call for them),
432
- * - the exact load syntax is included so the model can refresh/parameterize
433
- * via the `skill` tool mid-turn,
434
- * - ONE block max (bounded system-prompt growth).
435
- *
436
- * Marks nothing: usage tracking belongs to markLoopSkillUsed (the caller
437
- * decides when a match actually got USED — i.e. was injected).
438
- *
439
- * @param goal the user's goal text (matched against skill triggers)
440
- * @param cm ConfigManager for the disabled-skills gate (optional)
441
- * @param injected out-param: when provided, receives the match that was
442
- * injected (null when none).
94
+ * It names the two model-driven paths to a skill (the `skill` tool and the
95
+ * capability search) and leaves the decision with the model. Returns '' when
96
+ * there are no skills to discover (nothing to say — never a forced hint).
443
97
  */
444
- export async function buildLoopSkillHint(goal, cm, injected) {
445
- const match = await findLoopSkillMatch(goal, cm).catch(() => null);
446
- if (injected)
447
- injected.value = match;
448
- if (!match)
98
+ export async function buildSkillPointerHint(cm, loadHint = 'skill-tool') {
99
+ const entries = await collectSkillEntries(cm);
100
+ if (entries.length === 0)
449
101
  return '';
450
- // Full methodology (Level 2). Compiled: the stored Skill (steps carry the
451
- // methodology). Hub: the SKILL.md body.
452
- let methodology = '';
453
- if (match.source === 'hub') {
454
- try {
455
- const { findHubSkillMatch } = await import('../learning/hub-skill-catalog.js');
456
- methodology = cap(findHubSkillMatch(goal, cm)?.body ?? '', HUB_BODY_CAP);
457
- }
458
- catch {
459
- methodology = '';
460
- }
461
- }
462
- else {
463
- try {
464
- const { getSkillStore } = await import('../learning/skill-store.js');
465
- methodology = formatCompiledMethodology(getSkillStore().get(match.id));
466
- }
467
- catch {
468
- methodology = '';
469
- }
470
- }
471
- const lines = [
102
+ return [
472
103
  '',
473
- '## Matched skill',
474
- `A first-party skill matches this goal: **${match.name}** (${match.source} skill, id ${match.id}).`,
475
- 'This is a RECOMMENDATION — follow it when it fits the request; ignore it when it does not (you still own the plan).',
476
- ];
477
- if (methodology) {
478
- lines.push('', 'Its methodology:', '', methodology);
479
- }
480
- lines.push('', `To (re)load it with parameters mid-turn, call the skill tool with {"skill":"${match.name}"}.`);
481
- return lines.join('\n');
104
+ '## Skills',
105
+ `${entries.length} reusable capability packs (skills) are available. Decide from the task itself whether one applies — do not guess:`,
106
+ ' - call the skill tool with no name to list every skill, or',
107
+ ' - call tool_search with a query describing this task; skills come back as capabilities (kind "skill").',
108
+ loadTail(loadHint),
109
+ 'If none applies, ignore this and proceed.',
110
+ ].join('\n');
482
111
  }
483
112
  /**
484
- * A bounded CATALOG of available skills for the system prompt — the model-facing
485
- * replacement for keyword auto-injection.
486
- *
487
- * WHY THIS REPLACES THE MATCHER: a word list cannot decide whether "blood test
488
- * report" is software testing, and every stopword added to force it right made
489
- * some real match wrong. The model can read the same catalog and judge instantly,
490
- * so the fix is to STOP deciding in code and hand the model the list: name + a
491
- * one-line description each, plus the exact `skill` tool syntax to load one. This
492
- * scales to infinite permutations with no maintenance and no false positives —
493
- * the model loads a skill only when it actually applies.
113
+ * The bounded CATALOG of available skills for the system prompt — the model-facing
114
+ * discovery surface, read straight through.
494
115
  *
495
116
  * Bounded deliberately: descriptions are capped and the list is capped, so a
496
- * crowded catalog cannot balloon the system prompt. Returns '' when there are no
497
- * skills (nothing to say) — never a forced recommendation.
117
+ * crowded catalog cannot balloon the prompt. Returns '' when there are no skills.
498
118
  *
499
119
  * @param cm ConfigManager (honors skills.disabled — a disabled skill is
500
120
  * never listed, the same gate the tool enforces)
501
121
  * @param opts caps: maxSkills (default 200 — the full bundled+hub catalog,
502
122
  * so NO skill is dropped from the model's view; missing a skill
503
123
  * is the failure this design exists to avoid), descriptionChars
504
- * (default 140)
124
+ * (default 140), namesOnly (default false), loadHint
505
125
  */
506
126
  export async function buildSkillCatalogHint(cm, opts = {}) {
507
127
  const maxSkills = opts.maxSkills ?? 200;
508
128
  const descChars = opts.descriptionChars ?? 140;
509
129
  const namesOnly = opts.namesOnly === true;
510
- const entries = [];
511
- // Compiled first-party skills.
512
- try {
513
- const { getSkillStore } = await import('../learning/skill-store.js');
514
- for (const skill of getSkillStore().getAll()) {
515
- if (isDisabled(skill.id, cm))
516
- continue;
517
- entries.push({ name: skill.name, description: skill.description ?? '' });
518
- }
519
- }
520
- catch {
521
- // Best-effort — a store failure must not remove the hub half.
522
- }
523
- // Hub (installed SKILL.md) skills.
524
- try {
525
- const { listMatchableHubSkills } = await import('../learning/hub-skill-catalog.js');
526
- for (const skill of listMatchableHubSkills(cm)) {
527
- if (isDisabled(skill.id, cm))
528
- continue;
529
- if (entries.some((e) => e.name === skill.name))
530
- continue;
531
- entries.push({ name: skill.name, description: skill.description ?? '' });
532
- }
533
- }
534
- catch {
535
- // Best-effort — a catalog failure leaves the compiled half.
536
- }
130
+ const loadHint = opts.loadHint ?? 'skill-tool';
131
+ const entries = await collectSkillEntries(cm);
537
132
  if (entries.length === 0)
538
133
  return '';
539
134
  const shown = entries.slice(0, maxSkills);
540
135
  // `namesOnly` (mode `names`) drops the per-skill description: the model still
541
136
  // sees the whole catalog and can `skill` with no name to read the details, but
542
- // the prompt pays a fraction of the ~24K of a full description catalog.
137
+ // the prompt pays a fraction of the full description catalog.
543
138
  const lines = shown.map((e) => (namesOnly ? ` - ${e.name}` : ` - ${e.name}: ${cap(e.description, descChars)}`));
544
139
  const more = entries.length > shown.length ? `\n (+${entries.length - shown.length} more — call the skill tool with no name to list all)` : '';
545
140
  return [
@@ -547,31 +142,35 @@ export async function buildSkillCatalogHint(cm, opts = {}) {
547
142
  '## Available skills',
548
143
  namesOnly
549
144
  ? 'A first-party skill may fit this goal. These are NAMES only — call the skill tool with no name to read a skill\u2019s description, then load one ONLY when it genuinely applies (ignore the rest):'
550
- : 'A first-party skill may fit this goal. Read the list and decide — load one with the skill tool ONLY when it genuinely applies (ignore the rest):',
145
+ : 'A first-party skill may fit this goal. Read the list and decide — load one ONLY when it genuinely applies (ignore the rest):',
551
146
  ...lines,
552
147
  more,
553
148
  '',
554
- 'Load one with the skill tool, e.g. {"skill":"<name>"} (or call it with no name to list every skill).',
149
+ loadTail(loadHint),
555
150
  ].filter((l) => l !== undefined).join('\n');
556
151
  }
557
152
  /** The default. The catalog is ~24K chars — it must never be the default. */
558
- export const DEFAULT_SKILL_HINT_MODE = 'match';
153
+ export const DEFAULT_SKILL_HINT_MODE = 'pointer';
559
154
  /** Env names, `NUVIRA_*` first with the legacy `BUFF_*` alias accepted. */
560
155
  const SKILL_HINT_ENV_NAMES = ['NUVIRA_SKILL_CATALOG', 'BUFF_SKILL_CATALOG'];
561
156
  /**
562
157
  * Parse a raw value into a mode. Synonyms accepted so a typo cannot silently
563
158
  * change behaviour; null (unrecognized) falls through to the next source.
564
- * - match / keyword / auto / small / default → 'match'
565
- * - catalog / full / all / on / true / 1 → 'catalog'
566
- * - names / names-only / list / bare / titles → 'names'
567
- * - off / none / never / false / 0 → 'off'
159
+ * - pointer / match / keyword / auto / small / default → 'pointer'
160
+ * - catalog / full / all / on / true / 1 → 'catalog'
161
+ * - names / names-only / list / bare / titles → 'names'
162
+ * - off / none / never / false / 0 → 'off'
163
+ *
164
+ * `match`/`keyword` are kept as ACCEPTED SYNONYMS for back-compat (an existing
165
+ * `NUVIRA_SKILL_CATALOG=match` or `skills.catalogHint: "match"` still works) —
166
+ * they now mean the pointer, since there is no keyword matcher any more.
568
167
  */
569
168
  export function parseSkillHintMode(raw) {
570
169
  const v = String(raw ?? '').trim().toLowerCase();
571
170
  if (!v)
572
171
  return null;
573
- if (v === 'match' || v === 'keyword' || v === 'auto' || v === 'small' || v === 'default')
574
- return 'match';
172
+ if (v === 'pointer' || v === 'match' || v === 'keyword' || v === 'auto' || v === 'small' || v === 'default')
173
+ return 'pointer';
575
174
  if (v === 'catalog' || v === 'full' || v === 'all' || v === 'on' || v === 'true' || v === '1')
576
175
  return 'catalog';
577
176
  if (v === 'names' || v === 'names-only' || v === 'list' || v === 'bare' || v === 'titles')
@@ -583,15 +182,7 @@ export function parseSkillHintMode(raw) {
583
182
  /**
584
183
  * The effective skill-hint mode. Env first (`NUVIRA_SKILL_CATALOG`, then the
585
184
  * legacy `BUFF_*`), then `skills.catalogHint` in the config file, then the
586
- * default (`match`). Pure and never throws.
587
- *
588
- * WHY THIS EXISTS (2026-10-04). 3.3.11 replaced the keyword hint with the full
589
- * catalog unconditionally — measured live, `buildSkillCatalogHint()` returned
590
- * 24,543 chars on the goal "create mac od gui app", taking the chat system
591
- * prompt from 7,653 chars (3.3.10) to 32,809. That ~6.1K-token tax on EVERY
592
- * turn buried the task for weak/free-tier models and made 16K-token tiers
593
- * impossible (the prompt alone is ~8.2K). The catalog is a genuinely useful
594
- * discovery mechanism, but it must be CHOSEN, not imposed.
185
+ * default (`pointer`). Pure and never throws.
595
186
  */
596
187
  export function resolveSkillHintMode(cm) {
597
188
  for (const name of SKILL_HINT_ENV_NAMES) {
@@ -611,44 +202,27 @@ export function resolveSkillHintMode(cm) {
611
202
  return DEFAULT_SKILL_HINT_MODE;
612
203
  }
613
204
  /**
614
- * The skill hint for a goal, resolved through the configured mode. The ONE
615
- * entry point both chat and execute call, so the surface can never drift from
616
- * the policy:
205
+ * The skill hint, resolved through the configured mode — the ONE entry point
206
+ * both the chat/execute loop and the pipeline call, so a surface can never drift
207
+ * from the policy:
617
208
  * - `off` → ''
618
209
  * - `catalog` → the full name+description catalog ({@link buildSkillCatalogHint})
619
210
  * - `names` → the names-only catalog (no descriptions)
620
- * - `match` → the small keyword-matched hint ({@link buildLoopSkillHint})
211
+ * - `pointer` → the discovery pointer ({@link buildSkillPointerHint})
621
212
  *
622
- * `injected` is the same out-param `buildLoopSkillHint` takes (the match that
623
- * was injected, for usage marking) — left untouched in the catalog/names/off
624
- * modes, where no single skill was selected.
213
+ * `loadHint` lets the pipeline point its tail at skill_view (the writer's load
214
+ * path) instead of the loop's skill tool; it is ignored in the catalog modes'
215
+ * default wording and only affects the tail line.
625
216
  */
626
- export async function buildConfiguredSkillHint(goal, cm, injected) {
217
+ export async function buildConfiguredSkillHint(cm, opts = {}) {
627
218
  const mode = resolveSkillHintMode(cm);
219
+ const loadHint = opts.loadHint ?? 'skill-tool';
628
220
  if (mode === 'off')
629
221
  return '';
630
222
  if (mode === 'catalog')
631
- return buildSkillCatalogHint(cm);
223
+ return buildSkillCatalogHint(cm, { loadHint });
632
224
  if (mode === 'names')
633
- return buildSkillCatalogHint(cm, { namesOnly: true });
634
- return buildLoopSkillHint(goal, cm, injected);
635
- }
636
- /**
637
- * Mark an injected skill as used (usage tracking parity with the orchestrator
638
- * — compiled skills only; hub skills have no compiled usage counter). The
639
- * SINGLE usage marker for the loop hint path (the hint builder never marks).
640
- * Best-effort, fire-and-forget: never throws, never awaited by callers on the
641
- * hot path.
642
- */
643
- export async function markLoopSkillUsed(match) {
644
- if (!match || match.source !== 'compiled')
645
- return;
646
- try {
647
- const { getSkillStore } = await import('../learning/skill-store.js');
648
- getSkillStore().markUsed(match.id);
649
- }
650
- catch {
651
- // Best-effort.
652
- }
225
+ return buildSkillCatalogHint(cm, { namesOnly: true, loadHint });
226
+ return buildSkillPointerHint(cm, loadHint);
653
227
  }
654
228
  //# sourceMappingURL=loop-skill-hint.js.map