@wix/agent-skills 1.15.0 → 1.16.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 (355) hide show
  1. package/README.md +5 -1
  2. package/package.json +1 -1
  3. package/skills/wix-app/SKILL.md +4 -1
  4. package/skills/wix-app/references/APP_TOOLS.md +134 -0
  5. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +1 -1
  6. package/skills/wix-app/references/DASHBOARD_PAGE.md +0 -10
  7. package/skills/wix-app/references/DATA_COLLECTION.md +6 -4
  8. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +28 -7
  9. package/skills/wix-app/references/SERVICE_PLUGIN.md +12 -10
  10. package/skills/wix-app/references/STORES_VERSIONING.md +9 -211
  11. package/skills/wix-app/references/app-tools/TOOLS.md +75 -0
  12. package/skills/wix-app/references/backend-event/COMMON-EVENTS.md +5 -0
  13. package/skills/wix-app/references/dashboard-page/DASHBOARD_API.md +2 -2
  14. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW-REFERENCE.md +172 -0
  15. package/skills/wix-app/references/editor-react-component/A11Y-REVIEW.md +138 -0
  16. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +172 -0
  17. package/skills/wix-app/references/editor-react-component/BRANDED-COMPONENTS.md +29 -0
  18. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +1 -1
  19. package/skills/wix-app/references/editor-react-component/COMPONENT-PREVIEW.md +57 -0
  20. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +33 -2
  21. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +5 -3
  22. package/skills/wix-app/references/editor-react-component/DIRECTIONALITY.md +18 -1
  23. package/skills/wix-app/references/editor-react-component/PARTS.md +15 -2
  24. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +4 -3
  25. package/skills/wix-app/references/service-plugin/BOOKINGS-STAFF-SORTING.md +13 -9
  26. package/skills/wix-app/references/service-plugin/DISCOUNT-TRIGGERS.md +4 -0
  27. package/skills/wix-app/references/service-plugin/GIFT-CARDS.md +4 -0
  28. package/skills/wix-app/references/service-plugin/PAYMENT-SETTINGS.md +3 -1
  29. package/skills/wix-app/references/service-plugin/SHIPPING-RATES.md +4 -0
  30. package/skills/wix-app/references/service-plugin/TOOLS_PROVIDER.md +54 -0
  31. package/skills/wix-app/references/stores/CATEGORIES.md +22 -0
  32. package/skills/wix-app/references/stores/GET_PRODUCT.md +99 -0
  33. package/skills/wix-app/references/stores/INVENTORY.md +37 -0
  34. package/skills/wix-app/references/stores/QUERY.md +119 -0
  35. package/skills/wix-app/references/stores/WRITE.md +55 -0
  36. package/skills/wix-docs/SKILL.md +35 -3
  37. package/skills/wix-headless/SKILL.md +9 -2
  38. package/skills/wix-headless/entry/bootstrap.mjs +2 -2
  39. package/skills/wix-headless/entry/skill.md +0 -2
  40. package/skills/wix-headless/references/CAPABILITIES.md +6 -4
  41. package/skills/wix-headless/references/CONTENT.md +36 -0
  42. package/skills/wix-headless/references/DESIGN.md +54 -0
  43. package/skills/wix-headless/references/DISCOVERY.md +25 -1
  44. package/skills/wix-headless/references/FEEDBACK.md +16 -5
  45. package/skills/wix-headless/references/IMAGE_GENERATION.md +10 -0
  46. package/skills/wix-headless/references/SDK_HANDOFF.md +2 -0
  47. package/skills/wix-headless/references/SEED.md +3 -1
  48. package/skills/wix-headless/references/SETUP.md +1 -1
  49. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +3 -2
  50. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +42 -2
  51. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +5 -1
  52. package/skills/wix-headless/references/inline-recipes/setup-forms.md +1 -1
  53. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +33 -8
  54. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +3 -1
  55. package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +73 -0
  56. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +38 -2
  57. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +20 -1
  58. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +1 -1
  59. package/skills/wix-headless/references/managed/CONNECT.md +2 -2
  60. package/skills/wix-headless/references/managed/CREATE.md +15 -1
  61. package/skills/wix-headless/references/managed/DEPLOYMENT.md +47 -0
  62. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +8 -0
  63. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +8 -0
  64. package/skills/wix-manage/SKILL.md +131 -12
  65. package/skills/wix-manage/references/analytics/analytics-dashboard-navigation.md +41 -0
  66. package/skills/wix-manage/references/analytics/query-site-analytics.md +66 -9
  67. package/skills/wix-manage/references/app-installation/app-installation-dashboard-navigation.md +28 -0
  68. package/skills/wix-manage/references/app-installation/install-wix-apps.md +3 -0
  69. package/skills/wix-manage/references/blog/blog-dashboard-navigation.md +56 -0
  70. package/skills/wix-manage/references/blog/how-to-create-blog-posts.md +31 -6
  71. package/skills/wix-manage/references/bookings/booking-service-policy-setup.md +3 -1
  72. package/skills/wix-manage/references/bookings/bookings-dashboard-navigation.md +63 -0
  73. package/skills/wix-manage/references/bookings/create-booking-service-from-prompt.md +6 -5
  74. package/skills/wix-manage/references/bookings/create-course-service.md +30 -5
  75. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +85 -42
  76. package/skills/wix-manage/references/cms/cms-dashboard-navigation.md +44 -0
  77. package/skills/wix-manage/references/cms/cms-data-items-crud.md +31 -3
  78. package/skills/wix-manage/references/cms/cms-publishing-flow.md +287 -0
  79. package/skills/wix-manage/references/cms/cms-schema-management.md +33 -1
  80. package/skills/wix-manage/references/contacts/contacts-dashboard-navigation.md +46 -0
  81. package/skills/wix-manage/references/contacts/create-a-contact.md +82 -0
  82. package/skills/wix-manage/references/contacts/update-a-contact.md +119 -0
  83. package/skills/wix-manage/references/dashboard-navigation/dashboard-navigation.md +82 -0
  84. package/skills/wix-manage/references/dashboard-navigation/routes.json +1733 -0
  85. package/skills/wix-manage/references/domains/domains-dashboard-navigation.md +32 -0
  86. package/skills/wix-manage/references/ecommerce/ecom-pricing.md +4 -4
  87. package/skills/wix-manage/references/ecommerce/ecom-shipping.md +1 -1
  88. package/skills/wix-manage/references/ecommerce/gift-cards/ecom-gift-cards-goal-sell-gift-cards.md +338 -0
  89. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-create-discount-rule.md +42 -78
  90. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-bundle-and-save.md +1 -1
  91. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-stock-mover.md +1 -1
  92. package/skills/wix-manage/references/ecommerce/pricing-promotions/ecom-pricing-flow-upsell-boost.md +1 -1
  93. package/skills/wix-manage/references/ecommerce/recommend-ecommerce-strategy.md +90 -92
  94. package/skills/wix-manage/references/events/create-wix-event.md +176 -0
  95. package/skills/wix-manage/references/events/manage-wix-events.md +174 -0
  96. package/skills/wix-manage/references/forms/forms-dashboard-navigation.md +44 -0
  97. package/skills/wix-manage/references/get-paid/get-paid-dashboard-navigation.md +52 -0
  98. package/skills/wix-manage/references/get-paid/how-to-setup-wix-payments.md +30 -7
  99. package/skills/wix-manage/references/google-ads/billing-and-payment.md +80 -0
  100. package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +212 -0
  101. package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +110 -0
  102. package/skills/wix-manage/references/google-ads/google-ads-dashboard-navigation.md +25 -0
  103. package/skills/wix-manage/references/google-ads/install-and-create-account.md +155 -0
  104. package/skills/wix-manage/references/google-ads/manage-campaign-lifecycle.md +63 -0
  105. package/skills/wix-manage/references/google-ads/query-campaign-analytics.md +155 -0
  106. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +225 -144
  107. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +19 -10
  108. package/skills/wix-manage/references/marketing/marketing-dashboard-navigation.md +52 -0
  109. package/skills/wix-manage/references/pricing-plans/create-and-update-pricing-plans.md +99 -1
  110. package/skills/wix-manage/references/pricing-plans/pricing-plans-dashboard-navigation.md +45 -0
  111. package/skills/wix-manage/references/restaurants/restaurants-dashboard-navigation.md +68 -0
  112. package/skills/wix-manage/references/restaurants/wix-restaurants-setup.md +94 -125
  113. package/skills/wix-manage/references/site-properties/change-payment-currency-site-properties.md +48 -9
  114. package/skills/wix-manage/references/site-properties/site-properties-dashboard-navigation.md +31 -0
  115. package/skills/wix-manage/references/sites/create-headless-site.md +52 -0
  116. package/skills/wix-manage/references/sites/create-site-from-template.md +2 -25
  117. package/skills/wix-manage/references/sites/site-import.md +243 -0
  118. package/skills/wix-manage/references/sites/sites-dashboard-navigation.md +29 -0
  119. package/skills/wix-manage/references/stores/add-store-pages-to-site.md +17 -1
  120. package/skills/wix-manage/references/stores/create-product-from-image.md +8 -6
  121. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +16 -10
  122. package/skills/wix-manage/references/stores/find-products-query-and-search-catalog-v3.md +26 -8
  123. package/skills/wix-manage/references/stores/stores-dashboard-navigation.md +65 -0
  124. package/skills/wix-manage/references/stores/update-product-with-options.md +39 -7
  125. package/skills/wix-replatform/.publish-manifest.json +8 -0
  126. package/skills/wix-replatform/SKILL.md +693 -0
  127. package/skills/wix-replatform/lib/artifact-freshness.js +215 -0
  128. package/skills/wix-replatform/lib/completion-report.js +200 -0
  129. package/skills/wix-replatform/lib/config-env.js +59 -0
  130. package/skills/wix-replatform/lib/execution-manifest.js +185 -0
  131. package/skills/wix-replatform/lib/execution-state.js +173 -0
  132. package/skills/wix-replatform/lib/import-recovery.js +313 -0
  133. package/skills/wix-replatform/lib/local-state.js +642 -0
  134. package/skills/wix-replatform/lib/orchestration-preflight.js +143 -0
  135. package/skills/wix-replatform/lib/orchestration-router.js +122 -0
  136. package/skills/wix-replatform/lib/orchestration-state.js +455 -0
  137. package/skills/wix-replatform/lib/progress-log.js +224 -0
  138. package/skills/wix-replatform/lib/progress-log.sh +140 -0
  139. package/skills/wix-replatform/lib/url-preservation-state.js +391 -0
  140. package/skills/wix-replatform/resources/rp-discovery/SKILL.md +184 -0
  141. package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +529 -0
  142. package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +316 -0
  143. package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +64 -0
  144. package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +1114 -0
  145. package/skills/wix-replatform/resources/rp-mapper/SKILL.md +430 -0
  146. package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +217 -0
  147. package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +148 -0
  148. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +378 -0
  149. package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +183 -0
  150. package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +478 -0
  151. package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +136 -0
  152. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
  153. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +310 -0
  154. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +1081 -0
  155. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +618 -0
  156. package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +949 -0
  157. package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +196 -0
  158. package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +66 -0
  159. package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +60 -0
  160. package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +95 -0
  161. package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +82 -0
  162. package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +256 -0
  163. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +249 -0
  164. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +444 -0
  165. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +774 -0
  166. package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +71 -0
  167. package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +632 -0
  168. package/skills/wix-replatform/resources/rp-target-wix/SPEC-product-reviews-and-blog-authorship.md +330 -0
  169. package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +21 -0
  170. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +19 -0
  171. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +37 -0
  172. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +37 -0
  173. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +39 -0
  174. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +35 -0
  175. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +14 -0
  176. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +35 -0
  177. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +36 -0
  178. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +35 -0
  179. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +14 -0
  180. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +131 -0
  181. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +37 -0
  182. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +37 -0
  183. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +21 -0
  184. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +37 -0
  185. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +37 -0
  186. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +97 -0
  187. package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +528 -0
  188. package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +14 -0
  189. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +38 -0
  190. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +37 -0
  191. package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +13 -0
  192. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +37 -0
  193. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +53 -0
  194. package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +84 -0
  195. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +25 -0
  196. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +37 -0
  197. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +37 -0
  198. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +38 -0
  199. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +37 -0
  200. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +90 -0
  201. package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +64 -0
  202. package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +141 -0
  203. package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +384 -0
  204. package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +260 -0
  205. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +238 -0
  206. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +237 -0
  207. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +238 -0
  208. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +2219 -0
  209. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +31 -0
  210. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +100 -0
  211. package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +107 -0
  212. package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +344 -0
  213. package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +250 -0
  214. package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +1927 -0
  215. package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +83 -0
  216. package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +141 -0
  217. package/skills/wix-replatform/scripts/artifact-freshness.js +76 -0
  218. package/skills/wix-replatform/scripts/execution-manifest-validate.js +43 -0
  219. package/skills/wix-replatform/scripts/execution-state-prepare.js +128 -0
  220. package/skills/wix-replatform/scripts/orchestration-preflight.js +48 -0
  221. package/skills/wix-replatform/scripts/orchestration-route.js +46 -0
  222. package/skills/wix-replatform/scripts/orchestration-state.js +245 -0
  223. package/skills/wix-vibe-headless/SKILL.md +54 -25
  224. package/skills/wix-vibe-headless/install/deploy.cjs +95 -0
  225. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +34 -0
  226. package/skills/wix-vibe-headless/platforms/README.md +26 -0
  227. package/skills/wix-vibe-headless/platforms/base44.md +177 -0
  228. package/skills/wix-vibe-headless/platforms/generic.md +122 -0
  229. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +230 -119
  230. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +43 -0
  231. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +25 -0
  232. package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +15 -0
  233. package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +35 -0
  234. package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +38 -0
  235. package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +40 -0
  236. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +54 -0
  237. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +65 -0
  238. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +50 -0
  239. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +103 -0
  240. package/skills/wix-vibe-headless/references/blog/seed/seed-blog.js +270 -0
  241. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +260 -145
  242. package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +65 -0
  243. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +47 -0
  244. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +13 -0
  245. package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +126 -0
  246. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +108 -0
  247. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +58 -0
  248. package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +95 -0
  249. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +94 -0
  250. package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +89 -0
  251. package/skills/wix-vibe-headless/references/bookings/{wix-bookings-checkout.js → app/rest/wix-bookings-checkout.js} +1 -1
  252. package/skills/wix-vibe-headless/references/bookings/{wix-bookings-services.js → app/rest/wix-bookings-services.js} +90 -12
  253. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +117 -0
  254. package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.js +333 -0
  255. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +169 -147
  256. package/skills/wix-vibe-headless/references/cms/app/collection.config.js +31 -0
  257. package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +18 -0
  258. package/skills/wix-vibe-headless/references/cms/{wix-cms.js → app/rest/wix-cms.js} +47 -2
  259. package/skills/wix-vibe-headless/references/cms/seed/SEED.md +145 -0
  260. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +228 -131
  261. package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +23 -0
  262. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +43 -0
  263. package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +13 -0
  264. package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +29 -0
  265. package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +57 -0
  266. package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +78 -0
  267. package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +27 -0
  268. package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +54 -0
  269. package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +40 -0
  270. package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +81 -0
  271. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +48 -0
  272. package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +36 -0
  273. package/skills/wix-vibe-headless/references/events/{wix-events-browse.js → app/rest/wix-events-browse.js} +3 -2
  274. package/skills/wix-vibe-headless/references/events/seed/SEED.md +107 -0
  275. package/skills/wix-vibe-headless/references/events/seed/seed-events.js +251 -0
  276. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +276 -188
  277. package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +101 -0
  278. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +33 -0
  279. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +21 -0
  280. package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +29 -0
  281. package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +54 -0
  282. package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +77 -0
  283. package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +36 -0
  284. package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +32 -0
  285. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +35 -0
  286. package/skills/wix-vibe-headless/references/members/{wix-members-auth.js → app/rest/wix-members-auth.js} +6 -3
  287. package/skills/wix-vibe-headless/references/members/install/Register.jsx +22 -0
  288. package/skills/wix-vibe-headless/references/members/seed/SEED.md +22 -0
  289. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +233 -104
  290. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +31 -0
  291. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +15 -0
  292. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +39 -0
  293. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +15 -0
  294. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +29 -0
  295. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +35 -0
  296. package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +27 -0
  297. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +25 -0
  298. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +39 -0
  299. package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +27 -0
  300. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +60 -0
  301. package/skills/wix-vibe-headless/references/portfolio/{wix-portfolio.js → app/rest/wix-portfolio.js} +84 -55
  302. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +94 -0
  303. package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.js +236 -0
  304. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +240 -117
  305. package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +35 -0
  306. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +48 -0
  307. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +16 -0
  308. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +35 -0
  309. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +25 -0
  310. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +28 -0
  311. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +30 -0
  312. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +30 -0
  313. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +53 -0
  314. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +28 -0
  315. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +86 -0
  316. package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.js +251 -0
  317. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +248 -124
  318. package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +81 -0
  319. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +71 -0
  320. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +43 -0
  321. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +21 -0
  322. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +60 -0
  323. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +63 -0
  324. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +32 -0
  325. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +73 -0
  326. package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +28 -0
  327. package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +102 -0
  328. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +180 -0
  329. package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.js +452 -0
  330. package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +56 -0
  331. package/skills/wix-vibe-headless/references/shared/{wix-client.js → app/rest/wix-client.js} +6 -8
  332. package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +6 -0
  333. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +263 -148
  334. package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +20 -0
  335. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +150 -0
  336. package/skills/wix-vibe-headless/references/storefront/app/components/ProductCard.jsx +167 -0
  337. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGallery.jsx +51 -0
  338. package/skills/wix-vibe-headless/references/storefront/app/components/ProductGrid.jsx +54 -0
  339. package/skills/wix-vibe-headless/references/storefront/app/components/VariantPicker.jsx +119 -0
  340. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +71 -0
  341. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +109 -0
  342. package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +98 -0
  343. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +27 -0
  344. package/skills/wix-vibe-headless/references/storefront/app/pages/ProductDetail.jsx +139 -0
  345. package/skills/wix-vibe-headless/references/storefront/app/pages/Shop.jsx +75 -0
  346. package/skills/wix-vibe-headless/references/storefront/{wix-store-cart.js → app/rest/wix-store-cart.js} +1 -1
  347. package/skills/wix-vibe-headless/references/storefront/{wix-store-catalog.js → app/rest/wix-store-catalog.js} +25 -2
  348. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +111 -0
  349. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.js +299 -0
  350. /package/skills/wix-vibe-headless/references/blog/{wix-blog.js → app/rest/wix-blog.js} +0 -0
  351. /package/skills/wix-vibe-headless/references/events/{wix-events-registration.js → app/rest/wix-events-registration.js} +0 -0
  352. /package/skills/wix-vibe-headless/references/pricing-plans/{wix-pricing-plans.js → app/rest/wix-pricing-plans.js} +0 -0
  353. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-menu.js → app/rest/wix-restaurants-menu.js} +0 -0
  354. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-ordering.js → app/rest/wix-restaurants-ordering.js} +0 -0
  355. /package/skills/wix-vibe-headless/references/restaurants/{wix-restaurants-reservations.js → app/rest/wix-restaurants-reservations.js} +0 -0
@@ -0,0 +1,136 @@
1
+ 'use strict';
2
+
3
+ // rp-source-csv — reader shape -> CANONICAL record.
4
+ //
5
+ // This closes the seam between the two deterministic halves:
6
+ //
7
+ // csv rows --[reader]--> reader-shaped record --[HERE]--> canonical record --[wix-build]--> Wix
8
+ //
9
+ // A reader names fields the way its vendor thinks (`bodyHtml`, `vendor`, `weightKg`); `wix-build.js`
10
+ // consumes the vendor-neutral vocabulary from `wix-target-spec.js` (`description`, `brand`,
11
+ // `weight`). Without this module that rename is hand-written per project — which is exactly the
12
+ // improvisation the deterministic pipeline exists to remove.
13
+ //
14
+ // The maps are DATA, per vendor, so adding a vendor is a data edit plus a fixture.
15
+ //
16
+ // Longer term the readers should emit canonical records directly and this module becomes a no-op
17
+ // identity map. It is deliberately a separate step rather than being folded into the reader, so the
18
+ // change can happen per vendor without a flag day.
19
+
20
+ const { validateCanonicalPath } = require('../../rp-target-wix/lib/wix-target-spec.js');
21
+
22
+ // `rename` moves a value unchanged. `derive` computes one from the whole record — kept to genuine
23
+ // multi-field logic, because a derive that only reads one field should be a rename.
24
+ const READER_FIELD_MAPS = {
25
+ shopify: {
26
+ product: {
27
+ rename: {
28
+ title: 'name',
29
+ bodyHtml: 'description',
30
+ slug: 'slug',
31
+ vendor: 'brand',
32
+ seoTitle: 'seoTitle',
33
+ seoDescription: 'seoDescription',
34
+ images: 'images',
35
+ optionNames: 'optionNames',
36
+ categoryPath: 'categoryPath',
37
+ tags: 'tags',
38
+ sourceId: 'sourceId',
39
+ },
40
+ derive: {
41
+ // Shopify carries BOTH a lifecycle status and a publish flag; a product is visible only
42
+ // when both agree. Collapsing to either one alone silently publishes drafts.
43
+ visible: (record) => record.status === 'active' && record.published !== false,
44
+ },
45
+ },
46
+ variant: {
47
+ rename: {
48
+ sku: 'sku',
49
+ price: 'price',
50
+ compareAtPrice: 'compareAtPrice',
51
+ // The reader has already converted grams to the site's weight unit; the canonical field
52
+ // carries a bare number, so the converted value is the one that travels.
53
+ weightKg: 'weight',
54
+ barcode: 'barcode',
55
+ cost: 'cost',
56
+ choices: 'choices',
57
+ },
58
+ derive: {
59
+ visible: () => true,
60
+ },
61
+ },
62
+ category: {
63
+ rename: { name: 'name', parentPath: 'parentPath', path: 'path', sourceId: 'sourceId' },
64
+ derive: { visible: () => true },
65
+ },
66
+ },
67
+ };
68
+
69
+ // woocommerce / magento / bigcommerce readers are not built yet. Registering them explicitly as
70
+ // absent is better than falling back to shopify's map and silently mis-renaming fields.
71
+ const SUPPORTED_VENDORS = Object.keys(READER_FIELD_MAPS);
72
+
73
+ function mapEntity(record, entityMap) {
74
+ const out = {};
75
+ for (const [readerKey, canonicalKey] of Object.entries(entityMap.rename || {})) {
76
+ const value = record[readerKey];
77
+ if (value !== undefined && value !== null) out[canonicalKey] = value;
78
+ }
79
+ for (const [canonicalKey, fn] of Object.entries(entityMap.derive || {})) {
80
+ out[canonicalKey] = fn(record);
81
+ }
82
+ return out;
83
+ }
84
+
85
+ function mapFor(vendor, entity) {
86
+ const vendorMap = READER_FIELD_MAPS[vendor];
87
+ if (!vendorMap) {
88
+ throw new Error(
89
+ `canonical-record: no reader field map for vendor "${vendor}". ` +
90
+ `Known: ${SUPPORTED_VENDORS.join(', ')}. Add one in READER_FIELD_MAPS rather than reusing another vendor's.`,
91
+ );
92
+ }
93
+ const entityMap = vendorMap[entity];
94
+ if (!entityMap) throw new Error(`canonical-record: vendor "${vendor}" has no map for entity "${entity}"`);
95
+ return entityMap;
96
+ }
97
+
98
+ function toCanonicalProduct(record, { vendor = 'shopify' } = {}) {
99
+ const product = mapEntity(record, mapFor(vendor, 'product'));
100
+ const variantMap = mapFor(vendor, 'variant');
101
+ product.variants = (record.variants || []).map((variant) => mapEntity(variant, variantMap));
102
+ return product;
103
+ }
104
+
105
+ function toCanonicalCategory(record, { vendor = 'shopify' } = {}) {
106
+ return mapEntity(record, mapFor(vendor, 'category'));
107
+ }
108
+
109
+ // Self-check: every canonical key a map produces must be a real canonical field. Runs at require
110
+ // time so a typo in the map is a load error, not a field that silently never lands in Wix.
111
+ function validateMaps() {
112
+ const problems = [];
113
+ for (const [vendor, entities] of Object.entries(READER_FIELD_MAPS)) {
114
+ for (const [entity, entityMap] of Object.entries(entities)) {
115
+ const keys = [...Object.values(entityMap.rename || {}), ...Object.keys(entityMap.derive || {})];
116
+ for (const key of keys) {
117
+ // Canonical paths are `<entity>.<field>`; the maps hold the bare field name.
118
+ if (!validateCanonicalPath(`${entity}.${key}`)) problems.push(`${vendor}.${entity} -> ${entity}.${key}`);
119
+ }
120
+ }
121
+ }
122
+ return problems;
123
+ }
124
+
125
+ const MAP_PROBLEMS = validateMaps();
126
+ if (MAP_PROBLEMS.length) {
127
+ throw new Error(`canonical-record: map targets are not canonical fields: ${MAP_PROBLEMS.join(', ')}`);
128
+ }
129
+
130
+ module.exports = {
131
+ READER_FIELD_MAPS,
132
+ SUPPORTED_VENDORS,
133
+ toCanonicalProduct,
134
+ toCanonicalCategory,
135
+ validateMaps,
136
+ };
@@ -0,0 +1,310 @@
1
+ 'use strict';
2
+
3
+ // Vendor detection from the header row.
4
+ //
5
+ // The header read at discovery time is authoritative; a vendor profile only
6
+ // (a) identifies the vendor and (b) pre-fills mappings the LLM would otherwise
7
+ // propose. A stale profile can therefore make the pre-fill less complete, but
8
+ // can never cause a wrong import — see SKILL.md → Profile drift & resilience.
9
+
10
+ const fs = require('node:fs');
11
+ const path = require('node:path');
12
+ const { normalizeHeaderName } = require('./csv-parse.js');
13
+
14
+ const VENDORS_DIR = path.join(__dirname, '..', 'vendors');
15
+
16
+ // Scoring constants. Deliberately conservative: falling back to `custom` costs
17
+ // the user a less complete mapping pre-fill, while a wrong vendor match costs
18
+ // them a wrong layout.
19
+ const BASE_REQUIRED = 0.5;
20
+ const STRONG_WEIGHT = 0.5;
21
+ const PARTIAL_FACTOR = 0.6;
22
+ const NEGATIVE_PENALTY = 0.35;
23
+ const MATCH_THRESHOLD = 0.7;
24
+ const MARGIN = 0.15;
25
+ const MIN_STRONG_HITS = 2;
26
+ const NEAR_MISS_FLOOR = 0.25;
27
+ const NEAR_MISS_STRONG_RATIO = 0.6;
28
+
29
+ const CUSTOM_VENDOR = 'custom';
30
+
31
+ function normalizedSet(columns) {
32
+ const set = new Set();
33
+ for (const column of columns || []) {
34
+ const normalized = normalizeHeaderName(column);
35
+ if (normalized) {
36
+ set.add(normalized);
37
+ }
38
+ }
39
+ return set;
40
+ }
41
+
42
+ function validateProfile(profile) {
43
+ const errors = [];
44
+ if (!profile || typeof profile !== 'object') {
45
+ return { ok: false, errors: ['profile is not an object'] };
46
+ }
47
+ if (!profile.vendor || typeof profile.vendor !== 'string') {
48
+ errors.push('vendor must be a non-empty string');
49
+ }
50
+ if (!profile.profileVersion) {
51
+ errors.push('profileVersion is required (provenance for drift)');
52
+ }
53
+ if (!profile.sourceOfTruth) {
54
+ errors.push('sourceOfTruth is required');
55
+ }
56
+ const anchors = profile.anchors || {};
57
+ if (!Array.isArray(anchors.required) || anchors.required.length === 0) {
58
+ errors.push('anchors.required must be a non-empty array');
59
+ }
60
+ if (!Array.isArray(anchors.strong) || anchors.strong.length < MIN_STRONG_HITS) {
61
+ errors.push(`anchors.strong must hold at least ${MIN_STRONG_HITS} columns`);
62
+ }
63
+ if (!profile.layout || typeof profile.layout.pattern !== 'string') {
64
+ errors.push('layout.pattern is required');
65
+ }
66
+ if (profile.columnMap && !Array.isArray(profile.columnMap)) {
67
+ errors.push('columnMap must be an array when present');
68
+ }
69
+ for (const entry of profile.columnMap || []) {
70
+ if (!entry.wixTarget || !Array.isArray(entry.aliases) || entry.aliases.length === 0) {
71
+ errors.push(`columnMap entry ${JSON.stringify(entry.wixTarget)} needs a wixTarget and a non-empty aliases array`);
72
+ }
73
+ }
74
+ for (const derived of profile.derived || []) {
75
+ if (!derived.entity || !derived.fromColumn) {
76
+ errors.push('each derived entry needs entity + fromColumn');
77
+ }
78
+ }
79
+ return { ok: errors.length === 0, errors };
80
+ }
81
+
82
+ function loadVendorProfiles(dir = VENDORS_DIR) {
83
+ const files = fs.readdirSync(dir)
84
+ .filter((file) => file.endsWith('.json'))
85
+ .sort();
86
+ return files.map((file) => {
87
+ const profile = JSON.parse(fs.readFileSync(path.join(dir, file), 'utf8'));
88
+ const validation = validateProfile(profile);
89
+ if (!validation.ok) {
90
+ throw new Error(`Invalid vendor profile ${file}: ${validation.errors.join('; ')}`);
91
+ }
92
+ return profile;
93
+ });
94
+ }
95
+
96
+ function aliasIndex(profile) {
97
+ // normalized column name -> wixTarget, built from columnMap only.
98
+ const index = new Map();
99
+ for (const entry of profile.columnMap || []) {
100
+ for (const alias of entry.aliases) {
101
+ const normalized = normalizeHeaderName(alias);
102
+ if (normalized && !index.has(normalized)) {
103
+ index.set(normalized, { wixTarget: entry.wixTarget, alias });
104
+ }
105
+ }
106
+ }
107
+ return index;
108
+ }
109
+
110
+ // Anchors match by normalized EXACT equality and never through columnMap
111
+ // aliases. Aliases exist to be permissive for mapping; permissiveness is poison
112
+ // for identification — Shopify's variant.sku aliases include a bare "SKU",
113
+ // which every WooCommerce and Magento export also has.
114
+ function scoreProfile(headerColumns, profile) {
115
+ const header = normalizedSet(headerColumns);
116
+ const anchors = profile.anchors || {};
117
+ const required = anchors.required || [];
118
+ const strong = anchors.strong || [];
119
+ const negative = anchors.negative || [];
120
+
121
+ const matchedRequired = required.filter((column) => header.has(normalizeHeaderName(column)));
122
+ const missingRequired = required.filter((column) => !header.has(normalizeHeaderName(column)));
123
+ const matchedStrong = strong.filter((column) => header.has(normalizeHeaderName(column)));
124
+ const missingStrong = strong.filter((column) => !header.has(normalizeHeaderName(column)));
125
+ const negativeHits = negative.filter((column) => header.has(normalizeHeaderName(column)));
126
+
127
+ const requiredRatio = required.length === 0 ? 0 : matchedRequired.length / required.length;
128
+ const strongRatio = strong.length === 0 ? 0 : matchedStrong.length / strong.length;
129
+
130
+ const core = BASE_REQUIRED + STRONG_WEIGHT * strongRatio;
131
+ let score = requiredRatio === 1 ? core : PARTIAL_FACTOR * requiredRatio * core;
132
+ if (negativeHits.length > 0) {
133
+ score *= NEGATIVE_PENALTY;
134
+ }
135
+
136
+ // Evidence only — deliberately NOT part of the score. Coupling identification
137
+ // to columnMap completeness would mean adding a mapping alias could change
138
+ // which vendor a file is detected as.
139
+ const aliases = aliasIndex(profile);
140
+ const anchorNames = normalizedSet([...required, ...strong]);
141
+ const knownColumns = (headerColumns || []).filter((column) => {
142
+ const normalized = normalizeHeaderName(column);
143
+ return anchorNames.has(normalized) || aliases.has(normalized);
144
+ });
145
+ const vocabularyCoverage = headerColumns && headerColumns.length > 0
146
+ ? knownColumns.length / headerColumns.length
147
+ : 0;
148
+
149
+ return {
150
+ vendor: profile.vendor,
151
+ score: Number(score.toFixed(4)),
152
+ requiredRatio,
153
+ strongRatio,
154
+ matchedRequired,
155
+ missingRequired,
156
+ matchedStrong,
157
+ missingStrong,
158
+ negativeHits,
159
+ vocabularyCoverage: Number(vocabularyCoverage.toFixed(4)),
160
+ };
161
+ }
162
+
163
+ function evidenceLine(winner, runnerUp) {
164
+ const parts = [
165
+ `required ${winner.matchedRequired.length}/${winner.matchedRequired.length + winner.missingRequired.length}`,
166
+ `strong ${winner.matchedStrong.length}/${winner.matchedStrong.length + winner.missingStrong.length}`,
167
+ `score ${winner.score}`,
168
+ ];
169
+ if (winner.negativeHits.length > 0) {
170
+ parts.push(`negative anchors present: ${winner.negativeHits.join(', ')}`);
171
+ }
172
+ parts.push(runnerUp ? `runner-up ${runnerUp.vendor} ${runnerUp.score}` : 'no runner-up');
173
+ return parts.join('; ');
174
+ }
175
+
176
+ function detectVendor(headerColumns, profiles, { statedVendor = null } = {}) {
177
+ const scores = profiles
178
+ .map((profile) => scoreProfile(headerColumns, profile))
179
+ .sort((a, b) => b.score - a.score || a.vendor.localeCompare(b.vendor));
180
+
181
+ const winner = scores[0] || null;
182
+ const runnerUp = scores[1] || null;
183
+ const profileByVendor = new Map(profiles.map((profile) => [profile.vendor, profile]));
184
+
185
+ let reason = 'match';
186
+ let matched = Boolean(winner);
187
+ if (!winner || winner.score < MATCH_THRESHOLD) {
188
+ matched = false;
189
+ reason = 'below-threshold';
190
+ } else if (winner.matchedStrong.length < MIN_STRONG_HITS) {
191
+ matched = false;
192
+ reason = 'insufficient-strong-anchors';
193
+ } else if (runnerUp && winner.score - runnerUp.score < MARGIN) {
194
+ matched = false;
195
+ reason = 'ambiguous';
196
+ }
197
+
198
+ // A drifted vendor export should become a user question, not silence.
199
+ let nearMiss = null;
200
+ if (!matched) {
201
+ const candidate = scores.find((entry) => entry.score >= NEAR_MISS_FLOOR
202
+ && entry.strongRatio >= NEAR_MISS_STRONG_RATIO
203
+ && entry.requiredRatio > 0
204
+ && entry.negativeHits.length === 0);
205
+ if (candidate) {
206
+ nearMiss = {
207
+ vendor: candidate.vendor,
208
+ score: candidate.score,
209
+ missingRequired: candidate.missingRequired,
210
+ missingStrong: candidate.missingStrong,
211
+ };
212
+ }
213
+ }
214
+
215
+ const detectedVendor = matched ? winner.vendor : CUSTOM_VENDOR;
216
+
217
+ // A user-stated vendor wins, but detection still runs so a disagreement is
218
+ // visible rather than silently overridden.
219
+ if (statedVendor) {
220
+ const stated = String(statedVendor).toLowerCase();
221
+ if (stated !== CUSTOM_VENDOR && !profileByVendor.has(stated)) {
222
+ throw new Error(`Unknown vendor "${statedVendor}". Known vendors: ${[...profileByVendor.keys()].join(', ')}, ${CUSTOM_VENDOR}.`);
223
+ }
224
+ const statedScore = scores.find((entry) => entry.vendor === stated) || null;
225
+ return {
226
+ vendor: stated,
227
+ profile: profileByVendor.get(stated) || null,
228
+ confidence: statedScore ? statedScore.score : 1,
229
+ source: 'user',
230
+ reason: 'user-stated',
231
+ evidence: `vendor stated by the user${statedScore ? `; fingerprint would score it ${statedScore.score}` : ''}`,
232
+ scores,
233
+ runnerUp,
234
+ nearMiss,
235
+ conflict: detectedVendor !== stated ? { stated, detected: detectedVendor } : null,
236
+ };
237
+ }
238
+
239
+ return {
240
+ vendor: detectedVendor,
241
+ profile: matched ? profileByVendor.get(winner.vendor) : null,
242
+ confidence: winner ? winner.score : 0,
243
+ source: matched ? 'fingerprint' : 'fallback',
244
+ reason,
245
+ evidence: winner ? evidenceLine(winner, runnerUp) : 'no vendor profiles available',
246
+ scores,
247
+ runnerUp,
248
+ nearMiss,
249
+ conflict: null,
250
+ };
251
+ }
252
+
253
+ // The two drift lists are scoped differently on purpose: `unmappedColumns` is
254
+ // about mapping coverage (anchors + columnMap), `missingExpectedColumns` is
255
+ // about format drift (anchors only — including every columnMap alias would
256
+ // make the list enormous and useless).
257
+ function diffProfile(headerColumns, profile) {
258
+ if (!profile) {
259
+ return { unmappedColumns: [...(headerColumns || [])], missingExpectedColumns: [] };
260
+ }
261
+ const aliases = aliasIndex(profile);
262
+ const anchors = profile.anchors || {};
263
+ const anchorNames = normalizedSet([...(anchors.required || []), ...(anchors.strong || [])]);
264
+ const header = normalizedSet(headerColumns);
265
+
266
+ const unmappedColumns = (headerColumns || []).filter((column) => {
267
+ const normalized = normalizeHeaderName(column);
268
+ return normalized && !anchorNames.has(normalized) && !aliases.has(normalized);
269
+ });
270
+ const missingExpectedColumns = [...(anchors.required || []), ...(anchors.strong || [])]
271
+ .filter((column) => !header.has(normalizeHeaderName(column)));
272
+
273
+ return { unmappedColumns, missingExpectedColumns };
274
+ }
275
+
276
+ // Advisory pre-fill for rp-mapper. Every column this does not cover still flows
277
+ // through discovery → mapper → user unchanged.
278
+ function prefillColumnMap(headerColumns, profile) {
279
+ if (!profile) {
280
+ return [];
281
+ }
282
+ const aliases = aliasIndex(profile);
283
+ const hints = [];
284
+ for (const column of headerColumns || []) {
285
+ const hit = aliases.get(normalizeHeaderName(column));
286
+ if (hit) {
287
+ hints.push({ column, wixTarget: hit.wixTarget, matchedAlias: hit.alias });
288
+ }
289
+ }
290
+ return hints;
291
+ }
292
+
293
+ module.exports = {
294
+ VENDORS_DIR,
295
+ BASE_REQUIRED,
296
+ STRONG_WEIGHT,
297
+ PARTIAL_FACTOR,
298
+ NEGATIVE_PENALTY,
299
+ MATCH_THRESHOLD,
300
+ MARGIN,
301
+ MIN_STRONG_HITS,
302
+ NEAR_MISS_FLOOR,
303
+ CUSTOM_VENDOR,
304
+ loadVendorProfiles,
305
+ validateProfile,
306
+ scoreProfile,
307
+ detectVendor,
308
+ diffProfile,
309
+ prefillColumnMap,
310
+ };