@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,1114 @@
1
+ ---
2
+ name: rp-import-codegen
3
+ description: >-
4
+ Generates migration readers, transforms, setup plans, and thin Wix write specs from schema and mapping
5
+ artifacts. Use when producing runnable extract/import code under the migration project.
6
+ ---
7
+
8
+ # rp-import-codegen
9
+
10
+ Generate source readers, transforms, setup/import entrypoints, and thin Wix write specs from approved migration artifacts.
11
+
12
+ ## Purpose
13
+
14
+ This skill turns the schema, mapping, and setup decisions into implementation files under the active migration project.
15
+
16
+ ## Required inputs
17
+
18
+ - `migrations/<project>/source-schema.json`
19
+ - `migrations/<project>/mapping/mapping-plan.json`
20
+ - `migrations/<project>/setup/setup-plan.json`
21
+ - `migrations/<project>/setup/setup-requirements.json` when setup affects write paths
22
+
23
+ Prefer the machine-readable artifacts above. Markdown review files are secondary renderings
24
+ for humans, not the primary codegen contract.
25
+
26
+ ## Source read contract
27
+
28
+ Generating a correct reader requires platform-specific knowledge — auth model,
29
+ pagination, rate limits, and REST quirks. That knowledge lives in the matching **source
30
+ adapter** skill, not here, so this skill never names a platform. Resolve the adapter from
31
+ the `platform` field in `source-schema.json` via the naming convention `rp-source-<platform>`
32
+ (e.g. `platform: "wordpress"` → `rp-source-wordpress`) and read its "Read contract"
33
+ section. The operational facts should already be recorded in `source-profile.md`; use the
34
+ adapter to fill any gaps rather than guessing. `rp-execute-import` runs the reader you
35
+ generate and stays platform-agnostic — so the platform specifics must be baked into this
36
+ generated code, not deferred to execution.
37
+
38
+ Adding a new source platform therefore requires no change to this skill: a new
39
+ `rp-source-<platform>` adapter is enough.
40
+
41
+ ### CSV sources (`platform: "csv"`)
42
+
43
+ When `source-schema.json.platform === "csv"`, generate a **file reader** instead of an HTTP
44
+ reader and read `rp-source-csv` → "Read contract". The differences that matter:
45
+
46
+ - **Vendor `lib/csv-parse.js` into `src/lib/`** and import it, exactly as a WordPress reader
47
+ vendors `wp-http.js`. Do not re-emit parsing: the sampler and the reader must agree on what
48
+ the file contains. There is no auth, no pagination, and no rate limiting to generate.
49
+ - **Grouping is the reader's core job.** Replay `sourceMeta.sourceFiles[].layout`: with
50
+ `continuation: "blank-key"` a blank key extends the current group; with a `sectioned`
51
+ pattern the discriminator column routes parent vs child rows and `parentRefColumn` resolves
52
+ a child to its parent (it may hold `id:123` or a SKU, and the child is not guaranteed to
53
+ follow its parent).
54
+ - **Iterate the file set** by role, treating `sourceFiles[].partOf` entries as continuations
55
+ of the same logical stream and honoring each part's own column order.
56
+ - **Materialize `column-values` entities**: collect the distinct values of the source column
57
+ and their ancestors into their own entity file, emitted depth-ascending so a parent
58
+ category exists before its child, plus the linking relation. Do not invent Wix ids at
59
+ extract time — the `ImportCrosswalk` resolves them at import time.
60
+ - **Apply `sourceMeta.dialect.emptyPolicy`** through the shared `coerceEmpty` helper so a
61
+ required Wix field is never fed an empty string the source did not have.
62
+ - CSV values are plain text; write them as-is with no entity-decoding step.
63
+
64
+ ## Target write contract
65
+
66
+ Symmetrically, do **not** re-derive the Wix write surface here. It is identical for
67
+ every migration and is pre-verified in the **`rp-target-wix`** internal resource (see
68
+ `CONVENTIONS.md`), which ships shared Wix runtime code: verified request builders,
69
+ executors, and reusable execution logic for retries, throttling, checkpoints, and
70
+ reporting. **Vendor copies of the shared runtime modules from `rp-target-wix` into the
71
+ project** (like the source transport) and generate thin project-specific write specs and
72
+ transforms that **call those shared primitives/runtime functions**. Never hand-emit Wix
73
+ endpoints/bodies inline —
74
+ that path repeatedly shipped wrong shapes (lowercase Ricos plugin enums, `{tag:{…}}`
75
+ tag bodies, `media.wixMedia.image.id` featured images) that only failed at execution.
76
+
77
+ **Validate by real call, not by doc example.** MCP doc checks confirm an endpoint
78
+ *exists*; they do not confirm the request *shape works* — public examples have been
79
+ wrong (e.g. Ricos plugin enums shown lowercase that 400). Trust a Wix request shape only once a real call (or
80
+ `tests/target-wix/contract-test.js` in live mode, run from the repo root) has succeeded. Treat the
81
+ adapter's `// VERIFIED:` shapes as the source of truth over any docs example.
82
+
83
+ Adding a new source platform requires no change here, and the Wix surface change for
84
+ *all* migrations is a one-place edit in `rp-target-wix` (caught by its contract test),
85
+ not a per-project regeneration.
86
+
87
+ ## Workflow
88
+
89
+ 1. Read the discovery, mapping, and setup artifacts, plus the source adapter's read
90
+ contract and the `rp-target-wix` write contract.
91
+ If a mapping entity includes `targetRef`, validate its selected writer and reliability
92
+ against `rp-target-wix/scripts/domain-knowledge.js summarize-entities`; do not remap
93
+ source entities independently.
94
+ 2. Generate machine-readable execution artifacts:
95
+ - `execution/execution-manifest.json`
96
+ - `execution/llm-handoff.json`
97
+ - when `SAFE_MODE=true` or `DRY_RUN=true`, `execution/review/code-safety-review.md`
98
+ - optional supporting execution subplans only when the runtime truly needs them
99
+ 3. Generate setup code that can verify/provision Wix prerequisites by executing the
100
+ machine setup artifacts through the shared setup runtime.
101
+ 4. Generate source reader code that can enumerate and fetch source entities. If the adapter
102
+ ships a shared transport module (auth, pagination, throttling, retries), vendor a copy of
103
+ it into the project (e.g. `migrations/<project>/src/lib/`) and import from it instead of
104
+ re-emitting that plumbing — the reader should hold only per-project orchestration.
105
+ The reader must extract source records to durable files on disk; it must not require the
106
+ whole source dataset to live in memory before import begins.
107
+ 5. Generate transform code that maps source records into Wix-shaped objects — thin glue over
108
+ `wix-build.js`, which already owns slug sanitizing and the money/price/variant rules; see
109
+ "Never hand-write slug sanitizing" below.
110
+ **Wix Stores products: Catalog V3 only. Catalog V1 is not supported by this workflow —
111
+ there is nothing to generate for it.** The only destination a migration ever writes to is
112
+ a `V3_CATALOG` site (guaranteed at provisioning and gated before any write — see
113
+ `replatform` → "Headless site creation" and `rp-execute-setup`), so generated code may
114
+ assume V3 unconditionally: no version detection, no branch, no V1 shape, no V1 fallback
115
+ for a failing V3 write. A V1 site is a **blocker the run halts on**, never a case codegen
116
+ handles. Concretely: never emit Catalog V1-style top-level `price`, `sku`, or variant
117
+ inventory fields. For simple products, emit one variant under
118
+ `variantsInfo.variants[]` with variant-level `price`, `sku`, and physical properties.
119
+ When the source product is subscription-based and the source payload exposes explicit
120
+ recurring cadence in structured product data, emit native
121
+ `product.subscriptionDetails` with at least `allowOneTimePurchases` and one
122
+ `subscriptions[]` entry carrying `title`, `description`, `frequency`, `interval`, and
123
+ `autoRenewal`. Do not emit placeholder-only metadata or skip those products on create
124
+ when that cadence can be inferred deterministically; live create coverage for this
125
+ shape was verified on July 26, 2026.
126
+ Product HTML descriptions land in `plainDescription`, which Wix converts to rich content
127
+ server-side — it is HTML, not a plain-text flattening, so there is no fidelity loss to
128
+ accept. Do NOT call the Ricos conversion endpoint on the product path: it costs one HTTP
129
+ round-trip per product ahead of a bulk create, and that burst is what the endpoint throttles
130
+ with a 403. Two traps: `plainDescription` is silently ignored when `description` is also set
131
+ (set exactly one), and it is capped at 16,000 characters — longer bodies need truncation or
132
+ an info section, recorded in `mapping-gaps.json`. Ricos conversion remains correct for blog
133
+ posts, where `richContent` really is a Ricos document.
134
+ Media scope should be relationship-driven by default: generate imports only for media
135
+ referenced by mapped entities, not for the entire unattached source library. When the
136
+ target adapter says an entity can ingest external URLs directly (for example Wix Stores
137
+ product media), generate that entity-native path instead of routing those files through
138
+ the slower generic Media Manager import flow.
139
+ 6. Generate thin project-specific write specs and import orchestration code that pass
140
+ those Wix-shaped objects into the shared `rp-target-wix` runtime. Generated code should
141
+ describe *what* to write and in what order, not *how* to implement retries, throttling,
142
+ checkpointing, or audit logging.
143
+ Prefer the selected entity's `preferredWrite`; if it is not `verified-live`, surface an
144
+ execution warning before consent. Native mappings must have a known `writerId`, a
145
+ direct REST plan that calls `notifyMissingWriter`, or an explicit unsupported/gap
146
+ fallback.
147
+ 7. Generate or wire the deterministic execution-state preparation step before any import
148
+ write. The generated runner should call the shared `execution-state` preparation
149
+ contract, or the execution instructions should run
150
+ `skills/replatform/scripts/execution-state-prepare.js` before the generated import
151
+ entrypoint.
152
+ 8. Generate the runnable setup/extraction/import entrypoints (see below) — the artifacts
153
+ `rp-execute-setup` and `rp-execute-import` actually run. This is required, not optional.
154
+ Then run the **sample-preview gate** (see below) before the execution-plan approval.
155
+ 9. Generate `execution/review/import-plan.md` plus
156
+ `execution/review/import-plan.freshness.json` using
157
+ `skills/replatform/scripts/artifact-freshness.js write ...`. The freshness metadata
158
+ must include hashes for `source-schema.json`, `mapping/mapping-plan.json`,
159
+ `setup/setup-verification.json`, generated import code, and the target contract ledger
160
+ revision. If codegen follows a newly promoted write contract, regenerated code and this
161
+ metadata must reflect that promotion.
162
+ 10. Document any manual code follow-up still required.
163
+ 11. Generate any post-import remediation helpers that are required to reach the accepted
164
+ mapping fidelity when the source capture cannot express the relationship inline during
165
+ the first create pass.
166
+
167
+ ## Post-codegen code-safety review checkpoint
168
+
169
+ When either `SAFE_MODE=true` or `DRY_RUN=true` for the active project, codegen must
170
+ produce a mandatory review artifact before the execution approval gate:
171
+
172
+ - `migrations/<project>/execution/review/code-safety-review.md`
173
+
174
+ This review is performed by the agent, not delegated to the user. It verifies the
175
+ generated code itself. It must check:
176
+
177
+ - every generated write path that can carry email/phone data passes `safeModeOptions`
178
+ into the shared Wix runtime or direct REST wrapper
179
+ - every shared/native writer reached by generated code actually consumes those
180
+ `safeModeOptions` and routes the request body through the shared sanitizer rather than
181
+ silently ignoring the parameter
182
+ - no generated writer path silently bypasses safe mode because of a missing function
183
+ parameter or a direct call that skips the shared sanitizer
184
+ - dry-run uses the same generated write code path as live import, with Wix calls skipped
185
+ only at the shared `wix.send` boundary
186
+ - dry-run reporting does not label would-send placeholders as live-created/imported site
187
+ objects
188
+ - mapping-declared `safeModeReplacements[]` are reflected in the generated write specs and
189
+ runner wiring, and any entity that still carries outbound contact data without matching
190
+ replacement-path coverage is treated as a review failure rather than left for the user
191
+ to reason about manually
192
+
193
+ If the review finds a gap, execution approval must remain pending until the generated
194
+ code is corrected and the review artifact is regenerated with a passing verdict. The
195
+ user's role at this checkpoint is final go/no-go approval after the agent has already
196
+ completed the review and surfaced the findings.
197
+
198
+ ## Codegen boundary
199
+
200
+ This skill owns the **project-specific layer** only.
201
+
202
+ It should generate:
203
+
204
+ - setup plan renderings and setup runner wiring
205
+ - source readers
206
+ - transforms
207
+ - per-entity write specs
208
+ - import ordering and dependency wiring
209
+ - project-local config loading
210
+ - execution review artifacts
211
+ - post-codegen code-safety review artifacts when safe mode or dry-run is enabled
212
+
213
+ It must not regenerate for each migration:
214
+
215
+ - raw Wix auth/client plumbing
216
+ - generic retry loops
217
+ - throttling behavior
218
+ - audit log shape
219
+ - compact execution report shape
220
+ - checkpoint store mechanics
221
+ - generic bulk-write orchestration
222
+
223
+ Those behaviors belong in `rp-target-wix`.
224
+
225
+ ## Final handoff expectations
226
+
227
+ The generated plan and downstream execution path must make the final state legible to the
228
+ user. Treat these as required handoff details, not optional niceties:
229
+
230
+ - Surface the **dashboard URL** for the destination site.
231
+ - Surface the **editor URL** only when editor work was actually performed or the next
232
+ required step is explicitly in the editor.
233
+ - Surface the **preview URL** only when public route/site verification is relevant to the
234
+ completed work.
235
+ - Distinguish clearly between:
236
+ - **catalog/data imported**
237
+ - **website/homepage built**
238
+ - Do not imply that a successful Stores import means the site's homepage or full website
239
+ experience exists. A migration can finish with valid catalog/product/cart/checkout
240
+ routes while the homepage is still blank or unbuilt.
241
+ - If Shopify quick mode relies on public collection feeds such as
242
+ `/collections/{handle}/products.json` to recover category membership, bake that into the
243
+ generated extractor/importer or emit an explicit remediation helper and call it out in
244
+ `execution/review/import-plan.md`.
245
+
246
+ ## Runnable setup/extraction/import entrypoints — the artifacts are the execution path (required)
247
+
248
+ `rp-execute-setup` and `rp-execute-import` run the migration by **executing these
249
+ artifacts**, never by the agent hand-issuing Wix MCP calls. So codegen must emit real,
250
+ runnable entrypoints:
251
+
252
+ - **`src/setup/run-setup.js`** or equivalent setup entrypoint — reads the machine setup
253
+ artifacts and executes them through the shared setup runtime.
254
+ - **`src/extract/run-extract.js`** or equivalent reader entrypoint — reads the source APIs and
255
+ writes durable extracted files under the project. Extraction is a separate step from
256
+ destination writes, so large migrations can be resumed or re-imported without re-reading
257
+ the whole source.
258
+ - **`src/import/run-import.js`** or equivalent import entrypoint — reads the extracted files,
259
+ applies transforms, and writes to Wix in dependency order through the vendored shared
260
+ write runtime. It must:
261
+ - load project-local config files, then process env, for all expected env-style values
262
+ (never hardcoded; fail fast if absent — do not fall back to any agent/MCP auth),
263
+ - run the **notification-mute preflight** before the first entity write whenever mute
264
+ is in effect (see "Notification-mute preflight" below),
265
+ - consume extracted source files from disk rather than materializing the entire source in
266
+ memory,
267
+ - apply idempotent dedupe keyed by source ID, using either a client-controlled source-id
268
+ field on the target or the authoritative local
269
+ `state/crosswalk/crosswalk.ndjson` durable `sourceId -> targetId` crosswalk for native Wix
270
+ entities with server-assigned IDs, reading existing target state under the rules in
271
+ "Reading existing target state" below — an empty read is not an empty site,
272
+ - honor `DRY_RUN=true` and `--dry-run` for the safe-validation pass; `--dry-run` takes
273
+ precedence over config and enables the shared Wix runtime's dry-run mode.
274
+ - `--sample` may be supported as a narrower dry-run-style validation mode, but it must
275
+ not replace `--dry-run` as the primary safe-validation control.
276
+ - honor deterministic selective resume flags: `--entity <entity>`,
277
+ `--source-type <subtype>`, `--missing-only`, `--failed-only`, and `--deferred-only`.
278
+ `--missing-only`, `--failed-only`, and `--deferred-only` are mutually exclusive. These
279
+ flags must drive the same import path as a full run after selecting a stable record
280
+ set; do not generate one-off recovery drivers.
281
+ - emit a stable `runId` at process start and include it in every audit event, dry-run
282
+ request capture, placeholder crosswalk row, and summary artifact.
283
+ - emit `execution/live-import-summary.json` and `execution/completion-report.json`
284
+ through the shared completion-report runtime, with entity/subtype completeness counters
285
+ for extracted, in-scope, attempted, imported, already present by crosswalk, deferred,
286
+ failed, and skipped-out-of-scope records.
287
+ - stop before dependent phases when required upstream entities fail. For example, do not
288
+ create products after product-category failures unless the execution plan explicitly
289
+ marks category assignments as non-blocking.
290
+ - pass `safeModeOptions` to every relevant writer path, including direct REST fallback
291
+ paths and unverified native writers that can carry contact values.
292
+ - **The dry-run is the same import code path with Wix calls skipped at the shared Wix
293
+ boundary** — not a separate driver. Generated code must construct the same Wix client,
294
+ call the same writer helpers, run `SAFE_MODE` sanitization, and pass request metadata
295
+ (`phase`, `operation`, `entity`, `sourceId`, `verification`, and when needed
296
+ `responseShape`) into `wix.send` so the runtime can capture would-send requests and
297
+ return live-compatible dry-run placeholders.
298
+
299
+ Extraction format requirements:
300
+
301
+ - write extracted data to project-local files, not process memory
302
+ - chunk by entity and page/batch so a large source does not become one giant file
303
+ - write a manifest that lets the import step discover which entity files exist and in what
304
+ order to consume them
305
+ - make the extracted files deterministic enough for resume, replay, and debugging
306
+
307
+ ### Notification-mute preflight (spec 0012, required)
308
+
309
+ When mute is in effect — **always** for `WIX_SITE_STRATEGY=new` (unconditional,
310
+ regardless of `WIX_MUTE_NOTIFICATIONS`), and for existing sites only when
311
+ `WIX_MUTE_NOTIFICATIONS=on` — the generated import script must contain a mandatory
312
+ preflight step, **before the first entity write**, that asserts the site is muted:
313
+
314
+ - Primary: `getSiteMuteState(wix)` (rp-target-wix, VERIFIED 2026-08-04) returns
315
+ `muted: true`.
316
+ - Fallback (only if the status read is unavailable): an idempotent
317
+ `muteSiteNotifications(wix, { reason })` call — passing the **same
318
+ project-identifying reason as setup** (`RePlatform migration — <project>`), because a
319
+ re-mute overwrites the recorded reason (last caller wins).
320
+
321
+ If the preflight call fails or reads `muted: false` and the re-mute fails, the script
322
+ **aborts before any write** with a clear error routing back to setup — exit non-zero, no
323
+ degraded mode, no `--skip-mute-preflight`-style flag, no warning-and-continue. For
324
+ new-site projects the preflight is emitted unconditionally and never appears as a
325
+ skippable option; for existing-site projects with `WIX_MUTE_NOTIFICATIONS=off` (the
326
+ default), no preflight is emitted. The preflight logs its re-verification and outcome
327
+ into the run's execution/progress log (keyed by `runId`) — terminal reports read this
328
+ recorded state, never strategy/config inference. In dry-run mode the preflight follows
329
+ the shared dry-run contract like any other Wix call: the intent is captured and the
330
+ state read is skipped (`stateKnown: false`), not asserted as muted. The generated script
331
+ must never call `unmuteSiteNotifications` — unmute is an explicit owner request outside
332
+ the import path. A preflight mute-verification failure is recorded through the standard
333
+ `rp-telemetry` recorder as an `error` event (with `error_code`) like any other run
334
+ event — no new telemetry surface.
335
+
336
+ ### Use the target's BULK write path (required)
337
+
338
+ **A generated importer must write through the target's bulk endpoint whenever one exists.**
339
+ Per-record creates are acceptable only when the target has no bulk equivalent, or for a
340
+ deliberate single-record contract probe. This is not an optimization to add later: at 1000
341
+ products, per-record creates are 1000 round trips where bulk is ~11, and the latency
342
+ difference is the difference between a minute and half an hour.
343
+
344
+ Derive the batch shape from the endpoint's **own limits, all of them at once**. Bulk
345
+ endpoints routinely cap several dimensions simultaneously and exceeding **any one** rejects
346
+ the entire request — Wix bulk product create caps products (100), variants (1000), options
347
+ (100), modifiers (100) and infoSections (100) per request, so with 2 options per product the
348
+ options cap binds at 50 products, not 100. Batch with `ndjson.readBatchesByLimits` and the
349
+ limits/cost helpers the target adapter exports (`BULK_PRODUCT_LIMITS`,
350
+ `storesProductBulkCost`); never batch on record count alone.
351
+
352
+ Three properties of bulk responses that generated code must handle explicitly, because each
353
+ one silently corrupts a report if ignored:
354
+
355
+ - **Bulk is not atomic.** A `200` can contain per-item failures. Walk every
356
+ `results[]` entry; never infer success from the HTTP status.
357
+ - **Correlate by the response's own index field** (`itemMetadata.originalIndex` for Wix), not
358
+ by response position, and verify that every input is accounted for. A mis-correlated
359
+ result crosswalks the wrong target id onto a source record.
360
+ - **Count the "undetailed failures" bucket.** Servers drop failure detail past a threshold;
361
+ those are still failures and must appear in the completion report.
362
+
363
+ Dedupe **before** building the batch — a skipped record must never reach the API — and
364
+ record the crosswalk per successful item, not per batch, so an interrupted run resumes
365
+ correctly.
366
+
367
+ ### Record streams are NDJSON, single documents are JSON (required)
368
+
369
+ **Every file that holds a stream of records must be newline-delimited JSON (`.ndjson`), one
370
+ record per line — never a `{ "records": [ … ] }` array.** Vendor
371
+ `rp-target-wix/lib/ndjson.js` into the project (like `wix-writers.js`) and use it; do not
372
+ hand-roll line splitting, which gets chunk boundaries and CRLF wrong.
373
+
374
+ This applies to:
375
+
376
+ - `data/source-extract/<entity>.ndjson` — the extractor's output
377
+ - the `sourceId -> targetId` crosswalk
378
+ - audit logs (already NDJSON)
379
+
380
+ It exists because every downstream stage does the same three things with these files, and an
381
+ array is the wrong shape for all of them:
382
+
383
+ - **scan** — `countRecords` counts lines; nothing is parsed and nothing is held in memory. A
384
+ JSON array must be fully parsed to be counted.
385
+ - **batch** — a bulk endpoint's page is `readBatches(file, 100)`. Use `readBatchesBy` when the
386
+ target caps more than one dimension: Wix bulk product create allows **≤100 products AND
387
+ ≤1000 variants per request**, which is `{ maxCount: 100, maxCost: 1000, cost: p =>
388
+ p.variantsInfo.variants.length }`.
389
+ - **cursor / resume** — `readSlice(file, { offset, limit })` skips what is already done
390
+ without rebuilding it into objects.
391
+
392
+ Two more properties that matter in practice: a producer can append records as it finds them
393
+ instead of buffering the whole entity, and an interrupted write leaves a **valid readable
394
+ prefix** — a truncated JSON array is unparseable, so a crash mid-extract loses everything.
395
+
396
+ **Do not line-delimit single documents.** A manifest, `mapping-plan.json`,
397
+ `decisions.json`, `execution-manifest.json`, `preview-result.json` or
398
+ `completion-report.json` is one object; it stays `.json`. NDJSON buys nothing there and makes
399
+ it unreadable.
400
+
401
+ Generated importers must **stream** these files (`for await (const batch of
402
+ readBatches(...))`), not `readAllRecords` them. `readAllRecords` is an escape hatch for
403
+ genuinely small streams (a six-record category list) and is named to make its misuse on a
404
+ large stream obvious.
405
+
406
+ Projects generated before this rule can be moved forward with
407
+ `convertLegacyJsonFile(jsonPath, ndjsonPath)` rather than re-extracting.
408
+
409
+ ### Reading existing target state (required)
410
+
411
+ An idempotent importer has to know what is already on the site before it writes. Every bug in
412
+ this section is the same bug: **a read that returns nothing looks exactly like a site that
413
+ contains nothing**, and nothing-on-the-site is the branch that writes. None of them throw, so
414
+ none of them show up in a dry-run.
415
+
416
+ **The adapter's `query*` executors already return the array.** `queryStoresCategories`,
417
+ `queryStoresProducts`, `queryContacts`, `queryCoupons` and `queryOrders` unwrap the response
418
+ before returning it, so the value **is** `categories` / `products` / etc. Generated code must
419
+ use it directly:
420
+
421
+ ```js
422
+ const existing = await W.queryStoresCategories(wix); // an array
423
+ const existing = (await W.queryStoresCategories(wix)).categories; // WRONG → undefined → []
424
+ ```
425
+
426
+ The second form is what shipped, and reading `.categories` off an array yields `undefined`,
427
+ which the usual `|| []` turns into an empty array. It silently disabled a category dedupe
428
+ index, silently disabled a product name-match safety net, and made a setup verification
429
+ report **0 categories on a site that had 25** — all without one error line.
430
+
431
+ **Never cursor-page through those executors.** Unwrapping discards `pagingMetadata`, so the
432
+ cursor a loop needs is already gone; a loop built on them cannot advance past page one, and
433
+ reading `.pagingMetadata` off the returned array is the same `undefined` as above. Prefer the
434
+ adapter's sweep primitives, which own the loop and the failure semantics:
435
+
436
+ - `queryAllStoresCategories(wix)`, `queryAllStoresProducts(wix)`, `queryAllDataItems(...)`
437
+
438
+ When a sweep is needed for an entity that has no `queryAll*` primitive yet, generate the loop
439
+ against the **raw** response and add the primitive to `rp-target-wix` rather than leaving the
440
+ loop in project code:
441
+
442
+ ```js
443
+ let cursor = null;
444
+ do {
445
+ const body = cursor ? { cursorPaging: { limit: 100, cursor } } : { cursorPaging: { limit: 100 } };
446
+ const response = await wix.send(W.buildQueryStoresProductsRequest(body)); // raw, not the executor
447
+ for (const p of response.products || []) { /* index it */ }
448
+ cursor = (response.pagingMetadata && response.pagingMetadata.cursors && response.pagingMetadata.cursors.next) || null;
449
+ } while (cursor);
450
+ ```
451
+
452
+ **An incomplete sweep must throw, not fall through.** If any page fails, or the loop hits its
453
+ page ceiling with a cursor still outstanding, the generated code must abort the import with a
454
+ message naming the sweep. It must **not** continue with the partial index, and must not treat
455
+ "the sweep failed" as "nothing exists" — that is precisely the state in which a re-run
456
+ re-creates the entire catalog it already imported. The single most expensive failure in this
457
+ whole pipeline is a duplicate import, and it arrives through an empty net.
458
+
459
+ **A match must be ADOPTED into the crosswalk, not skipped.** When a safety net (name match,
460
+ slug match, source-id field) finds that the target entity already exists, record it in the
461
+ crosswalk with its **target id and revision** and count it as reused. A bare `continue` that
462
+ skips the write without recording the id looks correct — nothing is duplicated — but every
463
+ later phase that resolves ids *from the crosswalk* then silently drops the record. Concretely:
464
+ the product was already on the site, so it was skipped, so it had no crosswalk row, so the
465
+ category-link phase could not resolve its id and it ended up in no category at all. Index the
466
+ net as `name -> { id, revision }`, not as a `Set` of names, so the id is available to adopt.
467
+
468
+ An ambiguous match is the one case that must not be adopted: if the source key is not unique
469
+ (e.g. four source products share a title), the net cannot tell which existing entity
470
+ corresponds to which source record. Import rather than guess, and report the ambiguity in the
471
+ completion report.
472
+
473
+ ### Never hand-write slug sanitizing (required)
474
+
475
+ A source handle is **not** already a valid Wix slug. Wix rejects anything outside `[a-z0-9-]`,
476
+ and because slug validation happens before the batch is applied, **one bad slug fails the
477
+ entire bulk request** — 100 products lost for one character. Shopify mints underscores from
478
+ decimal titles ("pH 5.5" → `ph-5_5`), so this is routine input, not an edge case.
479
+
480
+ It is already solved: `wix-build.js` exports `toWixSlug` and applies it automatically through the
481
+ `coerce: 'slug'` rule on `product.slug` in `wix-target-spec.js`. Generated transforms that call
482
+ the build layer (see the `src/import/transforms/` note under "File targets") get it for free and
483
+ must not re-derive it — a per-project copy is how the underscore bug reached a live site in the
484
+ first place.
485
+
486
+ Two properties to preserve when a generated transform sets a slug explicitly:
487
+
488
+ - **Sanitize in the build layer, not the writer**, and keep both values. URL preservation needs
489
+ the original `sourceSlug` alongside the `plannedTargetSlug` actually derived from it (see the
490
+ URL preservation rules under "Codegen rules"), which a silent rewrite inside the writer would
491
+ falsify. `normalizeStoresProductV3` therefore passes a slug through untouched.
492
+ - **`toWixSlug` throws when a value sanitizes to empty** (an all-non-latin title, for example).
493
+ That is a signal to supply a deterministic fallback — the record's source id — not to omit the
494
+ slug and let Wix derive one, which breaks URL preservation with no trace.
495
+
496
+ ## Sample-preview gate
497
+
498
+ Between the extractor being generated and the execution-plan approval, show the user what
499
+ their data actually became. The mapping review checkpoint validates *intent*; this validates
500
+ *structure* — how source rows turned into entities — before any full run.
501
+
502
+ Required whenever the source cannot be read back from a live API — in particular every
503
+ `platform: "csv"` run, where a misread layout silently produces the wrong entity split.
504
+
505
+ 1. Generate the extractor first (`src/extract/run-extract.js`).
506
+ 2. Run it in sample mode (`--sample`) to materialize a small `data/source-extract/` slice.
507
+ 3. Write two artifacts under `migrations/<project>/preview/`:
508
+ - `preview-summary.md` — a short human-readable structure preview: how rows became grouped
509
+ entities (e.g. one product with its variants and images), per-entity record counts, and
510
+ which columns landed in which Wix fields.
511
+ - `preview-result.json` — `{ "status": "pending", "decidedAt": null, "decidedBy": null,
512
+ "entityCounts": {...}, "warnings": [] }`.
513
+ 4. Pause and ask the user to validate the structure. On accept, set `status: "accepted"` with
514
+ `decidedAt`/`decidedBy`; on reject, set `status: "rejected"` and set
515
+ `approvals.mapping.status` back to `pending` so the router returns to `rp-mapper`.
516
+ 5. Record the artifacts on the codegen checkpoint (`checkpoints.codegen.artifactRefs` +
517
+ `lastCompletedStep: "codegen.sample-preview"`).
518
+
519
+ This is a **codegen sub-gate, not an orchestration phase**: it adds no state to
520
+ `orchestration-state.js`. While `preview-result.json` says `pending`, the router keeps routing
521
+ back to this skill instead of advancing to the execution-plan gate — that routing behavior is
522
+ the enforcement, so the artifact must be written honestly. The gate rides on the existing
523
+ extract→import split and does not change how import writes to Wix.
524
+
525
+ ## Project-local config files
526
+
527
+ Generated code should treat `migrations/<project>/config/` as the canonical home for all
528
+ values that are otherwise expected as environment variables. Use simple `.env` syntax and
529
+ load these files before reading config:
530
+
531
+ - `config/wix.env` always exists. Default `DRY_RUN=false`, except when the user has
532
+ explicitly asked to start, create, prepare, or run the migration in dry-run mode; in
533
+ that case scaffold or preserve `DRY_RUN=true`:
534
+
535
+ ```bash
536
+ WIX_SITE_STRATEGY=
537
+ WIX_SITE_ID=
538
+ WIX_AUTH_TOKEN=
539
+ WIX_MUTE_NOTIFICATIONS=
540
+ DRY_RUN=false
541
+ SAFE_MODE=true
542
+ SAFE_MODE_PHONE_NUMBER=+972 50 0000000
543
+ ```
544
+
545
+ - `config/source.<platform>.env` exists after the source platform is known. For WordPress:
546
+
547
+ ```bash
548
+ WP_BASE_URL=
549
+ WP_USERNAME=
550
+ WP_APPLICATION_PASSWORD=
551
+ WP_MEDIA_URL_REWRITE_FROM=
552
+ WP_MEDIA_URL_REWRITE_TO=
553
+ WC_CONSUMER_KEY=
554
+ WC_CONSUMER_SECRET=
555
+ ```
556
+
557
+ For CSV sources this is `config/source.csv.env`, which is **not** secret-bearing — all keys
558
+ are optional hints (`CSV_INPUT_ROOT`, `CSV_DELIMITER`, `CSV_ENCODING`, `CSV_VENDOR`,
559
+ `CSV_MEDIA_URL_REWRITE_FROM`, `CSV_MEDIA_URL_REWRITE_TO`). Generated readers must resolve
560
+ input paths against `CSV_INPUT_ROOT` (falling back to the project directory) rather than
561
+ baking absolute paths into generated code.
562
+
563
+ Codegen rules:
564
+
565
+ - Generate a small dependency-free config loader in the runnable entrypoint or `src/lib/`.
566
+ - Load `config/wix.env` and the selected source config before constructing source/Wix
567
+ clients.
568
+ - Default `DRY_RUN` to disabled. Treat `true`, `1`, `yes`, and `on` as enabled and
569
+ `false`, `0`, `no`, and `off` as disabled. `--dry-run` must override config and enable
570
+ dry-run. `--no-dry-run` may be supported to override `DRY_RUN=true`.
571
+ - When scaffolding a project that is in dry-run mode, generated review artifacts must say
572
+ that leaving dry-run later requires explicit user approval for any step other than
573
+ new-site creation, and that such overrides should be avoided when a dry-run or report
574
+ is sufficient.
575
+ - Preserve an explicit `DRY_RUN=true` from project config when regenerating code or
576
+ config. Do not reset it to `false` during later codegen passes.
577
+ - Default safe mode to enabled when `SAFE_MODE` is missing or blank. Honor
578
+ `SAFE_MODE=false` when the user set it before mapping: do not require
579
+ `safeModeReplacements[]`, do not replace contact values, and do not write safe-mode email
580
+ recovery rows.
581
+ - When safe mode is enabled, require `SAFE_MODE_PHONE_NUMBER`, default missing/blank values
582
+ to `+972 50 0000000`, and make the generated config explicit.
583
+ - Real process environment variables may override file values.
584
+ - Blank values in config files must not overwrite non-empty process env values.
585
+ - If a required key is still missing after loading file + env, fail fast with the key
586
+ name, not a downstream 401.
587
+ - In dry-run, missing or blank `WIX_AUTH_TOKEN` and `WIX_SITE_ID` are `would_block_live`
588
+ findings, not blockers, unless a generated local artifact requires the site ID as a
589
+ stable namespace. Do not mint a Wix CLI token solely for dry-run.
590
+ - `WIX_MUTE_NOTIFICATIONS` (spec 0012) resolves by strategy when blank: `new` → `on`,
591
+ `existing` → `off`; record the resolved value explicitly (mirrored from
592
+ `orchestration/decisions.json`). **`WIX_MUTE_NOTIFICATIONS=off` together with
593
+ `WIX_SITE_STRATEGY=new` fails codegen validation** — halt with the config conflict
594
+ rather than generating artifacts (the same rule fails in `rp-setup-discovery`; fail
595
+ fast at whichever runs first). Note the preflight emission rule below ignores the
596
+ config for new sites anyway — it is unconditional.
597
+ - Treat `WIX_SITE_STRATEGY` as required. `WIX_SITE_ID` becomes required no later than the
598
+ point where generated code needs to construct Wix clients or destination-specific
599
+ artifacts. For `WIX_SITE_STRATEGY=new`, codegen should fail with a clear message to
600
+ create/select the new Wix site first rather than assuming an existing site flow.
601
+ - For RePlatform `new site` + `headless`, that unblock message must point back to the **Wix
602
+ CLI headless scaffold** in `replatform` → "Headless site creation"
603
+ (`npm create @wix/new@latest headless`). The account-level Projects API is deprecated for
604
+ this workflow.
605
+ - `WIX_AUTH_TOKEN` is the canonical Wix auth key in project-local config and holds the
606
+ **site write credential** for import. With CLI-scaffolded headless sites this is a
607
+ short-lived CLI token sent as a **Bearer** token — the generated Wix client must send
608
+ `Authorization: Bearer <token>` (plus `wix-site-id`). Do not assume a raw, non-expiring API
609
+ key; mint the token at write time.
610
+ - Never log secret values. It is okay to log that a key is present/missing.
611
+ - Dry-run must write request captures under `state/attempts/wix-request-captures.ndjson`
612
+ and dry-run placeholder target IDs only under `state/crosswalk/dry-run-crosswalk.ndjson`
613
+ or in memory. It must never append simulated target IDs to
614
+ `state/crosswalk/crosswalk.ndjson`.
615
+ - Do not generate debug output that dumps config file contents, environment snapshots, or
616
+ request headers carrying credentials.
617
+
618
+ ## WooCommerce subscription product codegen
619
+
620
+ For WooCommerce Stores products, subscription products are a native Wix Stores product
621
+ subtype when the target metadata marks `product.subscriptionDetails` writable for
622
+ Catalog V3 create. Codegen must read the `stores/product` `fieldContracts[]` metadata and
623
+ vendor/use the matching `rp-target-wix/lib/wix-writers.js` helpers:
624
+
625
+ - `STORES_SUBSCRIPTION_CONTRACT`
626
+ - `normalizeStoresProductSubscriptions`
627
+ - `validateStoresProductSubscriptionDetails`
628
+
629
+ Generate deterministic native subscription mapping only from recognized structured
630
+ WooCommerce subscription fields. Accepted first-pass source keys include:
631
+
632
+ - `_subscription_period_interval`
633
+ - `_subscription_period`
634
+ - `_subscription_length`
635
+ - `_subscription_trial_period`
636
+ - `_subscription_trial_length`
637
+ - `_subscription_sign_up_fee`
638
+ - `_subscription_price`
639
+
640
+ Equivalent public REST fields may be used when discovery normalized them into the source
641
+ schema, but do not infer cadence from product titles, descriptions, prose, shortcode
642
+ blobs, or unrecognized plugin metadata.
643
+
644
+ Mapping rules:
645
+
646
+ - Treat source `type: "subscription"` or recognized subscription metadata as the product
647
+ subtype signal.
648
+ - Parse billing interval as an integer `>= 1`.
649
+ - Parse billing period from `day`, `week`, `month`, or `year`, then emit Wix frequency
650
+ `DAY`, `WEEK`, `MONTH`, or `YEAR`.
651
+ - Use subscription price when present, otherwise the normal product price, and still emit
652
+ the Catalog V3 variant-level money object required by the shared writer.
653
+ - Parse optional length/trial/signup-fee fields only when they are clean structured
654
+ values. If a field is present but malformed and needed for the selected mapping, defer
655
+ the record rather than guessing.
656
+ - Build subscription descriptions deterministically from source subscription labels or
657
+ product names, then pass them through `normalizeStoresProductSubscriptions` so the Wix
658
+ `description <= 60` contract is satisfied before write.
659
+ - Run `validateStoresProductSubscriptionDetails` in the generated dry-run path and before
660
+ live create for every product carrying `subscriptionDetails`.
661
+
662
+ Do not generate a generic subscription skip gate. If a subscription product lacks
663
+ structured cadence or required values, emit an explicit deferred record such as
664
+ `unsupported_subscription_shape`, `missing_subscription_cadence`, or
665
+ `invalid_subscription_interval`, and include that reason in the execution summary. A
666
+ deferred subscription is a counted import outcome, not a silent skip.
667
+
668
+ **Token minting — always route through `scripts/mint-token.sh`.** Every migration project
669
+ must include `scripts/mint-token.sh`. The script reads `WIX_SITE_ID` from `config/wix.env`,
670
+ runs `npx @wix/cli@latest token --site "$WIX_SITE_ID"`, captures the token (shape:
671
+ `OauthNG.JWS.<base64>.<base64>.<sig>` — single line, no JSON wrapper), and writes it
672
+ directly to `config/wix.env` as `WIX_AUTH_TOKEN` without printing the value. Run via Bash:
673
+
674
+ ```bash
675
+ bash migrations/<project>/scripts/mint-token.sh
676
+ ```
677
+
678
+ **Do NOT** run `npx @wix/cli@latest token` raw in a Bash tool call — it prints the
679
+ credential to stdout which lands in the transcript. Always use `mint-token.sh`.
680
+
681
+ **During scaffolding, copy `scripts/mint-token.sh` from the canonical skills location** —
682
+ do not generate it from scratch:
683
+
684
+ ```bash
685
+ cp skills/replatform/resources/rp-execute-setup/scripts/mint-token.sh \
686
+ migrations/<project>/scripts/mint-token.sh
687
+ ```
688
+
689
+ The preferred
690
+ pre-import flow is:
691
+
692
+ 1. verify `wix whoami`,
693
+ 2. run `bash scripts/mint-token.sh` (writes `WIX_AUTH_TOKEN` silently),
694
+ 3. run the import — the generated client reads `WIX_AUTH_TOKEN` and sends it as
695
+ `Authorization: Bearer <token>` with `wix-site-id`.
696
+
697
+ ## Localhost media sources
698
+
699
+ If the source profile shows `localhost`, `127.0.0.1`, or another private-only source URL,
700
+ generated media import code must not assume Wix can fetch those URLs. Wix Media import is
701
+ URL-based (`rp-target-wix` import-from-URL primitive), so live media import needs a public
702
+ URL reachable by Wix servers. This is optional and, as far as we know today, only affects
703
+ media import. Entity-native background ingestion from external URLs follows the same
704
+ reachability requirement: if the target API ingests a source URL itself, that URL must
705
+ still be publicly reachable by Wix.
706
+
707
+ Codegen/runtime should support one of these explicit paths:
708
+
709
+ - Use a public HTTPS tunnel/source URL for live media import. For ngrok on macOS:
710
+
711
+ ```bash
712
+ brew install ngrok
713
+ ngrok config add-authtoken "<YOUR_AUTHTOKEN>"
714
+ ngrok http 8090
715
+ export WP_BASE_URL=https://<id>.ngrok-free.app
716
+ ```
717
+
718
+ - If the source REST responses still contain local media URLs, generate a configurable
719
+ rewrite from the local base URL to the public tunnel base URL. For WordPress, use
720
+ `WP_MEDIA_URL_REWRITE_FROM` and `WP_MEDIA_URL_REWRITE_TO`; when those are blank, it is
721
+ acceptable to rewrite localhost/private origins to public `WP_BASE_URL`.
722
+ - Or generate/allow a media-skip/defer mode and document that media-dependent references
723
+ such as hero images, galleries, and downloadable files will be absent until media is
724
+ imported.
725
+
726
+ Surface the selected path in `execution/review/import-plan.md` and the execution plan before any live
727
+ write. Do not let a dry-run with localhost media URLs imply live Wix Media import is ready.
728
+
729
+ ## File targets
730
+
731
+ Write code under the project-local source tree:
732
+
733
+ - `migrations/<project>/execution/`
734
+ - `migrations/<project>/src/setup/`
735
+ - `migrations/<project>/src/extract/`
736
+ - `migrations/<project>/src/import/`
737
+ - `migrations/<project>/src/lib/` — vendored shared modules (the source adapter's transport
738
+ module, `rp-target-wix/lib/ndjson.js`, `rp-target-wix/lib/wix-writers.js`,
739
+ `rp-target-wix/lib/wix-target-spec.js`, `rp-target-wix/lib/wix-build.js`), copied here so
740
+ the project runs standalone with no external deps
741
+ - `migrations/<project>/src/extract/readers/`
742
+ - `migrations/<project>/src/import/transforms/` — **thin glue only.** Vendor and call
743
+ `wix-build.js`; do **not** re-derive the canonical→Wix payload layer here. Money objects, slug
744
+ sanitization, the empty `physicalProperties` trap, choice-by-name variant references, the
745
+ compare-at-must-exceed-price rule and the regular/sale price resolution are all settled in
746
+ `wix-target-spec.js` + `wix-build.js` and regression-locked by
747
+ `tests/mapping/wix-build-oracle-test.js` against 220 payloads from two live-verified imports.
748
+ That layer is vendor-independent, so a per-project reimplementation only re-introduces bugs
749
+ that were already found and fixed. This directory should hold at most the mapping from THIS
750
+ project's reader field names onto the canonical vocabulary — and once the reader emits canonical
751
+ records directly, nothing at all.
752
+ - `migrations/<project>/src/import/write-specs/`
753
+ - `migrations/<project>/src/setup/run-setup.js` — setup execution entrypoint
754
+ - `migrations/<project>/src/extract/run-extract.js` — extraction entrypoint. It must accept
755
+ `--sample` (extract a small slice only); that is what the sample-preview gate runs.
756
+ - `migrations/<project>/src/import/run-import.js` — the runnable import entrypoint
757
+ (required; see "Runnable setup/extraction/import entrypoints" above). `--dry-run`
758
+ drives the safe-validation pass through the same import code path.
759
+ - `migrations/<project>/data/source-extract/` — extracted `<entity>.ndjson` record streams plus
760
+ a `manifest.json` (the manifest is a single document, so it stays JSON)
761
+ - `migrations/<project>/state/crosswalk/crosswalk.ndjson` — authoritative local
762
+ `sourceId -> targetId` crosswalk for native Wix entities
763
+ - `migrations/<project>/state/attempts/write-attempts.ndjson` — append-only write attempt
764
+ journal for resume/reconciliation
765
+ - `migrations/<project>/state/url-preservation/base-paths.json` — entity-level public
766
+ route intent from mapping `urlPolicy`
767
+ - `migrations/<project>/state/url-preservation/url-ledger.ndjson` — append-only URL
768
+ preservation upsert log, one latest row per `sourceStableKey + sourceRelativeUrl`
769
+ - `migrations/<project>/state/url-preservation/redirects.ndjson` — planned redirect rows
770
+ when source and target relative URLs are both known and differ
771
+ - `migrations/<project>/state/url-preservation/unresolved.ndjson` — public source URLs
772
+ waiting on target route configuration, target lookup, or manual review
773
+ - `migrations/<project>/logs/` — audit/error logs emitted by the shared runtime
774
+ - `migrations/<project>/execution/review/import-plan.md`
775
+ - `migrations/<project>/execution/review/code-safety-review.md` when `SAFE_MODE=true` or
776
+ `DRY_RUN=true`
777
+ - `migrations/<project>/execution/recovery-log.json` — append-only standard recovery
778
+ actions emitted by every resumed, partial, missing-only, failed-only, or deferred-only
779
+ run
780
+
781
+ Recommended machine-readable artifacts:
782
+
783
+ - `migrations/<project>/execution/setup-plan.json`
784
+ - `migrations/<project>/execution/execution-manifest.json`
785
+ - `migrations/<project>/execution/llm-handoff.json`
786
+ - `migrations/<project>/execution/live-import-summary.json`
787
+ - `migrations/<project>/execution/completion-report.json`
788
+
789
+ ## Generated write spec contract
790
+
791
+ Generated writer code should be thin. It should primarily define deterministic per-entity
792
+ write specs, then pass Wix-shaped objects into the shared runtime.
793
+
794
+ Each write spec should define, as applicable:
795
+
796
+ - `entity`
797
+ - `mode`: `create | update | upsert | bulk_create | bulk_upsert`
798
+ - `create`
799
+ - `update`
800
+ - `lookup`
801
+ - `bulk`
802
+ - `batchSize`
803
+ - `concurrency`
804
+ - `retryPolicy`
805
+ - `throttlePolicy`
806
+ - `auditKeys`
807
+ - `crosswalkAuthority: "local"`
808
+ - `cmsMirror: "none" | "download" | "upload" | "download-and-upload"`
809
+ - `crosswalkStrategy`
810
+ - `reconciliationStrategy`
811
+ - `dependencyRefs`
812
+ - `verificationLevel`: `verified | unverified`
813
+ - `safeMode.replacePaths[]`: resolved request-body paths copied from mapper
814
+ `safeModeReplacements[]`, with `{ kind: "email" | "phone", path }` entries. Paths use
815
+ the shared safe-mode grammar (`field`, `field[]`, `field.items[]`) and are relative to
816
+ the request body passed to the shared writer builder. The mapper is required to surface
817
+ these replacements in both machine artifacts and review markdown; codegen should treat
818
+ missing `safeModeReplacements[]` for an entity with outbound contact fields as a mapper
819
+ contract failure, not as a cue to infer or invent replacements silently.
820
+
821
+ The transform layer should output Wix-shaped objects only. Request-envelope building and
822
+ retry/reporting logic belong in the shared runtime.
823
+
824
+ When safe mode is enabled, generated import code must derive one `safeModeOptions` object
825
+ per source record and pass it to every Wix writer call. The options must include origin
826
+ `entityType`, deterministic origin `entityId`, `safeModePhoneNumber`, and the write spec's
827
+ resolved replacement paths. `entityId` must be the source ID or deterministic
828
+ `sourceStableKey`, never the target Wix ID. If no deterministic origin identity exists,
829
+ fail before writing.
830
+
831
+ Generated code must not query Wix by original email or phone values while safe mode is
832
+ enabled. Any destination lookup keyed by contact data must use the same mock value that the
833
+ writer will send, with local crosswalk state remaining the primary idempotency authority.
834
+
835
+ ## Execution artifact contract
836
+
837
+ Codegen should emit machine-readable execution artifacts alongside runnable code.
838
+
839
+ - `execution/setup-plan.json`: execution-ready rendering of setup work
840
+ - `execution/execution-manifest.json`: authoritative ordered task graph covering setup,
841
+ extraction, transform/write execution, artifact refs, checkpoint ids, and plan version
842
+ - `execution/llm-handoff.json`: whether unresolved codegen/execution decisions remain
843
+
844
+ This manifest is the primary downstream contract for `rp-execute-setup` and
845
+ `rp-execute-import`.
846
+
847
+ For every import task that handles public routed entities, include:
848
+
849
+ ```json
850
+ {
851
+ "urlPreservation": {
852
+ "enabled": true,
853
+ "basePathsPath": "state/url-preservation/base-paths.json",
854
+ "ledgerPath": "state/url-preservation/url-ledger.ndjson",
855
+ "redirectsPath": "state/url-preservation/redirects.ndjson",
856
+ "unresolvedPath": "state/url-preservation/unresolved.ndjson",
857
+ "applyRedirects": false
858
+ }
859
+ }
860
+ ```
861
+
862
+ Do not set `applyRedirects` to `true`; the current phase records redirect plans but does
863
+ not configure Wix redirects or site routes.
864
+
865
+ ## Import completeness accounting contract
866
+
867
+ Generated import runners must treat completeness accounting as a first-class runtime
868
+ output. For each mapped entity class and meaningful subtype, the runner must produce an
869
+ `entityCompleteness` row with these counters:
870
+
871
+ - `extracted`
872
+ - `inScope`
873
+ - `attempted`
874
+ - `imported`
875
+ - `alreadyPresentByCrosswalk`
876
+ - `deferred`
877
+ - `failed`
878
+ - `skippedOutOfScope`
879
+ - `unexpectedSkipped`
880
+
881
+ Subtype is required whenever source records with the same entity map through materially
882
+ different write paths or deferral rules, for example simple vs subscription Stores
883
+ products. `deferred` means intentionally not attempted with a recorded reason. `failed`
884
+ means attempted and not successfully written. `unexpectedSkipped` is for in-scope mapped
885
+ records that were skipped outside an accepted out-of-scope rule.
886
+
887
+ The generated runner must call or vendor `skills/replatform/lib/completion-report.js` and
888
+ write both:
889
+
890
+ - `execution/live-import-summary.json` during/after live import for machine inspection
891
+ - `execution/completion-report.json` as the authoritative final outcome artifact
892
+
893
+ For each row, reconciliation is:
894
+
895
+ ```text
896
+ imported + alreadyPresentByCrosswalk + deferred + failed == inScope
897
+ ```
898
+
899
+ Any reconciliation mismatch, non-zero `failed`, non-zero `deferred`, or non-zero
900
+ `unexpectedSkipped` count must appear in the report headline and in the deterministic
901
+ human completion summary. Do not report a run as cleanly complete when source, import, and
902
+ crosswalk counts do not reconcile.
903
+
904
+ ## Verifying Wix APIs
905
+
906
+ **The primary control is the Target write contract above: call `rp-target-wix`'s
907
+ verified primitives when they exist.** That adapter is where each stable shape is
908
+ verified-once (by a real call) and where a Wix surface change is fixed in one place.
909
+ When Wix has a native entity but `rp-target-wix` does not yet have a dedicated writer,
910
+ codegen must generate a Wix REST call for that native entity via the adapter's generic
911
+ direct REST helper, log the missing writer, and call the RePlatform notification hook.
912
+ Do **not** route to CMS merely because the writer is missing.
913
+
914
+ - If a Wix tool surface such as Wix MCP is available, prefer it to locate the endpoint
915
+ and request/response shape. If the shape is common enough, add a dedicated primitive to
916
+ `resources/rp-target-wix/lib/wix-writers.js`; otherwise generate a project-local native
917
+ REST call through `sendDirectRest` and mark it `UNVERIFIED`.
918
+ - **Confirm the shape with a real call, not a doc example** — public examples have been
919
+ wrong (e.g. lowercase Ricos plugin enums that 400). Cover the new primitive in
920
+ `tests/target-wix/contract-test.js` so drift stays visible.
921
+ - **Fallback when no Wix tool surface is available:** rely on published Wix REST/SDK docs
922
+ and conservative names. Mark the generated native call `// UNVERIFIED:` until a real
923
+ call confirms it — never ship an unchecked Wix call to a user's live site without
924
+ surfacing it in the execution plan.
925
+
926
+ ## Runtime policy
927
+
928
+ Verify each Wix endpoint and field at codegen time. The `// UNVERIFIED:` marker is a
929
+ fallback only for environments where no direct verification aid is available, not a way
930
+ to ship unchecked calls that fail later on the user's live site. Anything unverified must
931
+ be surfaced explicitly in downstream artifacts before execution.
932
+
933
+ ## Missing writer policy
934
+
935
+ CMS fallback is for source concepts that do **not** have a suitable native Wix entity, or
936
+ for native entities explicitly rejected because they cannot preserve fidelity or would
937
+ cause unsafe side effects. CMS is **not** a fallback for a missing writer, and it is not a
938
+ special default for coupons just because coupon scoping/restrictions need mapping.
939
+
940
+ When the mapping targets a native Wix entity and no dedicated `rp-target-wix` writer
941
+ exists:
942
+
943
+ 1. Generate project-local code that calls the native Wix REST endpoint through
944
+ `sendDirectRest`.
945
+ 2. Add a clear log line before the first use of that generated REST path.
946
+ 3. Call `notifyMissingWriter({ sourceEntity, wixEntity, method, path, reason })`. The
947
+ current implementation may be a no-op; the generated code must still call it.
948
+ 4. Mark the path `UNVERIFIED` in `execution/review/import-plan.md` and the execution-plan report until a
949
+ live/sandbox call promotes it.
950
+ 5. Maintain the same idempotency rules as dedicated writers: crosswalk by source ID in
951
+ local state and never dedupe by slug.
952
+
953
+ ## Codegen rules
954
+
955
+ - Keep reader and writer responsibilities separate.
956
+ - Keep setup, extraction, and import responsibilities separate.
957
+ - Do not generate a read-all-into-memory importer for the general case. The reader extracts
958
+ to disk first; the importer consumes extracted files from disk.
959
+ - Make transforms deterministic and testable.
960
+ - Make generated write specs deterministic and declarative.
961
+ - Preserve **source IDs** for traceability, but do not assume native Wix target IDs can
962
+ be preserved or client-assigned.
963
+ - Generate a stable selection layer before executing writes. Use the shared
964
+ `import-recovery.js` runtime helpers where available, or vendor equivalent helpers into
965
+ the project. Selection must:
966
+ - apply `--entity` before entity write execution,
967
+ - apply `--source-type` against deterministic source subtype fields such as
968
+ WooCommerce `type: "subscription"`,
969
+ - exclude local-crosswalk hits in `--missing-only` mode and count them as
970
+ `alreadyPresent`,
971
+ - select latest failed attempt rows for `--failed-only`,
972
+ - select latest deferred/needs-verification attempt rows for `--deferred-only`,
973
+ - emit an execution selection summary before the first write.
974
+ - Native Wix creates must perform a local crosswalk lookup immediately before every create,
975
+ even after pre-selection. If a crosswalk row is found, skip idempotently and count the
976
+ record as already present instead of writing a duplicate.
977
+ - Every selective/resumed/partial run must append `execution/recovery-log.json` with a
978
+ standard recovery entry containing: recovery id, timestamp, selection filters, reason,
979
+ records selected, records attempted, imported, already present, failed, deferred,
980
+ crosswalk changes, summary changes, operator-visible outcome, and links to detailed logs.
981
+ Recovery artifacts are append-only; never overwrite or collapse prior recovery actions.
982
+ - Update `execution/live-import-summary.json` through a shared summary writer, not by
983
+ hand-editing counters in recovery-specific code. The recovery-log entry must include
984
+ the summary delta so final state can be reconstructed from standard execution artifacts.
985
+ - For public routed entities, consume mapping `urlPolicy` and initialize local URL
986
+ preservation state before writes. Generate deterministic helpers, or vendor the shared
987
+ `url-preservation-state.js` behavior, to:
988
+ - write `base-paths.json` from entity-level route policies
989
+ - derive `sourceRelativeUrl` from `sourceUrlField` or `sourceBasePath + sourceSlugField`
990
+ - preserve the original `sourceSlug` before any normalization
991
+ - record `plannedTargetSlug` before create/update
992
+ - record `actualTargetSlug` and `actualTargetRelativeUrl` only after the Wix response or
993
+ a safe target lookup proves them
994
+ - append replacement rows to `url-ledger.ndjson` instead of editing rows in place
995
+ - write `redirects.ndjson` only when both relative URLs are known and differ
996
+ - write `unresolved.ndjson` with `pending_target_route`, `target_url_missing`,
997
+ `source_url_missing`, or `manual_review` when a concrete preserved URL or redirect
998
+ cannot be derived safely
999
+ - never silently overwrite a source slug with a normalized slug
1000
+ - URL ledger resume must replay the latest valid `url-ledger.ndjson` row by
1001
+ `sourceStableKey + sourceRelativeUrl`, derive expected rows from extracted source
1002
+ records and `urlPolicy`, merge target IDs from the local crosswalk, and query Wix only
1003
+ when the write spec declares the lookup safe.
1004
+ - For native Wix entities, generate and use the shared local-state runtime
1005
+ (`local-state.js`) whenever the target API does not expose a client-controlled
1006
+ source-id field. Load `state/crosswalk/crosswalk.ndjson` at startup, rebuild missing or
1007
+ corrupt index caches from it, append a `started` row to
1008
+ `state/attempts/write-attempts.ndjson` before each native write, write the confirmed
1009
+ crosswalk row after success, then mark the attempt `imported`. **Slug-based dedupe does
1010
+ NOT work** — Wix rewrites slugs; never rely on it.
1011
+ - Only fetch CMS `ImportCrosswalk` rows as a pre-execution seed for existing-site,
1012
+ legacy, recovery, or delta flows, and only when valid local crosswalk state does not
1013
+ already exist. Dedupe downloaded mirror rows by `sourceStableKey` and newest valid
1014
+ `updatedAt`. Never use CMS as the ordinary resume source after local state exists.
1015
+ - **Conditional-entity gating must match the verification artifact exactly.** When an
1016
+ entity's import is gated on a `setup/setup-verification.json` item (e.g. an unverified
1017
+ native path that setup must promote), the generated lookup must key on the same field
1018
+ the generated setup runner writes (requirement id vs step id — pick one and use it in
1019
+ both). A mismatched key silently reports "not verified" (fails safe into deferral, but
1020
+ would wrongly defer a passing entity).
1021
+ - The optional CMS mirror collection name is **`ImportCrosswalk`**. If upstream artifacts
1022
+ still say `MigrationRefs`, normalize them to `ImportCrosswalk` in the generated code and
1023
+ note the normalization in `execution/review/import-plan.md`.
1024
+ - **Attach every related entity, don't just create it.** Creating a tag/category is not the
1025
+ same as linking it. Blog posts attach tags via `tagIds` (GUIDs) and categories via
1026
+ `categoryIds` on the draft-post create — collect the resolved ids and pass them, or the
1027
+ taxonomy exists on the site but `postCount` stays 0 (a builder bug we hit before).
1028
+ - **Taxonomy creates are not idempotent**: treat `409 ALREADY_EXISTS` as success
1029
+ AND resolve the existing entity's id (e.g. `listBlogTags`) so it can still be attached —
1030
+ don't drop it.
1031
+ - **Blog rich text is chunked for you.** `convertHtmlToRichContent` transparently splits HTML
1032
+ over the 30k Ricos cap and merges the node arrays; pass full HTML, don't pre-truncate
1033
+ or skip large posts. This is the **blog** path only — a blog post's `richContent` really is a
1034
+ Ricos document. Stores products must NOT use it: their HTML goes in `plainDescription` and Wix
1035
+ converts it server-side (see the product-description rule above).
1036
+ - Use the shared runtime for batching, retries, throttling, checkpoints, and audit/report
1037
+ emission rather than generating those mechanics ad hoc.
1038
+ - Use the deterministic execution-state preparation contract before native writes. Do not
1039
+ let generated import code query CMS directly for resume; CMS mirror rows must be copied
1040
+ into local crosswalk state first.
1041
+ - Do not hardcode secrets.
1042
+
1043
+ ## Headless storefront codegen rules
1044
+
1045
+ When the delivery mode includes a headless storefront (i.e. a `wix-headless` Astro project
1046
+ is generated alongside the import), apply these rules in addition to the general codegen
1047
+ rules above.
1048
+
1049
+ **Cursor-paginated catalog queries (required).** Generated shop and category pages must
1050
+ never call `queryProducts().limit(N).find()` once and stop. Wix Stores returns at most 100
1051
+ items per page — a store with more than 100 products silently truncates the listing.
1052
+ Always generate a cursor loop in the shared catalog helper and call it from every page
1053
+ that lists products:
1054
+
1055
+ ```ts
1056
+ async function listAllProducts(): Promise<Product[]> {
1057
+ const all: Product[] = [];
1058
+ let result = await products.queryProducts().limit(100).find();
1059
+ all.push(...result.items);
1060
+ while (result.hasNext()) {
1061
+ result = await result.next();
1062
+ all.push(...result.items);
1063
+ }
1064
+ return all;
1065
+ }
1066
+ ```
1067
+
1068
+ Apply the same pattern to category-filtered product queries (`productsInCategory`). This
1069
+ is a data-correctness requirement, not a UX preference.
1070
+
1071
+ **Product count display (required).** Every generated shop and category page must display
1072
+ the total product count (e.g. `מציג X מוצרים` for RTL Hebrew sites, or equivalent).
1073
+ The count is `products.length` after the cursor loop completes and must appear above the
1074
+ product grid.
1075
+
1076
+ **`client:load` for primary CTA islands (required).** Generated product detail pages must
1077
+ mount add-to-cart and cart-view React islands with `client:load`, not `client:only`.
1078
+ `client:only` omits the component from the server-rendered HTML entirely — it is
1079
+ invisible to crawlers and does not render until after full React hydration.
1080
+ `client:load` hydrates immediately on page load. `client:only` must never be the default
1081
+ for a primary call-to-action.
1082
+
1083
+ **URL redirect file for WooCommerce sources (required).** When the source platform is
1084
+ WooCommerce and the delivery includes a storefront, generate `frontend/public/_redirects`
1085
+ mapping old WordPress URL patterns to the new Astro routes. At minimum:
1086
+
1087
+ ```
1088
+ /product/:slug /products/:slug 301
1089
+ /product-category/:slug /category/:slug 301
1090
+ /shop/ /shop 301
1091
+ /?p=* / 301
1092
+ ```
1093
+
1094
+ Also generate `frontend/src/pages/product/[slug].astro` (singular path) as a redirect
1095
+ shim to `/products/[slug]` (plural path). This prevents 404s on all inbound links from
1096
+ the old site. Derive the source URL pattern from the source profile captured during
1097
+ discovery; `/product/` is the standard WooCommerce single-product path.
1098
+
1099
+ The `_redirects` file and redirect shim are required migration outputs, not optional
1100
+ polish.
1101
+
1102
+ ## When codegen must halt to LLM
1103
+
1104
+ Emit `execution/llm-handoff.json` with `needsLlm: true` when any of the following occur:
1105
+
1106
+ - a native Wix path exists but only an unverified write surface is available
1107
+ - setup artifacts are insufficient to generate deterministic setup execution
1108
+ - transform semantics remain unresolved
1109
+ - a multi-pass relationship strategy cannot be derived deterministically
1110
+ - the runtime contract required from `rp-target-wix` is missing for the mapped target
1111
+
1112
+ ## Output
1113
+
1114
+ Summarize which files were generated, which entities they cover, and any remaining implementation gaps.