luckiest-co 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (618) hide show
  1. package/.claude-plugin/marketplace.json +16 -0
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/LICENSE +24 -0
  4. package/bin/install.js +6 -4
  5. package/commands/{luckiest/finish.md → finish.md} +2 -0
  6. package/commands/go.md +53 -0
  7. package/commands/plan.md +66 -0
  8. package/package.json +3 -2
  9. package/skills/brainstorm/ATTRIBUTION.md +27 -0
  10. package/skills/brainstorm/SKILL.md +139 -0
  11. package/skills/luckiest-ab-testing/ATTRIBUTION.md +35 -0
  12. package/skills/luckiest-ab-testing/CHANGELOG.md +27 -0
  13. package/skills/luckiest-ab-testing/SKILL.md +379 -0
  14. package/skills/luckiest-ab-testing/evals/evals.json +118 -0
  15. package/skills/luckiest-ab-testing/references/sample-size-guide.md +290 -0
  16. package/skills/luckiest-ab-testing/references/test-templates.md +284 -0
  17. package/skills/luckiest-ad-creative/ATTRIBUTION.md +35 -0
  18. package/skills/luckiest-ad-creative/CHANGELOG.md +23 -0
  19. package/skills/luckiest-ad-creative/SKILL.md +393 -0
  20. package/skills/luckiest-ad-creative/evals/evals.json +90 -0
  21. package/skills/luckiest-ad-creative/references/generative-tools.md +637 -0
  22. package/skills/luckiest-ad-creative/references/platform-specs.md +213 -0
  23. package/skills/luckiest-ads/ATTRIBUTION.md +36 -0
  24. package/skills/luckiest-ads/CHANGELOG.md +24 -0
  25. package/skills/luckiest-ads/LICENSE +21 -0
  26. package/skills/luckiest-ads/SKILL.md +434 -0
  27. package/skills/luckiest-ads/evals/evals.json +90 -0
  28. package/skills/luckiest-ads/references/ad-copy-templates.md +207 -0
  29. package/skills/luckiest-ads/references/audience-targeting.md +243 -0
  30. package/skills/luckiest-ads/references/conversion-tracking.md +361 -0
  31. package/skills/luckiest-ads/references/platform-setup-checklists.md +277 -0
  32. package/skills/luckiest-advisors/ATTRIBUTION.md +16 -0
  33. package/skills/luckiest-advisors/CHANGELOG.md +99 -0
  34. package/skills/luckiest-advisors/SKILL.md +151 -0
  35. package/skills/luckiest-aeo-grader/ATTRIBUTION.md +19 -0
  36. package/skills/luckiest-aeo-grader/CHANGELOG.md +52 -0
  37. package/skills/luckiest-aeo-grader/SKILL.md +200 -0
  38. package/skills/luckiest-aeo-grader/evals/evals.json +19 -0
  39. package/skills/luckiest-aeo-grader/references/rubric.md +72 -0
  40. package/skills/luckiest-aeo-grader/scripts/scan.py +265 -0
  41. package/skills/luckiest-ai-seo/ATTRIBUTION.md +38 -0
  42. package/skills/luckiest-ai-seo/CHANGELOG.md +23 -0
  43. package/skills/luckiest-ai-seo/SKILL.md +510 -0
  44. package/skills/luckiest-ai-seo/evals/evals.json +90 -0
  45. package/skills/luckiest-ai-seo/references/content-patterns.md +285 -0
  46. package/skills/luckiest-ai-seo/references/content-types.md +71 -0
  47. package/skills/luckiest-ai-seo/references/okf.md +104 -0
  48. package/skills/luckiest-ai-seo/references/platform-ranking-factors.md +154 -0
  49. package/skills/luckiest-analytics/ATTRIBUTION.md +42 -0
  50. package/skills/luckiest-analytics/CHANGELOG.md +36 -0
  51. package/skills/luckiest-analytics/SKILL.md +380 -0
  52. package/skills/luckiest-analytics/evals/evals.json +90 -0
  53. package/skills/luckiest-analytics/references/event-library.md +260 -0
  54. package/skills/luckiest-analytics/references/ga4-implementation.md +300 -0
  55. package/skills/luckiest-analytics/references/gtm-implementation.md +390 -0
  56. package/skills/luckiest-aso/ATTRIBUTION.md +40 -0
  57. package/skills/luckiest-aso/CHANGELOG.md +33 -0
  58. package/skills/luckiest-aso/SKILL.md +327 -0
  59. package/skills/luckiest-aso/evals/evals.json +91 -0
  60. package/skills/luckiest-aso/references/apple-specs.md +107 -0
  61. package/skills/luckiest-aso/references/benchmarks.md +129 -0
  62. package/skills/luckiest-aso/references/google-play-specs.md +131 -0
  63. package/skills/luckiest-aso/references/report-template.md +213 -0
  64. package/skills/luckiest-aso/references/scoring-criteria.md +213 -0
  65. package/skills/luckiest-churn-prevention/ATTRIBUTION.md +41 -0
  66. package/skills/luckiest-churn-prevention/CHANGELOG.md +24 -0
  67. package/skills/luckiest-churn-prevention/SKILL.md +445 -0
  68. package/skills/luckiest-churn-prevention/evals/evals.json +93 -0
  69. package/skills/luckiest-churn-prevention/references/cancel-flow-patterns.md +316 -0
  70. package/skills/luckiest-churn-prevention/references/dunning-playbook.md +408 -0
  71. package/skills/luckiest-co-marketing/ATTRIBUTION.md +38 -0
  72. package/skills/luckiest-co-marketing/CHANGELOG.md +25 -0
  73. package/skills/luckiest-co-marketing/SKILL.md +331 -0
  74. package/skills/luckiest-co-marketing/evals/evals.json +84 -0
  75. package/skills/luckiest-coder/ATTRIBUTION.md +26 -0
  76. package/skills/luckiest-coder/CHANGELOG.md +30 -0
  77. package/skills/luckiest-coder/SKILL.md +77 -0
  78. package/skills/luckiest-coder/references/antigravity-tools.md +23 -0
  79. package/skills/luckiest-coder/references/codex-tools.md +39 -0
  80. package/skills/luckiest-coder/references/pi-tools.md +16 -0
  81. package/skills/luckiest-coder-brainstorming/ATTRIBUTION.md +26 -0
  82. package/skills/luckiest-coder-brainstorming/CHANGELOG.md +31 -0
  83. package/skills/luckiest-coder-brainstorming/SKILL.md +173 -0
  84. package/skills/luckiest-coder-brainstorming/scripts/frame-template.html +213 -0
  85. package/skills/luckiest-coder-brainstorming/scripts/helper.js +168 -0
  86. package/skills/luckiest-coder-brainstorming/scripts/server.cjs +721 -0
  87. package/skills/luckiest-coder-brainstorming/scripts/start-server.sh +209 -0
  88. package/skills/luckiest-coder-brainstorming/scripts/stop-server.sh +120 -0
  89. package/skills/luckiest-coder-brainstorming/spec-document-reviewer-prompt.md +49 -0
  90. package/skills/luckiest-coder-brainstorming/visual-companion.md +291 -0
  91. package/skills/luckiest-coder-consistency/ATTRIBUTION.md +30 -0
  92. package/skills/luckiest-coder-consistency/CHANGELOG.md +26 -0
  93. package/skills/luckiest-coder-consistency/SKILL.md +98 -0
  94. package/skills/luckiest-coder-constitution/ATTRIBUTION.md +28 -0
  95. package/skills/luckiest-coder-constitution/CHANGELOG.md +25 -0
  96. package/skills/luckiest-coder-constitution/SKILL.md +115 -0
  97. package/skills/luckiest-coder-debugging/ATTRIBUTION.md +26 -0
  98. package/skills/luckiest-coder-debugging/CHANGELOG.md +22 -0
  99. package/skills/luckiest-coder-debugging/CREATION-LOG.md +119 -0
  100. package/skills/luckiest-coder-debugging/SKILL.md +309 -0
  101. package/skills/luckiest-coder-debugging/condition-based-waiting-example.ts +158 -0
  102. package/skills/luckiest-coder-debugging/condition-based-waiting.md +115 -0
  103. package/skills/luckiest-coder-debugging/defense-in-depth.md +122 -0
  104. package/skills/luckiest-coder-debugging/find-polluter.sh +63 -0
  105. package/skills/luckiest-coder-debugging/root-cause-tracing.md +169 -0
  106. package/skills/luckiest-coder-debugging/test-academic.md +14 -0
  107. package/skills/luckiest-coder-debugging/test-pressure-1.md +58 -0
  108. package/skills/luckiest-coder-debugging/test-pressure-2.md +68 -0
  109. package/skills/luckiest-coder-debugging/test-pressure-3.md +69 -0
  110. package/skills/luckiest-coder-dispatching-parallel-agents/ATTRIBUTION.md +26 -0
  111. package/skills/luckiest-coder-dispatching-parallel-agents/CHANGELOG.md +23 -0
  112. package/skills/luckiest-coder-dispatching-parallel-agents/SKILL.md +198 -0
  113. package/skills/luckiest-coder-executing-plans/ATTRIBUTION.md +26 -0
  114. package/skills/luckiest-coder-executing-plans/CHANGELOG.md +22 -0
  115. package/skills/luckiest-coder-executing-plans/SKILL.md +83 -0
  116. package/skills/luckiest-coder-finishing-a-branch/ATTRIBUTION.md +26 -0
  117. package/skills/luckiest-coder-finishing-a-branch/CHANGELOG.md +22 -0
  118. package/skills/luckiest-coder-finishing-a-branch/SKILL.md +258 -0
  119. package/skills/luckiest-coder-git-worktrees/ATTRIBUTION.md +26 -0
  120. package/skills/luckiest-coder-git-worktrees/CHANGELOG.md +22 -0
  121. package/skills/luckiest-coder-git-worktrees/SKILL.md +215 -0
  122. package/skills/luckiest-coder-guard/ATTRIBUTION.md +29 -0
  123. package/skills/luckiest-coder-guard/CHANGELOG.md +48 -0
  124. package/skills/luckiest-coder-guard/LICENSE +21 -0
  125. package/skills/luckiest-coder-guard/SKILL.md +126 -0
  126. package/skills/luckiest-coder-guard/bin/check-careful.sh +65 -0
  127. package/skills/luckiest-coder-guard/bin/check-freeze.sh +48 -0
  128. package/skills/luckiest-coder-qa/ATTRIBUTION.md +28 -0
  129. package/skills/luckiest-coder-qa/CHANGELOG.md +49 -0
  130. package/skills/luckiest-coder-qa/LICENSE +21 -0
  131. package/skills/luckiest-coder-qa/SKILL.md +160 -0
  132. package/skills/luckiest-coder-qa/references/issue-taxonomy.md +85 -0
  133. package/skills/luckiest-coder-qa/references/qa-report-template.md +126 -0
  134. package/skills/luckiest-coder-receiving-code-review/ATTRIBUTION.md +26 -0
  135. package/skills/luckiest-coder-receiving-code-review/CHANGELOG.md +28 -0
  136. package/skills/luckiest-coder-receiving-code-review/SKILL.md +226 -0
  137. package/skills/luckiest-coder-requesting-code-review/ATTRIBUTION.md +26 -0
  138. package/skills/luckiest-coder-requesting-code-review/CHANGELOG.md +31 -0
  139. package/skills/luckiest-coder-requesting-code-review/SKILL.md +118 -0
  140. package/skills/luckiest-coder-requesting-code-review/code-reviewer.md +172 -0
  141. package/skills/luckiest-coder-shipping/ATTRIBUTION.md +26 -0
  142. package/skills/luckiest-coder-shipping/CHANGELOG.md +48 -0
  143. package/skills/luckiest-coder-shipping/LICENSE +21 -0
  144. package/skills/luckiest-coder-shipping/SKILL.md +148 -0
  145. package/skills/luckiest-coder-shipping/references/canary.md +44 -0
  146. package/skills/luckiest-coder-shipping/references/test-and-coverage.md +91 -0
  147. package/skills/luckiest-coder-subagent-driven-development/ATTRIBUTION.md +26 -0
  148. package/skills/luckiest-coder-subagent-driven-development/CHANGELOG.md +28 -0
  149. package/skills/luckiest-coder-subagent-driven-development/SKILL.md +439 -0
  150. package/skills/luckiest-coder-subagent-driven-development/implementer-prompt.md +139 -0
  151. package/skills/luckiest-coder-subagent-driven-development/scripts/review-package +44 -0
  152. package/skills/luckiest-coder-subagent-driven-development/scripts/sdd-workspace +22 -0
  153. package/skills/luckiest-coder-subagent-driven-development/scripts/task-brief +40 -0
  154. package/skills/luckiest-coder-subagent-driven-development/task-reviewer-prompt.md +188 -0
  155. package/skills/luckiest-coder-tdd/ATTRIBUTION.md +26 -0
  156. package/skills/luckiest-coder-tdd/CHANGELOG.md +26 -0
  157. package/skills/luckiest-coder-tdd/SKILL.md +384 -0
  158. package/skills/luckiest-coder-tdd/testing-anti-patterns.md +299 -0
  159. package/skills/luckiest-coder-verification/ATTRIBUTION.md +26 -0
  160. package/skills/luckiest-coder-verification/CHANGELOG.md +22 -0
  161. package/skills/luckiest-coder-verification/SKILL.md +152 -0
  162. package/skills/luckiest-coder-writing-plans/ATTRIBUTION.md +26 -0
  163. package/skills/luckiest-coder-writing-plans/CHANGELOG.md +22 -0
  164. package/skills/luckiest-coder-writing-plans/SKILL.md +191 -0
  165. package/skills/luckiest-coder-writing-plans/plan-document-reviewer-prompt.md +49 -0
  166. package/skills/luckiest-coder-writing-skills/ATTRIBUTION.md +26 -0
  167. package/skills/luckiest-coder-writing-skills/CHANGELOG.md +31 -0
  168. package/skills/luckiest-coder-writing-skills/SKILL.md +702 -0
  169. package/skills/luckiest-coder-writing-skills/anthropic-best-practices.md +1150 -0
  170. package/skills/luckiest-coder-writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  171. package/skills/luckiest-coder-writing-skills/graphviz-conventions.dot +172 -0
  172. package/skills/luckiest-coder-writing-skills/persuasion-principles.md +187 -0
  173. package/skills/luckiest-coder-writing-skills/render-graphs.js +168 -0
  174. package/skills/luckiest-coder-writing-skills/testing-skills-with-subagents.md +384 -0
  175. package/skills/luckiest-cold-email/ATTRIBUTION.md +36 -0
  176. package/skills/luckiest-cold-email/CHANGELOG.md +24 -0
  177. package/skills/luckiest-cold-email/SKILL.md +213 -0
  178. package/skills/luckiest-cold-email/evals/evals.json +94 -0
  179. package/skills/luckiest-cold-email/references/benchmarks.md +83 -0
  180. package/skills/luckiest-cold-email/references/follow-up-sequences.md +81 -0
  181. package/skills/luckiest-cold-email/references/frameworks.md +90 -0
  182. package/skills/luckiest-cold-email/references/personalization.md +79 -0
  183. package/skills/luckiest-cold-email/references/subject-lines.md +53 -0
  184. package/skills/luckiest-community-marketing/ATTRIBUTION.md +41 -0
  185. package/skills/luckiest-community-marketing/CHANGELOG.md +35 -0
  186. package/skills/luckiest-community-marketing/SKILL.md +200 -0
  187. package/skills/luckiest-community-marketing/evals/evals.json +89 -0
  188. package/skills/luckiest-competitor-profiling/ATTRIBUTION.md +36 -0
  189. package/skills/luckiest-competitor-profiling/CHANGELOG.md +24 -0
  190. package/skills/luckiest-competitor-profiling/SKILL.md +443 -0
  191. package/skills/luckiest-competitor-profiling/evals/evals.json +85 -0
  192. package/skills/luckiest-competitor-profiling/references/templates.md +167 -0
  193. package/skills/luckiest-competitor-profiling/references/tool-reference.md +179 -0
  194. package/skills/luckiest-competitors/ATTRIBUTION.md +36 -0
  195. package/skills/luckiest-competitors/CHANGELOG.md +25 -0
  196. package/skills/luckiest-competitors/SKILL.md +171 -0
  197. package/skills/luckiest-competitors/evals/evals.json +93 -0
  198. package/skills/luckiest-competitors/references/content-architecture.md +271 -0
  199. package/skills/luckiest-competitors/references/templates.md +223 -0
  200. package/skills/luckiest-content-strategy/ATTRIBUTION.md +39 -0
  201. package/skills/luckiest-content-strategy/CHANGELOG.md +23 -0
  202. package/skills/luckiest-content-strategy/SKILL.md +395 -0
  203. package/skills/luckiest-content-strategy/evals/evals.json +90 -0
  204. package/skills/luckiest-content-strategy/references/headless-cms.md +194 -0
  205. package/skills/luckiest-copy-editing/ATTRIBUTION.md +41 -0
  206. package/skills/luckiest-copy-editing/CHANGELOG.md +31 -0
  207. package/skills/luckiest-copy-editing/SKILL.md +491 -0
  208. package/skills/luckiest-copy-editing/evals/evals.json +89 -0
  209. package/skills/luckiest-copy-editing/references/checklist.md +66 -0
  210. package/skills/luckiest-copy-editing/references/content-refresh.md +38 -0
  211. package/skills/luckiest-copy-editing/references/plain-english-alternatives.md +394 -0
  212. package/skills/luckiest-copywriting/ATTRIBUTION.md +35 -0
  213. package/skills/luckiest-copywriting/CHANGELOG.md +23 -0
  214. package/skills/luckiest-copywriting/SKILL.md +296 -0
  215. package/skills/luckiest-copywriting/evals/evals.json +111 -0
  216. package/skills/luckiest-copywriting/references/copy-frameworks.md +344 -0
  217. package/skills/luckiest-copywriting/references/natural-transitions.md +272 -0
  218. package/skills/luckiest-cro/ATTRIBUTION.md +34 -0
  219. package/skills/luckiest-cro/CHANGELOG.md +23 -0
  220. package/skills/luckiest-cro/SKILL.md +215 -0
  221. package/skills/luckiest-cro/evals/evals.json +111 -0
  222. package/skills/luckiest-cro/references/experiments.md +248 -0
  223. package/skills/luckiest-cro/references/form.md +422 -0
  224. package/skills/luckiest-customer-research/ATTRIBUTION.md +40 -0
  225. package/skills/luckiest-customer-research/CHANGELOG.md +26 -0
  226. package/skills/luckiest-customer-research/SKILL.md +293 -0
  227. package/skills/luckiest-customer-research/evals/evals.json +162 -0
  228. package/skills/luckiest-customer-research/references/source-guides.md +401 -0
  229. package/skills/luckiest-directory-submissions/ATTRIBUTION.md +40 -0
  230. package/skills/luckiest-directory-submissions/CHANGELOG.md +33 -0
  231. package/skills/luckiest-directory-submissions/SKILL.md +419 -0
  232. package/skills/luckiest-directory-submissions/evals/evals.json +94 -0
  233. package/skills/luckiest-directory-submissions/references/directory-list.md +477 -0
  234. package/skills/luckiest-directory-submissions/references/positioning-variations.md +232 -0
  235. package/skills/luckiest-directory-submissions/references/submission-tracker-template.csv +266 -0
  236. package/skills/luckiest-emails/ATTRIBUTION.md +42 -0
  237. package/skills/luckiest-emails/CHANGELOG.md +33 -0
  238. package/skills/luckiest-emails/SKILL.md +220 -0
  239. package/skills/luckiest-emails/evals/evals.json +93 -0
  240. package/skills/luckiest-emails/references/copy-guidelines.md +120 -0
  241. package/skills/luckiest-emails/references/email-types.md +515 -0
  242. package/skills/luckiest-emails/references/sequence-templates.md +168 -0
  243. package/skills/luckiest-extract-design-system/ATTRIBUTION.md +8 -0
  244. package/skills/luckiest-extract-design-system/CHANGELOG.md +37 -0
  245. package/skills/luckiest-extract-design-system/SKILL.md +83 -0
  246. package/skills/luckiest-free-tools/ATTRIBUTION.md +43 -0
  247. package/skills/luckiest-free-tools/CHANGELOG.md +25 -0
  248. package/skills/luckiest-free-tools/SKILL.md +220 -0
  249. package/skills/luckiest-free-tools/evals/evals.json +90 -0
  250. package/skills/luckiest-free-tools/references/tool-types.md +217 -0
  251. package/skills/luckiest-image/ATTRIBUTION.md +43 -0
  252. package/skills/luckiest-image/CHANGELOG.md +23 -0
  253. package/skills/luckiest-image/SKILL.md +376 -0
  254. package/skills/luckiest-image/evals/evals.json +89 -0
  255. package/skills/luckiest-image/references/ai-image-prompting.md +229 -0
  256. package/skills/luckiest-launch/ATTRIBUTION.md +40 -0
  257. package/skills/luckiest-launch/CHANGELOG.md +43 -0
  258. package/skills/luckiest-launch/SKILL.md +385 -0
  259. package/skills/luckiest-launch/evals/evals.json +91 -0
  260. package/skills/luckiest-lead-magnets/ATTRIBUTION.md +35 -0
  261. package/skills/luckiest-lead-magnets/CHANGELOG.md +23 -0
  262. package/skills/luckiest-lead-magnets/SKILL.md +331 -0
  263. package/skills/luckiest-lead-magnets/evals/evals.json +87 -0
  264. package/skills/luckiest-lead-magnets/references/benchmarks.md +129 -0
  265. package/skills/luckiest-lead-magnets/references/format-guide.md +196 -0
  266. package/skills/luckiest-marketing-ideas/ATTRIBUTION.md +39 -0
  267. package/skills/luckiest-marketing-ideas/CHANGELOG.md +33 -0
  268. package/skills/luckiest-marketing-ideas/SKILL.md +191 -0
  269. package/skills/luckiest-marketing-ideas/evals/evals.json +90 -0
  270. package/skills/luckiest-marketing-ideas/references/ideas-by-category.md +366 -0
  271. package/skills/luckiest-marketing-plan/ATTRIBUTION.md +40 -0
  272. package/skills/luckiest-marketing-plan/CHANGELOG.md +23 -0
  273. package/skills/luckiest-marketing-plan/SKILL.md +285 -0
  274. package/skills/luckiest-marketing-plan/evals/evals.json +96 -0
  275. package/skills/luckiest-marketing-plan/references/aarrr-framework.md +180 -0
  276. package/skills/luckiest-marketing-plan/references/budget-planning.md +168 -0
  277. package/skills/luckiest-marketing-plan/references/client-types.md +373 -0
  278. package/skills/luckiest-marketing-plan/references/current-state-rubric.md +255 -0
  279. package/skills/luckiest-marketing-plan/references/example-quietude.md +972 -0
  280. package/skills/luckiest-marketing-plan/references/funding-stage-unlocks.md +230 -0
  281. package/skills/luckiest-marketing-plan/references/growth-patterns.md +148 -0
  282. package/skills/luckiest-marketing-plan/references/idea-cross-reference.md +265 -0
  283. package/skills/luckiest-marketing-plan/references/measurement-framework.md +213 -0
  284. package/skills/luckiest-marketing-plan/references/methodology.md +363 -0
  285. package/skills/luckiest-marketing-plan/references/ops-stack-mapping.md +197 -0
  286. package/skills/luckiest-marketing-plan/references/plan-template.md +494 -0
  287. package/skills/luckiest-marketing-plan/references/team-and-agency-model.md +278 -0
  288. package/skills/luckiest-marketing-psychology/ATTRIBUTION.md +31 -0
  289. package/skills/luckiest-marketing-psychology/CHANGELOG.md +32 -0
  290. package/skills/luckiest-marketing-psychology/SKILL.md +202 -0
  291. package/skills/luckiest-marketing-psychology/evals.json +88 -0
  292. package/skills/luckiest-model-router/ATTRIBUTION.md +11 -0
  293. package/skills/luckiest-model-router/CHANGELOG.md +45 -0
  294. package/skills/luckiest-model-router/SKILL.md +74 -0
  295. package/skills/luckiest-model-router/scripts/route.py +145 -0
  296. package/skills/luckiest-offers/ATTRIBUTION.md +39 -0
  297. package/skills/luckiest-offers/CHANGELOG.md +23 -0
  298. package/skills/luckiest-offers/SKILL.md +167 -0
  299. package/skills/luckiest-offers/references/bonus-stacking.md +150 -0
  300. package/skills/luckiest-offers/references/examples.md +215 -0
  301. package/skills/luckiest-offers/references/guarantee-design.md +172 -0
  302. package/skills/luckiest-offers/references/offer-anatomy.md +203 -0
  303. package/skills/luckiest-offers/references/offer-formats.md +240 -0
  304. package/skills/luckiest-offers/references/scarcity-urgency.md +175 -0
  305. package/skills/luckiest-offers/references/value-equation.md +134 -0
  306. package/skills/luckiest-onboarding/ATTRIBUTION.md +43 -0
  307. package/skills/luckiest-onboarding/CHANGELOG.md +31 -0
  308. package/skills/luckiest-onboarding/SKILL.md +243 -0
  309. package/skills/luckiest-onboarding/references/experiments.md +258 -0
  310. package/skills/luckiest-paywalls/ATTRIBUTION.md +39 -0
  311. package/skills/luckiest-paywalls/CHANGELOG.md +25 -0
  312. package/skills/luckiest-paywalls/SKILL.md +256 -0
  313. package/skills/luckiest-paywalls/evals/evals.json +93 -0
  314. package/skills/luckiest-paywalls/references/experiments.md +164 -0
  315. package/skills/luckiest-popups/ATTRIBUTION.md +35 -0
  316. package/skills/luckiest-popups/CHANGELOG.md +27 -0
  317. package/skills/luckiest-popups/SKILL.md +477 -0
  318. package/skills/luckiest-popups/evals/evals.json +107 -0
  319. package/skills/luckiest-pricing/ATTRIBUTION.md +35 -0
  320. package/skills/luckiest-pricing/CHANGELOG.md +31 -0
  321. package/skills/luckiest-pricing/SKILL.md +283 -0
  322. package/skills/luckiest-pricing/evals/evals.json +90 -0
  323. package/skills/luckiest-pricing/references/research-methods.md +152 -0
  324. package/skills/luckiest-pricing/references/tier-structure.md +232 -0
  325. package/skills/luckiest-product-marketing/ATTRIBUTION.md +38 -0
  326. package/skills/luckiest-product-marketing/CHANGELOG.md +23 -0
  327. package/skills/luckiest-product-marketing/SKILL.md +256 -0
  328. package/skills/luckiest-product-marketing/evals/evals.json +85 -0
  329. package/skills/luckiest-programmatic-seo/ATTRIBUTION.md +35 -0
  330. package/skills/luckiest-programmatic-seo/CHANGELOG.md +24 -0
  331. package/skills/luckiest-programmatic-seo/SKILL.md +286 -0
  332. package/skills/luckiest-programmatic-seo/evals/evals.json +95 -0
  333. package/skills/luckiest-programmatic-seo/references/playbooks.md +308 -0
  334. package/skills/luckiest-prompt-rewrite/ATTRIBUTION.md +39 -0
  335. package/skills/luckiest-prompt-rewrite/CHANGELOG.md +70 -0
  336. package/skills/luckiest-prompt-rewrite/LICENSE +21 -0
  337. package/skills/luckiest-prompt-rewrite/SKILL.md +494 -0
  338. package/skills/luckiest-prompt-rewrite/references/patterns.md +82 -0
  339. package/skills/luckiest-prompt-rewrite/references/templates.md +454 -0
  340. package/skills/luckiest-prospecting/ATTRIBUTION.md +29 -0
  341. package/skills/luckiest-prospecting/CHANGELOG.md +24 -0
  342. package/skills/luckiest-prospecting/SKILL.md +275 -0
  343. package/skills/luckiest-prospecting/evals/evals.json +107 -0
  344. package/skills/luckiest-prospecting/references/b2b-prospecting.md +106 -0
  345. package/skills/luckiest-prospecting/references/compliance.md +123 -0
  346. package/skills/luckiest-prospecting/references/data-sources.md +287 -0
  347. package/skills/luckiest-prospecting/references/local-prospecting.md +165 -0
  348. package/skills/luckiest-prospecting/references/saas-prospecting.md +123 -0
  349. package/skills/luckiest-public-relations/ATTRIBUTION.md +34 -0
  350. package/skills/luckiest-public-relations/CHANGELOG.md +23 -0
  351. package/skills/luckiest-public-relations/SKILL.md +154 -0
  352. package/skills/luckiest-public-relations/references/journalist-pitching.md +368 -0
  353. package/skills/luckiest-public-relations/references/media-outlets.md +207 -0
  354. package/skills/luckiest-public-relations/references/newsjacking.md +218 -0
  355. package/skills/luckiest-public-relations/references/press-platforms.md +188 -0
  356. package/skills/luckiest-referrals/ATTRIBUTION.md +41 -0
  357. package/skills/luckiest-referrals/CHANGELOG.md +23 -0
  358. package/skills/luckiest-referrals/SKILL.md +292 -0
  359. package/skills/luckiest-referrals/evals/evals.json +90 -0
  360. package/skills/luckiest-referrals/references/affiliate-programs.md +167 -0
  361. package/skills/luckiest-referrals/references/program-examples.md +143 -0
  362. package/skills/luckiest-revops/ATTRIBUTION.md +40 -0
  363. package/skills/luckiest-revops/CHANGELOG.md +24 -0
  364. package/skills/luckiest-revops/SKILL.md +362 -0
  365. package/skills/luckiest-revops/evals/evals.json +91 -0
  366. package/skills/luckiest-revops/references/automation-playbooks.md +290 -0
  367. package/skills/luckiest-revops/references/lifecycle-definitions.md +278 -0
  368. package/skills/luckiest-revops/references/routing-rules.md +203 -0
  369. package/skills/luckiest-revops/references/scoring-models.md +247 -0
  370. package/skills/luckiest-sales-enablement/ATTRIBUTION.md +39 -0
  371. package/skills/luckiest-sales-enablement/CHANGELOG.md +23 -0
  372. package/skills/luckiest-sales-enablement/SKILL.md +379 -0
  373. package/skills/luckiest-sales-enablement/evals/evals.json +91 -0
  374. package/skills/luckiest-sales-enablement/references/deck-frameworks.md +263 -0
  375. package/skills/luckiest-sales-enablement/references/demo-scripts.md +355 -0
  376. package/skills/luckiest-sales-enablement/references/objection-library.md +270 -0
  377. package/skills/luckiest-sales-enablement/references/one-pager-templates.md +208 -0
  378. package/skills/luckiest-schema/ATTRIBUTION.md +39 -0
  379. package/skills/luckiest-schema/CHANGELOG.md +25 -0
  380. package/skills/luckiest-schema/SKILL.md +209 -0
  381. package/skills/luckiest-schema/evals/evals.json +88 -0
  382. package/skills/luckiest-schema/references/schema-examples.md +398 -0
  383. package/skills/luckiest-seo-audit/ATTRIBUTION.md +39 -0
  384. package/skills/luckiest-seo-audit/CHANGELOG.md +23 -0
  385. package/skills/luckiest-seo-audit/SKILL.md +529 -0
  386. package/skills/luckiest-seo-audit/evals/evals.json +136 -0
  387. package/skills/luckiest-seo-audit/references/ai-writing-detection.md +200 -0
  388. package/skills/luckiest-seo-audit/references/international-seo.md +230 -0
  389. package/skills/luckiest-session-handoff/ATTRIBUTION.md +14 -0
  390. package/skills/luckiest-session-handoff/CHANGELOG.md +30 -0
  391. package/skills/luckiest-session-handoff/SKILL.md +96 -0
  392. package/skills/luckiest-signup/ATTRIBUTION.md +48 -0
  393. package/skills/luckiest-signup/CHANGELOG.md +24 -0
  394. package/skills/luckiest-signup/SKILL.md +382 -0
  395. package/skills/luckiest-signup/evals/evals.json +88 -0
  396. package/skills/luckiest-site-architecture/ATTRIBUTION.md +38 -0
  397. package/skills/luckiest-site-architecture/CHANGELOG.md +23 -0
  398. package/skills/luckiest-site-architecture/SKILL.md +383 -0
  399. package/skills/luckiest-site-architecture/evals/evals.json +88 -0
  400. package/skills/luckiest-site-architecture/references/mermaid-templates.md +216 -0
  401. package/skills/luckiest-site-architecture/references/navigation-patterns.md +305 -0
  402. package/skills/luckiest-site-architecture/references/site-type-templates.md +293 -0
  403. package/skills/luckiest-sms/ATTRIBUTION.md +27 -0
  404. package/skills/luckiest-sms/CHANGELOG.md +24 -0
  405. package/skills/luckiest-sms/SKILL.md +400 -0
  406. package/skills/luckiest-sms/evals/evals.json +100 -0
  407. package/skills/luckiest-sms/references/compliance.md +202 -0
  408. package/skills/luckiest-sms/references/platforms.md +318 -0
  409. package/skills/luckiest-sms/references/sequence-templates.md +282 -0
  410. package/skills/luckiest-social/ATTRIBUTION.md +27 -0
  411. package/skills/luckiest-social/CHANGELOG.md +24 -0
  412. package/skills/luckiest-social/SKILL.md +430 -0
  413. package/skills/luckiest-social/evals/evals.json +92 -0
  414. package/skills/luckiest-social/references/listening-sources-template.md +123 -0
  415. package/skills/luckiest-social/references/listening.md +283 -0
  416. package/skills/luckiest-social/references/platform-limits.md +110 -0
  417. package/skills/luckiest-social/references/platforms.md +170 -0
  418. package/skills/luckiest-social/references/post-templates.md +177 -0
  419. package/skills/luckiest-social/references/reverse-engineering.md +195 -0
  420. package/skills/luckiest-social/references/short-form-video.md +237 -0
  421. package/skills/luckiest-thinker/ATTRIBUTION.md +16 -0
  422. package/skills/luckiest-thinker/CHANGELOG.md +20 -0
  423. package/skills/luckiest-thinker/LICENSE +21 -0
  424. package/skills/luckiest-thinker/SKILL.md +92 -0
  425. package/skills/luckiest-thinker/references/distribution-calibration.md +106 -0
  426. package/skills/luckiest-thinker/references/research-foundations.md +214 -0
  427. package/skills/luckiest-thinker/references/thinking-patterns.md +138 -0
  428. package/skills/luckiest-trends/.skillignore +10 -0
  429. package/skills/luckiest-trends/ATTRIBUTION.md +43 -0
  430. package/skills/luckiest-trends/CHANGELOG.md +86 -0
  431. package/skills/luckiest-trends/LICENSE +21 -0
  432. package/skills/luckiest-trends/SKILL.md +194 -0
  433. package/skills/luckiest-trends/agents/openai.yaml +8 -0
  434. package/skills/luckiest-trends/references/engine-contract.md +2041 -0
  435. package/skills/luckiest-trends/references/save-html-brief.md +206 -0
  436. package/skills/luckiest-trends/scripts/briefing.py +272 -0
  437. package/skills/luckiest-trends/scripts/build-skill.sh +39 -0
  438. package/skills/luckiest-trends/scripts/compare.sh +61 -0
  439. package/skills/luckiest-trends/scripts/evaluate_search_quality.py +573 -0
  440. package/skills/luckiest-trends/scripts/last30days.py +1467 -0
  441. package/skills/luckiest-trends/scripts/lib/__init__.py +1 -0
  442. package/skills/luckiest-trends/scripts/lib/__pycache__/__init__.cpython-313.pyc +0 -0
  443. package/skills/luckiest-trends/scripts/lib/__pycache__/arxiv.cpython-313.pyc +0 -0
  444. package/skills/luckiest-trends/scripts/lib/__pycache__/bird_x.cpython-313.pyc +0 -0
  445. package/skills/luckiest-trends/scripts/lib/__pycache__/bluesky.cpython-313.pyc +0 -0
  446. package/skills/luckiest-trends/scripts/lib/__pycache__/categories.cpython-313.pyc +0 -0
  447. package/skills/luckiest-trends/scripts/lib/__pycache__/cjk.cpython-313.pyc +0 -0
  448. package/skills/luckiest-trends/scripts/lib/__pycache__/cluster.cpython-313.pyc +0 -0
  449. package/skills/luckiest-trends/scripts/lib/__pycache__/dates.cpython-313.pyc +0 -0
  450. package/skills/luckiest-trends/scripts/lib/__pycache__/dedupe.cpython-313.pyc +0 -0
  451. package/skills/luckiest-trends/scripts/lib/__pycache__/digg.cpython-313.pyc +0 -0
  452. package/skills/luckiest-trends/scripts/lib/__pycache__/entity_extract.cpython-313.pyc +0 -0
  453. package/skills/luckiest-trends/scripts/lib/__pycache__/env.cpython-313.pyc +0 -0
  454. package/skills/luckiest-trends/scripts/lib/__pycache__/fusion.cpython-313.pyc +0 -0
  455. package/skills/luckiest-trends/scripts/lib/__pycache__/github.cpython-313.pyc +0 -0
  456. package/skills/luckiest-trends/scripts/lib/__pycache__/grounding.cpython-313.pyc +0 -0
  457. package/skills/luckiest-trends/scripts/lib/__pycache__/hackernews.cpython-313.pyc +0 -0
  458. package/skills/luckiest-trends/scripts/lib/__pycache__/hiring_signals.cpython-313.pyc +0 -0
  459. package/skills/luckiest-trends/scripts/lib/__pycache__/html_render.cpython-313.pyc +0 -0
  460. package/skills/luckiest-trends/scripts/lib/__pycache__/http.cpython-313.pyc +0 -0
  461. package/skills/luckiest-trends/scripts/lib/__pycache__/instagram.cpython-313.pyc +0 -0
  462. package/skills/luckiest-trends/scripts/lib/__pycache__/jobs.cpython-313.pyc +0 -0
  463. package/skills/luckiest-trends/scripts/lib/__pycache__/linkedin.cpython-313.pyc +0 -0
  464. package/skills/luckiest-trends/scripts/lib/__pycache__/log.cpython-313.pyc +0 -0
  465. package/skills/luckiest-trends/scripts/lib/__pycache__/normalize.cpython-313.pyc +0 -0
  466. package/skills/luckiest-trends/scripts/lib/__pycache__/permission_preflight.cpython-313.pyc +0 -0
  467. package/skills/luckiest-trends/scripts/lib/__pycache__/perplexity.cpython-313.pyc +0 -0
  468. package/skills/luckiest-trends/scripts/lib/__pycache__/pinterest.cpython-313.pyc +0 -0
  469. package/skills/luckiest-trends/scripts/lib/__pycache__/pipeline.cpython-313.pyc +0 -0
  470. package/skills/luckiest-trends/scripts/lib/__pycache__/planner.cpython-313.pyc +0 -0
  471. package/skills/luckiest-trends/scripts/lib/__pycache__/polymarket.cpython-313.pyc +0 -0
  472. package/skills/luckiest-trends/scripts/lib/__pycache__/preflight.cpython-313.pyc +0 -0
  473. package/skills/luckiest-trends/scripts/lib/__pycache__/providers.cpython-313.pyc +0 -0
  474. package/skills/luckiest-trends/scripts/lib/__pycache__/quality_nudge.cpython-313.pyc +0 -0
  475. package/skills/luckiest-trends/scripts/lib/__pycache__/query.cpython-313.pyc +0 -0
  476. package/skills/luckiest-trends/scripts/lib/__pycache__/reddit.cpython-313.pyc +0 -0
  477. package/skills/luckiest-trends/scripts/lib/__pycache__/reddit_arctic.cpython-313.pyc +0 -0
  478. package/skills/luckiest-trends/scripts/lib/__pycache__/reddit_enrich.cpython-313.pyc +0 -0
  479. package/skills/luckiest-trends/scripts/lib/__pycache__/reddit_keyless.cpython-313.pyc +0 -0
  480. package/skills/luckiest-trends/scripts/lib/__pycache__/reddit_listing.cpython-313.pyc +0 -0
  481. package/skills/luckiest-trends/scripts/lib/__pycache__/reddit_public.cpython-313.pyc +0 -0
  482. package/skills/luckiest-trends/scripts/lib/__pycache__/reddit_rss.cpython-313.pyc +0 -0
  483. package/skills/luckiest-trends/scripts/lib/__pycache__/reddit_shreddit.cpython-313.pyc +0 -0
  484. package/skills/luckiest-trends/scripts/lib/__pycache__/relevance.cpython-313.pyc +0 -0
  485. package/skills/luckiest-trends/scripts/lib/__pycache__/render.cpython-313.pyc +0 -0
  486. package/skills/luckiest-trends/scripts/lib/__pycache__/rerank.cpython-313.pyc +0 -0
  487. package/skills/luckiest-trends/scripts/lib/__pycache__/resolve.cpython-313.pyc +0 -0
  488. package/skills/luckiest-trends/scripts/lib/__pycache__/schema.cpython-313.pyc +0 -0
  489. package/skills/luckiest-trends/scripts/lib/__pycache__/signals.cpython-313.pyc +0 -0
  490. package/skills/luckiest-trends/scripts/lib/__pycache__/skill_meta.cpython-313.pyc +0 -0
  491. package/skills/luckiest-trends/scripts/lib/__pycache__/snippet.cpython-313.pyc +0 -0
  492. package/skills/luckiest-trends/scripts/lib/__pycache__/subproc.cpython-313.pyc +0 -0
  493. package/skills/luckiest-trends/scripts/lib/__pycache__/techmeme.cpython-313.pyc +0 -0
  494. package/skills/luckiest-trends/scripts/lib/__pycache__/threads.cpython-313.pyc +0 -0
  495. package/skills/luckiest-trends/scripts/lib/__pycache__/tiktok.cpython-313.pyc +0 -0
  496. package/skills/luckiest-trends/scripts/lib/__pycache__/trustpilot.cpython-313.pyc +0 -0
  497. package/skills/luckiest-trends/scripts/lib/__pycache__/truthsocial.cpython-313.pyc +0 -0
  498. package/skills/luckiest-trends/scripts/lib/__pycache__/ui.cpython-313.pyc +0 -0
  499. package/skills/luckiest-trends/scripts/lib/__pycache__/web_search_keyless.cpython-313.pyc +0 -0
  500. package/skills/luckiest-trends/scripts/lib/__pycache__/xai_x.cpython-313.pyc +0 -0
  501. package/skills/luckiest-trends/scripts/lib/__pycache__/xiaohongshu_api.cpython-313.pyc +0 -0
  502. package/skills/luckiest-trends/scripts/lib/__pycache__/xquik.cpython-313.pyc +0 -0
  503. package/skills/luckiest-trends/scripts/lib/__pycache__/xurl_x.cpython-313.pyc +0 -0
  504. package/skills/luckiest-trends/scripts/lib/__pycache__/youtube_yt.cpython-313.pyc +0 -0
  505. package/skills/luckiest-trends/scripts/lib/arxiv.py +290 -0
  506. package/skills/luckiest-trends/scripts/lib/bird_x.py +639 -0
  507. package/skills/luckiest-trends/scripts/lib/bluesky.py +323 -0
  508. package/skills/luckiest-trends/scripts/lib/categories.py +283 -0
  509. package/skills/luckiest-trends/scripts/lib/chrome_cookies.py +414 -0
  510. package/skills/luckiest-trends/scripts/lib/cjk.py +107 -0
  511. package/skills/luckiest-trends/scripts/lib/cluster.py +271 -0
  512. package/skills/luckiest-trends/scripts/lib/competitors.py +198 -0
  513. package/skills/luckiest-trends/scripts/lib/cookie_extract.py +508 -0
  514. package/skills/luckiest-trends/scripts/lib/dates.py +169 -0
  515. package/skills/luckiest-trends/scripts/lib/dedupe.py +145 -0
  516. package/skills/luckiest-trends/scripts/lib/digg.py +440 -0
  517. package/skills/luckiest-trends/scripts/lib/entity_extract.py +127 -0
  518. package/skills/luckiest-trends/scripts/lib/env.py +1073 -0
  519. package/skills/luckiest-trends/scripts/lib/fanout.py +84 -0
  520. package/skills/luckiest-trends/scripts/lib/fusion.py +207 -0
  521. package/skills/luckiest-trends/scripts/lib/github.py +996 -0
  522. package/skills/luckiest-trends/scripts/lib/grounding.py +331 -0
  523. package/skills/luckiest-trends/scripts/lib/hackernews.py +357 -0
  524. package/skills/luckiest-trends/scripts/lib/health.py +92 -0
  525. package/skills/luckiest-trends/scripts/lib/hiring_signals.py +326 -0
  526. package/skills/luckiest-trends/scripts/lib/html_publish.py +73 -0
  527. package/skills/luckiest-trends/scripts/lib/html_render.py +738 -0
  528. package/skills/luckiest-trends/scripts/lib/http.py +372 -0
  529. package/skills/luckiest-trends/scripts/lib/instagram.py +521 -0
  530. package/skills/luckiest-trends/scripts/lib/jobs.py +708 -0
  531. package/skills/luckiest-trends/scripts/lib/linkedin.py +363 -0
  532. package/skills/luckiest-trends/scripts/lib/log.py +35 -0
  533. package/skills/luckiest-trends/scripts/lib/normalize.py +759 -0
  534. package/skills/luckiest-trends/scripts/lib/permission_preflight.py +242 -0
  535. package/skills/luckiest-trends/scripts/lib/perplexity.py +745 -0
  536. package/skills/luckiest-trends/scripts/lib/pinterest.py +154 -0
  537. package/skills/luckiest-trends/scripts/lib/pipeline.py +1720 -0
  538. package/skills/luckiest-trends/scripts/lib/planner.py +763 -0
  539. package/skills/luckiest-trends/scripts/lib/polymarket.py +794 -0
  540. package/skills/luckiest-trends/scripts/lib/preflight.py +119 -0
  541. package/skills/luckiest-trends/scripts/lib/providers.py +380 -0
  542. package/skills/luckiest-trends/scripts/lib/quality_nudge.py +383 -0
  543. package/skills/luckiest-trends/scripts/lib/query.py +202 -0
  544. package/skills/luckiest-trends/scripts/lib/reddit.py +731 -0
  545. package/skills/luckiest-trends/scripts/lib/reddit_arctic.py +92 -0
  546. package/skills/luckiest-trends/scripts/lib/reddit_enrich.py +322 -0
  547. package/skills/luckiest-trends/scripts/lib/reddit_keyless.py +329 -0
  548. package/skills/luckiest-trends/scripts/lib/reddit_listing.py +188 -0
  549. package/skills/luckiest-trends/scripts/lib/reddit_public.py +275 -0
  550. package/skills/luckiest-trends/scripts/lib/reddit_rss.py +224 -0
  551. package/skills/luckiest-trends/scripts/lib/reddit_shreddit.py +184 -0
  552. package/skills/luckiest-trends/scripts/lib/relevance.py +200 -0
  553. package/skills/luckiest-trends/scripts/lib/render.py +2130 -0
  554. package/skills/luckiest-trends/scripts/lib/rerank.py +708 -0
  555. package/skills/luckiest-trends/scripts/lib/resolve.py +345 -0
  556. package/skills/luckiest-trends/scripts/lib/safari_cookies.py +193 -0
  557. package/skills/luckiest-trends/scripts/lib/schema.py +319 -0
  558. package/skills/luckiest-trends/scripts/lib/setup_wizard.py +843 -0
  559. package/skills/luckiest-trends/scripts/lib/signals.py +334 -0
  560. package/skills/luckiest-trends/scripts/lib/skill_meta.py +33 -0
  561. package/skills/luckiest-trends/scripts/lib/snippet.py +51 -0
  562. package/skills/luckiest-trends/scripts/lib/subproc.py +116 -0
  563. package/skills/luckiest-trends/scripts/lib/techmeme.py +239 -0
  564. package/skills/luckiest-trends/scripts/lib/threads.py +207 -0
  565. package/skills/luckiest-trends/scripts/lib/tiktok.py +596 -0
  566. package/skills/luckiest-trends/scripts/lib/transcribe.py +235 -0
  567. package/skills/luckiest-trends/scripts/lib/trustpilot.py +277 -0
  568. package/skills/luckiest-trends/scripts/lib/truthsocial.py +162 -0
  569. package/skills/luckiest-trends/scripts/lib/ui.py +626 -0
  570. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/LICENSE +21 -0
  571. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/bird-search.mjs +147 -0
  572. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/cookies.js +220 -0
  573. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/features.json +17 -0
  574. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/paginate-cursor.js +37 -0
  575. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/query-ids.json +20 -0
  576. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/runtime-features.js +151 -0
  577. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/runtime-query-ids.js +264 -0
  578. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/twitter-client-base.js +129 -0
  579. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/twitter-client-constants.js +50 -0
  580. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/twitter-client-features.js +347 -0
  581. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/twitter-client-search.js +157 -0
  582. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/twitter-client-types.js +2 -0
  583. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/lib/twitter-client-utils.js +511 -0
  584. package/skills/luckiest-trends/scripts/lib/vendor/bird-search/package.json +13 -0
  585. package/skills/luckiest-trends/scripts/lib/web_fetch_keyless.py +105 -0
  586. package/skills/luckiest-trends/scripts/lib/web_search_keyless.py +158 -0
  587. package/skills/luckiest-trends/scripts/lib/xai_x.py +236 -0
  588. package/skills/luckiest-trends/scripts/lib/xiaohongshu_api.py +162 -0
  589. package/skills/luckiest-trends/scripts/lib/xquik.py +404 -0
  590. package/skills/luckiest-trends/scripts/lib/xurl_x.py +171 -0
  591. package/skills/luckiest-trends/scripts/lib/youtube_yt.py +1365 -0
  592. package/skills/luckiest-trends/scripts/setup-keychain.sh +123 -0
  593. package/skills/luckiest-trends/scripts/setup-pass.sh +132 -0
  594. package/skills/luckiest-trends/scripts/store.py +1020 -0
  595. package/skills/luckiest-trends/scripts/test-v1-vs-v2.sh +220 -0
  596. package/skills/luckiest-trends/scripts/test_device_auth.py +128 -0
  597. package/skills/luckiest-trends/scripts/verify_v3.py +195 -0
  598. package/skills/luckiest-trends/scripts/watchlist.py +318 -0
  599. package/skills/luckiest-video/ATTRIBUTION.md +27 -0
  600. package/skills/luckiest-video/CHANGELOG.md +23 -0
  601. package/skills/luckiest-video/SKILL.md +371 -0
  602. package/skills/luckiest-video/evals/evals.json +88 -0
  603. package/skills/luckiest-video/references/ai-video-prompting.md +175 -0
  604. package/skills/remix/SKILL.md +32 -0
  605. package/commands/luckiest/go.md +0 -45
  606. package/commands/luckiest/plan.md +0 -55
  607. /package/commands/{luckiest/charms.md → charms.md} +0 -0
  608. /package/commands/{luckiest/helpers.md → helpers.md} +0 -0
  609. /package/commands/{luckiest/home.md → home.md} +0 -0
  610. /package/commands/{luckiest/leaderboard.md → leaderboard.md} +0 -0
  611. /package/commands/{luckiest/merge.md → merge.md} +0 -0
  612. /package/commands/{luckiest/overlaps.md → overlaps.md} +0 -0
  613. /package/commands/{luckiest/skills.md → skills.md} +0 -0
  614. /package/commands/{luckiest/start.md → start.md} +0 -0
  615. /package/commands/{luckiest/status.md → status.md} +0 -0
  616. /package/commands/{luckiest/updates.md → updates.md} +0 -0
  617. /package/commands/{luckiest/vouch.md → vouch.md} +0 -0
  618. /package/commands/{luckiest/wishes.md → wishes.md} +0 -0
@@ -0,0 +1,383 @@
1
+ """Post-research quality score and upgrade nudge.
2
+
3
+ Computes a quality score based on 5 core sources and builds
4
+ a nudge message describing what the user missed and how to fix it.
5
+ """
6
+
7
+ from typing import List
8
+
9
+
10
+ # The 5 core sources
11
+ CORE_SOURCES = ["hn", "polymarket", "x", "youtube", "reddit"]
12
+
13
+ # Labels for display
14
+ SOURCE_LABELS = {
15
+ "hn": "Hacker News",
16
+ "polymarket": "Polymarket",
17
+ "x": "X/Twitter",
18
+ "youtube": "YouTube",
19
+ "reddit": "Reddit",
20
+ }
21
+
22
+
23
+ def _is_x_active(config: dict, research_results: dict) -> bool:
24
+ """Check if X source is active (has credentials AND didn't error)."""
25
+ has_creds = _has_x_credentials(config)
26
+ if not has_creds:
27
+ return False
28
+ # If X errored this run, it's configured but broken
29
+ if research_results.get("x_error"):
30
+ return False
31
+ return True
32
+
33
+
34
+ def _has_x_credentials(config: dict) -> bool:
35
+ """Return True when any X/Twitter source credential is configured."""
36
+ return bool(
37
+ config.get("AUTH_TOKEN")
38
+ or config.get("XAI_API_KEY")
39
+ or config.get("XQUIK_API_KEY")
40
+ )
41
+
42
+
43
+ def _has_ytdlp() -> bool:
44
+ """Return True when the local/free YouTube lane is available."""
45
+ try:
46
+ from . import youtube_yt
47
+ return bool(youtube_yt.is_ytdlp_installed())
48
+ except Exception:
49
+ return False
50
+
51
+
52
+ def _youtube_returned_data(research_results: dict) -> bool:
53
+ """Return True when YouTube produced usable items through any provider."""
54
+ videos = int(research_results.get("youtube_videos_count") or 0)
55
+ transcripts = int(research_results.get("youtube_transcripts_count") or 0)
56
+ return videos > 0 or transcripts > 0
57
+
58
+
59
+ def _is_youtube_active(config: dict, research_results: dict, *, has_ytdlp: bool) -> bool:
60
+ """Check if YouTube source is active (yt-dlp installed)."""
61
+ if not has_ytdlp:
62
+ return False
63
+ if research_results.get("youtube_error"):
64
+ return False
65
+ return True
66
+
67
+
68
+ # Below this transcript-fetch ratio, YouTube is considered "degraded" rather
69
+ # than active. Picked at 50% so a single legitimate caption-disabled video in a
70
+ # multi-video result does not trip the nudge, but a stale-yt-dlp run that fails
71
+ # every transcript does. Tunable via DEGRADED_TRANSCRIPT_THRESHOLD env var if
72
+ # operators need to adjust without code changes.
73
+ DEFAULT_DEGRADED_TRANSCRIPT_THRESHOLD = 0.5
74
+
75
+
76
+ def _is_youtube_degraded(research_results: dict, threshold: float) -> bool:
77
+ """YouTube is degraded when videos were returned but the transcript-fetch
78
+ ratio is below threshold. The canonical cause is a stale yt-dlp binary -
79
+ YouTube's caption format changes frequently and old binaries silently fail
80
+ every transcript while the search itself still succeeds.
81
+
82
+ Captions-disabled videos are subtracted from the denominator: an uploader
83
+ who turned off captions can never produce a transcript, so counting that
84
+ video toward "fetch failures" produces false positives. A single
85
+ captions-disabled video in a small result set was tripping the nudge.
86
+
87
+ When actual fetch outcomes are available, they take precedence over the
88
+ post-pruning ratio: the report counts only see items that survived
89
+ freshness/relevance pruning, so a run where every transcript fetch
90
+ succeeded but the fetched videos were later pruned looks identical to a
91
+ stale-binary run (#531). Zero failures across attempted fetches proves
92
+ the binary works - don't flag.
93
+ """
94
+ videos = int(research_results.get("youtube_videos_count") or 0)
95
+ transcripts = int(research_results.get("youtube_transcripts_count") or 0)
96
+ captions_disabled = int(research_results.get("youtube_captions_disabled_count") or 0)
97
+ if videos <= 0:
98
+ return False
99
+ fetch_attempts = int(research_results.get("youtube_transcript_fetch_attempts") or 0)
100
+ fetch_failures = int(research_results.get("youtube_transcript_fetch_failures") or 0)
101
+ if fetch_attempts > 0 and fetch_failures == 0:
102
+ return False
103
+ eligible = videos - captions_disabled
104
+ if eligible <= 0:
105
+ # Every returned video had captions disabled - upstream content fact,
106
+ # not a yt-dlp problem. Don't flag.
107
+ return False
108
+ return (transcripts / eligible) < threshold
109
+
110
+
111
+ def _is_instagram_silent_failure(config: dict, research_results: dict) -> bool:
112
+ """Instagram is silently failing when SC is configured but the source
113
+ returned zero items. The canonical cause is SC's v2 reels endpoint
114
+ 500'ing on multi-token queries (it wraps Google Search and is documented
115
+ to be flaky there). Pre-fix the user got no signal at all - no Instagram
116
+ section in the brief, no error in the footer, just unexplained absence.
117
+ """
118
+ if not config.get("SCRAPECREATORS_API_KEY"):
119
+ return False # not configured — not a silent failure
120
+ # Honor EXCLUDE_SOURCES: a user who set EXCLUDE_SOURCES=instagram
121
+ # intentionally turned the source off, so a zero-item count is
122
+ # expected, not a silent failure. Mirror the canonical parsing
123
+ # pattern from pipeline.available_sources().
124
+ excluded = {
125
+ s.strip().lower()
126
+ for s in (config.get("EXCLUDE_SOURCES") or "").split(",")
127
+ if s.strip()
128
+ }
129
+ # Symmetric case: INCLUDE_SOURCES is an opt-in allowlist. If it is
130
+ # non-empty and does not name instagram, the source was intentionally
131
+ # filtered out, so a zero-item count is expected — not a silent failure.
132
+ included = {
133
+ s.strip().lower()
134
+ for s in (config.get("INCLUDE_SOURCES") or "").split(",")
135
+ if s.strip()
136
+ }
137
+ if "instagram" in excluded or (included and "instagram" not in included):
138
+ return False
139
+ count = research_results.get("instagram_items_count")
140
+ if count is None:
141
+ return False # source not run this invocation
142
+ return int(count) == 0
143
+
144
+
145
+ def compute_quality_score(config: dict, research_results: dict) -> dict:
146
+ """Compute research quality score based on 5 core sources.
147
+
148
+ Args:
149
+ config: Configuration dict from env.get_config()
150
+ research_results: Dict with keys like x_error, youtube_error,
151
+ reddit_error reflecting what happened this run. Optional keys
152
+ ``youtube_videos_count`` and ``youtube_transcripts_count`` enable
153
+ degraded-YouTube detection (transcript-fetch ratio below threshold,
154
+ or fallback/provider data returned without local yt-dlp).
155
+ Optional key ``instagram_items_count`` enables silent-failure
156
+ detection for the bonus Instagram source.
157
+
158
+ Returns:
159
+ {
160
+ "score_pct": 40-100,
161
+ "core_active": ["hn", "polymarket", ...],
162
+ "core_missing": ["x", "youtube"],
163
+ "core_errored": [], # configured but errored at top level
164
+ "core_degraded": [], # configured and returned items but quality below threshold
165
+ "bonus_errored": [], # bonus sources (Instagram, etc.) configured but silent
166
+ "nudge_text": "..." or None if all sources healthy
167
+ }
168
+ """
169
+ core_active: List[str] = []
170
+ core_missing: List[str] = []
171
+ core_errored: List[str] = []
172
+ core_degraded: List[str] = []
173
+ bonus_errored: List[str] = []
174
+
175
+ # HN, Polymarket, and Reddit are always active
176
+ core_active.append("hn")
177
+ core_active.append("polymarket")
178
+ core_active.append("reddit")
179
+
180
+ # X
181
+ has_x_creds = _has_x_credentials(config)
182
+ if _is_x_active(config, research_results):
183
+ core_active.append("x")
184
+ else:
185
+ core_missing.append("x")
186
+ if has_x_creds and research_results.get("x_error"):
187
+ core_errored.append("x")
188
+
189
+ # YouTube
190
+ has_ytdlp = _has_ytdlp()
191
+ yt_active = _is_youtube_active(config, research_results, has_ytdlp=has_ytdlp)
192
+ youtube_returned_data = _youtube_returned_data(research_results)
193
+ if yt_active:
194
+ core_active.append("youtube")
195
+ # Active means yt-dlp is installed and search did not error at the top
196
+ # level. But search-success + transcript-failure is the canonical
197
+ # stale-binary failure mode that the footer used to hide. Flag as
198
+ # degraded so the user gets an actionable nudge to update the binary.
199
+ threshold = float(config.get("DEGRADED_TRANSCRIPT_THRESHOLD") or DEFAULT_DEGRADED_TRANSCRIPT_THRESHOLD)
200
+ if _is_youtube_degraded(research_results, threshold):
201
+ core_degraded.append("youtube")
202
+ elif youtube_returned_data and not research_results.get("youtube_error"):
203
+ # YouTube produced data through a fallback/provider lane even though the
204
+ # local free yt-dlp lane is unavailable. Count the source as present,
205
+ # but surface it as degraded so users do not see the contradictory
206
+ # "Missing: YouTube" ending after a report with YouTube evidence.
207
+ # has_ytdlp is provably False here: yt_active is False and youtube_error
208
+ # is excluded by this guard, leaving unavailable yt-dlp as the cause.
209
+ core_active.append("youtube")
210
+ core_degraded.append("youtube")
211
+ else:
212
+ core_missing.append("youtube")
213
+ # Check if configured but errored (yt-dlp installed but failed this run)
214
+ if has_ytdlp and research_results.get("youtube_error"):
215
+ core_errored.append("youtube")
216
+
217
+ # Bonus sources (Instagram, etc.): SC-key holders expect content from
218
+ # these but until now the pipeline fell silent on configured-but-zero.
219
+ if _is_instagram_silent_failure(config, research_results):
220
+ bonus_errored.append("instagram")
221
+
222
+ score_pct = int(len(core_active) / 5 * 100)
223
+
224
+ has_sc = bool(config.get("SCRAPECREATORS_API_KEY"))
225
+ active_sources = research_results.get("active_sources") or []
226
+ nudge_text = _build_nudge_text(
227
+ core_missing,
228
+ core_errored,
229
+ core_degraded,
230
+ research_results,
231
+ has_sc=has_sc,
232
+ active_sources=active_sources,
233
+ bonus_errored=bonus_errored,
234
+ has_ytdlp=has_ytdlp,
235
+ ) if (core_missing or core_degraded or bonus_errored) else None
236
+
237
+ return {
238
+ "score_pct": score_pct,
239
+ "core_active": core_active,
240
+ "core_missing": core_missing,
241
+ "core_errored": core_errored,
242
+ "core_degraded": core_degraded,
243
+ "bonus_errored": bonus_errored,
244
+ "nudge_text": nudge_text,
245
+ }
246
+
247
+
248
+ def _build_nudge_text(
249
+ core_missing: List[str],
250
+ core_errored: List[str],
251
+ core_degraded: List[str] = None,
252
+ research_results: dict = None,
253
+ has_sc: bool = False,
254
+ active_sources: list = None,
255
+ bonus_errored: List[str] = None,
256
+ has_ytdlp: bool = False,
257
+ ) -> str:
258
+ """Build human-readable nudge text describing what was missed or degraded.
259
+
260
+ Prioritizes free suggestions. Optionally mentions bonus sources
261
+ (TikTok, Instagram, Threads, Pinterest) if ScrapeCreators key is configured.
262
+ """
263
+ lines: List[str] = []
264
+ core_degraded = core_degraded or []
265
+ bonus_errored = bonus_errored or []
266
+ research_results = research_results or {}
267
+
268
+ # Describe what was missed
269
+ missed_parts: List[str] = []
270
+ for src in core_missing:
271
+ label = SOURCE_LABELS[src]
272
+ if src in core_errored:
273
+ missed_parts.append(f"{label} (errored this run)")
274
+ else:
275
+ missed_parts.append(label)
276
+
277
+ active_count = 5 - len(core_missing)
278
+ lines.append(f"Research quality: {active_count}/5 core sources.")
279
+ if missed_parts:
280
+ lines.append(f"Missing: {', '.join(missed_parts)}.")
281
+ if core_degraded:
282
+ degraded_labels = ", ".join(SOURCE_LABELS[s] for s in core_degraded)
283
+ lines.append(f"Degraded: {degraded_labels}.")
284
+ if bonus_errored:
285
+ bonus_labels = ", ".join(s.capitalize() for s in bonus_errored)
286
+ lines.append(f"Bonus source silent: {bonus_labels}.")
287
+ lines.append("")
288
+
289
+ # Free suggestions
290
+ free_suggestions: List[str] = []
291
+
292
+ if "x" in core_missing:
293
+ if "x" in core_errored:
294
+ free_suggestions.append(
295
+ "X/Twitter errored - log into x.com in your browser, then re-run."
296
+ )
297
+ else:
298
+ free_suggestions.append(
299
+ "X/Twitter: real-time posts with likes and reposts - the fastest "
300
+ "signal for breaking topics. Three options: log into x.com in your "
301
+ "browser and re-run (cookies detected automatically), or add "
302
+ "XAI_API_KEY to your .env (get key at api.x.ai), or add "
303
+ "XQUIK_API_KEY to your .env (get key at xquik.com)."
304
+ )
305
+
306
+ if "youtube" in core_missing:
307
+ if "youtube" in core_errored:
308
+ free_suggestions.append(
309
+ "YouTube errored - update yt-dlp: brew upgrade yt-dlp"
310
+ )
311
+ else:
312
+ free_suggestions.append(
313
+ "YouTube: video transcripts with key moments - often the deepest "
314
+ "explanations on any topic. Install yt-dlp: brew install yt-dlp (free)"
315
+ )
316
+
317
+ if "youtube" in core_degraded:
318
+ videos = int(research_results.get("youtube_videos_count") or 0)
319
+ transcripts = int(research_results.get("youtube_transcripts_count") or 0)
320
+ captions_disabled = int(research_results.get("youtube_captions_disabled_count") or 0)
321
+ if not has_ytdlp and _youtube_returned_data(research_results):
322
+ free_suggestions.append(
323
+ f"YouTube returned {videos} videos and {transcripts} transcripts "
324
+ "through a fallback/provider path, but local yt-dlp is not "
325
+ "installed. Install yt-dlp to enable the free local YouTube lane "
326
+ "and reduce reliance on fallback providers: brew install yt-dlp "
327
+ "(macOS), scoop install yt-dlp (Windows), or pip install -U yt-dlp."
328
+ )
329
+ else:
330
+ captions_note = ""
331
+ if captions_disabled > 0:
332
+ captions_note = (
333
+ f" ({captions_disabled} of those had captions disabled by the "
334
+ "uploader, which is a separate cause and not fixable on your end)"
335
+ )
336
+ free_suggestions.append(
337
+ f"YouTube returned {videos} videos but only {transcripts} transcripts "
338
+ f"captured{captions_note}. The most common remaining cause is a stale "
339
+ "yt-dlp binary - YouTube's caption format changes frequently and old "
340
+ "binaries silently fail every transcript. Update via your package "
341
+ "manager: scoop update yt-dlp (Windows), brew upgrade yt-dlp (macOS), "
342
+ "or pip install -U yt-dlp."
343
+ )
344
+
345
+ if "instagram" in bonus_errored:
346
+ free_suggestions.append(
347
+ "Instagram returned 0 reels despite SC being configured. SC's "
348
+ "v2 reels endpoint wraps Google Search and 500's frequently on "
349
+ "multi-token queries. The skill now retries with hashtag-form "
350
+ "automatically; if zero items still appear, the topic may have "
351
+ "no reel coverage on Instagram. Try a single-word topic like "
352
+ "the most distinctive noun in your query."
353
+ )
354
+
355
+ # Mention bonus opt-in sources when SC key is present
356
+ if has_sc:
357
+ bonus_hints = []
358
+ if "threads" not in (active_sources or []):
359
+ bonus_hints.append("Threads")
360
+ if "pinterest" not in (active_sources or []):
361
+ bonus_hints.append("Pinterest")
362
+ if bonus_hints:
363
+ free_suggestions.append(
364
+ f"Your SC key also powers {', '.join(bonus_hints)} and YouTube comments. "
365
+ "Add them to INCLUDE_SOURCES in your .env to enable."
366
+ )
367
+
368
+ if free_suggestions:
369
+ lines.append("Free fixes:")
370
+ for s in free_suggestions:
371
+ lines.append(f" - {s}")
372
+ lines.append("")
373
+
374
+ # Bonus sources mention (non-blocking)
375
+ if not has_sc:
376
+ lines.append(
377
+ "Bonus: TikTok and Instagram are available with a free "
378
+ "ScrapeCreators key at scrapecreators.com (no affiliation)."
379
+ )
380
+ else:
381
+ lines.append("last30days has no affiliation with any API provider.")
382
+
383
+ return "\n".join(lines)
@@ -0,0 +1,202 @@
1
+ """Shared query preprocessing utilities: noise-word stripping, core subject
2
+ extraction, and compound term detection. Used by all search modules."""
3
+
4
+ import re
5
+ from typing import FrozenSet, List, Optional, Set
6
+
7
+ # Common multi-word prefixes stripped from all queries (identical across modules)
8
+ PREFIXES = [
9
+ 'what are the best', 'what is the best', 'what are the latest',
10
+ 'what are people saying about', 'what do people think about',
11
+ 'how do i use', 'how to use', 'how to',
12
+ 'what are', 'what is', 'tips for', 'best practices for',
13
+ # Hebrew question/meta prefixes
14
+ 'מה יש חדש ב', 'מה יש חדש על', 'מה אנשים אומרים על',
15
+ 'מה חדש ב', 'מה חדש על', 'איך להשתמש ב',
16
+ 'מהם המוצרים של', 'מה הם', 'מהם',
17
+ ]
18
+
19
+ # Multi-word suffixes (used by bird_x)
20
+ SUFFIXES = [
21
+ 'best practices', 'use cases', 'prompt techniques',
22
+ 'prompting techniques', 'prompting tips',
23
+ ]
24
+
25
+ # Base noise words shared across most modules
26
+ NOISE_WORDS = frozenset({
27
+ # Articles/prepositions/conjunctions
28
+ 'a', 'an', 'the', 'is', 'are', 'was', 'were', 'and', 'or',
29
+ 'of', 'in', 'on', 'for', 'with', 'about', 'to',
30
+ # Question words
31
+ 'how', 'what', 'which', 'who', 'why', 'when', 'where',
32
+ 'does', 'should', 'could', 'would',
33
+ # Research/meta descriptors
34
+ 'best', 'top', 'good', 'great', 'awesome', 'killer',
35
+ 'latest', 'new', 'news', 'update', 'updates',
36
+ 'trendiest', 'trending', 'hottest', 'hot', 'popular', 'viral',
37
+ 'practices', 'features', 'guide', 'tutorial',
38
+ 'recommendations', 'advice', 'review', 'reviews',
39
+ 'usecases', 'examples', 'comparison', 'versus', 'vs',
40
+ 'plugin', 'plugins', 'skill', 'skills', 'tool', 'tools',
41
+ # Prompting meta words
42
+ 'prompt', 'prompts', 'prompting', 'techniques', 'tips',
43
+ 'tricks', 'methods', 'strategies', 'approaches',
44
+ # Action words
45
+ 'using', 'uses', 'use',
46
+ # Misc filler
47
+ 'people', 'saying', 'think', 'said', 'lately',
48
+ # Hebrew function words / prepositions / filler
49
+ 'מה', 'מי', 'איך', 'למה', 'איפה', 'מתי', 'כמה', 'האם',
50
+ 'של', 'על', 'עם', 'אל', 'את', 'בין', 'כי', 'כן', 'לא',
51
+ 'יש', 'אין', 'כבר', 'רק', 'גם', 'אבל', 'כך', 'זה', 'זו',
52
+ 'חדש', 'חדשים', 'טוב', 'טובים', 'הכי', 'ביותר',
53
+ 'מוצרים', 'מבצע', 'מבצעים', 'חדשות', 'עדכונים',
54
+ })
55
+
56
+
57
+ # Shared noise sets for adapter `_extract_core_subject` wrappers.
58
+ #
59
+ # SOCIAL_NOISE: short-form micro-social platforms (Bluesky, Threads, Truth Social)
60
+ # where research/meta words rarely appear in the body of a post.
61
+ SOCIAL_NOISE = frozenset({
62
+ 'best', 'top', 'good', 'great', 'awesome',
63
+ 'latest', 'new', 'news', 'update', 'updates',
64
+ 'trending', 'hottest', 'popular', 'viral',
65
+ 'practices', 'features', 'recommendations', 'advice',
66
+ 'or', 'and',
67
+ })
68
+
69
+ # VIRAL_NOISE: viral / discovery platforms (TikTok, Instagram, Pinterest) and
70
+ # the base for YouTube. Adds 'killer', the prompt-meta cluster, and the
71
+ # methodology cluster on top of SOCIAL_NOISE.
72
+ VIRAL_NOISE = SOCIAL_NOISE | frozenset({
73
+ 'killer',
74
+ 'prompt', 'prompts', 'prompting',
75
+ 'methods', 'strategies', 'approaches',
76
+ })
77
+
78
+
79
+ def extract_core_subject(
80
+ topic: str,
81
+ *,
82
+ noise: Optional[FrozenSet[str]] = None,
83
+ max_words: Optional[int] = None,
84
+ strip_suffixes: bool = False,
85
+ ) -> str:
86
+ """Extract core subject from a verbose search query.
87
+
88
+ Strips common question/meta prefixes and noise words to produce a
89
+ compact search-friendly query. Platforms customize via parameters.
90
+
91
+ Args:
92
+ topic: Raw user query
93
+ noise: Override noise word set (default: NOISE_WORDS)
94
+ max_words: Cap result to N words (default: no cap)
95
+ strip_suffixes: Also strip trailing multi-word suffixes (bird_x uses this)
96
+
97
+ Returns:
98
+ Cleaned query string
99
+ """
100
+ text = topic.lower().strip()
101
+ if not text:
102
+ return text
103
+
104
+ # Phase 1: Strip multi-word prefixes (longest first, stop after first match)
105
+ for p in PREFIXES:
106
+ if text.startswith(p + ' '):
107
+ text = text[len(p):].strip()
108
+ break
109
+
110
+ # Phase 2: Strip multi-word suffixes (opt-in)
111
+ if strip_suffixes:
112
+ for s in SUFFIXES:
113
+ if text.endswith(' ' + s):
114
+ text = text[:-len(s)].strip()
115
+ break
116
+
117
+ # Phase 3: Filter individual noise words
118
+ noise_set = noise if noise is not None else NOISE_WORDS
119
+ words = text.split()
120
+ filtered = [w for w in words if w not in noise_set]
121
+
122
+ # Apply word cap if requested
123
+ if max_words is not None and filtered:
124
+ filtered = filtered[:max_words]
125
+
126
+ result = ' '.join(filtered) if filtered else text
127
+ return result.rstrip('?!.') if not max_words else (result or topic.lower().strip())
128
+
129
+
130
+ def infer_query_intent(topic: str) -> str:
131
+ """Classify a topic into a coarse intent for adapter query expansion.
132
+
133
+ Returns one of: ``comparison``, ``how_to``, ``opinion``, ``product``,
134
+ ``prediction``, ``breaking_news`` (default).
135
+
136
+ The ``how_to`` regex covers both prefixed forms (``how to install``)
137
+ and bare imperatives (``configure``, ``troubleshoot``, ``debug``,
138
+ ``fix``). Adapters that previously kept their own copy of this
139
+ classifier had drifted to subtly different word lists; this is the
140
+ superset.
141
+
142
+ Polymarket keeps a custom narrower classifier (prediction-only) and
143
+ does NOT delegate here; its expansion only needs that signal.
144
+ """
145
+ text = topic.lower().strip()
146
+ if re.search(r"\b(vs|versus|compare|difference between)\b", text):
147
+ return "comparison"
148
+ if re.search(
149
+ r"\b(how to|tutorial|guide|setup|step by step|deploy|install|"
150
+ r"configuration|configure|troubleshoot|troubleshooting|error|errors|"
151
+ r"fix|debug)\b",
152
+ text,
153
+ ):
154
+ return "how_to"
155
+ if re.search(r"\b(thoughts on|worth it|should i|opinion|review)\b", text):
156
+ return "opinion"
157
+ if re.search(r"\b(pricing|feature|features|best .* for)\b", text):
158
+ return "product"
159
+ if re.search(r"\b(predict|prediction|odds|forecast|chance)\b", text):
160
+ return "prediction"
161
+ return "breaking_news"
162
+
163
+
164
+ def extract_compound_terms(topic: str) -> List[str]:
165
+ """Detect multi-word terms that should be quoted in search queries.
166
+
167
+ Identifies:
168
+ - Hyphenated terms: "multi-agent", "vc-backed"
169
+ - Title-cased multi-word names: "Claude Code", "React Native"
170
+
171
+ Returns list of terms suitable for quoting (e.g., '"multi-agent"').
172
+ """
173
+ terms: List[str] = []
174
+
175
+ # Hyphenated terms
176
+ for match in re.finditer(r'\b\w+-\w+(?:-\w+)*\b', topic):
177
+ terms.append(match.group())
178
+
179
+ # Title-cased sequences (2+ capitalized words in a row)
180
+ for match in re.finditer(r'(?:[A-Z][a-z]+\s+){1,}[A-Z][a-z]+', topic):
181
+ terms.append(match.group())
182
+
183
+ return terms
184
+
185
+
186
+ def leading_mentions(text: Optional[str]) -> List[str]:
187
+ """Return the handles a post is directed at: the leading run of @mentions in the text.
188
+
189
+ X replies open with the target handle(s) (e.g. "@someone thanks!"), so the
190
+ leading run identifies who the post is addressed to. A mention later in the
191
+ body is not a reply target and is intentionally ignored. Returns normalized
192
+ (``@``-stripped, lowercased) handles, in order. Shared by every X-shaped
193
+ source adapter (bird, xquik) so leading-mention parsing has one definition.
194
+ """
195
+ out: List[str] = []
196
+ for token in (text or "").split():
197
+ tok = token.strip(",.:;!?")
198
+ if tok.startswith("@") and len(tok) > 1:
199
+ out.append(tok[1:].lower())
200
+ else:
201
+ break
202
+ return out