codymaster 4.8.0 → 7.0.0

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 (416) hide show
  1. package/CHANGELOG.md +331 -7
  2. package/README.md +226 -296
  3. package/dist/advisory-handoff.js +89 -0
  4. package/dist/advisory-report.js +105 -0
  5. package/dist/agent/antigravity.js +152 -0
  6. package/dist/agent/backend.js +2 -0
  7. package/dist/agent/claude.js +196 -0
  8. package/dist/agent/codex.js +204 -0
  9. package/dist/agent/copilot.js +284 -0
  10. package/dist/agent/cursor.js +211 -0
  11. package/dist/agent/factory.js +30 -0
  12. package/dist/agent/gemini.js +142 -0
  13. package/dist/agent/opencode.js +205 -0
  14. package/dist/agent/spawn-helper.js +237 -0
  15. package/dist/agent/version.js +25 -0
  16. package/dist/browse/adapter-factory.js +69 -0
  17. package/dist/browse/adapters/agent-browser-adapter.js +305 -0
  18. package/dist/browse/adapters/playwright-adapter.js +309 -0
  19. package/dist/browse/adapters/types.js +6 -0
  20. package/dist/browse/error-collector.js +132 -0
  21. package/dist/browse/event-log.js +109 -0
  22. package/dist/browse/index.js +17 -0
  23. package/dist/browse-server.js +204 -120
  24. package/dist/cli/command-registry.js +20 -0
  25. package/dist/cli/commands/bench.js +69 -0
  26. package/dist/cli/commands/brain.js +108 -0
  27. package/dist/cli/commands/dashboard.js +76 -2
  28. package/dist/cli/commands/engineering.js +326 -4
  29. package/dist/cli/commands/evolve.js +123 -0
  30. package/dist/cli/commands/install.js +160 -0
  31. package/dist/cli/commands/learn.js +181 -0
  32. package/dist/cli/commands/mcp-serve.js +104 -0
  33. package/dist/cli/commands/parallel.js +138 -0
  34. package/dist/cli/commands/quality.js +105 -0
  35. package/dist/cli/commands/stack.js +49 -0
  36. package/dist/cli/commands/update.js +159 -0
  37. package/dist/cli/update-check.js +94 -10
  38. package/dist/cm-config.js +0 -18
  39. package/dist/codybench/judges/automated.js +31 -0
  40. package/dist/codybench/runners/claude-code.js +32 -0
  41. package/dist/codybench/suites/memory-retention.js +85 -0
  42. package/dist/codybench/suites/tdd-regression.js +35 -0
  43. package/dist/codybench/suites/token-efficiency.js +55 -0
  44. package/dist/codybench/types.js +2 -0
  45. package/dist/context-db.js +157 -0
  46. package/dist/continuity.js +5 -7
  47. package/dist/dashboard.js +47 -6
  48. package/dist/data.js +35 -0
  49. package/dist/execution/tdd-gate.js +113 -0
  50. package/dist/execution-analyzer.js +138 -0
  51. package/dist/executor/cancel.js +34 -0
  52. package/dist/executor/gc.js +74 -0
  53. package/dist/executor/index.js +14 -0
  54. package/dist/executor/runner.js +70 -0
  55. package/dist/executor/workdir.js +31 -0
  56. package/dist/handoff/contracts.js +22 -0
  57. package/dist/handoff/index.js +18 -0
  58. package/dist/handoff/io.js +121 -0
  59. package/dist/index.js +7 -3
  60. package/dist/indexer/skills-lib.js +533 -0
  61. package/dist/indexer/skills-map.js +1374 -0
  62. package/dist/indexer/skills.js +16 -0
  63. package/dist/indexer/stack-detect.js +219 -0
  64. package/dist/install/copy.js +98 -0
  65. package/dist/install/engine.js +42 -0
  66. package/dist/install/paths.js +70 -0
  67. package/dist/install/platforms/_simple.js +85 -0
  68. package/dist/install/platforms/antigravity.js +91 -0
  69. package/dist/install/platforms/claude-code.js +107 -0
  70. package/dist/install/platforms/cursor.js +77 -0
  71. package/dist/install/platforms/index.js +27 -0
  72. package/dist/install/platforms/simple.js +163 -0
  73. package/dist/install/profiles.js +75 -0
  74. package/dist/install/types.js +2 -0
  75. package/dist/learning-promoter.js +246 -0
  76. package/dist/learnings.js +208 -0
  77. package/dist/mcp-context-server.js +230 -1
  78. package/dist/middleware/metrics.js +30 -0
  79. package/dist/middleware/security-headers.js +14 -0
  80. package/dist/realtime/event-bus.js +29 -0
  81. package/dist/realtime/ws-hub.js +91 -0
  82. package/dist/schemas/task-schema.js +48 -0
  83. package/dist/schemas/validate.js +18 -0
  84. package/dist/skill-chain.js +63 -1
  85. package/dist/skill-evolver.js +456 -0
  86. package/dist/skill-execution-cache.js +254 -0
  87. package/dist/skills-lock.js +96 -0
  88. package/dist/smart-brain-router.js +184 -0
  89. package/dist/sprint-pipeline.js +26 -0
  90. package/dist/storage/index.js +21 -0
  91. package/dist/storage/repos/activity-repo.js +46 -0
  92. package/dist/storage/repos/message-repo.js +39 -0
  93. package/dist/storage/repos/project-repo.js +56 -0
  94. package/dist/storage/repos/task-repo.js +142 -0
  95. package/dist/storage/services/project-service.js +49 -0
  96. package/dist/storage/services/task-service.js +97 -0
  97. package/dist/storage/sqlite.js +113 -0
  98. package/dist/storage-backend.js +10 -8
  99. package/dist/tier-classify.js +131 -0
  100. package/dist/token-budget.js +88 -0
  101. package/dist/ui/onboarding.js +51 -15
  102. package/dist/utils/cli-utils.js +7 -2
  103. package/dist/utils/design-taste.js +108 -0
  104. package/dist/utils/output-compress.js +143 -0
  105. package/dist/vibecoding-index.js +126 -0
  106. package/package.json +20 -6
  107. package/public/dashboard/app.js +52 -1
  108. package/scripts/build-skills-lock.mjs +88 -0
  109. package/scripts/build-skills.mjs +187 -28
  110. package/scripts/compress-skill.mjs +73 -0
  111. package/scripts/deprecate-skill.mjs +72 -0
  112. package/scripts/install.sh +170 -0
  113. package/scripts/mcp-bridge.js +2 -2
  114. package/scripts/postinstall.js +53 -335
  115. package/scripts/update-changelog.sh +88 -0
  116. package/scripts/validate-skills.mjs +101 -4
  117. package/skills/CLAUDE.md +0 -5
  118. package/skills/_shared/SKILL_TEMPLATE.md +62 -0
  119. package/skills/_shared/helpers.md +2 -8
  120. package/skills/cm-autopilot/scripts/autopilot.py +19 -2
  121. package/skills/cm-brainstorm-idea/SKILL.md +9 -0
  122. package/skills/cm-browse/SKILL.md +6 -0
  123. package/skills/cm-clean-code/SKILL.md +20 -0
  124. package/skills/cm-code-review/SKILL.md +21 -0
  125. package/skills/cm-codeintell/SKILL.md +9 -0
  126. package/skills/cm-conductor-worktrees/SKILL.archive.md +28 -0
  127. package/skills/cm-conductor-worktrees/SKILL.md +20 -18
  128. package/skills/cm-continuity/SKILL.md +41 -33
  129. package/skills/cm-dashboard/SKILL.archive.md +15 -0
  130. package/skills/cm-dashboard/SKILL.md +20 -9
  131. package/skills/cm-dashboard/ui/app.js +9 -1
  132. package/skills/cm-debugging/SKILL.md +9 -0
  133. package/skills/cm-design-studio/SKILL.archive.md +34 -0
  134. package/skills/cm-design-studio/SKILL.md +20 -24
  135. package/skills/cm-design-system/SKILL.md +1 -0
  136. package/skills/cm-ecosystem-roadmap/SKILL.md +4 -0
  137. package/skills/cm-engineering-meta/SKILL.archive.md +73 -0
  138. package/skills/cm-engineering-meta/SKILL.md +19 -62
  139. package/skills/cm-execution/SKILL.md +98 -0
  140. package/skills/cm-git-worktrees/SKILL.archive.md +157 -0
  141. package/skills/cm-git-worktrees/SKILL.md +15 -146
  142. package/skills/cm-guardian-runtime/SKILL.md +5 -1
  143. package/skills/cm-identity-guard/SKILL.md +8 -0
  144. package/skills/cm-mcp-engineering/SKILL.md +4 -0
  145. package/skills/cm-planning/SKILL.md +63 -92
  146. package/skills/cm-post-deploy-canary/SKILL.archive.md +22 -0
  147. package/skills/cm-post-deploy-canary/SKILL.md +20 -12
  148. package/skills/cm-project-bootstrap/SKILL.md +11 -0
  149. package/skills/cm-qa-visual-cli/SKILL.archive.md +22 -0
  150. package/skills/cm-qa-visual-cli/SKILL.md +19 -11
  151. package/skills/cm-quality-gate/SKILL.md +38 -0
  152. package/skills/cm-retro-cli/SKILL.md +4 -0
  153. package/skills/cm-safe-deploy/SKILL.md +9 -0
  154. package/skills/cm-second-opinion-cli/SKILL.archive.md +23 -0
  155. package/skills/cm-second-opinion-cli/SKILL.md +20 -13
  156. package/skills/cm-secret-shield/SKILL.archive.md +580 -0
  157. package/skills/cm-secret-shield/SKILL.md +15 -569
  158. package/skills/cm-security-gate/SKILL.archive.md +239 -0
  159. package/skills/cm-security-gate/SKILL.md +16 -228
  160. package/skills/cm-skill-chain/SKILL.md +25 -4
  161. package/skills/cm-skill-evolution/SKILL.md +83 -0
  162. package/skills/cm-skill-health/SKILL.archive.md +83 -0
  163. package/skills/cm-skill-health/SKILL.md +26 -0
  164. package/skills/cm-skill-index/SKILL.md +19 -3
  165. package/skills/cm-skill-mastery/SKILL.archive.md +156 -0
  166. package/skills/cm-skill-mastery/SKILL.md +16 -146
  167. package/skills/cm-skill-search/SKILL.archive.md +49 -0
  168. package/skills/cm-skill-search/SKILL.md +26 -0
  169. package/skills/cm-skill-share/SKILL.archive.md +58 -0
  170. package/skills/cm-skill-share/SKILL.md +26 -0
  171. package/skills/cm-sprint-bus/SKILL.md +13 -0
  172. package/skills/cm-start/SKILL.md +17 -10
  173. package/skills/cm-tdd/SKILL.md +21 -2
  174. package/skills/cm-terminal/SKILL.md +15 -0
  175. package/skills/cm-test-gate/SKILL.archive.md +245 -0
  176. package/skills/cm-test-gate/SKILL.md +15 -234
  177. package/skills/cm-ui-preview/SKILL.archive.md +153 -0
  178. package/skills/cm-ui-preview/SKILL.md +16 -143
  179. package/skills/cm-ux-master/cli/uxmaster/commands/mcp.py +1 -1
  180. package/skills/cm-ux-master/mcp/mcp-config.json +1 -1
  181. package/skills/cm-ux-master/mcp/server.py +2 -2
  182. package/skills/profiles/design.txt +1 -1
  183. package/skills/profiles/full.txt +4 -10
  184. package/skills/profiles/growth.txt +8 -8
  185. package/skills/profiles/knowledge.txt +1 -1
  186. package/skills/profiles/top35.json +41 -0
  187. package/adapters/antigravity.js +0 -15
  188. package/adapters/claude-code.js +0 -17
  189. package/adapters/cursor.js +0 -16
  190. package/install.sh +0 -1125
  191. package/scripts/viking-demo.ts +0 -105
  192. package/skills/cm-ads-tracker/SKILL.md +0 -401
  193. package/skills/cm-ads-tracker/evals/evals.json +0 -55
  194. package/skills/cm-ads-tracker/references/gtm-architecture.md +0 -321
  195. package/skills/cm-ads-tracker/references/industry-events.md +0 -294
  196. package/skills/cm-ads-tracker/references/platforms-api.md +0 -238
  197. package/skills/cm-ads-tracker/templates/capi-payload.md +0 -79
  198. package/skills/cm-ads-tracker/templates/datalayer-push.js +0 -104
  199. package/skills/cm-ads-tracker/templates/gtm-variables.js +0 -56
  200. package/skills/cm-auto-publisher/SKILL.md +0 -81
  201. package/skills/cm-booking-calendar/SKILL.md +0 -521
  202. package/skills/cm-booking-calendar/references/industry-patterns.md +0 -527
  203. package/skills/cm-booking-calendar/templates/booking-form.css +0 -626
  204. package/skills/cm-booking-calendar/templates/booking-form.html +0 -477
  205. package/skills/cm-booking-calendar/templates/calendar-engine.js +0 -419
  206. package/skills/cm-booking-calendar/templates/calendar-export.js +0 -395
  207. package/skills/cm-booking-calendar/templates/reminder-config.js +0 -629
  208. package/skills/cm-content-factory/.content-factory-state.json +0 -132
  209. package/skills/cm-content-factory/.git 2/logs/refs/heads/main +0 -1
  210. package/skills/cm-content-factory/.git 2/logs/refs/remotes/origin/main +0 -1
  211. package/skills/cm-content-factory/.git 2/objects/02/fb0956734b5f8ba3f918b7defd04a89cfe0076 +0 -0
  212. package/skills/cm-content-factory/.git 2/objects/08/1e129d75dc6feac6c02037272e6bd1a04e3324 +0 -0
  213. package/skills/cm-content-factory/.git 2/objects/0c/5393416f3c5e01c9a655a802bff0dd52f76f0a +0 -0
  214. package/skills/cm-content-factory/.git 2/objects/10/0b9be46978a946a77188f68be725098a122001 +0 -0
  215. package/skills/cm-content-factory/.git 2/objects/10/cf041167fc9843610eb3d90259ef3396315fdc +0 -0
  216. package/skills/cm-content-factory/.git 2/objects/12/5e19538dd6e1338ffe74f6c4c165b00435bf48 +0 -0
  217. package/skills/cm-content-factory/.git 2/objects/16/a9b9d0088d5c1347628b45a2620b479d8ad57c +0 -0
  218. package/skills/cm-content-factory/.git 2/objects/17/8c2a9ef93c33ae4eec9d58e82321f9229843a1 +0 -0
  219. package/skills/cm-content-factory/.git 2/objects/25/397ae41d09104d763bdcac2695209d85cdea89 +0 -0
  220. package/skills/cm-content-factory/.git 2/objects/2f/a836b7947f2d458e1f639788bf4bb0983a3305 +0 -0
  221. package/skills/cm-content-factory/.git 2/objects/3a/baaaf0a1c0909c0828335791557125fba911e0 +0 -0
  222. package/skills/cm-content-factory/.git 2/objects/42/2924221b81f5ce3c4e4daac9a64a24f9b01f9a +0 -0
  223. package/skills/cm-content-factory/.git 2/objects/42/ec0ce707447dc11446a34c9995fb8533801731 +0 -0
  224. package/skills/cm-content-factory/.git 2/objects/46/e43ce92866d56ce74b1d750db307cfe6154a15 +0 -0
  225. package/skills/cm-content-factory/.git 2/objects/48/5e41b633c63f55b8277bcc59f44f67681f671a +0 -0
  226. package/skills/cm-content-factory/.git 2/objects/49/49c596a3a89fa240642acd95dd3258e261eb09 +0 -0
  227. package/skills/cm-content-factory/.git 2/objects/50/9d42d8412ef8eaf7f7e138476bac2e4d10ce60 +0 -0
  228. package/skills/cm-content-factory/.git 2/objects/55/0c8c389d981b463ef849aeb792d8be3ccb6ec8 +0 -0
  229. package/skills/cm-content-factory/.git 2/objects/5d/82d3b18410cdda3ace3677436f0cb599dbe2d2 +0 -0
  230. package/skills/cm-content-factory/.git 2/objects/60/0617c58e871a38b33bf29e282d132bb3c381ad +0 -0
  231. package/skills/cm-content-factory/.git 2/objects/6a/8369a99c687b7245c92ffaf0e0f0dab9014504 +0 -0
  232. package/skills/cm-content-factory/.git 2/objects/79/bea435d40ab531c1aaf6be0432c6a5b7aaed21 +0 -0
  233. package/skills/cm-content-factory/.git 2/objects/7e/5ebd79251c2f14e4aceb86c74b6b6daae6b500 +0 -0
  234. package/skills/cm-content-factory/.git 2/objects/81/98a822a60178d6d5023ddb3e222cddf048742e +0 -0
  235. package/skills/cm-content-factory/.git 2/objects/86/0a0e1943dfe53411d2e499a1f16f46a96ef758 +0 -0
  236. package/skills/cm-content-factory/.git 2/objects/86/971fb55fdc081fdbae52376f0f13e57a4e9b04 +0 -0
  237. package/skills/cm-content-factory/.git 2/objects/88/b89dd609a0a03f8d4fe8bfde20d5b8fc1d326d +0 -0
  238. package/skills/cm-content-factory/.git 2/objects/90/8737edb6b7809e32cc01590b4e08ba42a9d40d +0 -0
  239. package/skills/cm-content-factory/.git 2/objects/93/d5a8a9a7d4fb7f11491cb596a6880528725118 +0 -0
  240. package/skills/cm-content-factory/.git 2/objects/98/46a2ab81d0c3b3eb00ef88fc56989aa7e9f316 +0 -0
  241. package/skills/cm-content-factory/.git 2/objects/9b/d8dd1e49cf274eaf9c555f3ab39dce7af5715e +0 -0
  242. package/skills/cm-content-factory/.git 2/objects/a1/13329fb0cec96ae78b222d33a24c3b5bc7fa1f +0 -0
  243. package/skills/cm-content-factory/.git 2/objects/a9/e6effe626e8a3aea3a8fc3364b492191c6e7d0 +0 -0
  244. package/skills/cm-content-factory/.git 2/objects/ad/6de7e48d9782cca9353d1ff0aa1aab7fe1df85 +0 -0
  245. package/skills/cm-content-factory/.git 2/objects/af/54ae316f771ff692e299ffcd8bf2f06b413b59 +0 -0
  246. package/skills/cm-content-factory/.git 2/objects/b0/4cb8b0b00dad633e731c1472161419e738d674 +0 -0
  247. package/skills/cm-content-factory/.git 2/objects/b3/094abb0b9ed46419b269e4a4e36a459690e3b0 +0 -0
  248. package/skills/cm-content-factory/.git 2/objects/b9/435c5d4baac2cfc5c83009ddd27b46b60db5f1 +0 -0
  249. package/skills/cm-content-factory/.git 2/objects/ba/5da17dbaec5ec2dcfdfd126aead518d1171d5c +0 -0
  250. package/skills/cm-content-factory/.git 2/objects/c0/bf58703aa258ba5dd63083bebaec8f223d844c +0 -0
  251. package/skills/cm-content-factory/.git 2/objects/c4/701a34edf1fc1bad58ccc57bd03f9426acb59a +0 -0
  252. package/skills/cm-content-factory/.git 2/objects/c7/5ccce9a4e5cc74d9b3174550cf6d993ca43638 +0 -0
  253. package/skills/cm-content-factory/.git 2/objects/c7/710d59b5a35b0f1f0a0399386643a0bd94c929 +0 -0
  254. package/skills/cm-content-factory/.git 2/objects/d1/fe58237112e953e5fec52da22cf38e08be3df9 +0 -5
  255. package/skills/cm-content-factory/.git 2/objects/d2/2bbe9fd2f74c95bc5583e803f5e435f1e2cd86 +0 -0
  256. package/skills/cm-content-factory/.git 2/objects/d7/e72852ea2bff74581dbf247d400120086229f4 +0 -0
  257. package/skills/cm-content-factory/.git 2/objects/d8/d4c3b5553e4fd72807e1d4b49ef07d9ef3ac35 +0 -0
  258. package/skills/cm-content-factory/.git 2/objects/dc/75050c2876f6a02ae2a53a3c886f395b622977 +0 -0
  259. package/skills/cm-content-factory/.git 2/objects/ee/e8546f95acec500187c08a28a8b9ee02db0dec +0 -0
  260. package/skills/cm-content-factory/.git 2/objects/ef/263c059208b416c2146434f10cb2b9fabcba16 +0 -0
  261. package/skills/cm-content-factory/.git 2/objects/f3/ae597e84d9a59b88acd21c99bde2eaf686d785 +0 -0
  262. package/skills/cm-content-factory/.git 2/objects/f3/f6f5673c821d3d8e76fa267a9e882e7a5387ea +0 -0
  263. package/skills/cm-content-factory/.git 2/objects/f9/6e6d0ad02624dd11d5848594d056caef7a5e8b +0 -0
  264. package/skills/cm-content-factory/.git 2/objects/ff/278988fc1edf0db3abcf18de795f4cc0b4f3e1 +0 -0
  265. package/skills/cm-content-factory/.git 2/refs/heads/main +0 -1
  266. package/skills/cm-content-factory/.git 2/refs/remotes/origin/main +0 -1
  267. package/skills/cm-content-factory/.pytest_cache 2/v/cache/nodeids +0 -76
  268. package/skills/cm-content-factory/.pytest_cache 2/v/cache/stepwise +0 -1
  269. package/skills/cm-content-factory/AGENTS.md +0 -61
  270. package/skills/cm-content-factory/CLAUDE.md +0 -63
  271. package/skills/cm-content-factory/CURSOR.md +0 -43
  272. package/skills/cm-content-factory/Content Factory.zip +0 -0
  273. package/skills/cm-content-factory/SKILL.md +0 -416
  274. package/skills/cm-content-factory/cf +0 -313
  275. package/skills/cm-content-factory/config.schema.json +0 -397
  276. package/skills/cm-content-factory/dashboard/app.js +0 -556
  277. package/skills/cm-content-factory/dashboard/index.html +0 -397
  278. package/skills/cm-content-factory/dashboard/style.css +0 -1211
  279. package/skills/cm-content-factory/examples/01-real-estate.config.json +0 -146
  280. package/skills/cm-content-factory/examples/02-personal-finance.config.json +0 -146
  281. package/skills/cm-content-factory/examples/03-health-wellness.config.json +0 -147
  282. package/skills/cm-content-factory/examples/04-saas-software.config.json +0 -147
  283. package/skills/cm-content-factory/examples/05-legal-services.config.json +0 -147
  284. package/skills/cm-content-factory/examples/06-insurance.config.json +0 -146
  285. package/skills/cm-content-factory/examples/07-ecommerce-dropship.config.json +0 -146
  286. package/skills/cm-content-factory/examples/08-online-education.config.json +0 -147
  287. package/skills/cm-content-factory/examples/09-crypto-defi.config.json +0 -147
  288. package/skills/cm-content-factory/examples/10-beauty-skincare.config.json +0 -147
  289. package/skills/cm-content-factory/examples/11-home-services.config.json +0 -146
  290. package/skills/cm-content-factory/examples/12-dental-clinic.config.json +0 -147
  291. package/skills/cm-content-factory/examples/13-pet-care.config.json +0 -147
  292. package/skills/cm-content-factory/examples/14-travel-hospitality.config.json +0 -147
  293. package/skills/cm-content-factory/examples/15-ai-automation.config.json +0 -147
  294. package/skills/cm-content-factory/examples/16-wedding-events.config.json +0 -147
  295. package/skills/cm-content-factory/examples/17-fitness-coaching.config.json +0 -148
  296. package/skills/cm-content-factory/examples/18-cybersecurity.config.json +0 -147
  297. package/skills/cm-content-factory/examples/19-food-restaurant.config.json +0 -148
  298. package/skills/cm-content-factory/examples/20-solar-energy.config.json +0 -147
  299. package/skills/cm-content-factory/examples/fitness-blog.config.json +0 -116
  300. package/skills/cm-content-factory/examples/tech-blog.config.json +0 -107
  301. package/skills/cm-content-factory/extensions/EXTENSION_GUIDE.md +0 -72
  302. package/skills/cm-content-factory/extensions/hooks.py +0 -126
  303. package/skills/cm-content-factory/extensions/openclaw_adapter.py +0 -132
  304. package/skills/cm-content-factory/landing/docs/content/changelog.md +0 -36
  305. package/skills/cm-content-factory/landing/docs/content/deployment.md +0 -46
  306. package/skills/cm-content-factory/landing/docs/content/execution-flow.md +0 -67
  307. package/skills/cm-content-factory/landing/docs/content/openspace.md +0 -27
  308. package/skills/cm-content-factory/landing/docs/content/openviking.md +0 -33
  309. package/skills/cm-content-factory/landing/docs/content/use-cases.md +0 -26
  310. package/skills/cm-content-factory/landing/docs/content/v5-intro.md +0 -28
  311. package/skills/cm-content-factory/landing/docs/index.html +0 -240
  312. package/skills/cm-content-factory/landing/index.html +0 -680
  313. package/skills/cm-content-factory/landing/script.js +0 -143
  314. package/skills/cm-content-factory/landing/style.css +0 -1216
  315. package/skills/cm-content-factory/landing/translations.js +0 -508
  316. package/skills/cm-content-factory/logs/events.jsonl +0 -11
  317. package/skills/cm-content-factory/profiles/_template.profile.json +0 -231
  318. package/skills/cm-content-factory/profiles/finance.profile.json +0 -278
  319. package/skills/cm-content-factory/profiles/legal.profile.json +0 -263
  320. package/skills/cm-content-factory/profiles/medical-research.profile.json +0 -321
  321. package/skills/cm-content-factory/profiles/technology.profile.json +0 -275
  322. package/skills/cm-content-factory/scripts/agent_dispatcher.py +0 -266
  323. package/skills/cm-content-factory/scripts/audit.py +0 -106
  324. package/skills/cm-content-factory/scripts/dashboard_server.py +0 -225
  325. package/skills/cm-content-factory/scripts/deploy.py +0 -146
  326. package/skills/cm-content-factory/scripts/extract.py +0 -132
  327. package/skills/cm-content-factory/scripts/landing_generator.py +0 -459
  328. package/skills/cm-content-factory/scripts/memory.py +0 -521
  329. package/skills/cm-content-factory/scripts/monetize.py +0 -239
  330. package/skills/cm-content-factory/scripts/pipeline.py +0 -357
  331. package/skills/cm-content-factory/scripts/plan.py +0 -163
  332. package/skills/cm-content-factory/scripts/publish.py +0 -145
  333. package/skills/cm-content-factory/scripts/research.py +0 -337
  334. package/skills/cm-content-factory/scripts/scaffold.py +0 -464
  335. package/skills/cm-content-factory/scripts/scoreboard.py +0 -336
  336. package/skills/cm-content-factory/scripts/seo.py +0 -90
  337. package/skills/cm-content-factory/scripts/state_manager.py +0 -320
  338. package/skills/cm-content-factory/scripts/token_manager.py +0 -268
  339. package/skills/cm-content-factory/scripts/validate.py +0 -221
  340. package/skills/cm-content-factory/scripts/wizard.py +0 -329
  341. package/skills/cm-content-factory/scripts/write.py +0 -93
  342. package/skills/cm-content-factory/sites/docs-site/src/assets/houston.webp +0 -0
  343. package/skills/cm-content-factory/sites/docs-site/src/content/docs/architecture.md +0 -90
  344. package/skills/cm-content-factory/sites/docs-site/src/content/docs/data-flow.md +0 -54
  345. package/skills/cm-content-factory/sites/docs-site/src/content/docs/deployment.md +0 -38
  346. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/index.md +0 -65
  347. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/lc-content-lifecycle.md +0 -48
  348. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/seq-write-mode.md +0 -39
  349. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/uj-first-batch.md +0 -42
  350. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/wf-content-pipeline.md +0 -51
  351. package/skills/cm-content-factory/sites/docs-site/src/content/docs/flows/wf-learning-cycle.md +0 -52
  352. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/configuration.md +0 -86
  353. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/installation.md +0 -80
  354. package/skills/cm-content-factory/sites/docs-site/src/content/docs/getting-started/intro.md +0 -58
  355. package/skills/cm-content-factory/sites/docs-site/src/content/docs/index.md +0 -102
  356. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/index.md +0 -45
  357. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/optimize-seo.md +0 -29
  358. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/scale-content-production.md +0 -55
  359. package/skills/cm-content-factory/sites/docs-site/src/content/docs/jtbd/standardize-quality.md +0 -29
  360. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/buyer-cmo-huong.md +0 -41
  361. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/buyer-content-lead-khoa.md +0 -40
  362. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/index.md +0 -56
  363. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-content-manager-lan.md +0 -46
  364. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-seo-minh.md +0 -45
  365. package/skills/cm-content-factory/sites/docs-site/src/content/docs/personas/user-writer-tu.md +0 -45
  366. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/content-pipeline.md +0 -108
  367. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/index.md +0 -22
  368. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/memory-system.md +0 -52
  369. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/seo-optimization.md +0 -58
  370. package/skills/cm-content-factory/sites/docs-site/src/content/docs/sop/troubleshooting-guide.md +0 -92
  371. package/skills/cm-content-factory/sites/docs-site/src/styles/custom.css +0 -575
  372. package/skills/cm-content-factory/tests/conftest.py +0 -66
  373. package/skills/cm-content-factory/tests/test_agent_dispatcher.py +0 -125
  374. package/skills/cm-content-factory/tests/test_memory.py +0 -128
  375. package/skills/cm-content-factory/tests/test_pipeline.py +0 -107
  376. package/skills/cm-content-factory/tests/test_research.py +0 -56
  377. package/skills/cm-content-factory/tests/test_state_manager.py +0 -131
  378. package/skills/cm-content-factory/tests/test_token_manager.py +0 -110
  379. package/skills/cm-content-factory/tests/test_wizard.py +0 -121
  380. package/skills/cm-cro-methodology/SKILL.md +0 -290
  381. package/skills/cm-cro-methodology/references/COPYWRITING.md +0 -178
  382. package/skills/cm-cro-methodology/references/OBJECTIONS.md +0 -135
  383. package/skills/cm-cro-methodology/references/PERSUASION.md +0 -158
  384. package/skills/cm-cro-methodology/references/RESEARCH.md +0 -220
  385. package/skills/cm-cro-methodology/references/funnel-analysis.md +0 -365
  386. package/skills/cm-cro-methodology/references/testing-methodology.md +0 -330
  387. package/skills/cm-google-form/SKILL.md +0 -266
  388. package/skills/cm-google-form/templates/apps-script.js +0 -55
  389. package/skills/cm-google-form/templates/form-markup.html +0 -110
  390. package/skills/cm-google-form/templates/form-submit.js +0 -201
  391. package/skills/cm-google-form/templates/toast.css +0 -152
  392. package/skills/cm-growth-hacking/SKILL.md +0 -282
  393. package/skills/cm-growth-hacking/bottom-sheet-engine.md +0 -261
  394. package/skills/cm-growth-hacking/calendar-integration.md +0 -264
  395. package/skills/cm-growth-hacking/references/engagement-patterns.md +0 -346
  396. package/skills/cm-growth-hacking/templates/bottom-sheet.css +0 -528
  397. package/skills/cm-growth-hacking/templates/bottom-sheet.js +0 -269
  398. package/skills/cm-growth-hacking/templates/calendar-cta.js +0 -213
  399. package/skills/cm-growth-hacking/templates/tracking-events.js +0 -211
  400. package/skills/cm-growth-hacking/templates/trigger-manager.js +0 -254
  401. package/skills/cm-growth-hacking/tracking-events.md +0 -246
  402. package/skills/cm-growth-hacking/trigger-system.md +0 -342
  403. package/skills/cm-jtbd/SKILL.md +0 -98
  404. package/skills/cm-notebooklm/SKILL.md +0 -156
  405. package/skills/cm-notebooklm/references/command_reference.md +0 -94
  406. package/skills/cm-notebooklm/references/workflows.md +0 -60
  407. package/skills/cm-notebooklm/resources/knowledge_sources.md +0 -106
  408. package/skills/cm-notebooklm/scripts/brain-sync.sh +0 -453
  409. package/skills/cm-notebooklm/scripts/graduate_wisdom.py +0 -101
  410. package/skills/cm-readit/SKILL.md +0 -289
  411. package/skills/cm-readit/audio-player.md +0 -206
  412. package/skills/cm-readit/examples/blog-reader.js +0 -352
  413. package/skills/cm-readit/examples/voice-cro.js +0 -390
  414. package/skills/cm-readit/tts-engine.md +0 -262
  415. package/skills/cm-readit/ui-patterns.md +0 -362
  416. package/skills/cm-readit/voice-cro.md +0 -223
@@ -1,269 +0,0 @@
1
- /**
2
- * CM Growth Hacking — BottomSheetEngine
3
- *
4
- * Universal bottom sheet component.
5
- * Create, show, hide, swipe-to-dismiss, multi-step content.
6
- * Zero dependencies.
7
- *
8
- * Usage:
9
- * const sheet = new BottomSheetEngine({
10
- * id: 'booking',
11
- * size: 'standard',
12
- * content: '<h3>Đặt Lịch</h3>...',
13
- * backdrop: false,
14
- * onDismiss: () => trackEngagement('cro_sheet_dismissed'),
15
- * onShow: () => trackEngagement('cro_sheet_shown'),
16
- * });
17
- * sheet.show();
18
- */
19
-
20
- (function () {
21
- 'use strict';
22
-
23
- const SWIPE_THRESHOLD = 80; // px to trigger dismiss
24
- const VELOCITY_THRESHOLD = 0.5; // px/ms for fast swipe
25
-
26
- class BottomSheetEngine {
27
- constructor(config) {
28
- this.config = {
29
- id: config.id || 'eng-sheet-' + Date.now(),
30
- size: config.size || 'standard', // compact | standard | full
31
- content: config.content || '',
32
- backdrop: config.backdrop ?? false, // show backdrop overlay
33
- dismissible: config.dismissible ?? true,
34
- swipeToDismiss: config.swipeToDismiss ?? true,
35
- closeButton: config.closeButton ?? true,
36
- ariaLabel: config.ariaLabel || 'Dialog',
37
- desktopPosition: config.desktopPosition || 'center', // center | right
38
- onDismiss: config.onDismiss || null,
39
- onShow: config.onShow || null,
40
- };
41
-
42
- this.el = null;
43
- this.backdropEl = null;
44
- this.isVisible = false;
45
- this._previousFocus = null;
46
- this._shownAt = null;
47
-
48
- // Touch tracking
49
- this._startY = 0;
50
- this._startTime = 0;
51
- this._currentY = 0;
52
-
53
- this._build();
54
- }
55
-
56
- // ─── DOM Construction ───────────────────────────────
57
- _build() {
58
- // Backdrop
59
- if (this.config.backdrop) {
60
- this.backdropEl = document.createElement('div');
61
- this.backdropEl.className = 'eng-backdrop';
62
- this.backdropEl.dataset.sheetId = this.config.id;
63
- if (this.config.dismissible) {
64
- this.backdropEl.addEventListener('click', () => this.hide());
65
- }
66
- }
67
-
68
- // Sheet
69
- this.el = document.createElement('div');
70
- this.el.className = `eng-sheet eng-sheet--${this.config.size}`;
71
- if (this.config.desktopPosition === 'right') {
72
- this.el.classList.add('eng-sheet--desktop-right');
73
- }
74
- this.el.dataset.sheetId = this.config.id;
75
- this.el.setAttribute('role', 'dialog');
76
- this.el.setAttribute('aria-modal', this.config.backdrop ? 'true' : 'false');
77
- this.el.setAttribute('aria-label', this.config.ariaLabel);
78
-
79
- const inner = document.createElement('div');
80
- inner.className = 'eng-sheet__inner';
81
-
82
- // Handle
83
- const handle = document.createElement('div');
84
- handle.className = 'eng-sheet__handle';
85
- handle.setAttribute('aria-hidden', 'true');
86
- const handleBar = document.createElement('div');
87
- handleBar.className = 'eng-sheet__handle-bar';
88
- handle.appendChild(handleBar);
89
- inner.appendChild(handle);
90
-
91
- // Close button
92
- if (this.config.closeButton && this.config.dismissible) {
93
- const close = document.createElement('button');
94
- close.className = 'eng-sheet__close';
95
- close.setAttribute('aria-label', 'Đóng');
96
- close.textContent = '✕';
97
- close.addEventListener('click', () => this.hide());
98
- inner.appendChild(close);
99
- }
100
-
101
- // Content
102
- this._contentEl = document.createElement('div');
103
- this._contentEl.className = 'eng-sheet__content';
104
- this._contentEl.innerHTML = this.config.content;
105
- inner.appendChild(this._contentEl);
106
-
107
- this.el.appendChild(inner);
108
-
109
- // Touch events for swipe-to-dismiss
110
- if (this.config.swipeToDismiss) {
111
- this._initSwipe(handle);
112
- }
113
-
114
- // Keyboard: Escape to close
115
- if (this.config.dismissible) {
116
- this._onKeyDown = (e) => {
117
- if (e.key === 'Escape' && this.isVisible) {
118
- this.hide();
119
- }
120
- };
121
- document.addEventListener('keydown', this._onKeyDown);
122
- }
123
- }
124
-
125
- // ─── Swipe-to-Dismiss ───────────────────────────────
126
- _initSwipe(handle) {
127
- handle.addEventListener('touchstart', (e) => {
128
- this._startY = e.touches[0].clientY;
129
- this._startTime = Date.now();
130
- this.el.classList.add('dragging');
131
- }, { passive: true });
132
-
133
- handle.addEventListener('touchmove', (e) => {
134
- const dy = e.touches[0].clientY - this._startY;
135
- this._currentY = dy;
136
- if (dy > 0) {
137
- // Only allow downward drag
138
- this.el.style.transform = `translateY(${dy}px)`;
139
- }
140
- }, { passive: true });
141
-
142
- handle.addEventListener('touchend', () => {
143
- this.el.classList.remove('dragging');
144
- const elapsed = Date.now() - this._startTime;
145
- const velocity = this._currentY / elapsed; // px/ms
146
-
147
- if (this._currentY > SWIPE_THRESHOLD || velocity > VELOCITY_THRESHOLD) {
148
- this.hide();
149
- } else {
150
- // Snap back
151
- this.el.style.transform = '';
152
- requestAnimationFrame(() => {
153
- this.el.classList.add('active');
154
- });
155
- }
156
- this._currentY = 0;
157
- }, { passive: true });
158
- }
159
-
160
- // ─── Public API ─────────────────────────────────────
161
-
162
- show() {
163
- if (this.isVisible) return;
164
-
165
- this._previousFocus = document.activeElement;
166
- this._shownAt = Date.now();
167
-
168
- // Append to DOM
169
- if (this.backdropEl) document.body.appendChild(this.backdropEl);
170
- document.body.appendChild(this.el);
171
-
172
- // Trigger animation (double rAF for initial paint)
173
- requestAnimationFrame(() => {
174
- requestAnimationFrame(() => {
175
- if (this.backdropEl) this.backdropEl.classList.add('active');
176
- this.el.classList.add('active');
177
- this.el.style.transform = '';
178
- });
179
- });
180
-
181
- this.isVisible = true;
182
-
183
- // Focus trap: focus the sheet
184
- const firstFocusable = this.el.querySelector('button, a, input, select, textarea');
185
- if (firstFocusable) firstFocusable.focus();
186
-
187
- if (typeof this.config.onShow === 'function') {
188
- this.config.onShow(this);
189
- }
190
- }
191
-
192
- hide() {
193
- if (!this.isVisible) return;
194
-
195
- if (this.backdropEl) this.backdropEl.classList.remove('active');
196
- this.el.classList.remove('active');
197
- this.el.style.transform = 'translateY(100%)';
198
-
199
- this.isVisible = false;
200
-
201
- const visibleDuration = this._shownAt ? Date.now() - this._shownAt : 0;
202
-
203
- // Remove from DOM after animation
204
- setTimeout(() => {
205
- if (this.backdropEl && this.backdropEl.parentNode) {
206
- this.backdropEl.remove();
207
- }
208
- if (this.el.parentNode) {
209
- this.el.remove();
210
- }
211
- }, 400);
212
-
213
- // Restore focus
214
- if (this._previousFocus) {
215
- this._previousFocus.focus();
216
- }
217
-
218
- if (typeof this.config.onDismiss === 'function') {
219
- this.config.onDismiss(this, visibleDuration);
220
- }
221
- }
222
-
223
- setContent(html) {
224
- if (this._contentEl) {
225
- this._contentEl.innerHTML = html;
226
- }
227
- }
228
-
229
- setSize(size) {
230
- this.el.classList.remove('eng-sheet--compact', 'eng-sheet--standard', 'eng-sheet--full');
231
- this.el.classList.add(`eng-sheet--${size}`);
232
- }
233
-
234
- destroy() {
235
- this.hide();
236
- if (this._onKeyDown) {
237
- document.removeEventListener('keydown', this._onKeyDown);
238
- }
239
- this.el = null;
240
- this.backdropEl = null;
241
- }
242
- }
243
-
244
- // ─── Toast Helper ───────────────────────────────────
245
- function showToast(type, message, duration) {
246
- const toast = document.createElement('div');
247
- toast.className = `eng-toast eng-toast--${type}`;
248
- toast.textContent = message;
249
- document.body.appendChild(toast);
250
-
251
- requestAnimationFrame(() => {
252
- requestAnimationFrame(() => {
253
- toast.classList.add('active');
254
- });
255
- });
256
-
257
- const autoDismiss = duration || (type === 'success' ? 4000 : type === 'error' ? 8000 : 5000);
258
-
259
- setTimeout(() => {
260
- toast.classList.remove('active');
261
- setTimeout(() => toast.remove(), 300);
262
- }, autoDismiss);
263
- }
264
-
265
- // ─── Export ─────────────────────────────────────────
266
- window.BottomSheetEngine = BottomSheetEngine;
267
- window.showEngToast = showToast;
268
-
269
- })();
@@ -1,213 +0,0 @@
1
- /**
2
- * CM Growth Hacking — Calendar CTA
3
- *
4
- * Post-action calendar buttons: Google Calendar deep link + ICS download.
5
- * Smart device routing: iOS → ICS, Android → GCal, Desktop → both.
6
- *
7
- * Kế thừa logic từ cm-booking-calendar/calendar-export.js
8
- *
9
- * Usage:
10
- * const html = CalendarCTA.render(event, config);
11
- * sheet.setContent(html);
12
- *
13
- * CalendarCTA.addToGoogleCal(event, config);
14
- * CalendarCTA.downloadICS(event, config);
15
- * CalendarCTA.autoRoute(event, config); // device-aware
16
- */
17
-
18
- (function () {
19
- 'use strict';
20
-
21
- const CalendarCTA = {
22
-
23
- // ─── Device Detection ─────────────────────────────
24
- detectDevice() {
25
- const ua = navigator.userAgent;
26
- if (/iPhone|iPad|iPod/.test(ua)) return 'ios';
27
- if (/Android/.test(ua)) return 'android';
28
- return 'desktop';
29
- },
30
-
31
- // ─── Google Calendar Deep Link ────────────────────
32
- buildGoogleCalUrl(event, config) {
33
- const startDate = new Date(event.date + 'T' + (event.time || '09:00'));
34
- const endDate = new Date(startDate.getTime() + (config.duration || 60) * 60 * 1000);
35
-
36
- const formatGCal = (d) => d.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
37
-
38
- const description = [
39
- event.description || event.service || '',
40
- '',
41
- config.clinicName ? '📍 ' + config.clinicName : '',
42
- config.address ? '📌 ' + config.address : '',
43
- config.phone ? '📞 ' + config.phone : '',
44
- config.mapsUrl ? '🗺️ ' + config.mapsUrl : '',
45
- '',
46
- config.preparation ? '⚠️ Lưu ý: ' + config.preparation : '',
47
- ].filter(Boolean).join('\n');
48
-
49
- const params = new URLSearchParams({
50
- action: 'TEMPLATE',
51
- text: event.title || (event.service + ' — ' + (config.clinicName || '')),
52
- dates: formatGCal(startDate) + '/' + formatGCal(endDate),
53
- details: description,
54
- location: config.address || '',
55
- sf: 'true',
56
- output: 'xml',
57
- });
58
-
59
- return 'https://calendar.google.com/calendar/render?' + params.toString();
60
- },
61
-
62
- addToGoogleCal(event, config) {
63
- const url = this.buildGoogleCalUrl(event, config);
64
- window.open(url, '_blank', 'noopener');
65
- },
66
-
67
- // ─── ICS File Generation (RFC 5545) ───────────────
68
- buildICSContent(event, config) {
69
- const uid = Date.now() + '-' + Math.random().toString(36).substr(2, 9) + '@' + (window.location.hostname || 'cm-growth-hacking');
70
-
71
- const startDate = new Date(event.date + 'T' + (event.time || '09:00'));
72
- const endDate = new Date(startDate.getTime() + (config.duration || 60) * 60 * 1000);
73
- const now = new Date();
74
-
75
- const formatICS = (d) => d.toISOString().replace(/[-:]/g, '').replace(/\.\d{3}/, '');
76
-
77
- const escapeICS = (str) => (str || '').replace(/\n/g, '\\n').replace(/,/g, '\\,').replace(/;/g, '\\;');
78
-
79
- const description = escapeICS([
80
- event.description || event.service || '',
81
- '',
82
- config.clinicName ? '📍 ' + config.clinicName : '',
83
- config.address ? '📌 ' + config.address : '',
84
- config.phone ? '📞 ' + config.phone : '',
85
- config.preparation ? '⚠️ ' + config.preparation : '',
86
- ].filter(Boolean).join('\n'));
87
-
88
- const lines = [
89
- 'BEGIN:VCALENDAR',
90
- 'VERSION:2.0',
91
- 'PRODID:-//CMGrowthHacking//Calendar//VI',
92
- 'CALSCALE:GREGORIAN',
93
- 'METHOD:PUBLISH',
94
- 'BEGIN:VEVENT',
95
- 'UID:' + uid,
96
- 'DTSTAMP:' + formatICS(now),
97
- 'DTSTART:' + formatICS(startDate),
98
- 'DTEND:' + formatICS(endDate),
99
- 'SUMMARY:' + escapeICS(event.title || (event.service + ' — ' + (config.clinicName || ''))),
100
- 'DESCRIPTION:' + description,
101
- 'LOCATION:' + escapeICS(config.address || ''),
102
- ];
103
-
104
- if (config.mapsUrl) {
105
- lines.push('URL:' + config.mapsUrl);
106
- }
107
-
108
- // Add reminders (VALARM)
109
- const reminders = config.reminderMinutes || [1440, 120]; // 1 day + 2h
110
- reminders.forEach(function (minutes) {
111
- const reminderText = minutes >= 1440
112
- ? 'Nhắc trước ' + (minutes / 1440) + ' ngày'
113
- : minutes >= 60
114
- ? 'Nhắc trước ' + (minutes / 60) + ' giờ'
115
- : 'Nhắc trước ' + minutes + ' phút';
116
-
117
- lines.push(
118
- 'BEGIN:VALARM',
119
- 'TRIGGER:-PT' + minutes + 'M',
120
- 'ACTION:DISPLAY',
121
- 'DESCRIPTION:' + escapeICS((event.title || event.service) + ' — ' + reminderText),
122
- 'END:VALARM'
123
- );
124
- });
125
-
126
- lines.push('END:VEVENT', 'END:VCALENDAR');
127
-
128
- return lines.join('\r\n');
129
- },
130
-
131
- downloadICS(event, config) {
132
- const content = this.buildICSContent(event, config);
133
- const filename = (event.service || 'appointment').replace(/\s+/g, '-').toLowerCase() + '.ics';
134
-
135
- const blob = new Blob([content], { type: 'text/calendar;charset=utf-8' });
136
- const url = URL.createObjectURL(blob);
137
- const a = document.createElement('a');
138
- a.href = url;
139
- a.download = filename;
140
- document.body.appendChild(a);
141
- a.click();
142
- document.body.removeChild(a);
143
- URL.revokeObjectURL(url);
144
- },
145
-
146
- // ─── Auto-Route by Device ─────────────────────────
147
- autoRoute(event, config) {
148
- const device = this.detectDevice();
149
- if (device === 'ios') {
150
- this.downloadICS(event, config);
151
- } else {
152
- this.addToGoogleCal(event, config);
153
- }
154
- },
155
-
156
- // ─── Render Calendar CTA HTML ─────────────────────
157
- render(event, config) {
158
- const device = this.detectDevice();
159
- let buttonsHTML = '';
160
-
161
- if (device === 'ios') {
162
- buttonsHTML = '<button class="eng-btn eng-btn--primary eng-btn--full" data-cal-action="ics">'
163
- + '📥 Thêm vào Apple Calendar</button>';
164
- } else if (device === 'android') {
165
- buttonsHTML = '<button class="eng-btn eng-btn--primary eng-btn--full" data-cal-action="gcal">'
166
- + '📅 Thêm vào Google Calendar</button>';
167
- } else {
168
- buttonsHTML = '<button class="eng-btn eng-btn--gcal" data-cal-action="gcal">'
169
- + '📅 Google Calendar</button>'
170
- + '<button class="eng-btn eng-btn--ics" data-cal-action="ics">'
171
- + '📥 Tải file lịch (.ics)</button>';
172
- }
173
-
174
- const reminderHours = config.reminderMinutes
175
- ? Math.round(config.reminderMinutes[0] / 60)
176
- : 24;
177
-
178
- const html = '<div class="eng-content-calendar">'
179
- + '<div class="eng-content__icon">✅</div>'
180
- + '<h3 class="eng-content__title">' + (config.successTitle || 'Thành công!') + '</h3>'
181
- + '<p class="eng-content__subtitle">' + (config.successSubtitle || 'Thêm vào lịch để không quên nhé') + '</p>'
182
- + '<div class="eng-calendar-buttons">' + buttonsHTML + '</div>'
183
- + '<p class="eng-content__benefit">💡 Lịch sẽ tự nhắc bạn trước '
184
- + reminderHours + 'h — hoàn toàn miễn phí</p>'
185
- + '</div>';
186
-
187
- return html;
188
- },
189
-
190
- // ─── Attach Click Handlers ────────────────────────
191
- attachHandlers(container, event, config, onAdd) {
192
- const self = this;
193
- const buttons = container.querySelectorAll('[data-cal-action]');
194
- buttons.forEach(function (btn) {
195
- btn.addEventListener('click', function () {
196
- const action = btn.dataset.calAction;
197
- if (action === 'gcal') {
198
- self.addToGoogleCal(event, config);
199
- } else if (action === 'ics') {
200
- self.downloadICS(event, config);
201
- }
202
- if (typeof onAdd === 'function') {
203
- onAdd(action);
204
- }
205
- });
206
- });
207
- },
208
- };
209
-
210
- // ─── Export ─────────────────────────────────────────
211
- window.CalendarCTA = CalendarCTA;
212
-
213
- })();
@@ -1,211 +0,0 @@
1
- /**
2
- * CM Growth Hacking — Tracking Events
3
- *
4
- * Engagement-specific dataLayer push helpers.
5
- * Compatible with cm-ads-tracker GTM architecture.
6
- *
7
- * Usage:
8
- * trackEngagement('cro_sheet_shown', { sheet_type: 'booking', trigger_type: 'scroll' });
9
- * trackEngagement('cro_booking_submit', { content_name: 'Khám thai', value: 500000 });
10
- * trackEngagement('cro_calendar_add', { calendar_type: 'gcal' });
11
- */
12
-
13
- (function () {
14
- 'use strict';
15
-
16
- // ─── UUID Generator ─────────────────────────────────
17
- function generateUUID() {
18
- if (typeof crypto !== 'undefined' && crypto.randomUUID) {
19
- return crypto.randomUUID();
20
- }
21
- return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
22
- var r = Math.random() * 16 | 0;
23
- var v = c === 'x' ? r : (r & 0x3 | 0x8);
24
- return v.toString(16);
25
- });
26
- }
27
-
28
- // ─── SHA256 Hash ────────────────────────────────────
29
- function sha256Hash(value) {
30
- if (typeof crypto === 'undefined' || !crypto.subtle) {
31
- return Promise.resolve('');
32
- }
33
- var encoder = new TextEncoder();
34
- var data = encoder.encode(value.toLowerCase().trim());
35
- return crypto.subtle.digest('SHA-256', data).then(function (hash) {
36
- return Array.from(new Uint8Array(hash))
37
- .map(function (b) { return b.toString(16).padStart(2, '0'); })
38
- .join('');
39
- });
40
- }
41
-
42
- function hashPhone(phone) {
43
- var digits = (phone || '').replace(/\D/g, '');
44
- return sha256Hash(digits);
45
- }
46
-
47
- // ─── Core Tracker ───────────────────────────────────
48
- function trackEngagement(eventName, data) {
49
- var payload = {
50
- event: eventName,
51
- event_id: generateUUID(),
52
- page_path: window.location.pathname,
53
- page_url: window.location.href,
54
- timestamp: Date.now(),
55
- };
56
-
57
- // Merge extra data
58
- if (data && typeof data === 'object') {
59
- for (var key in data) {
60
- if (data.hasOwnProperty(key)) {
61
- payload[key] = data[key];
62
- }
63
- }
64
- }
65
-
66
- // Push to GTM dataLayer
67
- window.dataLayer = window.dataLayer || [];
68
- window.dataLayer.push(payload);
69
-
70
- // Store locally for debug/analytics
71
- _storeLocal(payload);
72
-
73
- return payload;
74
- }
75
-
76
- // ─── Local Analytics Storage ────────────────────────
77
- var LOCAL_KEY = 'eng_analytics';
78
- var MAX_LOCAL_EVENTS = 100;
79
-
80
- function _storeLocal(payload) {
81
- try {
82
- var stored = JSON.parse(localStorage.getItem(LOCAL_KEY) || '[]');
83
- stored.push({
84
- event: payload.event,
85
- page: payload.page_path,
86
- time: new Date(payload.timestamp).toISOString(),
87
- data: payload
88
- });
89
- // Keep max events
90
- if (stored.length > MAX_LOCAL_EVENTS) {
91
- stored.splice(0, stored.length - MAX_LOCAL_EVENTS);
92
- }
93
- localStorage.setItem(LOCAL_KEY, JSON.stringify(stored));
94
- } catch (e) { /* noop */ }
95
- }
96
-
97
- // ─── Debug: Get Local Stats ─────────────────────────
98
- function getEngagementStats() {
99
- try {
100
- var events = JSON.parse(localStorage.getItem(LOCAL_KEY) || '[]');
101
- var stats = {};
102
-
103
- events.forEach(function (e) {
104
- var key = e.event;
105
- if (!stats[key]) stats[key] = { count: 0, last: null, pages: {} };
106
- stats[key].count++;
107
- stats[key].last = e.time;
108
- stats[key].pages[e.page] = (stats[key].pages[e.page] || 0) + 1;
109
- });
110
-
111
- console.table(stats);
112
- return stats;
113
- } catch (e) { return {}; }
114
- }
115
-
116
- // ─── Clear Local Stats ──────────────────────────────
117
- function clearEngagementStats() {
118
- try { localStorage.removeItem(LOCAL_KEY); }
119
- catch (e) { /* noop */ }
120
- }
121
-
122
- // ─── Preset Event Helpers ───────────────────────────
123
- var EngagementTracker = {
124
- // Sheet lifecycle
125
- sheetShown: function (sheetType, triggerType, extra) {
126
- return trackEngagement('cro_sheet_shown', Object.assign({
127
- sheet_type: sheetType,
128
- trigger_type: triggerType,
129
- }, extra || {}));
130
- },
131
-
132
- sheetDismissed: function (sheetType, method, timeVisible, interacted) {
133
- return trackEngagement('cro_sheet_dismissed', {
134
- sheet_type: sheetType,
135
- dismiss_method: method, // swipe | close_button | backdrop | escape
136
- time_visible: timeVisible || 0, // ms
137
- interacted: !!interacted,
138
- });
139
- },
140
-
141
- // Conversions
142
- bookingSubmit: function (serviceName, value, currency, extra) {
143
- return trackEngagement('cro_booking_submit', Object.assign({
144
- content_name: serviceName,
145
- value: value || 0,
146
- currency: currency || 'VND',
147
- source_sheet: true,
148
- }, extra || {}));
149
- },
150
-
151
- calendarAdd: function (calendarType, serviceName, extra) {
152
- return trackEngagement('cro_calendar_add', Object.assign({
153
- calendar_type: calendarType, // gcal | ics
154
- content_name: serviceName,
155
- device_type: _detectDeviceType(),
156
- }, extra || {}));
157
- },
158
-
159
- leadCapture: function (contentName, triggerType, value, extra) {
160
- return trackEngagement('cro_lead_capture', Object.assign({
161
- content_name: contentName,
162
- trigger_type: triggerType,
163
- value: value || 0,
164
- currency: 'VND',
165
- }, extra || {}));
166
- },
167
-
168
- promoEngage: function (promoName, extra) {
169
- return trackEngagement('cro_promo_engage', Object.assign({
170
- content_name: promoName,
171
- }, extra || {}));
172
- },
173
-
174
- surveyComplete: function (rating, hasFeedback, surveyType, extra) {
175
- return trackEngagement('cro_survey_complete', Object.assign({
176
- rating: rating,
177
- has_feedback: !!hasFeedback,
178
- survey_type: surveyType || 'post_service',
179
- }, extra || {}));
180
- },
181
-
182
- chatInitiate: function (channel, triggerType, extra) {
183
- return trackEngagement('cro_chat_initiate', Object.assign({
184
- channel: channel, // zalo | messenger | phone | whatsapp
185
- trigger_type: triggerType,
186
- }, extra || {}));
187
- },
188
-
189
- reengagement: function (visitCount, extra) {
190
- return trackEngagement('cro_reengagement', Object.assign({
191
- visit_count: visitCount,
192
- }, extra || {}));
193
- },
194
- };
195
-
196
- function _detectDeviceType() {
197
- var ua = navigator.userAgent;
198
- if (/iPhone|iPad|iPod/.test(ua)) return 'ios';
199
- if (/Android/.test(ua)) return 'android';
200
- return 'desktop';
201
- }
202
-
203
- // ─── Export ─────────────────────────────────────────
204
- window.trackEngagement = trackEngagement;
205
- window.EngagementTracker = EngagementTracker;
206
- window.getEngagementStats = getEngagementStats;
207
- window.clearEngagementStats = clearEngagementStats;
208
- window.sha256Hash = sha256Hash;
209
- window.hashPhone = hashPhone;
210
-
211
- })();