luckiest-co 1.0.47 → 1.0.48

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 (264) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/package.json +1 -1
  4. package/skills/ab-testing/CHANGELOG.md +5 -0
  5. package/skills/ab-testing/SKILL.md +12 -9
  6. package/skills/ab-testing/evals/evals.json +18 -7
  7. package/skills/ab-testing/references/sample-size-guide.md +2 -2
  8. package/skills/ads/CHANGELOG.md +5 -0
  9. package/skills/ads/SKILL.md +4 -4
  10. package/skills/ai-seo/CHANGELOG.md +7 -0
  11. package/skills/ai-seo/SKILL.md +27 -20
  12. package/skills/analytics/CHANGELOG.md +6 -0
  13. package/skills/analytics/SKILL.md +4 -3
  14. package/skills/analytics/evals/evals.json +27 -0
  15. package/skills/analytics/references/ga4-implementation.md +7 -3
  16. package/skills/analytics/references/gtm-implementation.md +8 -2
  17. package/skills/aso/CHANGELOG.md +5 -0
  18. package/skills/aso/SKILL.md +4 -4
  19. package/skills/aso/evals/evals.json +15 -2
  20. package/skills/aso/references/benchmarks.md +4 -2
  21. package/skills/aso/references/google-play-specs.md +5 -1
  22. package/skills/brainstorm/SKILL.md +59 -16
  23. package/skills/brainstorm/builder-check-prompt.md +23 -0
  24. package/skills/churn-prevention/CHANGELOG.md +5 -0
  25. package/skills/churn-prevention/SKILL.md +3 -3
  26. package/skills/churn-prevention/evals/evals.json +14 -0
  27. package/skills/churn-prevention/references/dunning-playbook.md +6 -1
  28. package/skills/coder-brainstorming/CHANGELOG.md +10 -0
  29. package/skills/coder-brainstorming/SKILL.md +62 -20
  30. package/skills/coder-brainstorming/builder-check-prompt.md +23 -0
  31. package/skills/coder-brainstorming/scripts/server.cjs +1 -1
  32. package/skills/coder-debugging/CHANGELOG.md +4 -0
  33. package/skills/coder-debugging/SKILL.md +5 -5
  34. package/skills/coder-requesting-code-review/CHANGELOG.md +4 -0
  35. package/skills/coder-requesting-code-review/SKILL.md +4 -4
  36. package/skills/coder-subagent-driven-development/CHANGELOG.md +4 -0
  37. package/skills/coder-subagent-driven-development/SKILL.md +3 -3
  38. package/skills/coder-subagent-driven-development/scripts/sdd-workspace +3 -1
  39. package/skills/cold-email/CHANGELOG.md +7 -0
  40. package/skills/cold-email/SKILL.md +27 -7
  41. package/skills/cold-email/evals/evals.json +30 -0
  42. package/skills/cold-email/references/benchmarks.md +15 -11
  43. package/skills/cold-email/references/deliverability.md +110 -0
  44. package/skills/cold-email/references/linkedin-outreach.md +91 -0
  45. package/skills/cold-email/references/multichannel-cadence.md +79 -0
  46. package/skills/cold-email/references/outbound-plays.md +88 -0
  47. package/skills/cold-email/references/personalization.md +11 -0
  48. package/skills/cold-email/references/reply-handling.md +65 -0
  49. package/skills/competitor-profiling/CHANGELOG.md +5 -0
  50. package/skills/competitor-profiling/SKILL.md +4 -4
  51. package/skills/content-strategy/CHANGELOG.md +5 -0
  52. package/skills/content-strategy/SKILL.md +5 -3
  53. package/skills/copy-editing/CHANGELOG.md +5 -0
  54. package/skills/copy-editing/SKILL.md +5 -5
  55. package/skills/copy-editing/references/content-refresh.md +33 -0
  56. package/skills/cro/CHANGELOG.md +5 -0
  57. package/skills/cro/SKILL.md +14 -3
  58. package/skills/cro/references/form.md +1 -1
  59. package/skills/directory-submissions/CHANGELOG.md +5 -0
  60. package/skills/directory-submissions/SKILL.md +13 -4
  61. package/skills/directory-submissions/evals/evals.json +15 -1
  62. package/skills/directory-submissions/references/directory-list.md +2 -4
  63. package/skills/emails/CHANGELOG.md +5 -0
  64. package/skills/emails/SKILL.md +14 -4
  65. package/skills/launch/CHANGELOG.md +7 -0
  66. package/skills/launch/SKILL.md +8 -4
  67. package/skills/launch/evals/evals.json +29 -0
  68. package/skills/launch/references/shipped-changes.md +84 -0
  69. package/skills/launch/references/site-launch-qa.md +55 -0
  70. package/skills/lead-magnets/CHANGELOG.md +5 -0
  71. package/skills/lead-magnets/SKILL.md +6 -4
  72. package/skills/lead-magnets/evals/evals.json +18 -0
  73. package/skills/lead-magnets/references/content-to-skill-corpus-design.md +89 -0
  74. package/skills/lead-magnets/references/content-to-skill-release.md +71 -0
  75. package/skills/lead-magnets/references/content-to-skill.md +108 -0
  76. package/skills/marketing-plan/CHANGELOG.md +5 -0
  77. package/skills/marketing-plan/SKILL.md +3 -3
  78. package/skills/marketing-plan/evals/evals.json +13 -0
  79. package/skills/marketing-plan/references/budget-planning.md +26 -17
  80. package/skills/pricing/CHANGELOG.md +5 -0
  81. package/skills/pricing/SKILL.md +4 -4
  82. package/skills/pricing/evals/evals.json +12 -0
  83. package/skills/pricing/references/research-methods.md +8 -4
  84. package/skills/programmatic-seo/CHANGELOG.md +5 -0
  85. package/skills/programmatic-seo/SKILL.md +8 -4
  86. package/skills/programmatic-seo/evals/evals.json +13 -0
  87. package/skills/programmatic-seo/references/implementation-platforms.md +37 -0
  88. package/skills/prospecting/CHANGELOG.md +7 -0
  89. package/skills/prospecting/SKILL.md +27 -13
  90. package/skills/prospecting/evals/evals.json +41 -0
  91. package/skills/prospecting/references/account-research.md +59 -0
  92. package/skills/prospecting/references/b2b-prospecting.md +1 -1
  93. package/skills/prospecting/references/compliance.md +44 -6
  94. package/skills/prospecting/references/data-sources.md +13 -15
  95. package/skills/prospecting/references/enrichment-playbook.md +61 -0
  96. package/skills/prospecting/references/saas-prospecting.md +1 -1
  97. package/skills/prospecting/references/signal-plays.md +99 -0
  98. package/skills/prospecting/references/sourcing-and-enrichment.md +89 -0
  99. package/skills/referrals/CHANGELOG.md +5 -0
  100. package/skills/referrals/SKILL.md +10 -4
  101. package/skills/referrals/evals/evals.json +99 -0
  102. package/skills/referrals/references/affiliate-operations.md +64 -0
  103. package/skills/referrals/references/affiliate-programs.md +2 -2
  104. package/skills/referrals/references/program-examples.md +14 -6
  105. package/skills/referrals/references/review-platform-rules.md +36 -0
  106. package/skills/referrals/references/review-program-operations.md +62 -0
  107. package/skills/referrals/references/review-programs.md +96 -0
  108. package/skills/revops/CHANGELOG.md +5 -0
  109. package/skills/revops/SKILL.md +10 -6
  110. package/skills/revops/evals/evals.json +13 -0
  111. package/skills/revops/references/automation-playbooks.md +1 -1
  112. package/skills/revops/references/inbound-routing.md +43 -0
  113. package/skills/revops/references/lifecycle-definitions.md +31 -0
  114. package/skills/sales-enablement/CHANGELOG.md +5 -0
  115. package/skills/sales-enablement/SKILL.md +6 -4
  116. package/skills/sales-enablement/evals/evals.json +14 -0
  117. package/skills/sales-enablement/references/cold-call-scripts.md +68 -0
  118. package/skills/schema/CHANGELOG.md +5 -0
  119. package/skills/schema/SKILL.md +20 -8
  120. package/skills/schema/evals/evals.json +40 -0
  121. package/skills/schema/references/schema-examples.md +9 -15
  122. package/skills/seo-audit/CHANGELOG.md +5 -0
  123. package/skills/seo-audit/SKILL.md +10 -16
  124. package/skills/seo-audit/evals/evals.json +68 -0
  125. package/skills/seo-audit/references/international-seo.md +9 -11
  126. package/skills/seo-audit/references/local-seo-pages-and-measurement.md +39 -0
  127. package/skills/seo-audit/references/local-seo-profile-and-citations.md +41 -0
  128. package/skills/seo-audit/references/local-seo.md +86 -0
  129. package/skills/seo-audit/references/rankings-push.md +62 -0
  130. package/skills/seo-audit/references/title-tags.md +89 -0
  131. package/skills/signup/CHANGELOG.md +5 -0
  132. package/skills/signup/SKILL.md +7 -3
  133. package/skills/site-architecture/CHANGELOG.md +5 -0
  134. package/skills/site-architecture/SKILL.md +5 -4
  135. package/skills/site-architecture/evals/evals.json +25 -0
  136. package/skills/site-architecture/references/platforms-and-migration.md +84 -0
  137. package/skills/social/CHANGELOG.md +5 -0
  138. package/skills/social/SKILL.md +4 -4
  139. package/skills/trends/.skillignore +3 -0
  140. package/skills/trends/CHANGELOG.md +20 -0
  141. package/skills/trends/SKILL.md +12 -8
  142. package/skills/trends/references/agent-mode.md +36 -0
  143. package/skills/trends/references/category-peers.md +38 -0
  144. package/skills/trends/references/comparison.md +227 -0
  145. package/skills/trends/references/competitors.md +29 -0
  146. package/skills/trends/references/discovery.md +90 -0
  147. package/skills/trends/references/engine-contract.md +111 -1889
  148. package/skills/trends/references/followups.md +112 -0
  149. package/skills/trends/references/grok-bot-x.md +55 -0
  150. package/skills/trends/references/hiring-signals.md +19 -0
  151. package/skills/trends/references/library-queue.md +33 -0
  152. package/skills/trends/references/recommendations.md +86 -0
  153. package/skills/trends/references/research-runbook.md +781 -0
  154. package/skills/trends/references/runtime.md +165 -0
  155. package/skills/trends/references/save-html-brief.md +39 -20
  156. package/skills/trends/references/setup-wizard.md +253 -0
  157. package/skills/trends/references/synthesis.md +289 -0
  158. package/skills/trends/scripts/box_chrome_login.py +209 -0
  159. package/skills/trends/scripts/briefing.py +9 -17
  160. package/skills/trends/scripts/last30days.py +3247 -280
  161. package/skills/trends/scripts/lib/agentcookie.py +196 -0
  162. package/skills/trends/scripts/lib/amazon.py +877 -0
  163. package/skills/trends/scripts/lib/arxiv.py +42 -8
  164. package/skills/trends/scripts/lib/backends.py +769 -0
  165. package/skills/trends/scripts/lib/bird_x.py +340 -57
  166. package/skills/trends/scripts/lib/bluesky.py +84 -10
  167. package/skills/trends/scripts/lib/bounded_get.py +156 -0
  168. package/skills/trends/scripts/lib/brightdata.py +291 -0
  169. package/skills/trends/scripts/lib/categories.py +7 -1
  170. package/skills/trends/scripts/lib/chrome_cdp.py +455 -0
  171. package/skills/trends/scripts/lib/chrome_cookies.py +132 -39
  172. package/skills/trends/scripts/lib/cluster.py +31 -54
  173. package/skills/trends/scripts/lib/competitors.py +10 -1
  174. package/skills/trends/scripts/lib/cookie_extract.py +221 -44
  175. package/skills/trends/scripts/lib/cookie_paths.py +27 -0
  176. package/skills/trends/scripts/lib/corpus.py +439 -0
  177. package/skills/trends/scripts/lib/devto.py +313 -0
  178. package/skills/trends/scripts/lib/discovery_handoff.py +988 -0
  179. package/skills/trends/scripts/lib/doctor.py +2166 -0
  180. package/skills/trends/scripts/lib/dripstack.py +203 -0
  181. package/skills/trends/scripts/lib/entity_extract.py +37 -0
  182. package/skills/trends/scripts/lib/env.py +1092 -138
  183. package/skills/trends/scripts/lib/fanout.py +11 -1
  184. package/skills/trends/scripts/lib/feed.py +61 -0
  185. package/skills/trends/scripts/lib/fetch_memo.py +135 -0
  186. package/skills/trends/scripts/lib/freshness.py +566 -0
  187. package/skills/trends/scripts/lib/fusion.py +314 -28
  188. package/skills/trends/scripts/lib/github.py +438 -24
  189. package/skills/trends/scripts/lib/grok_x.py +1237 -0
  190. package/skills/trends/scripts/lib/grounding.py +129 -11
  191. package/skills/trends/scripts/lib/hackernews.py +61 -4
  192. package/skills/trends/scripts/lib/health.py +373 -0
  193. package/skills/trends/scripts/lib/hosted.py +333 -0
  194. package/skills/trends/scripts/lib/html_publish.py +34 -0
  195. package/skills/trends/scripts/lib/html_render.py +169 -3
  196. package/skills/trends/scripts/lib/http.py +1215 -70
  197. package/skills/trends/scripts/lib/instagram.py +132 -9
  198. package/skills/trends/scripts/lib/jobs.py +4 -2
  199. package/skills/trends/scripts/lib/library.py +308 -0
  200. package/skills/trends/scripts/lib/library_index.py +477 -0
  201. package/skills/trends/scripts/lib/linkedin.py +271 -24
  202. package/skills/trends/scripts/lib/log.py +5 -2
  203. package/skills/trends/scripts/lib/meta_ads.py +982 -0
  204. package/skills/trends/scripts/lib/normalize.py +382 -28
  205. package/skills/trends/scripts/lib/parallel_mcp.py +234 -0
  206. package/skills/trends/scripts/lib/permission_preflight.py +42 -3
  207. package/skills/trends/scripts/lib/perplexity.py +1080 -468
  208. package/skills/trends/scripts/lib/pipeline.py +5079 -211
  209. package/skills/trends/scripts/lib/planner.py +396 -53
  210. package/skills/trends/scripts/lib/polymarket.py +285 -23
  211. package/skills/trends/scripts/lib/prescriptions.py +432 -0
  212. package/skills/trends/scripts/lib/private_files.py +21 -0
  213. package/skills/trends/scripts/lib/providers.py +231 -10
  214. package/skills/trends/scripts/lib/quality_nudge.py +122 -37
  215. package/skills/trends/scripts/lib/reddit.py +177 -12
  216. package/skills/trends/scripts/lib/reddit_arctic.py +146 -5
  217. package/skills/trends/scripts/lib/reddit_keyless.py +121 -60
  218. package/skills/trends/scripts/lib/reddit_listing.py +215 -14
  219. package/skills/trends/scripts/lib/reddit_public.py +12 -13
  220. package/skills/trends/scripts/lib/reddit_search.py +304 -0
  221. package/skills/trends/scripts/lib/reddit_shreddit.py +51 -7
  222. package/skills/trends/scripts/lib/registers.py +134 -0
  223. package/skills/trends/scripts/lib/relevance.py +17 -0
  224. package/skills/trends/scripts/lib/render.py +2161 -271
  225. package/skills/trends/scripts/lib/rerank.py +623 -55
  226. package/skills/trends/scripts/lib/resolve.py +50 -1
  227. package/skills/trends/scripts/lib/safari_cookies.py +42 -15
  228. package/skills/trends/scripts/lib/schema.py +782 -1
  229. package/skills/trends/scripts/lib/setup_wizard.py +779 -120
  230. package/skills/trends/scripts/lib/signals.py +206 -7
  231. package/skills/trends/scripts/lib/stocktwits.py +374 -0
  232. package/skills/trends/scripts/lib/subproc.py +307 -53
  233. package/skills/trends/scripts/lib/techmeme.py +89 -64
  234. package/skills/trends/scripts/lib/telegram.py +317 -0
  235. package/skills/trends/scripts/lib/tiktok.py +13 -9
  236. package/skills/trends/scripts/lib/topic_shape.py +340 -0
  237. package/skills/trends/scripts/lib/transcribe.py +12 -3
  238. package/skills/trends/scripts/lib/trustpilot.py +256 -5
  239. package/skills/trends/scripts/lib/truthsocial.py +9 -1
  240. package/skills/trends/scripts/lib/ui.py +6 -0
  241. package/skills/trends/scripts/lib/usage.py +132 -0
  242. package/skills/trends/scripts/lib/web_search_keyless.py +63 -4
  243. package/skills/trends/scripts/lib/windows_job.py +138 -0
  244. package/skills/trends/scripts/lib/x_api.py +824 -0
  245. package/skills/trends/scripts/lib/x_envelope.py +733 -0
  246. package/skills/trends/scripts/lib/x_judge.py +292 -0
  247. package/skills/trends/scripts/lib/xai_x.py +26 -3
  248. package/skills/trends/scripts/lib/xquik.py +89 -15
  249. package/skills/trends/scripts/lib/xurl_x.py +284 -91
  250. package/skills/trends/scripts/lib/youtube_yt.py +570 -119
  251. package/skills/trends/scripts/setup-keychain.sh +12 -4
  252. package/skills/trends/scripts/setup-pass.sh +3 -0
  253. package/skills/trends/scripts/store.py +444 -50
  254. package/skills/trends/scripts/watchlist.py +38 -11
  255. package/skills/trends/scripts/x_lane_parity.py +107 -0
  256. package/skills/video-studio/CHANGELOG.md +4 -0
  257. package/skills/video-studio/SKILL.md +4 -4
  258. package/skills/video-studio/references/styles/product-flight.md +45 -0
  259. package/skills/video-studio/references/styles.md +3 -1
  260. package/skills/video-studio-motion/ATTRIBUTION.md +1 -1
  261. package/skills/video-studio-motion/CHANGELOG.md +4 -0
  262. package/skills/video-studio-motion/SKILL.md +8 -5
  263. package/skills/coder-brainstorming/spec-document-reviewer-prompt.md +0 -49
  264. package/skills/trends/scripts/lib/reddit_rss.py +0 -224
@@ -5,9 +5,11 @@ from __future__ import annotations
5
5
 
6
6
  import argparse
7
7
  import json
8
+ import os
8
9
  import subprocess
9
10
  import sys
10
11
  import time
12
+ import tempfile
11
13
  import urllib.parse
12
14
  from pathlib import Path
13
15
 
@@ -15,7 +17,7 @@ SCRIPT_DIR = Path(__file__).parent.resolve()
15
17
  sys.path.insert(0, str(SCRIPT_DIR))
16
18
 
17
19
  import store
18
- from lib import http, schema
20
+ from lib import env as envlib, http, schema, usage
19
21
 
20
22
 
21
23
  # --- Webhook Delivery Functions ---
@@ -121,6 +123,7 @@ def cmd_list(args):
121
123
  "topics": topics,
122
124
  "budget_used": budget_used,
123
125
  "budget_limit": budget_limit,
126
+ "budget_unknown_runs": store.get_daily_unknown_cost_runs(),
124
127
  }, default=str))
125
128
 
126
129
 
@@ -137,7 +140,7 @@ def cmd_run_one(args):
137
140
  if not topic:
138
141
  print(json.dumps({"error": f'Topic not found: "{args.topic}"'}))
139
142
  sys.exit(1)
140
- print(json.dumps(_run_topic(topic), default=str))
143
+ print(json.dumps(_budget_skip(topic) or _run_topic(topic), default=str))
141
144
 
142
145
 
143
146
  def cmd_run_all(args):
@@ -150,27 +153,49 @@ def cmd_run_all(args):
150
153
  budget_limit = float(store.get_setting("daily_budget", "5.00"))
151
154
  results = []
152
155
  for topic in topics:
153
- if store.get_daily_cost() >= budget_limit:
154
- results.append({
155
- "topic": topic["name"],
156
- "status": "skipped",
157
- "reason": f"Budget exceeded: ${store.get_daily_cost():.2f}/${budget_limit:.2f}",
158
- })
159
- continue
160
- results.append(_run_topic(topic))
156
+ results.append(_budget_skip(topic) or _run_topic(topic))
161
157
 
162
158
  print(json.dumps({
163
159
  "action": "run_all",
164
160
  "results": results,
165
161
  "budget_used": store.get_daily_cost(),
166
162
  "budget_limit": budget_limit,
163
+ "budget_unknown_runs": store.get_daily_unknown_cost_runs(),
167
164
  }, default=str))
168
165
 
169
166
 
167
+ def _budget_skip(topic: dict) -> dict | None:
168
+ limit = float(store.get_setting("daily_budget", "5.00"))
169
+ cost = store.get_daily_cost()
170
+ unknown = store.get_daily_unknown_cost_runs()
171
+ if cost >= limit:
172
+ reason = f"Budget exceeded: ${cost:.2f}/${limit:.2f}"
173
+ elif unknown:
174
+ reason = f"Budget unknown: {unknown} run(s) today have unreported provider charges"
175
+ else:
176
+ return None
177
+ return {"topic": topic["name"], "status": "skipped", "reason": reason}
178
+
179
+
170
180
  def _run_topic(topic: dict) -> dict:
181
+ topic_id = topic["id"]
182
+ with tempfile.TemporaryDirectory(prefix="last30days-usage-") as temp_dir:
183
+ journal = Path(temp_dir) / "usage.db"
184
+ usage.create_journal(journal)
185
+ child_env = dict(os.environ, **{usage.JOURNAL_ENV: str(journal), "LAST30DAYS_STORE": "0"})
186
+ run_id = store.record_run(topic_id, source_mode="v3", status="running")
187
+ try:
188
+ result = _research_topic(topic, run_id, child_env)
189
+ finally:
190
+ costs = usage.read_journal(journal)
191
+ store.update_run(run_id, **costs)
192
+ result.update(costs)
193
+ return result
194
+
195
+
196
+ def _research_topic(topic: dict, run_id: int, child_env: dict) -> dict:
171
197
  start_time = time.time()
172
198
  topic_id = topic["id"]
173
- run_id = store.record_run(topic_id, source_mode="v3", status="running")
174
199
 
175
200
  try:
176
201
  search_queries = json.loads(topic["search_queries"]) if topic.get("search_queries") else None
@@ -181,6 +206,7 @@ def _run_topic(topic: dict) -> dict:
181
206
  str(SCRIPT_DIR / "last30days.py"),
182
207
  search_term,
183
208
  "--emit=json",
209
+ "--json-profile=raw",
184
210
  "--quick",
185
211
  "--lookback-days",
186
212
  "90",
@@ -193,6 +219,7 @@ def _run_topic(topic: dict) -> dict:
193
219
  capture_output=True,
194
220
  text=True,
195
221
  timeout=300,
222
+ env={**child_env, envlib.ALLOW_ENGINE_PLAN_VAR: "1"},
196
223
  )
197
224
  duration = time.time() - start_time
198
225
  if result.returncode != 0:
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/env python3
2
+ """Compare the X results of two saved last30days report JSON files.
3
+
4
+ Dev tool for checking one X lane against another on the same topic and
5
+ window. Each input is the output of ``last30days.py <topic> --emit=json
6
+ --json-profile=raw``; the optional envelope is the candidate's ``--x-posts``
7
+ file, so a baseline post the candidate fetched but did not keep still counts
8
+ toward recall.
9
+
10
+ python3 scripts/x_lane_parity.py baseline.json candidate.json [--envelope x-posts.json]
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ import argparse
16
+ import json
17
+ import re
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ _STATUS_RE = re.compile(r"/status/(\d+)")
22
+ _METRICS = ("likes", "reposts", "replies", "quotes")
23
+ TOP_N = 10
24
+
25
+
26
+ def _load(path: str) -> dict:
27
+ return json.loads(Path(path).read_text(encoding="utf-8"))
28
+
29
+
30
+ def _x_items(report: dict) -> list[dict]:
31
+ return list((report.get("items_by_source") or {}).get("x") or [])
32
+
33
+
34
+ def _require_same_run_shape(base: dict, cand: dict, envelope: dict | None) -> None:
35
+ """Refuse to compare reports that cover different topics or windows."""
36
+ for key in ("topic", "range_from", "range_to"):
37
+ if base.get(key) != cand.get(key):
38
+ raise ValueError(f"reports differ on {key}: {base.get(key)!r} vs {cand.get(key)!r}")
39
+ if envelope is not None and envelope.get("topic") != cand.get("topic"):
40
+ raise ValueError(
41
+ f"envelope topic {envelope.get('topic')!r} does not match the candidate report {cand.get('topic')!r}"
42
+ )
43
+
44
+
45
+ def _post_id(item: dict) -> str | None:
46
+ match = _STATUS_RE.search(str(item.get("url") or ""))
47
+ return match.group(1) if match else None
48
+
49
+
50
+ def _likes(item: dict) -> int:
51
+ value = (item.get("engagement") or {}).get("likes")
52
+ return int(value) if isinstance(value, (int, float)) else 0
53
+
54
+
55
+ def _envelope_ids(payload: dict | None) -> set[str]:
56
+ if not payload:
57
+ return set()
58
+ return {
59
+ str(post.get("id"))
60
+ for call in payload.get("calls") or []
61
+ for post in call.get("posts") or []
62
+ if post.get("id")
63
+ }
64
+
65
+
66
+ def _ratio(numerator: float, denominator: float) -> float:
67
+ return round(numerator / denominator, 3) if denominator else 0.0
68
+
69
+
70
+ def compare(baseline: str, candidate: str, *, envelope: str | None = None) -> dict:
71
+ """Counts, top-liked recall, field completeness, and author spread."""
72
+ base, cand = _load(baseline), _load(candidate)
73
+ env = _load(envelope) if envelope else None
74
+ _require_same_run_shape(base, cand, env)
75
+ base_items = _x_items(base)
76
+ cand_items = _x_items(cand)
77
+ cand_ids = {pid for pid in map(_post_id, cand_items) if pid} | _envelope_ids(env)
78
+ top = sorted(base_items, key=_likes, reverse=True)[:TOP_N]
79
+ top_ids = [pid for pid in map(_post_id, top) if pid]
80
+ complete = sum(
81
+ 1 for item in cand_items
82
+ if all(isinstance((item.get("engagement") or {}).get(m), (int, float)) for m in _METRICS)
83
+ )
84
+ return {
85
+ "baseline_count": len(base_items),
86
+ "candidate_count": len(cand_items),
87
+ "count_ratio": _ratio(len(cand_items), len(base_items)),
88
+ "top_liked_recall": _ratio(sum(1 for pid in top_ids if pid in cand_ids), len(top_ids)),
89
+ "candidate_field_completeness": _ratio(complete, len(cand_items)),
90
+ "baseline_authors": len({item.get("author") for item in base_items}),
91
+ "candidate_authors": len({item.get("author") for item in cand_items}),
92
+ }
93
+
94
+
95
+ def main(argv: list[str] | None = None) -> int:
96
+ parser = argparse.ArgumentParser(description=__doc__.splitlines()[0])
97
+ parser.add_argument("baseline")
98
+ parser.add_argument("candidate")
99
+ parser.add_argument("--envelope")
100
+ args = parser.parse_args(argv)
101
+ json.dump(compare(args.baseline, args.candidate, envelope=args.envelope), sys.stdout, indent=2)
102
+ sys.stdout.write("\n")
103
+ return 0
104
+
105
+
106
+ if __name__ == "__main__":
107
+ raise SystemExit(main())
@@ -1,5 +1,9 @@
1
1
  # Changelog — luckiest-video-studio
2
2
 
3
+ ## 1.19.0 — 2026-10-15
4
+
5
+ - New motion-design style card `product-flight` (Continuous Product Flight): one camera flight around one hero object, speed ramps between stops on downbeats, side captions, glass callouts with pointer lines, one procedural VFX peak. Distilled from the approved PSA slab film and its review corrections. Offered for collectible and single premium product reveals. 39 styles.
6
+
3
7
  ## 1.18.0 — 2026-10-13
4
8
 
5
9
  - New QA gate `node qa.mjs logo <run-dir> [--svg path] [--max 8]`: for every logo scene it takes the clip's last frame, finds the mark's box, draws the logo SVG (default `brand/logo.svg`) into the same box on the same background with HyperFrames, and fails when they differ. Enforces the "resolve frame equals the master logo" rule in the style cards' Logo construction sections.
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: luckiest-video-studio
3
- description: "Make product launch videos, product demos with motion design between demo shots, and logo showcases, all editable after render, in 38 named styles. Starts with a short context interview, plans a scripted storyboard the user approves scene by scene in a review player before anything renders, builds motion scenes with HyperFrames, records or places demo footage, renders each scene as its own clip, then hands back an MP4 plus a storyboard.json that re-renders one scene at a time, a review player for edits and notes (Concat, OpenScreen, or Diffusion Studio on request), and optional After Effects compositions. Use for 'make a launch video', 'product demo video', 'demo with motion graphics', 'logo animation', 'logo reveal', 'portfolio reel', 'animate my logos', 'brand reel', 'turn my talking-head recording into a reel', 'add graphics over me talking', or 'change scene 3 of the video'. For AI-generated footage, avatars, and text-to-video models use luckiest-video. For what to post and when use luckiest-social."
3
+ description: "Make product launch videos, product demos with motion design between demo shots, and logo showcases, all editable after render, in 39 named styles. Starts with a short context interview, plans a scripted storyboard the user approves scene by scene in a review player before anything renders, builds motion scenes with HyperFrames, records or places demo footage, renders each scene as its own clip, then hands back an MP4 plus a storyboard.json that re-renders one scene at a time, a review player for edits and notes (Concat, OpenScreen, or Diffusion Studio on request), and optional After Effects compositions. Use for 'make a launch video', 'product demo video', 'demo with motion graphics', 'logo animation', 'logo reveal', 'portfolio reel', 'animate my logos', 'brand reel', 'turn my talking-head recording into a reel', 'add graphics over me talking', or 'change scene 3 of the video'. For AI-generated footage, avatars, and text-to-video models use luckiest-video. For what to post and when use luckiest-social."
4
4
  license: See ATTRIBUTION.md
5
5
  allowed-tools: Bash, Read, Write, Edit, Glob, Grep, AskUserQuestion
6
6
  metadata:
7
- version: "1.18.0"
7
+ version: "1.19.0"
8
8
  listing_id: luckiest-video-studio
9
9
  author: luckiest
10
10
  ---
@@ -25,7 +25,7 @@ further if `upToDate: true`. Never block on this check; if the tool is unavailab
25
25
  proceed.
26
26
 
27
27
  When the skill's work is done, call the Luckiest MCP `report_usage` tool once with
28
- `{ listing_id: "luckiest-video-studio", skill_version: "1.18.0", matched: true, success: <true if the skill completed, false otherwise> }`.
28
+ `{ listing_id: "luckiest-video-studio", skill_version: "1.19.0", matched: true, success: <true if the skill completed, false otherwise> }`.
29
29
  Metadata only, never prompt text. Never block on it; if the tool is unavailable,
30
30
  skip silently.
31
31
 
@@ -69,7 +69,7 @@ in `<skill-dir>/assets/sfx/`. Resolve it; never assume an install path.
69
69
  |---|---|---|
70
70
  | `--mode` | `launch`, `demo`, `logos` | inferred |
71
71
  | `--tone` | preset or freeform ([references/tones.md](references/tones.md)) | inferred |
72
- | `--style` | a style id from [references/styles.md](references/styles.md); its card is `references/styles/<id>.md`. 38 looks (flat vector, synthwave, whiteboard explainer, paper collage, ink wash...) plus era styles | named in the request, else asked |
72
+ | `--style` | a style id from [references/styles.md](references/styles.md); its card is `references/styles/<id>.md`. 39 looks (flat vector, synthwave, whiteboard explainer, paper collage, ink wash...) plus era styles | named in the request, else asked |
73
73
  | `--format` | `landscape`, `vertical`, `square`: the master size scenes are designed at | `landscape` |
74
74
  | `--formats` | comma list of `landscape`, `vertical`, `square`: render the same video once per format, one file each | master only |
75
75
  | `--duration` | seconds | per mode |
@@ -0,0 +1,45 @@
1
+ # Continuous Product Flight
2
+
3
+ - id: `product-flight`
4
+ - Source: Luckiest, from the approved PSA slab film (2026-10-14), a remake of the whatships.com OneKey Pro 2 film. Rules come from the user's Motion OS review notes on that run.
5
+ - Best for: collectible and premium single-object reveals (graded cards, watches, sneakers, devices, bottles), music-timed hero films, launch teasers, 9:16 and 4:5 cutdowns of the same flight
6
+ - Not for: product lineups, UI walkthroughs, voiceover explainers, anything that needs more than one product on screen
7
+ - Triggers: continuous shot, one take, oner, camera flight, fly around, orbit the product, speed ramp, speed ramps, transparent case, clear acrylic, acrylic slab, graded card, PSA slab, collectible, trading card, whatships
8
+ - Tone cell: calm-sharp
9
+ - Clock: smooth 30 fps, motion blur only on fast stretches
10
+
11
+ ## Look
12
+ One hero object on a near-black ground (#0B0B0F, never pure #000, which bands after recompression). Clear material where the product has one: transmission with IOR about 1.49 for acrylic, a thin edge glow, raised lips and wells modeled, not painted. Textures are cut from the user's own photos; the product's art, labels and text are never redrawn. One warm rim light is the only accent and carries one meaning. Bold side captions (about 64px at 1080p, heavy grotesk) sit beside the subject, never over it. Feature beats get a frosted glass callout with a drawn pointer line to the exact detail. The real brand logo file, never a typed stand-in.
13
+
14
+ ## Motion
15
+ One continuous camera flight around one object, no cuts. Each line of the script is a camera stop: a slow drift while the caption reads, then a speed ramp (cubic in-out, fast middle) to the next stop, so the energy comes from velocity changes, not edits. Motion blur scales with pose speed, so drifts stay crisp and whips smear. Feature stops are angled and wide enough to tease, then reveal; tight macros read as cropped. Set pieces, at most one each: a whip-around reveal of the full product, the case drifting apart then slamming shut, a whip-flip to the back, and one procedural VFX peak (cloud, smoke and fire shader) that fills the frame behind the hero.
16
+
17
+ ## Signature features (judged against these)
18
+ - One product on screen at all times, one continuous camera, zero hard cuts.
19
+ - Stops joined by speed ramps: slow drift, whip, slow drift.
20
+ - Ramps start on downbeats. The reveal lands on the music's bass entry and the VFX peak on the drop.
21
+ - Captions beside the subject, never over it, readable at phone size.
22
+ - A glass callout with a pointer line on every feature beat.
23
+ - Real photos and real brand assets only. No AI redraw of the product, its art or its label.
24
+ - The edge light pulses on the beat only in sections with drums.
25
+
26
+ ## 10-second beat seed
27
+ - 0-1.5s: product dark, a sliver of rim light, one word of setup.
28
+ - 1.5-4s: slow drift past a detail at an angle, caption beside it.
29
+ - 4-5s (on a downbeat): ramp into a whip-around.
30
+ - 5-7.5s (hero at 50-75%, on the bass entry): land front-on, the whole product seen for the first time, name it.
31
+ - 7.5-10s: callout with a line to the one feature that matters, slow push, hold the last 1s.
32
+
33
+ ## Sound
34
+ A licensed track or the user's own, cut on downbeats so film time 0 is a downbeat and every join falls on one. Splice only at the song's natural transitions or with beat-aligned crossfades; a hard swap skips audibly. Anchor the reveal, the flip and the VFX peak to the song's own entries and drop. Master near -13 LUFS. No whooshes stacked on every ramp; the music already carries them.
35
+
36
+ ## Build it in HyperFrames
37
+ Three.js (WebGL2) with MeshPhysicalMaterial (transmission, thickness, ior 1.49, clearcoat) for the case, the photo textures on planes inside it, and an edge-light shader for the glow. The camera is an orbit pose (azimuth, elevation, distance, target) interpolated over a key list of `[end time, pose, ease]`, with closed-form eases (`in`, `out`, `ramp`, `sin`) so any frame renders alone from `?at=<seconds>`: no stateful animation. Captions, callouts and the logo are canvas or SVG textures drawn in the same frame. Motion blur is a sub-frame average whose count follows pose speed. The VFX peak is a raymarched or noise-driven fragment shader, not generated plates. Reels re-use the same keys: 9:16 moves captions clear of the platform buttons, 4:5 pulls the camera back about 1.2x.
38
+
39
+ ## Logo construction
40
+ Rule from logo-design (MIT, kaankiziltug): the entrance is built from the mark's own construction, and the resolve frame equals the master logo. Before animating, write the mark's construction in one line in `plan.md` (its primitives, strokes or modules, and the order they would be drawn). The resolve frame is the real logo file (`brand/logo.svg` or the SVG the user supplied), never a styled stand-in or an invented wordmark: render the last frame and the logo SVG at the same size and position, and any visible difference is a Block. Sting length 1 to 3 seconds, easing from this card.
41
+ - Construction: the logo SVG's own paths are flat planes in the scene, and the camera flies to them as its last stop. They build in construction order (outer shape first, then cuts and counters) during the final ramp, lit by the same rim light.
42
+ - Resolve: the ramp lands front-on and orthographic-matched; in the last 0.3s blur, glow and depth flatten so the hold frame is the flat logo SVG in brand colors.
43
+
44
+ ## Watch out
45
+ Transmission in headless WebGL is slow and goes flat on a weak GPU: check the renderer logs a real GPU, and cap sub-frames. Too many stops makes the flight feel like a slideshow; keep 2.5 to 4s per stop. Several products, a second accent color, or a numeric claim the user did not give all break the card. Callout lines must point at the real detail in the texture, so check them on stills at each stop before the full render.
@@ -1,6 +1,6 @@
1
1
  # Style library
2
2
 
3
- 38 visual styles plus 18 era styles, each a card in `styles/`. A style decides the
3
+ 39 visual styles plus 18 era styles, each a card in `styles/`. A style decides the
4
4
  renderer, texture, motion signature, clock and transition family. The brand still
5
5
  decides the colors and faces when it has a design system (art director section 0):
6
6
  map the card's palette roles onto the brand palette instead of replacing it.
@@ -28,6 +28,7 @@ map the card's palette roles onto the brand palette instead of replacing it.
28
28
  | Hype, gaming, dev tools | `synthwave`, `hud`, `pixel` |
29
29
  | Vertical social (9:16) | `variety-show`, `kinetic-type`, `collage` |
30
30
  | Logo showcase | `morph`, `liquid`, `bauhaus` |
31
+ | Collectible, single premium product reveal | `product-flight`, `3d-render`, `aurora-glass` |
31
32
 
32
33
  When all three offers are polished looks, swap the third for one hand-made style
33
34
  (`collage`, `cel-boil`, `line-art`, `whiteboard`, `cut-paper`): in 2026 feeds full
@@ -72,6 +73,7 @@ the concept. Brand names in seeds are placeholders: use the real product.
72
73
  | [`liquid`](styles/liquid.md) | Liquid Metaball Motion | kinetic-soft | music video packaging, food and drink ads, logo genesis, transition packs | liquid, fluid, metaball, goo, gooey, paint splash, drip, melt, blob, ink flood, liquid transition, logo reveal |
73
74
  | [`morph`](styles/morph.md) | Shape Morph Chain | calm-sharp | keynote-grade storytelling, icon sequences, feature walkthroughs, brand reveal built from meaningful symbols | morph, morphing, shape transition, icon morph, shape shifting, one shape becomes another, Apple keynote, visual storytelling, flubber |
74
75
  | [`pixel`](styles/pixel.md) | Pixel Art 8-bit | kinetic-sharp | game trailers and attract screens, 8-bit music videos, nostalgic brand marketing, indie game promos | pixel art, 8-bit, 16-bit, retro game, sprite, chiptune, side scroller, CRT, dithering, PICO-8, Aseprite, Minecraft, Terraria |
76
+ | [`product-flight`](styles/product-flight.md) | Continuous Product Flight | calm-sharp | collectible and premium single-object reveals (graded cards, watches, sneakers, devices, bottles), music-timed hero films, launch teasers, 9:16 and 4:5 cutdowns of the same flight | continuous shot, one take, oner, camera flight, fly around, orbit the product, speed ramp, speed ramps, transparent case, clear acrylic, acrylic slab, graded card, PSA slab, collectible, trading card, whatships |
75
77
  | [`sticker-explainer`](styles/sticker-explainer.md) | Sticker Knowledge Explainer | calm-sharp | hard-core science explainers, finance and knowledge channels, corporate documentary explainers, data-rich narration videos | sticker, knowledge video, science explainer, infographic video, big canvas, camera pan and zoom, photo cutouts with white outline, periodic table, PaperClip, Lin Chao, explainer channel |
76
78
  | [`synthwave`](styles/synthwave.md) | Synthwave VHS Retro | kinetic-sharp | retro title sequences, music videos, trend brand films, gaming and nostalgia content, Y2K chrome revivals | synthwave, outrun, 80s, retro, neon, VHS, vaporwave, Y2K, chrome text, scanlines, grid horizon, retrowave |
77
79
  | [`variety-show`](styles/variety-show.md) | Variety Show Kinetic Captions | kinetic-soft | 9:16 vlogs, pet and lifestyle shorts, interview and reaction edits, comedic re-edits, caption-heavy social video | variety show, hanazi, Chinese variety captions, kinetic captions, sticker text, fancy text, reaction text, vlog captions, burst box, outlined text, TikTok captions, Douyin, bilibili |
@@ -4,7 +4,7 @@
4
4
 
5
5
  | Source | License | What this sub-skill uses | License file |
6
6
  |---|---|---|---|
7
- | **skills** by Emil Kowalski (`emilkowalski/skills`) | MIT | The animation decision order, easing and duration rules, physicality and origin rules, blur-masked transitions, stagger, asymmetric timing, and the strict review posture from `emil-design-eng`, `animate`, `review-animations`, and `find-animation-opportunities`; type and material rules from `apple-design`; the glossary from `animation-vocabulary` | `LICENSE-emil` |
7
+ | **skills** by Emil Kowalski (`emilkowalski/skills`) | MIT | The animation decision order, easing and duration rules, physicality and origin rules, blur-masked transitions, stagger, asymmetric timing, and the strict review posture from `emil-design-eng`, `animate`, `review-animations`, and `find-animation-opportunities`; type and material rules from `apple-design`; the glossary from `animation-vocabulary`; shadow, CSS-variable and `transition: all` rules from `animation-performance` | `LICENSE-emil` |
8
8
  | **motionmaxxing** by Tejas Makwana (`Tejashmakwana/motionmaxxing`, FinalMotion, finalmotion.video), commit 8c8ec0f2 | Apache-2.0 | Frame-measured durations, ease roles, stagger and camera values, handoff and transition recipes, and the numbers in `references/kinetic-type.md` and `references/ui-demo.md`. Rewritten in our own words; no code, runtime, media, studies or `library/` rows are copied | `LICENSE-motionmaxxing` |
9
9
 
10
10
  ## Changes in this edition
@@ -1,5 +1,9 @@
1
1
  # Changelog — luckiest-video-studio-motion
2
2
 
3
+ ## 1.3.1 — 2026-10-16
4
+
5
+ - Transform rule now covers shadows (`drop-shadow` over `box-shadow`), tweening transforms directly instead of an inherited CSS variable, and no `transition: all`. From emilkowalski/skills animation-performance at 2d22863 (MIT).
6
+
3
7
  ## 1.3.0 — 2026-10-12
4
8
 
5
9
  - Camera as punctuation: three questions before each move, a move table (slow push, pull, glide, snap, whip, slam), accents at most a third of shots, no three push-ins in a row, enter slow and exit fast, reveals landed on beats or words (from huashu-art-motion, MIT).
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: luckiest-video-studio-motion
2
+ name: video-studio-motion
3
3
  description: >-
4
4
  Motion taste for luckiest-video-studio. Decides whether a beat should move,
5
5
  then picks the easing, duration, origin, stagger, and transition for HyperFrames
@@ -16,7 +16,7 @@ user-invocable: true
16
16
  license: MIT. See ATTRIBUTION.md
17
17
  allowed-tools: Bash, Read, Write, Edit, Glob, Grep
18
18
  metadata:
19
- version: "1.3.0"
19
+ version: "1.3.1"
20
20
  listing_id: luckiest-video-studio-motion
21
21
  author: luckiest
22
22
  ---
@@ -32,11 +32,11 @@ interruption, and how often a user triggers something.
32
32
  ## Staying current
33
33
 
34
34
  On activation, call the Luckiest MCP `check_updates` tool with
35
- `{ listingId: "luckiest-video-studio-motion", installedSemver: "1.3.0" }`. If
35
+ `{ listingId: "luckiest-video-studio-motion", installedSemver: "1.3.1" }`. If
36
36
  `upToDate: false`, surface the `notice` once and continue. Never block on it.
37
37
 
38
38
  When done, call `report_usage` once with
39
- `{ listing_id: "luckiest-video-studio-motion", skill_version: "1.3.0", matched: true, success: <true|false> }`.
39
+ `{ listing_id: "luckiest-video-studio-motion", skill_version: "1.3.1", matched: true, success: <true|false> }`.
40
40
  Metadata only, never prompt text. Skip silently if unavailable.
41
41
 
42
42
  ## Modes
@@ -151,7 +151,10 @@ change about every 0.8 seconds.
151
151
  for fades, wipes, and linear fills.
152
152
  - **Transform, not layout.** Animate `x`, `y`, `scale`, `rotate`, `autoAlpha`,
153
153
  `clipPath`, and `filter`. `width`, `height`, `top`, and `left` snap to whole
154
- pixels and shimmer in the render.
154
+ pixels and shimmer in the render. Animate a shadow with `filter: drop-shadow()`,
155
+ not `box-shadow`. Tween `transform` on the element itself, never a CSS variable
156
+ on a parent: every child restyles each frame and long scenes render slowly.
157
+ Name the tweened properties; no `transition: all`.
155
158
  - **Fast moves strobe.** At 30fps, an element crossing more than about a tenth of
156
159
  the frame per frame reads as jumps. Shorten the distance, lengthen the move, or
157
160
  make it a deliberate whip with a blur.
@@ -1,49 +0,0 @@
1
- # Spec Document Reviewer Prompt Template
2
-
3
- Use this template when dispatching a spec document reviewer subagent.
4
-
5
- **Purpose:** Verify the spec is complete, consistent, and ready for implementation planning.
6
-
7
- **Dispatch after:** Spec document is written to docs/luckiest-coder/specs/
8
-
9
- ```
10
- Subagent (general-purpose):
11
- description: "Review spec document"
12
- prompt: |
13
- You are a spec document reviewer. Verify this spec is complete and ready for planning.
14
-
15
- **Spec to review:** [SPEC_FILE_PATH]
16
-
17
- ## What to Check
18
-
19
- | Category | What to Look For |
20
- |----------|------------------|
21
- | Completeness | TODOs, placeholders, "TBD", incomplete sections |
22
- | Consistency | Internal contradictions, conflicting requirements |
23
- | Clarity | Requirements ambiguous enough to cause someone to build the wrong thing |
24
- | Scope | Focused enough for a single plan — not covering multiple independent subsystems |
25
- | YAGNI | Unrequested features, over-engineering |
26
-
27
- ## Calibration
28
-
29
- **Only flag issues that would cause real problems during implementation planning.**
30
- A missing section, a contradiction, or a requirement so ambiguous it could be
31
- interpreted two different ways — those are issues. Minor wording improvements,
32
- stylistic preferences, and "sections less detailed than others" are not.
33
-
34
- Approve unless there are serious gaps that would lead to a flawed plan.
35
-
36
- ## Output Format
37
-
38
- ## Spec Review
39
-
40
- **Status:** Approved | Issues Found
41
-
42
- **Issues (if any):**
43
- - [Section X]: [specific issue] - [why it matters for planning]
44
-
45
- **Recommendations (advisory, do not block approval):**
46
- - [suggestions for improvement]
47
- ```
48
-
49
- **Reviewer returns:** Status, Issues (if any), Recommendations