webmcp-cli 1.2.2 → 1.2.3

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 (330) hide show
  1. package/dist/analysis/form-to-tool-mapper.d.ts +61 -0
  2. package/dist/analysis/form-to-tool-mapper.js +360 -0
  3. package/dist/analysis/form-to-tool-mapper.js.map +1 -0
  4. package/dist/analysis/index.d.ts +84 -0
  5. package/dist/analysis/index.js +81 -0
  6. package/dist/analysis/index.js.map +1 -0
  7. package/dist/analysis/missing-tool-analyzer.d.ts +35 -0
  8. package/dist/analysis/missing-tool-analyzer.js +617 -0
  9. package/dist/analysis/missing-tool-analyzer.js.map +1 -0
  10. package/dist/audit/run-multi-page-audit.d.ts +34 -0
  11. package/dist/audit/run-multi-page-audit.js +233 -0
  12. package/dist/audit/run-multi-page-audit.js.map +1 -0
  13. package/dist/cli/commands/potential.d.ts +8 -0
  14. package/dist/cli/commands/potential.js +323 -0
  15. package/dist/cli/commands/potential.js.map +1 -0
  16. package/dist/cli/commands/report.d.ts +12 -0
  17. package/dist/cli/commands/report.js +89 -0
  18. package/dist/cli/commands/report.js.map +1 -0
  19. package/dist/cli/index.js +35 -0
  20. package/dist/cli/index.js.map +1 -1
  21. package/dist/config/defaults.d.ts +36 -0
  22. package/dist/config/defaults.js +33 -0
  23. package/dist/config/defaults.js.map +1 -0
  24. package/dist/config/index.d.ts +7 -0
  25. package/dist/config/index.js +7 -0
  26. package/dist/config/index.js.map +1 -0
  27. package/dist/config/loader.d.ts +22 -0
  28. package/dist/config/loader.js +91 -0
  29. package/dist/config/loader.js.map +1 -0
  30. package/dist/config/schema.d.ts +280 -0
  31. package/dist/config/schema.js +42 -0
  32. package/dist/config/schema.js.map +1 -0
  33. package/dist/core/types/audit.d.ts +1 -1
  34. package/dist/core/types/index.d.ts +1 -0
  35. package/dist/core/types/index.js +1 -0
  36. package/dist/core/types/index.js.map +1 -1
  37. package/dist/core/types/recon.d.ts +265 -0
  38. package/dist/core/types/recon.js +5 -0
  39. package/dist/core/types/recon.js.map +1 -0
  40. package/dist/core/types/rule.d.ts +1 -1
  41. package/dist/core/types/rule.js +7 -5
  42. package/dist/core/types/rule.js.map +1 -1
  43. package/dist/crawler/depth-crawler.d.ts +29 -0
  44. package/dist/crawler/depth-crawler.js +212 -0
  45. package/dist/crawler/depth-crawler.js.map +1 -0
  46. package/dist/crawler/index.d.ts +2 -0
  47. package/dist/crawler/index.js +3 -0
  48. package/dist/crawler/index.js.map +1 -0
  49. package/dist/crawler/link-extractor.d.ts +1 -0
  50. package/dist/crawler/link-extractor.js +49 -0
  51. package/dist/crawler/link-extractor.js.map +1 -0
  52. package/dist/generators/index.d.ts +10 -0
  53. package/dist/generators/index.js +8 -0
  54. package/dist/generators/index.js.map +1 -0
  55. package/dist/generators/report-html.d.ts +12 -0
  56. package/dist/generators/report-html.js +470 -0
  57. package/dist/generators/report-html.js.map +1 -0
  58. package/dist/generators/report-json.d.ts +95 -0
  59. package/dist/generators/report-json.js +144 -0
  60. package/dist/generators/report-json.js.map +1 -0
  61. package/dist/generators/report-manager.d.ts +31 -0
  62. package/dist/generators/report-manager.js +208 -0
  63. package/dist/generators/report-manager.js.map +1 -0
  64. package/dist/generators/tool-code-generator.d.ts +31 -0
  65. package/dist/generators/tool-code-generator.js +201 -0
  66. package/dist/generators/tool-code-generator.js.map +1 -0
  67. package/dist/potential/ai-recommender.d.ts +33 -0
  68. package/dist/potential/ai-recommender.js +414 -0
  69. package/dist/potential/ai-recommender.js.map +1 -0
  70. package/dist/potential/analyzer.d.ts +32 -0
  71. package/dist/potential/analyzer.js +383 -0
  72. package/dist/potential/analyzer.js.map +1 -0
  73. package/dist/potential/index.d.ts +3 -0
  74. package/dist/potential/index.js +4 -0
  75. package/dist/potential/index.js.map +1 -0
  76. package/dist/potential/prompts.d.ts +20 -0
  77. package/dist/potential/prompts.js +42 -0
  78. package/dist/potential/prompts.js.map +1 -0
  79. package/dist/potential/types.d.ts +40 -0
  80. package/dist/potential/types.js +2 -0
  81. package/dist/potential/types.js.map +1 -0
  82. package/dist/recon/index.d.ts +20 -0
  83. package/dist/recon/index.js +143 -0
  84. package/dist/recon/index.js.map +1 -0
  85. package/dist/recon/manifest.d.ts +16 -0
  86. package/dist/recon/manifest.js +108 -0
  87. package/dist/recon/manifest.js.map +1 -0
  88. package/dist/recon/meta-extractor.d.ts +11 -0
  89. package/dist/recon/meta-extractor.js +276 -0
  90. package/dist/recon/meta-extractor.js.map +1 -0
  91. package/dist/recon/robots.d.ts +16 -0
  92. package/dist/recon/robots.js +158 -0
  93. package/dist/recon/robots.js.map +1 -0
  94. package/dist/recon/route-discovery.d.ts +25 -0
  95. package/dist/recon/route-discovery.js +303 -0
  96. package/dist/recon/route-discovery.js.map +1 -0
  97. package/dist/recon/sitemap.d.ts +12 -0
  98. package/dist/recon/sitemap.js +177 -0
  99. package/dist/recon/sitemap.js.map +1 -0
  100. package/dist/rules/accessibility/AXE-001.d.ts +9 -0
  101. package/dist/rules/accessibility/AXE-001.js +109 -0
  102. package/dist/rules/accessibility/AXE-001.js.map +1 -0
  103. package/dist/rules/accessibility/AXE-002.d.ts +8 -0
  104. package/dist/rules/accessibility/AXE-002.js +85 -0
  105. package/dist/rules/accessibility/AXE-002.js.map +1 -0
  106. package/dist/rules/accessibility/AXE-003.d.ts +8 -0
  107. package/dist/rules/accessibility/AXE-003.js +94 -0
  108. package/dist/rules/accessibility/AXE-003.js.map +1 -0
  109. package/dist/rules/accessibility/AXE-004.d.ts +8 -0
  110. package/dist/rules/accessibility/AXE-004.js +101 -0
  111. package/dist/rules/accessibility/AXE-004.js.map +1 -0
  112. package/dist/rules/accessibility/AXE-005.d.ts +9 -0
  113. package/dist/rules/accessibility/AXE-005.js +89 -0
  114. package/dist/rules/accessibility/AXE-005.js.map +1 -0
  115. package/dist/rules/best-practices/BP-004.d.ts +9 -0
  116. package/dist/rules/best-practices/BP-004.js +96 -0
  117. package/dist/rules/best-practices/BP-004.js.map +1 -0
  118. package/dist/rules/best-practices/BP-005.d.ts +8 -0
  119. package/dist/rules/best-practices/BP-005.js +94 -0
  120. package/dist/rules/best-practices/BP-005.js.map +1 -0
  121. package/dist/rules/best-practices/BP-006.d.ts +8 -0
  122. package/dist/rules/best-practices/BP-006.js +80 -0
  123. package/dist/rules/best-practices/BP-006.js.map +1 -0
  124. package/dist/rules/best-practices/BP-007.d.ts +8 -0
  125. package/dist/rules/best-practices/BP-007.js +92 -0
  126. package/dist/rules/best-practices/BP-007.js.map +1 -0
  127. package/dist/rules/best-practices/BP-008.d.ts +12 -0
  128. package/dist/rules/best-practices/BP-008.js +86 -0
  129. package/dist/rules/best-practices/BP-008.js.map +1 -0
  130. package/dist/rules/best-practices/BP-009.d.ts +9 -0
  131. package/dist/rules/best-practices/BP-009.js +77 -0
  132. package/dist/rules/best-practices/BP-009.js.map +1 -0
  133. package/dist/rules/best-practices/BP-010.d.ts +8 -0
  134. package/dist/rules/best-practices/BP-010.js +85 -0
  135. package/dist/rules/best-practices/BP-010.js.map +1 -0
  136. package/dist/rules/coverage/COV-002.d.ts +8 -0
  137. package/dist/rules/coverage/COV-002.js +68 -0
  138. package/dist/rules/coverage/COV-002.js.map +1 -0
  139. package/dist/rules/coverage/COV-003.d.ts +8 -0
  140. package/dist/rules/coverage/COV-003.js +68 -0
  141. package/dist/rules/coverage/COV-003.js.map +1 -0
  142. package/dist/rules/coverage/COV-004.d.ts +8 -0
  143. package/dist/rules/coverage/COV-004.js +89 -0
  144. package/dist/rules/coverage/COV-004.js.map +1 -0
  145. package/dist/rules/coverage/COV-005.d.ts +8 -0
  146. package/dist/rules/coverage/COV-005.js +67 -0
  147. package/dist/rules/coverage/COV-005.js.map +1 -0
  148. package/dist/rules/coverage/COV-006.d.ts +9 -0
  149. package/dist/rules/coverage/COV-006.js +76 -0
  150. package/dist/rules/coverage/COV-006.js.map +1 -0
  151. package/dist/rules/coverage/COV-007.d.ts +8 -0
  152. package/dist/rules/coverage/COV-007.js +67 -0
  153. package/dist/rules/coverage/COV-007.js.map +1 -0
  154. package/dist/rules/coverage/COV-008.d.ts +9 -0
  155. package/dist/rules/coverage/COV-008.js +87 -0
  156. package/dist/rules/coverage/COV-008.js.map +1 -0
  157. package/dist/rules/coverage/COV-009.d.ts +8 -0
  158. package/dist/rules/coverage/COV-009.js +73 -0
  159. package/dist/rules/coverage/COV-009.js.map +1 -0
  160. package/dist/rules/coverage/COV-010.d.ts +9 -0
  161. package/dist/rules/coverage/COV-010.js +82 -0
  162. package/dist/rules/coverage/COV-010.js.map +1 -0
  163. package/dist/rules/description/DESC-001.d.ts +9 -0
  164. package/dist/rules/description/DESC-001.js +88 -0
  165. package/dist/rules/description/DESC-001.js.map +1 -0
  166. package/dist/rules/description/DESC-002.d.ts +10 -0
  167. package/dist/rules/description/DESC-002.js +99 -0
  168. package/dist/rules/description/DESC-002.js.map +1 -0
  169. package/dist/rules/description/DESC-006.d.ts +9 -0
  170. package/dist/rules/description/DESC-006.js +78 -0
  171. package/dist/rules/description/DESC-006.js.map +1 -0
  172. package/dist/rules/description/DESC-007.d.ts +9 -0
  173. package/dist/rules/description/DESC-007.js +70 -0
  174. package/dist/rules/description/DESC-007.js.map +1 -0
  175. package/dist/rules/description/DESC-008.d.ts +9 -0
  176. package/dist/rules/description/DESC-008.js +70 -0
  177. package/dist/rules/description/DESC-008.js.map +1 -0
  178. package/dist/rules/description/DESC-009.d.ts +8 -0
  179. package/dist/rules/description/DESC-009.js +55 -0
  180. package/dist/rules/description/DESC-009.js.map +1 -0
  181. package/dist/rules/description/DESC-010.d.ts +9 -0
  182. package/dist/rules/description/DESC-010.js +92 -0
  183. package/dist/rules/description/DESC-010.js.map +1 -0
  184. package/dist/rules/description/DESC-011.d.ts +9 -0
  185. package/dist/rules/description/DESC-011.js +81 -0
  186. package/dist/rules/description/DESC-011.js.map +1 -0
  187. package/dist/rules/description/DESC-012.d.ts +9 -0
  188. package/dist/rules/description/DESC-012.js +98 -0
  189. package/dist/rules/description/DESC-012.js.map +1 -0
  190. package/dist/rules/implementation/IMP-002.d.ts +9 -0
  191. package/dist/rules/implementation/IMP-002.js +59 -0
  192. package/dist/rules/implementation/IMP-002.js.map +1 -0
  193. package/dist/rules/implementation/IMP-006.d.ts +9 -0
  194. package/dist/rules/implementation/IMP-006.js +48 -0
  195. package/dist/rules/implementation/IMP-006.js.map +1 -0
  196. package/dist/rules/implementation/IMP-008.d.ts +9 -0
  197. package/dist/rules/implementation/IMP-008.js +46 -0
  198. package/dist/rules/implementation/IMP-008.js.map +1 -0
  199. package/dist/rules/implementation/IMP-009.d.ts +9 -0
  200. package/dist/rules/implementation/IMP-009.js +48 -0
  201. package/dist/rules/implementation/IMP-009.js.map +1 -0
  202. package/dist/rules/implementation/IMP-010.d.ts +9 -0
  203. package/dist/rules/implementation/IMP-010.js +66 -0
  204. package/dist/rules/implementation/IMP-010.js.map +1 -0
  205. package/dist/rules/implementation/IMP-011.d.ts +9 -0
  206. package/dist/rules/implementation/IMP-011.js +82 -0
  207. package/dist/rules/implementation/IMP-011.js.map +1 -0
  208. package/dist/rules/implementation/IMP-012.d.ts +9 -0
  209. package/dist/rules/implementation/IMP-012.js +88 -0
  210. package/dist/rules/implementation/IMP-012.js.map +1 -0
  211. package/dist/rules/implementation/IMP-014.d.ts +9 -0
  212. package/dist/rules/implementation/IMP-014.js +58 -0
  213. package/dist/rules/implementation/IMP-014.js.map +1 -0
  214. package/dist/rules/implementation/IMP-015.d.ts +9 -0
  215. package/dist/rules/implementation/IMP-015.js +64 -0
  216. package/dist/rules/implementation/IMP-015.js.map +1 -0
  217. package/dist/rules/implementation/IMP-016.d.ts +9 -0
  218. package/dist/rules/implementation/IMP-016.js +52 -0
  219. package/dist/rules/implementation/IMP-016.js.map +1 -0
  220. package/dist/rules/implementation/IMP-017.d.ts +8 -0
  221. package/dist/rules/implementation/IMP-017.js +51 -0
  222. package/dist/rules/implementation/IMP-017.js.map +1 -0
  223. package/dist/rules/implementation/IMP-018.d.ts +8 -0
  224. package/dist/rules/implementation/IMP-018.js +52 -0
  225. package/dist/rules/implementation/IMP-018.js.map +1 -0
  226. package/dist/rules/implementation/IMP-019.d.ts +8 -0
  227. package/dist/rules/implementation/IMP-019.js +53 -0
  228. package/dist/rules/implementation/IMP-019.js.map +1 -0
  229. package/dist/rules/implementation/IMP-020.d.ts +9 -0
  230. package/dist/rules/implementation/IMP-020.js +62 -0
  231. package/dist/rules/implementation/IMP-020.js.map +1 -0
  232. package/dist/rules/implementation/IMP-021.d.ts +8 -0
  233. package/dist/rules/implementation/IMP-021.js +64 -0
  234. package/dist/rules/implementation/IMP-021.js.map +1 -0
  235. package/dist/rules/implementation/IMP-022.d.ts +8 -0
  236. package/dist/rules/implementation/IMP-022.js +70 -0
  237. package/dist/rules/implementation/IMP-022.js.map +1 -0
  238. package/dist/rules/index.d.ts +73 -6
  239. package/dist/rules/index.js +141 -6
  240. package/dist/rules/index.js.map +1 -1
  241. package/dist/rules/schema/SCHEMA-004.d.ts +9 -0
  242. package/dist/rules/schema/SCHEMA-004.js +57 -0
  243. package/dist/rules/schema/SCHEMA-004.js.map +1 -0
  244. package/dist/rules/schema/SCHEMA-005.d.ts +9 -0
  245. package/dist/rules/schema/SCHEMA-005.js +61 -0
  246. package/dist/rules/schema/SCHEMA-005.js.map +1 -0
  247. package/dist/rules/schema/SCHEMA-006.d.ts +10 -0
  248. package/dist/rules/schema/SCHEMA-006.js +85 -0
  249. package/dist/rules/schema/SCHEMA-006.js.map +1 -0
  250. package/dist/rules/schema/SCHEMA-007.d.ts +9 -0
  251. package/dist/rules/schema/SCHEMA-007.js +73 -0
  252. package/dist/rules/schema/SCHEMA-007.js.map +1 -0
  253. package/dist/rules/schema/SCHEMA-008.d.ts +9 -0
  254. package/dist/rules/schema/SCHEMA-008.js +70 -0
  255. package/dist/rules/schema/SCHEMA-008.js.map +1 -0
  256. package/dist/rules/schema/SCHEMA-009.d.ts +10 -0
  257. package/dist/rules/schema/SCHEMA-009.js +80 -0
  258. package/dist/rules/schema/SCHEMA-009.js.map +1 -0
  259. package/dist/rules/schema/SCHEMA-010.d.ts +9 -0
  260. package/dist/rules/schema/SCHEMA-010.js +96 -0
  261. package/dist/rules/schema/SCHEMA-010.js.map +1 -0
  262. package/dist/rules/schema/SCHEMA-012.d.ts +9 -0
  263. package/dist/rules/schema/SCHEMA-012.js +65 -0
  264. package/dist/rules/schema/SCHEMA-012.js.map +1 -0
  265. package/dist/rules/security/SEC-002.d.ts +8 -0
  266. package/dist/rules/security/SEC-002.js +81 -0
  267. package/dist/rules/security/SEC-002.js.map +1 -0
  268. package/dist/rules/security/SEC-003.d.ts +8 -0
  269. package/dist/rules/security/SEC-003.js +85 -0
  270. package/dist/rules/security/SEC-003.js.map +1 -0
  271. package/dist/rules/security/SEC-004.d.ts +9 -0
  272. package/dist/rules/security/SEC-004.js +87 -0
  273. package/dist/rules/security/SEC-004.js.map +1 -0
  274. package/dist/rules/security/SEC-005.d.ts +8 -0
  275. package/dist/rules/security/SEC-005.js +87 -0
  276. package/dist/rules/security/SEC-005.js.map +1 -0
  277. package/dist/rules/security/SEC-006.d.ts +10 -0
  278. package/dist/rules/security/SEC-006.js +108 -0
  279. package/dist/rules/security/SEC-006.js.map +1 -0
  280. package/dist/rules/security/SEC-007.d.ts +9 -0
  281. package/dist/rules/security/SEC-007.js +108 -0
  282. package/dist/rules/security/SEC-007.js.map +1 -0
  283. package/dist/rules/security/SEC-008.d.ts +8 -0
  284. package/dist/rules/security/SEC-008.js +109 -0
  285. package/dist/rules/security/SEC-008.js.map +1 -0
  286. package/dist/rules/security/SEC-009.d.ts +9 -0
  287. package/dist/rules/security/SEC-009.js +93 -0
  288. package/dist/rules/security/SEC-009.js.map +1 -0
  289. package/dist/rules/security/SEC-010.d.ts +8 -0
  290. package/dist/rules/security/SEC-010.js +78 -0
  291. package/dist/rules/security/SEC-010.js.map +1 -0
  292. package/dist/rules/security/SEC-011.d.ts +8 -0
  293. package/dist/rules/security/SEC-011.js +93 -0
  294. package/dist/rules/security/SEC-011.js.map +1 -0
  295. package/dist/rules/security/SEC-012.d.ts +8 -0
  296. package/dist/rules/security/SEC-012.js +79 -0
  297. package/dist/rules/security/SEC-012.js.map +1 -0
  298. package/dist/rules/security/SEC-013.d.ts +9 -0
  299. package/dist/rules/security/SEC-013.js +107 -0
  300. package/dist/rules/security/SEC-013.js.map +1 -0
  301. package/dist/scoring/calculator.js +1 -0
  302. package/dist/scoring/calculator.js.map +1 -1
  303. package/dist/ui/ink/components/AIRecommendationCard.d.ts +11 -0
  304. package/dist/ui/ink/components/AIRecommendationCard.js +23 -0
  305. package/dist/ui/ink/components/AIRecommendationCard.js.map +1 -0
  306. package/dist/ui/ink/components/OpportunityList.d.ts +10 -0
  307. package/dist/ui/ink/components/OpportunityList.js +48 -0
  308. package/dist/ui/ink/components/OpportunityList.js.map +1 -0
  309. package/dist/ui/ink/components/PotentialPageCard.d.ts +13 -0
  310. package/dist/ui/ink/components/PotentialPageCard.js +43 -0
  311. package/dist/ui/ink/components/PotentialPageCard.js.map +1 -0
  312. package/dist/ui/ink/components/PotentialProgress.d.ts +16 -0
  313. package/dist/ui/ink/components/PotentialProgress.js +44 -0
  314. package/dist/ui/ink/components/PotentialProgress.js.map +1 -0
  315. package/dist/ui/ink/components/PotentialSummary.d.ts +10 -0
  316. package/dist/ui/ink/components/PotentialSummary.js +86 -0
  317. package/dist/ui/ink/components/PotentialSummary.js.map +1 -0
  318. package/dist/ui/ink/components/SuggestionCard.d.ts +34 -0
  319. package/dist/ui/ink/components/SuggestionCard.js +36 -0
  320. package/dist/ui/ink/components/SuggestionCard.js.map +1 -0
  321. package/dist/ui/ink/components/views/MultiPageCrawlView.d.ts +21 -0
  322. package/dist/ui/ink/components/views/MultiPageCrawlView.js +55 -0
  323. package/dist/ui/ink/components/views/MultiPageCrawlView.js.map +1 -0
  324. package/dist/ui/ink/components/views/PotentialView.d.ts +18 -0
  325. package/dist/ui/ink/components/views/PotentialView.js +74 -0
  326. package/dist/ui/ink/components/views/PotentialView.js.map +1 -0
  327. package/dist/ui/ink/components/views/ReconView.d.ts +22 -0
  328. package/dist/ui/ink/components/views/ReconView.js +30 -0
  329. package/dist/ui/ink/components/views/ReconView.js.map +1 -0
  330. package/package.json +2 -1
@@ -0,0 +1,67 @@
1
+ /**
2
+ * COV-007: Keyboard Shortcuts Not Exposed
3
+ *
4
+ * Checks if the page has keyboard shortcuts that aren't documented
5
+ * as WebMCP tools, leaving agents unaware of these capabilities.
6
+ */
7
+ import { createRuleResult } from '../runner.js';
8
+ const KEYBOARD_SHORTCUT_PATTERNS = [
9
+ /addEventListener\s*\(\s*['"]keydown["']/,
10
+ /addEventListener\s*\(\s*['"]keyup["']/,
11
+ /addEventListener\s*\(\s*['"]keypress["']/,
12
+ /\.onkeydown\s*=/,
13
+ /\.onkeyup\s*=/,
14
+ /\.onkeypress\s*=/,
15
+ /Mousetrap\./i,
16
+ /hotkeys\s*\(/i,
17
+ /\.key\s*===?\s*['"][^'"]+['"]/,
18
+ /event\.(?:ctrlKey|altKey|shiftKey|metaKey)/,
19
+ /accesskey\s*=\s*["']/i,
20
+ ];
21
+ export const COV_007 = {
22
+ id: 'COV-007',
23
+ category: 'coverage',
24
+ name: 'Keyboard Shortcuts Not Exposed',
25
+ description: 'Keyboard shortcuts should be documented as WebMCP tools or context',
26
+ severity: 'info',
27
+ maxScore: 3,
28
+ async check(context) {
29
+ const scripts = context.scripts ?? [];
30
+ const html = context.html ?? '';
31
+ const hasKeyboardHandlers = scripts.some((s) => KEYBOARD_SHORTCUT_PATTERNS.some((p) => p.test(s.content))) ||
32
+ /accesskey\s*=\s*["']/i.test(html);
33
+ if (!hasKeyboardHandlers) {
34
+ return createRuleResult('COV-007', 3, {
35
+ passed: true,
36
+ score: 3,
37
+ message: 'No keyboard shortcuts detected',
38
+ });
39
+ }
40
+ // Check if there's a tool or context that documents shortcuts
41
+ const hasShortcutTool = context.tools.some((t) => {
42
+ const text = `${t.name} ${t.description}`.toLowerCase();
43
+ return /\bshortcut\b|\bhotkey\b|\bkeyboard\b|\bkeybind/.test(text);
44
+ });
45
+ if (hasShortcutTool) {
46
+ return createRuleResult('COV-007', 3, {
47
+ passed: true,
48
+ score: 3,
49
+ message: 'Keyboard shortcuts are documented via WebMCP',
50
+ });
51
+ }
52
+ return createRuleResult('COV-007', 3, {
53
+ passed: false,
54
+ score: 1,
55
+ message: 'Keyboard shortcuts exist but are not exposed via WebMCP',
56
+ details: [
57
+ 'The page has keyboard event handlers but no tool documenting available shortcuts',
58
+ ],
59
+ suggestions: [
60
+ 'Use provideContext() to list available keyboard shortcuts',
61
+ 'Or register a tool that returns the list of available shortcuts',
62
+ 'Agents benefit from knowing keyboard shortcuts for efficiency',
63
+ ],
64
+ });
65
+ },
66
+ };
67
+ //# sourceMappingURL=COV-007.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"COV-007.js","sourceRoot":"","sources":["../../../src/rules/coverage/COV-007.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,0BAA0B,GAAG;IACjC,yCAAyC;IACzC,uCAAuC;IACvC,0CAA0C;IAC1C,iBAAiB;IACjB,eAAe;IACf,kBAAkB;IAClB,cAAc;IACd,eAAe;IACf,+BAA+B;IAC/B,4CAA4C;IAC5C,uBAAuB;CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAS;IAC3B,EAAE,EAAE,SAAS;IACb,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,gCAAgC;IACtC,WAAW,EACT,oEAAoE;IACtE,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,CAAC;IAEX,KAAK,CAAC,KAAK,CAAC,OAAoB;QAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAC;QAEhC,MAAM,mBAAmB,GACvB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACjB,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAC1D;YACD,uBAAuB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACzB,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;gBACpC,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,gCAAgC;aAC1C,CAAC,CAAC;QACL,CAAC;QAED,8DAA8D;QAC9D,MAAM,eAAe,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE;YAC/C,MAAM,IAAI,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,WAAW,EAAE,CAAC;YACxD,OAAO,gDAAgD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrE,CAAC,CAAC,CAAC;QAEH,IAAI,eAAe,EAAE,CAAC;YACpB,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;gBACpC,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,8CAA8C;aACxD,CAAC,CAAC;QACL,CAAC;QAED,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;YACpC,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,CAAC;YACR,OAAO,EAAE,yDAAyD;YAClE,OAAO,EAAE;gBACP,kFAAkF;aACnF;YACD,WAAW,EAAE;gBACX,2DAA2D;gBAC3D,iEAAiE;gBACjE,+DAA+D;aAChE;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * COV-008: Multi-Step Flow Incomplete
3
+ *
4
+ * Checks if a multi-page/multi-step flow has tools on some pages
5
+ * but not others, leaving gaps in the agent's ability to complete
6
+ * the flow.
7
+ */
8
+ import type { Rule } from '../../core/types/rule.js';
9
+ export declare const COV_008: Rule;
@@ -0,0 +1,87 @@
1
+ /**
2
+ * COV-008: Multi-Step Flow Incomplete
3
+ *
4
+ * Checks if a multi-page/multi-step flow has tools on some pages
5
+ * but not others, leaving gaps in the agent's ability to complete
6
+ * the flow.
7
+ */
8
+ import { createRuleResult } from '../runner.js';
9
+ const MULTI_STEP_PATTERNS = [
10
+ /class\s*=\s*["'][^"']*(?:stepper|wizard|multi-step|progress-bar|step-indicator)[^"']*["']/i,
11
+ /data-step/i,
12
+ /step\s*\d+\s*of\s*\d+/i,
13
+ /class\s*=\s*["'][^"']*(?:checkout-step|form-step|onboarding)[^"']*["']/i,
14
+ ];
15
+ export const COV_008 = {
16
+ id: 'COV-008',
17
+ category: 'coverage',
18
+ name: 'Multi-Step Flow Incomplete',
19
+ description: 'Multi-step flows should have tools on all pages, not just some',
20
+ severity: 'warning',
21
+ maxScore: 5,
22
+ async check(context) {
23
+ const { pages, tools } = context;
24
+ if (pages.length <= 1) {
25
+ // Single page — check for multi-step UI in HTML
26
+ const html = context.html ?? '';
27
+ const hasMultiStep = MULTI_STEP_PATTERNS.some((p) => p.test(html));
28
+ if (!hasMultiStep) {
29
+ return createRuleResult('COV-008', 5, {
30
+ passed: true,
31
+ score: 5,
32
+ message: 'No multi-step flow detected',
33
+ });
34
+ }
35
+ // Multi-step on single page — check if tools exist
36
+ if (tools.length > 0) {
37
+ return createRuleResult('COV-008', 5, {
38
+ passed: true,
39
+ score: 5,
40
+ message: 'Multi-step flow has WebMCP tools registered',
41
+ });
42
+ }
43
+ return createRuleResult('COV-008', 5, {
44
+ passed: false,
45
+ score: 0,
46
+ message: 'Multi-step flow detected but no WebMCP tools registered',
47
+ suggestions: [
48
+ 'Register tools for each step of the flow',
49
+ 'Use dynamic tool registration to add/remove tools per step',
50
+ ],
51
+ });
52
+ }
53
+ // Multi-page: check for pages with tools vs without
54
+ const pagesWithTools = pages.filter((p) => p.toolCount > 0);
55
+ const pagesWithoutTools = pages.filter((p) => p.toolCount === 0 && p.formCount > 0);
56
+ if (pagesWithTools.length === 0) {
57
+ return createRuleResult('COV-008', 5, {
58
+ passed: true,
59
+ score: 5,
60
+ message: 'No pages with tools detected (rule not applicable)',
61
+ });
62
+ }
63
+ if (pagesWithoutTools.length === 0) {
64
+ return createRuleResult('COV-008', 5, {
65
+ passed: true,
66
+ score: 5,
67
+ message: 'All pages with forms have WebMCP tools',
68
+ });
69
+ }
70
+ const totalPages = pagesWithTools.length + pagesWithoutTools.length;
71
+ const coverageRatio = pagesWithTools.length / totalPages;
72
+ const score = Math.round(coverageRatio * 5);
73
+ return createRuleResult('COV-008', 5, {
74
+ passed: false,
75
+ score,
76
+ message: `${pagesWithoutTools.length} page(s) with forms lack WebMCP tools`,
77
+ details: pagesWithoutTools.map((p) => `Page "${p.url}" has ${p.formCount} form(s) but no WebMCP tools`),
78
+ suggestions: [
79
+ 'Add WebMCP tools to all pages in a multi-step flow',
80
+ 'Agents cannot complete flows if intermediate steps lack tools',
81
+ 'Consider using provideContext() to describe the flow structure',
82
+ ],
83
+ affectedPages: pagesWithoutTools.map((p) => p.url),
84
+ });
85
+ },
86
+ };
87
+ //# sourceMappingURL=COV-008.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"COV-008.js","sourceRoot":"","sources":["../../../src/rules/coverage/COV-008.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * COV-009: Critical Page No Tools
3
+ *
4
+ * Checks if critical pages (checkout, login, dashboard, settings)
5
+ * have zero WebMCP tools.
6
+ */
7
+ import type { Rule } from '../../core/types/rule.js';
8
+ export declare const COV_009: Rule;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * COV-009: Critical Page No Tools
3
+ *
4
+ * Checks if critical pages (checkout, login, dashboard, settings)
5
+ * have zero WebMCP tools.
6
+ */
7
+ import { createRuleResult } from '../runner.js';
8
+ const CRITICAL_PAGE_PATTERNS = [
9
+ /\/(?:checkout|cart|basket)/i,
10
+ /\/(?:login|signin|sign-in|auth)/i,
11
+ /\/(?:register|signup|sign-up)/i,
12
+ /\/(?:dashboard|admin|panel)/i,
13
+ /\/(?:settings|preferences|profile|account)/i,
14
+ /\/(?:search|results)/i,
15
+ /\/(?:booking|reservation)/i,
16
+ /\/(?:payment|billing)/i,
17
+ ];
18
+ const CRITICAL_TITLE_PATTERNS = [
19
+ /\b(?:checkout|cart|basket)\b/i,
20
+ /\b(?:login|sign\s*in)\b/i,
21
+ /\b(?:register|sign\s*up|create\s+account)\b/i,
22
+ /\b(?:dashboard|admin)\b/i,
23
+ /\b(?:settings|preferences|profile)\b/i,
24
+ /\b(?:search\s+results?)\b/i,
25
+ ];
26
+ export const COV_009 = {
27
+ id: 'COV-009',
28
+ category: 'coverage',
29
+ name: 'Critical Page No Tools',
30
+ description: 'Critical pages should have WebMCP tools registered',
31
+ severity: 'warning',
32
+ maxScore: 5,
33
+ async check(context) {
34
+ const { pages } = context;
35
+ if (pages.length === 0) {
36
+ return createRuleResult('COV-009', 5, {
37
+ passed: true,
38
+ score: 5,
39
+ message: 'No pages available for analysis',
40
+ });
41
+ }
42
+ const criticalPagesWithNoTools = [];
43
+ for (const page of pages) {
44
+ const isCriticalByURL = CRITICAL_PAGE_PATTERNS.some((p) => p.test(page.url));
45
+ const isCriticalByTitle = CRITICAL_TITLE_PATTERNS.some((p) => p.test(page.title));
46
+ if ((isCriticalByURL || isCriticalByTitle) && page.toolCount === 0) {
47
+ criticalPagesWithNoTools.push(page.url);
48
+ }
49
+ }
50
+ if (criticalPagesWithNoTools.length === 0) {
51
+ return createRuleResult('COV-009', 5, {
52
+ passed: true,
53
+ score: 5,
54
+ message: 'All critical pages have WebMCP tools',
55
+ });
56
+ }
57
+ const penalty = criticalPagesWithNoTools.length * 2;
58
+ const score = Math.max(0, 5 - penalty);
59
+ return createRuleResult('COV-009', 5, {
60
+ passed: false,
61
+ score,
62
+ message: `${criticalPagesWithNoTools.length} critical page(s) have no WebMCP tools`,
63
+ details: criticalPagesWithNoTools.map((url) => `Critical page "${url}" has zero WebMCP tools`),
64
+ suggestions: [
65
+ 'Add WebMCP tools to high-value pages (checkout, login, dashboard, etc.)',
66
+ 'Critical pages are the most important for agent interaction',
67
+ 'Even basic read-only tools (get_cart_contents) add significant value',
68
+ ],
69
+ affectedPages: criticalPagesWithNoTools,
70
+ });
71
+ },
72
+ };
73
+ //# sourceMappingURL=COV-009.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"COV-009.js","sourceRoot":"","sources":["../../../src/rules/coverage/COV-009.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,sBAAsB,GAAG;IAC7B,6BAA6B;IAC7B,kCAAkC;IAClC,gCAAgC;IAChC,8BAA8B;IAC9B,6CAA6C;IAC7C,uBAAuB;IACvB,4BAA4B;IAC5B,wBAAwB;CACzB,CAAC;AAEF,MAAM,uBAAuB,GAAG;IAC9B,+BAA+B;IAC/B,0BAA0B;IAC1B,8CAA8C;IAC9C,0BAA0B;IAC1B,uCAAuC;IACvC,4BAA4B;CAC7B,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAS;IAC3B,EAAE,EAAE,SAAS;IACb,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,oDAAoD;IACjE,QAAQ,EAAE,SAAS;IACnB,QAAQ,EAAE,CAAC;IAEX,KAAK,CAAC,KAAK,CAAC,OAAoB;QAC9B,MAAM,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC;QAE1B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;gBACpC,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,iCAAiC;aAC3C,CAAC,CAAC;QACL,CAAC;QAED,MAAM,wBAAwB,GAAa,EAAE,CAAC;QAE9C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,eAAe,GAAG,sBAAsB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACxD,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CACjB,CAAC;YACF,MAAM,iBAAiB,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAC3D,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CACnB,CAAC;YAEF,IAAI,CAAC,eAAe,IAAI,iBAAiB,CAAC,IAAI,IAAI,CAAC,SAAS,KAAK,CAAC,EAAE,CAAC;gBACnE,wBAAwB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC1C,CAAC;QACH,CAAC;QAED,IAAI,wBAAwB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC1C,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;gBACpC,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,sCAAsC;aAChD,CAAC,CAAC;QACL,CAAC;QAED,MAAM,OAAO,GAAG,wBAAwB,CAAC,MAAM,GAAG,CAAC,CAAC;QACpD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC;QAEvC,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;YACpC,MAAM,EAAE,KAAK;YACb,KAAK;YACL,OAAO,EAAE,GAAG,wBAAwB,CAAC,MAAM,wCAAwC;YACnF,OAAO,EAAE,wBAAwB,CAAC,GAAG,CACnC,CAAC,GAAG,EAAE,EAAE,CAAC,kBAAkB,GAAG,yBAAyB,CACxD;YACD,WAAW,EAAE;gBACX,yEAAyE;gBACzE,6DAA6D;gBAC7D,sEAAsE;aACvE;YACD,aAAa,EAAE,wBAAwB;SACxC,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * COV-010: State Transition Gaps
3
+ *
4
+ * Checks if SPA state transitions leave tool gaps.
5
+ * Detects if the page uses client-side routing but tools
6
+ * are only registered on initial load.
7
+ */
8
+ import type { Rule } from '../../core/types/rule.js';
9
+ export declare const COV_010: Rule;
@@ -0,0 +1,82 @@
1
+ /**
2
+ * COV-010: State Transition Gaps
3
+ *
4
+ * Checks if SPA state transitions leave tool gaps.
5
+ * Detects if the page uses client-side routing but tools
6
+ * are only registered on initial load.
7
+ */
8
+ import { createRuleResult } from '../runner.js';
9
+ const SPA_ROUTING_PATTERNS = [
10
+ /pushState\s*\(/,
11
+ /replaceState\s*\(/,
12
+ /history\.(?:push|replace)/,
13
+ /\.navigate\s*\(/,
14
+ /router\.(?:push|go|replace)/i,
15
+ /useRouter|useNavigate|useHistory/,
16
+ /react-router|vue-router|@angular\/router/,
17
+ /popstate/,
18
+ /hashchange/,
19
+ ];
20
+ const DYNAMIC_TOOL_PATTERNS = [
21
+ /registerTool/,
22
+ /unregisterTool/,
23
+ /modelContext/,
24
+ ];
25
+ export const COV_010 = {
26
+ id: 'COV-010',
27
+ category: 'coverage',
28
+ name: 'State Transition Gaps',
29
+ description: 'SPA state transitions should not leave tool registration gaps',
30
+ severity: 'info',
31
+ maxScore: 3,
32
+ async check(context) {
33
+ const scripts = context.scripts ?? [];
34
+ if (scripts.length === 0) {
35
+ return createRuleResult('COV-010', 3, {
36
+ passed: true,
37
+ score: 3,
38
+ message: 'No scripts available for analysis',
39
+ });
40
+ }
41
+ // Check if the site uses client-side routing
42
+ const hasSPARouting = scripts.some((s) => SPA_ROUTING_PATTERNS.some((p) => p.test(s.content)));
43
+ if (!hasSPARouting) {
44
+ return createRuleResult('COV-010', 3, {
45
+ passed: true,
46
+ score: 3,
47
+ message: 'No SPA routing detected (rule not applicable)',
48
+ });
49
+ }
50
+ // Check if tools are registered/unregistered dynamically
51
+ const hasDynamicToolRegistration = scripts.some((s) => DYNAMIC_TOOL_PATTERNS.some((p) => p.test(s.content)));
52
+ if (hasDynamicToolRegistration) {
53
+ return createRuleResult('COV-010', 3, {
54
+ passed: true,
55
+ score: 3,
56
+ message: 'SPA uses dynamic tool registration for route changes',
57
+ });
58
+ }
59
+ if (context.tools.length === 0) {
60
+ return createRuleResult('COV-010', 3, {
61
+ passed: true,
62
+ score: 3,
63
+ message: 'No tools registered (rule not applicable)',
64
+ });
65
+ }
66
+ return createRuleResult('COV-010', 3, {
67
+ passed: false,
68
+ score: 1,
69
+ message: 'SPA routing detected but tools appear static (not route-aware)',
70
+ details: [
71
+ 'Client-side routing detected but tool registration does not appear to respond to route changes',
72
+ 'Tools registered at initial page load may become stale after navigation',
73
+ ],
74
+ suggestions: [
75
+ 'Register/unregister tools when the SPA route changes',
76
+ 'Listen for popstate or router events to update tool registrations',
77
+ 'Use unregisterTool() to remove tools that are no longer relevant',
78
+ ],
79
+ });
80
+ },
81
+ };
82
+ //# sourceMappingURL=COV-010.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"COV-010.js","sourceRoot":"","sources":["../../../src/rules/coverage/COV-010.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAEhD,MAAM,oBAAoB,GAAG;IAC3B,gBAAgB;IAChB,mBAAmB;IACnB,2BAA2B;IAC3B,iBAAiB;IACjB,8BAA8B;IAC9B,kCAAkC;IAClC,0CAA0C;IAC1C,UAAU;IACV,YAAY;CACb,CAAC;AAEF,MAAM,qBAAqB,GAAG;IAC5B,cAAc;IACd,gBAAgB;IAChB,cAAc;CACf,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAS;IAC3B,EAAE,EAAE,SAAS;IACb,QAAQ,EAAE,UAAU;IACpB,IAAI,EAAE,uBAAuB;IAC7B,WAAW,EACT,+DAA+D;IACjE,QAAQ,EAAE,MAAM;IAChB,QAAQ,EAAE,CAAC;IAEX,KAAK,CAAC,KAAK,CAAC,OAAoB;QAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;QAEtC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzB,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;gBACpC,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,mCAAmC;aAC7C,CAAC,CAAC;QACL,CAAC;QAED,6CAA6C;QAC7C,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACvC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CACpD,CAAC;QAEF,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;gBACpC,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,+CAA+C;aACzD,CAAC,CAAC;QACL,CAAC;QAED,yDAAyD;QACzD,MAAM,0BAA0B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CACpD,qBAAqB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CACrD,CAAC;QAEF,IAAI,0BAA0B,EAAE,CAAC;YAC/B,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;gBACpC,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,sDAAsD;aAChE,CAAC,CAAC;QACL,CAAC;QAED,IAAI,OAAO,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC/B,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;gBACpC,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,CAAC;gBACR,OAAO,EAAE,2CAA2C;aACrD,CAAC,CAAC;QACL,CAAC;QAED,OAAO,gBAAgB,CAAC,SAAS,EAAE,CAAC,EAAE;YACpC,MAAM,EAAE,KAAK;YACb,KAAK,EAAE,CAAC;YACR,OAAO,EAAE,gEAAgE;YACzE,OAAO,EAAE;gBACP,gGAAgG;gBAChG,yEAAyE;aAC1E;YACD,WAAW,EAAE;gBACX,sDAAsD;gBACtD,mEAAmE;gBACnE,kEAAkE;aACnE;SACF,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * DESC-001: Name Uses Specific Verb
3
+ *
4
+ * Checks that tool names use specific action verbs (create, search, delete,
5
+ * book, submit) rather than ambiguous ones (handle, process, do, manage).
6
+ */
7
+ import type { Rule } from '../../core/types/rule.js';
8
+ export declare const DESC_001: Rule;
9
+ export default DESC_001;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * DESC-001: Name Uses Specific Verb
3
+ *
4
+ * Checks that tool names use specific action verbs (create, search, delete,
5
+ * book, submit) rather than ambiguous ones (handle, process, do, manage).
6
+ */
7
+ import { createRuleResult } from '../runner.js';
8
+ const SPECIFIC_VERBS = new Set([
9
+ 'create', 'search', 'find', 'get', 'list', 'delete', 'remove',
10
+ 'update', 'edit', 'book', 'submit', 'send', 'fetch', 'check',
11
+ 'validate', 'calculate', 'convert', 'generate', 'export', 'import',
12
+ 'upload', 'download', 'publish', 'archive', 'cancel', 'confirm',
13
+ 'accept', 'reject', 'approve', 'deny', 'add', 'set', 'reset',
14
+ 'filter', 'sort', 'count', 'compare', 'merge', 'split', 'parse',
15
+ 'format', 'encode', 'decode', 'encrypt', 'decrypt', 'sign', 'verify',
16
+ 'subscribe', 'unsubscribe', 'register', 'login', 'logout', 'connect',
17
+ 'disconnect', 'open', 'close', 'start', 'stop', 'pause', 'resume',
18
+ 'enable', 'disable', 'toggle', 'select', 'deselect', 'move', 'copy',
19
+ 'rename', 'save', 'load', 'read', 'write', 'log', 'track', 'notify',
20
+ 'schedule', 'reserve', 'assign', 'transfer', 'refund', 'purchase',
21
+ 'order', 'ship', 'deliver', 'rate', 'review', 'comment', 'share',
22
+ 'pin', 'bookmark', 'follow', 'unfollow', 'block', 'report', 'flag',
23
+ 'translate', 'summarize', 'analyze', 'inspect', 'scan', 'test',
24
+ 'run', 'execute', 'invoke', 'call', 'apply', 'deploy', 'install',
25
+ ]);
26
+ const AMBIGUOUS_VERBS = new Set([
27
+ 'handle', 'process', 'do', 'manage', 'perform', 'make', 'run',
28
+ 'use', 'work', 'go', 'put', 'take', 'give', 'try', 'help',
29
+ 'change', 'stuff', 'thing',
30
+ ]);
31
+ function extractVerb(name) {
32
+ // Split by separators (- or _) and take first word
33
+ const parts = name.split(/[-_]/);
34
+ return parts[0]?.toLowerCase() ?? null;
35
+ }
36
+ export const DESC_001 = {
37
+ id: 'DESC-001',
38
+ category: 'description',
39
+ name: 'Name Uses Specific Verb',
40
+ description: 'Tool names should use specific action verbs, not ambiguous ones',
41
+ severity: 'warning',
42
+ maxScore: 5,
43
+ async check(context) {
44
+ if (context.tools.length === 0) {
45
+ return createRuleResult('DESC-001', 5, {
46
+ passed: true,
47
+ score: 5,
48
+ message: 'No tools detected (rule not applicable)',
49
+ });
50
+ }
51
+ const violations = [];
52
+ for (const tool of context.tools) {
53
+ if (!tool.name)
54
+ continue;
55
+ const verb = extractVerb(tool.name);
56
+ if (!verb)
57
+ continue;
58
+ if (AMBIGUOUS_VERBS.has(verb)) {
59
+ violations.push({ name: tool.name, verb });
60
+ }
61
+ else if (!SPECIFIC_VERBS.has(verb)) {
62
+ // Single-word tool names without a recognized verb are acceptable
63
+ // (e.g., "calculator", "weather") — only flag known ambiguous verbs
64
+ }
65
+ }
66
+ if (violations.length === 0) {
67
+ return createRuleResult('DESC-001', 5, {
68
+ passed: true,
69
+ score: 5,
70
+ message: 'All tool names use specific action verbs',
71
+ });
72
+ }
73
+ return createRuleResult('DESC-001', 5, {
74
+ passed: false,
75
+ score: Math.max(0, 5 - violations.length * 2),
76
+ message: `${violations.length} tool(s) use ambiguous verbs in their names`,
77
+ details: violations.map((v) => `Tool "${v.name}" uses ambiguous verb "${v.verb}"`),
78
+ suggestions: [
79
+ 'Use specific verbs: create, search, delete, book, submit, fetch, etc.',
80
+ 'Avoid ambiguous verbs: handle, process, do, manage, perform',
81
+ 'Specific verbs help agents understand the tool\'s action clearly',
82
+ ],
83
+ affectedTools: violations.map((v) => v.name),
84
+ });
85
+ },
86
+ };
87
+ export default DESC_001;
88
+ //# sourceMappingURL=DESC-001.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DESC-001.js","sourceRoot":"","sources":["../../../src/rules/description/DESC-001.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * DESC-002: Name Distinguishes Execution
3
+ *
4
+ * Checks that tool names distinguish execution from initiation.
5
+ * Per spec: create-event (immediate) vs start-event-creation (process).
6
+ * Uses heuristic analysis of name + description.
7
+ */
8
+ import type { Rule } from '../../core/types/rule.js';
9
+ export declare const DESC_002: Rule;
10
+ export default DESC_002;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * DESC-002: Name Distinguishes Execution
3
+ *
4
+ * Checks that tool names distinguish execution from initiation.
5
+ * Per spec: create-event (immediate) vs start-event-creation (process).
6
+ * Uses heuristic analysis of name + description.
7
+ */
8
+ import { createRuleResult } from '../runner.js';
9
+ /**
10
+ * Words that indicate process initiation rather than immediate execution
11
+ */
12
+ const INITIATION_PREFIXES = ['start', 'begin', 'initiate', 'launch', 'open'];
13
+ /**
14
+ * Words in the description that suggest the tool starts a process
15
+ * (multi-step, async, workflow) rather than completing an action
16
+ */
17
+ const PROCESS_INDICATORS = [
18
+ /multi[- ]?step/i,
19
+ /workflow/i,
20
+ /wizard/i,
21
+ /begins?\s+(a\s+)?process/i,
22
+ /starts?\s+(a\s+)?process/i,
23
+ /initiates?\s+(a\s+)?process/i,
24
+ /opens?\s+(a\s+)?dialog/i,
25
+ /opens?\s+(a\s+)?modal/i,
26
+ /opens?\s+(a\s+)?form/i,
27
+ ];
28
+ function getNameVerb(name) {
29
+ const parts = name.split(/[-_]/);
30
+ return parts[0]?.toLowerCase() ?? null;
31
+ }
32
+ export const DESC_002 = {
33
+ id: 'DESC-002',
34
+ category: 'description',
35
+ name: 'Name Distinguishes Execution',
36
+ description: 'Tool names should distinguish execution from initiation',
37
+ severity: 'warning',
38
+ maxScore: 5,
39
+ async check(context) {
40
+ if (context.tools.length === 0) {
41
+ return createRuleResult('DESC-002', 5, {
42
+ passed: true,
43
+ score: 5,
44
+ message: 'No tools detected (rule not applicable)',
45
+ });
46
+ }
47
+ const violations = [];
48
+ for (const tool of context.tools) {
49
+ if (!tool.name)
50
+ continue;
51
+ const verb = getNameVerb(tool.name);
52
+ const desc = tool.description?.toLowerCase() ?? '';
53
+ // Check if name suggests immediate action but description suggests process
54
+ if (verb && !INITIATION_PREFIXES.includes(verb)) {
55
+ const isProcess = PROCESS_INDICATORS.some((p) => p.test(desc));
56
+ if (isProcess) {
57
+ violations.push({
58
+ name: tool.name,
59
+ reason: `Name "${tool.name}" suggests immediate action, but description indicates a multi-step process`,
60
+ });
61
+ }
62
+ }
63
+ // Check if name uses initiation prefix but description suggests immediate action
64
+ if (verb && INITIATION_PREFIXES.includes(verb)) {
65
+ const hasImmediateDesc = desc.includes('immediately') ||
66
+ desc.includes('instantly') ||
67
+ desc.includes('directly creates') ||
68
+ desc.includes('directly deletes');
69
+ if (hasImmediateDesc) {
70
+ violations.push({
71
+ name: tool.name,
72
+ reason: `Name "${tool.name}" suggests process initiation, but description indicates immediate execution`,
73
+ });
74
+ }
75
+ }
76
+ }
77
+ if (violations.length === 0) {
78
+ return createRuleResult('DESC-002', 5, {
79
+ passed: true,
80
+ score: 5,
81
+ message: 'Tool names properly distinguish execution from initiation',
82
+ });
83
+ }
84
+ return createRuleResult('DESC-002', 5, {
85
+ passed: false,
86
+ score: Math.max(0, 5 - violations.length * 2),
87
+ message: `${violations.length} tool(s) have naming/description mismatch`,
88
+ details: violations.map((v) => v.reason),
89
+ suggestions: [
90
+ 'Use immediate verbs (create, delete, send) for one-shot actions',
91
+ 'Use initiation verbs (start, begin, open) for multi-step processes',
92
+ 'Example: "create-event" (immediate) vs "start-event-creation" (process)',
93
+ ],
94
+ affectedTools: violations.map((v) => v.name),
95
+ });
96
+ },
97
+ };
98
+ export default DESC_002;
99
+ //# sourceMappingURL=DESC-002.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DESC-002.js","sourceRoot":"","sources":["../../../src/rules/description/DESC-002.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * DESC-006: Description Positive Framing
3
+ *
4
+ * Checks that descriptions use positive instructions,
5
+ * not negative limitations ("do not", "don't", "never").
6
+ */
7
+ import type { Rule } from '../../core/types/rule.js';
8
+ export declare const DESC_006: Rule;
9
+ export default DESC_006;