@caoscompanybr/merlin 3.5.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 (762) hide show
  1. package/.claude/CLAUDE.md +216 -0
  2. package/.claude/hooks/README-license-gate.md +45 -0
  3. package/.claude/hooks/auto-summarize.js +47 -0
  4. package/.claude/hooks/context-monitor.js +60 -0
  5. package/.claude/hooks/doc-sync.js +111 -0
  6. package/.claude/hooks/license-gate.cjs +59 -0
  7. package/.claude/hooks/session-reset.js +27 -0
  8. package/.claude/hooks/thoughts-indexer.js +80 -0
  9. package/.claude/rules/merlin-constitution.md +27 -0
  10. package/.merlin-core/commands/README.md +19 -0
  11. package/.merlin-core/commands/founder-mode.md +51 -0
  12. package/.merlin-core/commands/git/commit.md +35 -0
  13. package/.merlin-core/commands/git/describe-pr.md +43 -0
  14. package/.merlin-core/commands/git/safe-commit.md +182 -0
  15. package/.merlin-core/commands/implementation/implement-plan.md +129 -0
  16. package/.merlin-core/commands/implementation/oneshot.md +63 -0
  17. package/.merlin-core/commands/implementation/tdd.md +152 -0
  18. package/.merlin-core/commands/planning/create-plan.md +184 -0
  19. package/.merlin-core/commands/planning/iterate-plan.md +45 -0
  20. package/.merlin-core/commands/planning/validate-plan.md +48 -0
  21. package/.merlin-core/commands/research/analyze-issue.md +155 -0
  22. package/.merlin-core/commands/research/research-codebase.md +157 -0
  23. package/.merlin-core/commands/review/adversarial-review.md +112 -0
  24. package/.merlin-core/commands/review/check.md +91 -0
  25. package/.merlin-core/commands/review/debug.md +135 -0
  26. package/.merlin-core/commands/review/doubts.md +178 -0
  27. package/.merlin-core/commands/review/engineering-audit.md +87 -0
  28. package/.merlin-core/commands/review/local-review.md +48 -0
  29. package/.merlin-core/commands/review/verify-goals.md +83 -0
  30. package/.merlin-core/commands/session/capture-feedback.md +74 -0
  31. package/.merlin-core/commands/session/capture-learning.md +155 -0
  32. package/.merlin-core/commands/session/check-objectives.md +85 -0
  33. package/.merlin-core/commands/session/conclude.md +125 -0
  34. package/.merlin-core/commands/session/create-handoff.md +88 -0
  35. package/.merlin-core/commands/session/create-objective.md +111 -0
  36. package/.merlin-core/commands/session/create-process.md +105 -0
  37. package/.merlin-core/commands/session/create-reminder.md +86 -0
  38. package/.merlin-core/commands/session/fast-start.md +261 -0
  39. package/.merlin-core/commands/session/recall-learnings.md +79 -0
  40. package/.merlin-core/commands/session/recall-processes.md +74 -0
  41. package/.merlin-core/commands/session/resume-handoff.md +51 -0
  42. package/.merlin-core/commands/session/run-process.md +53 -0
  43. package/.merlin-core/commands/special/beauty.md +89 -0
  44. package/.merlin-core/commands/special/common-ground.md +114 -0
  45. package/.merlin-core/commands/special/elicit.md +98 -0
  46. package/.merlin-core/commands/special/party.md +66 -0
  47. package/.merlin-core/commands/special/scrape.md +78 -0
  48. package/.merlin-core/commands/special/skill-audit.md +128 -0
  49. package/.merlin-core/commands/special/start-here.md +132 -0
  50. package/.merlin-core/constitution.md +442 -0
  51. package/.merlin-core/core/README.md +19 -0
  52. package/.merlin-core/core/alkimia/README.md +20 -0
  53. package/.merlin-core/core/alkimia/context/context-tracker.js +209 -0
  54. package/.merlin-core/core/alkimia/domain/domain-loader.js +215 -0
  55. package/.merlin-core/core/alkimia/engine.js +284 -0
  56. package/.merlin-core/core/alkimia/layers/l0-constitution.js +47 -0
  57. package/.merlin-core/core/alkimia/layers/l1-global.js +58 -0
  58. package/.merlin-core/core/alkimia/layers/l2-agent.js +58 -0
  59. package/.merlin-core/core/alkimia/layers/l3-workflow.js +54 -0
  60. package/.merlin-core/core/alkimia/layers/l4-task.js +45 -0
  61. package/.merlin-core/core/alkimia/layers/l5-squad.js +161 -0
  62. package/.merlin-core/core/alkimia/layers/l6-skill.js +520 -0
  63. package/.merlin-core/core/alkimia/layers/l7-star-command.js +87 -0
  64. package/.merlin-core/core/alkimia/layers/layer-processor.js +78 -0
  65. package/.merlin-core/core/alkimia/mandate.js +46 -0
  66. package/.merlin-core/core/alkimia/memory/doc-sync.js +201 -0
  67. package/.merlin-core/core/alkimia/memory/document-sharder.js +272 -0
  68. package/.merlin-core/core/alkimia/memory/git-history-retriever.js +225 -0
  69. package/.merlin-core/core/alkimia/memory/memory-bridge.js +97 -0
  70. package/.merlin-core/core/alkimia/memory/session-analyzer.js +400 -0
  71. package/.merlin-core/core/alkimia/memory/thoughts-indexer.js +477 -0
  72. package/.merlin-core/core/alkimia/memory/thoughts-provider.js +603 -0
  73. package/.merlin-core/core/alkimia/output/formatter.js +464 -0
  74. package/.merlin-core/core/alkimia/security/content-sanitizer.js +140 -0
  75. package/.merlin-core/core/alkimia/skill-importer.js +440 -0
  76. package/.merlin-core/core/alkimia/squads/default/.synapse/manifest +17 -0
  77. package/.merlin-core/core/alkimia/utils/frontmatter.js +321 -0
  78. package/.merlin-core/core/alkimia/utils/tokens.js +24 -0
  79. package/.merlin-core/core/approval/README.md +16 -0
  80. package/.merlin-core/core/approval/approval-engine.js +380 -0
  81. package/.merlin-core/core/approval/channels/cli-channel.js +50 -0
  82. package/.merlin-core/core/config/README.md +17 -0
  83. package/.merlin-core/core/config/config-cache.js +182 -0
  84. package/.merlin-core/core/config/config-loader.js +279 -0
  85. package/.merlin-core/core/config/config-resolver.js +411 -0
  86. package/.merlin-core/core/config/env-interpolator.js +123 -0
  87. package/.merlin-core/core/config/merge-utils.js +102 -0
  88. package/.merlin-core/core/config/schemas/core-config.schema.json +41 -0
  89. package/.merlin-core/core/config/schemas/framework-config.schema.json +24 -0
  90. package/.merlin-core/core/config/schemas/local-config.schema.json +23 -0
  91. package/.merlin-core/core/config/schemas/project-config.schema.json +189 -0
  92. package/.merlin-core/core/docs-consistency.js +140 -0
  93. package/.merlin-core/core/events/event-bus.js +344 -0
  94. package/.merlin-core/core/events/hook-handler.js +419 -0
  95. package/.merlin-core/core/execution/README.md +17 -0
  96. package/.merlin-core/core/execution/attempt-journal.js +380 -0
  97. package/.merlin-core/core/execution/autonomous-build-loop.js +637 -0
  98. package/.merlin-core/core/execution/build-orchestrator.js +296 -0
  99. package/.merlin-core/core/execution/build-state-manager.js +196 -0
  100. package/.merlin-core/core/execution/context-injector.js +204 -0
  101. package/.merlin-core/core/execution/cron-engine.js +247 -0
  102. package/.merlin-core/core/execution/cron-expression.js +148 -0
  103. package/.merlin-core/core/execution/env-preflight.js +423 -0
  104. package/.merlin-core/core/execution/guardrail-engine.js +745 -0
  105. package/.merlin-core/core/execution/heartbeat-engine.js +198 -0
  106. package/.merlin-core/core/execution/model-router.js +282 -0
  107. package/.merlin-core/core/execution/parallel-executor.js +378 -0
  108. package/.merlin-core/core/execution/parallel-monitor.js +201 -0
  109. package/.merlin-core/core/execution/party-session.js +311 -0
  110. package/.merlin-core/core/execution/rate-limit-manager.js +152 -0
  111. package/.merlin-core/core/execution/result-aggregator.js +215 -0
  112. package/.merlin-core/core/execution/semantic-merge-engine.js +320 -0
  113. package/.merlin-core/core/execution/subagent-dispatcher.js +721 -0
  114. package/.merlin-core/core/execution/success-verifier.js +227 -0
  115. package/.merlin-core/core/execution/task-metadata.js +105 -0
  116. package/.merlin-core/core/execution/team-executor.js +195 -0
  117. package/.merlin-core/core/execution/two-tier-editor.js +290 -0
  118. package/.merlin-core/core/execution/version-snapshot.js +294 -0
  119. package/.merlin-core/core/execution/wave-executor.js +224 -0
  120. package/.merlin-core/core/health-check/health-engine.js +415 -0
  121. package/.merlin-core/core/licensing/activation.js +281 -0
  122. package/.merlin-core/core/licensing/crc.js +103 -0
  123. package/.merlin-core/core/licensing/entitlement.js +99 -0
  124. package/.merlin-core/core/licensing/fingerprint.js +104 -0
  125. package/.merlin-core/core/licensing/gate.js +133 -0
  126. package/.merlin-core/core/licensing/hmac.js +42 -0
  127. package/.merlin-core/core/licensing/key.js +144 -0
  128. package/.merlin-core/core/licensing/license.js +212 -0
  129. package/.merlin-core/core/mcp/README.md +16 -0
  130. package/.merlin-core/core/mcp/browser-capability.js +191 -0
  131. package/.merlin-core/core/mcp/capability-mapper.js +92 -0
  132. package/.merlin-core/core/mcp/mcp-connector.js +278 -0
  133. package/.merlin-core/core/mcp/mcp-registry.js +101 -0
  134. package/.merlin-core/core/orchestration/README.md +17 -0
  135. package/.merlin-core/core/orchestration/agent-invoker.js +456 -0
  136. package/.merlin-core/core/orchestration/condition-evaluator.js +250 -0
  137. package/.merlin-core/core/orchestration/decision-tree.js +192 -0
  138. package/.merlin-core/core/orchestration/executor-assignment.js +372 -0
  139. package/.merlin-core/core/orchestration/gate-evaluator.js +653 -0
  140. package/.merlin-core/core/orchestration/intent-classifier.js +579 -0
  141. package/.merlin-core/core/orchestration/lock-manager.js +308 -0
  142. package/.merlin-core/core/orchestration/master-orchestrator.js +363 -0
  143. package/.merlin-core/core/orchestration/phase-tool-masks.js +194 -0
  144. package/.merlin-core/core/orchestration/recovery-handler.js +402 -0
  145. package/.merlin-core/core/orchestration/reflect-checkpoint.js +431 -0
  146. package/.merlin-core/core/orchestration/session-state.js +430 -0
  147. package/.merlin-core/core/orchestration/skill-dispatcher.js +255 -0
  148. package/.merlin-core/core/orchestration/step-loader.js +226 -0
  149. package/.merlin-core/core/orchestration/workflow-executor.js +864 -0
  150. package/.merlin-core/core/process/executor.js +231 -0
  151. package/.merlin-core/core/process/process-file.js +50 -0
  152. package/.merlin-core/core/process/secret-scan.js +86 -0
  153. package/.merlin-core/core/process/signature.js +77 -0
  154. package/.merlin-core/core/quality-gates/README.md +17 -0
  155. package/.merlin-core/core/quality-gates/layer1-precommit.js +110 -0
  156. package/.merlin-core/core/quality-gates/layer2-pr-automation.js +116 -0
  157. package/.merlin-core/core/quality-gates/layer3-human-review.js +133 -0
  158. package/.merlin-core/core/registry/service-registry.js +140 -0
  159. package/.merlin-core/core-config.yaml +159 -0
  160. package/.merlin-core/development/README.md +17 -0
  161. package/.merlin-core/development/agents/README.md +16 -0
  162. package/.merlin-core/development/agents/analyst.md +214 -0
  163. package/.merlin-core/development/agents/architect.md +166 -0
  164. package/.merlin-core/development/agents/data-engineer.md +154 -0
  165. package/.merlin-core/development/agents/dev.md +203 -0
  166. package/.merlin-core/development/agents/devops.md +236 -0
  167. package/.merlin-core/development/agents/grimorio.md +125 -0
  168. package/.merlin-core/development/agents/merlin-master.md +173 -0
  169. package/.merlin-core/development/agents/meta.md +190 -0
  170. package/.merlin-core/development/agents/pm.md +145 -0
  171. package/.merlin-core/development/agents/po.md +172 -0
  172. package/.merlin-core/development/agents/qa.md +275 -0
  173. package/.merlin-core/development/agents/researcher.md +218 -0
  174. package/.merlin-core/development/agents/scout.md +179 -0
  175. package/.merlin-core/development/agents/sm.md +148 -0
  176. package/.merlin-core/development/agents/ux.md +169 -0
  177. package/.merlin-core/development/agents/web-researcher.md +203 -0
  178. package/.merlin-core/development/checklists/adversarial-review-checklist.md +70 -0
  179. package/.merlin-core/development/checklists/operations-ci-checklist.md +40 -0
  180. package/.merlin-core/development/checklists/operations-deploy-checklist.md +54 -0
  181. package/.merlin-core/development/checklists/operations-publish-checklist.md +47 -0
  182. package/.merlin-core/development/checklists/source-verification-checklist.md +38 -0
  183. package/.merlin-core/development/templates/HEARTBEAT-template.md +46 -0
  184. package/.merlin-core/development/templates/ears-requirements-template.md +93 -0
  185. package/.merlin-core/development/templates/handoff-template.md +50 -0
  186. package/.merlin-core/development/templates/prd-template.md +62 -0
  187. package/.merlin-core/development/templates/research-template.md +53 -0
  188. package/.merlin-core/development/templates/spec-template.md +84 -0
  189. package/.merlin-core/development/workflows/brownfield-discovery.yaml +166 -0
  190. package/.merlin-core/development/workflows/brownfield-service.yaml +52 -0
  191. package/.merlin-core/development/workflows/development-cycle.yaml +57 -0
  192. package/.merlin-core/development/workflows/epic-orchestration.yaml +47 -0
  193. package/.merlin-core/development/workflows/folloni-funnel.yaml +177 -0
  194. package/.merlin-core/development/workflows/greenfield-fullstack.yaml +167 -0
  195. package/.merlin-core/development/workflows/greenfield-service.yaml +56 -0
  196. package/.merlin-core/development/workflows/qa-loop.yaml +115 -0
  197. package/.merlin-core/development/workflows/spec-pipeline.yaml +185 -0
  198. package/.merlin-core/development/workflows/steps/folloni-01-research.yaml +35 -0
  199. package/.merlin-core/development/workflows/steps/folloni-02-architecture.yaml +41 -0
  200. package/.merlin-core/development/workflows/steps/folloni-03-implementation.yaml +52 -0
  201. package/.merlin-core/development/workflows/story-development-cycle.yaml +67 -0
  202. package/.merlin-core/docs/GUIDE.md +413 -0
  203. package/.merlin-core/docs/merlin-commands-guide-pt.md +183 -0
  204. package/.merlin-core/framework-config.yaml +148 -0
  205. package/.merlin-core/hooks/README.md +16 -0
  206. package/.merlin-core/hooks/precompact-memory-flush.js +69 -0
  207. package/.merlin-core/hooks/pretooluse-remote-approve.js +113 -0
  208. package/.merlin-core/hooks/spikes/spike-b-hook.js +70 -0
  209. package/.merlin-core/hooks/spikes/spike-b-stub.js +70 -0
  210. package/.merlin-core/index.js +91 -0
  211. package/.merlin-core/local-config.yaml.template +31 -0
  212. package/.merlin-core/mcp-servers/lsp-bridge/index.js +397 -0
  213. package/.merlin-core/modules/scraping/module.json +23 -0
  214. package/.merlin-core/project-config.yaml +89 -0
  215. package/.merlin-core/schemas/README.md +18 -0
  216. package/.merlin-core/schemas/agent-hook-schema.json +152 -0
  217. package/.merlin-core/schemas/agent-schema.json +31 -0
  218. package/.merlin-core/schemas/command-schema.json +18 -0
  219. package/.merlin-core/schemas/feedback-schema.json +36 -0
  220. package/.merlin-core/schemas/handoff-schema.json +19 -0
  221. package/.merlin-core/schemas/learning-schema.json +51 -0
  222. package/.merlin-core/schemas/module.schema.json +124 -0
  223. package/.merlin-core/schemas/must-haves-schema.json +95 -0
  224. package/.merlin-core/schemas/objective-schema.json +23 -0
  225. package/.merlin-core/schemas/plan-schema.json +20 -0
  226. package/.merlin-core/schemas/process-schema.json +82 -0
  227. package/.merlin-core/schemas/reminder-schema.json +20 -0
  228. package/.merlin-core/schemas/skill-eval-schema.json +92 -0
  229. package/.merlin-core/schemas/skill-schema.json +77 -0
  230. package/.merlin-core/schemas/workflow-schema.json +38 -0
  231. package/.merlin-core/skills/README.md +16 -0
  232. package/.merlin-core/skills/domain/azure-cloud/SKILL.md +211 -0
  233. package/.merlin-core/skills/domain/azure-cloud/references/appinsights-instrumentation.md +63 -0
  234. package/.merlin-core/skills/domain/azure-cloud/references/azure-compliance.md +99 -0
  235. package/.merlin-core/skills/domain/azure-cloud/references/azure-cost-optimization.md +419 -0
  236. package/.merlin-core/skills/domain/azure-cloud/references/azure-deploy.md +82 -0
  237. package/.merlin-core/skills/domain/azure-cloud/references/azure-diagnostics.md +130 -0
  238. package/.merlin-core/skills/domain/azure-cloud/references/azure-prepare.md +134 -0
  239. package/.merlin-core/skills/domain/azure-cloud/references/azure-quotas.md +290 -0
  240. package/.merlin-core/skills/domain/azure-cloud/references/azure-rbac.md +11 -0
  241. package/.merlin-core/skills/domain/azure-cloud/references/azure-resource-lookup.md +97 -0
  242. package/.merlin-core/skills/domain/azure-cloud/references/azure-resource-visualizer.md +178 -0
  243. package/.merlin-core/skills/domain/azure-cloud/references/azure-storage.md +91 -0
  244. package/.merlin-core/skills/domain/azure-cloud/references/azure-validate.md +58 -0
  245. package/.merlin-core/skills/domain/azure-cloud/references/entra-app-registration.md +192 -0
  246. package/.merlin-core/skills/domain/browser-automation/SKILL.md +311 -0
  247. package/.merlin-core/skills/domain/browser-automation/references/agent-browser-skill.md +632 -0
  248. package/.merlin-core/skills/domain/browser-automation/references/authentication.md +308 -0
  249. package/.merlin-core/skills/domain/browser-automation/references/commands.md +266 -0
  250. package/.merlin-core/skills/domain/browser-automation/references/profiling.md +120 -0
  251. package/.merlin-core/skills/domain/browser-automation/references/proxy-support.md +194 -0
  252. package/.merlin-core/skills/domain/browser-automation/references/session-management.md +194 -0
  253. package/.merlin-core/skills/domain/browser-automation/references/snapshot-refs.md +196 -0
  254. package/.merlin-core/skills/domain/browser-automation/references/video-recording.md +173 -0
  255. package/.merlin-core/skills/domain/browser-automation/templates/authenticated-session.sh +105 -0
  256. package/.merlin-core/skills/domain/browser-automation/templates/capture-workflow.sh +69 -0
  257. package/.merlin-core/skills/domain/browser-automation/templates/form-automation.sh +62 -0
  258. package/.merlin-core/skills/domain/digital-marketing/SKILL.md +292 -0
  259. package/.merlin-core/skills/domain/digital-marketing/references/content-strategy.md +320 -0
  260. package/.merlin-core/skills/domain/digital-marketing/references/copy-formats.md +298 -0
  261. package/.merlin-core/skills/domain/digital-marketing/references/copy-methodology.md +180 -0
  262. package/.merlin-core/skills/domain/digital-marketing/references/email-sequences.md +135 -0
  263. package/.merlin-core/skills/domain/digital-marketing/references/launch-strategy.md +213 -0
  264. package/.merlin-core/skills/domain/digital-marketing/references/pricing-strategy.md +160 -0
  265. package/.merlin-core/skills/domain/digital-marketing/references/programmatic-seo.md +237 -0
  266. package/.merlin-core/skills/domain/digital-marketing/references/revops-lifecycle.md +170 -0
  267. package/.merlin-core/skills/domain/digital-marketing/references/revops-operations.md +167 -0
  268. package/.merlin-core/skills/domain/digital-marketing/references/schema-markup.md +190 -0
  269. package/.merlin-core/skills/domain/digital-marketing/references/strategy-frameworks.md +324 -0
  270. package/.merlin-core/skills/domain/digital-marketing/references/traffic-management.md +350 -0
  271. package/.merlin-core/skills/domain/expo-native-ui/SKILL.md +348 -0
  272. package/.merlin-core/skills/domain/expo-native-ui/references/animations.md +220 -0
  273. package/.merlin-core/skills/domain/expo-native-ui/references/api-routes.md +361 -0
  274. package/.merlin-core/skills/domain/expo-native-ui/references/cicd-workflows.md +84 -0
  275. package/.merlin-core/skills/domain/expo-native-ui/references/controls.md +266 -0
  276. package/.merlin-core/skills/domain/expo-native-ui/references/data-fetching.md +553 -0
  277. package/.merlin-core/skills/domain/expo-native-ui/references/deployment-stores.md +1353 -0
  278. package/.merlin-core/skills/domain/expo-native-ui/references/deployment.md +183 -0
  279. package/.merlin-core/skills/domain/expo-native-ui/references/dev-client.md +166 -0
  280. package/.merlin-core/skills/domain/expo-native-ui/references/dom-components.md +410 -0
  281. package/.merlin-core/skills/domain/expo-native-ui/references/form-sheet.md +253 -0
  282. package/.merlin-core/skills/domain/expo-native-ui/references/gradients.md +117 -0
  283. package/.merlin-core/skills/domain/expo-native-ui/references/icons.md +218 -0
  284. package/.merlin-core/skills/domain/expo-native-ui/references/media.md +245 -0
  285. package/.merlin-core/skills/domain/expo-native-ui/references/platform-native.md +75 -0
  286. package/.merlin-core/skills/domain/expo-native-ui/references/route-structure.md +229 -0
  287. package/.merlin-core/skills/domain/expo-native-ui/references/search.md +249 -0
  288. package/.merlin-core/skills/domain/expo-native-ui/references/storage.md +121 -0
  289. package/.merlin-core/skills/domain/expo-native-ui/references/tabs.md +433 -0
  290. package/.merlin-core/skills/domain/expo-native-ui/references/tailwind-native.md +473 -0
  291. package/.merlin-core/skills/domain/expo-native-ui/references/toolbar-and-headers.md +284 -0
  292. package/.merlin-core/skills/domain/expo-native-ui/references/upgrading-guides.md +674 -0
  293. package/.merlin-core/skills/domain/expo-native-ui/references/upgrading.md +127 -0
  294. package/.merlin-core/skills/domain/expo-native-ui/references/visual-effects.md +199 -0
  295. package/.merlin-core/skills/domain/expo-native-ui/references/webgpu-three.md +605 -0
  296. package/.merlin-core/skills/domain/expo-native-ui/references/zoom-transitions.md +161 -0
  297. package/.merlin-core/skills/domain/marketing-ops/SKILL.md +117 -0
  298. package/.merlin-core/skills/domain/marketing-ops/references/_index.md +78 -0
  299. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ad-creative/references/generative-tools.md +19 -0
  300. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ad-creative/references/platform-specs.md +19 -0
  301. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ad-creative.md +251 -0
  302. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ads/references/ad-copy-templates.md +19 -0
  303. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ads/references/audience-targeting.md +19 -0
  304. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ads/references/conversion-tracking.md +19 -0
  305. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ads/references/platform-setup-checklists.md +19 -0
  306. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ads.md +322 -0
  307. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ai-seo/references/content-patterns.md +19 -0
  308. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ai-seo/references/content-types.md +19 -0
  309. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ai-seo/references/platform-ranking-factors.md +19 -0
  310. package/.merlin-core/skills/domain/marketing-ops/references/acquire/ai-seo.md +388 -0
  311. package/.merlin-core/skills/domain/marketing-ops/references/acquire/aso/references/apple-specs.md +19 -0
  312. package/.merlin-core/skills/domain/marketing-ops/references/acquire/aso/references/benchmarks.md +19 -0
  313. package/.merlin-core/skills/domain/marketing-ops/references/acquire/aso/references/google-play-specs.md +19 -0
  314. package/.merlin-core/skills/domain/marketing-ops/references/acquire/aso/references/report-template.md +19 -0
  315. package/.merlin-core/skills/domain/marketing-ops/references/acquire/aso/references/scoring-criteria.md +19 -0
  316. package/.merlin-core/skills/domain/marketing-ops/references/acquire/aso.md +316 -0
  317. package/.merlin-core/skills/domain/marketing-ops/references/acquire/co-marketing.md +305 -0
  318. package/.merlin-core/skills/domain/marketing-ops/references/acquire/community-marketing.md +169 -0
  319. package/.merlin-core/skills/domain/marketing-ops/references/acquire/competitor-profiling/references/templates.md +19 -0
  320. package/.merlin-core/skills/domain/marketing-ops/references/acquire/competitor-profiling/references/tool-reference.md +19 -0
  321. package/.merlin-core/skills/domain/marketing-ops/references/acquire/competitor-profiling.md +442 -0
  322. package/.merlin-core/skills/domain/marketing-ops/references/acquire/competitors/references/content-architecture.md +19 -0
  323. package/.merlin-core/skills/domain/marketing-ops/references/acquire/competitors/references/templates.md +19 -0
  324. package/.merlin-core/skills/domain/marketing-ops/references/acquire/competitors.md +281 -0
  325. package/.merlin-core/skills/domain/marketing-ops/references/acquire/content-strategy.md +16 -0
  326. package/.merlin-core/skills/domain/marketing-ops/references/acquire/directory-submissions/references/directory-list.md +19 -0
  327. package/.merlin-core/skills/domain/marketing-ops/references/acquire/directory-submissions/references/positioning-variations.md +19 -0
  328. package/.merlin-core/skills/domain/marketing-ops/references/acquire/directory-submissions/references/submission-tracker-template.md +19 -0
  329. package/.merlin-core/skills/domain/marketing-ops/references/acquire/directory-submissions.md +396 -0
  330. package/.merlin-core/skills/domain/marketing-ops/references/acquire/free-tools/references/tool-types.md +19 -0
  331. package/.merlin-core/skills/domain/marketing-ops/references/acquire/free-tools.md +196 -0
  332. package/.merlin-core/skills/domain/marketing-ops/references/acquire/image/references/ai-image-prompting.md +19 -0
  333. package/.merlin-core/skills/domain/marketing-ops/references/acquire/image.md +352 -0
  334. package/.merlin-core/skills/domain/marketing-ops/references/acquire/launch.md +18 -0
  335. package/.merlin-core/skills/domain/marketing-ops/references/acquire/lead-magnets/references/benchmarks.md +19 -0
  336. package/.merlin-core/skills/domain/marketing-ops/references/acquire/lead-magnets/references/format-guide.md +19 -0
  337. package/.merlin-core/skills/domain/marketing-ops/references/acquire/lead-magnets.md +333 -0
  338. package/.merlin-core/skills/domain/marketing-ops/references/acquire/programmatic-seo.md +16 -0
  339. package/.merlin-core/skills/domain/marketing-ops/references/acquire/schema.md +16 -0
  340. package/.merlin-core/skills/domain/marketing-ops/references/acquire/seo-audit/references/ai-writing-detection.md +19 -0
  341. package/.merlin-core/skills/domain/marketing-ops/references/acquire/seo-audit/references/international-seo.md +19 -0
  342. package/.merlin-core/skills/domain/marketing-ops/references/acquire/seo-audit.md +546 -0
  343. package/.merlin-core/skills/domain/marketing-ops/references/acquire/site-architecture/references/mermaid-templates.md +19 -0
  344. package/.merlin-core/skills/domain/marketing-ops/references/acquire/site-architecture/references/navigation-patterns.md +19 -0
  345. package/.merlin-core/skills/domain/marketing-ops/references/acquire/site-architecture/references/site-type-templates.md +19 -0
  346. package/.merlin-core/skills/domain/marketing-ops/references/acquire/site-architecture.md +371 -0
  347. package/.merlin-core/skills/domain/marketing-ops/references/acquire/social/references/platform-limits.md +19 -0
  348. package/.merlin-core/skills/domain/marketing-ops/references/acquire/social/references/platforms.md +19 -0
  349. package/.merlin-core/skills/domain/marketing-ops/references/acquire/social/references/post-templates.md +19 -0
  350. package/.merlin-core/skills/domain/marketing-ops/references/acquire/social/references/reverse-engineering.md +19 -0
  351. package/.merlin-core/skills/domain/marketing-ops/references/acquire/social/references/short-form-video.md +19 -0
  352. package/.merlin-core/skills/domain/marketing-ops/references/acquire/social.md +431 -0
  353. package/.merlin-core/skills/domain/marketing-ops/references/acquire/video/references/ai-video-prompting.md +19 -0
  354. package/.merlin-core/skills/domain/marketing-ops/references/acquire/video.md +353 -0
  355. package/.merlin-core/skills/domain/marketing-ops/references/activate/ab-testing/references/sample-size-guide.md +19 -0
  356. package/.merlin-core/skills/domain/marketing-ops/references/activate/ab-testing/references/test-templates.md +19 -0
  357. package/.merlin-core/skills/domain/marketing-ops/references/activate/ab-testing.md +379 -0
  358. package/.merlin-core/skills/domain/marketing-ops/references/activate/analytics/references/event-library.md +19 -0
  359. package/.merlin-core/skills/domain/marketing-ops/references/activate/analytics/references/ga4-implementation.md +19 -0
  360. package/.merlin-core/skills/domain/marketing-ops/references/activate/analytics/references/gtm-implementation.md +19 -0
  361. package/.merlin-core/skills/domain/marketing-ops/references/activate/analytics.md +323 -0
  362. package/.merlin-core/skills/domain/marketing-ops/references/activate/copy-editing.md +18 -0
  363. package/.merlin-core/skills/domain/marketing-ops/references/activate/copywriting.md +18 -0
  364. package/.merlin-core/skills/domain/marketing-ops/references/activate/cro/references/experiments.md +19 -0
  365. package/.merlin-core/skills/domain/marketing-ops/references/activate/cro/references/form.md +19 -0
  366. package/.merlin-core/skills/domain/marketing-ops/references/activate/cro.md +211 -0
  367. package/.merlin-core/skills/domain/marketing-ops/references/activate/emails.md +18 -0
  368. package/.merlin-core/skills/domain/marketing-ops/references/activate/paywalls/references/experiments.md +19 -0
  369. package/.merlin-core/skills/domain/marketing-ops/references/activate/paywalls.md +255 -0
  370. package/.merlin-core/skills/domain/marketing-ops/references/activate/popups.md +518 -0
  371. package/.merlin-core/skills/domain/marketing-ops/references/activate/pricing.md +18 -0
  372. package/.merlin-core/skills/domain/marketing-ops/references/activate/sales-enablement/references/deck-frameworks.md +19 -0
  373. package/.merlin-core/skills/domain/marketing-ops/references/activate/sales-enablement/references/demo-scripts.md +19 -0
  374. package/.merlin-core/skills/domain/marketing-ops/references/activate/sales-enablement/references/objection-library.md +19 -0
  375. package/.merlin-core/skills/domain/marketing-ops/references/activate/sales-enablement/references/one-pager-templates.md +19 -0
  376. package/.merlin-core/skills/domain/marketing-ops/references/activate/sales-enablement.md +371 -0
  377. package/.merlin-core/skills/domain/marketing-ops/references/activate/signup.md +406 -0
  378. package/.merlin-core/skills/domain/marketing-ops/references/expand/co-marketing.md +18 -0
  379. package/.merlin-core/skills/domain/marketing-ops/references/expand/community-marketing.md +18 -0
  380. package/.merlin-core/skills/domain/marketing-ops/references/expand/referrals/references/affiliate-programs.md +19 -0
  381. package/.merlin-core/skills/domain/marketing-ops/references/expand/referrals/references/program-examples.md +19 -0
  382. package/.merlin-core/skills/domain/marketing-ops/references/expand/referrals.md +278 -0
  383. package/.merlin-core/skills/domain/marketing-ops/references/foundation/customer-research/references/source-guides.md +425 -0
  384. package/.merlin-core/skills/domain/marketing-ops/references/foundation/customer-research.md +284 -0
  385. package/.merlin-core/skills/domain/marketing-ops/references/foundation/marketing-ideas/references/ideas-by-category.md +216 -0
  386. package/.merlin-core/skills/domain/marketing-ops/references/foundation/marketing-ideas.md +188 -0
  387. package/.merlin-core/skills/domain/marketing-ops/references/foundation/marketing-psychology.md +532 -0
  388. package/.merlin-core/skills/domain/marketing-ops/references/foundation/product-marketing.md +276 -0
  389. package/.merlin-core/skills/domain/marketing-ops/references/retain/churn-prevention/references/cancel-flow-patterns.md +19 -0
  390. package/.merlin-core/skills/domain/marketing-ops/references/retain/churn-prevention/references/dunning-playbook.md +19 -0
  391. package/.merlin-core/skills/domain/marketing-ops/references/retain/churn-prevention.md +442 -0
  392. package/.merlin-core/skills/domain/marketing-ops/references/retain/onboarding/references/experiments.md +19 -0
  393. package/.merlin-core/skills/domain/marketing-ops/references/retain/onboarding.md +243 -0
  394. package/.merlin-core/skills/domain/marketing-ops/references/retain/revops-lifecycle.md +18 -0
  395. package/.merlin-core/skills/domain/marketing-ops/references/retain/revops-operations.md +18 -0
  396. package/.merlin-core/skills/domain/n8n-automation/SKILL.md +149 -0
  397. package/.merlin-core/skills/domain/n8n-automation/references/code-javascript.md +3744 -0
  398. package/.merlin-core/skills/domain/n8n-automation/references/code-python.md +3293 -0
  399. package/.merlin-core/skills/domain/n8n-automation/references/expression-syntax.md +1662 -0
  400. package/.merlin-core/skills/domain/n8n-automation/references/mcp-tools-expert.md +2111 -0
  401. package/.merlin-core/skills/domain/n8n-automation/references/node-configuration.md +2523 -0
  402. package/.merlin-core/skills/domain/n8n-automation/references/validation-expert.md +2491 -0
  403. package/.merlin-core/skills/domain/n8n-automation/references/workflow-patterns.md +4624 -0
  404. package/.merlin-core/skills/domain/ops-manual/SKILL.md +225 -0
  405. package/.merlin-core/skills/domain/ops-manual/references/elicitation-questions.md +141 -0
  406. package/.merlin-core/skills/domain/ops-manual/references/external-skills-registry.md +63 -0
  407. package/.merlin-core/skills/domain/ops-manual/references/operations-template.yaml +132 -0
  408. package/.merlin-core/skills/domain/remotion-best-practices/SKILL.md +99 -0
  409. package/.merlin-core/skills/domain/remotion-best-practices/rules/3d.md +86 -0
  410. package/.merlin-core/skills/domain/remotion-best-practices/rules/animations.md +27 -0
  411. package/.merlin-core/skills/domain/remotion-best-practices/rules/assets/charts-bar-chart.tsx +173 -0
  412. package/.merlin-core/skills/domain/remotion-best-practices/rules/assets/text-animations-typewriter.tsx +100 -0
  413. package/.merlin-core/skills/domain/remotion-best-practices/rules/assets/text-animations-word-highlight.tsx +108 -0
  414. package/.merlin-core/skills/domain/remotion-best-practices/rules/assets.md +78 -0
  415. package/.merlin-core/skills/domain/remotion-best-practices/rules/audio.md +172 -0
  416. package/.merlin-core/skills/domain/remotion-best-practices/rules/calculate-metadata.md +131 -0
  417. package/.merlin-core/skills/domain/remotion-best-practices/rules/can-decode.md +75 -0
  418. package/.merlin-core/skills/domain/remotion-best-practices/rules/charts.md +68 -0
  419. package/.merlin-core/skills/domain/remotion-best-practices/rules/compositions.md +154 -0
  420. package/.merlin-core/skills/domain/remotion-best-practices/rules/display-captions.md +126 -0
  421. package/.merlin-core/skills/domain/remotion-best-practices/rules/extract-frames.md +229 -0
  422. package/.merlin-core/skills/domain/remotion-best-practices/rules/fonts.md +152 -0
  423. package/.merlin-core/skills/domain/remotion-best-practices/rules/get-audio-duration.md +58 -0
  424. package/.merlin-core/skills/domain/remotion-best-practices/rules/get-video-dimensions.md +68 -0
  425. package/.merlin-core/skills/domain/remotion-best-practices/rules/get-video-duration.md +58 -0
  426. package/.merlin-core/skills/domain/remotion-best-practices/rules/gifs.md +144 -0
  427. package/.merlin-core/skills/domain/remotion-best-practices/rules/images.md +134 -0
  428. package/.merlin-core/skills/domain/remotion-best-practices/rules/import-srt-captions.md +67 -0
  429. package/.merlin-core/skills/domain/remotion-best-practices/rules/lottie.md +70 -0
  430. package/.merlin-core/skills/domain/remotion-best-practices/rules/maps.md +414 -0
  431. package/.merlin-core/skills/domain/remotion-best-practices/rules/measuring-dom-nodes.md +34 -0
  432. package/.merlin-core/skills/domain/remotion-best-practices/rules/measuring-text.md +143 -0
  433. package/.merlin-core/skills/domain/remotion-best-practices/rules/parameters.md +109 -0
  434. package/.merlin-core/skills/domain/remotion-best-practices/rules/sequencing.md +118 -0
  435. package/.merlin-core/skills/domain/remotion-best-practices/rules/tailwind.md +11 -0
  436. package/.merlin-core/skills/domain/remotion-best-practices/rules/text-animations.md +20 -0
  437. package/.merlin-core/skills/domain/remotion-best-practices/rules/timing.md +179 -0
  438. package/.merlin-core/skills/domain/remotion-best-practices/rules/transcribe-captions.md +19 -0
  439. package/.merlin-core/skills/domain/remotion-best-practices/rules/transitions.md +137 -0
  440. package/.merlin-core/skills/domain/remotion-best-practices/rules/transparent-videos.md +106 -0
  441. package/.merlin-core/skills/domain/remotion-best-practices/rules/trimming.md +51 -0
  442. package/.merlin-core/skills/domain/remotion-best-practices/rules/videos.md +171 -0
  443. package/.merlin-core/skills/domain/resend-email/SKILL.md +377 -0
  444. package/.merlin-core/skills/general/adversarial-review/SKILL.md +144 -0
  445. package/.merlin-core/skills/general/api-design/SKILL.md +513 -0
  446. package/.merlin-core/skills/general/apify-scrape/SKILL.md +137 -0
  447. package/.merlin-core/skills/general/apify-scrape/scripts/apify-scrape.sh +68 -0
  448. package/.merlin-core/skills/general/backup/SKILL.md +87 -0
  449. package/.merlin-core/skills/general/blkskrn/SKILL.md +392 -0
  450. package/.merlin-core/skills/general/blkskrn/references/animation-patterns.md +521 -0
  451. package/.merlin-core/skills/general/blkskrn/references/design-system.md +637 -0
  452. package/.merlin-core/skills/general/blkskrn/references/html-templates.md +440 -0
  453. package/.merlin-core/skills/general/blkskrn/references/presenter-template.md +45 -0
  454. package/.merlin-core/skills/general/blkskrn/references/slide-types.md +424 -0
  455. package/.merlin-core/skills/general/blkskrn/scripts/canvas-manager.js +502 -0
  456. package/.merlin-core/skills/general/blkskrn/scripts/presenter.js +90 -0
  457. package/.merlin-core/skills/general/blkskrn/templates/presenter.html +273 -0
  458. package/.merlin-core/skills/general/blkskrn/templates/slide-base.html +277 -0
  459. package/.merlin-core/skills/general/blkskrn/templates/viewer.html +165 -0
  460. package/.merlin-core/skills/general/browser-takeover/SKILL.md +53 -0
  461. package/.merlin-core/skills/general/claude-api/SKILL.md +90 -0
  462. package/.merlin-core/skills/general/code-javascript/SKILL.md +268 -0
  463. package/.merlin-core/skills/general/code-python/SKILL.md +424 -0
  464. package/.merlin-core/skills/general/code-style/SKILL.md +97 -0
  465. package/.merlin-core/skills/general/code-typescript/SKILL.md +361 -0
  466. package/.merlin-core/skills/general/cold-email/SKILL.md +164 -0
  467. package/.merlin-core/skills/general/cold-email/references/benchmarks.md +18 -0
  468. package/.merlin-core/skills/general/cold-email/references/follow-up-sequences.md +18 -0
  469. package/.merlin-core/skills/general/cold-email/references/frameworks.md +18 -0
  470. package/.merlin-core/skills/general/cold-email/references/personalization.md +18 -0
  471. package/.merlin-core/skills/general/cold-email/references/subject-lines.md +18 -0
  472. package/.merlin-core/skills/general/container-security/SKILL.md +462 -0
  473. package/.merlin-core/skills/general/context-management/SKILL.md +79 -0
  474. package/.merlin-core/skills/general/copy-editing/SKILL.md +501 -0
  475. package/.merlin-core/skills/general/copy-editing/references/checklist.md +18 -0
  476. package/.merlin-core/skills/general/copy-editing/references/content-refresh.md +18 -0
  477. package/.merlin-core/skills/general/copy-editing/references/plain-english-alternatives.md +18 -0
  478. package/.merlin-core/skills/general/copywriting/SKILL.md +294 -0
  479. package/.merlin-core/skills/general/copywriting/references/copy-frameworks.md +392 -0
  480. package/.merlin-core/skills/general/copywriting/references/natural-transitions.md +276 -0
  481. package/.merlin-core/skills/general/database/SKILL.md +561 -0
  482. package/.merlin-core/skills/general/database/references/postgres-concurrency.md +182 -0
  483. package/.merlin-core/skills/general/database/references/postgres-connections.md +97 -0
  484. package/.merlin-core/skills/general/database/references/postgres-data-patterns.md +159 -0
  485. package/.merlin-core/skills/general/database/references/postgres-monitoring.md +136 -0
  486. package/.merlin-core/skills/general/database/references/postgres-rls.md +140 -0
  487. package/.merlin-core/skills/general/database-provision/SKILL.md +56 -0
  488. package/.merlin-core/skills/general/deploy/SKILL.md +65 -0
  489. package/.merlin-core/skills/general/design-inspiration/SKILL.md +146 -0
  490. package/.merlin-core/skills/general/design-palette/SKILL.md +99 -0
  491. package/.merlin-core/skills/general/design-palette/references/full-palettes.md +144 -0
  492. package/.merlin-core/skills/general/design-system/SKILL.md +94 -0
  493. package/.merlin-core/skills/general/design-typography/SKILL.md +115 -0
  494. package/.merlin-core/skills/general/design-typography/references/full-pairings.md +144 -0
  495. package/.merlin-core/skills/general/design-ux-patterns/SKILL.md +155 -0
  496. package/.merlin-core/skills/general/design-ux-patterns/references/charts-data-guidelines.md +197 -0
  497. package/.merlin-core/skills/general/design-ux-patterns/references/landing-patterns.md +199 -0
  498. package/.merlin-core/skills/general/design-ux-patterns/references/professional-ui-checklist.md +56 -0
  499. package/.merlin-core/skills/general/design-ux-patterns/references/style-catalog.md +89 -0
  500. package/.merlin-core/skills/general/design-ux-patterns/references/ux-guidelines.md +837 -0
  501. package/.merlin-core/skills/general/discover-cloud/SKILL.md +108 -0
  502. package/.merlin-core/skills/general/doc-sync/SKILL.md +52 -0
  503. package/.merlin-core/skills/general/document-sharding/SKILL.md +53 -0
  504. package/.merlin-core/skills/general/docx/SKILL.md +418 -0
  505. package/.merlin-core/skills/general/docx/references/windows-setup.md +27 -0
  506. package/.merlin-core/skills/general/docx/scripts/__init__.py +1 -0
  507. package/.merlin-core/skills/general/docx/scripts/accept_changes.py +135 -0
  508. package/.merlin-core/skills/general/docx/scripts/comment.py +318 -0
  509. package/.merlin-core/skills/general/docx/scripts/office/__init__.py +0 -0
  510. package/.merlin-core/skills/general/docx/scripts/office/helpers/__init__.py +0 -0
  511. package/.merlin-core/skills/general/docx/scripts/office/helpers/merge_runs.py +199 -0
  512. package/.merlin-core/skills/general/docx/scripts/office/helpers/simplify_redlines.py +197 -0
  513. package/.merlin-core/skills/general/docx/scripts/office/pack.py +159 -0
  514. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
  515. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
  516. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
  517. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
  518. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
  519. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
  520. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
  521. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
  522. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
  523. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
  524. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
  525. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
  526. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
  527. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
  528. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
  529. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
  530. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
  531. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
  532. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
  533. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
  534. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
  535. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
  536. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
  537. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
  538. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
  539. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
  540. package/.merlin-core/skills/general/docx/scripts/office/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
  541. package/.merlin-core/skills/general/docx/scripts/office/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
  542. package/.merlin-core/skills/general/docx/scripts/office/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
  543. package/.merlin-core/skills/general/docx/scripts/office/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
  544. package/.merlin-core/skills/general/docx/scripts/office/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
  545. package/.merlin-core/skills/general/docx/scripts/office/schemas/mce/mc.xsd +75 -0
  546. package/.merlin-core/skills/general/docx/scripts/office/schemas/microsoft/wml-2010.xsd +560 -0
  547. package/.merlin-core/skills/general/docx/scripts/office/schemas/microsoft/wml-2012.xsd +67 -0
  548. package/.merlin-core/skills/general/docx/scripts/office/schemas/microsoft/wml-2018.xsd +14 -0
  549. package/.merlin-core/skills/general/docx/scripts/office/schemas/microsoft/wml-cex-2018.xsd +20 -0
  550. package/.merlin-core/skills/general/docx/scripts/office/schemas/microsoft/wml-cid-2016.xsd +13 -0
  551. package/.merlin-core/skills/general/docx/scripts/office/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
  552. package/.merlin-core/skills/general/docx/scripts/office/schemas/microsoft/wml-symex-2015.xsd +8 -0
  553. package/.merlin-core/skills/general/docx/scripts/office/soffice.py +183 -0
  554. package/.merlin-core/skills/general/docx/scripts/office/unpack.py +132 -0
  555. package/.merlin-core/skills/general/docx/scripts/office/validate.py +111 -0
  556. package/.merlin-core/skills/general/docx/scripts/office/validators/__init__.py +15 -0
  557. package/.merlin-core/skills/general/docx/scripts/office/validators/base.py +847 -0
  558. package/.merlin-core/skills/general/docx/scripts/office/validators/docx.py +446 -0
  559. package/.merlin-core/skills/general/docx/scripts/office/validators/pptx.py +275 -0
  560. package/.merlin-core/skills/general/docx/scripts/office/validators/redlining.py +247 -0
  561. package/.merlin-core/skills/general/docx/scripts/templates/comments.xml +3 -0
  562. package/.merlin-core/skills/general/docx/scripts/templates/commentsExtended.xml +3 -0
  563. package/.merlin-core/skills/general/docx/scripts/templates/commentsExtensible.xml +3 -0
  564. package/.merlin-core/skills/general/docx/scripts/templates/commentsIds.xml +3 -0
  565. package/.merlin-core/skills/general/docx/scripts/templates/people.xml +3 -0
  566. package/.merlin-core/skills/general/elicitation/SKILL.md +188 -0
  567. package/.merlin-core/skills/general/engineering-audit/SKILL.md +122 -0
  568. package/.merlin-core/skills/general/find-and-edit/SKILL.md +102 -0
  569. package/.merlin-core/skills/general/first-party-docs/SKILL.md +51 -0
  570. package/.merlin-core/skills/general/frontend-design/SKILL.md +204 -0
  571. package/.merlin-core/skills/general/guardrails/SKILL.md +144 -0
  572. package/.merlin-core/skills/general/image-gen/SKILL.md +49 -0
  573. package/.merlin-core/skills/general/learning-capture/SKILL.md +192 -0
  574. package/.merlin-core/skills/general/lgpd-compliance-audit/SKILL.md +448 -0
  575. package/.merlin-core/skills/general/load-testing/SKILL.md +114 -0
  576. package/.merlin-core/skills/general/load-testing/docker/Dockerfile.dashboard +21 -0
  577. package/.merlin-core/skills/general/load-testing/docker/docker-compose.locust.yml +39 -0
  578. package/.merlin-core/skills/general/load-testing/requirements.txt +1 -0
  579. package/.merlin-core/skills/general/load-testing/scripts/compare_baseline.py +172 -0
  580. package/.merlin-core/skills/general/load-testing/scripts/run_local.py +245 -0
  581. package/.merlin-core/skills/general/load-testing/templates/load_shape_stepped.py +35 -0
  582. package/.merlin-core/skills/general/load-testing/templates/locustfile_dashboard.py +47 -0
  583. package/.merlin-core/skills/general/load-testing/templates/threshold_hook.py +36 -0
  584. package/.merlin-core/skills/general/mage-beauty/SKILL.md +89 -0
  585. package/.merlin-core/skills/general/mage-beauty/references/anti-patterns.md +148 -0
  586. package/.merlin-core/skills/general/mage-beauty/references/color-and-contrast.md +87 -0
  587. package/.merlin-core/skills/general/mage-beauty/references/interaction-design.md +99 -0
  588. package/.merlin-core/skills/general/mage-beauty/references/motion-design.md +90 -0
  589. package/.merlin-core/skills/general/mage-beauty/references/remotion-bridge.md +187 -0
  590. package/.merlin-core/skills/general/mage-beauty/references/responsive-and-multi-format.md +98 -0
  591. package/.merlin-core/skills/general/mage-beauty/references/spatial-design.md +88 -0
  592. package/.merlin-core/skills/general/mage-beauty/references/typography.md +60 -0
  593. package/.merlin-core/skills/general/mage-beauty/references/verb-adapt.md +102 -0
  594. package/.merlin-core/skills/general/mage-beauty/references/verb-animate.md +97 -0
  595. package/.merlin-core/skills/general/mage-beauty/references/verb-audit.md +99 -0
  596. package/.merlin-core/skills/general/mage-beauty/references/verb-bolder.md +94 -0
  597. package/.merlin-core/skills/general/mage-beauty/references/verb-cinematic.md +128 -0
  598. package/.merlin-core/skills/general/mage-beauty/references/verb-clarify.md +107 -0
  599. package/.merlin-core/skills/general/mage-beauty/references/verb-colorize.md +106 -0
  600. package/.merlin-core/skills/general/mage-beauty/references/verb-critique.md +88 -0
  601. package/.merlin-core/skills/general/mage-beauty/references/verb-delight.md +98 -0
  602. package/.merlin-core/skills/general/mage-beauty/references/verb-distill.md +97 -0
  603. package/.merlin-core/skills/general/mage-beauty/references/verb-harden.md +79 -0
  604. package/.merlin-core/skills/general/mage-beauty/references/verb-layout.md +104 -0
  605. package/.merlin-core/skills/general/mage-beauty/references/verb-onboard.md +98 -0
  606. package/.merlin-core/skills/general/mage-beauty/references/verb-optimize.md +124 -0
  607. package/.merlin-core/skills/general/mage-beauty/references/verb-overdrive.md +105 -0
  608. package/.merlin-core/skills/general/mage-beauty/references/verb-polish.md +91 -0
  609. package/.merlin-core/skills/general/mage-beauty/references/verb-quieter.md +95 -0
  610. package/.merlin-core/skills/general/mage-beauty/references/verb-rebrand.md +127 -0
  611. package/.merlin-core/skills/general/mage-beauty/references/verb-shape.md +160 -0
  612. package/.merlin-core/skills/general/mage-beauty/references/verb-typeset.md +109 -0
  613. package/.merlin-core/skills/general/mage-beauty/references/voice-and-microcopy.md +137 -0
  614. package/.merlin-core/skills/general/mcp-builder/SKILL.md +92 -0
  615. package/.merlin-core/skills/general/network-debug/SKILL.md +51 -0
  616. package/.merlin-core/skills/general/next-best-practices/SKILL.md +177 -0
  617. package/.merlin-core/skills/general/next-best-practices/references/async-patterns.md +87 -0
  618. package/.merlin-core/skills/general/next-best-practices/references/bundling.md +182 -0
  619. package/.merlin-core/skills/general/next-best-practices/references/data-patterns.md +306 -0
  620. package/.merlin-core/skills/general/next-best-practices/references/debug-tricks.md +125 -0
  621. package/.merlin-core/skills/general/next-best-practices/references/directives.md +74 -0
  622. package/.merlin-core/skills/general/next-best-practices/references/error-handling.md +232 -0
  623. package/.merlin-core/skills/general/next-best-practices/references/file-conventions.md +141 -0
  624. package/.merlin-core/skills/general/next-best-practices/references/font.md +257 -0
  625. package/.merlin-core/skills/general/next-best-practices/references/functions.md +108 -0
  626. package/.merlin-core/skills/general/next-best-practices/references/hydration-error.md +88 -0
  627. package/.merlin-core/skills/general/next-best-practices/references/image.md +179 -0
  628. package/.merlin-core/skills/general/next-best-practices/references/metadata.md +296 -0
  629. package/.merlin-core/skills/general/next-best-practices/references/parallel-routes.md +298 -0
  630. package/.merlin-core/skills/general/next-best-practices/references/route-handlers.md +146 -0
  631. package/.merlin-core/skills/general/next-best-practices/references/rsc-boundaries.md +164 -0
  632. package/.merlin-core/skills/general/next-best-practices/references/runtime-selection.md +40 -0
  633. package/.merlin-core/skills/general/next-best-practices/references/scripts.md +141 -0
  634. package/.merlin-core/skills/general/next-best-practices/references/self-hosting.md +384 -0
  635. package/.merlin-core/skills/general/next-best-practices/references/suspense-boundaries.md +67 -0
  636. package/.merlin-core/skills/general/next-steps/SKILL.md +43 -0
  637. package/.merlin-core/skills/general/party-mode/SKILL.md +57 -0
  638. package/.merlin-core/skills/general/pdf/SKILL.md +298 -0
  639. package/.merlin-core/skills/general/pdf/references/forms.md +312 -0
  640. package/.merlin-core/skills/general/pdf/references/reference.md +640 -0
  641. package/.merlin-core/skills/general/pdf/references/windows-setup.md +40 -0
  642. package/.merlin-core/skills/general/pdf/scripts/check_bounding_boxes.py +65 -0
  643. package/.merlin-core/skills/general/pdf/scripts/check_fillable_fields.py +11 -0
  644. package/.merlin-core/skills/general/pdf/scripts/convert_pdf_to_images.py +33 -0
  645. package/.merlin-core/skills/general/pdf/scripts/create_validation_image.py +37 -0
  646. package/.merlin-core/skills/general/pdf/scripts/extract_form_field_info.py +122 -0
  647. package/.merlin-core/skills/general/pdf/scripts/extract_form_structure.py +115 -0
  648. package/.merlin-core/skills/general/pdf/scripts/fill_fillable_fields.py +98 -0
  649. package/.merlin-core/skills/general/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
  650. package/.merlin-core/skills/general/pptx/SKILL.md +133 -0
  651. package/.merlin-core/skills/general/pptx/references/editing.md +213 -0
  652. package/.merlin-core/skills/general/pptx/references/pptxgenjs.md +581 -0
  653. package/.merlin-core/skills/general/pptx/references/windows-setup.md +27 -0
  654. package/.merlin-core/skills/general/pptx/scripts/__init__.py +0 -0
  655. package/.merlin-core/skills/general/pptx/scripts/add_slide.py +195 -0
  656. package/.merlin-core/skills/general/pptx/scripts/clean.py +286 -0
  657. package/.merlin-core/skills/general/pptx/scripts/thumbnail.py +289 -0
  658. package/.merlin-core/skills/general/property-testing/SKILL.md +214 -0
  659. package/.merlin-core/skills/general/purge-leaked-secret/SKILL.md +383 -0
  660. package/.merlin-core/skills/general/reflection/SKILL.md +100 -0
  661. package/.merlin-core/skills/general/secret-safe-commit/SKILL.md +246 -0
  662. package/.merlin-core/skills/general/secret-safe-commit/templates/.gitleaks.toml +91 -0
  663. package/.merlin-core/skills/general/secret-safe-commit/templates/.pre-commit-config.yaml +57 -0
  664. package/.merlin-core/skills/general/secret-safe-commit/templates/secret-scan.yml +48 -0
  665. package/.merlin-core/skills/general/semantic-search/SKILL.md +79 -0
  666. package/.merlin-core/skills/general/skill-creator/SKILL.md +342 -0
  667. package/.merlin-core/skills/general/skill-creator/agents/analyzer.md +283 -0
  668. package/.merlin-core/skills/general/skill-creator/agents/comparator.md +211 -0
  669. package/.merlin-core/skills/general/skill-creator/agents/grader.md +227 -0
  670. package/.merlin-core/skills/general/skill-creator/assets/eval_review.html +146 -0
  671. package/.merlin-core/skills/general/skill-creator/eval-viewer/generate_review.py +471 -0
  672. package/.merlin-core/skills/general/skill-creator/eval-viewer/viewer.html +1325 -0
  673. package/.merlin-core/skills/general/skill-creator/references/schemas.md +439 -0
  674. package/.merlin-core/skills/general/skill-creator/scripts/__init__.py +0 -0
  675. package/.merlin-core/skills/general/skill-creator/scripts/aggregate_benchmark.py +401 -0
  676. package/.merlin-core/skills/general/skill-creator/scripts/generate_report.py +326 -0
  677. package/.merlin-core/skills/general/skill-creator/scripts/improve_description.py +247 -0
  678. package/.merlin-core/skills/general/skill-creator/scripts/package_skill.py +136 -0
  679. package/.merlin-core/skills/general/skill-creator/scripts/quick_validate.py +103 -0
  680. package/.merlin-core/skills/general/skill-creator/scripts/run_eval.py +310 -0
  681. package/.merlin-core/skills/general/skill-creator/scripts/run_loop.py +328 -0
  682. package/.merlin-core/skills/general/skill-creator/scripts/utils.py +47 -0
  683. package/.merlin-core/skills/general/start-here/SKILL.md +63 -0
  684. package/.merlin-core/skills/general/start-here/recipes.json +758 -0
  685. package/.merlin-core/skills/general/start-here/recipes.schema.json +57 -0
  686. package/.merlin-core/skills/general/static-analysis/SKILL.md +151 -0
  687. package/.merlin-core/skills/general/tailwind-design-system/SKILL.md +201 -0
  688. package/.merlin-core/skills/general/tailwind-design-system/references/advanced-v4.md +152 -0
  689. package/.merlin-core/skills/general/tailwind-design-system/references/component-patterns.md +353 -0
  690. package/.merlin-core/skills/general/teach-method/SKILL.md +86 -0
  691. package/.merlin-core/skills/general/team-execution/SKILL.md +67 -0
  692. package/.merlin-core/skills/general/testing/SKILL.md +412 -0
  693. package/.merlin-core/skills/general/token-economy/SKILL.md +55 -0
  694. package/.merlin-core/skills/general/vps-security-hardening/SKILL.md +406 -0
  695. package/.merlin-core/skills/general/web-quality/SKILL.md +180 -0
  696. package/.merlin-core/skills/general/webapp-testing/SKILL.md +153 -0
  697. package/.merlin-core/skills/general/webapp-testing/scripts/screenshot_compare.py +72 -0
  698. package/.merlin-core/skills/general/webapp-testing/scripts/with_server.py +103 -0
  699. package/.merlin-core/skills/general/xlsx/SKILL.md +167 -0
  700. package/.merlin-core/skills/general/xlsx/references/nodejs-sheetjs-styled-reports.md +141 -0
  701. package/.merlin-core/skills/general/xlsx/references/windows-setup.md +17 -0
  702. package/.merlin-core/skills/general/xlsx/scripts/recalc.py +184 -0
  703. package/.merlin-core/skills/general/xlsx/scripts/styled-report.js +130 -0
  704. package/.merlin-core/skills/general/yolo-mode/SKILL.md +60 -0
  705. package/.merlin-core/skills/general/youtube-transcript/SKILL.md +177 -0
  706. package/.merlin-core/skills/general/youtube-transcript/scripts/fetch_transcript.py +188 -0
  707. package/.merlin-core/skills/general/youtube-transcript/scripts/gladia_transcribe.mjs +230 -0
  708. package/.merlin-core/tools/commands/activate.js +72 -0
  709. package/.merlin-core/tools/commands/archive-thoughts.js +181 -0
  710. package/.merlin-core/tools/commands/backup.js +156 -0
  711. package/.merlin-core/tools/commands/certify-process.js +196 -0
  712. package/.merlin-core/tools/commands/convert.js +87 -0
  713. package/.merlin-core/tools/commands/cron.js +147 -0
  714. package/.merlin-core/tools/commands/disable.js +73 -0
  715. package/.merlin-core/tools/commands/doc-sync.js +127 -0
  716. package/.merlin-core/tools/commands/eval-skill.js +193 -0
  717. package/.merlin-core/tools/commands/frontmatter.js +49 -0
  718. package/.merlin-core/tools/commands/heartbeat.js +43 -0
  719. package/.merlin-core/tools/commands/index-thoughts.js +35 -0
  720. package/.merlin-core/tools/commands/install-remote-approve.js +184 -0
  721. package/.merlin-core/tools/commands/install.js +81 -0
  722. package/.merlin-core/tools/commands/lib/__verify__/diff-reports.js +170 -0
  723. package/.merlin-core/tools/commands/lib/fs-safe.js +186 -0
  724. package/.merlin-core/tools/commands/lib/preflight.js +607 -0
  725. package/.merlin-core/tools/commands/lib/preserve.js +232 -0
  726. package/.merlin-core/tools/commands/lib/project-config.template.yaml +69 -0
  727. package/.merlin-core/tools/commands/lib/report.js +231 -0
  728. package/.merlin-core/tools/commands/lib/settings-merge.js +134 -0
  729. package/.merlin-core/tools/commands/license.js +52 -0
  730. package/.merlin-core/tools/commands/list.js +125 -0
  731. package/.merlin-core/tools/commands/migrate-alkimia.js +271 -0
  732. package/.merlin-core/tools/commands/modules.js +68 -0
  733. package/.merlin-core/tools/commands/provision.js +83 -0
  734. package/.merlin-core/tools/commands/prune-feedback.js +114 -0
  735. package/.merlin-core/tools/commands/run-process.js +28 -0
  736. package/.merlin-core/tools/commands/state.js +79 -0
  737. package/.merlin-core/tools/commands/sync-bridges.js +197 -0
  738. package/.merlin-core/tools/commands/upgrade.js +1135 -0
  739. package/.merlin-core/tools/commands/validate-recipes.js +218 -0
  740. package/.merlin-core/tools/commands/validate.js +159 -0
  741. package/.merlin-core/tools/commands/yolo.js +82 -0
  742. package/.merlin-core/tools/compose-rules.mjs +179 -0
  743. package/.merlin-core/tools/disable-module.mjs +150 -0
  744. package/.merlin-core/tools/lib/deployer.mjs +131 -0
  745. package/.merlin-core/tools/lib/modules-activation.mjs +225 -0
  746. package/.merlin-core/tools/merlin-tools.js +153 -0
  747. package/.merlin-core/tools/migrate-frontmatter-v3.js +192 -0
  748. package/.merlin-core/tools/modules-catalog.mjs +174 -0
  749. package/.merlin-core/tools/provision-module.mjs +191 -0
  750. package/.merlin-core/tools/verify-module.mjs +99 -0
  751. package/.merlin-core/tools/vps-security-audit.sh +234 -0
  752. package/INSTALL.md +312 -0
  753. package/LICENSE +118 -0
  754. package/PRIVACY-LICENSING.md +65 -0
  755. package/README.md +391 -0
  756. package/bin/README.md +15 -0
  757. package/bin/convert-to-merlin.sh +109 -0
  758. package/bin/fleet-patch-hooks.sh +144 -0
  759. package/bin/fleet-patch-v3-fixes.sh +127 -0
  760. package/bin/merlin-init.js +232 -0
  761. package/bin/merlin.js +321 -0
  762. package/package.json +127 -0
@@ -0,0 +1,1135 @@
1
+ /**
2
+ * Merlin-Tools: upgrade — Sync Merlin Core to a satellite project.
3
+ *
4
+ * Copies all framework files from the source of truth (this repo) to a target
5
+ * project, preserving project-specific data: thoughts, domain skills, and
6
+ * project-config.yaml.
7
+ *
8
+ * SAFETY: Uses copy-then-delete pattern (NEVER rename or delete-first).
9
+ * Temp backups are preserved on failure for manual recovery.
10
+ *
11
+ * Usage:
12
+ * node .merlin-core/tools/merlin-tools.js upgrade <target-path> [--dry-run]
13
+ *
14
+ * Examples:
15
+ * node .merlin-core/tools/merlin-tools.js upgrade "/path/to/project"
16
+ * node .merlin-core/tools/merlin-tools.js upgrade "/path/to/another-project" --dry-run
17
+ *
18
+ * @module tools/commands/upgrade
19
+ */
20
+
21
+ "use strict";
22
+
23
+ const fs = require("fs");
24
+ const path = require("path");
25
+ const {
26
+ copyDirSync,
27
+ rmDirSync,
28
+ countFiles,
29
+ listSubdirs,
30
+ countRealThoughts,
31
+ extractVersion,
32
+ extractFrameworkVersion,
33
+ extractProjectName,
34
+ bumpProjectConfigVersion,
35
+ } = require("./lib/fs-safe");
36
+ const { runPreflight } = require("./lib/preflight");
37
+ const {
38
+ writeUpgradeReport,
39
+ formatWhatChanged,
40
+ formatRecoveryInstructions,
41
+ } = require("./lib/report");
42
+ const {
43
+ preserveProjectData,
44
+ restoreDomainSkills,
45
+ restoreThoughts,
46
+ } = require("./lib/preserve");
47
+ const { mergeSettingsLocal } = require("./lib/settings-merge");
48
+ const syncBridges = require("./sync-bridges");
49
+
50
+ // Directories that are part of the framework (synced on upgrade).
51
+ // NOTE: "skills" and "thoughts" are handled separately — never list them here.
52
+ const FRAMEWORK_DIRS = [
53
+ "core",
54
+ "commands",
55
+ "development",
56
+ "tools",
57
+ "data",
58
+ "elicitation",
59
+ "infrastructure",
60
+ "manifests",
61
+ "mcp-servers",
62
+ "monitor",
63
+ "presets",
64
+ "product",
65
+ "quality",
66
+ "schemas",
67
+ "scripts",
68
+ "utils",
69
+ "workflow-intelligence",
70
+ "hooks",
71
+ ];
72
+
73
+ // Root-level framework files (synced on upgrade)
74
+ const FRAMEWORK_FILES = [
75
+ "constitution.md",
76
+ "core-config.yaml",
77
+ "framework-config.yaml",
78
+ "index.js",
79
+ "local-config.yaml.template",
80
+ ];
81
+
82
+ // Files in .claude/ to sync (overwrite from source)
83
+ const CLAUDE_FILES = ["CLAUDE.md", "settings.json"];
84
+
85
+ // Root-level project files to sync
86
+ const PROJECT_ROOT_FILES = [".mcp.json"];
87
+
88
+ async function run(command, args, projectRoot) {
89
+ // Flag parsing: filter out all known flags, leaving only positional targetPath.
90
+ // --yes is silently accepted (no-op in JS; needed for bash wrapper pass-through).
91
+ const dryRun = args.includes("--dry-run") || args.includes("-n");
92
+ const flattenNesting = args.includes("--flatten-nesting");
93
+ const knownFlags = new Set([
94
+ "--dry-run",
95
+ "-n",
96
+ "--yes",
97
+ "-y",
98
+ "--flatten-nesting",
99
+ ]);
100
+ const filteredArgs = args.filter((a) => !knownFlags.has(a));
101
+ const targetPath = filteredArgs[0];
102
+
103
+ if (!targetPath) {
104
+ throw new Error(
105
+ "Usage: upgrade <target-path> [--dry-run] [--yes] [--flatten-nesting]\n" +
106
+ 'Example: upgrade "/path/to/project" --dry-run',
107
+ );
108
+ }
109
+
110
+ const resolvedTarget = path.resolve(targetPath);
111
+ const srcMerlin = path.join(projectRoot, ".merlin-core");
112
+ const dstMerlin = path.join(resolvedTarget, ".merlin-core");
113
+ const srcClaude = path.join(projectRoot, ".claude");
114
+ const dstClaude = path.join(resolvedTarget, ".claude");
115
+
116
+ // Validate source
117
+ if (!fs.existsSync(srcMerlin)) {
118
+ throw new Error(`Source .merlin-core not found at: ${srcMerlin}`);
119
+ }
120
+
121
+ // Validate target dir exists (even for CONVERSION mode, the project dir must exist)
122
+ if (!fs.existsSync(resolvedTarget)) {
123
+ throw new Error(`Target directory not found at: ${resolvedTarget}`);
124
+ }
125
+
126
+ // MODE DETECTION (Phase 5): no .merlin-core/ in target → CONVERSION; else → UPGRADE
127
+ const hasExistingMerlin = fs.existsSync(dstMerlin);
128
+ const mode = hasExistingMerlin ? "upgrade" : "convert";
129
+
130
+ // Read versions
131
+ // SOURCE: framework BUILD version from framework-config.yaml.framework_version
132
+ // (NOT core-config.yaml.version — that's the schema version, doesn't bump
133
+ // on releases. Reading the wrong file caused the pre-Phase-0 fleet drift
134
+ // where the script thought everything was at 3.0.0 while source was 3.0.2.)
135
+ // TARGET: project's installed-framework version from project-config.yaml.version
136
+ // (what THIS project thinks it's running — sed-bumped after each upgrade)
137
+ // For CONVERSION mode: no project-config exists yet → "none"
138
+ const srcFrameworkConfig = path.join(srcMerlin, "framework-config.yaml");
139
+ const dstProjectConfigPath = path.join(dstMerlin, "project-config.yaml");
140
+ const srcVersion = extractFrameworkVersion(srcFrameworkConfig);
141
+ const dstVersion = hasExistingMerlin
142
+ ? extractVersion(dstProjectConfigPath)
143
+ : "none";
144
+
145
+ // Read project name: from existing config OR derive from dir name for CONVERSION
146
+ const dstProjectConfig = path.join(dstMerlin, "project-config.yaml");
147
+ const projectName = hasExistingMerlin
148
+ ? extractProjectName(dstProjectConfig)
149
+ : path.basename(resolvedTarget);
150
+
151
+ // Count project-owned data BEFORE upgrade (CONVERSION: zero of everything)
152
+ const dstThoughts = path.join(dstMerlin, "thoughts");
153
+ const dstDomain = path.join(dstMerlin, "skills", "domain");
154
+ const thoughtCount = hasExistingMerlin ? countRealThoughts(dstThoughts) : 0;
155
+ const domainSkills = hasExistingMerlin ? listSubdirs(dstDomain) : [];
156
+
157
+ const result = {
158
+ project: projectName,
159
+ target: resolvedTarget,
160
+ mode,
161
+ from: dstVersion,
162
+ to: srcVersion,
163
+ dryRun,
164
+ synced: { dirs: [], files: [], claude: [], rootFiles: [] },
165
+ preserved: {
166
+ projectConfig: hasExistingMerlin,
167
+ thoughts: thoughtCount,
168
+ domainSkills: domainSkills,
169
+ },
170
+ errors: [],
171
+ };
172
+
173
+ // ============================================================================
174
+ // PRE-FLIGHT — idempotency check, major-version warning, bug A + bug C scans
175
+ // ============================================================================
176
+ // Always runs FIRST. May short-circuit (idempotency) or print warnings.
177
+ // In dry-run mode, exits cleanly after the summary block.
178
+ const preflight = runPreflight({
179
+ projectDir: resolvedTarget,
180
+ projectName,
181
+ srcDir: projectRoot,
182
+ srcVersion,
183
+ currentVersion: dstVersion,
184
+ mode,
185
+ dryRun,
186
+ flattenNesting,
187
+ thoughtCount,
188
+ domainSkillCount: domainSkills.length,
189
+ });
190
+
191
+ // Capture preflight findings on result for downstream use + final report
192
+ result.preflight = {
193
+ brokenLinks: preflight.brokenLinks,
194
+ nestedSkills: preflight.nestedSkills,
195
+ willFlatten: preflight.willFlatten,
196
+ };
197
+
198
+ // Short-circuit: idempotency bail OR dry-run completion
199
+ if (preflight.shouldExit) {
200
+ result.shortCircuit = true;
201
+ result.shortCircuitReason =
202
+ dstVersion === srcVersion ? "idempotency" : "dry-run";
203
+ return result;
204
+ }
205
+
206
+ // ============================================================================
207
+ // CONVERSION BRANCH (Phase 5): target has no .merlin-core/ — fresh install
208
+ // ============================================================================
209
+ // CONVERSION skips preserve/restore (nothing to preserve) and does extra
210
+ // legacy cleanup: clears source's stale thoughts, migrates legacy thoughts/
211
+ // at project root, removes legacy .claude/agents and .claude/templates dirs,
212
+ // and generates a fresh project-config.yaml from the template.
213
+ if (mode === "convert") {
214
+ return runConversion({
215
+ resolvedTarget,
216
+ srcMerlin,
217
+ dstMerlin,
218
+ srcClaude,
219
+ dstClaude,
220
+ projectRoot,
221
+ projectName,
222
+ srcVersion,
223
+ result,
224
+ });
225
+ }
226
+
227
+ // === EXECUTE UPGRADE ===
228
+
229
+ // 1. Create pre-upgrade backup in .merlin-backups/latest/
230
+ const backupDir = path.join(resolvedTarget, ".merlin-backups", "latest");
231
+ try {
232
+ createPreUpgradeBackup(dstMerlin, dstClaude, backupDir, resolvedTarget);
233
+ result.backup = backupDir;
234
+ } catch (backupErr) {
235
+ result.errors.push(`Pre-upgrade backup warning: ${backupErr.message}`);
236
+ // Non-fatal: temp dir is the safety net
237
+ }
238
+
239
+ // 2. Backup project-config.yaml to memory
240
+ const projectConfigBackup = fs.readFileSync(dstProjectConfig, "utf8");
241
+
242
+ // 3. Preserve project-owned data: thoughts + domain skills
243
+ // SAFE PATTERN: copy to temp, verify, then allow originals to be overwritten.
244
+ // NEVER use renameSync (fails with EXDEV across drives on Windows).
245
+ const tempDir = path.join(
246
+ resolvedTarget,
247
+ `.merlin-upgrade-temp-${Date.now()}`,
248
+ );
249
+ fs.mkdirSync(tempDir, { recursive: true });
250
+
251
+ let upgradeVerified = false;
252
+
253
+ try {
254
+ // 3. Preserve project-owned data to temp (thoughts + domain skills + project-config).
255
+ // Verifies thought-count integrity post-copy; throws ABORT if backup is incomplete.
256
+ preserveProjectData({
257
+ projectMerlinDir: dstMerlin,
258
+ tempDir,
259
+ thoughtCount,
260
+ });
261
+
262
+ // 4. Sync framework directories (delete + copy from source)
263
+ for (const dir of FRAMEWORK_DIRS) {
264
+ const src = path.join(srcMerlin, dir);
265
+ if (fs.existsSync(src)) {
266
+ const dst = path.join(dstMerlin, dir);
267
+ rmDirSync(dst);
268
+ const fileCount = copyDirSync(src, dst);
269
+ result.synced.dirs.push({ name: dir, files: fileCount });
270
+ }
271
+ }
272
+
273
+ // 5. Sync skills/general (replace entirely)
274
+ const srcGeneral = path.join(srcMerlin, "skills", "general");
275
+ const dstGeneral = path.join(dstMerlin, "skills", "general");
276
+ if (fs.existsSync(srcGeneral)) {
277
+ rmDirSync(dstGeneral);
278
+ const fileCount = copyDirSync(srcGeneral, dstGeneral);
279
+ result.synced.dirs.push({ name: "skills/general", files: fileCount });
280
+ }
281
+
282
+ // 6. Restore domain skills (BUG B + bug C defenses live in preserve module).
283
+ // - rm -rf target before cp -r per skill (bug B — project wins on conflict)
284
+ // - opt-in flatten of legacy nested subdirs (bug C — via preflight willFlatten)
285
+ // - additive merge of source-only skills (new from framework)
286
+ const domainResult = restoreDomainSkills({
287
+ tempDomainDir: path.join(tempDir, "domain"),
288
+ dstDomainDir: path.join(dstMerlin, "skills", "domain"),
289
+ srcDomainDir: path.join(srcMerlin, "skills", "domain"),
290
+ flattenNesting: preflight.willFlatten,
291
+ nestedSkills: preflight.nestedSkills,
292
+ });
293
+ if (domainResult.addedFromSource.length > 0) {
294
+ result.synced.dirs.push({
295
+ name: `skills/domain (added: ${domainResult.addedFromSource.join(", ")})`,
296
+ files: domainResult.addedFromSource.length,
297
+ });
298
+ }
299
+ if (domainResult.flattened.length > 0) {
300
+ result.synced.dirs.push({
301
+ name: `skills/domain (flattened legacy nesting: ${domainResult.flattened.join(", ")})`,
302
+ files: domainResult.flattened.length,
303
+ });
304
+ }
305
+
306
+ // 7. Restore thoughts from temp (wholesale replace; ensure canonical subdirs;
307
+ // throw ABORT if count regresses).
308
+ restoreThoughts({
309
+ tempThoughtsDir: path.join(tempDir, "thoughts"),
310
+ dstThoughtsDir: path.join(dstMerlin, "thoughts"),
311
+ thoughtCountBefore: thoughtCount,
312
+ });
313
+
314
+ upgradeVerified = true;
315
+ } finally {
316
+ // SAFETY: Only delete temp if upgrade verified successfully.
317
+ // If not verified, preserve temp for manual recovery.
318
+ if (upgradeVerified) {
319
+ rmDirSync(tempDir);
320
+ } else {
321
+ result.errors.push(
322
+ `Temp backup preserved at ${tempDir} — upgrade not fully verified. ` +
323
+ `Restore from there or from .merlin-backups/latest/ if needed.`,
324
+ );
325
+ }
326
+ }
327
+
328
+ // 8. Sync framework root files
329
+ for (const file of FRAMEWORK_FILES) {
330
+ const src = path.join(srcMerlin, file);
331
+ if (fs.existsSync(src)) {
332
+ fs.copyFileSync(src, path.join(dstMerlin, file));
333
+ result.synced.files.push(file);
334
+ }
335
+ }
336
+
337
+ // 9. Restore project-config.yaml (preserve project identity)
338
+ fs.writeFileSync(dstProjectConfig, projectConfigBackup, "utf8");
339
+
340
+ // 9a. Bump version in project-config.yaml to match source
341
+ bumpProjectConfigVersion(dstProjectConfig, srcVersion);
342
+
343
+ // 10. Sync .claude/rules (additive — never delete first)
344
+ fs.mkdirSync(dstClaude, { recursive: true });
345
+ const srcRules = path.join(srcClaude, "rules");
346
+ if (fs.existsSync(srcRules)) {
347
+ const dstRules = path.join(dstClaude, "rules");
348
+ fs.mkdirSync(dstRules, { recursive: true });
349
+ const fileCount = copyDirSync(srcRules, dstRules);
350
+ result.synced.claude.push({ name: ".claude/rules", files: fileCount });
351
+ }
352
+
353
+ // 10a. Regenerate .claude/commands/ bridges via sync-bridges (Phase 6).
354
+ // Replaces the prior "copy .claude/commands/ wholesale" — bridges
355
+ // are now properly generated from .merlin-core/commands/ sources
356
+ // so the target has the same 31 enriched bridges as gestao-merlin.
357
+ try {
358
+ const bridgesResult = await syncBridges.run(
359
+ "sync-bridges",
360
+ [],
361
+ resolvedTarget,
362
+ );
363
+ if (bridgesResult && bridgesResult.generated) {
364
+ result.synced.claude.push({
365
+ name: ".claude/commands (sync-bridges)",
366
+ files: bridgesResult.generated.length,
367
+ });
368
+ }
369
+ } catch (bridgeErr) {
370
+ result.errors.push(`sync-bridges failed: ${bridgeErr.message}`);
371
+ }
372
+
373
+ // 10b. Copy converterparamagos.md (project-specific — not generated by sync-bridges)
374
+ const converterSrc = path.join(
375
+ srcClaude,
376
+ "commands",
377
+ "converterparamagos.md",
378
+ );
379
+ if (fs.existsSync(converterSrc)) {
380
+ const dstCommands = path.join(dstClaude, "commands");
381
+ fs.mkdirSync(dstCommands, { recursive: true });
382
+ fs.copyFileSync(
383
+ converterSrc,
384
+ path.join(dstCommands, "converterparamagos.md"),
385
+ );
386
+ }
387
+
388
+ // 10c. Copy .claude/commands/Merlin/ subfolder if present (agents, commands, skills bridges)
389
+ const merlinSubfolderSrc = path.join(srcClaude, "commands", "Merlin");
390
+ if (fs.existsSync(merlinSubfolderSrc)) {
391
+ const merlinSubfolderDst = path.join(dstClaude, "commands", "Merlin");
392
+ const fileCount = copyDirSync(merlinSubfolderSrc, merlinSubfolderDst);
393
+ result.synced.claude.push({
394
+ name: ".claude/commands/Merlin",
395
+ files: fileCount,
396
+ });
397
+ }
398
+
399
+ // 11. Sync .claude/CLAUDE.md + .claude/settings.json (hard-overwrite is fine — framework-owned)
400
+ for (const file of CLAUDE_FILES) {
401
+ const src = path.join(srcClaude, file);
402
+ if (fs.existsSync(src)) {
403
+ fs.copyFileSync(src, path.join(dstClaude, file));
404
+ result.synced.claude.push({ name: `.claude/${file}`, files: 1 });
405
+ }
406
+ }
407
+
408
+ // 11a. Sync .claude/hooks/*.js (additive — copy each file individually)
409
+ const srcHooks = path.join(srcClaude, "hooks");
410
+ if (fs.existsSync(srcHooks)) {
411
+ const dstHooks = path.join(dstClaude, "hooks");
412
+ fs.mkdirSync(dstHooks, { recursive: true });
413
+ let hookCount = 0;
414
+ for (const entry of fs.readdirSync(srcHooks, { withFileTypes: true })) {
415
+ if (
416
+ entry.isFile() &&
417
+ (entry.name.endsWith(".js") || entry.name.endsWith(".cjs"))
418
+ ) {
419
+ fs.copyFileSync(
420
+ path.join(srcHooks, entry.name),
421
+ path.join(dstHooks, entry.name),
422
+ );
423
+ hookCount++;
424
+ }
425
+ }
426
+ if (hookCount > 0) {
427
+ result.synced.claude.push({ name: ".claude/hooks", files: hookCount });
428
+ }
429
+ }
430
+
431
+ // 11a-bis. Wire the license gate into the target's settings.json (customer
432
+ // installs only — the framework's own settings omits it on purpose).
433
+ ensureLicenseGateRegistered(dstClaude, result);
434
+
435
+ // 11b. INTELLIGENT MERGE of .claude/settings.local.json (Phase 6).
436
+ // Preserves operator's permissions; additively merges source's hook
437
+ // registrations with dedupe-by-command. Non-fatal on errors.
438
+ try {
439
+ const srcSettings = path.join(srcClaude, "settings.local.json");
440
+ if (fs.existsSync(srcSettings)) {
441
+ const mergeResult = mergeSettingsLocal({
442
+ srcSettingsPath: srcSettings,
443
+ dstSettingsPath: path.join(dstClaude, "settings.local.json"),
444
+ });
445
+ if (mergeResult.created || mergeResult.merged) {
446
+ result.synced.claude.push({
447
+ name: ".claude/settings.local.json (merged)",
448
+ files: 1,
449
+ });
450
+ }
451
+ }
452
+ } catch (mergeErr) {
453
+ result.errors.push(`settings.local.json merge failed: ${mergeErr.message}`);
454
+ }
455
+
456
+ // 12. Sync project root files (.mcp.json)
457
+ for (const file of PROJECT_ROOT_FILES) {
458
+ const src = path.join(projectRoot, file);
459
+ if (fs.existsSync(src)) {
460
+ fs.copyFileSync(src, path.join(resolvedTarget, file));
461
+ result.synced.rootFiles.push(file);
462
+ }
463
+ }
464
+
465
+ // 13. Final verification
466
+ // Post-upgrade: read from project-config.yaml (sed-bumped to srcVersion in step 9a)
467
+ const finalVersion = extractVersion(
468
+ path.join(dstMerlin, "project-config.yaml"),
469
+ );
470
+ const finalThoughts = countRealThoughts(path.join(dstMerlin, "thoughts"));
471
+ const finalDomainSkills = listSubdirs(dstDomain);
472
+ const finalAgents = countFiles(path.join(dstMerlin, "development", "agents"));
473
+ // Count .md files at .claude/commands/ top level (not subdirs)
474
+ const claudeCommandsDir = path.join(resolvedTarget, ".claude", "commands");
475
+ let finalCommandCount = 0;
476
+ if (fs.existsSync(claudeCommandsDir)) {
477
+ finalCommandCount = fs
478
+ .readdirSync(claudeCommandsDir, { withFileTypes: true })
479
+ .filter((e) => e.isFile() && e.name.endsWith(".md")).length;
480
+ }
481
+
482
+ result.verified = finalVersion === srcVersion;
483
+ result.preserved.thoughtsAfter = finalThoughts;
484
+ result.preserved.domainSkillsAfter = finalDomainSkills.length;
485
+ result.installed = { agents: finalAgents, commands: finalCommandCount };
486
+
487
+ // 14. Write upgrade-report.json (always, even on partial failure)
488
+ const reportDate = new Date()
489
+ .toISOString()
490
+ .replace(/[-:]/g, "")
491
+ .replace(/\..*$/, "")
492
+ .replace("T", "-");
493
+ const reportPath = writeUpgradeReport({
494
+ targetDir: resolvedTarget,
495
+ projectName,
496
+ projectDir: resolvedTarget,
497
+ merlinSource: projectRoot,
498
+ date: reportDate,
499
+ mode: "upgrade",
500
+ versionFrom: dstVersion,
501
+ versionTo: srcVersion,
502
+ preserved: {
503
+ thoughts_before: thoughtCount,
504
+ thoughts_after: finalThoughts,
505
+ domain_skills_before: domainSkills.length,
506
+ domain_skills_after: finalDomainSkills.length,
507
+ },
508
+ installed: {
509
+ agents: finalAgents,
510
+ commands: finalCommandCount,
511
+ },
512
+ backups: {
513
+ claude_backup: "", // JS engine doesn't snapshot full .claude — only .claude/commands
514
+ merlin_core_backup: result.backup || "",
515
+ },
516
+ errors: result.errors.length,
517
+ verified: result.verified,
518
+ });
519
+ if (reportPath) {
520
+ result.reportPath = reportPath;
521
+ }
522
+
523
+ // 15. Print WHAT CHANGED block (success) or recovery instructions (failure)
524
+ if (result.verified && result.errors.length === 0) {
525
+ console.log(
526
+ formatWhatChanged({
527
+ versionFrom: dstVersion,
528
+ versionTo: srcVersion,
529
+ thoughtsBefore: thoughtCount,
530
+ thoughtsAfter: finalThoughts,
531
+ domainBefore: domainSkills.length,
532
+ domainAfter: finalDomainSkills.length,
533
+ agentsCount: finalAgents,
534
+ commandsCount: finalCommandCount,
535
+ }),
536
+ );
537
+ } else {
538
+ console.log(
539
+ formatRecoveryInstructions({
540
+ projectDir: resolvedTarget,
541
+ merlinSource: projectRoot,
542
+ backupDir:
543
+ result.backup ||
544
+ path.join(resolvedTarget, ".merlin-backups", "latest"),
545
+ scriptPath: path.join(
546
+ projectRoot,
547
+ ".merlin-core",
548
+ "tools",
549
+ "merlin-tools.js",
550
+ ),
551
+ }),
552
+ );
553
+ }
554
+
555
+ return result;
556
+ }
557
+
558
+ /**
559
+ * CONVERSION pipeline: target has no .merlin-core/ — fresh install + legacy cleanup.
560
+ *
561
+ * Differs from UPGRADE in 4 ways:
562
+ * - No preserve step (nothing to preserve in target)
563
+ * - No restoreDomainSkills / restoreThoughts (source's content stays as-is then trimmed)
564
+ * - Cleans source's stale thoughts/shared/* (those belong to framework, not new project)
565
+ * - Migrates legacy thoughts/ from project root into .merlin-core/thoughts/shared/
566
+ * - Removes legacy .claude/agents/ and .claude/templates/ dirs
567
+ * - Generates fresh project-config.yaml from template (with {{PROJECT_NAME}}, {{SOURCE_VERSION}})
568
+ */
569
+ function runConversion(opts) {
570
+ const {
571
+ resolvedTarget,
572
+ srcMerlin,
573
+ dstMerlin,
574
+ srcClaude,
575
+ dstClaude,
576
+ projectRoot,
577
+ projectName,
578
+ srcVersion,
579
+ result,
580
+ } = opts;
581
+
582
+ // 1. Copy fresh .merlin-core/ from source (whole tree)
583
+ fs.mkdirSync(dstMerlin, { recursive: true });
584
+ for (const dir of FRAMEWORK_DIRS) {
585
+ const src = path.join(srcMerlin, dir);
586
+ if (fs.existsSync(src)) {
587
+ const dst = path.join(dstMerlin, dir);
588
+ const fileCount = copyDirSync(src, dst);
589
+ result.synced.dirs.push({ name: dir, files: fileCount });
590
+ }
591
+ }
592
+ // skills/ (general + domain — both fresh from source for CONVERSION)
593
+ const srcSkills = path.join(srcMerlin, "skills");
594
+ if (fs.existsSync(srcSkills)) {
595
+ const fileCount = copyDirSync(srcSkills, path.join(dstMerlin, "skills"));
596
+ result.synced.dirs.push({ name: "skills", files: fileCount });
597
+ }
598
+ // framework root files
599
+ for (const file of FRAMEWORK_FILES) {
600
+ const src = path.join(srcMerlin, file);
601
+ if (fs.existsSync(src)) {
602
+ fs.copyFileSync(src, path.join(dstMerlin, file));
603
+ result.synced.files.push(file);
604
+ }
605
+ }
606
+
607
+ // 2. Clean source's stale thoughts/shared/* (framework's, not project's)
608
+ const dstThoughtsShared = path.join(dstMerlin, "thoughts", "shared");
609
+ const THOUGHT_SUBDIRS = [
610
+ "decisions",
611
+ "handoffs",
612
+ "learnings",
613
+ "objectives",
614
+ "plans",
615
+ "processes",
616
+ "reminders",
617
+ "research",
618
+ "feedback",
619
+ ];
620
+ for (const sub of THOUGHT_SUBDIRS) {
621
+ const dir = path.join(dstThoughtsShared, sub);
622
+ rmDirSync(dir);
623
+ fs.mkdirSync(dir, { recursive: true });
624
+ fs.writeFileSync(path.join(dir, ".gitkeep"), "");
625
+ }
626
+ // Also clean root-level INDEX files (will be regenerated)
627
+ for (const f of ["INDEX.json", "INDEX.md"]) {
628
+ const p = path.join(dstThoughtsShared, f);
629
+ if (fs.existsSync(p)) fs.unlinkSync(p);
630
+ }
631
+
632
+ // 3. Migrate legacy thoughts/ at project root into .merlin-core/thoughts/shared/
633
+ const legacyThoughts = path.join(resolvedTarget, "thoughts");
634
+ let migrated = 0;
635
+ if (fs.existsSync(legacyThoughts)) {
636
+ const legacyShared = path.join(legacyThoughts, "shared");
637
+ if (fs.existsSync(legacyShared)) {
638
+ for (const sub of THOUGHT_SUBDIRS) {
639
+ const srcSubdir = path.join(legacyShared, sub);
640
+ if (!fs.existsSync(srcSubdir)) continue;
641
+ const dstSubdir = path.join(dstThoughtsShared, sub);
642
+ for (const entry of fs.readdirSync(srcSubdir, {
643
+ withFileTypes: true,
644
+ })) {
645
+ if (entry.isFile() && entry.name !== ".gitkeep") {
646
+ fs.copyFileSync(
647
+ path.join(srcSubdir, entry.name),
648
+ path.join(dstSubdir, entry.name),
649
+ );
650
+ migrated++;
651
+ }
652
+ }
653
+ }
654
+ }
655
+ }
656
+ if (migrated > 0) {
657
+ result.migratedLegacyThoughts = migrated;
658
+ result.legacyThoughtsRootPreserved = legacyThoughts;
659
+ }
660
+
661
+ // 4. Remove legacy .claude/agents/ and .claude/templates/ if present
662
+ const legacyAgents = path.join(dstClaude, "agents");
663
+ const legacyTemplates = path.join(dstClaude, "templates");
664
+ if (fs.existsSync(legacyAgents)) {
665
+ rmDirSync(legacyAgents);
666
+ result.removedLegacy = (result.removedLegacy || []).concat([
667
+ ".claude/agents",
668
+ ]);
669
+ }
670
+ if (fs.existsSync(legacyTemplates)) {
671
+ rmDirSync(legacyTemplates);
672
+ result.removedLegacy = (result.removedLegacy || []).concat([
673
+ ".claude/templates",
674
+ ]);
675
+ }
676
+
677
+ // 4b. Bug-D defense — back up pre-existing .claude/* + .mcp.json BEFORE
678
+ // Step 5/6 overwrites them. Delegated to shared helper so UPGRADE mode
679
+ // uses the same code path.
680
+ // See: learnings/2026-05-17-plan-a-conversion-doesnt-backup-claude-mcp.md
681
+ const convertBackupDir = path.join(
682
+ resolvedTarget,
683
+ ".merlin-backups",
684
+ "latest",
685
+ );
686
+ backupOverwriteRiskArtifacts(dstClaude, resolvedTarget, convertBackupDir);
687
+
688
+ // 5. Sync .claude/ (rules + sync-bridges-generated commands + Merlin/ subfolder +
689
+ // converterparamagos + CLAUDE.md + settings.json + hooks + settings.local.json merge)
690
+ fs.mkdirSync(dstClaude, { recursive: true });
691
+ const srcRules = path.join(srcClaude, "rules");
692
+ if (fs.existsSync(srcRules)) {
693
+ const dstRules = path.join(dstClaude, "rules");
694
+ fs.mkdirSync(dstRules, { recursive: true });
695
+ const fileCount = copyDirSync(srcRules, dstRules);
696
+ result.synced.claude.push({ name: ".claude/rules", files: fileCount });
697
+ }
698
+ // Bridges generated from .merlin-core/commands/ sources
699
+ // (caller-async note: runConversion is sync but syncBridges.run is async-but-sync-body;
700
+ // we treat it as sync via .then-style would complicate — but the run() function is
701
+ // marked async so callers await; bridges only does fs ops; calling without await is fine
702
+ // in practice since its work completes synchronously before any returned promise resolves.
703
+ // Doing a fire-and-forget here mirrors how the test fixture handles it.)
704
+ try {
705
+ const bridgesResult = syncBridges.run("sync-bridges", [], resolvedTarget);
706
+ // syncBridges.run() returns the result object directly (despite being async,
707
+ // its body is sync; the Promise just wraps the result).
708
+ if (bridgesResult && typeof bridgesResult.then === "function") {
709
+ // Best-effort: don't block — but in CONVERSION we want bridges before we return.
710
+ // Switch to await would require runConversion to be async — change deferred.
711
+ }
712
+ } catch (bridgeErr) {
713
+ result.errors.push(`sync-bridges failed: ${bridgeErr.message}`);
714
+ }
715
+ // converterparamagos.md (project-specific)
716
+ const converterSrc = path.join(
717
+ srcClaude,
718
+ "commands",
719
+ "converterparamagos.md",
720
+ );
721
+ if (fs.existsSync(converterSrc)) {
722
+ const dstCommands = path.join(dstClaude, "commands");
723
+ fs.mkdirSync(dstCommands, { recursive: true });
724
+ fs.copyFileSync(
725
+ converterSrc,
726
+ path.join(dstCommands, "converterparamagos.md"),
727
+ );
728
+ }
729
+ // .claude/commands/Merlin/ subfolder
730
+ const merlinSubfolderSrc = path.join(srcClaude, "commands", "Merlin");
731
+ if (fs.existsSync(merlinSubfolderSrc)) {
732
+ copyDirSync(merlinSubfolderSrc, path.join(dstClaude, "commands", "Merlin"));
733
+ }
734
+ // CLAUDE.md + settings.json
735
+ for (const file of CLAUDE_FILES) {
736
+ const src = path.join(srcClaude, file);
737
+ if (fs.existsSync(src)) {
738
+ fs.copyFileSync(src, path.join(dstClaude, file));
739
+ result.synced.claude.push({ name: `.claude/${file}`, files: 1 });
740
+ }
741
+ }
742
+ // .claude/hooks/*.js
743
+ const srcHooks = path.join(srcClaude, "hooks");
744
+ if (fs.existsSync(srcHooks)) {
745
+ const dstHooks = path.join(dstClaude, "hooks");
746
+ fs.mkdirSync(dstHooks, { recursive: true });
747
+ for (const entry of fs.readdirSync(srcHooks, { withFileTypes: true })) {
748
+ if (
749
+ entry.isFile() &&
750
+ (entry.name.endsWith(".js") || entry.name.endsWith(".cjs"))
751
+ ) {
752
+ fs.copyFileSync(
753
+ path.join(srcHooks, entry.name),
754
+ path.join(dstHooks, entry.name),
755
+ );
756
+ }
757
+ }
758
+ }
759
+ // Wire the license gate into the target's settings.json (customer install).
760
+ ensureLicenseGateRegistered(dstClaude, result);
761
+ // settings.local.json merge
762
+ try {
763
+ const srcSettings = path.join(srcClaude, "settings.local.json");
764
+ if (fs.existsSync(srcSettings)) {
765
+ mergeSettingsLocal({
766
+ srcSettingsPath: srcSettings,
767
+ dstSettingsPath: path.join(dstClaude, "settings.local.json"),
768
+ });
769
+ }
770
+ } catch (mergeErr) {
771
+ result.errors.push(`settings.local.json merge failed: ${mergeErr.message}`);
772
+ }
773
+
774
+ // 6. Sync .mcp.json
775
+ for (const file of PROJECT_ROOT_FILES) {
776
+ const src = path.join(projectRoot, file);
777
+ if (fs.existsSync(src)) {
778
+ fs.copyFileSync(src, path.join(resolvedTarget, file));
779
+ result.synced.rootFiles.push(file);
780
+ }
781
+ }
782
+
783
+ // 7. Generate project-config.yaml from template
784
+ const templatePath = path.join(
785
+ __dirname,
786
+ "lib",
787
+ "project-config.template.yaml",
788
+ );
789
+ if (fs.existsSync(templatePath)) {
790
+ let template = fs.readFileSync(templatePath, "utf8");
791
+ template = template
792
+ .replace(/\{\{PROJECT_NAME\}\}/g, projectName)
793
+ .replace(/\{\{SOURCE_VERSION\}\}/g, srcVersion);
794
+ fs.writeFileSync(
795
+ path.join(dstMerlin, "project-config.yaml"),
796
+ template,
797
+ "utf8",
798
+ );
799
+ result.generatedProjectConfig = true;
800
+ } else {
801
+ result.errors.push(
802
+ `project-config.template.yaml not found at: ${templatePath}`,
803
+ );
804
+ }
805
+
806
+ // 8. Verification (lighter than UPGRADE — only check key files exist)
807
+ const finalAgents = countFiles(path.join(dstMerlin, "development", "agents"));
808
+ const claudeCommandsDir = path.join(resolvedTarget, ".claude", "commands");
809
+ let finalCommandCount = 0;
810
+ if (fs.existsSync(claudeCommandsDir)) {
811
+ finalCommandCount = fs
812
+ .readdirSync(claudeCommandsDir, { withFileTypes: true })
813
+ .filter((e) => e.isFile() && e.name.endsWith(".md")).length;
814
+ }
815
+ const finalDomainSkills = listSubdirs(
816
+ path.join(dstMerlin, "skills", "domain"),
817
+ );
818
+ result.verified =
819
+ fs.existsSync(path.join(dstMerlin, "constitution.md")) &&
820
+ fs.existsSync(path.join(dstMerlin, "project-config.yaml")) &&
821
+ finalAgents >= 15;
822
+ result.preserved.thoughtsAfter = countRealThoughts(
823
+ path.join(dstMerlin, "thoughts"),
824
+ );
825
+ result.preserved.domainSkillsAfter = finalDomainSkills.length;
826
+ result.installed = { agents: finalAgents, commands: finalCommandCount };
827
+
828
+ // 9. Write upgrade-report.json (CONVERSION variant)
829
+ const reportDate = new Date()
830
+ .toISOString()
831
+ .replace(/[-:]/g, "")
832
+ .replace(/\..*$/, "")
833
+ .replace("T", "-");
834
+ const reportPath = writeUpgradeReport({
835
+ targetDir: resolvedTarget,
836
+ projectName,
837
+ projectDir: resolvedTarget,
838
+ merlinSource: projectRoot,
839
+ date: reportDate,
840
+ mode: "convert",
841
+ versionFrom: "none",
842
+ versionTo: srcVersion,
843
+ preserved: {
844
+ thoughts_before: 0,
845
+ thoughts_after: result.preserved.thoughtsAfter,
846
+ domain_skills_before: 0,
847
+ domain_skills_after: result.preserved.domainSkillsAfter,
848
+ },
849
+ installed: { agents: finalAgents, commands: finalCommandCount },
850
+ backups: { claude_backup: "", merlin_core_backup: "" },
851
+ errors: result.errors.length,
852
+ verified: result.verified,
853
+ });
854
+ if (reportPath) result.reportPath = reportPath;
855
+
856
+ // 10. WHAT CHANGED (success) or recovery (failure)
857
+ if (result.verified && result.errors.length === 0) {
858
+ console.log(
859
+ formatWhatChanged({
860
+ versionFrom: "none",
861
+ versionTo: srcVersion,
862
+ thoughtsBefore: 0,
863
+ thoughtsAfter: result.preserved.thoughtsAfter,
864
+ domainBefore: 0,
865
+ domainAfter: result.preserved.domainSkillsAfter,
866
+ agentsCount: finalAgents,
867
+ commandsCount: finalCommandCount,
868
+ }),
869
+ );
870
+ } else {
871
+ console.log(
872
+ formatRecoveryInstructions({
873
+ projectDir: resolvedTarget,
874
+ merlinSource: projectRoot,
875
+ backupDir: path.join(resolvedTarget, ".merlin-backups", "latest"),
876
+ scriptPath: path.join(
877
+ projectRoot,
878
+ ".merlin-core",
879
+ "tools",
880
+ "merlin-tools.js",
881
+ ),
882
+ }),
883
+ );
884
+ }
885
+
886
+ return result;
887
+ }
888
+
889
+ /**
890
+ * Pure: should the license gate be wired for THIS install? Opt-in only — the
891
+ * paid-client install sets `MERLIN_LICENSE_GATE=1`. Every other install (and the
892
+ * dev repo) leaves it unset, so we do NOT auto-inject a blocking hook that would
893
+ * brick an unlicensed session (see .claude/hooks/README-license-gate.md and
894
+ * [[gotcha-merlin-license-gate-blocks-fresh-install]]).
895
+ */
896
+ function shouldRegisterLicenseGate(env = process.env) {
897
+ return env.MERLIN_LICENSE_GATE === "1";
898
+ }
899
+
900
+ /**
901
+ * Pure: given a parsed settings object, return a NEW settings object with the
902
+ * license-gate hook registered AND the arming env (`env.MERLIN_LICENSE_GATE="1"`)
903
+ * set so the hook is live at runtime — or null if it was already wired
904
+ * (idempotent). Does no I/O.
905
+ */
906
+ function computeLicenseGateSettings(settings) {
907
+ const existing = (settings.hooks && settings.hooks.UserPromptSubmit) || [];
908
+ if (JSON.stringify(existing).includes("license-gate.cjs")) return null;
909
+ return {
910
+ ...settings,
911
+ hooks: {
912
+ ...(settings.hooks || {}),
913
+ UserPromptSubmit: [
914
+ ...existing,
915
+ {
916
+ hooks: [
917
+ { type: "command", command: "node .claude/hooks/license-gate.cjs" },
918
+ ],
919
+ },
920
+ ],
921
+ },
922
+ env: { ...(settings.env || {}), MERLIN_LICENSE_GATE: "1" },
923
+ };
924
+ }
925
+
926
+ /**
927
+ * Register + ARM the license gate in the TARGET project's settings.json — but
928
+ * only for an opted-in (paid-client) install. The hook ships either way; this
929
+ * just wires it and sets the arming env. Idempotent + non-fatal.
930
+ */
931
+ function ensureLicenseGateRegistered(dstClaude, result, opts = {}) {
932
+ try {
933
+ if (!shouldRegisterLicenseGate(opts.env || process.env)) return; // opt-in only
934
+ const settingsPath = path.join(dstClaude, "settings.json");
935
+ if (!fs.existsSync(settingsPath)) return;
936
+ const settings = JSON.parse(fs.readFileSync(settingsPath, "utf8"));
937
+ const next = computeLicenseGateSettings(settings);
938
+ if (!next) return; // already wired
939
+ fs.writeFileSync(settingsPath, JSON.stringify(next, null, 2) + "\n");
940
+ result.synced.claude.push({
941
+ name: ".claude/settings.json (license gate, armed)",
942
+ files: 1,
943
+ });
944
+ } catch {
945
+ // non-fatal — never let a settings.json quirk break the install
946
+ }
947
+ }
948
+
949
+ /**
950
+ * Bug-D defense — back up files that the install/upgrade pipeline overwrites:
951
+ * .claude/CLAUDE.md, .claude/settings.json, .claude/hooks/, .mcp.json
952
+ * .claude/rules/ is intentionally excluded — its sync is additive.
953
+ * Idempotent: missing source files are silently skipped.
954
+ *
955
+ * Used by BOTH:
956
+ * - runConversion()'s Step 4b (before .claude/ + .mcp.json overwrites)
957
+ * - createPreUpgradeBackup() (UPGRADE mode parity)
958
+ *
959
+ * @param {string} claudeDir Target's .claude/ directory
960
+ * @param {string} mcpRoot Target's root (for .mcp.json)
961
+ * @param {string} backupDir Destination .merlin-backups/latest/
962
+ */
963
+ function backupOverwriteRiskArtifacts(claudeDir, mcpRoot, backupDir) {
964
+ fs.mkdirSync(backupDir, { recursive: true });
965
+ const backupClaudeDir = path.join(backupDir, ".claude");
966
+ const claudeMd = path.join(claudeDir, "CLAUDE.md");
967
+ if (fs.existsSync(claudeMd)) {
968
+ fs.mkdirSync(backupClaudeDir, { recursive: true });
969
+ fs.copyFileSync(claudeMd, path.join(backupClaudeDir, "CLAUDE.md"));
970
+ }
971
+ const claudeSettings = path.join(claudeDir, "settings.json");
972
+ if (fs.existsSync(claudeSettings)) {
973
+ fs.mkdirSync(backupClaudeDir, { recursive: true });
974
+ fs.copyFileSync(
975
+ claudeSettings,
976
+ path.join(backupClaudeDir, "settings.json"),
977
+ );
978
+ }
979
+ const claudeHooks = path.join(claudeDir, "hooks");
980
+ if (fs.existsSync(claudeHooks)) {
981
+ copyDirSync(claudeHooks, path.join(backupClaudeDir, "hooks"));
982
+ }
983
+ const mcpJson = path.join(mcpRoot, ".mcp.json");
984
+ if (fs.existsSync(mcpJson)) {
985
+ fs.copyFileSync(mcpJson, path.join(backupDir, ".mcp.json"));
986
+ }
987
+ }
988
+
989
+ /**
990
+ * Create a pre-upgrade backup in .merlin-backups/latest/.
991
+ * Rotates old backup (only keeps one).
992
+ */
993
+ function createPreUpgradeBackup(merlinDir, claudeDir, backupDir, targetRoot) {
994
+ // Rotate: delete previous "latest" if exists
995
+ rmDirSync(backupDir);
996
+ fs.mkdirSync(backupDir, { recursive: true });
997
+
998
+ // Backup thoughts
999
+ const srcThoughts = path.join(merlinDir, "thoughts");
1000
+ if (fs.existsSync(srcThoughts)) {
1001
+ copyDirSync(srcThoughts, path.join(backupDir, "thoughts"));
1002
+ }
1003
+
1004
+ // Backup domain skills
1005
+ const srcDomain = path.join(merlinDir, "skills", "domain");
1006
+ if (fs.existsSync(srcDomain)) {
1007
+ copyDirSync(srcDomain, path.join(backupDir, "domain-skills"));
1008
+ }
1009
+
1010
+ // Backup project-config
1011
+ const projConfig = path.join(merlinDir, "project-config.yaml");
1012
+ if (fs.existsSync(projConfig)) {
1013
+ fs.copyFileSync(projConfig, path.join(backupDir, "project-config.yaml"));
1014
+ }
1015
+
1016
+ // Backup .claude/commands (custom satellite commands)
1017
+ const claudeCommands = path.join(claudeDir, "commands");
1018
+ if (fs.existsSync(claudeCommands)) {
1019
+ copyDirSync(claudeCommands, path.join(backupDir, "claude-commands"));
1020
+ }
1021
+
1022
+ // Bug-D parity (2026-05-17) — delegate to shared helper so CONVERT mode
1023
+ // also gets the same coverage. Falls back to deriving targetRoot from
1024
+ // claudeDir when not passed (backward-compat for older call sites).
1025
+ backupOverwriteRiskArtifacts(
1026
+ claudeDir,
1027
+ targetRoot || path.dirname(claudeDir),
1028
+ backupDir,
1029
+ );
1030
+
1031
+ // Write manifest — version is project's pre-upgrade installed version
1032
+ const manifest = {
1033
+ timestamp: new Date().toISOString(),
1034
+ version: extractVersion(path.join(merlinDir, "project-config.yaml")),
1035
+ contents: [
1036
+ "thoughts",
1037
+ "domain-skills",
1038
+ "project-config.yaml",
1039
+ "claude-commands",
1040
+ ".claude/CLAUDE.md",
1041
+ ".claude/settings.json",
1042
+ ".claude/hooks",
1043
+ ".mcp.json",
1044
+ ],
1045
+ };
1046
+ fs.writeFileSync(
1047
+ path.join(backupDir, "backup-manifest.json"),
1048
+ JSON.stringify(manifest, null, 2),
1049
+ );
1050
+ }
1051
+
1052
+ function formatHuman(result) {
1053
+ // Short-circuit cases (idempotency bail OR dry-run): preflight already printed
1054
+ // the banner + summary live during execution. Nothing more to add here.
1055
+ if (result.shortCircuit) {
1056
+ return result.reportPath ? `\nReport written: ${result.reportPath}\n` : "";
1057
+ }
1058
+
1059
+ const lines = [];
1060
+ const mode = result.dryRun ? "DRY RUN" : "UPGRADE";
1061
+ lines.push(`\n=== Merlin Core ${mode}: ${result.project} ===`);
1062
+ lines.push(`Target: ${result.target}`);
1063
+ lines.push(`Version: ${result.from} → ${result.to}`);
1064
+ lines.push("");
1065
+
1066
+ if (result.backup) {
1067
+ lines.push(`Pre-upgrade backup: ${result.backup}`);
1068
+ lines.push("");
1069
+ }
1070
+
1071
+ if (result.synced.dirs.length > 0) {
1072
+ lines.push("Framework directories:");
1073
+ for (const d of result.synced.dirs) {
1074
+ lines.push(` ✓ ${d.name} (${d.files} files)`);
1075
+ }
1076
+ }
1077
+
1078
+ if (result.synced.files.length > 0) {
1079
+ lines.push("\nFramework files:");
1080
+ for (const f of result.synced.files) {
1081
+ lines.push(` ✓ ${f}`);
1082
+ }
1083
+ }
1084
+
1085
+ if (result.synced.claude.length > 0) {
1086
+ lines.push("\nClaude IDE integration:");
1087
+ for (const c of result.synced.claude) {
1088
+ lines.push(` ✓ ${c.name} (${c.files} files)`);
1089
+ }
1090
+ }
1091
+
1092
+ if (result.synced.rootFiles && result.synced.rootFiles.length > 0) {
1093
+ lines.push("\nProject root files:");
1094
+ for (const f of result.synced.rootFiles) {
1095
+ lines.push(` ✓ ${f}`);
1096
+ }
1097
+ }
1098
+
1099
+ // Preserved data
1100
+ const p = result.preserved;
1101
+ lines.push("\nPreserved (project-owned):");
1102
+ lines.push(` ✓ project-config.yaml`);
1103
+ lines.push(
1104
+ ` ✓ thoughts/ (${p.thoughts} files${p.thoughtsAfter !== undefined ? ` → ${p.thoughtsAfter} after` : ""})`,
1105
+ );
1106
+ lines.push(
1107
+ ` ✓ skills/domain/ (${p.domainSkills.length} skills: ${p.domainSkills.join(", ") || "none"})`,
1108
+ );
1109
+
1110
+ if (!result.dryRun && result.verified !== undefined) {
1111
+ lines.push(
1112
+ `\nVerification: ${result.verified ? "PASSED" : "FAILED"} (${result.to})`,
1113
+ );
1114
+ }
1115
+
1116
+ if (result.errors.length > 0) {
1117
+ lines.push("\nWarnings:");
1118
+ for (const e of result.errors) {
1119
+ lines.push(` ⚠ ${e}`);
1120
+ }
1121
+ }
1122
+
1123
+ if (result.reportPath) {
1124
+ lines.push(`\nReport written: ${result.reportPath}`);
1125
+ }
1126
+
1127
+ return lines.join("\n");
1128
+ }
1129
+
1130
+ module.exports = {
1131
+ run,
1132
+ formatHuman,
1133
+ shouldRegisterLicenseGate,
1134
+ computeLicenseGateSettings,
1135
+ };