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,336 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Scoreboard — Reward/penalty tracking for self-learning content factory.
4
-
5
- Tracks content quality scores based on user feedback and pipeline outcomes.
6
- Higher scores → patterns reinforced. Lower scores → patterns avoided.
7
-
8
- Usage:
9
- python3 scoreboard.py --config content-factory.config.json --status
10
- python3 scoreboard.py --config content-factory.config.json --reward "Great article!" article.md
11
- python3 scoreboard.py --config content-factory.config.json --penalty "edited" article.md
12
- python3 scoreboard.py --config content-factory.config.json --detect-changes
13
- python3 scoreboard.py --config content-factory.config.json --leaderboard
14
- """
15
-
16
- import json
17
- import sys
18
- import os
19
- import re
20
- import subprocess
21
- import argparse
22
- from pathlib import Path
23
- from datetime import datetime
24
-
25
-
26
- DEFAULT_SCORING = {
27
- "reward_praise": 10,
28
- "reward_engagement": 5,
29
- "reward_first_pass": 3,
30
- "penalty_edit": -5,
31
- "penalty_delete": -10,
32
- "penalty_audit_fail": -3
33
- }
34
-
35
- PRAISE_KEYWORDS_VI = [
36
- "tốt", "hay", "giį»i", "xuįŗ„t sįŗÆc", "tuyệt vį»i", "đỉnh", "chįŗ„t lượng",
37
- "perfect", "great", "nice", "good", "awesome", "excellent", "LGTM"
38
- ]
39
-
40
- CRITICISM_KEYWORDS_VI = [
41
- "sį»­a", "fix", "sai", "lį»—i", "xoĆ”", "delete", "remove", "wrong",
42
- "dở", "tệ", "bad", "redo", "viįŗæt lįŗ”i", "chỉnh"
43
- ]
44
-
45
-
46
- class Scoreboard:
47
- """Reward/penalty tracking system."""
48
-
49
- def __init__(self, config_path: str):
50
- with open(config_path, "r", encoding="utf-8") as f:
51
- self.config = json.load(f)
52
-
53
- self.project_root = Path(config_path).resolve().parent
54
- mem_dir = self.project_root / self.config.get("memory", {}).get("memory_dir", "memory")
55
- self.scoreboard_file = mem_dir / "scoreboard.json"
56
- self.scoring_rules = {**DEFAULT_SCORING, **self.config.get("scoring", {})}
57
-
58
- # Ensure file exists
59
- mem_dir.mkdir(parents=True, exist_ok=True)
60
- if not self.scoreboard_file.exists():
61
- self._save({
62
- "total_score": 0,
63
- "lifetime_rewards": 0,
64
- "lifetime_penalties": 0,
65
- "articles": {},
66
- "events": [],
67
- "streaks": {"current_success": 0, "best_success": 0},
68
- "created_at": datetime.now().isoformat()
69
- })
70
-
71
- def _load(self) -> dict:
72
- with open(self.scoreboard_file, "r", encoding="utf-8") as f:
73
- return json.load(f)
74
-
75
- def _save(self, data: dict):
76
- data["updated_at"] = datetime.now().isoformat()
77
- with open(self.scoreboard_file, "w", encoding="utf-8") as f:
78
- json.dump(data, f, ensure_ascii=False, indent=2)
79
-
80
- def reward(self, reason: str, article: str = None, points: int = None):
81
- """Add reward points."""
82
- data = self._load()
83
-
84
- # Auto-detect reward type
85
- if points is None:
86
- if any(kw in reason.lower() for kw in PRAISE_KEYWORDS_VI):
87
- points = self.scoring_rules["reward_praise"]
88
- event_type = "praise"
89
- elif "engagement" in reason.lower() or "share" in reason.lower():
90
- points = self.scoring_rules["reward_engagement"]
91
- event_type = "engagement"
92
- elif "first_pass" in reason.lower() or "audit pass" in reason.lower():
93
- points = self.scoring_rules["reward_first_pass"]
94
- event_type = "first_pass"
95
- else:
96
- points = self.scoring_rules["reward_praise"]
97
- event_type = "general"
98
- else:
99
- event_type = "custom"
100
-
101
- data["total_score"] += points
102
- data["lifetime_rewards"] += points
103
-
104
- # Track per-article
105
- if article:
106
- art_key = Path(article).stem if "/" in article else article
107
- if art_key not in data["articles"]:
108
- data["articles"][art_key] = {"score": 0, "events": []}
109
- data["articles"][art_key]["score"] += points
110
- data["articles"][art_key]["events"].append({
111
- "type": event_type, "points": points,
112
- "reason": reason[:100], "at": datetime.now().isoformat()
113
- })
114
-
115
- # Update streak
116
- data["streaks"]["current_success"] += 1
117
- if data["streaks"]["current_success"] > data["streaks"]["best_success"]:
118
- data["streaks"]["best_success"] = data["streaks"]["current_success"]
119
-
120
- # Log event
121
- data["events"].append({
122
- "type": "reward", "event_type": event_type,
123
- "points": points, "article": article,
124
- "reason": reason[:100], "at": datetime.now().isoformat()
125
- })
126
-
127
- # Keep last 500 events
128
- data["events"] = data["events"][-500:]
129
-
130
- self._save(data)
131
- print(f" šŸ† +{points} points ({event_type}){f' → {article}' if article else ''}")
132
- return points
133
-
134
- def penalty(self, reason: str, article: str = None, points: int = None):
135
- """Subtract penalty points."""
136
- data = self._load()
137
-
138
- # Auto-detect penalty type
139
- if points is None:
140
- if any(kw in reason.lower() for kw in ["xoĆ”", "delete", "remove"]):
141
- points = self.scoring_rules["penalty_delete"]
142
- event_type = "delete"
143
- elif any(kw in reason.lower() for kw in ["sį»­a", "edit", "fix", "chỉnh"]):
144
- points = self.scoring_rules["penalty_edit"]
145
- event_type = "edit"
146
- elif "audit" in reason.lower() or "fail" in reason.lower():
147
- points = self.scoring_rules["penalty_audit_fail"]
148
- event_type = "audit_fail"
149
- else:
150
- points = self.scoring_rules["penalty_edit"]
151
- event_type = "general"
152
- else:
153
- event_type = "custom"
154
-
155
- data["total_score"] += points # points is negative
156
- data["lifetime_penalties"] += abs(points)
157
-
158
- # Track per-article
159
- if article:
160
- art_key = Path(article).stem if "/" in article else article
161
- if art_key not in data["articles"]:
162
- data["articles"][art_key] = {"score": 0, "events": []}
163
- data["articles"][art_key]["score"] += points
164
- data["articles"][art_key]["events"].append({
165
- "type": event_type, "points": points,
166
- "reason": reason[:100], "at": datetime.now().isoformat()
167
- })
168
-
169
- # Reset streak
170
- data["streaks"]["current_success"] = 0
171
-
172
- data["events"].append({
173
- "type": "penalty", "event_type": event_type,
174
- "points": points, "article": article,
175
- "reason": reason[:100], "at": datetime.now().isoformat()
176
- })
177
- data["events"] = data["events"][-500:]
178
-
179
- self._save(data)
180
- print(f" šŸ“‰ {points} points ({event_type}){f' → {article}' if article else ''}")
181
- return points
182
-
183
- def detect_changes(self) -> dict:
184
- """Detect git changes to auto-score edits and deletes."""
185
- content_dir = self.config["output"]["content_dir"]
186
-
187
- try:
188
- # Detect deleted files
189
- result = subprocess.run(
190
- ["git", "diff", "--name-only", "--diff-filter=D", "HEAD~5", "HEAD", content_dir],
191
- capture_output=True, text=True, cwd=str(self.project_root)
192
- )
193
- deleted = [f.strip() for f in result.stdout.strip().split('\n') if f.strip()]
194
-
195
- # Detect modified files
196
- result = subprocess.run(
197
- ["git", "diff", "--name-only", "--diff-filter=M", "HEAD~5", "HEAD", content_dir],
198
- capture_output=True, text=True, cwd=str(self.project_root)
199
- )
200
- modified = [f.strip() for f in result.stdout.strip().split('\n') if f.strip()]
201
-
202
- # Score deletes
203
- for f in deleted:
204
- self.penalty(f"File deleted: {f}", article=f)
205
-
206
- # Score user-edits (not auto-generated)
207
- for f in modified:
208
- # Check if edit was manual (not by pipeline)
209
- result = subprocess.run(
210
- ["git", "log", "-1", "--format=%s", "--", f],
211
- capture_output=True, text=True, cwd=str(self.project_root)
212
- )
213
- commit_msg = result.stdout.strip()
214
- if not commit_msg.startswith("auto:"):
215
- self.penalty(f"User edited: {f}", article=f)
216
-
217
- return {"deleted": len(deleted), "edited": len(modified)}
218
-
219
- except Exception as e:
220
- print(f" āš ļø Git detection error: {e}")
221
- return {"deleted": 0, "edited": 0}
222
-
223
- def auto_score_feedback(self, feedback: str, article: str = None):
224
- """Auto-detect sentiment and score accordingly."""
225
- feedback_lower = feedback.lower()
226
-
227
- if any(kw in feedback_lower for kw in PRAISE_KEYWORDS_VI):
228
- self.reward(feedback, article)
229
- elif any(kw in feedback_lower for kw in CRITICISM_KEYWORDS_VI):
230
- self.penalty(feedback, article)
231
- else:
232
- print(f" ā„¹ļø Neutral feedback — no score change")
233
-
234
- def get_leaderboard(self, top_n: int = 10) -> list:
235
- """Get top-scoring articles."""
236
- data = self._load()
237
- ranked = sorted(
238
- data.get("articles", {}).items(),
239
- key=lambda x: x[1].get("score", 0),
240
- reverse=True
241
- )
242
- return ranked[:top_n]
243
-
244
- def get_worst(self, top_n: int = 10) -> list:
245
- """Get worst-scoring articles (candidates for rewrite)."""
246
- data = self._load()
247
- ranked = sorted(
248
- data.get("articles", {}).items(),
249
- key=lambda x: x[1].get("score", 0)
250
- )
251
- return ranked[:top_n]
252
-
253
- def get_status(self) -> dict:
254
- """Get current scoreboard status."""
255
- data = self._load()
256
- return {
257
- "total_score": data.get("total_score", 0),
258
- "lifetime_rewards": data.get("lifetime_rewards", 0),
259
- "lifetime_penalties": data.get("lifetime_penalties", 0),
260
- "tracked_articles": len(data.get("articles", {})),
261
- "total_events": len(data.get("events", [])),
262
- "current_streak": data.get("streaks", {}).get("current_success", 0),
263
- "best_streak": data.get("streaks", {}).get("best_success", 0),
264
- "grade": _calc_grade(data.get("total_score", 0))
265
- }
266
-
267
-
268
- def _calc_grade(score: int) -> str:
269
- """Calculate grade from score."""
270
- if score >= 100: return "šŸ† S-Tier (Master)"
271
- if score >= 50: return "šŸ„‡ A-Tier (Expert)"
272
- if score >= 20: return "🄈 B-Tier (Skilled)"
273
- if score >= 0: return "šŸ„‰ C-Tier (Learning)"
274
- return "šŸ“‰ D-Tier (Needs Improvement)"
275
-
276
-
277
- def main():
278
- parser = argparse.ArgumentParser(description="Scoreboard — Reward/Penalty System")
279
- parser.add_argument("--config", required=True, help="Path to config JSON")
280
- parser.add_argument("--status", action="store_true", help="Show scoreboard")
281
- parser.add_argument("--reward", help="Add reward with reason")
282
- parser.add_argument("--penalty", help="Add penalty with reason")
283
- parser.add_argument("--feedback", help="Auto-detect sentiment from feedback")
284
- parser.add_argument("--detect-changes", action="store_true", help="Auto-score from git changes")
285
- parser.add_argument("--leaderboard", action="store_true", help="Show top articles")
286
- parser.add_argument("--worst", action="store_true", help="Show worst articles")
287
- parser.add_argument("article", nargs="?", help="Article slug or path")
288
- args = parser.parse_args()
289
-
290
- board = Scoreboard(args.config)
291
-
292
- if args.status:
293
- status = board.get_status()
294
- print(f"\n{'═' * 50}")
295
- print(f" šŸ“Š SCOREBOARD")
296
- print(f"{'═' * 50}")
297
- print(f" Grade: {status['grade']}")
298
- print(f" Total Score: {status['total_score']}")
299
- print(f" Rewards: +{status['lifetime_rewards']}")
300
- print(f" Penalties: -{status['lifetime_penalties']}")
301
- print(f" Articles: {status['tracked_articles']}")
302
- print(f" Streak: {status['current_streak']} (best: {status['best_streak']})")
303
- print(f"{'═' * 50}")
304
-
305
- elif args.reward:
306
- board.reward(args.reward, args.article)
307
-
308
- elif args.penalty:
309
- board.penalty(args.penalty, args.article)
310
-
311
- elif args.feedback:
312
- board.auto_score_feedback(args.feedback, args.article)
313
-
314
- elif args.detect_changes:
315
- print("šŸ” Detecting git changes...")
316
- changes = board.detect_changes()
317
- print(f" Deleted: {changes['deleted']}, Edited: {changes['edited']}")
318
-
319
- elif args.leaderboard:
320
- top = board.get_leaderboard()
321
- print(f"\nšŸ† TOP ARTICLES:")
322
- for slug, info in top:
323
- print(f" {info['score']:+4d} {slug}")
324
-
325
- elif args.worst:
326
- worst = board.get_worst()
327
- print(f"\nšŸ“‰ WORST ARTICLES (rewrite candidates):")
328
- for slug, info in worst:
329
- print(f" {info['score']:+4d} {slug}")
330
-
331
- else:
332
- parser.print_help()
333
-
334
-
335
- if __name__ == "__main__":
336
- main()
@@ -1,90 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- SEO Phase — Config-driven SEO extraction and optimization.
4
-
5
- Two sub-commands:
6
- extract: Scan content → CSV with current SEO metadata
7
- apply: Read optimized CSV → apply changes back to files
8
-
9
- Usage:
10
- python3 seo.py --config content-factory.config.json extract
11
- python3 seo.py --config content-factory.config.json apply
12
- python3 seo.py --config content-factory.config.json apply --dry-run
13
- """
14
-
15
- import json
16
- import sys
17
- import subprocess
18
- import argparse
19
- from pathlib import Path
20
-
21
-
22
- def load_config(config_path: str) -> dict:
23
- with open(config_path, "r", encoding="utf-8") as f:
24
- return json.load(f)
25
-
26
-
27
- def run_seo_extract(project_root: Path, config: dict, dry_run: bool):
28
- """Run SEO metadata extraction."""
29
- extractor = project_root / "scripts" / "seo_extract.py"
30
- if not extractor.exists():
31
- print(" āš ļø scripts/seo_extract.py not found.")
32
- return False
33
-
34
- if dry_run:
35
- print(f" [DRY RUN] Would extract SEO data from: {config['output']['content_dir']}")
36
- return True
37
-
38
- print(f" šŸ”Ž Extracting SEO metadata...")
39
- result = subprocess.run(["python3", str(extractor)], cwd=str(project_root))
40
- return result.returncode == 0
41
-
42
-
43
- def run_seo_apply(project_root: Path, config: dict, dry_run: bool):
44
- """Apply SEO optimizations from CSV."""
45
- applier = project_root / "scripts" / "seo_apply.py"
46
- if not applier.exists():
47
- print(" āš ļø scripts/seo_apply.py not found.")
48
- return False
49
-
50
- cmd = ["python3", str(applier)]
51
- if dry_run:
52
- cmd.append("--dry-run")
53
-
54
- print(f" šŸ“ Applying SEO changes...")
55
- result = subprocess.run(cmd, cwd=str(project_root))
56
- return result.returncode == 0
57
-
58
-
59
- def main():
60
- parser = argparse.ArgumentParser(description="SEO Phase — Extract & Apply")
61
- parser.add_argument("--config", required=True, help="Path to config JSON")
62
- parser.add_argument("action", nargs="?", default="extract",
63
- choices=["extract", "apply", "both"],
64
- help="Action: extract, apply, or both")
65
- parser.add_argument("--dry-run", action="store_true")
66
- parser.add_argument("--group", help="(unused, for pipeline compat)")
67
- args = parser.parse_args()
68
-
69
- config = load_config(args.config)
70
- project_root = Path(args.config).resolve().parent
71
-
72
- print(f"šŸ”Ž SEO Phase — Action: {args.action}")
73
-
74
- success = True
75
- if args.action in ("extract", "both"):
76
- success = run_seo_extract(project_root, config, args.dry_run) and success
77
-
78
- if args.action in ("apply", "both"):
79
- success = run_seo_apply(project_root, config, args.dry_run) and success
80
-
81
- if args.action == "extract" and success and not args.dry_run:
82
- csv_path = project_root / "scripts" / "seo_data.csv"
83
- print(f"\n šŸ’” Next: Optimize {csv_path}")
84
- print(f" Then run: python3 seo.py --config {args.config} apply")
85
-
86
- sys.exit(0 if success else 1)
87
-
88
-
89
- if __name__ == "__main__":
90
- main()