@oriro/orirocli 0.1.8 → 0.1.11

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 (1445) hide show
  1. package/ATTRIBUTION.md +53 -45
  2. package/LICENSE +21 -0
  3. package/README.md +20 -17
  4. package/dist/cli.js +4425 -2975
  5. package/package.json +64 -64
  6. package/skills/1password/SKILL.md +118 -118
  7. package/skills/1password/references/cli-examples.md +29 -29
  8. package/skills/1password/references/get-started.md +21 -21
  9. package/skills/21stdev/SKILL.md +64 -0
  10. package/skills/algorithmic-art/LICENSE +21 -21
  11. package/skills/algorithmic-art/SKILL.md +446 -446
  12. package/skills/algorithmic-art/templates/generator_template.js +223 -223
  13. package/skills/algorithmic-art/templates/viewer.html +598 -598
  14. package/skills/apple-notes/SKILL.md +81 -81
  15. package/skills/apple-reminders/SKILL.md +122 -122
  16. package/skills/bear-notes/SKILL.md +111 -111
  17. package/skills/blogwatcher/SKILL.md +73 -73
  18. package/skills/blucli/SKILL.md +51 -51
  19. package/skills/brand-guidelines/LICENSE +21 -21
  20. package/skills/brand-guidelines/SKILL.md +76 -76
  21. package/skills/business/biz-analysis/LICENSE +21 -21
  22. package/skills/business/biz-analysis/SKILL.md +103 -103
  23. package/skills/business/biz-corporate-strategy/LICENSE +21 -21
  24. package/skills/business/biz-corporate-strategy/SKILL.md +76 -76
  25. package/skills/business/biz-customer-success/LICENSE +21 -21
  26. package/skills/business/biz-customer-success/SKILL.md +55 -55
  27. package/skills/business/biz-entrepreneurship/LICENSE +21 -21
  28. package/skills/business/biz-entrepreneurship/SKILL.md +72 -72
  29. package/skills/business/biz-hr/LICENSE +21 -21
  30. package/skills/business/biz-hr/SKILL.md +67 -67
  31. package/skills/business/biz-international/LICENSE +21 -21
  32. package/skills/business/biz-international/SKILL.md +51 -51
  33. package/skills/business/biz-leadership/LICENSE +21 -21
  34. package/skills/business/biz-leadership/SKILL.md +106 -106
  35. package/skills/business/biz-marketing-strategy/LICENSE +21 -21
  36. package/skills/business/biz-marketing-strategy/SKILL.md +119 -119
  37. package/skills/business/biz-negotiation/LICENSE +21 -21
  38. package/skills/business/biz-negotiation/SKILL.md +152 -152
  39. package/skills/business/biz-operations/LICENSE +21 -21
  40. package/skills/business/biz-operations/SKILL.md +74 -74
  41. package/skills/business/biz-project/LICENSE +21 -21
  42. package/skills/business/biz-project/SKILL.md +203 -203
  43. package/skills/business/biz-risk/LICENSE +21 -21
  44. package/skills/business/biz-risk/SKILL.md +85 -85
  45. package/skills/business/biz-sales/LICENSE +21 -21
  46. package/skills/business/biz-sales/SKILL.md +92 -92
  47. package/skills/business/biz-startup-ops/LICENSE +21 -21
  48. package/skills/business/biz-startup-ops/SKILL.md +70 -70
  49. package/skills/business/biz-strategy/LICENSE +21 -21
  50. package/skills/business/biz-strategy/SKILL.md +233 -233
  51. package/skills/business/biz-supply-chain-advanced/LICENSE +21 -21
  52. package/skills/business/biz-supply-chain-advanced/SKILL.md +68 -68
  53. package/skills/business/fin-chartered-exams/LICENSE +21 -21
  54. package/skills/business/fin-chartered-exams/SKILL.md +69 -69
  55. package/skills/camsnap/SKILL.md +49 -49
  56. package/skills/canvas/SKILL.md +82 -82
  57. package/skills/canvas-design/LICENSE +21 -21
  58. package/skills/canvas-design/SKILL.md +140 -140
  59. package/skills/canvas-design/canvas-fonts/ArsenalSC-OFL.txt +93 -93
  60. package/skills/canvas-design/canvas-fonts/BigShoulders-OFL.txt +93 -93
  61. package/skills/canvas-design/canvas-fonts/Boldonse-OFL.txt +93 -93
  62. package/skills/canvas-design/canvas-fonts/BricolageGrotesque-OFL.txt +93 -93
  63. package/skills/canvas-design/canvas-fonts/CrimsonPro-OFL.txt +93 -93
  64. package/skills/canvas-design/canvas-fonts/DMMono-OFL.txt +93 -93
  65. package/skills/canvas-design/canvas-fonts/EricaOne-OFL.txt +94 -94
  66. package/skills/canvas-design/canvas-fonts/GeistMono-OFL.txt +93 -93
  67. package/skills/canvas-design/canvas-fonts/Gloock-OFL.txt +93 -93
  68. package/skills/canvas-design/canvas-fonts/IBMPlexMono-OFL.txt +93 -93
  69. package/skills/canvas-design/canvas-fonts/InstrumentSans-OFL.txt +93 -93
  70. package/skills/canvas-design/canvas-fonts/JetBrainsMono-OFL.txt +93 -93
  71. package/skills/canvas-design/canvas-fonts/Jura-OFL.txt +93 -93
  72. package/skills/canvas-design/canvas-fonts/LibreBaskerville-OFL.txt +93 -93
  73. package/skills/canvas-design/canvas-fonts/Lora-OFL.txt +93 -93
  74. package/skills/canvas-design/canvas-fonts/NationalPark-OFL.txt +93 -93
  75. package/skills/canvas-design/canvas-fonts/Outfit-OFL.txt +93 -93
  76. package/skills/canvas-design/canvas-fonts/PixelifySans-OFL.txt +93 -93
  77. package/skills/canvas-design/canvas-fonts/RedHatMono-OFL.txt +93 -93
  78. package/skills/canvas-design/canvas-fonts/Silkscreen-OFL.txt +93 -93
  79. package/skills/canvas-design/canvas-fonts/SmoochSans-OFL.txt +93 -93
  80. package/skills/canvas-design/canvas-fonts/Tektur-OFL.txt +93 -93
  81. package/skills/canvas-design/canvas-fonts/WorkSans-OFL.txt +93 -93
  82. package/skills/canvas-design/canvas-fonts/YoungSerif-OFL.txt +93 -93
  83. package/skills/coding-agent/SKILL.md +146 -146
  84. package/skills/communication/comm-business-writing/LICENSE +21 -21
  85. package/skills/communication/comm-business-writing/SKILL.md +67 -67
  86. package/skills/communication/comm-cross-cultural/LICENSE +21 -21
  87. package/skills/communication/comm-cross-cultural/SKILL.md +88 -88
  88. package/skills/communication/comm-journalism/LICENSE +21 -21
  89. package/skills/communication/comm-journalism/SKILL.md +81 -81
  90. package/skills/communication/comm-linguistics/LICENSE +21 -21
  91. package/skills/communication/comm-linguistics/SKILL.md +82 -82
  92. package/skills/communication/comm-negotiation/LICENSE +21 -21
  93. package/skills/communication/comm-negotiation/SKILL.md +120 -120
  94. package/skills/communication/comm-presentations/LICENSE +21 -21
  95. package/skills/communication/comm-presentations/SKILL.md +93 -93
  96. package/skills/communication/comm-public-speaking/LICENSE +21 -21
  97. package/skills/communication/comm-public-speaking/SKILL.md +68 -68
  98. package/skills/communication/comm-writing/LICENSE +21 -21
  99. package/skills/communication/comm-writing/SKILL.md +69 -69
  100. package/skills/craft/ai-engineering/LICENSE +21 -21
  101. package/skills/craft/ai-engineering/SKILL.md +828 -828
  102. package/skills/craft/app-builder-guide/LICENSE +21 -21
  103. package/skills/craft/app-builder-guide/SKILL.md +332 -332
  104. package/skills/craft/become-an-ai-engineer-26/CONTRIBUTING.md +46 -46
  105. package/skills/craft/become-an-ai-engineer-26/LICENSE +21 -21
  106. package/skills/craft/become-an-ai-engineer-26/README.md +270 -270
  107. package/skills/craft/become-an-ai-engineer-26/SKILL.md +667 -667
  108. package/skills/craft/become-an-ai-engineer-26/community/BUILDS.md +13 -13
  109. package/skills/craft/become-an-ai-engineer-26/community/DISCUSSIONS.md +8 -8
  110. package/skills/craft/become-an-ai-engineer-26/phases/phase-0-mental-models/README.md +14 -14
  111. package/skills/craft/become-an-ai-engineer-26/phases/phase-0-mental-models/project/TEMPLATE.md +33 -33
  112. package/skills/craft/become-an-ai-engineer-26/phases/phase-1-first-agent/README.md +25 -25
  113. package/skills/craft/become-an-ai-engineer-26/phases/phase-1-first-agent/code/raw_loop.py +126 -126
  114. package/skills/craft/become-an-ai-engineer-26/phases/phase-2-architecture/README.md +17 -17
  115. package/skills/craft/become-an-ai-engineer-26/phases/phase-3-harness/README.md +17 -17
  116. package/skills/craft/become-an-ai-engineer-26/phases/phase-4-evals/README.md +21 -21
  117. package/skills/craft/become-an-ai-engineer-26/phases/phase-4-evals/code/.github/workflows/eval.yml +40 -40
  118. package/skills/craft/become-an-ai-engineer-26/phases/phase-5-production/README.md +16 -16
  119. package/skills/craft/become-an-ai-engineer-26/projects/1-mobile-app-slm/README.md +11 -11
  120. package/skills/craft/become-an-ai-engineer-26/projects/2-self-improving-coder/README.md +11 -11
  121. package/skills/craft/become-an-ai-engineer-26/projects/3-video-editor-agent/README.md +11 -11
  122. package/skills/craft/become-an-ai-engineer-26/projects/4-personal-life-os/README.md +12 -12
  123. package/skills/craft/become-an-ai-engineer-26/projects/5-enterprise-workflow/README.md +12 -12
  124. package/skills/craft/become-an-ai-engineer-26/references/benchmark-numbers.md +41 -41
  125. package/skills/craft/become-an-ai-engineer-26/references/mhc-stable-training.md +73 -73
  126. package/skills/craft/become-an-ai-engineer-26/references/stack-decisions.md +37 -37
  127. package/skills/craft/become-an-ai-engineer-26/references/yarn-context-extension.md +123 -123
  128. package/skills/craft/codex-result-handling/LICENSE +21 -21
  129. package/skills/craft/codex-result-handling/SKILL.md +26 -26
  130. package/skills/craft/debug-and-build-methodology/LICENSE +21 -21
  131. package/skills/craft/debug-and-build-methodology/SKILL.md +432 -432
  132. package/skills/craft/design/LICENSE +21 -21
  133. package/skills/craft/design/SKILL.md +274 -274
  134. package/skills/craft/dev/LICENSE +21 -21
  135. package/skills/craft/dev/SKILL.md +12 -12
  136. package/skills/craft/dev/release.md +85 -85
  137. package/skills/craft/dev/roll.md +50 -50
  138. package/skills/craft/doc-coauthoring/LICENSE +21 -21
  139. package/skills/craft/doc-coauthoring/SKILL.md +397 -397
  140. package/skills/craft/focus/LICENSE +21 -21
  141. package/skills/craft/focus/SKILL.md +432 -432
  142. package/skills/craft/focus/UPSTREAM_README.md +233 -233
  143. package/skills/craft/gh/LICENSE +21 -21
  144. package/skills/craft/gh/SKILL.md +84 -84
  145. package/skills/craft/gh-skill/LICENSE +21 -21
  146. package/skills/craft/gh-skill/SKILL.md +121 -121
  147. package/skills/craft/godmode/LICENSE +21 -21
  148. package/skills/craft/godmode/SKILL.md +87 -87
  149. package/skills/craft/godmode/references/android-launch.md +680 -680
  150. package/skills/craft/godmode/references/data-gcp.md +1038 -1038
  151. package/skills/craft/godmode/references/expo-eas.md +816 -816
  152. package/skills/craft/godmode/references/ios-launch.md +734 -734
  153. package/skills/craft/google-ai-latest/LICENSE +21 -21
  154. package/skills/craft/google-ai-latest/SKILL.md +682 -682
  155. package/skills/craft/gpt-5-4-prompting/LICENSE +21 -21
  156. package/skills/craft/gpt-5-4-prompting/SKILL.md +63 -63
  157. package/skills/craft/gpt-5-4-prompting/references/codex-prompt-antipatterns.md +101 -101
  158. package/skills/craft/gpt-5-4-prompting/references/codex-prompt-recipes.md +150 -150
  159. package/skills/craft/gpt-5-4-prompting/references/prompt-blocks.md +172 -172
  160. package/skills/craft/grill-me/LICENSE +21 -21
  161. package/skills/craft/grill-me/SKILL.md +13 -13
  162. package/skills/craft/idea-to-deploy/LICENSE +21 -21
  163. package/skills/craft/idea-to-deploy/SKILL.md +292 -292
  164. package/skills/craft/idea-to-deploy/references/auth-playbook.md +195 -195
  165. package/skills/craft/idea-to-deploy/references/gcp-deployment.md +268 -268
  166. package/skills/craft/idea-to-deploy/references/stack-selection.md +117 -117
  167. package/skills/craft/image-generation-engineer/LICENSE +21 -21
  168. package/skills/craft/image-generation-engineer/SKILL.md +183 -183
  169. package/skills/craft/image-generation-engineer/references/architectures.md +260 -260
  170. package/skills/craft/image-generation-engineer/references/foundations.md +107 -107
  171. package/skills/craft/image-generation-engineer/references/inference-and-serving.md +253 -253
  172. package/skills/craft/image-generation-engineer/references/training.md +149 -149
  173. package/skills/craft/marketing/LICENSE +21 -21
  174. package/skills/craft/marketing/SKILL.md +1954 -1954
  175. package/skills/craft/master-architect/LICENSE +21 -21
  176. package/skills/craft/master-architect/SKILL.md +361 -361
  177. package/skills/craft/master-architect/references/ai-ml.md +317 -317
  178. package/skills/craft/master-architect/references/architecture.md +268 -268
  179. package/skills/craft/master-architect/references/auth-playbook.md +195 -195
  180. package/skills/craft/master-architect/references/cloud.md +323 -323
  181. package/skills/craft/master-architect/references/cyber.md +839 -839
  182. package/skills/craft/master-architect/references/data-eng.md +366 -366
  183. package/skills/craft/master-architect/references/devops.md +550 -550
  184. package/skills/craft/master-architect/references/gcp-deployment.md +268 -268
  185. package/skills/craft/master-architect/references/languages.md +748 -748
  186. package/skills/craft/master-architect/references/legacy.md +240 -240
  187. package/skills/craft/master-architect/references/mobile.md +447 -447
  188. package/skills/craft/master-architect/references/patterns.md +451 -451
  189. package/skills/craft/master-architect/references/saas-patterns.md +379 -379
  190. package/skills/craft/master-architect/references/sdlc.md +349 -349
  191. package/skills/craft/master-architect/references/stack-selection.md +117 -117
  192. package/skills/craft/oriro-ui-2026/LICENSE +21 -21
  193. package/skills/craft/oriro-ui-2026/SKILL.md +329 -329
  194. package/skills/craft/playwright-cli/LICENSE +21 -21
  195. package/skills/craft/playwright-cli/SKILL.md +393 -393
  196. package/skills/craft/playwright-cli/references/element-attributes.md +23 -23
  197. package/skills/craft/playwright-cli/references/playwright-tests.md +39 -39
  198. package/skills/craft/playwright-cli/references/request-mocking.md +87 -87
  199. package/skills/craft/playwright-cli/references/running-code.md +240 -240
  200. package/skills/craft/playwright-cli/references/session-management.md +226 -226
  201. package/skills/craft/playwright-cli/references/spec-driven-testing.md +312 -312
  202. package/skills/craft/playwright-cli/references/storage-state.md +275 -275
  203. package/skills/craft/playwright-cli/references/test-generation.md +134 -134
  204. package/skills/craft/playwright-cli/references/tracing.md +142 -142
  205. package/skills/craft/playwright-cli/references/video-recording.md +150 -150
  206. package/skills/craft/remotion-best-practices/LICENSE +21 -21
  207. package/skills/craft/remotion-best-practices/SKILL.md +345 -345
  208. package/skills/craft/remotion-best-practices/rules/3d.md +86 -86
  209. package/skills/craft/remotion-best-practices/rules/assets/charts-bar-chart.tsx +165 -165
  210. package/skills/craft/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +89 -89
  211. package/skills/craft/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +101 -101
  212. package/skills/craft/remotion-best-practices/rules/audio-visualization.md +195 -195
  213. package/skills/craft/remotion-best-practices/rules/audio.md +167 -167
  214. package/skills/craft/remotion-best-practices/rules/calculate-metadata.md +118 -118
  215. package/skills/craft/remotion-best-practices/rules/compositions.md +132 -132
  216. package/skills/craft/remotion-best-practices/rules/display-captions.md +176 -176
  217. package/skills/craft/remotion-best-practices/rules/ffmpeg.md +34 -34
  218. package/skills/craft/remotion-best-practices/rules/get-audio-duration.md +58 -58
  219. package/skills/craft/remotion-best-practices/rules/get-video-dimensions.md +68 -68
  220. package/skills/craft/remotion-best-practices/rules/get-video-duration.md +60 -60
  221. package/skills/craft/remotion-best-practices/rules/gifs.md +135 -135
  222. package/skills/craft/remotion-best-practices/rules/google-fonts.md +72 -72
  223. package/skills/craft/remotion-best-practices/rules/html-in-canvas.md +122 -122
  224. package/skills/craft/remotion-best-practices/rules/images.md +67 -67
  225. package/skills/craft/remotion-best-practices/rules/import-srt-captions.md +69 -69
  226. package/skills/craft/remotion-best-practices/rules/light-leaks.md +73 -73
  227. package/skills/craft/remotion-best-practices/rules/local-fonts.md +65 -65
  228. package/skills/craft/remotion-best-practices/rules/lottie.md +67 -67
  229. package/skills/craft/remotion-best-practices/rules/maplibre.md +441 -441
  230. package/skills/craft/remotion-best-practices/rules/measuring-dom-nodes.md +34 -34
  231. package/skills/craft/remotion-best-practices/rules/measuring-text.md +140 -140
  232. package/skills/craft/remotion-best-practices/rules/parameters.md +109 -109
  233. package/skills/craft/remotion-best-practices/rules/sequencing.md +144 -144
  234. package/skills/craft/remotion-best-practices/rules/sfx.md +30 -30
  235. package/skills/craft/remotion-best-practices/rules/silence-detection.md +73 -73
  236. package/skills/craft/remotion-best-practices/rules/subtitles.md +36 -36
  237. package/skills/craft/remotion-best-practices/rules/tailwind.md +11 -11
  238. package/skills/craft/remotion-best-practices/rules/text-animations.md +20 -20
  239. package/skills/craft/remotion-best-practices/rules/timing.md +130 -130
  240. package/skills/craft/remotion-best-practices/rules/transcribe-captions.md +70 -70
  241. package/skills/craft/remotion-best-practices/rules/transitions.md +193 -193
  242. package/skills/craft/remotion-best-practices/rules/transparent-videos.md +102 -102
  243. package/skills/craft/remotion-best-practices/rules/trimming.md +51 -51
  244. package/skills/craft/remotion-best-practices/rules/videos.md +169 -169
  245. package/skills/craft/remotion-best-practices/rules/voiceover.md +94 -94
  246. package/skills/craft/supabase-postgres-best-practices/CHANGELOG.md +25 -25
  247. package/skills/craft/supabase-postgres-best-practices/LICENSE +21 -21
  248. package/skills/craft/supabase-postgres-best-practices/SKILL.md +69 -69
  249. package/skills/craft/supabase-postgres-best-practices/references/_contributing.md +166 -166
  250. package/skills/craft/supabase-postgres-best-practices/references/_sections.md +47 -47
  251. package/skills/craft/supabase-postgres-best-practices/references/_template.md +34 -34
  252. package/skills/craft/supabase-postgres-best-practices/references/advanced-full-text-search.md +55 -55
  253. package/skills/craft/supabase-postgres-best-practices/references/advanced-jsonb-indexing.md +49 -49
  254. package/skills/craft/supabase-postgres-best-practices/references/conn-idle-timeout.md +46 -46
  255. package/skills/craft/supabase-postgres-best-practices/references/conn-limits.md +44 -44
  256. package/skills/craft/supabase-postgres-best-practices/references/conn-pooling.md +41 -41
  257. package/skills/craft/supabase-postgres-best-practices/references/conn-prepared-statements.md +46 -46
  258. package/skills/craft/supabase-postgres-best-practices/references/data-batch-inserts.md +54 -54
  259. package/skills/craft/supabase-postgres-best-practices/references/data-n-plus-one.md +53 -53
  260. package/skills/craft/supabase-postgres-best-practices/references/data-pagination.md +50 -50
  261. package/skills/craft/supabase-postgres-best-practices/references/data-upsert.md +50 -50
  262. package/skills/craft/supabase-postgres-best-practices/references/lock-advisory.md +56 -56
  263. package/skills/craft/supabase-postgres-best-practices/references/lock-deadlock-prevention.md +68 -68
  264. package/skills/craft/supabase-postgres-best-practices/references/lock-short-transactions.md +50 -50
  265. package/skills/craft/supabase-postgres-best-practices/references/lock-skip-locked.md +54 -54
  266. package/skills/craft/supabase-postgres-best-practices/references/monitor-explain-analyze.md +45 -45
  267. package/skills/craft/supabase-postgres-best-practices/references/monitor-pg-stat-statements.md +55 -55
  268. package/skills/craft/supabase-postgres-best-practices/references/monitor-vacuum-analyze.md +55 -55
  269. package/skills/craft/supabase-postgres-best-practices/references/query-composite-indexes.md +44 -44
  270. package/skills/craft/supabase-postgres-best-practices/references/query-covering-indexes.md +40 -40
  271. package/skills/craft/supabase-postgres-best-practices/references/query-index-types.md +48 -48
  272. package/skills/craft/supabase-postgres-best-practices/references/query-missing-indexes.md +43 -43
  273. package/skills/craft/supabase-postgres-best-practices/references/query-partial-indexes.md +45 -45
  274. package/skills/craft/supabase-postgres-best-practices/references/schema-constraints.md +80 -80
  275. package/skills/craft/supabase-postgres-best-practices/references/schema-data-types.md +46 -46
  276. package/skills/craft/supabase-postgres-best-practices/references/schema-foreign-key-indexes.md +59 -59
  277. package/skills/craft/supabase-postgres-best-practices/references/schema-lowercase-identifiers.md +55 -55
  278. package/skills/craft/supabase-postgres-best-practices/references/schema-partitioning.md +55 -55
  279. package/skills/craft/supabase-postgres-best-practices/references/schema-primary-keys.md +61 -61
  280. package/skills/craft/supabase-postgres-best-practices/references/security-privileges.md +54 -54
  281. package/skills/craft/supabase-postgres-best-practices/references/security-rls-basics.md +50 -50
  282. package/skills/craft/supabase-postgres-best-practices/references/security-rls-performance.md +63 -63
  283. package/skills/craft/uipm-banner-design/LICENSE +21 -21
  284. package/skills/craft/uipm-banner-design/SKILL.md +201 -201
  285. package/skills/craft/uipm-banner-design/references/banner-sizes-and-styles.md +129 -129
  286. package/skills/craft/uipm-brand/LICENSE +21 -21
  287. package/skills/craft/uipm-brand/SKILL.md +104 -104
  288. package/skills/craft/uipm-brand/references/approval-checklist.md +184 -184
  289. package/skills/craft/uipm-brand/references/asset-organization.md +167 -167
  290. package/skills/craft/uipm-brand/references/brand-guideline-template.md +161 -161
  291. package/skills/craft/uipm-brand/references/color-palette-management.md +203 -203
  292. package/skills/craft/uipm-brand/references/consistency-checklist.md +105 -105
  293. package/skills/craft/uipm-brand/references/logo-usage-rules.md +204 -204
  294. package/skills/craft/uipm-brand/references/messaging-framework.md +91 -91
  295. package/skills/craft/uipm-brand/references/typography-specifications.md +265 -265
  296. package/skills/craft/uipm-brand/references/update.md +128 -128
  297. package/skills/craft/uipm-brand/references/visual-identity.md +109 -109
  298. package/skills/craft/uipm-brand/references/voice-framework.md +99 -99
  299. package/skills/craft/uipm-brand/scripts/extract-colors.cjs +333 -333
  300. package/skills/craft/uipm-brand/scripts/inject-brand-context.cjs +324 -324
  301. package/skills/craft/uipm-brand/scripts/sync-brand-to-tokens.cjs +269 -269
  302. package/skills/craft/uipm-brand/scripts/validate-asset.cjs +361 -361
  303. package/skills/craft/uipm-brand/templates/brand-guidelines-starter.md +280 -280
  304. package/skills/craft/uipm-design/LICENSE +21 -21
  305. package/skills/craft/uipm-design/SKILL.md +305 -305
  306. package/skills/craft/uipm-design/data/cip/deliverables.csv +50 -50
  307. package/skills/craft/uipm-design/data/cip/industries.csv +20 -20
  308. package/skills/craft/uipm-design/data/cip/mockup-contexts.csv +20 -20
  309. package/skills/craft/uipm-design/data/cip/styles.csv +20 -20
  310. package/skills/craft/uipm-design/data/icon/styles.csv +16 -16
  311. package/skills/craft/uipm-design/data/logo/colors.csv +56 -56
  312. package/skills/craft/uipm-design/data/logo/industries.csv +56 -56
  313. package/skills/craft/uipm-design/data/logo/styles.csv +56 -56
  314. package/skills/craft/uipm-design/references/banner-sizes-and-styles.md +129 -129
  315. package/skills/craft/uipm-design/references/cip-deliverable-guide.md +111 -111
  316. package/skills/craft/uipm-design/references/cip-design.md +121 -121
  317. package/skills/craft/uipm-design/references/cip-prompt-engineering.md +94 -94
  318. package/skills/craft/uipm-design/references/cip-style-guide.md +76 -76
  319. package/skills/craft/uipm-design/references/design-routing.md +226 -226
  320. package/skills/craft/uipm-design/references/icon-design.md +122 -122
  321. package/skills/craft/uipm-design/references/logo-color-psychology.md +113 -113
  322. package/skills/craft/uipm-design/references/logo-design.md +92 -92
  323. package/skills/craft/uipm-design/references/logo-prompt-engineering.md +176 -176
  324. package/skills/craft/uipm-design/references/logo-style-guide.md +129 -129
  325. package/skills/craft/uipm-design/references/slides-copywriting-formulas.md +92 -92
  326. package/skills/craft/uipm-design/references/slides-create.md +5 -5
  327. package/skills/craft/uipm-design/references/slides-html-template.md +374 -374
  328. package/skills/craft/uipm-design/references/slides-layout-patterns.md +155 -155
  329. package/skills/craft/uipm-design/references/slides-strategies.md +97 -97
  330. package/skills/craft/uipm-design/references/slides.md +42 -42
  331. package/skills/craft/uipm-design/references/social-photos-design.md +353 -353
  332. package/skills/craft/uipm-design/scripts/cip/core.py +215 -215
  333. package/skills/craft/uipm-design/scripts/cip/generate.py +484 -484
  334. package/skills/craft/uipm-design/scripts/cip/render-html.py +424 -424
  335. package/skills/craft/uipm-design/scripts/cip/search.py +127 -127
  336. package/skills/craft/uipm-design/scripts/icon/generate.py +487 -487
  337. package/skills/craft/uipm-design/scripts/logo/core.py +175 -175
  338. package/skills/craft/uipm-design/scripts/logo/generate.py +362 -362
  339. package/skills/craft/uipm-design/scripts/logo/search.py +114 -114
  340. package/skills/craft/uipm-design-system/LICENSE +21 -21
  341. package/skills/craft/uipm-design-system/SKILL.md +255 -255
  342. package/skills/craft/uipm-design-system/data/slide-backgrounds.csv +11 -11
  343. package/skills/craft/uipm-design-system/data/slide-charts.csv +26 -26
  344. package/skills/craft/uipm-design-system/data/slide-color-logic.csv +14 -14
  345. package/skills/craft/uipm-design-system/data/slide-copy.csv +26 -26
  346. package/skills/craft/uipm-design-system/data/slide-layout-logic.csv +16 -16
  347. package/skills/craft/uipm-design-system/data/slide-layouts.csv +26 -26
  348. package/skills/craft/uipm-design-system/data/slide-strategies.csv +16 -16
  349. package/skills/craft/uipm-design-system/data/slide-typography.csv +15 -15
  350. package/skills/craft/uipm-design-system/references/component-specs.md +236 -236
  351. package/skills/craft/uipm-design-system/references/component-tokens.md +214 -214
  352. package/skills/craft/uipm-design-system/references/primitive-tokens.md +199 -199
  353. package/skills/craft/uipm-design-system/references/semantic-tokens.md +215 -215
  354. package/skills/craft/uipm-design-system/references/states-and-variants.md +243 -243
  355. package/skills/craft/uipm-design-system/references/tailwind-integration.md +257 -257
  356. package/skills/craft/uipm-design-system/references/token-architecture.md +226 -226
  357. package/skills/craft/uipm-design-system/scripts/embed-tokens.cjs +97 -97
  358. package/skills/craft/uipm-design-system/scripts/fetch-background.py +317 -317
  359. package/skills/craft/uipm-design-system/scripts/generate-slide.py +753 -753
  360. package/skills/craft/uipm-design-system/scripts/generate-tokens.cjs +213 -213
  361. package/skills/craft/uipm-design-system/scripts/html-token-validator.py +327 -327
  362. package/skills/craft/uipm-design-system/scripts/search-slides.py +218 -218
  363. package/skills/craft/uipm-design-system/scripts/slide-token-validator.py +35 -35
  364. package/skills/craft/uipm-design-system/scripts/slide_search_core.py +453 -453
  365. package/skills/craft/uipm-design-system/scripts/validate-tokens.cjs +254 -254
  366. package/skills/craft/uipm-design-system/templates/design-tokens-starter.json +143 -143
  367. package/skills/craft/uipm-slides/LICENSE +21 -21
  368. package/skills/craft/uipm-slides/SKILL.md +45 -45
  369. package/skills/craft/uipm-slides/references/copywriting-formulas.md +92 -92
  370. package/skills/craft/uipm-slides/references/create.md +5 -5
  371. package/skills/craft/uipm-slides/references/html-template.md +374 -374
  372. package/skills/craft/uipm-slides/references/layout-patterns.md +155 -155
  373. package/skills/craft/uipm-slides/references/slide-strategies.md +97 -97
  374. package/skills/craft/uipm-ui-ux-pro-max/LICENSE +21 -21
  375. package/skills/craft/uipm-ui-ux-pro-max/SKILL.md +678 -678
  376. package/skills/craft/uipm-ui-ux-pro-max/data/_sync_all.py +414 -414
  377. package/skills/craft/uipm-ui-ux-pro-max/data/app-interface.csv +30 -30
  378. package/skills/craft/uipm-ui-ux-pro-max/data/charts.csv +26 -26
  379. package/skills/craft/uipm-ui-ux-pro-max/data/colors.csv +161 -161
  380. package/skills/craft/uipm-ui-ux-pro-max/data/design.csv +1775 -1775
  381. package/skills/craft/uipm-ui-ux-pro-max/data/draft.csv +1778 -1778
  382. package/skills/craft/uipm-ui-ux-pro-max/data/google-fonts.csv +1924 -1924
  383. package/skills/craft/uipm-ui-ux-pro-max/data/icons.csv +105 -105
  384. package/skills/craft/uipm-ui-ux-pro-max/data/landing.csv +35 -35
  385. package/skills/craft/uipm-ui-ux-pro-max/data/products.csv +162 -162
  386. package/skills/craft/uipm-ui-ux-pro-max/data/react-performance.csv +45 -45
  387. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/angular.csv +51 -51
  388. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/astro.csv +54 -54
  389. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/flutter.csv +53 -53
  390. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/html-tailwind.csv +56 -56
  391. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/jetpack-compose.csv +53 -53
  392. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/laravel.csv +51 -51
  393. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nextjs.csv +53 -53
  394. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nuxt-ui.csv +51 -51
  395. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/nuxtjs.csv +59 -59
  396. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/react-native.csv +52 -52
  397. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/react.csv +54 -54
  398. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/shadcn.csv +61 -61
  399. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/svelte.csv +54 -54
  400. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/swiftui.csv +51 -51
  401. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/threejs.csv +54 -54
  402. package/skills/craft/uipm-ui-ux-pro-max/data/stacks/vue.csv +50 -50
  403. package/skills/craft/uipm-ui-ux-pro-max/data/styles.csv +85 -85
  404. package/skills/craft/uipm-ui-ux-pro-max/data/typography.csv +74 -74
  405. package/skills/craft/uipm-ui-ux-pro-max/data/ui-reasoning.csv +162 -162
  406. package/skills/craft/uipm-ui-ux-pro-max/data/ux-guidelines.csv +99 -99
  407. package/skills/craft/uipm-ui-ux-pro-max/scripts/core.py +262 -262
  408. package/skills/craft/uipm-ui-ux-pro-max/scripts/design_system.py +1148 -1148
  409. package/skills/craft/uipm-ui-ux-pro-max/scripts/search.py +114 -114
  410. package/skills/craft/uipm-ui-ux-pro-max/templates/base/quick-reference.md +297 -297
  411. package/skills/craft/uipm-ui-ux-pro-max/templates/base/skill-content.md +375 -375
  412. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/agent.json +21 -21
  413. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/augment.json +18 -18
  414. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/claude.json +21 -21
  415. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/codebuddy.json +21 -21
  416. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/codex.json +21 -21
  417. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/continue.json +21 -21
  418. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/copilot.json +21 -21
  419. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/cursor.json +21 -21
  420. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/droid.json +21 -21
  421. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/gemini.json +21 -21
  422. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/kilocode.json +21 -21
  423. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/kiro.json +21 -21
  424. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/opencode.json +21 -21
  425. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/qoder.json +21 -21
  426. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/roocode.json +21 -21
  427. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/trae.json +21 -21
  428. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/warp.json +18 -18
  429. package/skills/craft/uipm-ui-ux-pro-max/templates/platforms/windsurf.json +21 -21
  430. package/skills/craft/vercel-optimize/AGENTS.md +48 -48
  431. package/skills/craft/vercel-optimize/CONTRIBUTING.md +41 -41
  432. package/skills/craft/vercel-optimize/LICENSE +21 -21
  433. package/skills/craft/vercel-optimize/README.md +91 -91
  434. package/skills/craft/vercel-optimize/SKILL.md +325 -325
  435. package/skills/craft/vercel-optimize/lib/auth-route.mjs +23 -23
  436. package/skills/craft/vercel-optimize/lib/budget-summary.mjs +208 -208
  437. package/skills/craft/vercel-optimize/lib/citations.mjs +147 -147
  438. package/skills/craft/vercel-optimize/lib/cost-coverage.mjs +162 -162
  439. package/skills/craft/vercel-optimize/lib/dedup-recs.mjs +340 -340
  440. package/skills/craft/vercel-optimize/lib/deep-dive.mjs +371 -371
  441. package/skills/craft/vercel-optimize/lib/display-labels.mjs +219 -219
  442. package/skills/craft/vercel-optimize/lib/extract-claims.mjs +640 -640
  443. package/skills/craft/vercel-optimize/lib/framework-support.mjs +69 -69
  444. package/skills/craft/vercel-optimize/lib/gates/build-minutes-fanout.mjs +73 -73
  445. package/skills/craft/vercel-optimize/lib/gates/cold-start.mjs +72 -72
  446. package/skills/craft/vercel-optimize/lib/gates/contract.mjs +82 -82
  447. package/skills/craft/vercel-optimize/lib/gates/cwv-poor.mjs +95 -95
  448. package/skills/craft/vercel-optimize/lib/gates/external-api-slow.mjs +60 -60
  449. package/skills/craft/vercel-optimize/lib/gates/hard-gates.mjs +70 -70
  450. package/skills/craft/vercel-optimize/lib/gates/index.mjs +45 -45
  451. package/skills/craft/vercel-optimize/lib/gates/isr-overrevalidation.mjs +62 -62
  452. package/skills/craft/vercel-optimize/lib/gates/middleware-heavy.mjs +53 -53
  453. package/skills/craft/vercel-optimize/lib/gates/observability-events-attribution.mjs +58 -58
  454. package/skills/craft/vercel-optimize/lib/gates/platform-bot-protection.mjs +123 -123
  455. package/skills/craft/vercel-optimize/lib/gates/platform-fluid-compute.mjs +94 -94
  456. package/skills/craft/vercel-optimize/lib/gates/region-misconfig.mjs +71 -71
  457. package/skills/craft/vercel-optimize/lib/gates/route-errors.mjs +95 -95
  458. package/skills/craft/vercel-optimize/lib/gates/scanner-driven.mjs +150 -150
  459. package/skills/craft/vercel-optimize/lib/gates/select-candidates.mjs +137 -137
  460. package/skills/craft/vercel-optimize/lib/gates/slow-route.mjs +97 -97
  461. package/skills/craft/vercel-optimize/lib/gates/types.d.ts +38 -38
  462. package/skills/craft/vercel-optimize/lib/gates/uncached-route.mjs +103 -103
  463. package/skills/craft/vercel-optimize/lib/gates/usage-spike-triage.mjs +122 -122
  464. package/skills/craft/vercel-optimize/lib/grade-recommendation.mjs +170 -170
  465. package/skills/craft/vercel-optimize/lib/impact-label.mjs +128 -128
  466. package/skills/craft/vercel-optimize/lib/impact-magnitude.mjs +66 -66
  467. package/skills/craft/vercel-optimize/lib/investigation-brief.mjs +751 -751
  468. package/skills/craft/vercel-optimize/lib/observation-safety.mjs +217 -217
  469. package/skills/craft/vercel-optimize/lib/project-facts.mjs +101 -101
  470. package/skills/craft/vercel-optimize/lib/queries.mjs +333 -333
  471. package/skills/craft/vercel-optimize/lib/reconcile-candidates.mjs +388 -388
  472. package/skills/craft/vercel-optimize/lib/render-report.mjs +1065 -1065
  473. package/skills/craft/vercel-optimize/lib/repo-root.mjs +97 -97
  474. package/skills/craft/vercel-optimize/lib/route-normalize.mjs +224 -224
  475. package/skills/craft/vercel-optimize/lib/sanitizers/bot-protection-certainty.mjs +56 -56
  476. package/skills/craft/vercel-optimize/lib/sanitizers/cache-tag-invalidation-certainty.mjs +33 -33
  477. package/skills/craft/vercel-optimize/lib/sanitizers/count-correct.mjs +53 -53
  478. package/skills/craft/vercel-optimize/lib/sanitizers/function-duration-invocations.mjs +32 -32
  479. package/skills/craft/vercel-optimize/lib/sanitizers/index.mjs +87 -87
  480. package/skills/craft/vercel-optimize/lib/sanitizers/middleware-conflict.mjs +37 -37
  481. package/skills/craft/vercel-optimize/lib/sanitizers/missing-citation.mjs +16 -16
  482. package/skills/craft/vercel-optimize/lib/sanitizers/pre-release.mjs +75 -75
  483. package/skills/craft/vercel-optimize/lib/sanitizers/rate-limit.mjs +73 -73
  484. package/skills/craft/vercel-optimize/lib/sanitizers/rendering-mode-mislabel.mjs +42 -42
  485. package/skills/craft/vercel-optimize/lib/sanitizers/undeclared-dep.mjs +110 -110
  486. package/skills/craft/vercel-optimize/lib/sanitizers/vercel-directive-strip.mjs +37 -37
  487. package/skills/craft/vercel-optimize/lib/sanitizers/window-units.mjs +26 -26
  488. package/skills/craft/vercel-optimize/lib/scanners/cache-components-suspense-dedupe.mjs +114 -114
  489. package/skills/craft/vercel-optimize/lib/scanners/edge-heavy-import.mjs +102 -102
  490. package/skills/craft/vercel-optimize/lib/scanners/force-dynamic.mjs +39 -39
  491. package/skills/craft/vercel-optimize/lib/scanners/headers-in-page.mjs +43 -43
  492. package/skills/craft/vercel-optimize/lib/scanners/index.mjs +35 -35
  493. package/skills/craft/vercel-optimize/lib/scanners/large-static-asset.mjs +93 -93
  494. package/skills/craft/vercel-optimize/lib/scanners/max-age-without-s-maxage.mjs +47 -47
  495. package/skills/craft/vercel-optimize/lib/scanners/middleware-broad-matcher.mjs +53 -53
  496. package/skills/craft/vercel-optimize/lib/scanners/missing-cache-headers.mjs +97 -97
  497. package/skills/craft/vercel-optimize/lib/scanners/prisma-include-tree.mjs +39 -39
  498. package/skills/craft/vercel-optimize/lib/scanners/region-pin-in-config.mjs +89 -89
  499. package/skills/craft/vercel-optimize/lib/scanners/source-maps-production.mjs +33 -33
  500. package/skills/craft/vercel-optimize/lib/scanners/sveltekit-prerender-missing.mjs +47 -47
  501. package/skills/craft/vercel-optimize/lib/scanners/turbo-force-bypass.mjs +136 -136
  502. package/skills/craft/vercel-optimize/lib/scanners/unoptimized-image.mjs +127 -127
  503. package/skills/craft/vercel-optimize/lib/scanners/use-cache-date-stamp.mjs +112 -112
  504. package/skills/craft/vercel-optimize/lib/support-topics.mjs +365 -365
  505. package/skills/craft/vercel-optimize/lib/throttle.mjs +280 -280
  506. package/skills/craft/vercel-optimize/lib/util.mjs +17 -17
  507. package/skills/craft/vercel-optimize/lib/vercel.mjs +855 -855
  508. package/skills/craft/vercel-optimize/lib/verify-claim.mjs +1843 -1843
  509. package/skills/craft/vercel-optimize/lib/workspace-resolver.mjs +552 -552
  510. package/skills/craft/vercel-optimize/metadata.json +14 -14
  511. package/skills/craft/vercel-optimize/references/candidates.md +176 -176
  512. package/skills/craft/vercel-optimize/references/data-collection.md +224 -224
  513. package/skills/craft/vercel-optimize/references/docs-library.json +683 -683
  514. package/skills/craft/vercel-optimize/references/doctrine.md +108 -108
  515. package/skills/craft/vercel-optimize/references/observability-plus.md +109 -109
  516. package/skills/craft/vercel-optimize/references/playbooks/README.md +57 -57
  517. package/skills/craft/vercel-optimize/references/playbooks/ai-application.md +32 -32
  518. package/skills/craft/vercel-optimize/references/playbooks/api-service.md +30 -30
  519. package/skills/craft/vercel-optimize/references/playbooks/content-site.md +30 -30
  520. package/skills/craft/vercel-optimize/references/playbooks/ecommerce.md +30 -30
  521. package/skills/craft/vercel-optimize/references/playbooks/marketing.md +30 -30
  522. package/skills/craft/vercel-optimize/references/playbooks/saas.md +31 -31
  523. package/skills/craft/vercel-optimize/references/playbooks/sveltekit.md +75 -75
  524. package/skills/craft/vercel-optimize/references/recommendations.md +214 -214
  525. package/skills/craft/vercel-optimize/references/scanner-patterns.md +266 -266
  526. package/skills/craft/vercel-optimize/references/scoring.md +208 -208
  527. package/skills/craft/vercel-optimize/references/support-topics/README.md +50 -50
  528. package/skills/craft/vercel-optimize/references/support-topics/astro-edge-middleware-scope.md +30 -30
  529. package/skills/craft/vercel-optimize/references/support-topics/astro-output-mode-and-isr.md +31 -31
  530. package/skills/craft/vercel-optimize/references/support-topics/auth-preserving-parallelization.md +30 -30
  531. package/skills/craft/vercel-optimize/references/support-topics/bot-protection-product-guardrails.md +32 -32
  532. package/skills/craft/vercel-optimize/references/support-topics/build-minutes-monorepo-fanout.md +32 -32
  533. package/skills/craft/vercel-optimize/references/support-topics/cache-components-static-shell-boundaries.md +31 -31
  534. package/skills/craft/vercel-optimize/references/support-topics/cache-components-suspense-dedupe-pitfall.md +32 -32
  535. package/skills/craft/vercel-optimize/references/support-topics/cdn-cache-auth-safety.md +31 -31
  536. package/skills/craft/vercel-optimize/references/support-topics/cold-start-initialization-bundle.md +31 -31
  537. package/skills/craft/vercel-optimize/references/support-topics/core-web-vitals-client-bottlenecks.md +33 -33
  538. package/skills/craft/vercel-optimize/references/support-topics/database-egress-pooling-region.md +32 -32
  539. package/skills/craft/vercel-optimize/references/support-topics/dynamic-rendering-traps.md +31 -31
  540. package/skills/craft/vercel-optimize/references/support-topics/external-api-critical-path-platform.md +31 -31
  541. package/skills/craft/vercel-optimize/references/support-topics/external-api-critical-path.md +31 -31
  542. package/skills/craft/vercel-optimize/references/support-topics/fast-data-transfer-payloads.md +26 -26
  543. package/skills/craft/vercel-optimize/references/support-topics/fluid-compute-caveats.md +26 -26
  544. package/skills/craft/vercel-optimize/references/support-topics/function-duration-io-and-after.md +31 -31
  545. package/skills/craft/vercel-optimize/references/support-topics/function-invocation-reduction.md +31 -31
  546. package/skills/craft/vercel-optimize/references/support-topics/function-region-misconfiguration-ttfb.md +31 -31
  547. package/skills/craft/vercel-optimize/references/support-topics/image-optimization-cost-control.md +31 -31
  548. package/skills/craft/vercel-optimize/references/support-topics/isr-revalidation-static-generation.md +31 -31
  549. package/skills/craft/vercel-optimize/references/support-topics/middleware-proxy-edge-cost.md +30 -30
  550. package/skills/craft/vercel-optimize/references/support-topics/next-fetch-revalidate-floor.md +30 -30
  551. package/skills/craft/vercel-optimize/references/support-topics/next-font-cls-self-hosting.md +31 -31
  552. package/skills/craft/vercel-optimize/references/support-topics/next-heavy-ui-lazy-load-boundaries.md +28 -28
  553. package/skills/craft/vercel-optimize/references/support-topics/next-image-lcp-preload-sizes.md +31 -31
  554. package/skills/craft/vercel-optimize/references/support-topics/next-route-handler-get-cache-defaults.md +30 -30
  555. package/skills/craft/vercel-optimize/references/support-topics/next-script-third-party-strategy.md +31 -31
  556. package/skills/craft/vercel-optimize/references/support-topics/nextjs-version-cache-semantics.md +31 -31
  557. package/skills/craft/vercel-optimize/references/support-topics/not-found-catchall-request-waste.md +33 -33
  558. package/skills/craft/vercel-optimize/references/support-topics/nuxt-route-rules-cache-isr.md +31 -31
  559. package/skills/craft/vercel-optimize/references/support-topics/observability-events-cost-attribution.md +27 -27
  560. package/skills/craft/vercel-optimize/references/support-topics/post-response-work-waituntil.md +26 -26
  561. package/skills/craft/vercel-optimize/references/support-topics/route-error-durable-offload.md +33 -33
  562. package/skills/craft/vercel-optimize/references/support-topics/route-error-runtime-limits.md +31 -31
  563. package/skills/craft/vercel-optimize/references/support-topics/runtime-cache-reusable-data.md +30 -30
  564. package/skills/craft/vercel-optimize/references/support-topics/sveltekit-isr-prerender-safety.md +31 -31
  565. package/skills/craft/vercel-optimize/references/support-topics/sveltekit-split-cold-start-tradeoff.md +30 -30
  566. package/skills/craft/vercel-optimize/references/support-topics/usage-spike-triage.md +31 -31
  567. package/skills/craft/vercel-optimize/references/support-topics/use-cache-date-stamp-isr-write-amplifier.md +31 -31
  568. package/skills/craft/vercel-optimize/references/support-topics/use-cache-remote-shared-origin-data.md +30 -30
  569. package/skills/craft/vercel-optimize/references/support-topics/workflow-resumable-stream-routes.md +32 -32
  570. package/skills/craft/vercel-optimize/references/verification.md +102 -102
  571. package/skills/craft/vercel-optimize/references/voice.md +76 -76
  572. package/skills/craft/vercel-optimize/scripts/budget-summary.mjs +58 -58
  573. package/skills/craft/vercel-optimize/scripts/build-docs.mjs +76 -76
  574. package/skills/craft/vercel-optimize/scripts/check-citations.mjs +91 -91
  575. package/skills/craft/vercel-optimize/scripts/check-docs-fresh.mjs +100 -100
  576. package/skills/craft/vercel-optimize/scripts/collect-signals.mjs +638 -638
  577. package/skills/craft/vercel-optimize/scripts/collect-sub-agent-outputs.mjs +306 -306
  578. package/skills/craft/vercel-optimize/scripts/deep-dive.mjs +358 -358
  579. package/skills/craft/vercel-optimize/scripts/gate-investigations.mjs +178 -178
  580. package/skills/craft/vercel-optimize/scripts/merge-signals.mjs +203 -203
  581. package/skills/craft/vercel-optimize/scripts/prepare-investigation-brief.mjs +249 -249
  582. package/skills/craft/vercel-optimize/scripts/reconcile-candidates.mjs +69 -69
  583. package/skills/craft/vercel-optimize/scripts/render-report.mjs +462 -462
  584. package/skills/craft/vercel-optimize/scripts/scan-codebase.mjs +361 -361
  585. package/skills/craft/vercel-optimize/scripts/verify-and-regen.mjs +379 -379
  586. package/skills/craft/vercel-optimize/scripts/verify-finding.mjs +21 -21
  587. package/skills/craft/web-design-guidelines/LICENSE +21 -21
  588. package/skills/craft/web-design-guidelines/SKILL.md +43 -43
  589. package/skills/craft/zero-to-live/LICENSE +21 -21
  590. package/skills/craft/zero-to-live/SKILL.md +422 -422
  591. package/skills/creative/creative-3d-modeling/LICENSE +21 -21
  592. package/skills/creative/creative-3d-modeling/SKILL.md +70 -70
  593. package/skills/creative/creative-architecture/LICENSE +21 -21
  594. package/skills/creative/creative-architecture/SKILL.md +94 -94
  595. package/skills/creative/creative-design-principles/LICENSE +21 -21
  596. package/skills/creative/creative-design-principles/SKILL.md +95 -95
  597. package/skills/creative/creative-fashion-advanced/LICENSE +21 -21
  598. package/skills/creative/creative-fashion-advanced/SKILL.md +68 -68
  599. package/skills/creative/creative-fashion-design/LICENSE +21 -21
  600. package/skills/creative/creative-fashion-design/SKILL.md +66 -66
  601. package/skills/creative/creative-game-design/LICENSE +21 -21
  602. package/skills/creative/creative-game-design/SKILL.md +77 -77
  603. package/skills/creative/creative-industrial-design/LICENSE +21 -21
  604. package/skills/creative/creative-industrial-design/SKILL.md +57 -57
  605. package/skills/creative/creative-interior-design/LICENSE +21 -21
  606. package/skills/creative/creative-interior-design/SKILL.md +59 -59
  607. package/skills/creative/creative-music-theory/LICENSE +21 -21
  608. package/skills/creative/creative-music-theory/SKILL.md +98 -98
  609. package/skills/creative/creative-photography/LICENSE +21 -21
  610. package/skills/creative/creative-photography/SKILL.md +87 -87
  611. package/skills/creative/creative-textile-science/LICENSE +21 -21
  612. package/skills/creative/creative-textile-science/SKILL.md +67 -67
  613. package/skills/creative/creative-ux/LICENSE +21 -21
  614. package/skills/creative/creative-ux/SKILL.md +81 -81
  615. package/skills/creative/creative-video/LICENSE +21 -21
  616. package/skills/creative/creative-video/SKILL.md +84 -84
  617. package/skills/creative/creative-writing-craft/LICENSE +21 -21
  618. package/skills/creative/creative-writing-craft/SKILL.md +91 -91
  619. package/skills/diagram-maker/SKILL.md +56 -56
  620. package/skills/diagram-maker/references/excalidraw-patterns.md +85 -85
  621. package/skills/diagram-maker/references/svg-template.md +112 -112
  622. package/skills/discord/SKILL.md +140 -140
  623. package/skills/education/edu-adult-learning/LICENSE +21 -21
  624. package/skills/education/edu-adult-learning/SKILL.md +81 -81
  625. package/skills/education/edu-africa-multilingual/LICENSE +21 -21
  626. package/skills/education/edu-africa-multilingual/SKILL.md +55 -55
  627. package/skills/education/edu-arabic/LICENSE +21 -21
  628. package/skills/education/edu-arabic/SKILL.md +60 -60
  629. package/skills/education/edu-australia-nz/LICENSE +21 -21
  630. package/skills/education/edu-australia-nz/SKILL.md +48 -48
  631. package/skills/education/edu-china-mandarin/LICENSE +21 -21
  632. package/skills/education/edu-china-mandarin/SKILL.md +58 -58
  633. package/skills/education/edu-critical-thinking/LICENSE +21 -21
  634. package/skills/education/edu-critical-thinking/SKILL.md +86 -86
  635. package/skills/education/edu-curriculum/LICENSE +21 -21
  636. package/skills/education/edu-curriculum/SKILL.md +87 -87
  637. package/skills/education/edu-ed-tech/LICENSE +21 -21
  638. package/skills/education/edu-ed-tech/SKILL.md +73 -73
  639. package/skills/education/edu-france/LICENSE +21 -21
  640. package/skills/education/edu-france/SKILL.md +42 -42
  641. package/skills/education/edu-germany/LICENSE +21 -21
  642. package/skills/education/edu-germany/SKILL.md +46 -46
  643. package/skills/education/edu-india-competitive/LICENSE +21 -21
  644. package/skills/education/edu-india-competitive/SKILL.md +159 -159
  645. package/skills/education/edu-india-east/LICENSE +21 -21
  646. package/skills/education/edu-india-east/SKILL.md +60 -60
  647. package/skills/education/edu-india-hindi/LICENSE +21 -21
  648. package/skills/education/edu-india-hindi/SKILL.md +107 -107
  649. package/skills/education/edu-india-south/LICENSE +21 -21
  650. package/skills/education/edu-india-south/SKILL.md +64 -64
  651. package/skills/education/edu-india-west/LICENSE +21 -21
  652. package/skills/education/edu-india-west/SKILL.md +68 -68
  653. package/skills/education/edu-indonesia-malay/LICENSE +21 -21
  654. package/skills/education/edu-indonesia-malay/SKILL.md +57 -57
  655. package/skills/education/edu-international-ib/LICENSE +21 -21
  656. package/skills/education/edu-international-ib/SKILL.md +61 -61
  657. package/skills/education/edu-japan/LICENSE +21 -21
  658. package/skills/education/edu-japan/SKILL.md +48 -48
  659. package/skills/education/edu-korea/LICENSE +21 -21
  660. package/skills/education/edu-korea/SKILL.md +48 -48
  661. package/skills/education/edu-learning-science/LICENSE +21 -21
  662. package/skills/education/edu-learning-science/SKILL.md +76 -76
  663. package/skills/education/edu-portuguese-brazil/LICENSE +21 -21
  664. package/skills/education/edu-portuguese-brazil/SKILL.md +51 -51
  665. package/skills/education/edu-russia/LICENSE +21 -21
  666. package/skills/education/edu-russia/SKILL.md +50 -50
  667. package/skills/education/edu-spain-latam/LICENSE +21 -21
  668. package/skills/education/edu-spain-latam/SKILL.md +55 -55
  669. package/skills/education/edu-special/LICENSE +21 -21
  670. package/skills/education/edu-special/SKILL.md +76 -76
  671. package/skills/education/edu-thailand/LICENSE +21 -21
  672. package/skills/education/edu-thailand/SKILL.md +55 -55
  673. package/skills/education/edu-turkey/LICENSE +21 -21
  674. package/skills/education/edu-turkey/SKILL.md +58 -58
  675. package/skills/education/edu-uk-gcse-alevel/LICENSE +21 -21
  676. package/skills/education/edu-uk-gcse-alevel/SKILL.md +51 -51
  677. package/skills/education/edu-usa-graduate/LICENSE +21 -21
  678. package/skills/education/edu-usa-graduate/SKILL.md +57 -57
  679. package/skills/education/edu-usa-sat-act/LICENSE +21 -21
  680. package/skills/education/edu-usa-sat-act/SKILL.md +55 -55
  681. package/skills/education/edu-vietnam/LICENSE +21 -21
  682. package/skills/education/edu-vietnam/SKILL.md +53 -53
  683. package/skills/eightctl/SKILL.md +54 -54
  684. package/skills/engineering/eng-aerospace/LICENSE +21 -21
  685. package/skills/engineering/eng-aerospace/SKILL.md +117 -117
  686. package/skills/engineering/eng-chemical/LICENSE +21 -21
  687. package/skills/engineering/eng-chemical/SKILL.md +63 -63
  688. package/skills/engineering/eng-civil/LICENSE +21 -21
  689. package/skills/engineering/eng-civil/SKILL.md +223 -223
  690. package/skills/engineering/eng-control-systems/LICENSE +21 -21
  691. package/skills/engineering/eng-control-systems/SKILL.md +158 -158
  692. package/skills/engineering/eng-cryogenics/LICENSE +21 -21
  693. package/skills/engineering/eng-cryogenics/SKILL.md +151 -151
  694. package/skills/engineering/eng-electrical/LICENSE +21 -21
  695. package/skills/engineering/eng-electrical/SKILL.md +70 -70
  696. package/skills/engineering/eng-electronics-embedded/LICENSE +21 -21
  697. package/skills/engineering/eng-electronics-embedded/SKILL.md +89 -89
  698. package/skills/engineering/eng-environmental/LICENSE +21 -21
  699. package/skills/engineering/eng-environmental/SKILL.md +66 -66
  700. package/skills/engineering/eng-manufacturing/LICENSE +21 -21
  701. package/skills/engineering/eng-manufacturing/SKILL.md +78 -78
  702. package/skills/engineering/eng-mechanical/LICENSE +21 -21
  703. package/skills/engineering/eng-mechanical/SKILL.md +66 -66
  704. package/skills/engineering/eng-project/LICENSE +21 -21
  705. package/skills/engineering/eng-project/SKILL.md +72 -72
  706. package/skills/engineering/eng-propulsion/LICENSE +21 -21
  707. package/skills/engineering/eng-propulsion/SKILL.md +133 -133
  708. package/skills/engineering/eng-robotics/LICENSE +21 -21
  709. package/skills/engineering/eng-robotics/SKILL.md +92 -92
  710. package/skills/engineering/eng-systems/LICENSE +21 -21
  711. package/skills/engineering/eng-systems/SKILL.md +81 -81
  712. package/skills/environment/env-biodiversity/LICENSE +21 -21
  713. package/skills/environment/env-biodiversity/SKILL.md +66 -66
  714. package/skills/environment/env-circular-economy/LICENSE +21 -21
  715. package/skills/environment/env-circular-economy/SKILL.md +71 -71
  716. package/skills/environment/env-climate-action/LICENSE +21 -21
  717. package/skills/environment/env-climate-action/SKILL.md +55 -55
  718. package/skills/environment/env-energy/LICENSE +21 -21
  719. package/skills/environment/env-energy/SKILL.md +83 -83
  720. package/skills/environment/env-sustainability-biz/LICENSE +21 -21
  721. package/skills/environment/env-sustainability-biz/SKILL.md +65 -65
  722. package/skills/environment/env-water/LICENSE +21 -21
  723. package/skills/environment/env-water/SKILL.md +67 -67
  724. package/skills/finance/finance-accounting/LICENSE +21 -21
  725. package/skills/finance/finance-accounting/SKILL.md +239 -239
  726. package/skills/finance/finance-banking/LICENSE +21 -21
  727. package/skills/finance/finance-banking/SKILL.md +54 -54
  728. package/skills/finance/finance-corporate/LICENSE +21 -21
  729. package/skills/finance/finance-corporate/SKILL.md +105 -105
  730. package/skills/finance/finance-crypto/LICENSE +21 -21
  731. package/skills/finance/finance-crypto/SKILL.md +94 -94
  732. package/skills/finance/finance-debt-management/LICENSE +21 -21
  733. package/skills/finance/finance-debt-management/SKILL.md +87 -87
  734. package/skills/finance/finance-insurance/LICENSE +21 -21
  735. package/skills/finance/finance-insurance/SKILL.md +91 -91
  736. package/skills/finance/finance-investing/LICENSE +21 -21
  737. package/skills/finance/finance-investing/SKILL.md +269 -269
  738. package/skills/finance/finance-options-derivatives/LICENSE +21 -21
  739. package/skills/finance/finance-options-derivatives/SKILL.md +68 -68
  740. package/skills/finance/finance-personal/LICENSE +21 -21
  741. package/skills/finance/finance-personal/SKILL.md +268 -268
  742. package/skills/finance/finance-real-estate/LICENSE +21 -21
  743. package/skills/finance/finance-real-estate/SKILL.md +110 -110
  744. package/skills/finance/finance-startup/LICENSE +21 -21
  745. package/skills/finance/finance-startup/SKILL.md +253 -253
  746. package/skills/finance/finance-tax-planning/LICENSE +21 -21
  747. package/skills/finance/finance-tax-planning/SKILL.md +89 -89
  748. package/skills/finance/finance-trading/LICENSE +21 -21
  749. package/skills/finance/finance-trading/SKILL.md +112 -112
  750. package/skills/gemini/SKILL.md +51 -51
  751. package/skills/gh-issues/SKILL.md +216 -216
  752. package/skills/gifgrep/SKILL.md +89 -89
  753. package/skills/github/SKILL.md +87 -87
  754. package/skills/gog/SKILL.md +120 -120
  755. package/skills/goplaces/SKILL.md +56 -56
  756. package/skills/graphify/SKILL.md +619 -0
  757. package/skills/graphify/__init__.py +28 -0
  758. package/skills/graphify/__main__.py +4582 -0
  759. package/skills/graphify/affected.py +154 -0
  760. package/skills/graphify/always_on/agents-md.md +12 -0
  761. package/skills/graphify/always_on/antigravity-rules.md +14 -0
  762. package/skills/graphify/always_on/claude-md.md +9 -0
  763. package/skills/graphify/always_on/gemini-md.md +9 -0
  764. package/skills/graphify/always_on/kiro-steering.md +5 -0
  765. package/skills/graphify/always_on/vscode-instructions.md +17 -0
  766. package/skills/graphify/analyze.py +724 -0
  767. package/skills/graphify/benchmark.py +155 -0
  768. package/skills/graphify/build.py +487 -0
  769. package/skills/graphify/cache.py +417 -0
  770. package/skills/graphify/callflow_html.py +2020 -0
  771. package/skills/graphify/cluster.py +272 -0
  772. package/skills/graphify/command-kilo.md +15 -0
  773. package/skills/graphify/dedup.py +429 -0
  774. package/skills/graphify/detect.py +1379 -0
  775. package/skills/graphify/diagnostics.py +390 -0
  776. package/skills/graphify/export.py +1408 -0
  777. package/skills/graphify/extract.py +11570 -0
  778. package/skills/graphify/global_graph.py +159 -0
  779. package/skills/graphify/google_workspace.py +223 -0
  780. package/skills/graphify/hooks.py +457 -0
  781. package/skills/graphify/ingest.py +331 -0
  782. package/skills/graphify/llm.py +1896 -0
  783. package/skills/graphify/manifest.py +4 -0
  784. package/skills/graphify/mcp_ingest.py +392 -0
  785. package/skills/graphify/multigraph_compat.py +212 -0
  786. package/skills/graphify/pg_introspect.py +142 -0
  787. package/skills/graphify/prs.py +748 -0
  788. package/skills/graphify/querylog.py +70 -0
  789. package/skills/graphify/report.py +218 -0
  790. package/skills/graphify/scip_ingest.py +363 -0
  791. package/skills/graphify/security.py +336 -0
  792. package/skills/graphify/semantic_cleanup.py +319 -0
  793. package/skills/graphify/serve.py +1309 -0
  794. package/skills/graphify/skill-aider.md +1246 -0
  795. package/skills/graphify/skill-amp.md +613 -0
  796. package/skills/graphify/skill-claw.md +616 -0
  797. package/skills/graphify/skill-codex.md +613 -0
  798. package/skills/graphify/skill-copilot.md +616 -0
  799. package/skills/graphify/skill-devin.md +1372 -0
  800. package/skills/graphify/skill-droid.md +613 -0
  801. package/skills/graphify/skill-kilo.md +625 -0
  802. package/skills/graphify/skill-kiro.md +615 -0
  803. package/skills/graphify/skill-opencode.md +608 -0
  804. package/skills/graphify/skill-pi.md +615 -0
  805. package/skills/graphify/skill-trae.md +614 -0
  806. package/skills/graphify/skill-vscode.md +612 -0
  807. package/skills/graphify/skill-windows.md +651 -0
  808. package/skills/graphify/skills/amp/references/add-watch.md +56 -0
  809. package/skills/graphify/skills/amp/references/exports.md +71 -0
  810. package/skills/graphify/skills/amp/references/extraction-spec.md +68 -0
  811. package/skills/graphify/skills/amp/references/github-and-merge.md +46 -0
  812. package/skills/graphify/skills/amp/references/hooks.md +33 -0
  813. package/skills/graphify/skills/amp/references/query.md +249 -0
  814. package/skills/graphify/skills/amp/references/transcribe.md +48 -0
  815. package/skills/graphify/skills/amp/references/update.md +179 -0
  816. package/skills/graphify/skills/claude/references/add-watch.md +56 -0
  817. package/skills/graphify/skills/claude/references/exports.md +71 -0
  818. package/skills/graphify/skills/claude/references/extraction-spec.md +68 -0
  819. package/skills/graphify/skills/claude/references/github-and-merge.md +46 -0
  820. package/skills/graphify/skills/claude/references/hooks.md +33 -0
  821. package/skills/graphify/skills/claude/references/query.md +103 -0
  822. package/skills/graphify/skills/claude/references/transcribe.md +48 -0
  823. package/skills/graphify/skills/claude/references/update.md +179 -0
  824. package/skills/graphify/skills/claw/references/add-watch.md +56 -0
  825. package/skills/graphify/skills/claw/references/exports.md +71 -0
  826. package/skills/graphify/skills/claw/references/extraction-spec.md +29 -0
  827. package/skills/graphify/skills/claw/references/github-and-merge.md +46 -0
  828. package/skills/graphify/skills/claw/references/hooks.md +33 -0
  829. package/skills/graphify/skills/claw/references/query.md +249 -0
  830. package/skills/graphify/skills/claw/references/transcribe.md +48 -0
  831. package/skills/graphify/skills/claw/references/update.md +179 -0
  832. package/skills/graphify/skills/codex/references/add-watch.md +56 -0
  833. package/skills/graphify/skills/codex/references/exports.md +71 -0
  834. package/skills/graphify/skills/codex/references/extraction-spec.md +29 -0
  835. package/skills/graphify/skills/codex/references/github-and-merge.md +46 -0
  836. package/skills/graphify/skills/codex/references/hooks.md +33 -0
  837. package/skills/graphify/skills/codex/references/query.md +249 -0
  838. package/skills/graphify/skills/codex/references/transcribe.md +48 -0
  839. package/skills/graphify/skills/codex/references/update.md +179 -0
  840. package/skills/graphify/skills/copilot/references/add-watch.md +56 -0
  841. package/skills/graphify/skills/copilot/references/exports.md +71 -0
  842. package/skills/graphify/skills/copilot/references/extraction-spec.md +68 -0
  843. package/skills/graphify/skills/copilot/references/github-and-merge.md +46 -0
  844. package/skills/graphify/skills/copilot/references/hooks.md +33 -0
  845. package/skills/graphify/skills/copilot/references/query.md +249 -0
  846. package/skills/graphify/skills/copilot/references/transcribe.md +48 -0
  847. package/skills/graphify/skills/copilot/references/update.md +179 -0
  848. package/skills/graphify/skills/droid/references/add-watch.md +56 -0
  849. package/skills/graphify/skills/droid/references/exports.md +71 -0
  850. package/skills/graphify/skills/droid/references/extraction-spec.md +68 -0
  851. package/skills/graphify/skills/droid/references/github-and-merge.md +46 -0
  852. package/skills/graphify/skills/droid/references/hooks.md +33 -0
  853. package/skills/graphify/skills/droid/references/query.md +249 -0
  854. package/skills/graphify/skills/droid/references/transcribe.md +48 -0
  855. package/skills/graphify/skills/droid/references/update.md +179 -0
  856. package/skills/graphify/skills/kilo/references/add-watch.md +56 -0
  857. package/skills/graphify/skills/kilo/references/exports.md +71 -0
  858. package/skills/graphify/skills/kilo/references/extraction-spec.md +68 -0
  859. package/skills/graphify/skills/kilo/references/github-and-merge.md +46 -0
  860. package/skills/graphify/skills/kilo/references/hooks.md +33 -0
  861. package/skills/graphify/skills/kilo/references/query.md +249 -0
  862. package/skills/graphify/skills/kilo/references/transcribe.md +48 -0
  863. package/skills/graphify/skills/kilo/references/update.md +179 -0
  864. package/skills/graphify/skills/kiro/references/add-watch.md +56 -0
  865. package/skills/graphify/skills/kiro/references/exports.md +71 -0
  866. package/skills/graphify/skills/kiro/references/extraction-spec.md +29 -0
  867. package/skills/graphify/skills/kiro/references/github-and-merge.md +46 -0
  868. package/skills/graphify/skills/kiro/references/hooks.md +33 -0
  869. package/skills/graphify/skills/kiro/references/query.md +249 -0
  870. package/skills/graphify/skills/kiro/references/transcribe.md +48 -0
  871. package/skills/graphify/skills/kiro/references/update.md +179 -0
  872. package/skills/graphify/skills/opencode/references/add-watch.md +56 -0
  873. package/skills/graphify/skills/opencode/references/exports.md +71 -0
  874. package/skills/graphify/skills/opencode/references/extraction-spec.md +68 -0
  875. package/skills/graphify/skills/opencode/references/github-and-merge.md +46 -0
  876. package/skills/graphify/skills/opencode/references/hooks.md +33 -0
  877. package/skills/graphify/skills/opencode/references/query.md +249 -0
  878. package/skills/graphify/skills/opencode/references/transcribe.md +48 -0
  879. package/skills/graphify/skills/opencode/references/update.md +179 -0
  880. package/skills/graphify/skills/pi/references/add-watch.md +56 -0
  881. package/skills/graphify/skills/pi/references/exports.md +71 -0
  882. package/skills/graphify/skills/pi/references/extraction-spec.md +29 -0
  883. package/skills/graphify/skills/pi/references/github-and-merge.md +46 -0
  884. package/skills/graphify/skills/pi/references/hooks.md +33 -0
  885. package/skills/graphify/skills/pi/references/query.md +249 -0
  886. package/skills/graphify/skills/pi/references/transcribe.md +48 -0
  887. package/skills/graphify/skills/pi/references/update.md +179 -0
  888. package/skills/graphify/skills/trae/references/add-watch.md +56 -0
  889. package/skills/graphify/skills/trae/references/exports.md +71 -0
  890. package/skills/graphify/skills/trae/references/extraction-spec.md +68 -0
  891. package/skills/graphify/skills/trae/references/github-and-merge.md +46 -0
  892. package/skills/graphify/skills/trae/references/hooks.md +35 -0
  893. package/skills/graphify/skills/trae/references/query.md +249 -0
  894. package/skills/graphify/skills/trae/references/transcribe.md +48 -0
  895. package/skills/graphify/skills/trae/references/update.md +179 -0
  896. package/skills/graphify/skills/vscode/references/add-watch.md +56 -0
  897. package/skills/graphify/skills/vscode/references/exports.md +71 -0
  898. package/skills/graphify/skills/vscode/references/extraction-spec.md +68 -0
  899. package/skills/graphify/skills/vscode/references/github-and-merge.md +46 -0
  900. package/skills/graphify/skills/vscode/references/hooks.md +33 -0
  901. package/skills/graphify/skills/vscode/references/query.md +249 -0
  902. package/skills/graphify/skills/vscode/references/transcribe.md +48 -0
  903. package/skills/graphify/skills/vscode/references/update.md +179 -0
  904. package/skills/graphify/skills/windows/references/add-watch.md +56 -0
  905. package/skills/graphify/skills/windows/references/exports.md +71 -0
  906. package/skills/graphify/skills/windows/references/extraction-spec.md +68 -0
  907. package/skills/graphify/skills/windows/references/github-and-merge.md +46 -0
  908. package/skills/graphify/skills/windows/references/hooks.md +33 -0
  909. package/skills/graphify/skills/windows/references/query.md +249 -0
  910. package/skills/graphify/skills/windows/references/transcribe.md +48 -0
  911. package/skills/graphify/skills/windows/references/update.md +179 -0
  912. package/skills/graphify/symbol_resolution.py +538 -0
  913. package/skills/graphify/transcribe.py +184 -0
  914. package/skills/graphify/tree_html.py +582 -0
  915. package/skills/graphify/validate.py +72 -0
  916. package/skills/graphify/watch.py +898 -0
  917. package/skills/graphify/wiki.py +282 -0
  918. package/skills/health/health-aging/LICENSE +21 -21
  919. package/skills/health/health-aging/SKILL.md +82 -82
  920. package/skills/health/health-chronic/LICENSE +21 -21
  921. package/skills/health/health-chronic/SKILL.md +202 -202
  922. package/skills/health/health-dental/LICENSE +21 -21
  923. package/skills/health/health-dental/SKILL.md +41 -41
  924. package/skills/health/health-eye-care/LICENSE +21 -21
  925. package/skills/health/health-eye-care/SKILL.md +56 -56
  926. package/skills/health/health-first-aid/LICENSE +21 -21
  927. package/skills/health/health-first-aid/SKILL.md +201 -201
  928. package/skills/health/health-fitness/LICENSE +21 -21
  929. package/skills/health/health-fitness/SKILL.md +111 -111
  930. package/skills/health/health-general/LICENSE +21 -21
  931. package/skills/health/health-general/SKILL.md +277 -277
  932. package/skills/health/health-mens/LICENSE +21 -21
  933. package/skills/health/health-mens/SKILL.md +53 -53
  934. package/skills/health/health-mental/LICENSE +21 -21
  935. package/skills/health/health-mental/SKILL.md +221 -221
  936. package/skills/health/health-naturopathy-ayurveda/LICENSE +21 -21
  937. package/skills/health/health-naturopathy-ayurveda/SKILL.md +60 -60
  938. package/skills/health/health-nutrition/LICENSE +21 -21
  939. package/skills/health/health-nutrition/SKILL.md +262 -262
  940. package/skills/health/health-pediatric/LICENSE +21 -21
  941. package/skills/health/health-pediatric/SKILL.md +94 -94
  942. package/skills/health/health-pharmacology/LICENSE +21 -21
  943. package/skills/health/health-pharmacology/SKILL.md +87 -87
  944. package/skills/health/health-pregnancy/LICENSE +21 -21
  945. package/skills/health/health-pregnancy/SKILL.md +71 -71
  946. package/skills/health/health-skin/LICENSE +21 -21
  947. package/skills/health/health-skin/SKILL.md +71 -71
  948. package/skills/health/health-sleep/LICENSE +21 -21
  949. package/skills/health/health-sleep/SKILL.md +81 -81
  950. package/skills/health/health-womens/LICENSE +21 -21
  951. package/skills/health/health-womens/SKILL.md +72 -72
  952. package/skills/health/health-yoga-wellness/LICENSE +21 -21
  953. package/skills/health/health-yoga-wellness/SKILL.md +58 -58
  954. package/skills/healthcare-systems/health-sys-global/LICENSE +21 -21
  955. package/skills/healthcare-systems/health-sys-global/SKILL.md +69 -69
  956. package/skills/healthcare-systems/health-sys-management/LICENSE +21 -21
  957. package/skills/healthcare-systems/health-sys-management/SKILL.md +71 -71
  958. package/skills/healthcare-systems/health-sys-navigation/LICENSE +21 -21
  959. package/skills/healthcare-systems/health-sys-navigation/SKILL.md +60 -60
  960. package/skills/healthcare-systems/health-sys-public/LICENSE +21 -21
  961. package/skills/healthcare-systems/health-sys-public/SKILL.md +71 -71
  962. package/skills/healthcheck/SKILL.md +109 -109
  963. package/skills/himalaya/SKILL.md +84 -84
  964. package/skills/himalaya/references/configuration.md +184 -184
  965. package/skills/himalaya/references/message-composition.md +199 -199
  966. package/skills/humanities/humanities-history-world/LICENSE +21 -21
  967. package/skills/humanities/humanities-history-world/SKILL.md +59 -59
  968. package/skills/humanities/humanities-indian-classical/LICENSE +21 -21
  969. package/skills/humanities/humanities-indian-classical/SKILL.md +104 -104
  970. package/skills/humanities/humanities-philosophy/LICENSE +21 -21
  971. package/skills/humanities/humanities-philosophy/SKILL.md +105 -105
  972. package/skills/humanities/humanities-world-religions/LICENSE +21 -21
  973. package/skills/humanities/humanities-world-religions/SKILL.md +67 -67
  974. package/skills/impeccable/SKILL.md +186 -0
  975. package/skills/impeccable/agents/impeccable_asset_producer.toml +92 -0
  976. package/skills/impeccable/agents/impeccable_manual_edit_applier.toml +95 -0
  977. package/skills/impeccable/agents/openai.yaml +4 -0
  978. package/skills/impeccable/reference/adapt.md +311 -0
  979. package/skills/impeccable/reference/animate.md +201 -0
  980. package/skills/impeccable/reference/audit.md +133 -0
  981. package/skills/impeccable/reference/bolder.md +113 -0
  982. package/skills/impeccable/reference/brand.md +108 -0
  983. package/skills/impeccable/reference/clarify.md +288 -0
  984. package/skills/impeccable/reference/codex.md +105 -0
  985. package/skills/impeccable/reference/colorize.md +257 -0
  986. package/skills/impeccable/reference/craft.md +123 -0
  987. package/skills/impeccable/reference/critique.md +790 -0
  988. package/skills/impeccable/reference/delight.md +302 -0
  989. package/skills/impeccable/reference/distill.md +111 -0
  990. package/skills/impeccable/reference/document.md +429 -0
  991. package/skills/impeccable/reference/extract.md +69 -0
  992. package/skills/impeccable/reference/harden.md +347 -0
  993. package/skills/impeccable/reference/init.md +172 -0
  994. package/skills/impeccable/reference/interaction-design.md +189 -0
  995. package/skills/impeccable/reference/layout.md +161 -0
  996. package/skills/impeccable/reference/live.md +720 -0
  997. package/skills/impeccable/reference/onboard.md +234 -0
  998. package/skills/impeccable/reference/optimize.md +258 -0
  999. package/skills/impeccable/reference/overdrive.md +130 -0
  1000. package/skills/impeccable/reference/polish.md +241 -0
  1001. package/skills/impeccable/reference/product.md +60 -0
  1002. package/skills/impeccable/reference/quieter.md +99 -0
  1003. package/skills/impeccable/reference/shape.md +165 -0
  1004. package/skills/impeccable/reference/typeset.md +279 -0
  1005. package/skills/impeccable/scripts/cleanup-deprecated.mjs +284 -0
  1006. package/skills/impeccable/scripts/command-metadata.json +94 -0
  1007. package/skills/impeccable/scripts/context-signals.mjs +225 -0
  1008. package/skills/impeccable/scripts/context.mjs +266 -0
  1009. package/skills/impeccable/scripts/critique-storage.mjs +242 -0
  1010. package/skills/impeccable/scripts/design-parser.mjs +835 -0
  1011. package/skills/impeccable/scripts/detect-csp.mjs +198 -0
  1012. package/skills/impeccable/scripts/detect.mjs +21 -0
  1013. package/skills/impeccable/scripts/detector/browser/injected/index.mjs +1733 -0
  1014. package/skills/impeccable/scripts/detector/cli/main.mjs +244 -0
  1015. package/skills/impeccable/scripts/detector/detect-antipatterns-browser.js +4618 -0
  1016. package/skills/impeccable/scripts/detector/detect-antipatterns.mjs +43 -0
  1017. package/skills/impeccable/scripts/detector/engines/browser/detect-url.mjs +252 -0
  1018. package/skills/impeccable/scripts/detector/engines/regex/detect-text.mjs +535 -0
  1019. package/skills/impeccable/scripts/detector/engines/static-html/css-cascade.mjs +986 -0
  1020. package/skills/impeccable/scripts/detector/engines/static-html/detect-html.mjs +208 -0
  1021. package/skills/impeccable/scripts/detector/engines/visual/screenshot-contrast.mjs +189 -0
  1022. package/skills/impeccable/scripts/detector/findings.mjs +12 -0
  1023. package/skills/impeccable/scripts/detector/node/file-system.mjs +198 -0
  1024. package/skills/impeccable/scripts/detector/profile/profiler.mjs +166 -0
  1025. package/skills/impeccable/scripts/detector/registry/antipatterns.mjs +419 -0
  1026. package/skills/impeccable/scripts/detector/rules/checks.mjs +2384 -0
  1027. package/skills/impeccable/scripts/detector/shared/color.mjs +124 -0
  1028. package/skills/impeccable/scripts/detector/shared/constants.mjs +101 -0
  1029. package/skills/impeccable/scripts/detector/shared/page.mjs +7 -0
  1030. package/skills/impeccable/scripts/impeccable-paths.mjs +126 -0
  1031. package/skills/impeccable/scripts/is-generated.mjs +69 -0
  1032. package/skills/impeccable/scripts/live-accept.mjs +812 -0
  1033. package/skills/impeccable/scripts/live-browser-session.js +123 -0
  1034. package/skills/impeccable/scripts/live-browser.js +10295 -0
  1035. package/skills/impeccable/scripts/live-commit-manual-edits.mjs +1241 -0
  1036. package/skills/impeccable/scripts/live-complete.mjs +75 -0
  1037. package/skills/impeccable/scripts/live-completion.mjs +19 -0
  1038. package/skills/impeccable/scripts/live-copy-edit-agent.mjs +683 -0
  1039. package/skills/impeccable/scripts/live-discard-manual-edits.mjs +51 -0
  1040. package/skills/impeccable/scripts/live-event-validation.mjs +137 -0
  1041. package/skills/impeccable/scripts/live-inject.mjs +557 -0
  1042. package/skills/impeccable/scripts/live-insert-ui.mjs +458 -0
  1043. package/skills/impeccable/scripts/live-insert.mjs +272 -0
  1044. package/skills/impeccable/scripts/live-manual-edit-evidence.mjs +363 -0
  1045. package/skills/impeccable/scripts/live-manual-edits-buffer.mjs +152 -0
  1046. package/skills/impeccable/scripts/live-poll.mjs +379 -0
  1047. package/skills/impeccable/scripts/live-resume.mjs +94 -0
  1048. package/skills/impeccable/scripts/live-server.mjs +2326 -0
  1049. package/skills/impeccable/scripts/live-session-store.mjs +289 -0
  1050. package/skills/impeccable/scripts/live-status.mjs +61 -0
  1051. package/skills/impeccable/scripts/live-svelte-component.mjs +826 -0
  1052. package/skills/impeccable/scripts/live-sveltekit-adapter.mjs +274 -0
  1053. package/skills/impeccable/scripts/live-ui-core.mjs +179 -0
  1054. package/skills/impeccable/scripts/live-vocabulary.mjs +36 -0
  1055. package/skills/impeccable/scripts/live-wrap.mjs +894 -0
  1056. package/skills/impeccable/scripts/live.mjs +246 -0
  1057. package/skills/impeccable/scripts/modern-screenshot.umd.js +14 -0
  1058. package/skills/impeccable/scripts/palette.mjs +633 -0
  1059. package/skills/impeccable/scripts/pin.mjs +214 -0
  1060. package/skills/imsg/SKILL.md +126 -126
  1061. package/skills/industry/industry-construction/LICENSE +21 -21
  1062. package/skills/industry/industry-construction/SKILL.md +81 -81
  1063. package/skills/industry/industry-education-sector/LICENSE +21 -21
  1064. package/skills/industry/industry-education-sector/SKILL.md +49 -49
  1065. package/skills/industry/industry-fashion/LICENSE +21 -21
  1066. package/skills/industry/industry-fashion/SKILL.md +82 -82
  1067. package/skills/industry/industry-food/LICENSE +21 -21
  1068. package/skills/industry/industry-food/SKILL.md +79 -79
  1069. package/skills/industry/industry-government/LICENSE +21 -21
  1070. package/skills/industry/industry-government/SKILL.md +80 -80
  1071. package/skills/industry/industry-hospitality/LICENSE +21 -21
  1072. package/skills/industry/industry-hospitality/SKILL.md +73 -73
  1073. package/skills/industry/industry-insurance-sector/LICENSE +21 -21
  1074. package/skills/industry/industry-insurance-sector/SKILL.md +57 -57
  1075. package/skills/industry/industry-logistics/LICENSE +21 -21
  1076. package/skills/industry/industry-logistics/SKILL.md +80 -80
  1077. package/skills/industry/industry-media/LICENSE +21 -21
  1078. package/skills/industry/industry-media/SKILL.md +66 -66
  1079. package/skills/industry/industry-nonprofit/LICENSE +21 -21
  1080. package/skills/industry/industry-nonprofit/SKILL.md +77 -77
  1081. package/skills/industry/industry-pharma/LICENSE +21 -21
  1082. package/skills/industry/industry-pharma/SKILL.md +69 -69
  1083. package/skills/industry/industry-real-estate/LICENSE +21 -21
  1084. package/skills/industry/industry-real-estate/SKILL.md +61 -61
  1085. package/skills/industry/industry-sports/LICENSE +21 -21
  1086. package/skills/industry/industry-sports/SKILL.md +71 -71
  1087. package/skills/industry/industry-tech-startup/LICENSE +21 -21
  1088. package/skills/industry/industry-tech-startup/SKILL.md +82 -82
  1089. package/skills/internal-comms/LICENSE +21 -21
  1090. package/skills/internal-comms/SKILL.md +38 -38
  1091. package/skills/internal-comms/examples/3p-updates.md +49 -49
  1092. package/skills/internal-comms/examples/company-newsletter.md +76 -76
  1093. package/skills/internal-comms/examples/faq-answers.md +35 -35
  1094. package/skills/internal-comms/examples/general-comms.md +19 -19
  1095. package/skills/legal/legal-business/LICENSE +21 -21
  1096. package/skills/legal/legal-business/SKILL.md +227 -227
  1097. package/skills/legal/legal-consumer/LICENSE +21 -21
  1098. package/skills/legal/legal-consumer/SKILL.md +155 -155
  1099. package/skills/legal/legal-contracts/LICENSE +21 -21
  1100. package/skills/legal/legal-contracts/SKILL.md +268 -268
  1101. package/skills/legal/legal-corporate-governance/LICENSE +21 -21
  1102. package/skills/legal/legal-corporate-governance/SKILL.md +53 -53
  1103. package/skills/legal/legal-employment/LICENSE +21 -21
  1104. package/skills/legal/legal-employment/SKILL.md +291 -291
  1105. package/skills/legal/legal-immigration/LICENSE +21 -21
  1106. package/skills/legal/legal-immigration/SKILL.md +146 -146
  1107. package/skills/legal/legal-international/LICENSE +21 -21
  1108. package/skills/legal/legal-international/SKILL.md +51 -51
  1109. package/skills/legal/legal-ip/LICENSE +21 -21
  1110. package/skills/legal/legal-ip/SKILL.md +264 -264
  1111. package/skills/legal/legal-privacy/LICENSE +21 -21
  1112. package/skills/legal/legal-privacy/SKILL.md +161 -161
  1113. package/skills/legal/legal-real-estate/LICENSE +21 -21
  1114. package/skills/legal/legal-real-estate/SKILL.md +142 -142
  1115. package/skills/legal/legal-startup/LICENSE +21 -21
  1116. package/skills/legal/legal-startup/SKILL.md +182 -182
  1117. package/skills/legal/legal-tax/LICENSE +21 -21
  1118. package/skills/legal/legal-tax/SKILL.md +156 -156
  1119. package/skills/mcp-builder/LICENSE +21 -21
  1120. package/skills/mcp-builder/SKILL.md +257 -257
  1121. package/skills/mcp-builder/reference/evaluation.md +630 -630
  1122. package/skills/mcp-builder/reference/mcp_best_practices.md +269 -269
  1123. package/skills/mcp-builder/reference/node_mcp_server.md +980 -980
  1124. package/skills/mcp-builder/reference/python_mcp_server.md +737 -737
  1125. package/skills/mcp-builder/scripts/connections.py +151 -151
  1126. package/skills/mcp-builder/scripts/evaluation.py +373 -373
  1127. package/skills/mcp-builder/scripts/example_evaluation.xml +22 -22
  1128. package/skills/mcp-builder/scripts/requirements.txt +2 -2
  1129. package/skills/mcporter/SKILL.md +65 -65
  1130. package/skills/meme-maker/SKILL.md +46 -46
  1131. package/skills/meme-maker/references/templates.json +358 -358
  1132. package/skills/meme-maker/scripts/meme.mjs +398 -398
  1133. package/skills/mental-health/mental-health-cbt/LICENSE +21 -21
  1134. package/skills/mental-health/mental-health-cbt/SKILL.md +254 -254
  1135. package/skills/mental-health/psych-addiction/LICENSE +21 -21
  1136. package/skills/mental-health/psych-addiction/SKILL.md +79 -79
  1137. package/skills/mental-health/psych-behavioral-econ/LICENSE +21 -21
  1138. package/skills/mental-health/psych-behavioral-econ/SKILL.md +84 -84
  1139. package/skills/mental-health/psych-child/LICENSE +21 -21
  1140. package/skills/mental-health/psych-child/SKILL.md +84 -84
  1141. package/skills/mental-health/psych-grief/LICENSE +21 -21
  1142. package/skills/mental-health/psych-grief/SKILL.md +85 -85
  1143. package/skills/mental-health/psych-mindfulness/LICENSE +21 -21
  1144. package/skills/mental-health/psych-mindfulness/SKILL.md +71 -71
  1145. package/skills/mental-health/psych-org/LICENSE +21 -21
  1146. package/skills/mental-health/psych-org/SKILL.md +115 -115
  1147. package/skills/mental-health/psych-positive/LICENSE +21 -21
  1148. package/skills/mental-health/psych-positive/SKILL.md +86 -86
  1149. package/skills/mental-health/psych-relationships/LICENSE +21 -21
  1150. package/skills/mental-health/psych-relationships/SKILL.md +100 -100
  1151. package/skills/mental-health/psych-trauma/LICENSE +21 -21
  1152. package/skills/mental-health/psych-trauma/SKILL.md +109 -109
  1153. package/skills/model-usage/SKILL.md +75 -75
  1154. package/skills/model-usage/references/codexbar-cli.md +33 -33
  1155. package/skills/model-usage/scripts/model_usage.py +319 -319
  1156. package/skills/model-usage/scripts/test_model_usage.py +40 -40
  1157. package/skills/nano-pdf/SKILL.md +42 -42
  1158. package/skills/node-connect/SKILL.md +147 -147
  1159. package/skills/node-inspect-debugger/SKILL.md +88 -88
  1160. package/skills/notion/SKILL.md +154 -154
  1161. package/skills/obsidian/SKILL.md +123 -123
  1162. package/skills/openai-whisper/SKILL.md +42 -42
  1163. package/skills/openai-whisper-api/SKILL.md +75 -75
  1164. package/skills/openai-whisper-api/scripts/transcribe.sh +154 -154
  1165. package/skills/openhue/SKILL.md +116 -116
  1166. package/skills/oracle/SKILL.md +130 -130
  1167. package/skills/ordercli/SKILL.md +82 -82
  1168. package/skills/peekaboo/SKILL.md +217 -217
  1169. package/skills/pyproject.toml +10 -10
  1170. package/skills/python-debugpy/SKILL.md +76 -76
  1171. package/skills/sag/SKILL.md +91 -91
  1172. package/skills/science/sci-astronomy/LICENSE +21 -21
  1173. package/skills/science/sci-astronomy/SKILL.md +80 -80
  1174. package/skills/science/sci-biology/LICENSE +21 -21
  1175. package/skills/science/sci-biology/SKILL.md +74 -74
  1176. package/skills/science/sci-chemistry/LICENSE +21 -21
  1177. package/skills/science/sci-chemistry/SKILL.md +89 -89
  1178. package/skills/science/sci-climate/LICENSE +21 -21
  1179. package/skills/science/sci-climate/SKILL.md +72 -72
  1180. package/skills/science/sci-data-analysis/LICENSE +21 -21
  1181. package/skills/science/sci-data-analysis/SKILL.md +87 -87
  1182. package/skills/science/sci-environmental-science/LICENSE +21 -21
  1183. package/skills/science/sci-environmental-science/SKILL.md +69 -69
  1184. package/skills/science/sci-geology/LICENSE +21 -21
  1185. package/skills/science/sci-geology/SKILL.md +56 -56
  1186. package/skills/science/sci-method/LICENSE +21 -21
  1187. package/skills/science/sci-method/SKILL.md +77 -77
  1188. package/skills/science/sci-neuroscience/LICENSE +21 -21
  1189. package/skills/science/sci-neuroscience/SKILL.md +79 -79
  1190. package/skills/science/sci-physics/LICENSE +21 -21
  1191. package/skills/science/sci-physics/SKILL.md +78 -78
  1192. package/skills/science/sci-research-methods/LICENSE +21 -21
  1193. package/skills/science/sci-research-methods/SKILL.md +83 -83
  1194. package/skills/science/sci-statistics/LICENSE +21 -21
  1195. package/skills/science/sci-statistics/SKILL.md +249 -249
  1196. package/skills/session-logs/SKILL.md +155 -155
  1197. package/skills/sherpa-onnx-tts/SKILL.md +113 -113
  1198. package/skills/skill-creator/SKILL.md +81 -81
  1199. package/skills/skill-creator/license.txt +202 -202
  1200. package/skills/skill-creator/scripts/init_skill.py +378 -378
  1201. package/skills/skill-creator/scripts/package_skill.py +144 -144
  1202. package/skills/skill-creator/scripts/quick_validate.py +169 -169
  1203. package/skills/skill-creator/scripts/test_init_skill.py +51 -51
  1204. package/skills/skill-creator/scripts/test_package_skill.py +199 -199
  1205. package/skills/skill-creator/scripts/test_quick_validate.py +116 -116
  1206. package/skills/slack/SKILL.md +82 -82
  1207. package/skills/slack-gif-creator/LICENSE +21 -21
  1208. package/skills/slack-gif-creator/SKILL.md +293 -293
  1209. package/skills/slack-gif-creator/requirements.txt +3 -3
  1210. package/skills/social-sciences/social-anthropology/LICENSE +21 -21
  1211. package/skills/social-sciences/social-anthropology/SKILL.md +62 -62
  1212. package/skills/social-sciences/social-economics/LICENSE +21 -21
  1213. package/skills/social-sciences/social-economics/SKILL.md +88 -88
  1214. package/skills/social-sciences/social-geography/LICENSE +21 -21
  1215. package/skills/social-sciences/social-geography/SKILL.md +61 -61
  1216. package/skills/social-sciences/social-international-dev/LICENSE +21 -21
  1217. package/skills/social-sciences/social-international-dev/SKILL.md +76 -76
  1218. package/skills/social-sciences/social-political-science/LICENSE +21 -21
  1219. package/skills/social-sciences/social-political-science/SKILL.md +70 -70
  1220. package/skills/social-sciences/social-public-policy/LICENSE +21 -21
  1221. package/skills/social-sciences/social-public-policy/SKILL.md +73 -73
  1222. package/skills/social-sciences/social-sociology/LICENSE +21 -21
  1223. package/skills/social-sciences/social-sociology/SKILL.md +78 -78
  1224. package/skills/songsee/SKILL.md +53 -53
  1225. package/skills/sonoscli/SKILL.md +69 -69
  1226. package/skills/spike/SKILL.md +55 -55
  1227. package/skills/spotify-player/SKILL.md +68 -68
  1228. package/skills/summarize/SKILL.md +90 -90
  1229. package/skills/taskflow/SKILL.md +153 -153
  1230. package/skills/taskflow/examples/inbox-triage.lobster +33 -33
  1231. package/skills/taskflow/examples/pr-intake.lobster +32 -32
  1232. package/skills/taskflow-inbox-triage/SKILL.md +123 -123
  1233. package/skills/technical/ai-ethics/LICENSE +21 -21
  1234. package/skills/technical/ai-ethics/SKILL.md +92 -92
  1235. package/skills/technical/ai-product-builder/LICENSE +21 -21
  1236. package/skills/technical/ai-product-builder/SKILL.md +180 -180
  1237. package/skills/technical/analytics-setup/LICENSE +21 -21
  1238. package/skills/technical/analytics-setup/SKILL.md +125 -125
  1239. package/skills/technical/api-builder/LICENSE +21 -21
  1240. package/skills/technical/api-builder/SKILL.md +202 -202
  1241. package/skills/technical/architecture-decisions/LICENSE +21 -21
  1242. package/skills/technical/architecture-decisions/SKILL.md +120 -120
  1243. package/skills/technical/auth-security/LICENSE +21 -21
  1244. package/skills/technical/auth-security/SKILL.md +209 -209
  1245. package/skills/technical/blockchain-web3/LICENSE +21 -21
  1246. package/skills/technical/blockchain-web3/SKILL.md +84 -84
  1247. package/skills/technical/cloud-architecture/LICENSE +21 -21
  1248. package/skills/technical/cloud-architecture/SKILL.md +85 -85
  1249. package/skills/technical/content-platform/LICENSE +21 -21
  1250. package/skills/technical/content-platform/SKILL.md +134 -134
  1251. package/skills/technical/cybersecurity-advanced/LICENSE +21 -21
  1252. package/skills/technical/cybersecurity-advanced/SKILL.md +99 -99
  1253. package/skills/technical/data-engineering/LICENSE +21 -21
  1254. package/skills/technical/data-engineering/SKILL.md +117 -117
  1255. package/skills/technical/database-design/LICENSE +21 -21
  1256. package/skills/technical/database-design/SKILL.md +185 -185
  1257. package/skills/technical/devops-cicd/LICENSE +21 -21
  1258. package/skills/technical/devops-cicd/SKILL.md +181 -181
  1259. package/skills/technical/ecommerce-builder/LICENSE +21 -21
  1260. package/skills/technical/ecommerce-builder/SKILL.md +123 -123
  1261. package/skills/technical/email-marketing/LICENSE +21 -21
  1262. package/skills/technical/email-marketing/SKILL.md +128 -128
  1263. package/skills/technical/fintech-builder/LICENSE +21 -21
  1264. package/skills/technical/fintech-builder/SKILL.md +141 -141
  1265. package/skills/technical/full-stack-web/LICENSE +21 -21
  1266. package/skills/technical/full-stack-web/SKILL.md +173 -173
  1267. package/skills/technical/gdpr-basics/LICENSE +21 -21
  1268. package/skills/technical/gdpr-basics/SKILL.md +145 -145
  1269. package/skills/technical/launch-playbook/LICENSE +21 -21
  1270. package/skills/technical/launch-playbook/SKILL.md +95 -95
  1271. package/skills/technical/marketing-copy/LICENSE +21 -21
  1272. package/skills/technical/marketing-copy/SKILL.md +126 -126
  1273. package/skills/technical/marketplace-builder/LICENSE +21 -21
  1274. package/skills/technical/marketplace-builder/SKILL.md +105 -105
  1275. package/skills/technical/mobile-pwa/LICENSE +21 -21
  1276. package/skills/technical/mobile-pwa/SKILL.md +191 -191
  1277. package/skills/technical/no-code-tools/LICENSE +21 -21
  1278. package/skills/technical/no-code-tools/SKILL.md +80 -80
  1279. package/skills/technical/open-source/LICENSE +21 -21
  1280. package/skills/technical/open-source/SKILL.md +71 -71
  1281. package/skills/technical/performance-optimization/LICENSE +21 -21
  1282. package/skills/technical/performance-optimization/SKILL.md +155 -155
  1283. package/skills/technical/pricing-design/LICENSE +21 -21
  1284. package/skills/technical/pricing-design/SKILL.md +87 -87
  1285. package/skills/technical/product-management/LICENSE +21 -21
  1286. package/skills/technical/product-management/SKILL.md +94 -94
  1287. package/skills/technical/saas-builder/LICENSE +21 -21
  1288. package/skills/technical/saas-builder/SKILL.md +138 -138
  1289. package/skills/technical/scope-estimation/LICENSE +21 -21
  1290. package/skills/technical/scope-estimation/SKILL.md +99 -99
  1291. package/skills/technical/secrets-management/LICENSE +21 -21
  1292. package/skills/technical/secrets-management/SKILL.md +135 -135
  1293. package/skills/technical/seo-technical/LICENSE +21 -21
  1294. package/skills/technical/seo-technical/SKILL.md +136 -136
  1295. package/skills/technical/technical-writing/LICENSE +21 -21
  1296. package/skills/technical/technical-writing/SKILL.md +149 -149
  1297. package/skills/technical/ux-research-tools/LICENSE +21 -21
  1298. package/skills/technical/ux-research-tools/SKILL.md +54 -54
  1299. package/skills/theme-factory/LICENSE +21 -21
  1300. package/skills/theme-factory/SKILL.md +65 -65
  1301. package/skills/theme-factory/themes/arctic-frost.md +19 -19
  1302. package/skills/theme-factory/themes/botanical-garden.md +19 -19
  1303. package/skills/theme-factory/themes/desert-rose.md +19 -19
  1304. package/skills/theme-factory/themes/forest-canopy.md +19 -19
  1305. package/skills/theme-factory/themes/golden-hour.md +19 -19
  1306. package/skills/theme-factory/themes/midnight-galaxy.md +19 -19
  1307. package/skills/theme-factory/themes/modern-minimalist.md +19 -19
  1308. package/skills/theme-factory/themes/ocean-depths.md +19 -19
  1309. package/skills/theme-factory/themes/sunset-boulevard.md +19 -19
  1310. package/skills/theme-factory/themes/tech-innovation.md +19 -19
  1311. package/skills/things-mac/SKILL.md +90 -90
  1312. package/skills/tmux/SKILL.md +95 -95
  1313. package/skills/tmux/scripts/find-sessions.sh +112 -112
  1314. package/skills/tmux/scripts/wait-for-text.sh +83 -83
  1315. package/skills/trades/trades-agriculture/LICENSE +21 -21
  1316. package/skills/trades/trades-agriculture/SKILL.md +80 -80
  1317. package/skills/trades/trades-automotive/LICENSE +21 -21
  1318. package/skills/trades/trades-automotive/SKILL.md +84 -84
  1319. package/skills/trades/trades-carpentry/LICENSE +21 -21
  1320. package/skills/trades/trades-carpentry/SKILL.md +71 -71
  1321. package/skills/trades/trades-cooking-pro/LICENSE +21 -21
  1322. package/skills/trades/trades-cooking-pro/SKILL.md +90 -90
  1323. package/skills/trades/trades-electrical/LICENSE +21 -21
  1324. package/skills/trades/trades-electrical/SKILL.md +146 -146
  1325. package/skills/trades/trades-hvac/LICENSE +21 -21
  1326. package/skills/trades/trades-hvac/SKILL.md +80 -80
  1327. package/skills/trades/trades-landscaping/LICENSE +21 -21
  1328. package/skills/trades/trades-landscaping/SKILL.md +60 -60
  1329. package/skills/trades/trades-metalworking/LICENSE +21 -21
  1330. package/skills/trades/trades-metalworking/SKILL.md +64 -64
  1331. package/skills/trades/trades-painting/LICENSE +21 -21
  1332. package/skills/trades/trades-painting/SKILL.md +70 -70
  1333. package/skills/trades/trades-plumbing/LICENSE +21 -21
  1334. package/skills/trades/trades-plumbing/SKILL.md +160 -160
  1335. package/skills/trades/trades-welding/LICENSE +21 -21
  1336. package/skills/trades/trades-welding/SKILL.md +82 -82
  1337. package/skills/trello/SKILL.md +112 -112
  1338. package/skills/uipm-ui-styling/LICENSE.txt +202 -0
  1339. package/skills/uipm-ui-styling/SKILL.md +328 -0
  1340. package/skills/uipm-ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
  1341. package/skills/uipm-ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
  1342. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
  1343. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
  1344. package/skills/uipm-ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
  1345. package/skills/uipm-ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
  1346. package/skills/uipm-ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
  1347. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
  1348. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
  1349. package/skills/uipm-ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
  1350. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
  1351. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
  1352. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
  1353. package/skills/uipm-ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
  1354. package/skills/uipm-ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
  1355. package/skills/uipm-ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
  1356. package/skills/uipm-ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
  1357. package/skills/uipm-ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
  1358. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
  1359. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
  1360. package/skills/uipm-ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
  1361. package/skills/uipm-ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
  1362. package/skills/uipm-ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
  1363. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
  1364. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
  1365. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
  1366. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
  1367. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
  1368. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
  1369. package/skills/uipm-ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
  1370. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
  1371. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
  1372. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
  1373. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
  1374. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
  1375. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
  1376. package/skills/uipm-ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
  1377. package/skills/uipm-ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
  1378. package/skills/uipm-ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
  1379. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
  1380. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
  1381. package/skills/uipm-ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
  1382. package/skills/uipm-ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
  1383. package/skills/uipm-ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
  1384. package/skills/uipm-ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
  1385. package/skills/uipm-ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
  1386. package/skills/uipm-ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
  1387. package/skills/uipm-ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
  1388. package/skills/uipm-ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
  1389. package/skills/uipm-ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
  1390. package/skills/uipm-ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
  1391. package/skills/uipm-ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
  1392. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
  1393. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
  1394. package/skills/uipm-ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
  1395. package/skills/uipm-ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
  1396. package/skills/uipm-ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
  1397. package/skills/uipm-ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
  1398. package/skills/uipm-ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
  1399. package/skills/uipm-ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
  1400. package/skills/uipm-ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
  1401. package/skills/uipm-ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
  1402. package/skills/uipm-ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
  1403. package/skills/uipm-ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
  1404. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
  1405. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
  1406. package/skills/uipm-ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
  1407. package/skills/uipm-ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
  1408. package/skills/uipm-ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
  1409. package/skills/uipm-ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
  1410. package/skills/uipm-ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
  1411. package/skills/uipm-ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
  1412. package/skills/uipm-ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
  1413. package/skills/uipm-ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
  1414. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
  1415. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
  1416. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
  1417. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
  1418. package/skills/uipm-ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
  1419. package/skills/uipm-ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
  1420. package/skills/uipm-ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
  1421. package/skills/uipm-ui-styling/references/canvas-design-system.md +320 -0
  1422. package/skills/uipm-ui-styling/references/shadcn-accessibility.md +471 -0
  1423. package/skills/uipm-ui-styling/references/shadcn-components.md +424 -0
  1424. package/skills/uipm-ui-styling/references/shadcn-theming.md +373 -0
  1425. package/skills/uipm-ui-styling/references/tailwind-customization.md +483 -0
  1426. package/skills/uipm-ui-styling/references/tailwind-responsive.md +382 -0
  1427. package/skills/uipm-ui-styling/references/tailwind-utilities.md +455 -0
  1428. package/skills/uipm-ui-styling/scripts/.coverage +0 -0
  1429. package/skills/uipm-ui-styling/scripts/requirements.txt +17 -0
  1430. package/skills/uipm-ui-styling/scripts/shadcn_add.py +292 -0
  1431. package/skills/uipm-ui-styling/scripts/tailwind_config_gen.py +456 -0
  1432. package/skills/uipm-ui-styling/scripts/tests/coverage-ui.json +1 -0
  1433. package/skills/uipm-ui-styling/scripts/tests/requirements.txt +3 -0
  1434. package/skills/uipm-ui-styling/scripts/tests/test_shadcn_add.py +266 -0
  1435. package/skills/uipm-ui-styling/scripts/tests/test_tailwind_config_gen.py +336 -0
  1436. package/skills/video-frames/SKILL.md +50 -50
  1437. package/skills/video-frames/scripts/frame.sh +81 -81
  1438. package/skills/voice-call/SKILL.md +49 -49
  1439. package/skills/wacli/SKILL.md +76 -76
  1440. package/skills/weather/SKILL.md +91 -91
  1441. package/skills/web-artifacts-builder/LICENSE +21 -21
  1442. package/skills/web-artifacts-builder/SKILL.md +82 -82
  1443. package/skills/web-artifacts-builder/scripts/bundle-artifact.sh +53 -53
  1444. package/skills/web-artifacts-builder/scripts/init-artifact.sh +322 -322
  1445. package/skills/xurl/SKILL.md +124 -124
@@ -1,1065 +1,1065 @@
1
- // Deterministic markdown renderer. Same inputs → byte-identical output (modulo caller-supplied generatedAt).
2
-
3
- import { createHash } from "node:crypto";
4
- import { computeCostCoverage, renderCostCoverageMarkdown } from "./cost-coverage.mjs";
5
- import {
6
- formatCandidateLabel,
7
- formatKind,
8
- formatPublicText,
9
- formatRoute,
10
- formatSignal,
11
- } from "./display-labels.mjs";
12
- import { gates as registeredGates } from "./gates/index.mjs";
13
- import { computeImpactLabel } from "./impact-label.mjs";
14
- import { splitCustomerSafeObservations } from "./observation-safety.mjs";
15
- import { deriveProjectFacts } from "./project-facts.mjs";
16
- import { canonicalizeRoute } from "./route-normalize.mjs";
17
-
18
- const PLATFORM_CAP = 3;
19
- const GATED_TARGET_PREVIEW = 5;
20
-
21
- export function renderReport({
22
- recommendations = [],
23
- gated = [],
24
- abstentions = [],
25
- observations = [],
26
- signals = {},
27
- candidates = [],
28
- opts = {},
29
- } = {}) {
30
- const safety = splitCustomerSafeObservations(observations, abstentions, signals);
31
- observations = safety.observations;
32
- abstentions = [...abstentions, ...safety.heldBackObservations];
33
- assertValidObservations(observations);
34
-
35
- const projectName = opts.projectName ?? signals.project?.name ?? "<project>";
36
- const stack = signals.stack ?? signals.codebase?.stack ?? {};
37
- const usage = signals.usage ?? null;
38
- const plan = signals.plan ?? { plan: "unknown", reason: "(not detected)" };
39
-
40
- // Sub-agents don't always propagate o11ySignal/aliasRoutes — look them up by candidateRef and canonicalize the displayed ref.
41
- recommendations = recommendations.map((r) => enrichRecFromCandidates(r, candidates));
42
- const { needsEvidenceRows, noChangeRows } = splitInvestigationOutcomes(abstentions);
43
-
44
- const lines = [];
45
- lines.push(`# Vercel Optimization Report — ${projectName}`);
46
- lines.push("");
47
- lines.push(renderMetadataLine(stack, plan, usage, signals));
48
- const coverageLine = renderCoverageLine(candidates, recommendations, signals, {
49
- abstentions,
50
- heldBackCount: opts.heldBackCount,
51
- noChangeCount: opts.noChangeCount,
52
- });
53
- if (coverageLine) lines.push(coverageLine);
54
- if (opts.generatedAt) {
55
- lines.push("");
56
- lines.push(`_Generated ${opts.generatedAt}_`);
57
- }
58
- lines.push("");
59
-
60
- lines.push(...renderCostHeader(signals));
61
- lines.push("");
62
- lines.push(...renderCostBreakdown(usage, signals));
63
- if (usage) {
64
- const coverage = computeCostCoverage(usage, registeredGates);
65
- lines.push(...renderCostCoverageMarkdown(coverage));
66
- }
67
- lines.push("");
68
-
69
- const platformRecs = recommendations.filter(isPlatformScope).slice(0, PLATFORM_CAP);
70
- const codeRecs = recommendations.filter((r) => !isPlatformScope(r));
71
- const sorted = sortRecs(codeRecs);
72
- const high = sorted.filter((r) => r.impactTier === "high");
73
- const medium = sorted.filter((r) => r.impactTier === "medium");
74
- const low = sorted.filter((r) => r.impactTier === "low" || !r.impactTier);
75
- lines.push("## Highest-impact recommendations");
76
- lines.push("");
77
- if (sorted.length === 0) {
78
- lines.push("_No recommendations are ready to apply from this run._");
79
- } else {
80
- const top = sorted.slice(0, 5);
81
- top.forEach((rec, i) => {
82
- const candidate = candidateForDisplay(rec);
83
- const signal = formatSignal(rec.o11ySignal ?? signalFromRec(rec) ?? "", candidate);
84
- lines.push(`${i + 1}. **${formatCandidateLabel(candidate)}** — ${signal}`);
85
- lines.push(` - **What to do**: ${formatRecommendationText(rec.what ?? "")}`);
86
- lines.push(` - **Impact**: ${formatRecommendationText(impactString(rec, signals))}`);
87
- if (rec.effort) lines.push(` - **Effort**: ${rec.effort}`);
88
- const cites = asArray(rec.citations);
89
- if (cites.length > 0) lines.push(` - **Citations**: ${cites.join(", ")}`);
90
- });
91
- }
92
- lines.push("");
93
-
94
- lines.push("## Recommendations");
95
- lines.push("");
96
- lines.push("### High impact");
97
- lines.push("");
98
- lines.push(...renderRecTable(high, signals));
99
- lines.push("");
100
- lines.push("### Medium impact");
101
- lines.push("");
102
- lines.push(...renderRecTable(medium, signals));
103
- lines.push("");
104
- if (low.length > 0) {
105
- lines.push("### Low impact");
106
- lines.push("");
107
- lines.push(...renderRecTable(low, signals));
108
- lines.push("");
109
- }
110
-
111
- lines.push("## Detailed recommendations");
112
- lines.push("");
113
- if (sorted.length === 0) {
114
- lines.push("_No recommendations are ready to apply from this run._");
115
- } else {
116
- for (const [i, rec] of sorted.entries()) {
117
- lines.push(...renderRecDetail(rec, i + 1, { signals }));
118
- }
119
- }
120
- lines.push("");
121
-
122
- lines.push("## Platform recommendations");
123
- lines.push("");
124
- if (platformRecs.length === 0) {
125
- lines.push("_(none — the gate did not surface any platform-scope recommendations)_");
126
- } else {
127
- for (const [i, rec] of platformRecs.entries()) {
128
- lines.push(...renderRecDetail(rec, i + 1, { compact: true, signals }));
129
- }
130
- }
131
- lines.push("");
132
-
133
- // Observations carry actionable signal discovered during investigation.
134
- if (observations.length > 0) {
135
- lines.push("## Observations from investigation");
136
- lines.push("");
137
- lines.push(
138
- "These are real signals from the audit, but they are not ready-to-apply recommendations.",
139
- );
140
- lines.push("");
141
- lines.push("| Candidate | Observation | Evidence | Suggested action | Kind |");
142
- lines.push("|---|---|---|---|---|");
143
- for (const o of observations) {
144
- const ref = o.candidateRef ?? "(unspecified)";
145
- lines.push(
146
- `| ${escape(displayCandidateRef(ref))} | ${escape(formatEvidenceText(o.summary))} | ${escape(formatEvidenceText(o.evidence ?? "_(none recorded)_"))} | ${escape(formatEvidenceText(o.suggestedAction ?? "_(none recorded)_"))} | ${escape(formatKind(o.kind ?? "other"))} |`,
147
- );
148
- }
149
- lines.push("");
150
- }
151
-
152
- // Trust mechanism: customer sees what was investigated and why no rec emerged.
153
- if (needsEvidenceRows.length > 0) {
154
- lines.push("## Needs more evidence");
155
- lines.push("");
156
- lines.push(
157
- "These candidates were investigated, but automated checks kept the change out of the ready-to-apply list.",
158
- );
159
- lines.push("");
160
- lines.push("| Candidate | Why it was held back |");
161
- lines.push("|---|---|");
162
- for (const a of needsEvidenceRows) {
163
- const ref = a.candidateRef ?? "(unspecified)";
164
- const reason = publicNoRecommendationReason(a.reason ?? "(no reason recorded)");
165
- lines.push(`| ${escape(displayCandidateRef(ref))} | ${escape(reason)} |`);
166
- }
167
- lines.push("");
168
- }
169
-
170
- if (noChangeRows.length > 0) {
171
- lines.push("## Investigated, no change recommended");
172
- lines.push("");
173
- lines.push("These candidates were checked and did not produce a supported change.");
174
- lines.push("");
175
- lines.push("| Candidate | Why no recommendation shipped |");
176
- lines.push("|---|---|");
177
- for (const a of noChangeRows) {
178
- const ref = a.candidateRef ?? "(unspecified)";
179
- const reason = publicNoRecommendationReason(a.reason ?? "(no reason recorded)");
180
- lines.push(`| ${escape(displayCandidateRef(ref))} | ${escape(reason)} |`);
181
- }
182
- lines.push("");
183
- }
184
-
185
- lines.push("## Not investigated in this run");
186
- lines.push("");
187
- lines.push(...renderGatedTable(gated));
188
- lines.push("");
189
-
190
- lines.push("## Strengths");
191
- lines.push("");
192
- lines.push(...renderStrengths(signals));
193
- lines.push("");
194
-
195
- const configNotes = renderConfigurationNotes(signals);
196
- if (configNotes.length > 0) {
197
- lines.push("## Configuration notes");
198
- lines.push("");
199
- lines.push(...configNotes);
200
- lines.push("");
201
- }
202
-
203
- lines.push("## Data gaps");
204
- lines.push("");
205
- lines.push(...renderDataGaps(signals));
206
-
207
- return lines.join("\n");
208
- }
209
-
210
- function assertValidObservations(observations) {
211
- if (!Array.isArray(observations)) {
212
- throw new TypeError("renderReport observations must be an array");
213
- }
214
- for (const [i, o] of observations.entries()) {
215
- if (!o || typeof o !== "object") {
216
- throw new TypeError(`renderReport observations[${i}] must be an object`);
217
- }
218
- if (typeof o.summary !== "string" || o.summary.trim() === "") {
219
- throw new TypeError(`renderReport observations[${i}].summary is required`);
220
- }
221
- }
222
- }
223
-
224
- export function buildFinalReportMessage({
225
- reportPath,
226
- markdown,
227
- recommendations = [],
228
- signals = {},
229
- maxRecommendations = 10,
230
- } = {}) {
231
- const destination = reportPath || "report.md";
232
- const coverageLine = extractCoverageLine(markdown);
233
- const lines = [`Report saved: ${destination}`];
234
- if (coverageLine) {
235
- lines.push("");
236
- lines.push(stripDetailsLink(coverageLine));
237
- } else {
238
- lines.push("");
239
- lines.push("Open the report for details. No coverage summary was available.");
240
- }
241
- const readyPreview = renderFinalRecommendationPreview(
242
- recommendations,
243
- signals,
244
- maxRecommendations,
245
- );
246
- if (readyPreview.length > 0) {
247
- lines.push("");
248
- lines.push(...readyPreview);
249
- }
250
- const body = lines.join("\n");
251
- return {
252
- body,
253
- lineCount: lines.length,
254
- sha256: createHash("sha256").update(body).digest("hex"),
255
- reportPath: destination,
256
- coverageLine: coverageLine ?? null,
257
- recommendationsShown: readyPreview.filter((line) => /^\d+\./.test(line)).length,
258
- };
259
- }
260
-
261
- function renderFinalRecommendationPreview(recommendations, signals, maxRecommendations) {
262
- const ready = Array.isArray(recommendations)
263
- ? sortRecs(recommendations.filter((r) => r && r.abstain !== true))
264
- : [];
265
- if (ready.length === 0) return [];
266
- const max = Math.max(
267
- 1,
268
- Math.min(Number.isInteger(maxRecommendations) ? maxRecommendations : 5, 10),
269
- );
270
- const shown = ready.slice(0, max);
271
- const lines = ["Ready recommendations:"];
272
- for (const [i, rec] of shown.entries()) {
273
- lines.push(`${i + 1}. ${compactFinalText(rec.what ?? displayCandidate(rec))}`);
274
- const impact = impactString(rec, signals);
275
- if (impact && !/^_\(no impact framing recorded\)_$/.test(impact)) {
276
- lines.push(` Impact: ${compactFinalText(impact)}`);
277
- }
278
- }
279
- const hidden = ready.length - shown.length;
280
- if (hidden > 0) {
281
- lines.push(
282
- `Open the report for ${hidden} more ready recommendation${hidden === 1 ? "" : "s"} and the full evidence.`,
283
- );
284
- }
285
- return lines;
286
- }
287
-
288
- function compactFinalText(value) {
289
- const text = formatRecommendationText(String(value ?? ""))
290
- .replace(/\s+/g, " ")
291
- .trim();
292
- if (text.length <= 220) return text;
293
- return `${text.slice(0, 217).trimEnd()}...`;
294
- }
295
-
296
- function extractCoverageLine(markdown) {
297
- if (typeof markdown !== "string") return null;
298
- return markdown.split("\n").find((line) => line.startsWith("**Coverage**:")) ?? null;
299
- }
300
-
301
- function stripDetailsLink(line) {
302
- return String(line).replace(/\s*·\s*\[details\]\(#not-investigated-in-this-run\)\s*$/, "");
303
- }
304
-
305
- // Hidden when no candidates exist (e.g., observability blocker — nothing to cover).
306
- function renderCoverageLine(candidates, recommendations, signals, opts = {}) {
307
- if (!Array.isArray(candidates) || candidates.length === 0) return null;
308
- const launched = candidates.filter(
309
- (c) => !c.gatedReason && !c.disqualified && c.scope !== "account",
310
- );
311
- const skippedByBudget = candidates.filter(
312
- (c) => typeof c.gatedReason === "string" && c.gatedReason.startsWith("skippedByBudget"),
313
- );
314
- const coveredByDedup = candidates.filter(
315
- (c) => typeof c.gatedReason === "string" && c.gatedReason.startsWith("coveredBy"),
316
- );
317
- const disqualified = candidates.filter(
318
- (c) => typeof c.gatedReason === "string" && c.gatedReason === c.disqualifyReason,
319
- );
320
- const total = launched.length + skippedByBudget.length;
321
- if (total === 0) return null;
322
- const parts = [];
323
- parts.push(`Found **${total}** potential issue${total === 1 ? "" : "s"} to check`);
324
- parts.push(`${launched.length} investigated`);
325
- if (skippedByBudget.length > 0) {
326
- parts.push(
327
- `${skippedByBudget.length} left for a larger run — re-run with \`--max-candidates all\` to see the rest`,
328
- );
329
- }
330
- if (coveredByDedup.length > 0) {
331
- parts.push(
332
- `${coveredByDedup.length} similar route variant${coveredByDedup.length === 1 ? "" : "s"} grouped`,
333
- );
334
- }
335
- const recCount = (recommendations ?? []).filter((r) => !r.abstain && !isPlatformScope(r)).length;
336
- parts.push(`${recCount} recommendation${recCount === 1 ? "" : "s"} ready`);
337
- const rawHeldBackCount = Number.isInteger(opts.heldBackCount)
338
- ? opts.heldBackCount
339
- : Array.isArray(opts.abstentions)
340
- ? opts.abstentions.filter((a) => a?.needsEvidence === true).length
341
- : 0;
342
- const heldBackCount = Math.min(rawHeldBackCount, Math.max(0, launched.length - recCount));
343
- if (heldBackCount > 0) {
344
- parts.push(`${heldBackCount} need more evidence`);
345
- }
346
- const rawNoChangeCount = Number.isInteger(opts.noChangeCount)
347
- ? opts.noChangeCount
348
- : Array.isArray(opts.abstentions)
349
- ? opts.abstentions.length
350
- : 0;
351
- const noChangeCount = Math.min(
352
- rawNoChangeCount,
353
- Math.max(0, launched.length - recCount - heldBackCount),
354
- );
355
- if (noChangeCount > 0) {
356
- parts.push(`${noChangeCount} investigated, no change recommended`);
357
- }
358
- return `**Coverage**: ${parts.join(" · ")} · [details](#not-investigated-in-this-run)`;
359
- }
360
-
361
- function renderMetadataLine(stack, plan, usage, signals = {}) {
362
- const fw = `${stack.framework ?? "unknown"}@${stack.frameworkVersion ?? "?"}`;
363
- const router = stack.hasAppRouter ? "app-router" : stack.hasPagesRouter ? "pages-router" : null;
364
- const orm = stack.orm && stack.orm !== "none" ? stack.orm : null;
365
- const stackParts = [fw, router, orm].filter(Boolean).join(" | ");
366
- const period = usage?.period
367
- ? `${usage.period.from ?? "?"} → ${usage.period.to ?? "?"}`
368
- : "(unavailable)";
369
- const oplusLabel = observabilityLabel(signals, usage);
370
- // Plan-inference reason is debug detail — only surface when plan is uncertain.
371
- const planLabel =
372
- plan.plan === "uncertain"
373
- ? `${plan.plan} (${plan.reason ?? "no signal"})`
374
- : (plan.plan ?? "unknown");
375
- return `**Stack**: ${stackParts} · **Plan**: ${planLabel} · **Period**: ${period} · **Observability**: ${oplusLabel}`;
376
- }
377
-
378
- function observabilityLabel(signals, usage) {
379
- if (signals.observabilityPlusUsable === true) {
380
- return "Observability Plus enabled — per-route metrics included";
381
- }
382
- if (signals.observabilityPlusUsable === false) {
383
- if (usage) {
384
- return "Per-route metrics unavailable — analysis based on billing + scanner findings";
385
- }
386
- if (signals.usageError === "NOT_COLLECTED_OBSERVABILITY_BLOCKED") {
387
- return "Per-route metrics unavailable — audit paused before metric-backed route ranking";
388
- }
389
- return "Per-route metrics unavailable — limited analysis based on scanner findings";
390
- }
391
- if (signals.observabilityPlus === true) {
392
- return "Observability Plus enabled — per-route metrics included";
393
- }
394
- if (signals.usageError === "NOT_COLLECTED_UNSUPPORTED_FRAMEWORK") {
395
- return "Not checked — audit paused at unsupported-framework preflight";
396
- }
397
- if (signals.usageError === "NOT_COLLECTED_OBSERVABILITY_BLOCKED") {
398
- return "Per-route metrics unavailable — audit paused before metric-backed route ranking";
399
- }
400
- if (usage) {
401
- return "Not enabled — analysis based on billing + scanner findings";
402
- }
403
- if (signals.observabilityPlus === false) {
404
- return "Not enabled — limited analysis only";
405
- }
406
- return "Not checked — limited analysis only";
407
- }
408
-
409
- function renderCostHeader(signals) {
410
- const scope = signals.usageScope;
411
- if (scope === "project") {
412
- return ["## Cost breakdown (this project)"];
413
- }
414
- if (scope === "team" && signals.usage) {
415
- return [
416
- "## Cost breakdown (team-wide — `vercel usage` has no per-project filter)",
417
- "",
418
- "_The Vercel CLI's `vercel usage` reports team-wide billing without a project filter (verified May 2026). This breakdown is the whole team's bill for the window. Per-route metrics in the rest of this report are project-scoped via `vercel metrics`._",
419
- ];
420
- }
421
- return ["## Cost breakdown"];
422
- }
423
-
424
- function renderCostBreakdown(usage, signals) {
425
- const lines = [];
426
- const services = Array.isArray(usage?.services) ? usage.services : null;
427
- if (services && services.length > 0) {
428
- const chargedRows = services.filter((s) => {
429
- const cost = serviceCost(s);
430
- return cost === null || costRoundsToCents(cost) > 0;
431
- });
432
- if (chargedRows.length > 0) {
433
- return renderServiceCostRows(chargedRows, {
434
- costLabel: "Billed cost",
435
- costOf: serviceCost,
436
- omittedZeroRows: services.length - chargedRows.length,
437
- total: usage.totals?.billedCost,
438
- totalLabel: "Total billed",
439
- totalSuffix:
440
- " _(precise observed cost; future-savings framing is magnitude, never precise)_",
441
- });
442
- }
443
-
444
- const effectiveRows = services.filter((s) => costRoundsToCents(serviceEffectiveCost(s)) > 0);
445
- if (effectiveRows.length > 0) {
446
- lines.push(
447
- "_Net billed cost is $0.00 after included credits or allotments. Showing effective usage cost so active cost drivers are still visible._",
448
- );
449
- lines.push("");
450
- return [
451
- ...lines,
452
- ...renderServiceCostRows(effectiveRows, {
453
- costLabel: "Effective cost",
454
- costOf: serviceEffectiveCost,
455
- omittedZeroRows: services.length - effectiveRows.length,
456
- total: usage.totals?.effectiveCost,
457
- totalLabel: "Total effective cost",
458
- totalSuffix: " _(usage cost before included-credit or allotment offsets)_",
459
- }),
460
- ];
461
- }
462
-
463
- if (chargedRows.length === 0) {
464
- const scope = signals.usageScope === "team" ? "team-wide " : "";
465
- lines.push(
466
- `_\`vercel usage\` returned a ${scope}billing payload, but every reported service cost was $0.00 for this window._`,
467
- );
468
- return lines;
469
- }
470
- }
471
-
472
- // Fallback to o11y-derived ranking when usage payload missing.
473
- const gbHr = signals.metrics?.fnGbHrByRoute?.rows ?? [];
474
- const usageGap = missingUsageSentence(signals);
475
- if (gbHr.length === 0) {
476
- lines.push(
477
- `_${usageGap} Without per-route function GB-hour data, this report cannot rank cost drivers._`,
478
- );
479
- return lines;
480
- }
481
- const top = groupGbHoursByCanonicalRoute(gbHr)
482
- .sort((a, b) => (b.value ?? 0) - (a.value ?? 0))
483
- .slice(0, 10);
484
- lines.push(
485
- `_${usageGap} Ranking by \`function_duration_gbhr\` instead. These do not translate to dollars directly, but they show which routes consume billable units._`,
486
- );
487
- lines.push("");
488
- lines.push("| Route | GB-hr (sum, 14d) |");
489
- lines.push("|---|---|");
490
- for (const r of top) {
491
- lines.push(`| ${escape(r.route ?? "(unnamed)")} | ${(r.value ?? 0).toFixed(4)} |`);
492
- }
493
- return lines;
494
- }
495
-
496
- function renderServiceCostRows(
497
- services,
498
- { costLabel, costOf, omittedZeroRows = 0, total = null, totalLabel, totalSuffix = "" },
499
- ) {
500
- const lines = [];
501
- const rows = services.slice().sort((a, b) => (costOf(b) ?? 0) - (costOf(a) ?? 0));
502
- // Drop Usage column when every cell is "(unspecified)" — happens when CLI emits pricingUnit=USD.
503
- const usageCells = rows.map((s) => formatUsage(s));
504
- const hasRealUsage = usageCells.some((c) => c !== "(unspecified)");
505
- if (hasRealUsage) {
506
- lines.push(`| Service | Usage | ${costLabel} |`);
507
- lines.push("|---|---|---|");
508
- for (let i = 0; i < rows.length; i++) {
509
- const s = rows[i];
510
- const costValue = costOf(s);
511
- const cost = typeof costValue === "number" ? `$${costValue.toFixed(2)}` : "(n/a)";
512
- lines.push(`| ${escape(s.name ?? "(unnamed)")} | ${escape(usageCells[i])} | ${cost} |`);
513
- }
514
- } else {
515
- lines.push(`| Service | ${costLabel} |`);
516
- lines.push("|---|---|");
517
- for (const s of rows) {
518
- const costValue = costOf(s);
519
- const cost = typeof costValue === "number" ? `$${costValue.toFixed(2)}` : "(n/a)";
520
- lines.push(`| ${escape(s.name ?? "(unnamed)")} | ${cost} |`);
521
- }
522
- }
523
- if (omittedZeroRows > 0) {
524
- lines.push("");
525
- lines.push(
526
- `_${omittedZeroRows} zero-cost service ${omittedZeroRows === 1 ? "row was" : "rows were"} omitted._`,
527
- );
528
- }
529
- if (typeof total === "number") {
530
- lines.push("");
531
- lines.push(`**${totalLabel}: $${total.toFixed(2)}**${totalSuffix}`);
532
- }
533
- return lines;
534
- }
535
-
536
- function serviceCost(service) {
537
- if (typeof service?.billedCost === "number") return service.billedCost;
538
- if (typeof service?.cost === "number") return service.cost;
539
- return null;
540
- }
541
-
542
- function serviceEffectiveCost(service) {
543
- if (typeof service?.effectiveCost === "number") return service.effectiveCost;
544
- if (typeof service?.pricingQuantity === "number" && service?.pricingUnit === "USD")
545
- return service.pricingQuantity;
546
- return 0;
547
- }
548
-
549
- function costRoundsToCents(cost) {
550
- if (typeof cost !== "number" || !Number.isFinite(cost)) return 0;
551
- return Math.round(cost * 100) / 100;
552
- }
553
-
554
- function renderRecTable(recs, signals = {}) {
555
- if (recs.length === 0) return ["_(none)_"];
556
- const lines = [];
557
- lines.push("| # | Bucket | What | Impact | Effort | Citations |");
558
- lines.push("|---|---|---|---|---|---|");
559
- recs.forEach((r, i) => {
560
- const cites = asArray(r.citations).slice(0, 2).join("<br>");
561
- lines.push(
562
- `| ${i + 1} | ${r.bucket ?? "?"} | ${escape(formatRecommendationText(r.what ?? ""))} | ${escape(formatRecommendationText(impactString(r, signals)))} | ${r.effort ?? "?"} | ${cites} |`,
563
- );
564
- });
565
- return lines;
566
- }
567
-
568
- function renderRecDetail(rec, index, { compact = false, signals = {} } = {}) {
569
- const lines = [];
570
- lines.push(`### ${index}. ${formatRecommendationText(rec.what ?? "(no `what`)")}`);
571
- lines.push("");
572
- const meta = [
573
- rec.bucket ? `**${rec.bucket}**` : null,
574
- rec.effort ? `effort: ${rec.effort}` : null,
575
- rec.impactTier ? `impact tier: ${rec.impactTier}` : null,
576
- rec.candidateRef ? `candidate: ${displayCandidate(rec)}` : null,
577
- rec.corroborationCount > 1 ? `corroborated: ${rec.corroborationCount}` : null,
578
- ].filter(Boolean);
579
- if (meta.length > 0) lines.push(`_${meta.join(" · ")}_`);
580
- lines.push("");
581
- const appliesAlsoTo = asArray(rec.appliesAlsoTo);
582
- if (appliesAlsoTo.length > 0) {
583
- const refs = appliesAlsoTo
584
- .map((a) => a?.candidateRef)
585
- .filter(Boolean)
586
- .slice(0, 4);
587
- if (refs.length > 0) {
588
- const suffix =
589
- appliesAlsoTo.length > refs.length ? `, +${appliesAlsoTo.length - refs.length} more` : "";
590
- lines.push(`_Also applies to: ${refs.map(displayCandidateRef).join(", ")}${suffix}._`);
591
- lines.push("");
592
- }
593
- }
594
- if (rec.why) {
595
- lines.push("**Why**");
596
- lines.push("");
597
- lines.push(formatRecommendationText(rec.why));
598
- lines.push("");
599
- }
600
- lines.push("**Impact**");
601
- lines.push("");
602
- lines.push(formatRecommendationText(impactString(rec, signals)));
603
- lines.push("");
604
- if (!compact && rec.fix) {
605
- lines.push("**Fix**");
606
- lines.push("");
607
- lines.push(rec.fix);
608
- lines.push("");
609
- }
610
- if (!compact && rec.currentBehavior) {
611
- lines.push("**Before**");
612
- lines.push("");
613
- lines.push(rec.currentBehavior);
614
- lines.push("");
615
- }
616
- if (!compact && rec.desiredBehavior) {
617
- lines.push("**After**");
618
- lines.push("");
619
- lines.push(rec.desiredBehavior);
620
- lines.push("");
621
- }
622
- if (rec.verify) {
623
- lines.push("**Verify**");
624
- lines.push("");
625
- lines.push(formatRecommendationText(rec.verify));
626
- lines.push("");
627
- }
628
- const cites = asArray(rec.citations);
629
- if (cites.length > 0) {
630
- lines.push("**Citations**");
631
- lines.push("");
632
- for (const c of cites) lines.push(`- \`${c}\``);
633
- lines.push("");
634
- }
635
- lines.push("");
636
- return lines;
637
- }
638
-
639
- function renderGatedTable(gated) {
640
- if (!Array.isArray(gated) || gated.length === 0) {
641
- return ["_(no candidates were held back)_"];
642
- }
643
- const groups = groupGatedCandidates(gated);
644
- const lines = [];
645
- lines.push("| Candidate type | Why not investigated | Targets | Count |");
646
- lines.push("|---|---|---|---:|");
647
- for (const group of groups) {
648
- lines.push(
649
- `| ${escape(group.kind)} | ${escape(group.reason)} | ${formatGatedTargets(group.targets, group.count)} | ${group.count} |`,
650
- );
651
- }
652
- return lines;
653
- }
654
-
655
- function formatGatedTargets(targets, count) {
656
- const unique = [...new Set(targets.map((t) => String(t)))];
657
- const shown = unique.slice(0, GATED_TARGET_PREVIEW).map((target) => escape(target));
658
- const hidden = Math.max(0, count - shown.length);
659
- if (hidden > 0) shown.push(`+${hidden} more`);
660
- return shown.join("<br>");
661
- }
662
-
663
- function groupGatedCandidates(gated) {
664
- const byKey = new Map();
665
- for (const g of gated) {
666
- const kind = formatKind(g.kind ?? "?");
667
- const reason = publicGatedReason(g.gatedReason ?? g.disqualifyReason ?? "(no reason recorded)");
668
- const target = formatRoute(g);
669
- const key = `${kind}\u0000${reason}`;
670
- const existing = byKey.get(key);
671
- if (existing) {
672
- existing.count += 1;
673
- existing.targets.push(String(target));
674
- } else {
675
- byKey.set(key, {
676
- kind: String(kind),
677
- reason: String(reason),
678
- targets: [String(target)],
679
- count: 1,
680
- });
681
- }
682
- }
683
- return Array.from(byKey.values());
684
- }
685
-
686
- function publicNoRecommendationReason(reason) {
687
- return formatEvidenceText(String(reason))
688
- .replace(/\bDropped at render:\s*/gi, "")
689
- .replace(
690
- /\bverifier flagged for regen, but no regen happened\b/gi,
691
- "needs stronger evidence before it is safe to apply",
692
- )
693
- .replace(
694
- /\bRe-run with a refreshed brief\.?/gi,
695
- "Re-run the investigation after refreshing the evidence.",
696
- )
697
- .replace(/\bregen\b/gi, "re-check")
698
- .replace(/\bverifier\b/gi, "verification")
699
- .replace(/\brec\b/gi, "recommendation")
700
- .replace(/\bsub[- ]agent\b/gi, "investigation")
701
- .replace(/\babstentions?\b/gi, "no-change findings")
702
- .replace(/\babstaining\b/gi, "not recommending a change")
703
- .replace(/\babstain(?:ed)?\b/gi, "found no supported change")
704
- .replace(/\bquality\s*\+\s*verification\b/gi, "verification")
705
- .replace(/\bquality\b/gi, "review")
706
- .replace(/\bsanitizers?\b/gi, "checks");
707
- }
708
-
709
- function splitInvestigationOutcomes(abstentions) {
710
- const rows = Array.isArray(abstentions) ? abstentions : [];
711
- return {
712
- needsEvidenceRows: rows.filter((a) => a?.needsEvidence === true),
713
- noChangeRows: rows.filter((a) => a?.needsEvidence !== true),
714
- };
715
- }
716
-
717
- function publicGatedReason(reason) {
718
- return formatPublicText(String(reason))
719
- .replace(/\bhardGated:\s*/gi, "")
720
- .replace(
721
- /skippedByBudget\s*\(max-candidates=([^);]+)(?:;[^)]*)?\)/i,
722
- "left for a larger run (max candidates: $1)",
723
- )
724
- .replace(/skippedByBudget\b/gi, "left for a larger run")
725
- .replace(/\s*;\s*raise with --max-candidates N or =all/gi, "")
726
- .replace(/=all/g, "all")
727
- .replace(/\bcoveredBy\b/gi, "covered by a higher-priority candidate")
728
- .replace(/\bdisqualified\b/gi, "not eligible");
729
- }
730
-
731
- function formatEvidenceText(value) {
732
- const expanded = formatPublicText(value)
733
- .replace(/\bdeepDive\b/gi, "follow-up metric")
734
- .replace(/\bdeep-dive\b/gi, "follow-up metric")
735
- .replace(/\blatency p95\b/gi, "95th percentile latency")
736
- .replace(/\bttfb p95\b/gi, "95th percentile TTFB")
737
- .replace(/\bcpu p95\b/gi, "95th percentile CPU time")
738
- .replace(/\bp95\b/gi, "95th percentile")
739
- .replace(/\bgate signal\b/gi, "broad metric signal")
740
- .replace(/\bo11ySignal\b/gi, "observed signal")
741
- .replace(/\bperDeployment\b/gi, "per-deployment")
742
- .replace(/\bstartTypeSplit\b/gi, "start-type breakdown")
743
- .replace(/\bstatusDistribution\b/gi, "status distribution")
744
- .replace(/\bcacheBreakdown\b/gi, "cache breakdown")
745
- .replace(/\bfunctionRoutes\b/gi, "function routes")
746
- .replace(/\bfnGbHrByRoute\b/gi, "function duration by route");
747
- return formatPublicText(expanded);
748
- }
749
-
750
- function formatRecommendationText(value) {
751
- return formatEvidenceText(value)
752
- .replace(/\bthe gate fires\b/gi, "this audit flags the signal")
753
- .replace(/\bships immediately\b/gi, "can ship sooner");
754
- }
755
-
756
- function displayCandidate(value) {
757
- return formatCandidateLabel(candidateForDisplay(value));
758
- }
759
-
760
- function candidateForDisplay(value) {
761
- const parsed = parseCandidateRef(value?.candidateRef);
762
- return parsed ? displayCandidateObject(value, parsed) : value;
763
- }
764
-
765
- function displayCandidateRef(ref) {
766
- const parsed = parseCandidateRef(ref);
767
- if (!parsed) return String(ref ?? "(unspecified)");
768
- return formatCandidateLabel(displayCandidateObject({}, parsed));
769
- }
770
-
771
- function parseCandidateRef(ref) {
772
- if (typeof ref !== "string") return null;
773
- const [kind, ...rest] = ref.split(":");
774
- const target = rest.join(":");
775
- if (!kind || !target) return null;
776
- return { kind, target };
777
- }
778
-
779
- function displayCandidateObject(base, parsed) {
780
- if (parsed.target.startsWith("<account>#")) {
781
- return { ...base, kind: parsed.kind, files: [parsed.target.slice("<account>#".length)] };
782
- }
783
- if (parsed.target === "<account>") {
784
- return { ...base, kind: parsed.kind };
785
- }
786
- return { ...base, kind: parsed.kind, route: parsed.target };
787
- }
788
-
789
- function groupGbHoursByCanonicalRoute(rows) {
790
- const byRoute = new Map();
791
- for (const row of rows) {
792
- const route = row?.route ? canonicalizeRoute(row.route) : "(unnamed)";
793
- byRoute.set(route, (byRoute.get(route) ?? 0) + (row?.value ?? 0));
794
- }
795
- return [...byRoute.entries()].map(([route, value]) => ({ route, value }));
796
- }
797
-
798
- function renderStrengths(signals) {
799
- const lines = [];
800
-
801
- // Stops agent from emitting "verify Fluid is on" recs. Source: defaultResourceConfig from project API.
802
- const projectFacts = deriveProjectFacts(signals);
803
- for (const f of projectFacts) {
804
- if (String(f.id ?? "").startsWith("memory_")) continue;
805
- lines.push(`- ${f.strength}`);
806
- }
807
-
808
- const cache = signals.metrics?.fdtByCache?.rows ?? [];
809
- const hit = cache.find((r) => r.cache_result === "HIT" || r.cache_result === "STALE");
810
- const miss = cache.find((r) => r.cache_result === "MISS" || r.cache_result === "BYPASS");
811
- if (hit && miss && (hit.value ?? 0) > (miss.value ?? 0)) {
812
- lines.push(
813
- `- Cache hit-rate is healthy at the bandwidth tier — HIT/STALE bandwidth (${formatBytes(hit.value)}) exceeds MISS/BYPASS (${formatBytes(miss.value)}).`,
814
- );
815
- }
816
- const cold = signals.metrics?.fnStartTypeByRoute?.rows ?? [];
817
- const totalInv = cold.reduce((s, r) => s + (r.total ?? 0), 0);
818
- const totalCold = cold.reduce((s, r) => s + (r.coldCount ?? 0), 0);
819
- if (totalInv > 1000) {
820
- const coldPct = totalCold / totalInv;
821
- if (coldPct < 0.02)
822
- lines.push(
823
- `- Cold-start rate is very low (${(coldPct * 100).toFixed(2)}%) — Fluid Compute or warm-instance reuse is doing its job.`,
824
- );
825
- }
826
- const errors = signals.metrics?.requestsByRouteStatus?.rows ?? [];
827
- const total5xx = errors
828
- .filter((r) => /^5/.test(r.http_status ?? ""))
829
- .reduce((s, r) => s + (r.value ?? 0), 0);
830
- const totalReq = errors.reduce((s, r) => s + (r.value ?? 0), 0);
831
- if (totalReq > 1000) {
832
- const rate = total5xx / totalReq;
833
- if (rate < 0.001)
834
- lines.push(
835
- `- 5xx rate is very low (${(rate * 100).toFixed(3)}%) on ${formatNum(totalReq)} requests.`,
836
- );
837
- }
838
- if (lines.length === 0)
839
- lines.push(
840
- "_(no headline strengths to call out — see the gated table for signals we considered)_",
841
- );
842
- return lines;
843
- }
844
-
845
- function renderConfigurationNotes(signals) {
846
- const projectFacts = deriveProjectFacts(signals);
847
- return projectFacts
848
- .filter((f) => String(f.id ?? "").startsWith("memory_"))
849
- .map((f) => `- ${f.strength}`);
850
- }
851
-
852
- function renderDataGaps(signals) {
853
- const lines = [];
854
- const observabilityGap = observabilityDataGap(signals);
855
- if (observabilityGap) lines.push(observabilityGap);
856
- if (!signals.usage) lines.push(`- ${missingUsageSentence(signals)}`);
857
- const cwvMetric = metricState(signals, "cwvCount");
858
- if (cwvMetric.failed) {
859
- lines.push(
860
- `- Speed Insights metrics were not usable (\`${cwvMetric.code}\`), so LCP/INP/CLS analysis was skipped.`,
861
- );
862
- } else if (cwvMetric.collected) {
863
- const cwv = cwvMetric.rows?.[0]?.value ?? 0;
864
- if (cwv === 0)
865
- lines.push(
866
- "- No Speed Insights measurements — Core Web Vitals analysis dormant. Wire up Speed Insights to enable LCP/INP/CLS recommendations.",
867
- );
868
- }
869
- const isrMetric = metricState(signals, "isrReadsByRoute");
870
- if (isrMetric.collected) {
871
- const isrR = isrMetric.rows ?? [];
872
- if (isrR.length === 0)
873
- lines.push(
874
- "- No ISR activity observed — either the project does not use ISR or no eligible routes had traffic in the window.",
875
- );
876
- }
877
- const imageMetric = metricState(signals, "imageCount");
878
- if (imageMetric.collected) {
879
- const images = imageMetric.rows?.[0]?.value ?? 0;
880
- if (images === 0)
881
- lines.push(
882
- "- No image transformations observed — either `next/image` is not used or no images served in the window.",
883
- );
884
- }
885
- const middlewareMetric = metricState(signals, "middlewareCount");
886
- if (middlewareMetric.collected) {
887
- const middleware = middlewareMetric.rows ?? [];
888
- if (middleware.length === 0)
889
- lines.push(
890
- "- No middleware invocations — either no `middleware.ts` is shipped or its matcher excludes all observed traffic.",
891
- );
892
- }
893
- if (lines.length === 0) lines.push("_(no relevant gaps — every signal had data)_");
894
- return lines;
895
- }
896
-
897
- function observabilityDataGap(signals = {}) {
898
- if (signals.usageError === "NOT_COLLECTED_UNSUPPORTED_FRAMEWORK") {
899
- return "- Observability Plus was not checked because the audit paused at the unsupported-framework preflight.";
900
- }
901
- if (signals.observabilityPlusUsable === false) {
902
- const blocker = signals.observabilityPlusBlocker;
903
- if (blocker === "project_disabled") {
904
- return "- Per-route metrics unavailable — Observability Plus is disabled for this project.";
905
- }
906
- if (blocker === "forbidden" || blocker === "project_not_found") {
907
- return "- Per-route metrics unavailable — the authenticated Vercel scope cannot read this project.";
908
- }
909
- if (blocker === "not_linked") {
910
- return "- Per-route metrics unavailable — the app directory is not linked to the Vercel project.";
911
- }
912
- if (blocker === "no_oplus_probe") {
913
- return "- Per-route metrics unavailable — Observability Plus was not detected for this scope.";
914
- }
915
- if (blocker === "payment_required") {
916
- return "- Per-route metrics unavailable — Observability Plus metrics were not usable for this scope.";
917
- }
918
- if (blocker === "daily_quota_exceeded") {
919
- return "- Per-route metrics unavailable — the Observability Plus query quota is exhausted for today.";
920
- }
921
- if (blocker === "no_traffic") {
922
- return "- Per-route metrics sparse — no route-level traffic was returned in the metrics window.";
923
- }
924
- if (blocker === "all_failed_other") {
925
- return "- Per-route metrics unavailable — all Observability Plus metric queries failed.";
926
- }
927
- if (blocker) {
928
- return `- Per-route metrics unavailable — Observability Plus metrics returned \`${blocker}\`.`;
929
- }
930
- return "- Per-route metrics unavailable — Observability Plus data was not usable for this run.";
931
- }
932
- if (signals.observabilityPlus === false) {
933
- return "- Observability Plus not enabled — per-route latency / cache-hit / cold-start metrics unavailable.";
934
- }
935
- return null;
936
- }
937
-
938
- function missingUsageSentence(signals = {}) {
939
- const code = signals.usageError;
940
- if (code === "NOT_COLLECTED_OBSERVABILITY_BLOCKED") {
941
- return "`vercel usage` was not collected because the audit paused before billing collection on the Observability Plus blocker.";
942
- }
943
- if (code === "NOT_COLLECTED_UNSUPPORTED_FRAMEWORK") {
944
- return "`vercel usage` was not collected because the audit paused at the unsupported-framework preflight.";
945
- }
946
- if (code === "USAGE_CONTEXT_MISMATCH") {
947
- return "`vercel usage` returned data for a different team context, so the billing breakdown was not used.";
948
- }
949
- if (code === "USAGE_UNAVAILABLE") {
950
- return "`vercel usage` returned `USAGE_UNAVAILABLE`; no billing breakdown was available from the Vercel CLI.";
951
- }
952
- if (typeof code === "string" && code.trim() !== "") {
953
- return `\`vercel usage\` returned \`${code}\`; no billing breakdown was available from the Vercel CLI.`;
954
- }
955
- return "`vercel usage` did not return a billing payload.";
956
- }
957
-
958
- function metricState(signals, id) {
959
- const metrics = signals.metrics ?? {};
960
- if (!Object.prototype.hasOwnProperty.call(metrics, id)) {
961
- return { collected: false, failed: false, rows: null, code: null };
962
- }
963
- const metric = metrics[id] ?? {};
964
- const failed = metric.ok === false;
965
- return {
966
- collected: !failed,
967
- failed,
968
- rows: Array.isArray(metric.rows) ? metric.rows : [],
969
- code: metric.code ?? "UNKNOWN",
970
- };
971
- }
972
-
973
- function sortRecs(recs) {
974
- return recs.slice().sort((a, b) => priorityScore(b) - priorityScore(a));
975
- }
976
-
977
- function priorityScore(rec) {
978
- return typeof rec.priority === "number" ? rec.priority : tierScore(rec.impactTier);
979
- }
980
- function tierScore(t) {
981
- return { high: 100, medium: 50, low: 10 }[t] ?? 0;
982
- }
983
-
984
- function isPlatformScope(rec) {
985
- const k = String(rec.candidateRef ?? "").split(":")[0];
986
- return k.startsWith("platform_") || rec.scope === "account";
987
- }
988
-
989
- function impactString(rec, signals = {}) {
990
- const label = computeImpactLabel(rec, signals);
991
- if (label) return label;
992
- return "_(no impact framing recorded)_";
993
- }
994
-
995
- function signalFromRec(rec) {
996
- return rec.findingRefs?.[0] ?? null;
997
- }
998
-
999
- function formatUsage(s) {
1000
- if (typeof s.usage === "string") return s.usage;
1001
- if (typeof s.usage === "number") return formatNum(s.usage) + (s.unit ? ` ${s.unit}` : "");
1002
- return "(unspecified)";
1003
- }
1004
-
1005
- function formatNum(n) {
1006
- if (!Number.isFinite(n)) return String(n);
1007
- if (n >= 1_000_000) return (n / 1_000_000).toFixed(2) + "M";
1008
- if (n >= 1_000) return (n / 1_000).toFixed(2) + "K";
1009
- return String(n);
1010
- }
1011
-
1012
- function formatBytes(b) {
1013
- if (!Number.isFinite(b)) return "(n/a)";
1014
- if (b >= 1e12) return (b / 1e12).toFixed(2) + " TB";
1015
- if (b >= 1e9) return (b / 1e9).toFixed(2) + " GB";
1016
- if (b >= 1e6) return (b / 1e6).toFixed(2) + " MB";
1017
- if (b >= 1e3) return (b / 1e3).toFixed(2) + " KB";
1018
- return Math.round(b) + " B";
1019
- }
1020
-
1021
- function escape(s) {
1022
- if (typeof s !== "string") return String(s ?? "");
1023
- return s.replace(/\|/g, "\\|").replace(/\n/g, " ");
1024
- }
1025
-
1026
- function asArray(v) {
1027
- return Array.isArray(v) ? v : [];
1028
- }
1029
-
1030
- function enrichRecFromCandidates(rec, candidates) {
1031
- if (!rec || typeof rec !== "object") return rec;
1032
- if (!Array.isArray(candidates) || candidates.length === 0) return rec;
1033
- const ref = rec.candidateRef ?? null;
1034
- // Match on raw OR canonical kind:route so pre-dedup-canonicalization refs still resolve.
1035
- let match = null;
1036
- if (ref) {
1037
- const [kind, route] = String(ref).split(":");
1038
- const canonical = route ? canonicalizeRoute(route) : null;
1039
- match = candidates.find((c) => {
1040
- if (!c || c.kind !== kind) return false;
1041
- const cRoute = c.route ?? c.hostname ?? "<account>";
1042
- return cRoute === route || cRoute === canonical || canonicalizeRoute(cRoute) === canonical;
1043
- });
1044
- }
1045
- const canonicalRef = ref ? canonicalRefOf(ref) : ref;
1046
- const merged = { ...rec, candidateRef: canonicalRef };
1047
- if (match) {
1048
- if (!merged.o11ySignal && match.o11ySignal) merged.o11ySignal = match.o11ySignal;
1049
- if (!merged.displayRoute && match.displayRoute) merged.displayRoute = match.displayRoute;
1050
- if (!merged.aliasRoutes && Array.isArray(match.aliasRoutes) && match.aliasRoutes.length > 0) {
1051
- merged.aliasRoutes = match.aliasRoutes;
1052
- }
1053
- if (!merged.mergedCount && typeof match.mergedCount === "number") {
1054
- merged.mergedCount = match.mergedCount;
1055
- }
1056
- }
1057
- return merged;
1058
- }
1059
-
1060
- function canonicalRefOf(ref) {
1061
- const [kind, ...rest] = String(ref).split(":");
1062
- const route = rest.join(":");
1063
- if (!route) return ref;
1064
- return `${kind}:${canonicalizeRoute(route)}`;
1065
- }
1
+ // Deterministic markdown renderer. Same inputs → byte-identical output (modulo caller-supplied generatedAt).
2
+
3
+ import { createHash } from "node:crypto";
4
+ import { computeCostCoverage, renderCostCoverageMarkdown } from "./cost-coverage.mjs";
5
+ import {
6
+ formatCandidateLabel,
7
+ formatKind,
8
+ formatPublicText,
9
+ formatRoute,
10
+ formatSignal,
11
+ } from "./display-labels.mjs";
12
+ import { gates as registeredGates } from "./gates/index.mjs";
13
+ import { computeImpactLabel } from "./impact-label.mjs";
14
+ import { splitCustomerSafeObservations } from "./observation-safety.mjs";
15
+ import { deriveProjectFacts } from "./project-facts.mjs";
16
+ import { canonicalizeRoute } from "./route-normalize.mjs";
17
+
18
+ const PLATFORM_CAP = 3;
19
+ const GATED_TARGET_PREVIEW = 5;
20
+
21
+ export function renderReport({
22
+ recommendations = [],
23
+ gated = [],
24
+ abstentions = [],
25
+ observations = [],
26
+ signals = {},
27
+ candidates = [],
28
+ opts = {},
29
+ } = {}) {
30
+ const safety = splitCustomerSafeObservations(observations, abstentions, signals);
31
+ observations = safety.observations;
32
+ abstentions = [...abstentions, ...safety.heldBackObservations];
33
+ assertValidObservations(observations);
34
+
35
+ const projectName = opts.projectName ?? signals.project?.name ?? "<project>";
36
+ const stack = signals.stack ?? signals.codebase?.stack ?? {};
37
+ const usage = signals.usage ?? null;
38
+ const plan = signals.plan ?? { plan: "unknown", reason: "(not detected)" };
39
+
40
+ // Sub-agents don't always propagate o11ySignal/aliasRoutes — look them up by candidateRef and canonicalize the displayed ref.
41
+ recommendations = recommendations.map((r) => enrichRecFromCandidates(r, candidates));
42
+ const { needsEvidenceRows, noChangeRows } = splitInvestigationOutcomes(abstentions);
43
+
44
+ const lines = [];
45
+ lines.push(`# Vercel Optimization Report — ${projectName}`);
46
+ lines.push("");
47
+ lines.push(renderMetadataLine(stack, plan, usage, signals));
48
+ const coverageLine = renderCoverageLine(candidates, recommendations, signals, {
49
+ abstentions,
50
+ heldBackCount: opts.heldBackCount,
51
+ noChangeCount: opts.noChangeCount,
52
+ });
53
+ if (coverageLine) lines.push(coverageLine);
54
+ if (opts.generatedAt) {
55
+ lines.push("");
56
+ lines.push(`_Generated ${opts.generatedAt}_`);
57
+ }
58
+ lines.push("");
59
+
60
+ lines.push(...renderCostHeader(signals));
61
+ lines.push("");
62
+ lines.push(...renderCostBreakdown(usage, signals));
63
+ if (usage) {
64
+ const coverage = computeCostCoverage(usage, registeredGates);
65
+ lines.push(...renderCostCoverageMarkdown(coverage));
66
+ }
67
+ lines.push("");
68
+
69
+ const platformRecs = recommendations.filter(isPlatformScope).slice(0, PLATFORM_CAP);
70
+ const codeRecs = recommendations.filter((r) => !isPlatformScope(r));
71
+ const sorted = sortRecs(codeRecs);
72
+ const high = sorted.filter((r) => r.impactTier === "high");
73
+ const medium = sorted.filter((r) => r.impactTier === "medium");
74
+ const low = sorted.filter((r) => r.impactTier === "low" || !r.impactTier);
75
+ lines.push("## Highest-impact recommendations");
76
+ lines.push("");
77
+ if (sorted.length === 0) {
78
+ lines.push("_No recommendations are ready to apply from this run._");
79
+ } else {
80
+ const top = sorted.slice(0, 5);
81
+ top.forEach((rec, i) => {
82
+ const candidate = candidateForDisplay(rec);
83
+ const signal = formatSignal(rec.o11ySignal ?? signalFromRec(rec) ?? "", candidate);
84
+ lines.push(`${i + 1}. **${formatCandidateLabel(candidate)}** — ${signal}`);
85
+ lines.push(` - **What to do**: ${formatRecommendationText(rec.what ?? "")}`);
86
+ lines.push(` - **Impact**: ${formatRecommendationText(impactString(rec, signals))}`);
87
+ if (rec.effort) lines.push(` - **Effort**: ${rec.effort}`);
88
+ const cites = asArray(rec.citations);
89
+ if (cites.length > 0) lines.push(` - **Citations**: ${cites.join(", ")}`);
90
+ });
91
+ }
92
+ lines.push("");
93
+
94
+ lines.push("## Recommendations");
95
+ lines.push("");
96
+ lines.push("### High impact");
97
+ lines.push("");
98
+ lines.push(...renderRecTable(high, signals));
99
+ lines.push("");
100
+ lines.push("### Medium impact");
101
+ lines.push("");
102
+ lines.push(...renderRecTable(medium, signals));
103
+ lines.push("");
104
+ if (low.length > 0) {
105
+ lines.push("### Low impact");
106
+ lines.push("");
107
+ lines.push(...renderRecTable(low, signals));
108
+ lines.push("");
109
+ }
110
+
111
+ lines.push("## Detailed recommendations");
112
+ lines.push("");
113
+ if (sorted.length === 0) {
114
+ lines.push("_No recommendations are ready to apply from this run._");
115
+ } else {
116
+ for (const [i, rec] of sorted.entries()) {
117
+ lines.push(...renderRecDetail(rec, i + 1, { signals }));
118
+ }
119
+ }
120
+ lines.push("");
121
+
122
+ lines.push("## Platform recommendations");
123
+ lines.push("");
124
+ if (platformRecs.length === 0) {
125
+ lines.push("_(none — the gate did not surface any platform-scope recommendations)_");
126
+ } else {
127
+ for (const [i, rec] of platformRecs.entries()) {
128
+ lines.push(...renderRecDetail(rec, i + 1, { compact: true, signals }));
129
+ }
130
+ }
131
+ lines.push("");
132
+
133
+ // Observations carry actionable signal discovered during investigation.
134
+ if (observations.length > 0) {
135
+ lines.push("## Observations from investigation");
136
+ lines.push("");
137
+ lines.push(
138
+ "These are real signals from the audit, but they are not ready-to-apply recommendations.",
139
+ );
140
+ lines.push("");
141
+ lines.push("| Candidate | Observation | Evidence | Suggested action | Kind |");
142
+ lines.push("|---|---|---|---|---|");
143
+ for (const o of observations) {
144
+ const ref = o.candidateRef ?? "(unspecified)";
145
+ lines.push(
146
+ `| ${escape(displayCandidateRef(ref))} | ${escape(formatEvidenceText(o.summary))} | ${escape(formatEvidenceText(o.evidence ?? "_(none recorded)_"))} | ${escape(formatEvidenceText(o.suggestedAction ?? "_(none recorded)_"))} | ${escape(formatKind(o.kind ?? "other"))} |`,
147
+ );
148
+ }
149
+ lines.push("");
150
+ }
151
+
152
+ // Trust mechanism: customer sees what was investigated and why no rec emerged.
153
+ if (needsEvidenceRows.length > 0) {
154
+ lines.push("## Needs more evidence");
155
+ lines.push("");
156
+ lines.push(
157
+ "These candidates were investigated, but automated checks kept the change out of the ready-to-apply list.",
158
+ );
159
+ lines.push("");
160
+ lines.push("| Candidate | Why it was held back |");
161
+ lines.push("|---|---|");
162
+ for (const a of needsEvidenceRows) {
163
+ const ref = a.candidateRef ?? "(unspecified)";
164
+ const reason = publicNoRecommendationReason(a.reason ?? "(no reason recorded)");
165
+ lines.push(`| ${escape(displayCandidateRef(ref))} | ${escape(reason)} |`);
166
+ }
167
+ lines.push("");
168
+ }
169
+
170
+ if (noChangeRows.length > 0) {
171
+ lines.push("## Investigated, no change recommended");
172
+ lines.push("");
173
+ lines.push("These candidates were checked and did not produce a supported change.");
174
+ lines.push("");
175
+ lines.push("| Candidate | Why no recommendation shipped |");
176
+ lines.push("|---|---|");
177
+ for (const a of noChangeRows) {
178
+ const ref = a.candidateRef ?? "(unspecified)";
179
+ const reason = publicNoRecommendationReason(a.reason ?? "(no reason recorded)");
180
+ lines.push(`| ${escape(displayCandidateRef(ref))} | ${escape(reason)} |`);
181
+ }
182
+ lines.push("");
183
+ }
184
+
185
+ lines.push("## Not investigated in this run");
186
+ lines.push("");
187
+ lines.push(...renderGatedTable(gated));
188
+ lines.push("");
189
+
190
+ lines.push("## Strengths");
191
+ lines.push("");
192
+ lines.push(...renderStrengths(signals));
193
+ lines.push("");
194
+
195
+ const configNotes = renderConfigurationNotes(signals);
196
+ if (configNotes.length > 0) {
197
+ lines.push("## Configuration notes");
198
+ lines.push("");
199
+ lines.push(...configNotes);
200
+ lines.push("");
201
+ }
202
+
203
+ lines.push("## Data gaps");
204
+ lines.push("");
205
+ lines.push(...renderDataGaps(signals));
206
+
207
+ return lines.join("\n");
208
+ }
209
+
210
+ function assertValidObservations(observations) {
211
+ if (!Array.isArray(observations)) {
212
+ throw new TypeError("renderReport observations must be an array");
213
+ }
214
+ for (const [i, o] of observations.entries()) {
215
+ if (!o || typeof o !== "object") {
216
+ throw new TypeError(`renderReport observations[${i}] must be an object`);
217
+ }
218
+ if (typeof o.summary !== "string" || o.summary.trim() === "") {
219
+ throw new TypeError(`renderReport observations[${i}].summary is required`);
220
+ }
221
+ }
222
+ }
223
+
224
+ export function buildFinalReportMessage({
225
+ reportPath,
226
+ markdown,
227
+ recommendations = [],
228
+ signals = {},
229
+ maxRecommendations = 10,
230
+ } = {}) {
231
+ const destination = reportPath || "report.md";
232
+ const coverageLine = extractCoverageLine(markdown);
233
+ const lines = [`Report saved: ${destination}`];
234
+ if (coverageLine) {
235
+ lines.push("");
236
+ lines.push(stripDetailsLink(coverageLine));
237
+ } else {
238
+ lines.push("");
239
+ lines.push("Open the report for details. No coverage summary was available.");
240
+ }
241
+ const readyPreview = renderFinalRecommendationPreview(
242
+ recommendations,
243
+ signals,
244
+ maxRecommendations,
245
+ );
246
+ if (readyPreview.length > 0) {
247
+ lines.push("");
248
+ lines.push(...readyPreview);
249
+ }
250
+ const body = lines.join("\n");
251
+ return {
252
+ body,
253
+ lineCount: lines.length,
254
+ sha256: createHash("sha256").update(body).digest("hex"),
255
+ reportPath: destination,
256
+ coverageLine: coverageLine ?? null,
257
+ recommendationsShown: readyPreview.filter((line) => /^\d+\./.test(line)).length,
258
+ };
259
+ }
260
+
261
+ function renderFinalRecommendationPreview(recommendations, signals, maxRecommendations) {
262
+ const ready = Array.isArray(recommendations)
263
+ ? sortRecs(recommendations.filter((r) => r && r.abstain !== true))
264
+ : [];
265
+ if (ready.length === 0) return [];
266
+ const max = Math.max(
267
+ 1,
268
+ Math.min(Number.isInteger(maxRecommendations) ? maxRecommendations : 5, 10),
269
+ );
270
+ const shown = ready.slice(0, max);
271
+ const lines = ["Ready recommendations:"];
272
+ for (const [i, rec] of shown.entries()) {
273
+ lines.push(`${i + 1}. ${compactFinalText(rec.what ?? displayCandidate(rec))}`);
274
+ const impact = impactString(rec, signals);
275
+ if (impact && !/^_\(no impact framing recorded\)_$/.test(impact)) {
276
+ lines.push(` Impact: ${compactFinalText(impact)}`);
277
+ }
278
+ }
279
+ const hidden = ready.length - shown.length;
280
+ if (hidden > 0) {
281
+ lines.push(
282
+ `Open the report for ${hidden} more ready recommendation${hidden === 1 ? "" : "s"} and the full evidence.`,
283
+ );
284
+ }
285
+ return lines;
286
+ }
287
+
288
+ function compactFinalText(value) {
289
+ const text = formatRecommendationText(String(value ?? ""))
290
+ .replace(/\s+/g, " ")
291
+ .trim();
292
+ if (text.length <= 220) return text;
293
+ return `${text.slice(0, 217).trimEnd()}...`;
294
+ }
295
+
296
+ function extractCoverageLine(markdown) {
297
+ if (typeof markdown !== "string") return null;
298
+ return markdown.split("\n").find((line) => line.startsWith("**Coverage**:")) ?? null;
299
+ }
300
+
301
+ function stripDetailsLink(line) {
302
+ return String(line).replace(/\s*·\s*\[details\]\(#not-investigated-in-this-run\)\s*$/, "");
303
+ }
304
+
305
+ // Hidden when no candidates exist (e.g., observability blocker — nothing to cover).
306
+ function renderCoverageLine(candidates, recommendations, signals, opts = {}) {
307
+ if (!Array.isArray(candidates) || candidates.length === 0) return null;
308
+ const launched = candidates.filter(
309
+ (c) => !c.gatedReason && !c.disqualified && c.scope !== "account",
310
+ );
311
+ const skippedByBudget = candidates.filter(
312
+ (c) => typeof c.gatedReason === "string" && c.gatedReason.startsWith("skippedByBudget"),
313
+ );
314
+ const coveredByDedup = candidates.filter(
315
+ (c) => typeof c.gatedReason === "string" && c.gatedReason.startsWith("coveredBy"),
316
+ );
317
+ const disqualified = candidates.filter(
318
+ (c) => typeof c.gatedReason === "string" && c.gatedReason === c.disqualifyReason,
319
+ );
320
+ const total = launched.length + skippedByBudget.length;
321
+ if (total === 0) return null;
322
+ const parts = [];
323
+ parts.push(`Found **${total}** potential issue${total === 1 ? "" : "s"} to check`);
324
+ parts.push(`${launched.length} investigated`);
325
+ if (skippedByBudget.length > 0) {
326
+ parts.push(
327
+ `${skippedByBudget.length} left for a larger run — re-run with \`--max-candidates all\` to see the rest`,
328
+ );
329
+ }
330
+ if (coveredByDedup.length > 0) {
331
+ parts.push(
332
+ `${coveredByDedup.length} similar route variant${coveredByDedup.length === 1 ? "" : "s"} grouped`,
333
+ );
334
+ }
335
+ const recCount = (recommendations ?? []).filter((r) => !r.abstain && !isPlatformScope(r)).length;
336
+ parts.push(`${recCount} recommendation${recCount === 1 ? "" : "s"} ready`);
337
+ const rawHeldBackCount = Number.isInteger(opts.heldBackCount)
338
+ ? opts.heldBackCount
339
+ : Array.isArray(opts.abstentions)
340
+ ? opts.abstentions.filter((a) => a?.needsEvidence === true).length
341
+ : 0;
342
+ const heldBackCount = Math.min(rawHeldBackCount, Math.max(0, launched.length - recCount));
343
+ if (heldBackCount > 0) {
344
+ parts.push(`${heldBackCount} need more evidence`);
345
+ }
346
+ const rawNoChangeCount = Number.isInteger(opts.noChangeCount)
347
+ ? opts.noChangeCount
348
+ : Array.isArray(opts.abstentions)
349
+ ? opts.abstentions.length
350
+ : 0;
351
+ const noChangeCount = Math.min(
352
+ rawNoChangeCount,
353
+ Math.max(0, launched.length - recCount - heldBackCount),
354
+ );
355
+ if (noChangeCount > 0) {
356
+ parts.push(`${noChangeCount} investigated, no change recommended`);
357
+ }
358
+ return `**Coverage**: ${parts.join(" · ")} · [details](#not-investigated-in-this-run)`;
359
+ }
360
+
361
+ function renderMetadataLine(stack, plan, usage, signals = {}) {
362
+ const fw = `${stack.framework ?? "unknown"}@${stack.frameworkVersion ?? "?"}`;
363
+ const router = stack.hasAppRouter ? "app-router" : stack.hasPagesRouter ? "pages-router" : null;
364
+ const orm = stack.orm && stack.orm !== "none" ? stack.orm : null;
365
+ const stackParts = [fw, router, orm].filter(Boolean).join(" | ");
366
+ const period = usage?.period
367
+ ? `${usage.period.from ?? "?"} → ${usage.period.to ?? "?"}`
368
+ : "(unavailable)";
369
+ const oplusLabel = observabilityLabel(signals, usage);
370
+ // Plan-inference reason is debug detail — only surface when plan is uncertain.
371
+ const planLabel =
372
+ plan.plan === "uncertain"
373
+ ? `${plan.plan} (${plan.reason ?? "no signal"})`
374
+ : (plan.plan ?? "unknown");
375
+ return `**Stack**: ${stackParts} · **Plan**: ${planLabel} · **Period**: ${period} · **Observability**: ${oplusLabel}`;
376
+ }
377
+
378
+ function observabilityLabel(signals, usage) {
379
+ if (signals.observabilityPlusUsable === true) {
380
+ return "Observability Plus enabled — per-route metrics included";
381
+ }
382
+ if (signals.observabilityPlusUsable === false) {
383
+ if (usage) {
384
+ return "Per-route metrics unavailable — analysis based on billing + scanner findings";
385
+ }
386
+ if (signals.usageError === "NOT_COLLECTED_OBSERVABILITY_BLOCKED") {
387
+ return "Per-route metrics unavailable — audit paused before metric-backed route ranking";
388
+ }
389
+ return "Per-route metrics unavailable — limited analysis based on scanner findings";
390
+ }
391
+ if (signals.observabilityPlus === true) {
392
+ return "Observability Plus enabled — per-route metrics included";
393
+ }
394
+ if (signals.usageError === "NOT_COLLECTED_UNSUPPORTED_FRAMEWORK") {
395
+ return "Not checked — audit paused at unsupported-framework preflight";
396
+ }
397
+ if (signals.usageError === "NOT_COLLECTED_OBSERVABILITY_BLOCKED") {
398
+ return "Per-route metrics unavailable — audit paused before metric-backed route ranking";
399
+ }
400
+ if (usage) {
401
+ return "Not enabled — analysis based on billing + scanner findings";
402
+ }
403
+ if (signals.observabilityPlus === false) {
404
+ return "Not enabled — limited analysis only";
405
+ }
406
+ return "Not checked — limited analysis only";
407
+ }
408
+
409
+ function renderCostHeader(signals) {
410
+ const scope = signals.usageScope;
411
+ if (scope === "project") {
412
+ return ["## Cost breakdown (this project)"];
413
+ }
414
+ if (scope === "team" && signals.usage) {
415
+ return [
416
+ "## Cost breakdown (team-wide — `vercel usage` has no per-project filter)",
417
+ "",
418
+ "_The Vercel CLI's `vercel usage` reports team-wide billing without a project filter (verified May 2026). This breakdown is the whole team's bill for the window. Per-route metrics in the rest of this report are project-scoped via `vercel metrics`._",
419
+ ];
420
+ }
421
+ return ["## Cost breakdown"];
422
+ }
423
+
424
+ function renderCostBreakdown(usage, signals) {
425
+ const lines = [];
426
+ const services = Array.isArray(usage?.services) ? usage.services : null;
427
+ if (services && services.length > 0) {
428
+ const chargedRows = services.filter((s) => {
429
+ const cost = serviceCost(s);
430
+ return cost === null || costRoundsToCents(cost) > 0;
431
+ });
432
+ if (chargedRows.length > 0) {
433
+ return renderServiceCostRows(chargedRows, {
434
+ costLabel: "Billed cost",
435
+ costOf: serviceCost,
436
+ omittedZeroRows: services.length - chargedRows.length,
437
+ total: usage.totals?.billedCost,
438
+ totalLabel: "Total billed",
439
+ totalSuffix:
440
+ " _(precise observed cost; future-savings framing is magnitude, never precise)_",
441
+ });
442
+ }
443
+
444
+ const effectiveRows = services.filter((s) => costRoundsToCents(serviceEffectiveCost(s)) > 0);
445
+ if (effectiveRows.length > 0) {
446
+ lines.push(
447
+ "_Net billed cost is $0.00 after included credits or allotments. Showing effective usage cost so active cost drivers are still visible._",
448
+ );
449
+ lines.push("");
450
+ return [
451
+ ...lines,
452
+ ...renderServiceCostRows(effectiveRows, {
453
+ costLabel: "Effective cost",
454
+ costOf: serviceEffectiveCost,
455
+ omittedZeroRows: services.length - effectiveRows.length,
456
+ total: usage.totals?.effectiveCost,
457
+ totalLabel: "Total effective cost",
458
+ totalSuffix: " _(usage cost before included-credit or allotment offsets)_",
459
+ }),
460
+ ];
461
+ }
462
+
463
+ if (chargedRows.length === 0) {
464
+ const scope = signals.usageScope === "team" ? "team-wide " : "";
465
+ lines.push(
466
+ `_\`vercel usage\` returned a ${scope}billing payload, but every reported service cost was $0.00 for this window._`,
467
+ );
468
+ return lines;
469
+ }
470
+ }
471
+
472
+ // Fallback to o11y-derived ranking when usage payload missing.
473
+ const gbHr = signals.metrics?.fnGbHrByRoute?.rows ?? [];
474
+ const usageGap = missingUsageSentence(signals);
475
+ if (gbHr.length === 0) {
476
+ lines.push(
477
+ `_${usageGap} Without per-route function GB-hour data, this report cannot rank cost drivers._`,
478
+ );
479
+ return lines;
480
+ }
481
+ const top = groupGbHoursByCanonicalRoute(gbHr)
482
+ .sort((a, b) => (b.value ?? 0) - (a.value ?? 0))
483
+ .slice(0, 10);
484
+ lines.push(
485
+ `_${usageGap} Ranking by \`function_duration_gbhr\` instead. These do not translate to dollars directly, but they show which routes consume billable units._`,
486
+ );
487
+ lines.push("");
488
+ lines.push("| Route | GB-hr (sum, 14d) |");
489
+ lines.push("|---|---|");
490
+ for (const r of top) {
491
+ lines.push(`| ${escape(r.route ?? "(unnamed)")} | ${(r.value ?? 0).toFixed(4)} |`);
492
+ }
493
+ return lines;
494
+ }
495
+
496
+ function renderServiceCostRows(
497
+ services,
498
+ { costLabel, costOf, omittedZeroRows = 0, total = null, totalLabel, totalSuffix = "" },
499
+ ) {
500
+ const lines = [];
501
+ const rows = services.slice().sort((a, b) => (costOf(b) ?? 0) - (costOf(a) ?? 0));
502
+ // Drop Usage column when every cell is "(unspecified)" — happens when CLI emits pricingUnit=USD.
503
+ const usageCells = rows.map((s) => formatUsage(s));
504
+ const hasRealUsage = usageCells.some((c) => c !== "(unspecified)");
505
+ if (hasRealUsage) {
506
+ lines.push(`| Service | Usage | ${costLabel} |`);
507
+ lines.push("|---|---|---|");
508
+ for (let i = 0; i < rows.length; i++) {
509
+ const s = rows[i];
510
+ const costValue = costOf(s);
511
+ const cost = typeof costValue === "number" ? `$${costValue.toFixed(2)}` : "(n/a)";
512
+ lines.push(`| ${escape(s.name ?? "(unnamed)")} | ${escape(usageCells[i])} | ${cost} |`);
513
+ }
514
+ } else {
515
+ lines.push(`| Service | ${costLabel} |`);
516
+ lines.push("|---|---|");
517
+ for (const s of rows) {
518
+ const costValue = costOf(s);
519
+ const cost = typeof costValue === "number" ? `$${costValue.toFixed(2)}` : "(n/a)";
520
+ lines.push(`| ${escape(s.name ?? "(unnamed)")} | ${cost} |`);
521
+ }
522
+ }
523
+ if (omittedZeroRows > 0) {
524
+ lines.push("");
525
+ lines.push(
526
+ `_${omittedZeroRows} zero-cost service ${omittedZeroRows === 1 ? "row was" : "rows were"} omitted._`,
527
+ );
528
+ }
529
+ if (typeof total === "number") {
530
+ lines.push("");
531
+ lines.push(`**${totalLabel}: $${total.toFixed(2)}**${totalSuffix}`);
532
+ }
533
+ return lines;
534
+ }
535
+
536
+ function serviceCost(service) {
537
+ if (typeof service?.billedCost === "number") return service.billedCost;
538
+ if (typeof service?.cost === "number") return service.cost;
539
+ return null;
540
+ }
541
+
542
+ function serviceEffectiveCost(service) {
543
+ if (typeof service?.effectiveCost === "number") return service.effectiveCost;
544
+ if (typeof service?.pricingQuantity === "number" && service?.pricingUnit === "USD")
545
+ return service.pricingQuantity;
546
+ return 0;
547
+ }
548
+
549
+ function costRoundsToCents(cost) {
550
+ if (typeof cost !== "number" || !Number.isFinite(cost)) return 0;
551
+ return Math.round(cost * 100) / 100;
552
+ }
553
+
554
+ function renderRecTable(recs, signals = {}) {
555
+ if (recs.length === 0) return ["_(none)_"];
556
+ const lines = [];
557
+ lines.push("| # | Bucket | What | Impact | Effort | Citations |");
558
+ lines.push("|---|---|---|---|---|---|");
559
+ recs.forEach((r, i) => {
560
+ const cites = asArray(r.citations).slice(0, 2).join("<br>");
561
+ lines.push(
562
+ `| ${i + 1} | ${r.bucket ?? "?"} | ${escape(formatRecommendationText(r.what ?? ""))} | ${escape(formatRecommendationText(impactString(r, signals)))} | ${r.effort ?? "?"} | ${cites} |`,
563
+ );
564
+ });
565
+ return lines;
566
+ }
567
+
568
+ function renderRecDetail(rec, index, { compact = false, signals = {} } = {}) {
569
+ const lines = [];
570
+ lines.push(`### ${index}. ${formatRecommendationText(rec.what ?? "(no `what`)")}`);
571
+ lines.push("");
572
+ const meta = [
573
+ rec.bucket ? `**${rec.bucket}**` : null,
574
+ rec.effort ? `effort: ${rec.effort}` : null,
575
+ rec.impactTier ? `impact tier: ${rec.impactTier}` : null,
576
+ rec.candidateRef ? `candidate: ${displayCandidate(rec)}` : null,
577
+ rec.corroborationCount > 1 ? `corroborated: ${rec.corroborationCount}` : null,
578
+ ].filter(Boolean);
579
+ if (meta.length > 0) lines.push(`_${meta.join(" · ")}_`);
580
+ lines.push("");
581
+ const appliesAlsoTo = asArray(rec.appliesAlsoTo);
582
+ if (appliesAlsoTo.length > 0) {
583
+ const refs = appliesAlsoTo
584
+ .map((a) => a?.candidateRef)
585
+ .filter(Boolean)
586
+ .slice(0, 4);
587
+ if (refs.length > 0) {
588
+ const suffix =
589
+ appliesAlsoTo.length > refs.length ? `, +${appliesAlsoTo.length - refs.length} more` : "";
590
+ lines.push(`_Also applies to: ${refs.map(displayCandidateRef).join(", ")}${suffix}._`);
591
+ lines.push("");
592
+ }
593
+ }
594
+ if (rec.why) {
595
+ lines.push("**Why**");
596
+ lines.push("");
597
+ lines.push(formatRecommendationText(rec.why));
598
+ lines.push("");
599
+ }
600
+ lines.push("**Impact**");
601
+ lines.push("");
602
+ lines.push(formatRecommendationText(impactString(rec, signals)));
603
+ lines.push("");
604
+ if (!compact && rec.fix) {
605
+ lines.push("**Fix**");
606
+ lines.push("");
607
+ lines.push(rec.fix);
608
+ lines.push("");
609
+ }
610
+ if (!compact && rec.currentBehavior) {
611
+ lines.push("**Before**");
612
+ lines.push("");
613
+ lines.push(rec.currentBehavior);
614
+ lines.push("");
615
+ }
616
+ if (!compact && rec.desiredBehavior) {
617
+ lines.push("**After**");
618
+ lines.push("");
619
+ lines.push(rec.desiredBehavior);
620
+ lines.push("");
621
+ }
622
+ if (rec.verify) {
623
+ lines.push("**Verify**");
624
+ lines.push("");
625
+ lines.push(formatRecommendationText(rec.verify));
626
+ lines.push("");
627
+ }
628
+ const cites = asArray(rec.citations);
629
+ if (cites.length > 0) {
630
+ lines.push("**Citations**");
631
+ lines.push("");
632
+ for (const c of cites) lines.push(`- \`${c}\``);
633
+ lines.push("");
634
+ }
635
+ lines.push("");
636
+ return lines;
637
+ }
638
+
639
+ function renderGatedTable(gated) {
640
+ if (!Array.isArray(gated) || gated.length === 0) {
641
+ return ["_(no candidates were held back)_"];
642
+ }
643
+ const groups = groupGatedCandidates(gated);
644
+ const lines = [];
645
+ lines.push("| Candidate type | Why not investigated | Targets | Count |");
646
+ lines.push("|---|---|---|---:|");
647
+ for (const group of groups) {
648
+ lines.push(
649
+ `| ${escape(group.kind)} | ${escape(group.reason)} | ${formatGatedTargets(group.targets, group.count)} | ${group.count} |`,
650
+ );
651
+ }
652
+ return lines;
653
+ }
654
+
655
+ function formatGatedTargets(targets, count) {
656
+ const unique = [...new Set(targets.map((t) => String(t)))];
657
+ const shown = unique.slice(0, GATED_TARGET_PREVIEW).map((target) => escape(target));
658
+ const hidden = Math.max(0, count - shown.length);
659
+ if (hidden > 0) shown.push(`+${hidden} more`);
660
+ return shown.join("<br>");
661
+ }
662
+
663
+ function groupGatedCandidates(gated) {
664
+ const byKey = new Map();
665
+ for (const g of gated) {
666
+ const kind = formatKind(g.kind ?? "?");
667
+ const reason = publicGatedReason(g.gatedReason ?? g.disqualifyReason ?? "(no reason recorded)");
668
+ const target = formatRoute(g);
669
+ const key = `${kind}\u0000${reason}`;
670
+ const existing = byKey.get(key);
671
+ if (existing) {
672
+ existing.count += 1;
673
+ existing.targets.push(String(target));
674
+ } else {
675
+ byKey.set(key, {
676
+ kind: String(kind),
677
+ reason: String(reason),
678
+ targets: [String(target)],
679
+ count: 1,
680
+ });
681
+ }
682
+ }
683
+ return Array.from(byKey.values());
684
+ }
685
+
686
+ function publicNoRecommendationReason(reason) {
687
+ return formatEvidenceText(String(reason))
688
+ .replace(/\bDropped at render:\s*/gi, "")
689
+ .replace(
690
+ /\bverifier flagged for regen, but no regen happened\b/gi,
691
+ "needs stronger evidence before it is safe to apply",
692
+ )
693
+ .replace(
694
+ /\bRe-run with a refreshed brief\.?/gi,
695
+ "Re-run the investigation after refreshing the evidence.",
696
+ )
697
+ .replace(/\bregen\b/gi, "re-check")
698
+ .replace(/\bverifier\b/gi, "verification")
699
+ .replace(/\brec\b/gi, "recommendation")
700
+ .replace(/\bsub[- ]agent\b/gi, "investigation")
701
+ .replace(/\babstentions?\b/gi, "no-change findings")
702
+ .replace(/\babstaining\b/gi, "not recommending a change")
703
+ .replace(/\babstain(?:ed)?\b/gi, "found no supported change")
704
+ .replace(/\bquality\s*\+\s*verification\b/gi, "verification")
705
+ .replace(/\bquality\b/gi, "review")
706
+ .replace(/\bsanitizers?\b/gi, "checks");
707
+ }
708
+
709
+ function splitInvestigationOutcomes(abstentions) {
710
+ const rows = Array.isArray(abstentions) ? abstentions : [];
711
+ return {
712
+ needsEvidenceRows: rows.filter((a) => a?.needsEvidence === true),
713
+ noChangeRows: rows.filter((a) => a?.needsEvidence !== true),
714
+ };
715
+ }
716
+
717
+ function publicGatedReason(reason) {
718
+ return formatPublicText(String(reason))
719
+ .replace(/\bhardGated:\s*/gi, "")
720
+ .replace(
721
+ /skippedByBudget\s*\(max-candidates=([^);]+)(?:;[^)]*)?\)/i,
722
+ "left for a larger run (max candidates: $1)",
723
+ )
724
+ .replace(/skippedByBudget\b/gi, "left for a larger run")
725
+ .replace(/\s*;\s*raise with --max-candidates N or =all/gi, "")
726
+ .replace(/=all/g, "all")
727
+ .replace(/\bcoveredBy\b/gi, "covered by a higher-priority candidate")
728
+ .replace(/\bdisqualified\b/gi, "not eligible");
729
+ }
730
+
731
+ function formatEvidenceText(value) {
732
+ const expanded = formatPublicText(value)
733
+ .replace(/\bdeepDive\b/gi, "follow-up metric")
734
+ .replace(/\bdeep-dive\b/gi, "follow-up metric")
735
+ .replace(/\blatency p95\b/gi, "95th percentile latency")
736
+ .replace(/\bttfb p95\b/gi, "95th percentile TTFB")
737
+ .replace(/\bcpu p95\b/gi, "95th percentile CPU time")
738
+ .replace(/\bp95\b/gi, "95th percentile")
739
+ .replace(/\bgate signal\b/gi, "broad metric signal")
740
+ .replace(/\bo11ySignal\b/gi, "observed signal")
741
+ .replace(/\bperDeployment\b/gi, "per-deployment")
742
+ .replace(/\bstartTypeSplit\b/gi, "start-type breakdown")
743
+ .replace(/\bstatusDistribution\b/gi, "status distribution")
744
+ .replace(/\bcacheBreakdown\b/gi, "cache breakdown")
745
+ .replace(/\bfunctionRoutes\b/gi, "function routes")
746
+ .replace(/\bfnGbHrByRoute\b/gi, "function duration by route");
747
+ return formatPublicText(expanded);
748
+ }
749
+
750
+ function formatRecommendationText(value) {
751
+ return formatEvidenceText(value)
752
+ .replace(/\bthe gate fires\b/gi, "this audit flags the signal")
753
+ .replace(/\bships immediately\b/gi, "can ship sooner");
754
+ }
755
+
756
+ function displayCandidate(value) {
757
+ return formatCandidateLabel(candidateForDisplay(value));
758
+ }
759
+
760
+ function candidateForDisplay(value) {
761
+ const parsed = parseCandidateRef(value?.candidateRef);
762
+ return parsed ? displayCandidateObject(value, parsed) : value;
763
+ }
764
+
765
+ function displayCandidateRef(ref) {
766
+ const parsed = parseCandidateRef(ref);
767
+ if (!parsed) return String(ref ?? "(unspecified)");
768
+ return formatCandidateLabel(displayCandidateObject({}, parsed));
769
+ }
770
+
771
+ function parseCandidateRef(ref) {
772
+ if (typeof ref !== "string") return null;
773
+ const [kind, ...rest] = ref.split(":");
774
+ const target = rest.join(":");
775
+ if (!kind || !target) return null;
776
+ return { kind, target };
777
+ }
778
+
779
+ function displayCandidateObject(base, parsed) {
780
+ if (parsed.target.startsWith("<account>#")) {
781
+ return { ...base, kind: parsed.kind, files: [parsed.target.slice("<account>#".length)] };
782
+ }
783
+ if (parsed.target === "<account>") {
784
+ return { ...base, kind: parsed.kind };
785
+ }
786
+ return { ...base, kind: parsed.kind, route: parsed.target };
787
+ }
788
+
789
+ function groupGbHoursByCanonicalRoute(rows) {
790
+ const byRoute = new Map();
791
+ for (const row of rows) {
792
+ const route = row?.route ? canonicalizeRoute(row.route) : "(unnamed)";
793
+ byRoute.set(route, (byRoute.get(route) ?? 0) + (row?.value ?? 0));
794
+ }
795
+ return [...byRoute.entries()].map(([route, value]) => ({ route, value }));
796
+ }
797
+
798
+ function renderStrengths(signals) {
799
+ const lines = [];
800
+
801
+ // Stops agent from emitting "verify Fluid is on" recs. Source: defaultResourceConfig from project API.
802
+ const projectFacts = deriveProjectFacts(signals);
803
+ for (const f of projectFacts) {
804
+ if (String(f.id ?? "").startsWith("memory_")) continue;
805
+ lines.push(`- ${f.strength}`);
806
+ }
807
+
808
+ const cache = signals.metrics?.fdtByCache?.rows ?? [];
809
+ const hit = cache.find((r) => r.cache_result === "HIT" || r.cache_result === "STALE");
810
+ const miss = cache.find((r) => r.cache_result === "MISS" || r.cache_result === "BYPASS");
811
+ if (hit && miss && (hit.value ?? 0) > (miss.value ?? 0)) {
812
+ lines.push(
813
+ `- Cache hit-rate is healthy at the bandwidth tier — HIT/STALE bandwidth (${formatBytes(hit.value)}) exceeds MISS/BYPASS (${formatBytes(miss.value)}).`,
814
+ );
815
+ }
816
+ const cold = signals.metrics?.fnStartTypeByRoute?.rows ?? [];
817
+ const totalInv = cold.reduce((s, r) => s + (r.total ?? 0), 0);
818
+ const totalCold = cold.reduce((s, r) => s + (r.coldCount ?? 0), 0);
819
+ if (totalInv > 1000) {
820
+ const coldPct = totalCold / totalInv;
821
+ if (coldPct < 0.02)
822
+ lines.push(
823
+ `- Cold-start rate is very low (${(coldPct * 100).toFixed(2)}%) — Fluid Compute or warm-instance reuse is doing its job.`,
824
+ );
825
+ }
826
+ const errors = signals.metrics?.requestsByRouteStatus?.rows ?? [];
827
+ const total5xx = errors
828
+ .filter((r) => /^5/.test(r.http_status ?? ""))
829
+ .reduce((s, r) => s + (r.value ?? 0), 0);
830
+ const totalReq = errors.reduce((s, r) => s + (r.value ?? 0), 0);
831
+ if (totalReq > 1000) {
832
+ const rate = total5xx / totalReq;
833
+ if (rate < 0.001)
834
+ lines.push(
835
+ `- 5xx rate is very low (${(rate * 100).toFixed(3)}%) on ${formatNum(totalReq)} requests.`,
836
+ );
837
+ }
838
+ if (lines.length === 0)
839
+ lines.push(
840
+ "_(no headline strengths to call out — see the gated table for signals we considered)_",
841
+ );
842
+ return lines;
843
+ }
844
+
845
+ function renderConfigurationNotes(signals) {
846
+ const projectFacts = deriveProjectFacts(signals);
847
+ return projectFacts
848
+ .filter((f) => String(f.id ?? "").startsWith("memory_"))
849
+ .map((f) => `- ${f.strength}`);
850
+ }
851
+
852
+ function renderDataGaps(signals) {
853
+ const lines = [];
854
+ const observabilityGap = observabilityDataGap(signals);
855
+ if (observabilityGap) lines.push(observabilityGap);
856
+ if (!signals.usage) lines.push(`- ${missingUsageSentence(signals)}`);
857
+ const cwvMetric = metricState(signals, "cwvCount");
858
+ if (cwvMetric.failed) {
859
+ lines.push(
860
+ `- Speed Insights metrics were not usable (\`${cwvMetric.code}\`), so LCP/INP/CLS analysis was skipped.`,
861
+ );
862
+ } else if (cwvMetric.collected) {
863
+ const cwv = cwvMetric.rows?.[0]?.value ?? 0;
864
+ if (cwv === 0)
865
+ lines.push(
866
+ "- No Speed Insights measurements — Core Web Vitals analysis dormant. Wire up Speed Insights to enable LCP/INP/CLS recommendations.",
867
+ );
868
+ }
869
+ const isrMetric = metricState(signals, "isrReadsByRoute");
870
+ if (isrMetric.collected) {
871
+ const isrR = isrMetric.rows ?? [];
872
+ if (isrR.length === 0)
873
+ lines.push(
874
+ "- No ISR activity observed — either the project does not use ISR or no eligible routes had traffic in the window.",
875
+ );
876
+ }
877
+ const imageMetric = metricState(signals, "imageCount");
878
+ if (imageMetric.collected) {
879
+ const images = imageMetric.rows?.[0]?.value ?? 0;
880
+ if (images === 0)
881
+ lines.push(
882
+ "- No image transformations observed — either `next/image` is not used or no images served in the window.",
883
+ );
884
+ }
885
+ const middlewareMetric = metricState(signals, "middlewareCount");
886
+ if (middlewareMetric.collected) {
887
+ const middleware = middlewareMetric.rows ?? [];
888
+ if (middleware.length === 0)
889
+ lines.push(
890
+ "- No middleware invocations — either no `middleware.ts` is shipped or its matcher excludes all observed traffic.",
891
+ );
892
+ }
893
+ if (lines.length === 0) lines.push("_(no relevant gaps — every signal had data)_");
894
+ return lines;
895
+ }
896
+
897
+ function observabilityDataGap(signals = {}) {
898
+ if (signals.usageError === "NOT_COLLECTED_UNSUPPORTED_FRAMEWORK") {
899
+ return "- Observability Plus was not checked because the audit paused at the unsupported-framework preflight.";
900
+ }
901
+ if (signals.observabilityPlusUsable === false) {
902
+ const blocker = signals.observabilityPlusBlocker;
903
+ if (blocker === "project_disabled") {
904
+ return "- Per-route metrics unavailable — Observability Plus is disabled for this project.";
905
+ }
906
+ if (blocker === "forbidden" || blocker === "project_not_found") {
907
+ return "- Per-route metrics unavailable — the authenticated Vercel scope cannot read this project.";
908
+ }
909
+ if (blocker === "not_linked") {
910
+ return "- Per-route metrics unavailable — the app directory is not linked to the Vercel project.";
911
+ }
912
+ if (blocker === "no_oplus_probe") {
913
+ return "- Per-route metrics unavailable — Observability Plus was not detected for this scope.";
914
+ }
915
+ if (blocker === "payment_required") {
916
+ return "- Per-route metrics unavailable — Observability Plus metrics were not usable for this scope.";
917
+ }
918
+ if (blocker === "daily_quota_exceeded") {
919
+ return "- Per-route metrics unavailable — the Observability Plus query quota is exhausted for today.";
920
+ }
921
+ if (blocker === "no_traffic") {
922
+ return "- Per-route metrics sparse — no route-level traffic was returned in the metrics window.";
923
+ }
924
+ if (blocker === "all_failed_other") {
925
+ return "- Per-route metrics unavailable — all Observability Plus metric queries failed.";
926
+ }
927
+ if (blocker) {
928
+ return `- Per-route metrics unavailable — Observability Plus metrics returned \`${blocker}\`.`;
929
+ }
930
+ return "- Per-route metrics unavailable — Observability Plus data was not usable for this run.";
931
+ }
932
+ if (signals.observabilityPlus === false) {
933
+ return "- Observability Plus not enabled — per-route latency / cache-hit / cold-start metrics unavailable.";
934
+ }
935
+ return null;
936
+ }
937
+
938
+ function missingUsageSentence(signals = {}) {
939
+ const code = signals.usageError;
940
+ if (code === "NOT_COLLECTED_OBSERVABILITY_BLOCKED") {
941
+ return "`vercel usage` was not collected because the audit paused before billing collection on the Observability Plus blocker.";
942
+ }
943
+ if (code === "NOT_COLLECTED_UNSUPPORTED_FRAMEWORK") {
944
+ return "`vercel usage` was not collected because the audit paused at the unsupported-framework preflight.";
945
+ }
946
+ if (code === "USAGE_CONTEXT_MISMATCH") {
947
+ return "`vercel usage` returned data for a different team context, so the billing breakdown was not used.";
948
+ }
949
+ if (code === "USAGE_UNAVAILABLE") {
950
+ return "`vercel usage` returned `USAGE_UNAVAILABLE`; no billing breakdown was available from the Vercel CLI.";
951
+ }
952
+ if (typeof code === "string" && code.trim() !== "") {
953
+ return `\`vercel usage\` returned \`${code}\`; no billing breakdown was available from the Vercel CLI.`;
954
+ }
955
+ return "`vercel usage` did not return a billing payload.";
956
+ }
957
+
958
+ function metricState(signals, id) {
959
+ const metrics = signals.metrics ?? {};
960
+ if (!Object.prototype.hasOwnProperty.call(metrics, id)) {
961
+ return { collected: false, failed: false, rows: null, code: null };
962
+ }
963
+ const metric = metrics[id] ?? {};
964
+ const failed = metric.ok === false;
965
+ return {
966
+ collected: !failed,
967
+ failed,
968
+ rows: Array.isArray(metric.rows) ? metric.rows : [],
969
+ code: metric.code ?? "UNKNOWN",
970
+ };
971
+ }
972
+
973
+ function sortRecs(recs) {
974
+ return recs.slice().sort((a, b) => priorityScore(b) - priorityScore(a));
975
+ }
976
+
977
+ function priorityScore(rec) {
978
+ return typeof rec.priority === "number" ? rec.priority : tierScore(rec.impactTier);
979
+ }
980
+ function tierScore(t) {
981
+ return { high: 100, medium: 50, low: 10 }[t] ?? 0;
982
+ }
983
+
984
+ function isPlatformScope(rec) {
985
+ const k = String(rec.candidateRef ?? "").split(":")[0];
986
+ return k.startsWith("platform_") || rec.scope === "account";
987
+ }
988
+
989
+ function impactString(rec, signals = {}) {
990
+ const label = computeImpactLabel(rec, signals);
991
+ if (label) return label;
992
+ return "_(no impact framing recorded)_";
993
+ }
994
+
995
+ function signalFromRec(rec) {
996
+ return rec.findingRefs?.[0] ?? null;
997
+ }
998
+
999
+ function formatUsage(s) {
1000
+ if (typeof s.usage === "string") return s.usage;
1001
+ if (typeof s.usage === "number") return formatNum(s.usage) + (s.unit ? ` ${s.unit}` : "");
1002
+ return "(unspecified)";
1003
+ }
1004
+
1005
+ function formatNum(n) {
1006
+ if (!Number.isFinite(n)) return String(n);
1007
+ if (n >= 1_000_000) return (n / 1_000_000).toFixed(2) + "M";
1008
+ if (n >= 1_000) return (n / 1_000).toFixed(2) + "K";
1009
+ return String(n);
1010
+ }
1011
+
1012
+ function formatBytes(b) {
1013
+ if (!Number.isFinite(b)) return "(n/a)";
1014
+ if (b >= 1e12) return (b / 1e12).toFixed(2) + " TB";
1015
+ if (b >= 1e9) return (b / 1e9).toFixed(2) + " GB";
1016
+ if (b >= 1e6) return (b / 1e6).toFixed(2) + " MB";
1017
+ if (b >= 1e3) return (b / 1e3).toFixed(2) + " KB";
1018
+ return Math.round(b) + " B";
1019
+ }
1020
+
1021
+ function escape(s) {
1022
+ if (typeof s !== "string") return String(s ?? "");
1023
+ return s.replace(/\|/g, "\\|").replace(/\n/g, " ");
1024
+ }
1025
+
1026
+ function asArray(v) {
1027
+ return Array.isArray(v) ? v : [];
1028
+ }
1029
+
1030
+ function enrichRecFromCandidates(rec, candidates) {
1031
+ if (!rec || typeof rec !== "object") return rec;
1032
+ if (!Array.isArray(candidates) || candidates.length === 0) return rec;
1033
+ const ref = rec.candidateRef ?? null;
1034
+ // Match on raw OR canonical kind:route so pre-dedup-canonicalization refs still resolve.
1035
+ let match = null;
1036
+ if (ref) {
1037
+ const [kind, route] = String(ref).split(":");
1038
+ const canonical = route ? canonicalizeRoute(route) : null;
1039
+ match = candidates.find((c) => {
1040
+ if (!c || c.kind !== kind) return false;
1041
+ const cRoute = c.route ?? c.hostname ?? "<account>";
1042
+ return cRoute === route || cRoute === canonical || canonicalizeRoute(cRoute) === canonical;
1043
+ });
1044
+ }
1045
+ const canonicalRef = ref ? canonicalRefOf(ref) : ref;
1046
+ const merged = { ...rec, candidateRef: canonicalRef };
1047
+ if (match) {
1048
+ if (!merged.o11ySignal && match.o11ySignal) merged.o11ySignal = match.o11ySignal;
1049
+ if (!merged.displayRoute && match.displayRoute) merged.displayRoute = match.displayRoute;
1050
+ if (!merged.aliasRoutes && Array.isArray(match.aliasRoutes) && match.aliasRoutes.length > 0) {
1051
+ merged.aliasRoutes = match.aliasRoutes;
1052
+ }
1053
+ if (!merged.mergedCount && typeof match.mergedCount === "number") {
1054
+ merged.mergedCount = match.mergedCount;
1055
+ }
1056
+ }
1057
+ return merged;
1058
+ }
1059
+
1060
+ function canonicalRefOf(ref) {
1061
+ const [kind, ...rest] = String(ref).split(":");
1062
+ const route = rest.join(":");
1063
+ if (!route) return ref;
1064
+ return `${kind}:${canonicalizeRoute(route)}`;
1065
+ }