@wix/agent-skills 1.36.0 → 1.36.1

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 (776) hide show
  1. package/package.json +8 -3
  2. package/skills/wix-headless-kit/install/pins.json +1 -1
  3. package/skills/wix-manage/SKILL.md +3 -3
  4. package/skills/wix-manage/references/cms/cms-data-items-crud.md +78 -1
  5. package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +11 -11
  6. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +20 -51
  7. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +4 -4
  8. package/skills/wix-base44-connector/SKILL.md +0 -437
  9. package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +0 -78
  10. package/skills/wix-base44-connector/scripts/utils.cjs +0 -466
  11. package/skills/wix-export/SKILL.md +0 -83
  12. package/skills/wix-harmony-editor/.publish-manifest.json +0 -8
  13. package/skills/wix-harmony-editor/COPY-SITE.md +0 -494
  14. package/skills/wix-harmony-editor/SKILL.md +0 -317
  15. package/skills/wix-harmony-editor/scripts/copy/build-description.mjs +0 -249
  16. package/skills/wix-harmony-editor/scripts/copy/check-description.mjs +0 -225
  17. package/skills/wix-harmony-editor/scripts/copy/check-mirror.mjs +0 -89
  18. package/skills/wix-harmony-editor/scripts/copy/compare-preview.mjs +0 -76
  19. package/skills/wix-harmony-editor/scripts/copy/deploy-description.mjs +0 -212
  20. package/skills/wix-harmony-editor/scripts/copy/desc-hash.mjs +0 -44
  21. package/skills/wix-harmony-editor/scripts/copy/editor-run.mjs +0 -45
  22. package/skills/wix-harmony-editor/scripts/copy/export-page.mjs +0 -53
  23. package/skills/wix-harmony-editor/scripts/copy/find-interactions.mjs +0 -76
  24. package/skills/wix-harmony-editor/scripts/copy/hide-scrollbars.mjs +0 -16
  25. package/skills/wix-harmony-editor/scripts/copy/import-media.mjs +0 -150
  26. package/skills/wix-harmony-editor/scripts/copy/link-url.mjs +0 -27
  27. package/skills/wix-harmony-editor/scripts/copy/lint-api.mjs +0 -56
  28. package/skills/wix-harmony-editor/scripts/copy/measure-source.mjs +0 -211
  29. package/skills/wix-harmony-editor/scripts/copy/merge-mirrors.mjs +0 -29
  30. package/skills/wix-harmony-editor/scripts/copy/mirror-site.mjs +0 -92
  31. package/skills/wix-harmony-editor/scripts/copy/mobile-stage.mjs +0 -56
  32. package/skills/wix-harmony-editor/scripts/copy/preview-widths.mjs +0 -73
  33. package/skills/wix-harmony-editor/scripts/copy/render-plate.mjs +0 -67
  34. package/skills/wix-harmony-editor/scripts/copy/serve-mirror.mjs +0 -102
  35. package/skills/wix-harmony-editor/scripts/copy/snapshot-capabilities.mjs +0 -40
  36. package/skills/wix-harmony-editor/scripts/copy/split-sections.mjs +0 -191
  37. package/skills/wix-harmony-editor/scripts/copy/upload-media-manager.mjs +0 -61
  38. package/skills/wix-harmony-editor/scripts/launch.sh +0 -359
  39. package/skills/wix-headless/SKILL.md +0 -151
  40. package/skills/wix-headless/references/AI_FEATURES.md +0 -178
  41. package/skills/wix-headless/references/CAPABILITIES.md +0 -117
  42. package/skills/wix-headless/references/CONTENT.md +0 -36
  43. package/skills/wix-headless/references/DESIGN.md +0 -55
  44. package/skills/wix-headless/references/DISCOVERY.md +0 -80
  45. package/skills/wix-headless/references/DOC_DISCOVERY.md +0 -43
  46. package/skills/wix-headless/references/FEEDBACK.md +0 -129
  47. package/skills/wix-headless/references/IMAGE_GENERATION.md +0 -80
  48. package/skills/wix-headless/references/SDK_HANDOFF.md +0 -108
  49. package/skills/wix-headless/references/SEED.md +0 -74
  50. package/skills/wix-headless/references/SETUP.md +0 -60
  51. package/skills/wix-headless/references/astro.md +0 -98
  52. package/skills/wix-headless/references/inline-recipes/experience-donations.md +0 -102
  53. package/skills/wix-headless/references/inline-recipes/experience-store.md +0 -49
  54. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +0 -196
  55. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +0 -590
  56. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +0 -279
  57. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +0 -163
  58. package/skills/wix-headless/references/inline-recipes/how-to-code-donations.md +0 -146
  59. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +0 -203
  60. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +0 -696
  61. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +0 -124
  62. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +0 -160
  63. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +0 -118
  64. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +0 -132
  65. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +0 -126
  66. package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +0 -254
  67. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +0 -191
  68. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +0 -213
  69. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +0 -161
  70. package/skills/wix-headless/references/inline-recipes/setup-blog.md +0 -175
  71. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +0 -232
  72. package/skills/wix-headless/references/inline-recipes/setup-cms.md +0 -200
  73. package/skills/wix-headless/references/inline-recipes/setup-donations.md +0 -15
  74. package/skills/wix-headless/references/inline-recipes/setup-events.md +0 -196
  75. package/skills/wix-headless/references/inline-recipes/setup-forms.md +0 -288
  76. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +0 -214
  77. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +0 -155
  78. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +0 -229
  79. package/skills/wix-headless/references/inline-recipes/setup-rentals.md +0 -254
  80. package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +0 -73
  81. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +0 -197
  82. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +0 -136
  83. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +0 -152
  84. package/skills/wix-headless/references/managed/AUTHENTICATION.md +0 -71
  85. package/skills/wix-headless/references/managed/CONNECT.md +0 -74
  86. package/skills/wix-headless/references/managed/CREATE.md +0 -149
  87. package/skills/wix-headless/references/managed/DEPLOYMENT.md +0 -104
  88. package/skills/wix-headless/references/non-astro.md +0 -59
  89. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +0 -22
  90. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +0 -15
  91. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +0 -55
  92. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +0 -71
  93. package/skills/wix-headless/scripts/bootstrap.mjs +0 -156
  94. package/skills/wix-headless-replatform/.publish-manifest.json +0 -8
  95. package/skills/wix-headless-replatform/SKILL.md +0 -116
  96. package/skills/wix-headless-replatform/agents/openai.yaml +0 -6
  97. package/skills/wix-headless-replatform/references/control-and-visual-fidelity-contract.md +0 -43
  98. package/skills/wix-headless-replatform/references/extraction-schema.md +0 -187
  99. package/skills/wix-headless-replatform/references/interaction-runtime-contract.md +0 -137
  100. package/skills/wix-headless-replatform/references/layout-blueprint-contract.md +0 -41
  101. package/skills/wix-headless-replatform/references/output-contract.md +0 -93
  102. package/skills/wix-headless-replatform/references/post-build-gap-contract.md +0 -125
  103. package/skills/wix-headless-replatform/references/qa-checklist.md +0 -83
  104. package/skills/wix-headless-replatform/references/safety.md +0 -19
  105. package/skills/wix-headless-replatform/references/ui-normalization-contract.md +0 -70
  106. package/skills/wix-headless-replatform/references/workflow.md +0 -157
  107. package/skills/wix-headless-replatform/registry/README.md +0 -20
  108. package/skills/wix-headless-replatform/registry/approvals/button/shadcn-default-ac60ef5.json +0 -28
  109. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/button.tsx +0 -54
  110. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/capabilities.json +0 -60
  111. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/contract.md +0 -48
  112. package/skills/wix-headless-replatform/registry/licenses/shadcn-ui-ac60ef5-MIT.txt +0 -21
  113. package/skills/wix-headless-replatform/registry/registry.json +0 -36
  114. package/skills/wix-headless-replatform/resources/rp-facelift/SKILL.md +0 -32
  115. package/skills/wix-headless-replatform/resources/rp-project-context/SKILL.md +0 -62
  116. package/skills/wix-headless-replatform/resources/rp-qa-gap-loop/SKILL.md +0 -64
  117. package/skills/wix-headless-replatform/resources/rp-source-evidence/SKILL.md +0 -42
  118. package/skills/wix-headless-replatform/resources/rp-ui-implementation/SKILL.md +0 -73
  119. package/skills/wix-headless-replatform/schemas/build-plan.schema.json +0 -10
  120. package/skills/wix-headless-replatform/schemas/candidate.schema.json +0 -19
  121. package/skills/wix-headless-replatform/schemas/common.schema.json +0 -33
  122. package/skills/wix-headless-replatform/schemas/decision-patch.schema.json +0 -10
  123. package/skills/wix-headless-replatform/schemas/decision-request.schema.json +0 -10
  124. package/skills/wix-headless-replatform/schemas/extraction-gap.schema.json +0 -28
  125. package/skills/wix-headless-replatform/schemas/extraction-manifest.schema.json +0 -34
  126. package/skills/wix-headless-replatform/schemas/final-report.schema.json +0 -10
  127. package/skills/wix-headless-replatform/schemas/foundation.schema.json +0 -11
  128. package/skills/wix-headless-replatform/schemas/metadata.schema.json +0 -11
  129. package/skills/wix-headless-replatform/schemas/observation-packet.schema.json +0 -17
  130. package/skills/wix-headless-replatform/schemas/page-capture.schema.json +0 -11
  131. package/skills/wix-headless-replatform/schemas/page-resolution.schema.json +0 -33
  132. package/skills/wix-headless-replatform/schemas/shared-chrome.schema.json +0 -11
  133. package/skills/wix-headless-replatform/schemas/unit.schema.json +0 -40
  134. package/skills/wix-headless-replatform/scripts/assemble-extraction.mjs +0 -844
  135. package/skills/wix-headless-replatform/scripts/benchmark-extraction.mjs +0 -163
  136. package/skills/wix-headless-replatform/scripts/browser-extraction-preflight.mjs +0 -42
  137. package/skills/wix-headless-replatform/scripts/build-extracted-homepage.mjs +0 -228
  138. package/skills/wix-headless-replatform/scripts/clear-wix-starter.mjs +0 -87
  139. package/skills/wix-headless-replatform/scripts/create-wix-project.mjs +0 -505
  140. package/skills/wix-headless-replatform/scripts/discover-urls.mjs +0 -142
  141. package/skills/wix-headless-replatform/scripts/extract-assets.mjs +0 -140
  142. package/skills/wix-headless-replatform/scripts/extract-design-system.mjs +0 -637
  143. package/skills/wix-headless-replatform/scripts/extract-interactions.mjs +0 -1903
  144. package/skills/wix-headless-replatform/scripts/extract-page.mjs +0 -2461
  145. package/skills/wix-headless-replatform/scripts/extract-seo.mjs +0 -25
  146. package/skills/wix-headless-replatform/scripts/extract-tokens.mjs +0 -63
  147. package/skills/wix-headless-replatform/scripts/finalize-extraction-report.mjs +0 -126
  148. package/skills/wix-headless-replatform/scripts/finalize-gap-review.mjs +0 -180
  149. package/skills/wix-headless-replatform/scripts/finalize-gap-review.test.mjs +0 -98
  150. package/skills/wix-headless-replatform/scripts/finalize-migration-website.mjs +0 -103
  151. package/skills/wix-headless-replatform/scripts/generate-control-state-contract.mjs +0 -176
  152. package/skills/wix-headless-replatform/scripts/generate-design-md.mjs +0 -261
  153. package/skills/wix-headless-replatform/scripts/generate-extraction-validators.mjs +0 -25
  154. package/skills/wix-headless-replatform/scripts/generate-invoice-download-backend.mjs +0 -342
  155. package/skills/wix-headless-replatform/scripts/generate-layout-blueprint.mjs +0 -140
  156. package/skills/wix-headless-replatform/scripts/generate-repeater-cms.mjs +0 -22
  157. package/skills/wix-headless-replatform/scripts/generate-route-plan.mjs +0 -143
  158. package/skills/wix-headless-replatform/scripts/generate-scene-contract.mjs +0 -288
  159. package/skills/wix-headless-replatform/scripts/generate-ui-normalization.mjs +0 -266
  160. package/skills/wix-headless-replatform/scripts/generate-visual-assets.mjs +0 -111
  161. package/skills/wix-headless-replatform/scripts/lib/browser-tooling.mjs +0 -570
  162. package/skills/wix-headless-replatform/scripts/lib/common.mjs +0 -329
  163. package/skills/wix-headless-replatform/scripts/lib/component-capabilities.mjs +0 -121
  164. package/skills/wix-headless-replatform/scripts/lib/component-registry.mjs +0 -282
  165. package/skills/wix-headless-replatform/scripts/lib/content-boundary.mjs +0 -61
  166. package/skills/wix-headless-replatform/scripts/lib/extraction-contract.mjs +0 -374
  167. package/skills/wix-headless-replatform/scripts/lib/extraction-detectors.mjs +0 -243
  168. package/skills/wix-headless-replatform/scripts/lib/extraction-validators.generated.mjs +0 -1139
  169. package/skills/wix-headless-replatform/scripts/lib/font-contract.mjs +0 -326
  170. package/skills/wix-headless-replatform/scripts/lib/frontend-automation-state.mjs +0 -184
  171. package/skills/wix-headless-replatform/scripts/lib/gap-analysis.mjs +0 -396
  172. package/skills/wix-headless-replatform/scripts/lib/html-extract.mjs +0 -168
  173. package/skills/wix-headless-replatform/scripts/lib/interaction-bootstrap.mjs +0 -10
  174. package/skills/wix-headless-replatform/scripts/lib/interaction-runtime.mjs +0 -194
  175. package/skills/wix-headless-replatform/scripts/lib/interaction-timeline.mjs +0 -348
  176. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/classifiers.mjs +0 -141
  177. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/geometry.mjs +0 -43
  178. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/vocabulary.mjs +0 -18
  179. package/skills/wix-headless-replatform/scripts/lib/ui-normalization.css +0 -64
  180. package/skills/wix-headless-replatform/scripts/optimize-svg.mjs +0 -31
  181. package/skills/wix-headless-replatform/scripts/post-build-gap.mjs +0 -358
  182. package/skills/wix-headless-replatform/scripts/provision-repeater-cms.mjs +0 -25
  183. package/skills/wix-headless-replatform/scripts/record-gap-decision.mjs +0 -39
  184. package/skills/wix-headless-replatform/scripts/replay-extraction.mjs +0 -107
  185. package/skills/wix-headless-replatform/scripts/resolve-home-page.mjs +0 -96
  186. package/skills/wix-headless-replatform/scripts/site-clone.mjs +0 -658
  187. package/skills/wix-headless-replatform/scripts/validate-font-contract.mjs +0 -29
  188. package/skills/wix-headless-replatform/scripts/verify-interactions.mjs +0 -669
  189. package/skills/wix-headless-replatform/scripts/visual-qa.mjs +0 -370
  190. package/skills/wix-import/SKILL.md +0 -90
  191. package/skills/wix-replatform/.publish-manifest.json +0 -8
  192. package/skills/wix-replatform/CLI.md +0 -162
  193. package/skills/wix-replatform/README.md +0 -52
  194. package/skills/wix-replatform/SKILL.md +0 -238
  195. package/skills/wix-replatform/console/account.css +0 -1
  196. package/skills/wix-replatform/console/app.css +0 -1
  197. package/skills/wix-replatform/console/app.js +0 -117
  198. package/skills/wix-replatform/console/index.html +0 -4
  199. package/skills/wix-replatform/console/json.css +0 -11
  200. package/skills/wix-replatform/lib/agent-adapters/index.js +0 -71
  201. package/skills/wix-replatform/lib/app-page-routing.js +0 -75
  202. package/skills/wix-replatform/lib/artifact-freshness.js +0 -225
  203. package/skills/wix-replatform/lib/blocked-data-requests.js +0 -427
  204. package/skills/wix-replatform/lib/census-reconciliation.js +0 -426
  205. package/skills/wix-replatform/lib/completion-report.js +0 -1580
  206. package/skills/wix-replatform/lib/config-env.js +0 -133
  207. package/skills/wix-replatform/lib/confirmed-pictures.js +0 -212
  208. package/skills/wix-replatform/lib/dependency-readiness.js +0 -423
  209. package/skills/wix-replatform/lib/dependency-recovery.js +0 -21
  210. package/skills/wix-replatform/lib/destination-choice.js +0 -163
  211. package/skills/wix-replatform/lib/destination-handoff.js +0 -62
  212. package/skills/wix-replatform/lib/destination-http.js +0 -81
  213. package/skills/wix-replatform/lib/destination-route.js +0 -98
  214. package/skills/wix-replatform/lib/destination.js +0 -919
  215. package/skills/wix-replatform/lib/discovered-census.js +0 -231
  216. package/skills/wix-replatform/lib/discovered-set-status.js +0 -255
  217. package/skills/wix-replatform/lib/document-url-guard.js +0 -203
  218. package/skills/wix-replatform/lib/entity-qa-attestation.js +0 -339
  219. package/skills/wix-replatform/lib/entity-verification.js +0 -18
  220. package/skills/wix-replatform/lib/execution-capability.js +0 -120
  221. package/skills/wix-replatform/lib/execution-log.js +0 -170
  222. package/skills/wix-replatform/lib/execution-manifest.js +0 -203
  223. package/skills/wix-replatform/lib/execution-state.js +0 -195
  224. package/skills/wix-replatform/lib/expectations-ledger.js +0 -96
  225. package/skills/wix-replatform/lib/generated-plugin-handoff.js +0 -140
  226. package/skills/wix-replatform/lib/import-readiness-contract.js +0 -23
  227. package/skills/wix-replatform/lib/import-recovery.js +0 -1107
  228. package/skills/wix-replatform/lib/imported-redirect-targets.js +0 -608
  229. package/skills/wix-replatform/lib/internal-link-reconciliation.js +0 -166
  230. package/skills/wix-replatform/lib/link-audit.js +0 -173
  231. package/skills/wix-replatform/lib/link-census.js +0 -194
  232. package/skills/wix-replatform/lib/link-plan.js +0 -148
  233. package/skills/wix-replatform/lib/link-verification.js +0 -274
  234. package/skills/wix-replatform/lib/link-write-journal.js +0 -42
  235. package/skills/wix-replatform/lib/local-state.js +0 -1481
  236. package/skills/wix-replatform/lib/member-completion.js +0 -658
  237. package/skills/wix-replatform/lib/member-crosswalk.js +0 -69
  238. package/skills/wix-replatform/lib/member-outcome-registry.js +0 -265
  239. package/skills/wix-replatform/lib/migration-completion.js +0 -311
  240. package/skills/wix-replatform/lib/operator-identity.js +0 -47
  241. package/skills/wix-replatform/lib/orchestration-decisions.js +0 -248
  242. package/skills/wix-replatform/lib/orchestration-preflight.js +0 -525
  243. package/skills/wix-replatform/lib/orchestration-router.js +0 -698
  244. package/skills/wix-replatform/lib/orchestration-state.js +0 -631
  245. package/skills/wix-replatform/lib/order-reference-readiness.js +0 -30
  246. package/skills/wix-replatform/lib/payments-outcome-registry.js +0 -200
  247. package/skills/wix-replatform/lib/plugin-cms-fallback.js +0 -618
  248. package/skills/wix-replatform/lib/preservation-approval-stamp.js +0 -54
  249. package/skills/wix-replatform/lib/product-media-deferral.js +0 -96
  250. package/skills/wix-replatform/lib/progress-log.js +0 -240
  251. package/skills/wix-replatform/lib/progress-log.sh +0 -140
  252. package/skills/wix-replatform/lib/read-back-approval.js +0 -184
  253. package/skills/wix-replatform/lib/read-back-comparison.js +0 -136
  254. package/skills/wix-replatform/lib/read-back-contract.js +0 -243
  255. package/skills/wix-replatform/lib/read-back-extract.js +0 -118
  256. package/skills/wix-replatform/lib/read-back-gate.js +0 -734
  257. package/skills/wix-replatform/lib/read-back-reads.js +0 -94
  258. package/skills/wix-replatform/lib/read-back-state.js +0 -107
  259. package/skills/wix-replatform/lib/read-back-summary.js +0 -81
  260. package/skills/wix-replatform/lib/rerun-conflicts.js +0 -334
  261. package/skills/wix-replatform/lib/run-controller.js +0 -401
  262. package/skills/wix-replatform/lib/seo-outcome-registry.js +0 -45
  263. package/skills/wix-replatform/lib/setup-verification.js +0 -148
  264. package/skills/wix-replatform/lib/source-access.js +0 -231
  265. package/skills/wix-replatform/lib/source-coverage.js +0 -1130
  266. package/skills/wix-replatform/lib/source-secrets.js +0 -277
  267. package/skills/wix-replatform/lib/structured-link-patch.js +0 -59
  268. package/skills/wix-replatform/lib/task-state.js +0 -110
  269. package/skills/wix-replatform/lib/url-preservation-report.js +0 -319
  270. package/skills/wix-replatform/lib/url-preservation-state.js +0 -739
  271. package/skills/wix-replatform/lib/url-redirect-plan.js +0 -728
  272. package/skills/wix-replatform/lib/url-verification.js +0 -315
  273. package/skills/wix-replatform/lib/user-action-effects.js +0 -42
  274. package/skills/wix-replatform/lib/user-actions.js +0 -264
  275. package/skills/wix-replatform/lib/website-handoff.js +0 -1220
  276. package/skills/wix-replatform/lib/wix-client-callers.js +0 -54
  277. package/skills/wix-replatform/lib/wix-dashboard-url.js +0 -35
  278. package/skills/wix-replatform/lib/write-verification-state.js +0 -92
  279. package/skills/wix-replatform/lib/write-verification.js +0 -274
  280. package/skills/wix-replatform/resources/rp-destination/SKILL.md +0 -137
  281. package/skills/wix-replatform/resources/rp-discovery/SKILL.md +0 -357
  282. package/skills/wix-replatform/resources/rp-discovery/scripts/promote-source-coverage.js +0 -47
  283. package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +0 -1369
  284. package/skills/wix-replatform/resources/rp-execute-import/scripts/shipping-estimate-audit.js +0 -70
  285. package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +0 -482
  286. package/skills/wix-replatform/resources/rp-execute-setup/scripts/execute-setup.js +0 -442
  287. package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +0 -64
  288. package/skills/wix-replatform/resources/rp-execution-policy/SKILL.md +0 -112
  289. package/skills/wix-replatform/resources/rp-execution-policy/lib/coupon-currency-plan-report.js +0 -143
  290. package/skills/wix-replatform/resources/rp-execution-policy/lib/payments-report.js +0 -244
  291. package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +0 -3158
  292. package/skills/wix-replatform/resources/rp-mapper/SKILL.md +0 -947
  293. package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +0 -217
  294. package/skills/wix-replatform/resources/rp-mapper/lib/structure-bridge-planning.js +0 -303
  295. package/skills/wix-replatform/resources/rp-mapper/scripts/coverage-reconcile.js +0 -88
  296. package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +0 -148
  297. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +0 -378
  298. package/skills/wix-replatform/resources/rp-preflight/SKILL.md +0 -40
  299. package/skills/wix-replatform/resources/rp-project-intake/SKILL.md +0 -55
  300. package/skills/wix-replatform/resources/rp-quick-runtime/SKILL.md +0 -60
  301. package/skills/wix-replatform/resources/rp-quick-runtime/lib/import-progress.js +0 -89
  302. package/skills/wix-replatform/resources/rp-quick-runtime/lib/limit-recovery.js +0 -36
  303. package/skills/wix-replatform/resources/rp-quick-shopify/SKILL.md +0 -123
  304. package/skills/wix-replatform/resources/rp-quick-shopify/quick-mode.json +0 -124
  305. package/skills/wix-replatform/resources/rp-quick-shopify/scripts/quick-mode.js +0 -522
  306. package/skills/wix-replatform/resources/rp-quick-woocommerce/SKILL.md +0 -56
  307. package/skills/wix-replatform/resources/rp-quick-woocommerce/quick-mode.json +0 -91
  308. package/skills/wix-replatform/resources/rp-quick-woocommerce/scripts/quick-mode.js +0 -255
  309. package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +0 -253
  310. package/skills/wix-replatform/resources/rp-setup-discovery/scripts/quick-setup-plan.js +0 -44
  311. package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +0 -481
  312. package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +0 -136
  313. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
  314. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +0 -310
  315. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +0 -1081
  316. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +0 -618
  317. package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +0 -969
  318. package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +0 -196
  319. package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +0 -66
  320. package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +0 -60
  321. package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +0 -95
  322. package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +0 -82
  323. package/skills/wix-replatform/resources/rp-source-inputs/SKILL.md +0 -66
  324. package/skills/wix-replatform/resources/rp-source-sfcc/SKILL.md +0 -153
  325. package/skills/wix-replatform/resources/rp-source-shopify/SKILL.md +0 -394
  326. package/skills/wix-replatform/resources/rp-source-shopify/lib/discovery-reads.js +0 -200
  327. package/skills/wix-replatform/resources/rp-source-shopify/lib/import-findings.js +0 -34
  328. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-bulk-sqlite-worker.js +0 -44
  329. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-bulk.js +0 -1470
  330. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-cli.js +0 -446
  331. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-gift-cards.js +0 -474
  332. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-protected-fields.js +0 -879
  333. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-session.js +0 -426
  334. package/skills/wix-replatform/resources/rp-source-shopify/queries/articles.graphql +0 -24
  335. package/skills/wix-replatform/resources/rp-source-shopify/queries/blogs.graphql +0 -18
  336. package/skills/wix-replatform/resources/rp-source-shopify/queries/collections.graphql +0 -40
  337. package/skills/wix-replatform/resources/rp-source-shopify/queries/customers.graphql +0 -76
  338. package/skills/wix-replatform/resources/rp-source-shopify/queries/delivery-profiles.graphql +0 -51
  339. package/skills/wix-replatform/resources/rp-source-shopify/queries/discounts.graphql +0 -35
  340. package/skills/wix-replatform/resources/rp-source-shopify/queries/files.graphql +0 -20
  341. package/skills/wix-replatform/resources/rp-source-shopify/queries/gift-cards.graphql +0 -18
  342. package/skills/wix-replatform/resources/rp-source-shopify/queries/inventory.graphql +0 -31
  343. package/skills/wix-replatform/resources/rp-source-shopify/queries/locations.graphql +0 -21
  344. package/skills/wix-replatform/resources/rp-source-shopify/queries/menus.graphql +0 -21
  345. package/skills/wix-replatform/resources/rp-source-shopify/queries/metaobjects.graphql +0 -30
  346. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-core.graphql +0 -150
  347. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-fulfillments.graphql +0 -36
  348. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-refunds.graphql +0 -48
  349. package/skills/wix-replatform/resources/rp-source-shopify/queries/pages.graphql +0 -20
  350. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-address.graphql +0 -8
  351. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-email.graphql +0 -6
  352. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-name.graphql +0 -8
  353. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-phone.graphql +0 -8
  354. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-address.graphql +0 -12
  355. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-email.graphql +0 -6
  356. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-name.graphql +0 -13
  357. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-phone.graphql +0 -13
  358. package/skills/wix-replatform/resources/rp-source-shopify/queries/products.graphql +0 -73
  359. package/skills/wix-replatform/resources/rp-source-shopify/queries/url-redirects.graphql +0 -13
  360. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-discovery.js +0 -693
  361. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-extract.js +0 -283
  362. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-gift-card-remedy.js +0 -191
  363. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-session-check.js +0 -115
  364. package/skills/wix-replatform/resources/rp-source-shopify/source-schema.example.json +0 -201
  365. package/skills/wix-replatform/resources/rp-source-wordpress/PLUGIN-READ-PLANS.md +0 -146
  366. package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +0 -970
  367. package/skills/wix-replatform/resources/rp-source-wordpress/lib/blocked-data-handlers.js +0 -73
  368. package/skills/wix-replatform/resources/rp-source-wordpress/lib/checkout-field-csv-parser.js +0 -115
  369. package/skills/wix-replatform/resources/rp-source-wordpress/lib/checkout-field-csv-parser.test-fixture.js +0 -91
  370. package/skills/wix-replatform/resources/rp-source-wordpress/lib/coupon-discovery.js +0 -440
  371. package/skills/wix-replatform/resources/rp-source-wordpress/lib/currency-gate.js +0 -125
  372. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-source-keys.js +0 -252
  373. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-source-keys.json +0 -183
  374. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-summary.mjs +0 -333
  375. package/skills/wix-replatform/resources/rp-source-wordpress/lib/invoice-discovery.js +0 -426
  376. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-disposition.js +0 -400
  377. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-entity-read-plan.js +0 -633
  378. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-knowledge.js +0 -1127
  379. package/skills/wix-replatform/resources/rp-source-wordpress/lib/refund-corroboration.js +0 -194
  380. package/skills/wix-replatform/resources/rp-source-wordpress/lib/refund-corroboration.json +0 -100
  381. package/skills/wix-replatform/resources/rp-source-wordpress/lib/sampled-ids-batch.js +0 -157
  382. package/skills/wix-replatform/resources/rp-source-wordpress/lib/secret-value-guard.js +0 -234
  383. package/skills/wix-replatform/resources/rp-source-wordpress/lib/store-currency.js +0 -101
  384. package/skills/wix-replatform/resources/rp-source-wordpress/lib/structure-bridge-reader.js +0 -755
  385. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wix-wp-plugin-v2-client.js +0 -1074
  386. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wix-wp-plugin-v2-client.test-fixture.js +0 -149
  387. package/skills/wix-replatform/resources/rp-source-wordpress/lib/woo-inventory.js +0 -25
  388. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +0 -444
  389. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-image-url.js +0 -186
  390. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-plugin-detect.js +0 -1422
  391. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-redirect-sources.js +0 -343
  392. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +0 -680
  393. package/skills/wix-replatform/resources/rp-source-wordpress/lib/yoast-product-seo-evidence.js +0 -272
  394. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/README.md +0 -373
  395. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/advanced-custom-fields.json +0 -101
  396. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/back-in-stock-notifier-for-woocommerce.json +0 -81
  397. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/capabilities-pending-decision.json +0 -128
  398. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/cms-fallback-eligible.json +0 -18
  399. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/contact-form-7.json +0 -104
  400. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/facebook-for-woocommerce.json +0 -44
  401. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/fingerprint-aliases.json +0 -49
  402. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/free-gifts-for-woocommerce.json +0 -94
  403. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/index.json +0 -863
  404. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/mailpoet.json +0 -52
  405. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/membership-for-woocommerce.json +0 -161
  406. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/mwb-bookings-for-woocommerce.json +0 -180
  407. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/no-migration-needed.json +0 -286
  408. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/pricing-deals-for-woocommerce.json +0 -79
  409. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/product-extras-for-woocommerce.json +0 -120
  410. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/pw-woocommerce-gift-cards.json +0 -128
  411. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/requires-development.json +0 -88
  412. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/seo-by-rank-math.json +0 -80
  413. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/seriously-simple-podcasting.json +0 -46
  414. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/strong-testimonials.json +0 -55
  415. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/subscriptions-for-woocommerce.json +0 -99
  416. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/tablepress.json +0 -55
  417. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/the-events-calendar.json +0 -160
  418. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/ti-woocommerce-wishlist.json +0 -81
  419. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-checkout-field-editor-pro.json +0 -60
  420. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-discount-rules.json +0 -74
  421. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-product-bundle.json +0 -75
  422. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-gift-cards.json +0 -60
  423. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-other-payment-gateway.json +0 -44
  424. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-pdf-invoices-packing-slips.json +0 -57
  425. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-product-addon.json +0 -141
  426. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-progressive-discounts.json +0 -54
  427. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wordpress-seo.json +0 -158
  428. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wpc-composite-products.json +0 -97
  429. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wpforms-lite.json +0 -86
  430. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/capture-store-settings.js +0 -90
  431. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/plugin-knowledge-validate.js +0 -51
  432. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/plugin-knowledge.js +0 -103
  433. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +0 -2409
  434. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-plugin-inventory.js +0 -273
  435. package/skills/wix-replatform/resources/rp-source-wordpress/secret-value-patterns.v1.json +0 -11
  436. package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +0 -71
  437. package/skills/wix-replatform/resources/rp-source-wordpress/sub-parts.json +0 -13
  438. package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +0 -1046
  439. package/skills/wix-replatform/resources/rp-target-wix/app-page-routing-capabilities.json +0 -36
  440. package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +0 -57
  441. package/skills/wix-replatform/resources/rp-target-wix/domains/SERVICE-PLUGINS.md +0 -322
  442. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/docs-survey.json +0 -70
  443. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +0 -29
  444. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +0 -71
  445. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +0 -83
  446. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +0 -95
  447. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +0 -66
  448. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/docs-survey.json +0 -332
  449. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/domain.json +0 -75
  450. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/booking.json +0 -181
  451. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/service-add-on.json +0 -130
  452. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/service.json +0 -180
  453. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/docs-survey.json +0 -161
  454. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +0 -25
  455. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +0 -67
  456. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +0 -75
  457. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +0 -41
  458. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/docs-survey.json +0 -204
  459. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +0 -27
  460. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +0 -275
  461. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +0 -105
  462. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +0 -77
  463. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/docs-survey.json +0 -297
  464. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +0 -44
  465. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/delivery-profile.json +0 -171
  466. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/discount-rule.json +0 -182
  467. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-applied-discount.json +0 -129
  468. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-invoice-document.json +0 -192
  469. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item-options.json +0 -123
  470. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +0 -85
  471. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-merchant-note.json +0 -112
  472. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-payment.json +0 -191
  473. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +0 -164
  474. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +0 -462
  475. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/pickup-location.json +0 -122
  476. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/shipping-option.json +0 -98
  477. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/wishlist-item.json +0 -86
  478. package/skills/wix-replatform/resources/rp-target-wix/domains/events/docs-survey.json +0 -128
  479. package/skills/wix-replatform/resources/rp-target-wix/domains/events/domain.json +0 -38
  480. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/category.json +0 -73
  481. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/event.json +0 -107
  482. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/registration-form.json +0 -89
  483. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/rsvp.json +0 -118
  484. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/ticket-definition.json +0 -93
  485. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/docs-survey.json +0 -86
  486. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/domain.json +0 -56
  487. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/entities/form-submission.json +0 -121
  488. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/entities/form.json +0 -134
  489. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/docs-survey.json +0 -41
  490. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/domain.json +0 -50
  491. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/entities/gift-card-product.json +0 -87
  492. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/entities/gift-card.json +0 -130
  493. package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +0 -1418
  494. package/skills/wix-replatform/resources/rp-target-wix/domains/media/docs-survey.json +0 -41
  495. package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +0 -24
  496. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +0 -75
  497. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +0 -71
  498. package/skills/wix-replatform/resources/rp-target-wix/domains/members/docs-survey.json +0 -119
  499. package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +0 -23
  500. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +0 -71
  501. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/custom-field.json +0 -82
  502. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member-about.json +0 -77
  503. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +0 -205
  504. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/docs-survey.json +0 -41
  505. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/domain.json +0 -46
  506. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/entities/plan-order.json +0 -137
  507. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/entities/plan.json +0 -133
  508. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/docs-survey.json +0 -7
  509. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/domain.json +0 -36
  510. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/amazon-shop-connect.json +0 -71
  511. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/ebay-shop-connect.json +0 -67
  512. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/google-youtube-connect.json +0 -72
  513. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/meta-catalog-connect.json +0 -74
  514. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/pinterest-catalog-connect.json +0 -69
  515. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/tiktok-catalog-connect.json +0 -61
  516. package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +0 -111
  517. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/docs-survey.json +0 -109
  518. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/domain.json +0 -73
  519. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/item-seo-tags.json +0 -148
  520. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/seo-pattern.json +0 -91
  521. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/site-seo-tags.json +0 -79
  522. package/skills/wix-replatform/resources/rp-target-wix/domains/site/docs-survey.json +0 -32
  523. package/skills/wix-replatform/resources/rp-target-wix/domains/site/domain.json +0 -49
  524. package/skills/wix-replatform/resources/rp-target-wix/domains/site/entities/business-contact.json +0 -103
  525. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/docs-survey.json +0 -203
  526. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +0 -42
  527. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/back-in-stock-request.json +0 -119
  528. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/brand.json +0 -111
  529. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +0 -81
  530. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +0 -241
  531. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +0 -118
  532. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-customization.json +0 -111
  533. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +0 -79
  534. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +0 -221
  535. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/promotion.json +0 -84
  536. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/review.json +0 -178
  537. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/subscription-product.json +0 -87
  538. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/docs-survey.json +0 -106
  539. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/domain.json +0 -64
  540. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/manual-tax-mapping.json +0 -119
  541. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-group.json +0 -94
  542. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-region.json +0 -113
  543. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-settings.json +0 -65
  544. package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +0 -64
  545. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-author-attribution.js +0 -165
  546. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-client.js +0 -60
  547. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-duplicates.js +0 -201
  548. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-ledger.js +0 -306
  549. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-report.js +0 -229
  550. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-stage.js +0 -55
  551. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build.js +0 -715
  552. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-media.js +0 -567
  553. package/skills/wix-replatform/resources/rp-target-wix/lib/bulk-results.js +0 -73
  554. package/skills/wix-replatform/resources/rp-target-wix/lib/contact-extended-fields.js +0 -194
  555. package/skills/wix-replatform/resources/rp-target-wix/lib/contact-import.js +0 -133
  556. package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +0 -150
  557. package/skills/wix-replatform/resources/rp-target-wix/lib/coupon-redemption-drift.js +0 -491
  558. package/skills/wix-replatform/resources/rp-target-wix/lib/customer-member.js +0 -104
  559. package/skills/wix-replatform/resources/rp-target-wix/lib/data-extension-schema.js +0 -673
  560. package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +0 -835
  561. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-balance-reconciliation.js +0 -119
  562. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-build.js +0 -566
  563. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-redemption-build.js +0 -249
  564. package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +0 -260
  565. package/skills/wix-replatform/resources/rp-target-wix/lib/order-applied-discount-build.js +0 -63
  566. package/skills/wix-replatform/resources/rp-target-wix/lib/order-buyer.js +0 -187
  567. package/skills/wix-replatform/resources/rp-target-wix/lib/order-channel-build.js +0 -64
  568. package/skills/wix-replatform/resources/rp-target-wix/lib/order-history.js +0 -1027
  569. package/skills/wix-replatform/resources/rp-target-wix/lib/order-invoice-contract.js +0 -90
  570. package/skills/wix-replatform/resources/rp-target-wix/lib/order-payment-mapping.js +0 -420
  571. package/skills/wix-replatform/resources/rp-target-wix/lib/pricing-plan-definition.js +0 -177
  572. package/skills/wix-replatform/resources/rp-target-wix/lib/product-import.js +0 -151
  573. package/skills/wix-replatform/resources/rp-target-wix/lib/product-seo.js +0 -723
  574. package/skills/wix-replatform/resources/rp-target-wix/lib/seo-redirects.js +0 -353
  575. package/skills/wix-replatform/resources/rp-target-wix/lib/shipping-build.js +0 -1437
  576. package/skills/wix-replatform/resources/rp-target-wix/lib/shipping-option-stage.js +0 -354
  577. package/skills/wix-replatform/resources/rp-target-wix/lib/store-config-build.js +0 -134
  578. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-category-attach.js +0 -221
  579. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-inventory.js +0 -248
  580. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +0 -321
  581. package/skills/wix-replatform/resources/rp-target-wix/lib/tax-build.js +0 -231
  582. package/skills/wix-replatform/resources/rp-target-wix/lib/url-mapper-transport.js +0 -28
  583. package/skills/wix-replatform/resources/rp-target-wix/lib/value-utils.js +0 -14
  584. package/skills/wix-replatform/resources/rp-target-wix/lib/variant-correlation.js +0 -34
  585. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +0 -388
  586. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +0 -255
  587. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +0 -6041
  588. package/skills/wix-replatform/resources/rp-target-wix/lib/write-verification.js +0 -3
  589. package/skills/wix-replatform/resources/rp-target-wix/scripts/docs-survey-sync.js +0 -150
  590. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +0 -69
  591. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +0 -100
  592. package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +0 -112
  593. package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +0 -484
  594. package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +0 -318
  595. package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +0 -2831
  596. package/skills/wix-replatform/resources/rp-telemetry/lib/transcript-digest.js +0 -318
  597. package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +0 -83
  598. package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +0 -243
  599. package/skills/wix-replatform/resources/rp-website-continuation/SKILL.md +0 -94
  600. package/skills/wix-replatform/scripts/artifact-freshness.js +0 -76
  601. package/skills/wix-replatform/scripts/census-reconciliation.js +0 -25
  602. package/skills/wix-replatform/scripts/cms-fallback.js +0 -89
  603. package/skills/wix-replatform/scripts/discovered-census.js +0 -26
  604. package/skills/wix-replatform/scripts/discovered-set-status.js +0 -33
  605. package/skills/wix-replatform/scripts/entity-qa-attestation.js +0 -130
  606. package/skills/wix-replatform/scripts/execution-health-check.js +0 -415
  607. package/skills/wix-replatform/scripts/execution-manifest-validate.js +0 -43
  608. package/skills/wix-replatform/scripts/execution-state-prepare.js +0 -128
  609. package/skills/wix-replatform/scripts/expectations-ledger.js +0 -44
  610. package/skills/wix-replatform/scripts/import-contract-verify.js +0 -183
  611. package/skills/wix-replatform/scripts/internal-link-audit.js +0 -90
  612. package/skills/wix-replatform/scripts/item-seo-tags-verify.js +0 -205
  613. package/skills/wix-replatform/scripts/migration-completion.js +0 -76
  614. package/skills/wix-replatform/scripts/orchestration-preflight.js +0 -67
  615. package/skills/wix-replatform/scripts/orchestration-route.js +0 -77
  616. package/skills/wix-replatform/scripts/orchestration-state.js +0 -381
  617. package/skills/wix-replatform/scripts/read-back-gate.js +0 -175
  618. package/skills/wix-replatform/scripts/replatform-console.js +0 -146
  619. package/skills/wix-replatform/scripts/replatform.js +0 -436
  620. package/skills/wix-replatform/scripts/source-secrets.js +0 -77
  621. package/skills/wix-replatform/scripts/url-redirects.js +0 -286
  622. package/skills/wix-replatform/scripts/user-action.js +0 -58
  623. package/skills/wix-replatform/scripts/website-handoff-generate.js +0 -64
  624. package/skills/wix-replatform/scripts/wix-dashboard-url.js +0 -54
  625. package/skills/wix-replatform/scripts/wix-destination.js +0 -143
  626. package/skills/wix-replatform/scripts/wix-headless-scaffold.js +0 -762
  627. package/skills/wix-vibe-headless/SKILL.md +0 -183
  628. package/skills/wix-vibe-headless/install/deploy.cjs +0 -221
  629. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +0 -35
  630. package/skills/wix-vibe-headless/platforms/README.md +0 -26
  631. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +0 -127
  632. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +0 -121
  633. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +0 -87
  634. package/skills/wix-vibe-headless/platforms/base44.md +0 -148
  635. package/skills/wix-vibe-headless/platforms/generic.md +0 -132
  636. package/skills/wix-vibe-headless/references/_shared/nav/nav.tanstack.js +0 -30
  637. package/skills/wix-vibe-headless/references/_shared/routing.md +0 -86
  638. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +0 -270
  639. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +0 -43
  640. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +0 -25
  641. package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +0 -15
  642. package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +0 -35
  643. package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +0 -38
  644. package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +0 -40
  645. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +0 -54
  646. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +0 -65
  647. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +0 -50
  648. package/skills/wix-vibe-headless/references/blog/app/rest/wix-blog.js +0 -217
  649. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +0 -99
  650. package/skills/wix-vibe-headless/references/blog/seed/seed-blog.cjs +0 -269
  651. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +0 -342
  652. package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +0 -65
  653. package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +0 -67
  654. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +0 -47
  655. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +0 -13
  656. package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +0 -126
  657. package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +0 -128
  658. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +0 -110
  659. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +0 -58
  660. package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +0 -95
  661. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +0 -94
  662. package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +0 -89
  663. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +0 -148
  664. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +0 -250
  665. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +0 -300
  666. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +0 -154
  667. package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.cjs +0 -333
  668. package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.cjs +0 -267
  669. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +0 -178
  670. package/skills/wix-vibe-headless/references/cms/app/collection.config.js +0 -31
  671. package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +0 -18
  672. package/skills/wix-vibe-headless/references/cms/app/rest/wix-cms.js +0 -231
  673. package/skills/wix-vibe-headless/references/cms/seed/SEED.md +0 -145
  674. package/skills/wix-vibe-headless/references/donations/INSTRUCTIONS.md +0 -88
  675. package/skills/wix-vibe-headless/references/donations/app/rest/wix-donations.js +0 -112
  676. package/skills/wix-vibe-headless/references/donations/seed/SEED.md +0 -11
  677. package/skills/wix-vibe-headless/references/donations/tests/donations.test.mjs +0 -258
  678. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +0 -267
  679. package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +0 -23
  680. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +0 -43
  681. package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +0 -13
  682. package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +0 -29
  683. package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +0 -57
  684. package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +0 -78
  685. package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +0 -27
  686. package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +0 -54
  687. package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +0 -40
  688. package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +0 -81
  689. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +0 -48
  690. package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +0 -36
  691. package/skills/wix-vibe-headless/references/events/app/rest/wix-events-browse.js +0 -136
  692. package/skills/wix-vibe-headless/references/events/app/rest/wix-events-registration.js +0 -187
  693. package/skills/wix-vibe-headless/references/events/seed/SEED.md +0 -103
  694. package/skills/wix-vibe-headless/references/events/seed/seed-events.cjs +0 -251
  695. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +0 -487
  696. package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +0 -425
  697. package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +0 -187
  698. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +0 -238
  699. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +0 -108
  700. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +0 -1836
  701. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +0 -328
  702. package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +0 -101
  703. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +0 -33
  704. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +0 -21
  705. package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +0 -29
  706. package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +0 -54
  707. package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +0 -77
  708. package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +0 -36
  709. package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +0 -32
  710. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +0 -35
  711. package/skills/wix-vibe-headless/references/members/app/rest/wix-members-auth.js +0 -390
  712. package/skills/wix-vibe-headless/references/members/install/Register.jsx +0 -22
  713. package/skills/wix-vibe-headless/references/members/seed/SEED.md +0 -21
  714. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +0 -270
  715. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +0 -31
  716. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +0 -15
  717. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +0 -39
  718. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +0 -15
  719. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +0 -29
  720. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +0 -35
  721. package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +0 -27
  722. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +0 -25
  723. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +0 -39
  724. package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +0 -27
  725. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +0 -60
  726. package/skills/wix-vibe-headless/references/portfolio/app/rest/wix-portfolio.js +0 -223
  727. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +0 -90
  728. package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.cjs +0 -236
  729. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +0 -280
  730. package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +0 -35
  731. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +0 -48
  732. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +0 -16
  733. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +0 -35
  734. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +0 -25
  735. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +0 -28
  736. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +0 -30
  737. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +0 -30
  738. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +0 -53
  739. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +0 -28
  740. package/skills/wix-vibe-headless/references/pricing-plans/app/rest/wix-pricing-plans.js +0 -157
  741. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +0 -82
  742. package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.cjs +0 -251
  743. package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +0 -13
  744. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +0 -290
  745. package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +0 -81
  746. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +0 -71
  747. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +0 -43
  748. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +0 -21
  749. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +0 -72
  750. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +0 -66
  751. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +0 -32
  752. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +0 -73
  753. package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +0 -28
  754. package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +0 -102
  755. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-menu.js +0 -224
  756. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +0 -218
  757. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-reservations.js +0 -107
  758. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +0 -176
  759. package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.cjs +0 -452
  760. package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +0 -56
  761. package/skills/wix-vibe-headless/references/shared/app/lib/nav.js +0 -9
  762. package/skills/wix-vibe-headless/references/shared/app/rest/wix-client.js +0 -185
  763. package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +0 -8
  764. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +0 -471
  765. package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +0 -20
  766. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +0 -167
  767. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +0 -83
  768. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +0 -104
  769. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +0 -163
  770. package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +0 -83
  771. package/skills/wix-vibe-headless/references/storefront/app/hooks/useVariantOptions.js +0 -76
  772. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +0 -64
  773. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +0 -176
  774. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +0 -218
  775. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +0 -174
  776. package/skills/wix-vibe-headless/references/storefront/seed/seed-store.cjs +0 -546
@@ -1,1580 +0,0 @@
1
- 'use strict';
2
-
3
- const fs = require('node:fs/promises');
4
- const path = require('node:path');
5
- const { verificationKind } = require('./entity-verification');
6
- const { appendExecutionLog } = require('./execution-log.js');
7
- const { validReceipt } = require('./write-verification');
8
- const { OUTCOME_RANK, aggregateOutcome } = require('./blocked-data-requests.js');
9
- const { PAYMENT_OUTCOMES, WRITER_OUTCOMES } = require('./payments-outcome-registry.js');
10
- const memberRegistry = require('./member-outcome-registry.js');
11
- const { SEO_OUTCOMES, SEO_ACCEPTED_OUTCOMES, SEO_OUTCOME_ACTIONS } = require('./seo-outcome-registry.js');
12
- const { coverageDisagreements, describeCoverageMismatch } = require('./import-recovery.js');
13
- const { cmsFallbackOperatorActions } = require('./plugin-cms-fallback.js');
14
- const { summarizeProjectCoverage } = require('./source-coverage.js');
15
- const { readLinkAudit, linkOperatorActions, RELATIVE_PATH: LINK_AUDIT_PATH } = require('./link-audit.js');
16
- const { projectDestinationOperatorActions } = require('./destination-handoff.js');
17
- const { sourceAccessOperatorActions, withheldDetailsOperatorActions } = require('./source-access.js');
18
- const { evaluateGiftCardCutover, GIFT_CODES_COVERAGE_ID, GIFT_ACTION_CODE } = require('../resources/rp-source-shopify/lib/shopify-gift-cards.js');
19
-
20
- const COMPLETION_STATUS = [
21
- 'aborted',
22
- 'incomplete_with_mismatches',
23
- 'incomplete_with_failures',
24
- 'complete_with_deferred_records',
25
- 'complete_with_recovered_records',
26
- 'complete_with_warnings',
27
- 'complete',
28
- ];
29
-
30
- const STATUS_RANK = new Map(COMPLETION_STATUS.map((status, index) => [status, index]));
31
-
32
- function count(value, field) {
33
- if (value === undefined || value === null) {
34
- return 0;
35
- }
36
- if (!Number.isInteger(value) || value < 0) {
37
- throw new Error(`${field} must be a non-negative integer`);
38
- }
39
- return value;
40
- }
41
-
42
- function requireString(value, field) {
43
- if (!value || typeof value !== 'string') {
44
- throw new Error(`${field} must be a non-empty string`);
45
- }
46
- return value;
47
- }
48
-
49
- function asArray(value, field) {
50
- if (value === undefined || value === null) {
51
- return [];
52
- }
53
- if (!Array.isArray(value)) {
54
- throw new Error(`${field} must be an array`);
55
- }
56
- return value;
57
- }
58
-
59
- function hasCount(rows, field) {
60
- return rows.some((row) => row[field] > 0);
61
- }
62
-
63
- function worseStatus(left, right) {
64
- const leftRank = STATUS_RANK.has(left) ? STATUS_RANK.get(left) : STATUS_RANK.get('complete');
65
- const rightRank = STATUS_RANK.has(right) ? STATUS_RANK.get(right) : STATUS_RANK.get('complete');
66
- return leftRank <= rightRank ? left : right;
67
- }
68
-
69
- function chooseCompletionStatus(input = {}) {
70
- const statuses = asArray(input.statuses, 'statuses');
71
- let selected = input.defaultStatus || 'complete';
72
- if (!STATUS_RANK.has(selected)) {
73
- throw new Error(`unknown completion status: ${selected}`);
74
- }
75
-
76
- for (const status of statuses) {
77
- if (!STATUS_RANK.has(status)) {
78
- throw new Error(`unknown completion status: ${status}`);
79
- }
80
- selected = worseStatus(selected, status);
81
- }
82
-
83
- if (input.aborted) {
84
- selected = worseStatus(selected, 'aborted');
85
- }
86
- if (input.hasMismatches) {
87
- selected = worseStatus(selected, 'incomplete_with_mismatches');
88
- }
89
- if (input.hasFailures) {
90
- selected = worseStatus(selected, 'incomplete_with_failures');
91
- }
92
- if (input.hasDeferred) {
93
- selected = worseStatus(selected, 'complete_with_deferred_records');
94
- }
95
- if (input.hasRecoveredRecords) {
96
- selected = worseStatus(selected, 'complete_with_recovered_records');
97
- }
98
- if (input.hasWarnings) {
99
- selected = worseStatus(selected, 'complete_with_warnings');
100
- }
101
-
102
- return selected;
103
- }
104
-
105
- // A structured reason entry is `{ outcome: 'deferred' | 'failed', code:
106
- // non-empty string, count: positive integer }`. `code` is taken verbatim and compared
107
- // case-sensitively -- there is no normalization, so `INTERNAL` and `internal` are distinct and
108
- // cannot collide. A plain string entry is a legacy free-text note and is returned unchanged.
109
- function normalizeReasonEntry(entry, label, index) {
110
- if (typeof entry === 'string') {
111
- return entry;
112
- }
113
- if (!entry || typeof entry !== 'object' || Array.isArray(entry)) {
114
- throw new Error(`${label}.reasons[${index}] must be a string or a structured { outcome, code, count } object`);
115
- }
116
- if (entry.outcome !== 'deferred' && entry.outcome !== 'failed') {
117
- throw new Error(`${label}.reasons[${index}].outcome must be 'deferred' or 'failed'`);
118
- }
119
- const code = requireString(entry.code, `${label}.reasons[${index}].code`);
120
- if (!Number.isInteger(entry.count) || entry.count <= 0) {
121
- throw new Error(`${label}.reasons[${index}].count must be a positive integer`);
122
- }
123
- return { outcome: entry.outcome, code, count: entry.count };
124
- }
125
-
126
- // A structured entry is only ever trustworthy because the journal join can tie it back
127
- // to the journal; with no `sourceKeys` there is nothing to join against, so a caller cannot hand
128
- // `createCompletionReport` a fabricated counted tally with no journal backing at all -- the exact
129
- // defect of "a count with no rows behind it". Also rejects a duplicate
130
- // `(outcome, code)` pair and a structured sum for an outcome that exceeds that outcome's count.
131
- function validateReasons(reasons, { entity, subtype, sourceKeys, deferred, failed }) {
132
- const label = `${entity}/${subtype}`;
133
- const hasStructured = reasons.some((entry) => typeof entry === 'object');
134
- if (hasStructured && (!sourceKeys || sourceKeys.length === 0)) {
135
- throw new Error(`${label}: a structured reason requires sourceKeys`);
136
- }
137
- const seen = new Set();
138
- const sums = { deferred: 0, failed: 0 };
139
- for (const entry of reasons) {
140
- if (typeof entry !== 'object') {
141
- continue;
142
- }
143
- const key = `${entry.outcome}\0${entry.code}`;
144
- if (seen.has(key)) {
145
- throw new Error(`${label}: duplicate reason (${entry.outcome}, ${entry.code})`);
146
- }
147
- seen.add(key);
148
- sums[entry.outcome] += entry.count;
149
- }
150
- if (sums.deferred > deferred) {
151
- throw new Error(`${label}: structured deferred reasons sum to ${sums.deferred}, more than deferred count ${deferred}`);
152
- }
153
- if (sums.failed > failed) {
154
- throw new Error(`${label}: structured failed reasons sum to ${sums.failed}, more than failed count ${failed}`);
155
- }
156
- }
157
-
158
- function normalizeCompletenessRow(row, index = 0) {
159
- if (!row || typeof row !== 'object' || Array.isArray(row)) {
160
- throw new Error(`entityCompleteness[${index}] must be an object`);
161
- }
162
-
163
- const entity = requireString(row.entity, `entityCompleteness[${index}].entity`);
164
- const subtype = row.subtype === undefined || row.subtype === null ? 'all' : requireString(row.subtype, `entityCompleteness[${index}].subtype`);
165
- const extracted = count(row.extracted, `${entity}/${subtype}.extracted`);
166
- const inScope = count(row.inScope, `${entity}/${subtype}.inScope`);
167
- const attempted = count(row.attempted, `${entity}/${subtype}.attempted`);
168
- const imported = count(row.imported, `${entity}/${subtype}.imported`);
169
- const alreadyPresentByCrosswalk = count(
170
- row.alreadyPresentByCrosswalk === undefined ? row.alreadyPresent : row.alreadyPresentByCrosswalk,
171
- `${entity}/${subtype}.alreadyPresentByCrosswalk`
172
- );
173
- const deferred = count(row.deferred, `${entity}/${subtype}.deferred`);
174
- const failed = count(row.failed, `${entity}/${subtype}.failed`);
175
- // A write of unknown outcome: may or may not be on the merchant's store. Its own bucket, never
176
- // folded into `failed` and never left as an unexplained shortfall. Existing callers omit it.
177
- const unresolved = count(row.unresolved, `${entity}/${subtype}.unresolved`);
178
- const skippedOutOfScope = count(row.skippedOutOfScope, `${entity}/${subtype}.skippedOutOfScope`);
179
- const unexpectedSkipped = count(
180
- row.unexpectedSkipped === undefined ? row.skippedInScope : row.unexpectedSkipped,
181
- `${entity}/${subtype}.unexpectedSkipped`
182
- );
183
- const reconciled = imported + alreadyPresentByCrosswalk + deferred + failed + unresolved;
184
- const expectedReconciled = inScope;
185
- // The shipped reconciliation contract (rp-import-codegen/SKILL.md) requires
186
- // `inScope + skippedOutOfScope <= extracted` -- an excluded record must never also be counted
187
- // inside `inScope`. This is only detectable when the caller actually supplied `extracted`
188
- // (present, not defaulted by `count()` to 0 for an omitted or explicit `null` field); the raw
189
- // field is checked here, before `count()` erases that distinction. `scopeOverflow` names only
190
- // the exact, arithmetic-provable excess -- never a claimed count of overlapping records, since
191
- // an extracted record that belongs to neither bucket can make the true overlap larger than this
192
- // number (worked example: 10 extracted, 8 in-scope, 4 skipped, 1 in neither bucket --
193
- // true overlap could be 3 while counts exceed extracted by only 2).
194
- const extractedSupplied = row.extracted !== undefined && row.extracted !== null;
195
- const scopeOverflow = extractedSupplied && inScope + skippedOutOfScope > extracted
196
- ? inScope + skippedOutOfScope - extracted
197
- : 0;
198
- const mismatch = reconciled !== expectedReconciled || unexpectedSkipped > 0 || scopeOverflow > 0;
199
- const sourceKeys = Array.isArray(row.sourceKeys) ? row.sourceKeys : null;
200
- const reasons = (Array.isArray(row.reasons) ? row.reasons : [])
201
- .map((entry, entryIndex) => normalizeReasonEntry(entry, `${entity}/${subtype}`, entryIndex));
202
- validateReasons(reasons, { entity, subtype, sourceKeys, deferred, failed });
203
-
204
- return {
205
- entity,
206
- subtype,
207
- extracted,
208
- inScope,
209
- attempted,
210
- imported,
211
- alreadyPresentByCrosswalk,
212
- deferred,
213
- failed,
214
- unresolved,
215
- skippedOutOfScope,
216
- unexpectedSkipped,
217
- reconciled,
218
- expectedReconciled,
219
- scopeOverflow,
220
- mismatch,
221
- reasons,
222
- verificationKind: verificationKind(row),
223
- sourceKeys,
224
- };
225
- }
226
-
227
- // The post-import voucher reconciliation answer. Closed set, no default: a run that
228
- // imported usage-limited coupons cannot report itself complete while staying silent about whether
229
- // the reconciliation happened. The whole defect this guards is that "we never did this" and
230
- // "there was nothing to do" used to be the same shape — an absent field.
231
- const VOUCHER_RECONCILIATION = [
232
- 'not-applicable',
233
- 'reconciled',
234
- 'plan-pending-owner',
235
- 'remedied',
236
- 'not-run',
237
- ];
238
- // Both of these are money still live on the merchant's store, or possibly so. Neither is allowed
239
- // to be a quiet line item: they reach the headline and they raise the final status.
240
- const VOUCHER_RECONCILIATION_WARNING = new Set(['not-run', 'plan-pending-owner']);
241
-
242
- const VOUCHER_RECONCILIATION_MESSAGE = {
243
- 'not-run': 'vouchers: the post-import reconciliation was due and did not run. Run it BEFORE cutover — afterwards there is no fresh source read to compare against and the target exposes no redemption count, so which codes were already spent becomes unknowable',
244
- 'plan-pending-owner': 'vouchers: a reconciliation plan is waiting on the owner\'s decision per code. Until each is decided and confirmed by a post-settle read-back, money spent at source is still redeemable on the target',
245
- };
246
-
247
- // The same two states also owe an urgent operator action, so the warning reaches the
248
- // "Urgent Operator Actions" section of both the summary and the merchant handoff instead of only
249
- // the headline. Fixed per state -- nothing is left for a renderer to invent.
250
- const VOUCHER_RECONCILIATION_ACTION = {
251
- 'not-run': {
252
- code: 'voucher-reconciliation-not-run',
253
- severity: 'critical',
254
- action: 'Run the post-import voucher reconciliation against a fresh source read before cutover.',
255
- deadlineReason: 'once the old platform stops being the system of record there is no fresh source read left to compare against, and which codes were already spent becomes permanently unknowable',
256
- },
257
- 'plan-pending-owner': {
258
- code: 'voucher-reconciliation-plan-pending',
259
- severity: 'critical',
260
- action: 'Decide the remedy for each coupon on the pending reconciliation plan, then confirm each decision with a post-settle read-back.',
261
- deadlineReason: 'until every code is decided and confirmed, money already spent at source remains redeemable on the target',
262
- },
263
- };
264
-
265
- // Anchored at the end of the entity name, not a bare
266
- // substring test. A bare `/coupon/i` also matches an entity whose name merely CONTAINS "coupon"
267
- // as a qualifier for something else entirely -- for example
268
- // `smart-coupons-extra-fields` (a per-coupon CMS-shadow metadata facet of the SAME coupon
269
- // records, recordCount tied 1:1 to `coupon`, not a second population of coupons) matched the old
270
- // regex and got summed into `affectedCount` alongside the real `coupon` row, inflating the
271
- // voucher-reconciliation operator action to roughly double the real exposure. Anchoring to "coupon(s)" at the end of the name keeps matching a
272
- // genuinely separate coupon population named with a suffix (`giftCoupons`, tested below) while
273
- // excluding a differently-suffixed entity that merely mentions coupons in passing
274
- // (`*-extra-fields`, `*-rule-definition`, etc.).
275
- const isCouponRow = (row) => /coupons?$/i.test(row.entity);
276
-
277
- // Confidentiality: the merchant handoff may carry the voucher urgency signal, but
278
- // never a caller's free-text warning, which can hold names, emails or order contents. Only the
279
- // fixed voucher messages above pass, rebuilt from constants so no caller-supplied field rides along.
280
- const VOUCHER_MESSAGES = new Set(Object.values(VOUCHER_RECONCILIATION_MESSAGE));
281
-
282
- function handoffVoucherSignal(report = {}) {
283
- const state = VOUCHER_RECONCILIATION.includes(report.voucherReconciliation) ? report.voucherReconciliation : null;
284
- const headline = (Array.isArray(report.headline) ? report.headline : [])
285
- .filter((row) => row && row.subtype === 'voucher-reconciliation' && VOUCHER_MESSAGES.has(row.message))
286
- .map((row) => ({ entity: 'coupons', subtype: 'voucher-reconciliation', message: row.message }));
287
- const warnings = (Array.isArray(report.warnings) ? report.warnings : [])
288
- .filter((message) => VOUCHER_MESSAGES.has(message));
289
- return { voucherReconciliation: state, headline, warnings };
290
- }
291
-
292
- // `affectedCount` counts from the same rows that decide whether the step is owed. With no coupon
293
- // completeness row (only `usageLimitedCouponsInSource` triggered it) it is 0, meaning "no row to
294
- // count from" -- never "no coupons affected", and never less urgent.
295
- function voucherOperatorAction(voucherReconciliation, entityCompleteness) {
296
- const template = VOUCHER_RECONCILIATION_ACTION[voucherReconciliation];
297
- if (!template) return null;
298
- const affectedCount = entityCompleteness.filter(isCouponRow).reduce((sum, row) => sum + row.inScope, 0);
299
- return { ...template, entity: 'coupons', affectedCount };
300
- }
301
-
302
- // Is this run subject to the step at all? Either the caller says the source carried
303
- // usage-limited coupons, or the run has an in-scope coupon entity row. Silence from a run that
304
- // never touched coupons is not the defect; silence from a run that imported them is.
305
- function voucherReconciliationRequired(input, entityCompleteness) {
306
- if (input.usageLimitedCouponsInSource === true) return true;
307
- return entityCompleteness.some((row) => isCouponRow(row) && row.inScope > 0);
308
- }
309
-
310
- function normalizeVoucherReconciliation(input, entityCompleteness) {
311
- const raw = input.voucherReconciliation;
312
- if (raw !== undefined && raw !== null) {
313
- if (typeof raw !== 'string' || !VOUCHER_RECONCILIATION.includes(raw)) {
314
- throw new Error(`voucherReconciliation must be one of ${VOUCHER_RECONCILIATION.join(', ')}`);
315
- }
316
- return raw;
317
- }
318
- // A missing answer is read as `not-run`, NEVER as `not-applicable`: defaulting an absent
319
- // answer to the benign value is exactly how a skipped step reported itself complete.
320
- return voucherReconciliationRequired(input, entityCompleteness) ? 'not-run' : null;
321
- }
322
-
323
- function headlineForRow(row) {
324
- const parts = [];
325
- // This fragment must name an actual reconciliation
326
- // shortfall, not merely `row.mismatch` -- `mismatch` can now also be forced by `scopeOverflow`
327
- // (a counting error, not a lost record) or by `unexpectedSkipped` alone, either of which can
328
- // leave `reconciled === expectedReconciled`. Gating on the real inequality avoids a
329
- // self-contradictory "mismatch N/N" once concatenated with the scopeOverflow headline below.
330
- if (row.reconciled !== row.expectedReconciled) {
331
- parts.push(`mismatch ${row.reconciled}/${row.expectedReconciled}`);
332
- }
333
- if (row.scopeOverflow > 0) {
334
- parts.push(`inScope + skippedOutOfScope exceeds extracted by ${row.scopeOverflow}; count exclusions outside inScope`);
335
- }
336
- if (row.deferred > 0) {
337
- parts.push(`${row.deferred} deferred`);
338
- }
339
- if (row.failed > 0) {
340
- parts.push(`${row.failed} failed`);
341
- }
342
- if (row.unresolved > 0) {
343
- parts.push(`${row.unresolved} unresolved`);
344
- }
345
- if (row.unexpectedSkipped > 0) {
346
- parts.push(`${row.unexpectedSkipped} unexpected skipped`);
347
- }
348
- if (!parts.length) {
349
- return null;
350
- }
351
- return {
352
- entity: row.entity,
353
- subtype: row.subtype,
354
- message: `${row.entity}/${row.subtype}: ${parts.join(', ')}`,
355
- };
356
- }
357
-
358
- function nextStepForBlockedRequest(request, snapshot, requestAggregateOutcome) {
359
- // A `fulfilled` request only means the source-side snapshot was captured cleanly — it says
360
- // nothing about whether any target field actually got written using it. Never let this
361
- // branch claim "no action is required" while a dependent's own write accounting says the
362
- // value was never applied (deferred/failed) or applied only via a degraded default
363
- // (warning); check the real per-dependent outcome, not the snapshot status alone.
364
- if (request.status === 'fulfilled' && (requestAggregateOutcome === 'deferred' || requestAggregateOutcome === 'failed')) {
365
- return 'The source data was captured successfully, but no target field has been written using it yet — capturing the definitions is not the same as completing the migration. See dependentOutcomes for which field(s) remain unattempted.';
366
- }
367
- if (request.status === 'fulfilled' && requestAggregateOutcome === 'warning') {
368
- return 'The source data was captured successfully, but at least one target field was written using its existing degraded default rather than this data — see dependentOutcomes for which field(s).';
369
- }
370
- if (request.status === 'fulfilled' && request.stale) {
371
- return `The import used data pulled ${snapshot.extractedAt} (snapshot v${snapshot.version}); verify no relevant source activity occurred after that date, or restore the ${request.fulfillment.kind} path and re-run to refresh.`;
372
- }
373
- if (request.status === 'fulfilled') return 'No action is required; the import used the recorded source-data snapshot.';
374
- if (request.status === 'invalid') {
375
- if (request.fulfillmentErrorCode === 'handler-not-registered') {
376
- return `Fulfillment handler ${request.fulfillment.handlerId} is not registered in this runner. This is a wiring bug in the import runner, not a data problem — register the handler and re-run.`;
377
- }
378
- return request.fulfillment.kind === 'csv-upload'
379
- ? `Correct the file at ${request.fulfillment.expectedInputPath} and re-run.`
380
- : 'The source bridge responded with unusable data; correct or reinstall it and re-run.';
381
- }
382
- if (request.status === 'declined') return 'Supply the blocked source data and re-run if you want to replace the degraded default.';
383
- if (request.lastError) return `The source namespace probe failed: ${request.lastError}. Fix source connectivity or authentication, then re-run.`;
384
- if (request.askedInteractively !== true) {
385
- return request.fulfillment.kind === 'csv-upload'
386
- ? `This run did not pause to ask. Supply ${request.fulfillment.expectedInputPath} and re-run.`
387
- : 'This run did not pause to ask. Install the production-ready source bridge and re-run when that option becomes available.';
388
- }
389
- return request.fulfillment.kind === 'csv-upload'
390
- ? `Supply ${request.fulfillment.expectedInputPath} and re-run.`
391
- : 'Install the production-ready source bridge and re-run when that option becomes available.';
392
- }
393
-
394
- function normalizeBlockedDataRequest(request, index = 0) {
395
- if (!request || typeof request !== 'object' || Array.isArray(request)) throw new Error(`blockedDataRequests[${index}] must be an object`);
396
- const sourceEntityRef = requireString(request.sourceEntityRef, `blockedDataRequests[${index}].sourceEntityRef`);
397
- const status = requireString(request.status, `blockedDataRequests[${index}].status`);
398
- if (!['offered', 'missing', 'declined', 'invalid', 'fulfilled'].includes(status)) throw new Error(`${sourceEntityRef}.status is invalid`);
399
- if (status === 'declined' && request.askedInteractively !== true) throw new Error(`${sourceEntityRef}: declined requires askedInteractively: true`);
400
- const snapshot = request.snapshot || {};
401
- if (status === 'fulfilled' && (!Number.isInteger(snapshot.version) || !snapshot.extractedAt || !snapshot.checksum)) {
402
- throw new Error(`${sourceEntityRef}: fulfilled requires snapshot version, extractedAt, and checksum`);
403
- }
404
- const dependentOutcomes = asArray(request.dependentOutcomes, `${sourceEntityRef}.dependentOutcomes`).map((dependent, dependentIndex) => {
405
- let recordOutcome = dependent.recordOutcome;
406
- if (recordOutcome === null || recordOutcome === undefined) {
407
- throw new Error(`${sourceEntityRef}.dependentOutcomes[${dependentIndex}].recordOutcome must be filled from write accounting`);
408
- }
409
- if (!OUTCOME_RANK.has(recordOutcome)) throw new Error(`${sourceEntityRef}.dependentOutcomes[${dependentIndex}].recordOutcome is invalid`);
410
- if (status !== 'fulfilled' && recordOutcome === 'fulfilled') {
411
- throw new Error(`${sourceEntityRef}.dependentOutcomes[${dependentIndex}] cannot be fulfilled without a fulfilled request`);
412
- }
413
- if (status === 'fulfilled' && request.stale && recordOutcome === 'fulfilled') recordOutcome = 'warning';
414
- const row = {
415
- targetEntity: requireString(dependent.targetEntity, `${sourceEntityRef}.dependentOutcomes[${dependentIndex}].targetEntity`),
416
- degradedField: requireString(dependent.degradedField, `${sourceEntityRef}.dependentOutcomes[${dependentIndex}].degradedField`),
417
- pitfallCode: dependent.pitfallCode || null,
418
- recordOutcome,
419
- };
420
- if (status === 'fulfilled') {
421
- row.snapshotVersion = snapshot.version;
422
- row.extractedAt = snapshot.extractedAt;
423
- row.checksum = snapshot.checksum;
424
- }
425
- return row;
426
- });
427
- const requestAggregateOutcome = aggregateOutcome(dependentOutcomes);
428
- return {
429
- sourceEntityRef,
430
- status,
431
- stale: Boolean(request.stale),
432
- snapshotVersion: status === 'fulfilled' ? snapshot.version : null,
433
- snapshotExtractedAt: status === 'fulfilled' ? snapshot.extractedAt : null,
434
- snapshotChecksum: status === 'fulfilled' ? snapshot.checksum : null,
435
- dependentOutcomes,
436
- aggregateOutcome: requestAggregateOutcome,
437
- consequenceIfMissing: request.consequenceIfMissing || null,
438
- whatUserCanDoNext: nextStepForBlockedRequest({ ...request, fulfillment: request.fulfillment || {} }, snapshot, requestAggregateOutcome),
439
- };
440
- }
441
-
442
- // A per-stage failure against a record the entity row already counts as `imported`.
443
- //
444
- // An order whose import succeeded and whose payment failed is a live order sitting unpaid on the
445
- // merchant's store, and the completeness arithmetic cannot see it: that arithmetic partitions the
446
- // POPULATION, and the order did import. So the report printed the failed payment and counted the
447
- // run complete. This is the orthogonal axis, and it is never folded into `failed` -- doing that
448
- // would break the `imported + alreadyPresentByCrosswalk + deferred + failed == inScope` identity
449
- // the partition exists to protect.
450
- //
451
- // The outcome vocabulary comes from the registry both sides already import, so a stage cannot
452
- // report a code the report has no line for.
453
- const STAGE_RESIDUAL_OUTCOMES = new Set([...WRITER_OUTCOMES, ...PAYMENT_OUTCOMES, ...SEO_OUTCOMES]);
454
- // Owner-dispositioned SEO rows stay visible as counts but are decisions, not open
455
- // work, so they never block completion.
456
- const ACCEPTED_STAGE_OUTCOMES = new Set(SEO_ACCEPTED_OUTCOMES);
457
-
458
- function normalizeStageResidual(row, index = 0) {
459
- if (!row || typeof row !== 'object' || Array.isArray(row)) {
460
- throw new Error(`stageResiduals[${index}] must be an object`);
461
- }
462
- const entity = requireString(row.entity, `stageResiduals[${index}].entity`);
463
- const stage = requireString(row.stage, `stageResiduals[${index}].stage`);
464
- const outcome = requireString(row.outcome, `stageResiduals[${index}].outcome`);
465
- if (!STAGE_RESIDUAL_OUTCOMES.has(outcome)) {
466
- throw new Error(`stageResiduals[${index}].outcome is invalid: ${outcome}`);
467
- }
468
- const rowCount = count(row.count, `stageResiduals[${index}].count`);
469
- const sourceKeys = asArray(row.sourceKeys, `stageResiduals[${index}].sourceKeys`)
470
- .map((key, keyIndex) => requireString(key, `stageResiduals[${index}].sourceKeys[${keyIndex}]`));
471
- return { entity, stage, outcome, count: rowCount, sourceKeys };
472
- }
473
-
474
- function stageResidualMessage(row) {
475
- const named = row.sourceKeys.length ? ` (${row.sourceKeys.join(', ')})` : '';
476
- if (SEO_OUTCOME_ACTIONS[row.outcome]) return `${row.entity}/${row.stage}: ${row.count} ${row.entity} ${row.outcome}${named}`;
477
- return `${row.entity}/${row.stage}: ${row.count} imported ${row.entity} still ${row.outcome}${named}`;
478
- }
479
-
480
- function stageResidualAction(row) {
481
- const named = row.sourceKeys.length ? ` (${row.sourceKeys.join(', ')})` : '';
482
- if (SEO_OUTCOME_ACTIONS[row.outcome]) return `${SEO_OUTCOME_ACTIONS[row.outcome]} Affected: ${row.count}${named}.`;
483
- return `Re-run the ${row.stage} stage for ${row.entity}${row.sourceKeys.length ? ` ${row.sourceKeys.join(', ')}` : ''}: ${row.count} imported ${row.entity} ${row.count === 1 ? 'is' : 'are'} ${row.outcome}.`;
484
- }
485
-
486
- // Consume the runner's final per-order outcomes, never recount API attempts or read a log.
487
- // Keep only the last result for a source key so a recovery pass clears a resolved failure.
488
- function collectOrderStageResiduals(results, { entity = 'order' } = {}) {
489
- if (!Array.isArray(results)) throw new Error('order history results must be an array');
490
- requireString(entity, 'order history entity');
491
- const latest = new Map();
492
- for (const row of results) {
493
- const sourceKey = requireString(row && row.sourceKey, 'order history sourceKey');
494
- if (!row.outcomes || !['order-imported', 'order-already-imported', 'order-import-failed', 'order-target-read-failed'].includes(row.outcomes.order)) {
495
- throw new Error(`order history ${sourceKey}: missing or invalid order outcome`);
496
- }
497
- latest.set(sourceKey, row.outcomes);
498
- }
499
- const groups = new Map();
500
- for (const [sourceKey, outcomes] of latest) {
501
- if (!['order-imported', 'order-already-imported'].includes(outcomes.order)) continue;
502
- const stages = [
503
- ['payment', outcomes.payment],
504
- ['invoice', outcomes.invoice],
505
- ...(outcomes.refunds || []).map((refund) => ['refund', refund.outcome]),
506
- ];
507
- for (const [stage, outcome] of stages) {
508
- if (!STAGE_RESIDUAL_OUTCOMES.has(outcome)) {
509
- throw new Error(`order history ${sourceKey}: missing or invalid ${stage} outcome`);
510
- }
511
- if (!outcome.endsWith('-failed') && outcome !== 'payment-reconciliation-ambiguous') continue;
512
- const key = `${stage}:${outcome}`;
513
- if (!groups.has(key)) groups.set(key, { entity, stage, outcome, sourceKeys: new Set() });
514
- groups.get(key).sourceKeys.add(sourceKey);
515
- }
516
- }
517
- return [...groups.values()].map((row) => ({
518
- ...row, count: row.sourceKeys.size, sourceKeys: [...row.sourceKeys],
519
- }));
520
- }
521
-
522
- const COMPLETION_REPORT_FILE = 'execution/completion-report.json';
523
- const COMPLETION_SUMMARY_FILE = 'execution/review/completion-summary.md';
524
-
525
- // There is no fourth shape and no bare free-text cause.
526
- const CAUSE_CONFIDENCE = ['verified-source', 'verified-target', 'unverified'];
527
-
528
- // `unverified` must not carry a cause string: a hypothesis rendered next to the
529
- // word "unverified" is read as a finding by every reader who is skimming. In practice that
530
- // turned "three products failed" into "the merchant's source data has duplicate slugs", which
531
- // nobody had checked and which was false. Reject it at build time rather than dropping it
532
- // quietly -- a row that meant to name a cause needs the check that establishes it, not silence.
533
- function normalizeCauseAttribution(row, label) {
534
- const confidence = row.causeConfidence === undefined || row.causeConfidence === null
535
- ? 'unverified'
536
- : requireString(row.causeConfidence, `${label}.causeConfidence`);
537
- if (!CAUSE_CONFIDENCE.includes(confidence)) {
538
- throw new Error(`${label}.causeConfidence must be one of ${CAUSE_CONFIDENCE.join(', ')}`);
539
- }
540
- if (confidence === 'unverified') {
541
- if (row.cause !== undefined && row.cause !== null && row.cause !== '') {
542
- throw new Error(`${label}: causeConfidence 'unverified' must not carry a cause; name the destination-side check or leave the cause out`);
543
- }
544
- if (row.check !== undefined && row.check !== null) {
545
- throw new Error(`${label}: causeConfidence 'unverified' must not carry a check`);
546
- }
547
- return { causeConfidence: 'unverified', cause: null, check: null };
548
- }
549
- const cause = requireString(row.cause, `${label}.cause`);
550
- const check = row.check;
551
- if (!check || typeof check !== 'object' || Array.isArray(check)) {
552
- throw new Error(`${label}: causeConfidence '${confidence}' requires a recorded check { kind, target, result }`);
553
- }
554
- return {
555
- causeConfidence: confidence,
556
- cause,
557
- check: {
558
- kind: requireString(check.kind, `${label}.check.kind`),
559
- target: requireString(check.target, `${label}.check.target`),
560
- result: requireString(check.result, `${label}.check.result`),
561
- },
562
- };
563
- }
564
-
565
- const OPERATOR_ACTION_SEVERITIES = ['critical', 'high', 'medium', 'low'];
566
-
567
- // Anything the operator has to do by hand goes above the counts, with the
568
- // deadline reason attached. The worked example is a large batch of discount codes
569
- // with no redemption cap -- correctable only while the source is still the system of record.
570
- function normalizeOperatorAction(row, index) {
571
- if (!row || typeof row !== 'object' || Array.isArray(row)) {
572
- throw new Error(`operatorActions[${index}] must be an object`);
573
- }
574
- const label = `operatorActions[${index}]`;
575
- const severity = requireString(row.severity, `${label}.severity`);
576
- if (!OPERATOR_ACTION_SEVERITIES.includes(severity)) {
577
- throw new Error(`${label}.severity must be one of ${OPERATOR_ACTION_SEVERITIES.join(', ')}`);
578
- }
579
- return {
580
- code: requireString(row.code, `${label}.code`),
581
- severity,
582
- action: requireString(row.action, `${label}.action`),
583
- deadlineReason: requireString(row.deadlineReason, `${label}.deadlineReason`),
584
- entity: row.entity || null,
585
- affectedCount: row.affectedCount === null ? null : count(row.affectedCount, `${label}.affectedCount`),
586
- };
587
- }
588
-
589
- // `createCompletionReport` never recomputes the check itself -- it only binds the
590
- // already-computed block (from `live-import-summary.json`, via `writeLiveImportSummary`) to the
591
- // run it is completing, and decides what that binding means for the final status and operator
592
- // actions.
593
- //
594
- // `live-import-summary.json` is one file, fully overwritten on every flush, and interleaved
595
- // run ids are allowed in the same project directory -- so the most recent `coverageCheck`
596
- // read off disk is not necessarily about the run being completed. A supplied check is honored only
597
- // when its own `runId` strictly equals `input.runId`; anything else (a different run's check, or
598
- // one with no `runId` at all) is treated exactly like an omitted check.
599
- function normalizeCoverageCheckInput(input) {
600
- const raw = input.coverageCheck;
601
- if (raw === undefined || raw === null) {
602
- return { coverageCheck: { supplied: false }, raw: null };
603
- }
604
- if (typeof raw !== 'object' || Array.isArray(raw)) {
605
- throw new Error('coverageCheck must be an object');
606
- }
607
- requireString(input.runId, 'runId must be a non-empty string when coverageCheck is supplied');
608
- const matches = typeof raw.runId === 'string' && raw.runId === input.runId;
609
- return { coverageCheck: { ...raw, supplied: matches }, raw };
610
- }
611
-
612
- function coverageFirstDisagreeingEntity(coverageCheck) {
613
- const items = coverageDisagreements(coverageCheck);
614
- if (items.length) {
615
- return items[0].key;
616
- }
617
- return (coverageCheck.unmatched && coverageCheck.unmatched[0]) || null;
618
- }
619
-
620
- function coverageAffectedCount(coverageCheck) {
621
- return coverageDisagreements(coverageCheck).length
622
- + ((coverageCheck.unmatched && coverageCheck.unmatched.length) || 0)
623
- + ((coverageCheck.unmatchedJournalEntities && coverageCheck.unmatchedJournalEntities.length) || 0);
624
- }
625
-
626
- // The reason text for a `coverage_unchecked` operator action: whatever reason the writer itself
627
- // recorded (or `has_unresolved`) when a run-matched check came back `unchecked`, or a
628
- // reason naming why no run-matched check was honored at all, when one wasn't.
629
- function coverageUncheckedReason(coverageCheck, raw, runId) {
630
- if (coverageCheck.supplied) {
631
- return coverageCheck.reason || 'unchecked';
632
- }
633
- if (!raw) {
634
- return 'omitted';
635
- }
636
- if (typeof raw.runId !== 'string' || !raw.runId) {
637
- return 'missing_run_id';
638
- }
639
- return `run_id_mismatch (coverageCheck.runId: ${raw.runId}, completing run: ${runId})`;
640
- }
641
-
642
- // The operator-action shape, with concrete values so `normalizeOperatorAction`'s required
643
- // `code`/`action` never throw: both are built here, never left for a caller to invent.
644
- function coverageOperatorActionRow(kind, { coverageCheck, raw, runId }) {
645
- if (kind === 'mismatch') {
646
- return {
647
- code: 'coverage_mismatch',
648
- severity: 'high',
649
- action: `Investigate the live-import count cross-check for run ${runId}: ${describeCoverageMismatch(coverageCheck)}. See the Import Operator prompt in the migration handoff.`,
650
- deadlineReason: 'before DNS change',
651
- entity: coverageFirstDisagreeingEntity(coverageCheck),
652
- affectedCount: coverageAffectedCount(coverageCheck),
653
- };
654
- }
655
- const reason = coverageUncheckedReason(coverageCheck, raw, runId);
656
- return {
657
- code: 'coverage_unchecked',
658
- severity: 'medium',
659
- action: `Confirm the live-import counts for run ${runId} before DNS: the completion report has no run-matched coverageCheck (reason: ${reason}). See the Import Operator prompt in the migration handoff.`,
660
- deadlineReason: 'before DNS change',
661
- entity: null,
662
- affectedCount: 0,
663
- };
664
- }
665
-
666
- // The omitted/rejected-run default escalation is bounded
667
- // to runs that declare participation (`coverageCheckExpected: true` -- this run called
668
- // `writeLiveImportSummary` with a `runId` at least once). A run that never adopted this contract
669
- // never sets that flag, so a missing check there changes nothing, exactly as before.
670
- function resolveCoverageCheckEffect(input) {
671
- const { coverageCheck, raw } = normalizeCoverageCheckInput(input);
672
- const coverageCheckExpected = input.coverageCheckExpected === true;
673
- let hasMismatch = false;
674
- let hasWarnings = false;
675
- let operatorActionRow = null;
676
-
677
- if (coverageCheck.supplied) {
678
- // Supplying a run-matched block at all is itself evidence of participation: its normal effect
679
- // applies regardless of `coverageCheckExpected`.
680
- if (coverageCheck.status === 'mismatch') {
681
- hasMismatch = true;
682
- operatorActionRow = coverageOperatorActionRow('mismatch', { coverageCheck, raw, runId: input.runId });
683
- } else if (coverageCheck.status === 'unchecked') {
684
- hasWarnings = true;
685
- operatorActionRow = coverageOperatorActionRow('unchecked', { coverageCheck, raw, runId: input.runId });
686
- }
687
- } else if (coverageCheckExpected) {
688
- hasWarnings = true;
689
- operatorActionRow = coverageOperatorActionRow('unchecked', { coverageCheck, raw, runId: input.runId });
690
- }
691
-
692
- return { coverageCheck, coverageCheckExpected, hasMismatch, hasWarnings, operatorActionRow };
693
- }
694
-
695
- // Four different things needing four different responses:
696
- // a loss is not an exclusion, an orphan is not a loss, and a dropped field is the one that
697
- // vanishes most easily because the record count reconciles perfectly. Rendered from these
698
- // durable rows, never recounted (the rows themselves are the journal contract).
699
- function normalizeCreditSubtype(row, label) {
700
- return row.subtype === undefined || row.subtype === null ? null : requireString(row.subtype, `${label}.subtype`);
701
- }
702
-
703
- function normalizeLoss(row, index) {
704
- if (!row || typeof row !== 'object' || Array.isArray(row)) throw new Error(`losses[${index}] must be an object`);
705
- const label = `losses[${index}]`;
706
- return {
707
- entity: requireString(row.entity, `${label}.entity`),
708
- // With a subtype, this credit covers only that entity/subtype's failed
709
- // shortfall; without one, it joins the entity's shared pool across its subtypes.
710
- subtype: normalizeCreditSubtype(row, label),
711
- reasonCode: requireString(row.reasonCode, `${label}.reasonCode`),
712
- count: count(row.count, `${label}.count`),
713
- whyNoRetry: requireString(row.whyNoRetry, `${label}.whyNoRetry`),
714
- sourceIds: Array.isArray(row.sourceIds) ? row.sourceIds : [],
715
- ...normalizeCauseAttribution(row, label),
716
- };
717
- }
718
-
719
- function normalizeExclusion(row, index) {
720
- if (!row || typeof row !== 'object' || Array.isArray(row)) throw new Error(`exclusions[${index}] must be an object`);
721
- const label = `exclusions[${index}]`;
722
- return {
723
- entity: requireString(row.entity, `${label}.entity`),
724
- ...(row.censusId !== undefined ? { censusId: requireString(row.censusId, `${label}.censusId`) } : {}),
725
- // With a subtype, this credit covers only that entity/subtype's deferred
726
- // shortfall; without one, it joins the entity's shared pool across its subtypes.
727
- subtype: normalizeCreditSubtype(row, label),
728
- reasonCode: requireString(row.reasonCode, `${label}.reasonCode`),
729
- count: count(row.count, `${label}.count`),
730
- rationale: requireString(row.rationale, `${label}.rationale`),
731
- // A choice is not a loss, and an undecided choice is not a decision: say whether a human
732
- // actually gated it rather than letting an unreviewed filter read as an approved one.
733
- operatorGateRecorded: Boolean(row.operatorGateRecorded),
734
- };
735
- }
736
-
737
- function normalizeUnresolved(row, index) {
738
- if (!row || typeof row !== 'object' || Array.isArray(row)) throw new Error(`unresolved[${index}] must be an object`);
739
- const label = `unresolved[${index}]`;
740
- const kind = requireString(row.kind, `${label}.kind`);
741
- if (!['orphaned_target', 'unmapped_source', 'mapping_without_record'].includes(kind)) {
742
- throw new Error(`${label}.kind must be orphaned_target, unmapped_source or mapping_without_record`);
743
- }
744
- return {
745
- entity: requireString(row.entity, `${label}.entity`),
746
- kind,
747
- count: count(row.count, `${label}.count`),
748
- targetIds: Array.isArray(row.targetIds) ? row.targetIds : [],
749
- sourceIds: Array.isArray(row.sourceIds) ? row.sourceIds : [],
750
- ...normalizeCauseAttribution(row, label),
751
- };
752
- }
753
-
754
- function normalizeDroppedField(row, index) {
755
- if (!row || typeof row !== 'object' || Array.isArray(row)) throw new Error(`droppedFields[${index}] must be an object`);
756
- const label = `droppedFields[${index}]`;
757
- return {
758
- entity: requireString(row.entity, `${label}.entity`),
759
- ...(row.subtype !== undefined ? { subtype: requireString(row.subtype, `${label}.subtype`) } : {}),
760
- field: requireString(row.field, `${label}.field`),
761
- recordCount: count(row.recordCount, `${label}.recordCount`),
762
- reasonCode: requireString(row.reasonCode, `${label}.reasonCode`),
763
- };
764
- }
765
-
766
- // The member pass's per-reason breakdown. Every registry code carries a line,
767
- // zeros included: an absent line is indistinguishable from a code nobody counted.
768
- function normalizeMemberOutcomes(value) {
769
- if (value === undefined || value === null) return null;
770
- if (typeof value !== 'object' || Array.isArray(value)) throw new Error('memberOutcomes must be an object');
771
- requireString(value.populationBasis, 'memberOutcomes.populationBasis');
772
- const lines = (field, codes) => {
773
- const source = value[field];
774
- if (!source || typeof source !== 'object') throw new Error(`memberOutcomes.${field} must be an object`);
775
- for (const key of Object.keys(source)) {
776
- if (!codes.includes(key)) throw new Error(`memberOutcomes.${field} has unknown code ${key}`);
777
- }
778
- return Object.fromEntries(codes.map((code) => {
779
- if (!(code in source)) throw new Error(`memberOutcomes.${field}.${code} is missing; every registry code carries a line`);
780
- return [code, count(source[code], `memberOutcomes.${field}.${code}`)];
781
- }));
782
- };
783
- const defect = value.populationDefect || {};
784
- return {
785
- ...value,
786
- entity: value.entity || memberRegistry.MEMBER_ENTITY,
787
- byOutcome: lines('byOutcome', memberRegistry.MEMBER_OUTCOMES),
788
- byFinding: lines('byFinding', memberRegistry.MEMBER_FINDINGS),
789
- populationDefect: {
790
- missingSourceKey: count(defect.missingSourceKey, 'memberOutcomes.populationDefect.missingSourceKey'),
791
- duplicateSourceKey: count(defect.duplicateSourceKey, 'memberOutcomes.populationDefect.duplicateSourceKey'),
792
- unknownSourceKey: count(defect.unknownSourceKey, 'memberOutcomes.populationDefect.unknownSourceKey'),
793
- },
794
- projectionErrors: asArray(value.projectionErrors, 'memberOutcomes.projectionErrors'),
795
- };
796
- }
797
-
798
- function memberHeadline(memberOutcomes) {
799
- if (!memberOutcomes) return [];
800
- const out = [];
801
- const d = memberOutcomes.populationDefect;
802
- if (d.missingSourceKey || d.duplicateSourceKey || d.unknownSourceKey) {
803
- out.push({ entity: memberOutcomes.entity, message: `${memberOutcomes.entity}: population gate refused the member pass (${d.missingSourceKey} missing, ${d.duplicateSourceKey} duplicate, ${d.unknownSourceKey} unknown source keys); no member was written` });
804
- }
805
- if (memberOutcomes.projectionErrors.length) {
806
- out.push({ entity: memberOutcomes.entity, message: `${memberOutcomes.entity}: ${memberOutcomes.projectionErrors.length} journal pairing error(s); member counts are not trustworthy until the journal is repaired` });
807
- }
808
- return out;
809
- }
810
-
811
- // `own(r, o)` -- the sum of a row's own structured entries for outcome `o`.
812
- function ownTally(row, outcome) {
813
- return row.reasons
814
- .filter((entry) => typeof entry === 'object' && entry.outcome === outcome)
815
- .reduce((sum, entry) => sum + entry.count, 0);
816
- }
817
-
818
- // Exclusions credit only deferred; losses credit only failed. A record with a
819
- // `subtype` covers only that entity/subtype; without one it joins the entity's shared pool.
820
- function buildCreditPools(records) {
821
- const scoped = new Map();
822
- const pool = new Map();
823
- for (const record of records) {
824
- if (record.subtype) {
825
- const key = `${record.entity}\0${record.subtype}`;
826
- scoped.set(key, (scoped.get(key) || 0) + record.count);
827
- } else {
828
- pool.set(record.entity, (pool.get(record.entity) || 0) + record.count);
829
- }
830
- }
831
- return { scoped, pool };
832
- }
833
-
834
- function spendCredit(map, key, amount) {
835
- if (amount <= 0) return 0;
836
- const available = map.get(key) || 0;
837
- const spent = Math.min(available, amount);
838
- if (spent > 0) map.set(key, available - spent);
839
- return spent;
840
- }
841
-
842
- // For each row, apply its subtype-scoped credit first, then draw from the
843
- // entity's shared pool -- but ONLY when the journal already attributes at least one reason of
844
- // this outcome to this specific row (`own(r, o) > 0`), or this row is its entity's only row. A
845
- // row whose own tally is exactly zero, in a multi-row entity, can be cleared only by a credit
846
- // explicitly scoped to its own subtype: count alone cannot show the pool's records are really
847
- // about this row, which is the "genuinely reason-less row" that must fail loudly.
848
- // Returns a parallel array of { unexplainedDeferred, unexplainedFailed }, same order/length as
849
- // `entityCompleteness`. Mutates nothing it is not given.
850
- function allocateUnexplainedCounts(entityCompleteness, exclusions, losses, memberOutcomes) {
851
- const deferredCredit = buildCreditPools(exclusions);
852
- const failedCredit = buildCreditPools(losses);
853
- const countByEntity = new Map();
854
- for (const row of entityCompleteness) {
855
- countByEntity.set(row.entity, (countByEntity.get(row.entity) || 0) + 1);
856
- }
857
-
858
- return entityCompleteness.map((row) => {
859
- // The member entity's unexplained is 0 for both outcomes, as today -- the
860
- // member breakdown already names every failed member's reason and recovery path.
861
- if (memberOutcomes && row.entity === memberOutcomes.entity) {
862
- return { unexplainedDeferred: 0, unexplainedFailed: 0 };
863
- }
864
- const ownDeferred = ownTally(row, 'deferred');
865
- const ownFailed = ownTally(row, 'failed');
866
- let residualDeferred = Math.max(0, row.deferred - ownDeferred);
867
- let residualFailed = Math.max(0, row.failed - ownFailed);
868
- const scopeKey = `${row.entity}\0${row.subtype}`;
869
-
870
- residualDeferred -= spendCredit(deferredCredit.scoped, scopeKey, residualDeferred);
871
- residualFailed -= spendCredit(failedCredit.scoped, scopeKey, residualFailed);
872
-
873
- const isOnlyRow = countByEntity.get(row.entity) === 1;
874
- if ((ownDeferred > 0 || isOnlyRow) && residualDeferred > 0) {
875
- residualDeferred -= spendCredit(deferredCredit.pool, row.entity, residualDeferred);
876
- }
877
- if ((ownFailed > 0 || isOnlyRow) && residualFailed > 0) {
878
- residualFailed -= spendCredit(failedCredit.pool, row.entity, residualFailed);
879
- }
880
- return { unexplainedDeferred: residualDeferred, unexplainedFailed: residualFailed };
881
- });
882
- }
883
-
884
- // The join between a completeness row and the journal rows that back its deferred
885
- // and failed counts: a completeness row cannot be identified by `targetEntityType` alone (two
886
- // subtypes can share one target type), so the join key is the row's own `sourceKeys` list, which
887
- // the codegen contract already asks every row to carry. Pure; returns a new rows array.
888
- //
889
- // `runIds` is required: a non-empty array of distinct, non-empty run id strings. An ordinary
890
- // report passes `[runId]`; a cutover repair regeneration lists the original run's id plus every
891
- // repair pass's own id, because a repair pass through the importer is a fresh process start and
892
- // its rows land under a new `runId` that the append-only journal never retrofits onto the
893
- // original run.
894
- function attachAttemptReasons(entityCompleteness, journalRows, { runIds } = {}) {
895
- if (!Array.isArray(runIds) || runIds.length === 0 || runIds.some((id) => typeof id !== 'string' || !id)) {
896
- throw new Error('attachAttemptReasons requires runIds: a non-empty array of non-empty run id strings');
897
- }
898
- const runIdSet = new Set(runIds);
899
-
900
- // One Map(sourceKey -> rowIndex). A key listed by two rows makes attribution ambiguous.
901
- const keyToIndex = new Map();
902
- entityCompleteness.forEach((row, index) => {
903
- for (const key of row.sourceKeys || []) {
904
- if (keyToIndex.has(key)) {
905
- throw new Error(`sourceKey ${key} is listed by ${keyToIndex.get(key)} and ${index}`);
906
- }
907
- keyToIndex.set(key, index);
908
- }
909
- });
910
-
911
- // One pass over journalRows: skip rows whose runId is not listed or whose sourceStableKey is
912
- // not in the map; keep the latest remaining row per key, in file order (same rule as
913
- // `foldAttemptsBySourceKey`, applied after the run filter) -- forward iteration with a Map
914
- // overwrite means the last (latest) row for a key always wins.
915
- const latestByKey = new Map();
916
- for (const row of journalRows || []) {
917
- if (!row || !runIdSet.has(row.runId)) continue;
918
- const key = row.sourceStableKey;
919
- if (!keyToIndex.has(key)) continue;
920
- latestByKey.set(key, row);
921
- }
922
-
923
- const tallies = entityCompleteness.map(() => new Map());
924
- for (const [key, row] of latestByKey) {
925
- let outcome = null;
926
- let code = null;
927
- if (row.status === 'deferred') {
928
- outcome = 'deferred';
929
- // The documented contract
930
- // (rp-import-codegen/SKILL.md's "Named reason" rule) is a top-level
931
- // `row.reason` string, but the real generated importer for that run wrote its
932
- // deferred rows' reason into `failure.errorCode` (the same field used for failed rows),
933
- // leaving `row.reason` absent on every one of its deferred rows. Preferring
934
- // `row.reason` keeps the documented contract authoritative when a future importer
935
- // actually writes it, while this fallback stops a real, already-recorded reason from
936
- // being silently dropped as "unexplained" just because it landed on the sibling field.
937
- code = typeof row.reason === 'string' && row.reason ? row.reason : row.failure && row.failure.errorCode;
938
- } else if (row.status === 'failed_retryable' || row.status === 'failed_terminal') {
939
- outcome = 'failed';
940
- code = row.failure && row.failure.errorCode;
941
- } else {
942
- continue;
943
- }
944
- if (typeof code !== 'string' || code === '') continue;
945
- const map = tallies[keyToIndex.get(key)];
946
- const tallyKey = `${outcome}\0${code}`;
947
- map.set(tallyKey, (map.get(tallyKey) || 0) + 1);
948
- }
949
-
950
- return entityCompleteness.map((row, index) => {
951
- if (!row.sourceKeys || !row.sourceKeys.length) {
952
- return row;
953
- }
954
- const structured = [...tallies[index].entries()]
955
- .map(([tallyKey, tallyCount]) => {
956
- const [outcome, code] = tallyKey.split('\0');
957
- return { outcome, code, count: tallyCount };
958
- })
959
- .sort((a, b) => (a.outcome === b.outcome ? (a.code < b.code ? -1 : a.code > b.code ? 1 : 0) : (a.outcome < b.outcome ? -1 : 1)));
960
- const strings = (row.reasons || []).filter((entry) => typeof entry === 'string');
961
- return { ...row, reasons: [...structured, ...strings] };
962
- });
963
- }
964
-
965
- // CMS records this run wrote per approved fallback capability: { capability, collections[], count }.
966
- function normalizeCmsFallbackWrites(value) {
967
- if (value === undefined || value === null) return [];
968
- if (!Array.isArray(value)) throw new Error('cmsFallback.writes must be an array');
969
- return value.map((row, index) => {
970
- if (!row || typeof row !== 'object' || Array.isArray(row)) throw new Error(`cmsFallback.writes[${index}] must be an object`);
971
- return {
972
- capability: requireString(row.capability, `cmsFallback.writes[${index}].capability`),
973
- collections: Array.isArray(row.collections) ? row.collections.map(String) : [],
974
- count: count(row.count, `cmsFallback.writes[${index}].count`),
975
- };
976
- });
977
- }
978
-
979
- function createCompletionReport(input = {}) {
980
- const entityCompleteness = asArray(input.entityCompleteness, 'entityCompleteness')
981
- .map((row, index) => normalizeCompletenessRow(row, index));
982
- const verification = input.verification || {};
983
- const verificationGaps = [];
984
- for (const row of entityCompleteness) {
985
- if (row.verificationKind === 'none') continue;
986
- const report = verification[row.entity];
987
- const entries = Array.isArray(report?.rows) ? report.rows : [];
988
- const unique = new Set(entries.map(r => r.sourceKey));
989
- const ids = entries.map(r => r.targetId);
990
- const kind = row.verificationKind;
991
- const expectedKeys = row.sourceKeys;
992
- const covered = Array.isArray(expectedKeys) && new Set(expectedKeys).size === row.inScope && expectedKeys.length === row.inScope && expectedKeys.every(k => unique.has(k)) && report?.siteId && report.siteId === (input.siteId || input.destinations?.siteId) && entries.every(r => typeof r.sourceKey === 'string' && r.sourceKey) && unique.size === entries.length && entries.length === row.inScope;
993
- const verified = entries.filter(r => validReceipt(r.receipt, { siteId: report?.siteId, sourceKey: r.sourceKey, targetId: r.targetId, kind })).length;
994
- if ((row.inScope && (!covered || verified !== row.inScope || new Set(ids).size !== ids.length)) || entries.length !== row.inScope) {
995
- // Absence stays exactly as blocking as a failed check; only the wording differs,
996
- // so a reader can tell "never supplied" from "supplied and failed".
997
- const absent = !Array.isArray(report?.rows) || report.rows.length === 0;
998
- verificationGaps.push({
999
- entity: row.entity,
1000
- message: absent
1001
- ? `${row.entity}: verification not recorded; supply verification input before completing`
1002
- : `${row.entity}: identity/value verification missing or invalid; reconcile source records before completing`,
1003
- });
1004
- }
1005
- }
1006
- const mismatches = entityCompleteness.filter((row) => row.mismatch);
1007
- const voucherReconciliation = normalizeVoucherReconciliation(input, entityCompleteness);
1008
- const voucherHeadline = VOUCHER_RECONCILIATION_WARNING.has(voucherReconciliation)
1009
- ? [{ entity: 'coupons', subtype: 'voucher-reconciliation', message: VOUCHER_RECONCILIATION_MESSAGE[voucherReconciliation] }]
1010
- : [];
1011
- // Missing accounting is not a clean payment history. Known order entities and mapped
1012
- // order targets must explicitly pass the collected list, including [] when it is empty.
1013
- const hasOrders = input.orderHistoryInScope === true || (input.entityCompleteness || []).some((row) =>
1014
- row.inScope > 0 && [row.entity, row.targetEntityType].some((name) => /(^|[/:._-])orders?$/i.test(name || '')));
1015
- if (hasOrders && !Array.isArray(input.stageResiduals)) {
1016
- throw new Error('stageResiduals must be an array for order history; collect outcomes before completing');
1017
- }
1018
- const stageResiduals = asArray(input.stageResiduals, 'stageResiduals')
1019
- .map((row, index) => normalizeStageResidual(row, index));
1020
- // A gate that fires on zero is noise, so only a row that actually has records speaks.
1021
- const openStageResiduals = stageResiduals.filter((row) => row.count > 0 && !ACCEPTED_STAGE_OUTCOMES.has(row.outcome));
1022
- const acceptedStageOutcomes = stageResiduals.filter((row) => row.count > 0 && ACCEPTED_STAGE_OUTCOMES.has(row.outcome));
1023
- const memberOutcomes = normalizeMemberOutcomes(input.memberOutcomes);
1024
- const headline = [
1025
- ...entityCompleteness.map(headlineForRow).filter(Boolean),
1026
- ...memberHeadline(memberOutcomes),
1027
- ...verificationGaps,
1028
- ...voucherHeadline,
1029
- ...openStageResiduals.map((row) => ({ entity: row.entity, stage: row.stage, message: stageResidualMessage(row) })),
1030
- ];
1031
- const warnings = [...asArray(input.warnings, 'warnings'), ...voucherHeadline.map((row) => row.message)];
1032
- const recoveryActions = [
1033
- ...asArray(input.recoveryActions, 'recoveryActions'),
1034
- ...verificationGaps.map(g => ({ entity: g.entity, action: g.message })),
1035
- ...openStageResiduals.map((row) => ({
1036
- entity: row.entity,
1037
- stage: row.stage,
1038
- action: stageResidualAction(row),
1039
- })),
1040
- ];
1041
- const blockedDataRequests = asArray(input.blockedDataRequests, 'blockedDataRequests')
1042
- .map((request, index) => normalizeBlockedDataRequest(request, index));
1043
- const urlPreservation = normalizeUrlPreservation(input.urlPreservation);
1044
- const operatorActions = asArray(input.operatorActions, 'operatorActions').map(normalizeOperatorAction);
1045
- for (const action of urlPreservation ? urlPreservation.operatorActions : []) {
1046
- if (!operatorActions.some((row) => row.code === action.code)) {
1047
- operatorActions.push(normalizeOperatorAction(action, operatorActions.length));
1048
- }
1049
- }
1050
- // Folded once, at the source, so no caller has to remember it. A caller-supplied row with the
1051
- // same code is authoritative; a derived duplicate would print the same urgent line twice.
1052
- const voucherAction = voucherOperatorAction(voucherReconciliation, entityCompleteness);
1053
- if (voucherAction && !operatorActions.some((row) => row.code === voucherAction.code)) {
1054
- operatorActions.push(normalizeOperatorAction(voucherAction, operatorActions.length));
1055
- }
1056
- // Binds a supplied `coverageCheck` to `input.runId` and decides the escalation --
1057
- // never recomputes the check itself.
1058
- const coverageEffect = resolveCoverageCheckEffect(input);
1059
- if (coverageEffect.operatorActionRow && !operatorActions.some((row) => row.code === coverageEffect.operatorActionRow.code)) {
1060
- operatorActions.push(normalizeOperatorAction(coverageEffect.operatorActionRow, operatorActions.length));
1061
- }
1062
- // CMS fallback for recognized plugin capabilities: one action per approved fallback (feature
1063
- // still absent), per undecided/declined eligible capability (records not migrated), per write
1064
- // the write-time guard refused, and per capability whose earlier CMS records no longer have a
1065
- // valid approval. `cmsFallbackWrites` is persisted so the next run can detect withdrawal.
1066
- const cmsFallbackInput = input.cmsFallback || null;
1067
- const cmsFallbackWrites = cmsFallbackInput ? normalizeCmsFallbackWrites(cmsFallbackInput.writes) : [];
1068
- if (cmsFallbackInput) {
1069
- const derived = cmsFallbackOperatorActions({
1070
- coverage: cmsFallbackInput.coverage || null,
1071
- refusals: Array.isArray(cmsFallbackInput.refusals) ? cmsFallbackInput.refusals : [],
1072
- previousWrites: normalizeCmsFallbackWrites(cmsFallbackInput.previousWrites
1073
- || (cmsFallbackInput.previousReport && cmsFallbackInput.previousReport.cmsFallbackWrites)),
1074
- writes: cmsFallbackWrites,
1075
- });
1076
- for (const row of derived) {
1077
- if (!operatorActions.some((existing) => existing.code === row.code && existing.entity === row.entity)) {
1078
- operatorActions.push(normalizeOperatorAction(row, operatorActions.length));
1079
- }
1080
- }
1081
- }
1082
- const losses = asArray(input.losses, 'losses').map(normalizeLoss);
1083
- const exclusions = asArray(input.exclusions, 'exclusions').map(normalizeExclusion);
1084
- const unresolved = asArray(input.unresolved, 'unresolved').map(normalizeUnresolved);
1085
- const droppedFields = asArray(input.droppedFields, 'droppedFields').map(normalizeDroppedField);
1086
-
1087
- // Where the durable rows are absent for an entity that reports a shortfall, the
1088
- // section says the shortfall is unexplained and the final status carries the mismatch. An
1089
- // entity that lost records with nothing on record explaining how is exactly the case this check
1090
- // exists to stop from rendering as a clean, empty section.
1091
- //
1092
- // Dropped fields never explain a missing record -- they are about records that did
1093
- // land -- so they are deliberately NOT in this set. `failed` is also no longer part of this
1094
- // predicate: a failed row now gets its own counted guard entry below, never the bare
1095
- // reconciliation message.
1096
- const mismatchExplainedEntities = new Set([
1097
- ...losses.map((row) => row.entity),
1098
- ...exclusions.map((row) => row.entity),
1099
- ...unresolved.map((row) => row.entity),
1100
- // A scopeOverflow row already carries its own proof of why it mismatches
1101
- // (the headline text plus the scopeOverflow count on its mismatches entry) -- exactly as
1102
- // self-explaining as a caller-supplied losses/exclusions/unresolved row. Never fabricate a
1103
- // synthetic entry in one of those arrays for it; that would misrepresent a counting-error
1104
- // row as a deliberate loss or exclusion.
1105
- ...entityCompleteness.filter((row) => row.scopeOverflow > 0).map((row) => row.entity),
1106
- // The member breakdown names every failed member's reason and recovery path.
1107
- ...(memberOutcomes ? [memberOutcomes.entity] : []),
1108
- ]);
1109
- const unexplainedShortfalls = entityCompleteness
1110
- .filter((row) => (row.mismatch || row.unexpectedSkipped > 0) && !mismatchExplainedEntities.has(row.entity))
1111
- .map((row) => ({
1112
- entity: row.entity,
1113
- subtype: row.subtype,
1114
- shortfall: row.expectedReconciled - row.reconciled,
1115
- message: `${row.entity}/${row.subtype}: shortfall unexplained -- no loss, exclusion or unresolved row accounts for it`,
1116
- }));
1117
- // Deferred and failed are counted, not just named. A row's deferred records
1118
- // are explained only by its own journal-backed tally and by exclusions; its failed records only
1119
- // by its own tally and by losses -- each capped at the row's actual residual, never spilling
1120
- // into another row (except through the gated, provenance-checked shared pool above).
1121
- const counts = allocateUnexplainedCounts(entityCompleteness, exclusions, losses, memberOutcomes);
1122
- entityCompleteness.forEach((row, index) => {
1123
- const { unexplainedDeferred, unexplainedFailed } = counts[index];
1124
- if (unexplainedDeferred > 0) {
1125
- unexplainedShortfalls.push({
1126
- entity: row.entity,
1127
- subtype: row.subtype,
1128
- outcome: 'deferred',
1129
- shortfall: unexplainedDeferred,
1130
- message: `${row.entity}/${row.subtype}: ${unexplainedDeferred} deferred with no recorded reason`,
1131
- });
1132
- }
1133
- if (unexplainedFailed > 0) {
1134
- unexplainedShortfalls.push({
1135
- entity: row.entity,
1136
- subtype: row.subtype,
1137
- outcome: 'failed',
1138
- shortfall: unexplainedFailed,
1139
- message: `${row.entity}/${row.subtype}: ${unexplainedFailed} failed with no recorded reason`,
1140
- });
1141
- }
1142
- });
1143
- // An `unresolved` counter must be matched by unresolved[] rows for that entity.
1144
- for (const row of entityCompleteness) {
1145
- if (!row.unresolved) continue;
1146
- const listed = unresolved.filter((entry) => entry.entity === row.entity).reduce((sum, entry) => sum + entry.count, 0);
1147
- if (listed < row.unresolved) {
1148
- unexplainedShortfalls.push({
1149
- entity: row.entity,
1150
- subtype: row.subtype,
1151
- shortfall: row.unresolved - listed,
1152
- message: `${row.entity}/${row.subtype}: ${row.unresolved - listed} unresolved record(s) with no unresolved row naming them`,
1153
- });
1154
- }
1155
- }
1156
-
1157
- const lastWriteAt = input.lastWriteAt === undefined || input.lastWriteAt === null
1158
- ? null
1159
- : requireString(input.lastWriteAt, 'lastWriteAt');
1160
-
1161
- const status = chooseCompletionStatus({
1162
- statuses: input.statuses,
1163
- aborted: input.aborted,
1164
- hasMismatches: mismatches.length > 0 || verificationGaps.length > 0 || unresolved.length > 0 || unexplainedShortfalls.length > 0
1165
- || coverageEffect.hasMismatch,
1166
- hasFailures: hasCount(entityCompleteness, 'failed') || losses.length > 0
1167
- || openStageResiduals.length > 0
1168
- || blockedDataRequests.some((request) => request.aggregateOutcome === 'failed'),
1169
- hasDeferred: hasCount(entityCompleteness, 'deferred') || blockedDataRequests.some((request) => request.aggregateOutcome === 'deferred'),
1170
- hasRecoveredRecords: recoveryActions.length > 0 || Boolean(input.hasRecoveredRecords),
1171
- // A deliberate exclusion is a choice, not a loss -- but an exclusion nobody gated is an
1172
- // unreviewed filter, and that is a warning.
1173
- hasWarnings: warnings.length > 0 || Boolean(input.hasWarnings) || droppedFields.length > 0
1174
- || exclusions.some((row) => !row.operatorGateRecorded)
1175
- || blockedDataRequests.some((request) => request.aggregateOutcome === 'warning')
1176
- || coverageEffect.hasWarnings,
1177
- });
1178
-
1179
- return {
1180
- schemaVersion: 1,
1181
- runId: input.runId || null,
1182
- status,
1183
- headline,
1184
- voucherReconciliation,
1185
- // The bound (or rejected/omitted) coverage check and whether this run declared
1186
- // participation in the contract at all -- `website-handoff.js` uses both to decide whether its
1187
- // "Count cross-check" section applies to this run.
1188
- coverageCheck: coverageEffect.coverageCheck,
1189
- coverageCheckExpected: coverageEffect.coverageCheckExpected,
1190
- entityCompleteness,
1191
- stageResiduals,
1192
- acceptedStageOutcomes,
1193
- verificationGaps,
1194
- verification,
1195
- mismatches: mismatches.map((row) => ({
1196
- entity: row.entity,
1197
- subtype: row.subtype,
1198
- expectedReconciled: row.expectedReconciled,
1199
- reconciled: row.reconciled,
1200
- unexpectedSkipped: row.unexpectedSkipped,
1201
- scopeOverflow: row.scopeOverflow,
1202
- })).concat(verificationGaps.map(gap => ({ ...gap, type: 'identity_value_verification' }))),
1203
- warnings,
1204
- recoveryActions,
1205
- blockedDataRequests,
1206
- operatorActions,
1207
- cmsFallbackWrites,
1208
- losses,
1209
- exclusions,
1210
- unresolved,
1211
- droppedFields,
1212
- unexplainedShortfalls,
1213
- memberOutcomes,
1214
- // The handoff proves it postdates the import by comparing its own
1215
- // `generatedAt` against this value -- never against a file mtime, which a copy refreshes.
1216
- lastWriteAt,
1217
- artifacts: input.artifacts || {},
1218
- destinations: input.destinations || {},
1219
- urlPreservation,
1220
- };
1221
- }
1222
-
1223
- const URL_PRESERVATION_STATUS = ['verified', 'action_required', 'pending_cutover_verification', 'pending_website_build'];
1224
-
1225
- function normalizeUrlPreservation(value) {
1226
- if (value === undefined || value === null) return null;
1227
- if (typeof value !== 'object' || Array.isArray(value)) throw new Error('urlPreservation must be an object');
1228
- // Older callers passed the import-time policy object; keep it verbatim.
1229
- if (value.status === undefined) return { ...value, operatorActions: [] };
1230
- if (!URL_PRESERVATION_STATUS.includes(value.status)) {
1231
- throw new Error(`urlPreservation.status must be one of ${URL_PRESERVATION_STATUS.join(', ')}`);
1232
- }
1233
- return { ...value, operatorActions: asArray(value.operatorActions, 'urlPreservation.operatorActions') };
1234
- }
1235
-
1236
- function causeLine(row) {
1237
- // `unverified` renders the words and nothing else. No cause text, no hypothesis.
1238
- if (row.causeConfidence !== 'verified-source' && row.causeConfidence !== 'verified-target') {
1239
- return 'cause unverified';
1240
- }
1241
- return `${row.cause} (${row.causeConfidence}; established by ${row.check.kind} on ${row.check.target} -> ${row.check.result})`;
1242
- }
1243
-
1244
- // "Permanent Losses: None" must not read as "nothing permanent happened" while
1245
- // Deliberate Exclusions lists records that were permanently left out. Only claim the
1246
- // exclusions were reviewed when every row has an operator gate recorded.
1247
- function emptyPermanentLossesLine(exclusions = []) {
1248
- if (!exclusions.length) return '- None.';
1249
- return exclusions.every((row) => row.operatorGateRecorded)
1250
- ? '- None (see Deliberate Exclusions below for permanent, operator-reviewed gaps).'
1251
- : '- None (see Deliberate Exclusions below for permanent gaps; some are not operator-reviewed).';
1252
- }
1253
-
1254
- // One line per outcome for a row with a nonzero count: the tallied reasons, and
1255
- // -- only when the tallies do not already cover the whole count -- the remainder with no
1256
- // recorded reason at all. `count` always comes from the row's own field (`deferred`/`failed`),
1257
- // never from the allocation/pool step, so this line is independent of whether an exclusion or
1258
- // loss credit later clears the row in "Unexplained Shortfalls".
1259
- function reasonLine(row, outcome, totalCount) {
1260
- const tallies = row.reasons.filter((entry) => typeof entry === 'object' && entry.outcome === outcome);
1261
- if (!tallies.length) {
1262
- return `- ${row.entity}/${row.subtype}: ${totalCount} ${outcome} -- no recorded reason`;
1263
- }
1264
- const tallySum = tallies.reduce((sum, entry) => sum + entry.count, 0);
1265
- const remainder = totalCount - tallySum;
1266
- const tallyText = tallies.map((entry) => `${entry.code}: ${entry.count}`).join(', ');
1267
- const remainderText = remainder > 0 ? `; ${remainder} with no recorded reason` : '';
1268
- return `- ${row.entity}/${row.subtype}: ${totalCount} ${outcome} -- ${tallyText}${remainderText}`;
1269
- }
1270
-
1271
- // The user-facing summary is RENDERED from the report object, never
1272
- // composed independently and never derived from `execution-log.md`.
1273
- function renderCompletionSummary(report) {
1274
- const lines = [
1275
- '# Migration Completion Summary',
1276
- '',
1277
- `- Status: ${report.status}`,
1278
- `- Run id: ${report.runId || 'not recorded'}`,
1279
- `- Last write: ${report.lastWriteAt || 'not recorded'}`,
1280
- ...(report.voucherReconciliation ? [`- Voucher reconciliation: ${report.voucherReconciliation}`] : []),
1281
- ...(report.headline || []).map((row) => `- ${row.message}`),
1282
- '',
1283
- '## Urgent Operator Actions',
1284
- '',
1285
- ];
1286
- if (!report.operatorActions.length) {
1287
- lines.push('- None.');
1288
- } else {
1289
- for (const action of report.operatorActions) {
1290
- lines.push(`- [${action.severity}] ${action.code}: ${action.action} (${action.affectedCount === null ? 'affected count unknown' : `${action.affectedCount} affected`}; act now because ${action.deadlineReason})`);
1291
- }
1292
- }
1293
-
1294
- if (report.urlPreservation && report.urlPreservation.status) {
1295
- const u = report.urlPreservation;
1296
- const c = u.counts || {};
1297
- lines.push('', '## Old Links', '', `- Status: ${u.status}${u.coverageComplete === false ? ' (source redirect discovery incomplete)' : ''}`);
1298
- lines.push(`- Verified: ${(c.verified_direct || 0) + (c.verified_redirect || 0)}; not verified: ${c.not_verified || 0}; unresolved: ${c.unresolved || 0}; manual review: ${c.manual_review || 0}; failed: ${c.failed || 0}`);
1299
- if (u.status !== 'verified') lines.push(`- Old emails and bookmarks using unconfirmed links may fail. Details: ${u.detailPath || 'execution/url-preservation-report.md'}`);
1300
- }
1301
- if (report.readBack) lines.push(...require('./read-back-summary').renderReadBackSummary(report.readBack));
1302
-
1303
- lines.push('', '## Per-Entity Reconciliation', '', '| Entity | Extracted | In scope | Landed | Unreconciled |', '| --- | --- | --- | --- | --- |');
1304
- if (!report.entityCompleteness.length) {
1305
- lines.push('| (none) | 0 | 0 | 0 | 0 |');
1306
- } else {
1307
- for (const row of report.entityCompleteness) {
1308
- lines.push(`| ${row.entity}/${row.subtype} | ${row.extracted} | ${row.inScope} | ${row.imported + row.alreadyPresentByCrosswalk} | ${row.expectedReconciled - row.reconciled} |`);
1309
- }
1310
- }
1311
-
1312
- lines.push('', '## Permanent Losses', '');
1313
- if (!report.losses.length) lines.push(emptyPermanentLossesLine(report.exclusions));
1314
- else for (const row of report.losses) lines.push(`- ${row.entity}: ${row.count} lost (${row.reasonCode}); ${row.whyNoRetry}; ${causeLine(row)}`);
1315
-
1316
- lines.push('', '## Deliberate Exclusions', '');
1317
- if (!report.exclusions.length) lines.push('- None.');
1318
- else for (const row of report.exclusions) lines.push(`- ${row.entity}: ${row.count} excluded (${row.reasonCode}); ${row.rationale}; operator gate recorded: ${row.operatorGateRecorded}`);
1319
-
1320
- lines.push('', '## Unresolved And Orphaned', '');
1321
- if (!report.unresolved.length) lines.push('- None.');
1322
- else for (const row of report.unresolved) lines.push(`- ${row.entity}: ${row.count} ${row.kind}; ${causeLine(row)}`);
1323
-
1324
- lines.push('', '## Fields Dropped For The Destination', '');
1325
- if (!report.droppedFields.length) lines.push('- None.');
1326
- else for (const row of report.droppedFields) lines.push(`- ${row.entity}.${row.field}: ${row.recordCount} records (${row.reasonCode})`);
1327
-
1328
- if ((report.acceptedStageOutcomes || []).length) {
1329
- lines.push('', '## Accepted And Materialized Gaps', '');
1330
- for (const row of report.acceptedStageOutcomes) lines.push(`- ${stageResidualAction(row)}`);
1331
- }
1332
-
1333
- if (report.memberOutcomes) {
1334
- const m = report.memberOutcomes;
1335
- lines.push('', '## Members', '', `- Population: ${m.populationBasis}`);
1336
- for (const [cls, entry] of Object.entries(m.byClass || {})) {
1337
- lines.push(`- ${entry.outcome}${cls !== entry.outcome && /^(failed-|reconciled-)/.test(cls) ? ` (${cls})` : ''}: ${entry.count}${entry.count && entry.nextAction ? ` -- ${entry.nextAction}` : ''}`);
1338
- }
1339
- if (m.danglingStarted) lines.push(`- write started, never concluded: ${m.danglingStarted}`);
1340
- if (m.unexpectedSkipped) lines.push(`- no journal row: ${m.unexpectedSkipped}`);
1341
- for (const [code, n] of Object.entries(m.byFinding)) lines.push(`- finding ${code}: ${n}`);
1342
- }
1343
-
1344
- if (report.recoveryActions.length) {
1345
- lines.push('', '## Recovery Actions', '');
1346
- for (const row of report.recoveryActions) lines.push(`- ${row.action}`);
1347
- }
1348
-
1349
- // Before "Unexplained Shortfalls": a reader sees why records did not land
1350
- // without opening JSON, and sees the unexplained remainder on the same line.
1351
- lines.push('', '## Why Records Did Not Land', '');
1352
- const reasonRows = report.entityCompleteness.filter((row) => row.deferred > 0 || row.failed > 0);
1353
- if (!reasonRows.length) {
1354
- lines.push('- None.');
1355
- } else {
1356
- for (const row of reasonRows) {
1357
- if (row.deferred > 0) lines.push(reasonLine(row, 'deferred', row.deferred));
1358
- if (row.failed > 0) lines.push(reasonLine(row, 'failed', row.failed));
1359
- for (const entry of row.reasons.filter((r) => typeof r === 'string')) {
1360
- lines.push(` - note: ${entry}`);
1361
- }
1362
- }
1363
- }
1364
-
1365
- if (report.unexplainedShortfalls.length) {
1366
- lines.push('', '## Unexplained Shortfalls', '');
1367
- for (const row of report.unexplainedShortfalls) lines.push(`- ${row.message}`);
1368
- }
1369
-
1370
- // Only a joined (schema v2) report carries this; an un-joined in-memory report
1371
- // renders exactly as before.
1372
- if (Array.isArray(report.sourceCoverage)) {
1373
- lines.push('', '## Not Migrated From The Source', '');
1374
- if (report.sourceCoverageRecorded === false) lines.push('- Source coverage was not recorded for this run (discovery predates the coverage contract).');
1375
- else if (!report.sourceCoverage.length) lines.push('- None.');
1376
- else for (const row of report.sourceCoverage) lines.push(sourceCoverageLine(row));
1377
- }
1378
-
1379
- return `${lines.join('\n')}\n`;
1380
- }
1381
-
1382
- function sourceCoverageLine(row) {
1383
- const label = row.capability || row.sourceEntity;
1384
- return `- ${label} (${row.reason}; ${row.treatment}): ${row.cutoverAction}`;
1385
- }
1386
-
1387
- async function writeFileAtomic(filePath, text) {
1388
- await fs.mkdir(path.dirname(filePath), { recursive: true });
1389
- const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;
1390
- await fs.writeFile(tempPath, text, 'utf8');
1391
- await fs.rename(tempPath, filePath);
1392
- }
1393
-
1394
- // Before this, `createCompletionReport` built the object and nothing
1395
- // shipped wrote it: the codegen snippet told generated importers to "persist it using the shared
1396
- // runtime" and the shared runtime had no such function, so no non-quick-mode run ever produced
1397
- // the artifact its own completion gate keys on. One shared writer, and the summary rendered from
1398
- // the same object it just wrote.
1399
- //
1400
- // The source-coverage join happens HERE, inside the one writer, so status is
1401
- // computed once from everything. `createCompletionReport` already chose a status before this
1402
- // function sees the project; folding the coverage floor in with the same rank (`worseStatus`)
1403
- // equals a one-pass computation. The written artifact is schema v2.
1404
- async function joinSourceCoverage(projectDir, report) {
1405
- if (Object.prototype.hasOwnProperty.call(report, 'sourceCoverage') || Object.prototype.hasOwnProperty.call(report, 'sourceCoverageRecorded')) {
1406
- throw new Error('writeCompletionReport: the report already carries sourceCoverage; the writer owns that join and a caller cannot pre-empt it');
1407
- }
1408
- // Throws on a stamped project whose coverage file is missing, malformed or unreconciled.
1409
- const coverage = await summarizeProjectCoverage(projectDir);
1410
- const giftCards = await evaluateGiftCardCutover(projectDir);
1411
- const operatorActions = [...asArray(report.operatorActions, 'operatorActions')].filter((row) => row.code !== GIFT_ACTION_CODE);
1412
- for (const row of coverage.operatorActions) {
1413
- operatorActions.push(normalizeOperatorAction(row, operatorActions.length));
1414
- }
1415
- const linkAudit = await readLinkAudit(projectDir);
1416
- for (const row of linkOperatorActions(linkAudit)) {
1417
- if (!operatorActions.some((existing) => existing.code === row.code)) operatorActions.push(normalizeOperatorAction(row, operatorActions.length));
1418
- }
1419
- const linkStatus = linkAudit && linkOperatorActions(linkAudit).length ? 'complete_with_warnings' : null;
1420
- // Remaining Editor website/publication work. A caller-supplied row with the
1421
- // same code is authoritative and is never duplicated.
1422
- for (const row of await projectDestinationOperatorActions(projectDir)) {
1423
- if (!operatorActions.some((existing) => existing.code === row.code)) {
1424
- operatorActions.push(normalizeOperatorAction(row, operatorActions.length));
1425
- }
1426
- }
1427
- // Source access that outlives the migration (the Shopify staff account) is an
1428
- // operator action beside the coverage rows until its removal is confirmed. It is an action, not
1429
- // a coverage gap, so status is unchanged.
1430
- for (const row of sourceAccessOperatorActions(projectDir)) {
1431
- if (!operatorActions.some((existing) => existing.code === row.code && existing.entity === row.entity)) {
1432
- operatorActions.push(normalizeOperatorAction(row, operatorActions.length));
1433
- }
1434
- }
1435
- // Mapping may accept withheld Shopify details, but Shopify remains their only
1436
- // copy until the merchant's export is confirmed after the latest read. This action is separate
1437
- // from sourceCoverage's disposition and does not change report status.
1438
- for (const row of withheldDetailsOperatorActions(projectDir)) {
1439
- if (!operatorActions.some((existing) => existing.code === row.code && existing.entity === row.entity)) {
1440
- operatorActions.push(normalizeOperatorAction(row, operatorActions.length));
1441
- }
1442
- }
1443
- if (giftCards.action) operatorActions.push(normalizeOperatorAction(giftCards.action, operatorActions.length));
1444
- const sourceCoverage = coverage.sourceCoverage.map((row) => (row.coverageId === GIFT_CODES_COVERAGE_ID
1445
- ? { ...row, cutoverAction: giftCards.cutoverAction || row.cutoverAction }
1446
- : row));
1447
- return {
1448
- ...report,
1449
- schemaVersion: 2,
1450
- status: linkStatus ? worseStatus(coverage.status ? worseStatus(report.status, coverage.status) : report.status, linkStatus)
1451
- : coverage.status ? worseStatus(report.status, coverage.status) : report.status,
1452
- headline: [...asArray(report.headline, 'headline'), ...coverage.headline],
1453
- operatorActions,
1454
- ...(linkAudit ? { linkAudit: {
1455
- path: LINK_AUDIT_PATH, stage: linkAudit.stage, counts: linkAudit.counts, estimate: linkAudit.estimate || null,
1456
- pendingOccurrenceIds: linkAudit.pendingDestinations.flatMap((row) => row.occurrenceIds),
1457
- unresolvedOccurrenceIds: linkAudit.unresolved.flatMap((row) => row.occurrenceIds),
1458
- pendingWriterFields: (linkAudit.writerIntegrations || []).filter((row) => row.status === 'pending').map((row) => row.field),
1459
- missingCutoverUiIntegration: true,
1460
- } } : {}),
1461
- sourceCoverageRecorded: coverage.sourceCoverageRecorded,
1462
- ...(coverage.sourceCoverageReason ? { sourceCoverageReason: coverage.sourceCoverageReason } : {}),
1463
- sourceCoverage,
1464
- };
1465
- }
1466
-
1467
- async function dependencyOperatorActions(projectDir) {
1468
- let diagnostic;
1469
- try { diagnostic = JSON.parse(await fs.readFile(path.join(projectDir, 'execution/dependency-readiness.json'), 'utf8')); } catch (error) { if (error.code === 'ENOENT') return []; throw error; }
1470
- const { rows } = await require('./local-state').loadAttemptJournal(projectDir).catch(error => { if (error.code === 'ENOENT') return { rows: [] }; throw error; });
1471
- const recovery = require('./dependency-recovery'), indexes = new Map(), result = [];
1472
- for (const task of Object.values(diagnostic.tasks || {})) if (!indexes.has(task.siteId)) indexes.set(task.siteId, recovery.foldRecoveryAttempts(rows, task.siteId));
1473
- for (const task of Object.values(diagnostic.tasks || {})) {
1474
- const waiting = recovery.waitingForTask(indexes.get(task.siteId), task.taskId);
1475
- const groups = new Map();
1476
- for (const block of task.blocked || []) groups.set(`${block.ref}:${block.recovery}`, { ref: block.ref, recovery: block.recovery, count: task.affectedCount ?? null });
1477
- for (const row of waiting) { const ref = row.deferral.ref || row.deferral.reason, key = `${ref}:resume-deferred`; if (!groups.has(key)) groups.set(key, { ref, recovery: 'resume-deferred', count: 0 }); groups.get(key).count++; }
1478
- for (const group of groups.values()) result.push({ code: 'dependency-readiness-blocked', severity: 'blocker', entity: task.taskId, affectedCount: group.count,
1479
- deadlineReason: 'Resolve before launch; affected dependent records have not finished importing.',
1480
- action: `Requires Import Operator. Prerequisites: original migration project, source snapshot and current-site access; retain existing owner approvals. Copy prompt: Inspect execution/dependency-readiness.json task ${task.taskId} and ref ${group.ref}; resolve ${group.recovery}, re-evaluate and resume only eligible deferred records. Read back uncertain writes, never infer completion from old-site evidence and do not resend existing orders. Completion requires terminal outcomes for dependent records as well as repaired prerequisites.` });
1481
- }
1482
- return result;
1483
- }
1484
- async function writeCompletionReport(projectDir, unjoinedReport, { runId = null, appendLog = true } = {}) {
1485
- if (!unjoinedReport || typeof unjoinedReport !== 'object' || !unjoinedReport.status) {
1486
- throw new Error('writeCompletionReport requires a completion report object');
1487
- }
1488
- const censusReport = JSON.parse(JSON.stringify(unjoinedReport));
1489
- if ((censusReport.exclusions || []).some(row => row.censusId)) {
1490
- const { readReconciliation, ownerApprovedCensusIds } = require('./census-reconciliation.js');
1491
- const reconciliation = await readReconciliation(projectDir);
1492
- const approved = await ownerApprovedCensusIds(projectDir);
1493
- for (const row of censusReport.exclusions) {
1494
- if (!row.censusId) continue;
1495
- if (!reconciliation?.rows?.some(entry => entry.censusId === row.censusId && ['excluded','unsupported'].includes(entry.state))) throw Object.assign(new Error('exclusion_census_id_invalid'), { code: 'exclusion_census_id_invalid' });
1496
- row.operatorGateRecorded = approved.has(row.censusId);
1497
- if (!row.operatorGateRecorded && censusReport.status === 'complete') censusReport.status = 'complete_with_warnings';
1498
- }
1499
- }
1500
- await require('./read-back-approval').recoverAcknowledgements(projectDir);
1501
- const gateState = require('./read-back-state');
1502
- const entities = await require('./read-back-approval').gatedEntities(projectDir);
1503
- const gateRun = censusReport.runId || runId || 'unidentified-completion';
1504
- if (entities.length) await gateState.update(projectDir, gate => {
1505
- gate.runs[gateRun] ||= { entities: {} };
1506
- for (const entity of entities) gate.runs[gateRun].entities[entity] ||= { status: 'unknown', stopReason: 'gate-not-run', canaries: [] };
1507
- });
1508
- for (const entity of entities) await require('./read-back-approval').createAcknowledgement(projectDir, gateRun, entity);
1509
- const gate = await gateState.load(projectDir);
1510
- const readBack = require('./read-back-summary').projectReadBackSummary(gate);
1511
- const gateActions = require('./read-back-gate').operatorActions(gate);
1512
- const readinessActions = await dependencyOperatorActions(projectDir);
1513
- gateActions.push(...readinessActions);
1514
- const blocked = gateActions.some(a => ['read-back-gate-stopped', 'read-back-suspect-interval'].includes(a.code));
1515
- let report = await joinSourceCoverage(projectDir, { ...censusReport,
1516
- readBack,
1517
- status: blocked ? worseStatus(censusReport.status, 'incomplete_with_failures') : censusReport.status,
1518
- operatorActions: [...(censusReport.operatorActions || []).filter(a => !a.code?.startsWith('read-back-')), ...gateActions] });
1519
- let redirectReport = null;
1520
- try {
1521
- redirectReport = JSON.parse(await fs.readFile(path.join(projectDir, 'execution', 'url-rewrite-report.json'), 'utf8'));
1522
- } catch (error) {
1523
- if (error.code !== 'ENOENT') throw error;
1524
- }
1525
- if (redirectReport) {
1526
- const actions = Array.isArray(report.operatorActions) ? report.operatorActions : [];
1527
- const known = new Set(actions.map((row) => `${row.code}\t${row.entity}`));
1528
- const redirectSources = new Map((redirectReport.rules || []).map((row) => [row.sourceStableKey, row.source]));
1529
- const urlVerificationOwned = new Set((report.urlPreservation?.urls || [])
1530
- .filter((row) => !String(row.disposition).startsWith('verified_'))
1531
- .map((row) => row.originalUrl));
1532
- for (const action of redirectReport.operatorActions || []) {
1533
- const source = redirectSources.get(action.entity);
1534
- if (source && urlVerificationOwned.has(source) &&
1535
- action.code === 'cutover_links_pending_verification') continue;
1536
- const key = `${action.code}\t${action.entity}`;
1537
- if (!known.has(key)) actions.push(normalizeOperatorAction(action, actions.length));
1538
- known.add(key);
1539
- }
1540
- report = { ...report, operatorActions: actions };
1541
- }
1542
- const reportPath = path.join(projectDir, COMPLETION_REPORT_FILE);
1543
- const summaryPath = path.join(projectDir, COMPLETION_SUMMARY_FILE);
1544
- const summary = renderCompletionSummary(report);
1545
- await writeFileAtomic(reportPath, `${JSON.stringify(report, null, 2)}\n`);
1546
- await writeFileAtomic(summaryPath, summary);
1547
- if (appendLog) {
1548
- await appendExecutionLog(projectDir, {
1549
- runId: runId || report.runId || 'unknown-run',
1550
- phase: 'completion',
1551
- event: 'completion_report_written',
1552
- detail: `final outcome recorded with status ${report.status}`,
1553
- artifacts: [COMPLETION_REPORT_FILE, COMPLETION_SUMMARY_FILE],
1554
- });
1555
- }
1556
- return { reportPath, summaryPath, summary, report };
1557
- }
1558
-
1559
- module.exports = {
1560
- dependencyOperatorActions,
1561
- COMPLETION_STATUS,
1562
- VOUCHER_RECONCILIATION,
1563
- handoffVoucherSignal,
1564
- COMPLETION_REPORT_FILE,
1565
- COMPLETION_SUMMARY_FILE,
1566
- CAUSE_CONFIDENCE,
1567
- normalizeCauseAttribution,
1568
- renderCompletionSummary,
1569
- emptyPermanentLossesLine,
1570
- writeCompletionReport,
1571
- chooseCompletionStatus,
1572
- createCompletionReport,
1573
- normalizeCompletenessRow,
1574
- normalizeBlockedDataRequest,
1575
- normalizeOperatorAction,
1576
- normalizeStageResidual,
1577
- normalizeMemberOutcomes,
1578
- collectOrderStageResiduals,
1579
- attachAttemptReasons,
1580
- };