@wix/agent-skills 1.35.1 → 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 (820) hide show
  1. package/package.json +8 -3
  2. package/skills/wix-app/references/CODE_QUALITY.md +1 -1
  3. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +27 -29
  4. package/skills/wix-app/references/editor-react-component/ANIMATED-COMPONENTS.md +1 -1
  5. package/skills/wix-app/references/editor-react-component/COMPONENT-CONTRACT.md +26 -25
  6. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +12 -42
  7. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +9 -20
  8. package/skills/wix-app/references/editor-react-component/MANIFEST-ERRORS.md +5 -4
  9. package/skills/wix-app/references/editor-react-component/PARTS.md +1 -1
  10. package/skills/wix-app/references/editor-react-component/PROPS-VS-CSS.md +1 -1
  11. package/skills/wix-app/references/editor-react-component/VECTOR-ART.md +95 -0
  12. package/skills/wix-app/references/editor-react-component/VISUAL-QUALITY.md +39 -0
  13. package/skills/wix-docs/references/CALLING.md +1 -1
  14. package/skills/wix-headless-kit/guides/api-run.md +1 -1
  15. package/skills/wix-headless-kit/install/pins.json +1 -1
  16. package/skills/wix-headless-templates/blog/seed/seed-blog.mjs +1 -1
  17. package/skills/wix-headless-templates/donations/app/wix/donations/campaigns.ts +0 -1
  18. package/skills/wix-headless-templates/donations/app/wix/donations/donate.ts +1 -1
  19. package/skills/wix-headless-templates/donations/project/src/wix/donations/campaigns.ts +0 -1
  20. package/skills/wix-headless-templates/donations/project/src/wix/donations/donate.ts +1 -1
  21. package/skills/wix-headless-templates/donations/rest/campaigns.ts +0 -1
  22. package/skills/wix-headless-templates/donations/rest/donate.ts +1 -1
  23. package/skills/wix-headless-templates/events/seed/seed-events.mjs +1 -1
  24. package/skills/wix-headless-templates/faq/INSTRUCTIONS.md +1 -1
  25. package/skills/wix-headless-templates/faq/app/wix/faq/faq.ts +2 -2
  26. package/skills/wix-headless-templates/faq/project/src/wix/faq/faq.ts +2 -2
  27. package/skills/wix-headless-templates/faq/rest/faq.ts +2 -2
  28. package/skills/wix-headless-templates/faq/seed/SEED.md +1 -1
  29. package/skills/wix-headless-templates/faq/seed/read-site.mjs +1 -1
  30. package/skills/wix-headless-templates/faq/seed/seed-faq.mjs +5 -5
  31. package/skills/wix-headless-templates/forms/app/wix/forms/forms.ts +2 -2
  32. package/skills/wix-headless-templates/forms/app/wix/forms/submissions.ts +2 -2
  33. package/skills/wix-headless-templates/forms/project/src/wix/forms/forms.ts +2 -2
  34. package/skills/wix-headless-templates/forms/project/src/wix/forms/submissions.ts +2 -2
  35. package/skills/wix-headless-templates/members/seed/read-site.mjs +1 -1
  36. package/skills/wix-headless-templates/pricing-plans/app/wix/pricing-plans/plan-access.ts +1 -1
  37. package/skills/wix-headless-templates/pricing-plans/project/src/wix/pricing-plans/plan-access.ts +1 -1
  38. package/skills/wix-headless-templates/pricing-plans/rest/plan-access.ts +1 -1
  39. package/skills/wix-headless-templates/restaurants/app/wix/restaurants/menu.ts +0 -1
  40. package/skills/wix-headless-templates/restaurants/project/src/wix/restaurants/menu.ts +0 -1
  41. package/skills/wix-headless-templates/restaurants/rest/menu.ts +0 -1
  42. package/skills/wix-headless-templates/shared/rest/client.ts +1 -1
  43. package/skills/wix-headless-templates/shared/seed/site.mjs +2 -1
  44. package/skills/wix-manage/SKILL.md +3 -3
  45. package/skills/wix-manage/references/cms/cms-data-items-crud.md +78 -1
  46. package/skills/wix-manage/references/google-ads/create-performance-max-campaign.md +11 -11
  47. package/skills/wix-manage/references/google-ads/get-campaign-suggestions.md +0 -1
  48. package/skills/wix-manage/references/google-ads/install-and-create-account.md +0 -1
  49. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +20 -51
  50. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +4 -4
  51. package/skills/wix-manage/references/rich-content/ricos-converter-service.md +1 -1
  52. package/skills/wix-base44-connector/SKILL.md +0 -437
  53. package/skills/wix-base44-connector/references/CAPABILITY_MAP.md +0 -78
  54. package/skills/wix-base44-connector/scripts/utils.cjs +0 -466
  55. package/skills/wix-export/SKILL.md +0 -83
  56. package/skills/wix-harmony-editor/.publish-manifest.json +0 -8
  57. package/skills/wix-harmony-editor/COPY-SITE.md +0 -494
  58. package/skills/wix-harmony-editor/SKILL.md +0 -317
  59. package/skills/wix-harmony-editor/scripts/copy/build-description.mjs +0 -249
  60. package/skills/wix-harmony-editor/scripts/copy/check-description.mjs +0 -225
  61. package/skills/wix-harmony-editor/scripts/copy/check-mirror.mjs +0 -89
  62. package/skills/wix-harmony-editor/scripts/copy/compare-preview.mjs +0 -76
  63. package/skills/wix-harmony-editor/scripts/copy/deploy-description.mjs +0 -212
  64. package/skills/wix-harmony-editor/scripts/copy/desc-hash.mjs +0 -44
  65. package/skills/wix-harmony-editor/scripts/copy/editor-run.mjs +0 -45
  66. package/skills/wix-harmony-editor/scripts/copy/export-page.mjs +0 -53
  67. package/skills/wix-harmony-editor/scripts/copy/find-interactions.mjs +0 -76
  68. package/skills/wix-harmony-editor/scripts/copy/hide-scrollbars.mjs +0 -16
  69. package/skills/wix-harmony-editor/scripts/copy/import-media.mjs +0 -150
  70. package/skills/wix-harmony-editor/scripts/copy/link-url.mjs +0 -27
  71. package/skills/wix-harmony-editor/scripts/copy/lint-api.mjs +0 -56
  72. package/skills/wix-harmony-editor/scripts/copy/measure-source.mjs +0 -211
  73. package/skills/wix-harmony-editor/scripts/copy/merge-mirrors.mjs +0 -29
  74. package/skills/wix-harmony-editor/scripts/copy/mirror-site.mjs +0 -92
  75. package/skills/wix-harmony-editor/scripts/copy/mobile-stage.mjs +0 -56
  76. package/skills/wix-harmony-editor/scripts/copy/preview-widths.mjs +0 -73
  77. package/skills/wix-harmony-editor/scripts/copy/render-plate.mjs +0 -67
  78. package/skills/wix-harmony-editor/scripts/copy/serve-mirror.mjs +0 -102
  79. package/skills/wix-harmony-editor/scripts/copy/snapshot-capabilities.mjs +0 -40
  80. package/skills/wix-harmony-editor/scripts/copy/split-sections.mjs +0 -191
  81. package/skills/wix-harmony-editor/scripts/copy/upload-media-manager.mjs +0 -61
  82. package/skills/wix-harmony-editor/scripts/launch.sh +0 -359
  83. package/skills/wix-headless/SKILL.md +0 -151
  84. package/skills/wix-headless/references/AI_FEATURES.md +0 -178
  85. package/skills/wix-headless/references/CAPABILITIES.md +0 -117
  86. package/skills/wix-headless/references/CONTENT.md +0 -36
  87. package/skills/wix-headless/references/DESIGN.md +0 -55
  88. package/skills/wix-headless/references/DISCOVERY.md +0 -80
  89. package/skills/wix-headless/references/DOC_DISCOVERY.md +0 -43
  90. package/skills/wix-headless/references/FEEDBACK.md +0 -129
  91. package/skills/wix-headless/references/IMAGE_GENERATION.md +0 -80
  92. package/skills/wix-headless/references/SDK_HANDOFF.md +0 -108
  93. package/skills/wix-headless/references/SEED.md +0 -74
  94. package/skills/wix-headless/references/SETUP.md +0 -60
  95. package/skills/wix-headless/references/astro.md +0 -98
  96. package/skills/wix-headless/references/inline-recipes/experience-donations.md +0 -102
  97. package/skills/wix-headless/references/inline-recipes/experience-store.md +0 -49
  98. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +0 -196
  99. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +0 -590
  100. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +0 -279
  101. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +0 -163
  102. package/skills/wix-headless/references/inline-recipes/how-to-code-donations.md +0 -146
  103. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +0 -203
  104. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +0 -696
  105. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +0 -124
  106. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +0 -160
  107. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +0 -118
  108. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +0 -132
  109. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +0 -126
  110. package/skills/wix-headless/references/inline-recipes/how-to-code-rentals.md +0 -254
  111. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +0 -191
  112. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +0 -213
  113. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +0 -161
  114. package/skills/wix-headless/references/inline-recipes/setup-blog.md +0 -175
  115. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +0 -232
  116. package/skills/wix-headless/references/inline-recipes/setup-cms.md +0 -200
  117. package/skills/wix-headless/references/inline-recipes/setup-donations.md +0 -15
  118. package/skills/wix-headless/references/inline-recipes/setup-events.md +0 -196
  119. package/skills/wix-headless/references/inline-recipes/setup-forms.md +0 -288
  120. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +0 -214
  121. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +0 -155
  122. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +0 -229
  123. package/skills/wix-headless/references/inline-recipes/setup-rentals.md +0 -254
  124. package/skills/wix-headless/references/inline-recipes/setup-restaurant-experiences.md +0 -73
  125. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +0 -197
  126. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +0 -136
  127. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +0 -152
  128. package/skills/wix-headless/references/managed/AUTHENTICATION.md +0 -71
  129. package/skills/wix-headless/references/managed/CONNECT.md +0 -74
  130. package/skills/wix-headless/references/managed/CREATE.md +0 -149
  131. package/skills/wix-headless/references/managed/DEPLOYMENT.md +0 -104
  132. package/skills/wix-headless/references/non-astro.md +0 -59
  133. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +0 -22
  134. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +0 -15
  135. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +0 -55
  136. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +0 -71
  137. package/skills/wix-headless/scripts/bootstrap.mjs +0 -156
  138. package/skills/wix-headless-replatform/.publish-manifest.json +0 -8
  139. package/skills/wix-headless-replatform/SKILL.md +0 -116
  140. package/skills/wix-headless-replatform/agents/openai.yaml +0 -6
  141. package/skills/wix-headless-replatform/references/control-and-visual-fidelity-contract.md +0 -43
  142. package/skills/wix-headless-replatform/references/extraction-schema.md +0 -187
  143. package/skills/wix-headless-replatform/references/interaction-runtime-contract.md +0 -137
  144. package/skills/wix-headless-replatform/references/layout-blueprint-contract.md +0 -41
  145. package/skills/wix-headless-replatform/references/output-contract.md +0 -93
  146. package/skills/wix-headless-replatform/references/post-build-gap-contract.md +0 -125
  147. package/skills/wix-headless-replatform/references/qa-checklist.md +0 -83
  148. package/skills/wix-headless-replatform/references/safety.md +0 -19
  149. package/skills/wix-headless-replatform/references/ui-normalization-contract.md +0 -70
  150. package/skills/wix-headless-replatform/references/workflow.md +0 -157
  151. package/skills/wix-headless-replatform/registry/README.md +0 -20
  152. package/skills/wix-headless-replatform/registry/approvals/button/shadcn-default-ac60ef5.json +0 -28
  153. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/button.tsx +0 -54
  154. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/capabilities.json +0 -60
  155. package/skills/wix-headless-replatform/registry/items/button/shadcn-default-ac60ef5/contract.md +0 -48
  156. package/skills/wix-headless-replatform/registry/licenses/shadcn-ui-ac60ef5-MIT.txt +0 -21
  157. package/skills/wix-headless-replatform/registry/registry.json +0 -36
  158. package/skills/wix-headless-replatform/resources/rp-facelift/SKILL.md +0 -32
  159. package/skills/wix-headless-replatform/resources/rp-project-context/SKILL.md +0 -62
  160. package/skills/wix-headless-replatform/resources/rp-qa-gap-loop/SKILL.md +0 -64
  161. package/skills/wix-headless-replatform/resources/rp-source-evidence/SKILL.md +0 -42
  162. package/skills/wix-headless-replatform/resources/rp-ui-implementation/SKILL.md +0 -73
  163. package/skills/wix-headless-replatform/schemas/build-plan.schema.json +0 -10
  164. package/skills/wix-headless-replatform/schemas/candidate.schema.json +0 -19
  165. package/skills/wix-headless-replatform/schemas/common.schema.json +0 -33
  166. package/skills/wix-headless-replatform/schemas/decision-patch.schema.json +0 -10
  167. package/skills/wix-headless-replatform/schemas/decision-request.schema.json +0 -10
  168. package/skills/wix-headless-replatform/schemas/extraction-gap.schema.json +0 -28
  169. package/skills/wix-headless-replatform/schemas/extraction-manifest.schema.json +0 -34
  170. package/skills/wix-headless-replatform/schemas/final-report.schema.json +0 -10
  171. package/skills/wix-headless-replatform/schemas/foundation.schema.json +0 -11
  172. package/skills/wix-headless-replatform/schemas/metadata.schema.json +0 -11
  173. package/skills/wix-headless-replatform/schemas/observation-packet.schema.json +0 -17
  174. package/skills/wix-headless-replatform/schemas/page-capture.schema.json +0 -11
  175. package/skills/wix-headless-replatform/schemas/page-resolution.schema.json +0 -33
  176. package/skills/wix-headless-replatform/schemas/shared-chrome.schema.json +0 -11
  177. package/skills/wix-headless-replatform/schemas/unit.schema.json +0 -40
  178. package/skills/wix-headless-replatform/scripts/assemble-extraction.mjs +0 -844
  179. package/skills/wix-headless-replatform/scripts/benchmark-extraction.mjs +0 -163
  180. package/skills/wix-headless-replatform/scripts/browser-extraction-preflight.mjs +0 -42
  181. package/skills/wix-headless-replatform/scripts/build-extracted-homepage.mjs +0 -228
  182. package/skills/wix-headless-replatform/scripts/clear-wix-starter.mjs +0 -87
  183. package/skills/wix-headless-replatform/scripts/create-wix-project.mjs +0 -505
  184. package/skills/wix-headless-replatform/scripts/discover-urls.mjs +0 -142
  185. package/skills/wix-headless-replatform/scripts/extract-assets.mjs +0 -140
  186. package/skills/wix-headless-replatform/scripts/extract-design-system.mjs +0 -637
  187. package/skills/wix-headless-replatform/scripts/extract-interactions.mjs +0 -1903
  188. package/skills/wix-headless-replatform/scripts/extract-page.mjs +0 -2461
  189. package/skills/wix-headless-replatform/scripts/extract-seo.mjs +0 -25
  190. package/skills/wix-headless-replatform/scripts/extract-tokens.mjs +0 -63
  191. package/skills/wix-headless-replatform/scripts/finalize-extraction-report.mjs +0 -126
  192. package/skills/wix-headless-replatform/scripts/finalize-gap-review.mjs +0 -180
  193. package/skills/wix-headless-replatform/scripts/finalize-gap-review.test.mjs +0 -98
  194. package/skills/wix-headless-replatform/scripts/finalize-migration-website.mjs +0 -103
  195. package/skills/wix-headless-replatform/scripts/generate-control-state-contract.mjs +0 -176
  196. package/skills/wix-headless-replatform/scripts/generate-design-md.mjs +0 -261
  197. package/skills/wix-headless-replatform/scripts/generate-extraction-validators.mjs +0 -25
  198. package/skills/wix-headless-replatform/scripts/generate-invoice-download-backend.mjs +0 -342
  199. package/skills/wix-headless-replatform/scripts/generate-layout-blueprint.mjs +0 -140
  200. package/skills/wix-headless-replatform/scripts/generate-repeater-cms.mjs +0 -22
  201. package/skills/wix-headless-replatform/scripts/generate-route-plan.mjs +0 -143
  202. package/skills/wix-headless-replatform/scripts/generate-scene-contract.mjs +0 -288
  203. package/skills/wix-headless-replatform/scripts/generate-ui-normalization.mjs +0 -266
  204. package/skills/wix-headless-replatform/scripts/generate-visual-assets.mjs +0 -111
  205. package/skills/wix-headless-replatform/scripts/lib/browser-tooling.mjs +0 -570
  206. package/skills/wix-headless-replatform/scripts/lib/common.mjs +0 -329
  207. package/skills/wix-headless-replatform/scripts/lib/component-capabilities.mjs +0 -121
  208. package/skills/wix-headless-replatform/scripts/lib/component-registry.mjs +0 -282
  209. package/skills/wix-headless-replatform/scripts/lib/content-boundary.mjs +0 -61
  210. package/skills/wix-headless-replatform/scripts/lib/extraction-contract.mjs +0 -374
  211. package/skills/wix-headless-replatform/scripts/lib/extraction-detectors.mjs +0 -243
  212. package/skills/wix-headless-replatform/scripts/lib/extraction-validators.generated.mjs +0 -1139
  213. package/skills/wix-headless-replatform/scripts/lib/font-contract.mjs +0 -326
  214. package/skills/wix-headless-replatform/scripts/lib/frontend-automation-state.mjs +0 -184
  215. package/skills/wix-headless-replatform/scripts/lib/gap-analysis.mjs +0 -396
  216. package/skills/wix-headless-replatform/scripts/lib/html-extract.mjs +0 -168
  217. package/skills/wix-headless-replatform/scripts/lib/interaction-bootstrap.mjs +0 -10
  218. package/skills/wix-headless-replatform/scripts/lib/interaction-runtime.mjs +0 -194
  219. package/skills/wix-headless-replatform/scripts/lib/interaction-timeline.mjs +0 -348
  220. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/classifiers.mjs +0 -141
  221. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/geometry.mjs +0 -43
  222. package/skills/wix-headless-replatform/scripts/lib/layout-blueprint/vocabulary.mjs +0 -18
  223. package/skills/wix-headless-replatform/scripts/lib/ui-normalization.css +0 -64
  224. package/skills/wix-headless-replatform/scripts/optimize-svg.mjs +0 -31
  225. package/skills/wix-headless-replatform/scripts/post-build-gap.mjs +0 -358
  226. package/skills/wix-headless-replatform/scripts/provision-repeater-cms.mjs +0 -25
  227. package/skills/wix-headless-replatform/scripts/record-gap-decision.mjs +0 -39
  228. package/skills/wix-headless-replatform/scripts/replay-extraction.mjs +0 -107
  229. package/skills/wix-headless-replatform/scripts/resolve-home-page.mjs +0 -96
  230. package/skills/wix-headless-replatform/scripts/site-clone.mjs +0 -658
  231. package/skills/wix-headless-replatform/scripts/validate-font-contract.mjs +0 -29
  232. package/skills/wix-headless-replatform/scripts/verify-interactions.mjs +0 -669
  233. package/skills/wix-headless-replatform/scripts/visual-qa.mjs +0 -370
  234. package/skills/wix-import/SKILL.md +0 -90
  235. package/skills/wix-replatform/.publish-manifest.json +0 -8
  236. package/skills/wix-replatform/CLI.md +0 -162
  237. package/skills/wix-replatform/README.md +0 -52
  238. package/skills/wix-replatform/SKILL.md +0 -238
  239. package/skills/wix-replatform/console/account.css +0 -1
  240. package/skills/wix-replatform/console/app.css +0 -1
  241. package/skills/wix-replatform/console/app.js +0 -117
  242. package/skills/wix-replatform/console/index.html +0 -4
  243. package/skills/wix-replatform/console/json.css +0 -11
  244. package/skills/wix-replatform/lib/agent-adapters/index.js +0 -71
  245. package/skills/wix-replatform/lib/app-page-routing.js +0 -75
  246. package/skills/wix-replatform/lib/artifact-freshness.js +0 -225
  247. package/skills/wix-replatform/lib/blocked-data-requests.js +0 -427
  248. package/skills/wix-replatform/lib/census-reconciliation.js +0 -426
  249. package/skills/wix-replatform/lib/completion-report.js +0 -1580
  250. package/skills/wix-replatform/lib/config-env.js +0 -133
  251. package/skills/wix-replatform/lib/confirmed-pictures.js +0 -212
  252. package/skills/wix-replatform/lib/dependency-readiness.js +0 -423
  253. package/skills/wix-replatform/lib/dependency-recovery.js +0 -21
  254. package/skills/wix-replatform/lib/destination-choice.js +0 -163
  255. package/skills/wix-replatform/lib/destination-handoff.js +0 -62
  256. package/skills/wix-replatform/lib/destination-http.js +0 -81
  257. package/skills/wix-replatform/lib/destination-route.js +0 -98
  258. package/skills/wix-replatform/lib/destination.js +0 -919
  259. package/skills/wix-replatform/lib/discovered-census.js +0 -231
  260. package/skills/wix-replatform/lib/discovered-set-status.js +0 -255
  261. package/skills/wix-replatform/lib/document-url-guard.js +0 -203
  262. package/skills/wix-replatform/lib/entity-qa-attestation.js +0 -339
  263. package/skills/wix-replatform/lib/entity-verification.js +0 -18
  264. package/skills/wix-replatform/lib/execution-capability.js +0 -120
  265. package/skills/wix-replatform/lib/execution-log.js +0 -170
  266. package/skills/wix-replatform/lib/execution-manifest.js +0 -203
  267. package/skills/wix-replatform/lib/execution-state.js +0 -195
  268. package/skills/wix-replatform/lib/expectations-ledger.js +0 -96
  269. package/skills/wix-replatform/lib/generated-plugin-handoff.js +0 -140
  270. package/skills/wix-replatform/lib/import-readiness-contract.js +0 -23
  271. package/skills/wix-replatform/lib/import-recovery.js +0 -1107
  272. package/skills/wix-replatform/lib/imported-redirect-targets.js +0 -608
  273. package/skills/wix-replatform/lib/internal-link-reconciliation.js +0 -166
  274. package/skills/wix-replatform/lib/link-audit.js +0 -173
  275. package/skills/wix-replatform/lib/link-census.js +0 -194
  276. package/skills/wix-replatform/lib/link-plan.js +0 -148
  277. package/skills/wix-replatform/lib/link-verification.js +0 -274
  278. package/skills/wix-replatform/lib/link-write-journal.js +0 -42
  279. package/skills/wix-replatform/lib/local-state.js +0 -1481
  280. package/skills/wix-replatform/lib/member-completion.js +0 -658
  281. package/skills/wix-replatform/lib/member-crosswalk.js +0 -69
  282. package/skills/wix-replatform/lib/member-outcome-registry.js +0 -265
  283. package/skills/wix-replatform/lib/migration-completion.js +0 -311
  284. package/skills/wix-replatform/lib/operator-identity.js +0 -47
  285. package/skills/wix-replatform/lib/orchestration-decisions.js +0 -248
  286. package/skills/wix-replatform/lib/orchestration-preflight.js +0 -525
  287. package/skills/wix-replatform/lib/orchestration-router.js +0 -698
  288. package/skills/wix-replatform/lib/orchestration-state.js +0 -631
  289. package/skills/wix-replatform/lib/order-reference-readiness.js +0 -30
  290. package/skills/wix-replatform/lib/payments-outcome-registry.js +0 -200
  291. package/skills/wix-replatform/lib/plugin-cms-fallback.js +0 -618
  292. package/skills/wix-replatform/lib/preservation-approval-stamp.js +0 -54
  293. package/skills/wix-replatform/lib/product-media-deferral.js +0 -96
  294. package/skills/wix-replatform/lib/progress-log.js +0 -240
  295. package/skills/wix-replatform/lib/progress-log.sh +0 -140
  296. package/skills/wix-replatform/lib/read-back-approval.js +0 -184
  297. package/skills/wix-replatform/lib/read-back-comparison.js +0 -136
  298. package/skills/wix-replatform/lib/read-back-contract.js +0 -243
  299. package/skills/wix-replatform/lib/read-back-extract.js +0 -118
  300. package/skills/wix-replatform/lib/read-back-gate.js +0 -734
  301. package/skills/wix-replatform/lib/read-back-reads.js +0 -94
  302. package/skills/wix-replatform/lib/read-back-state.js +0 -107
  303. package/skills/wix-replatform/lib/read-back-summary.js +0 -81
  304. package/skills/wix-replatform/lib/rerun-conflicts.js +0 -334
  305. package/skills/wix-replatform/lib/run-controller.js +0 -401
  306. package/skills/wix-replatform/lib/seo-outcome-registry.js +0 -45
  307. package/skills/wix-replatform/lib/setup-verification.js +0 -148
  308. package/skills/wix-replatform/lib/source-access.js +0 -231
  309. package/skills/wix-replatform/lib/source-coverage.js +0 -1130
  310. package/skills/wix-replatform/lib/source-secrets.js +0 -277
  311. package/skills/wix-replatform/lib/structured-link-patch.js +0 -59
  312. package/skills/wix-replatform/lib/task-state.js +0 -110
  313. package/skills/wix-replatform/lib/url-preservation-report.js +0 -319
  314. package/skills/wix-replatform/lib/url-preservation-state.js +0 -739
  315. package/skills/wix-replatform/lib/url-redirect-plan.js +0 -728
  316. package/skills/wix-replatform/lib/url-verification.js +0 -315
  317. package/skills/wix-replatform/lib/user-action-effects.js +0 -42
  318. package/skills/wix-replatform/lib/user-actions.js +0 -264
  319. package/skills/wix-replatform/lib/website-handoff.js +0 -1220
  320. package/skills/wix-replatform/lib/wix-client-callers.js +0 -54
  321. package/skills/wix-replatform/lib/wix-dashboard-url.js +0 -35
  322. package/skills/wix-replatform/lib/write-verification-state.js +0 -92
  323. package/skills/wix-replatform/lib/write-verification.js +0 -274
  324. package/skills/wix-replatform/resources/rp-destination/SKILL.md +0 -137
  325. package/skills/wix-replatform/resources/rp-discovery/SKILL.md +0 -357
  326. package/skills/wix-replatform/resources/rp-discovery/scripts/promote-source-coverage.js +0 -47
  327. package/skills/wix-replatform/resources/rp-execute-import/SKILL.md +0 -1369
  328. package/skills/wix-replatform/resources/rp-execute-import/scripts/shipping-estimate-audit.js +0 -70
  329. package/skills/wix-replatform/resources/rp-execute-setup/SKILL.md +0 -482
  330. package/skills/wix-replatform/resources/rp-execute-setup/scripts/execute-setup.js +0 -442
  331. package/skills/wix-replatform/resources/rp-execute-setup/scripts/mint-token.sh +0 -64
  332. package/skills/wix-replatform/resources/rp-execution-policy/SKILL.md +0 -112
  333. package/skills/wix-replatform/resources/rp-execution-policy/lib/coupon-currency-plan-report.js +0 -143
  334. package/skills/wix-replatform/resources/rp-execution-policy/lib/payments-report.js +0 -244
  335. package/skills/wix-replatform/resources/rp-import-codegen/SKILL.md +0 -3158
  336. package/skills/wix-replatform/resources/rp-mapper/SKILL.md +0 -947
  337. package/skills/wix-replatform/resources/rp-mapper/lib/mapping-resolve.js +0 -217
  338. package/skills/wix-replatform/resources/rp-mapper/lib/structure-bridge-planning.js +0 -303
  339. package/skills/wix-replatform/resources/rp-mapper/scripts/coverage-reconcile.js +0 -88
  340. package/skills/wix-replatform/resources/rp-mapper/scripts/resolve-mapping.js +0 -148
  341. package/skills/wix-replatform/resources/rp-mapper/wix-business-solutions-taxonomy.md +0 -378
  342. package/skills/wix-replatform/resources/rp-preflight/SKILL.md +0 -40
  343. package/skills/wix-replatform/resources/rp-project-intake/SKILL.md +0 -55
  344. package/skills/wix-replatform/resources/rp-quick-runtime/SKILL.md +0 -60
  345. package/skills/wix-replatform/resources/rp-quick-runtime/lib/import-progress.js +0 -89
  346. package/skills/wix-replatform/resources/rp-quick-runtime/lib/limit-recovery.js +0 -36
  347. package/skills/wix-replatform/resources/rp-quick-shopify/SKILL.md +0 -123
  348. package/skills/wix-replatform/resources/rp-quick-shopify/quick-mode.json +0 -124
  349. package/skills/wix-replatform/resources/rp-quick-shopify/scripts/quick-mode.js +0 -522
  350. package/skills/wix-replatform/resources/rp-quick-woocommerce/SKILL.md +0 -56
  351. package/skills/wix-replatform/resources/rp-quick-woocommerce/quick-mode.json +0 -91
  352. package/skills/wix-replatform/resources/rp-quick-woocommerce/scripts/quick-mode.js +0 -255
  353. package/skills/wix-replatform/resources/rp-setup-discovery/SKILL.md +0 -253
  354. package/skills/wix-replatform/resources/rp-setup-discovery/scripts/quick-setup-plan.js +0 -44
  355. package/skills/wix-replatform/resources/rp-source-csv/SKILL.md +0 -481
  356. package/skills/wix-replatform/resources/rp-source-csv/lib/canonical-record.js +0 -136
  357. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fileset.js +0 -0
  358. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-fingerprint.js +0 -310
  359. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-layout.js +0 -1081
  360. package/skills/wix-replatform/resources/rp-source-csv/lib/csv-parse.js +0 -618
  361. package/skills/wix-replatform/resources/rp-source-csv/scripts/csv-discovery.js +0 -969
  362. package/skills/wix-replatform/resources/rp-source-csv/source-schema.example.json +0 -196
  363. package/skills/wix-replatform/resources/rp-source-csv/vendors/bigcommerce.json +0 -66
  364. package/skills/wix-replatform/resources/rp-source-csv/vendors/magento.json +0 -60
  365. package/skills/wix-replatform/resources/rp-source-csv/vendors/shopify.json +0 -95
  366. package/skills/wix-replatform/resources/rp-source-csv/vendors/woocommerce.json +0 -82
  367. package/skills/wix-replatform/resources/rp-source-inputs/SKILL.md +0 -66
  368. package/skills/wix-replatform/resources/rp-source-sfcc/SKILL.md +0 -153
  369. package/skills/wix-replatform/resources/rp-source-shopify/SKILL.md +0 -394
  370. package/skills/wix-replatform/resources/rp-source-shopify/lib/discovery-reads.js +0 -200
  371. package/skills/wix-replatform/resources/rp-source-shopify/lib/import-findings.js +0 -34
  372. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-bulk-sqlite-worker.js +0 -44
  373. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-bulk.js +0 -1470
  374. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-cli.js +0 -446
  375. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-gift-cards.js +0 -474
  376. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-protected-fields.js +0 -879
  377. package/skills/wix-replatform/resources/rp-source-shopify/lib/shopify-session.js +0 -426
  378. package/skills/wix-replatform/resources/rp-source-shopify/queries/articles.graphql +0 -24
  379. package/skills/wix-replatform/resources/rp-source-shopify/queries/blogs.graphql +0 -18
  380. package/skills/wix-replatform/resources/rp-source-shopify/queries/collections.graphql +0 -40
  381. package/skills/wix-replatform/resources/rp-source-shopify/queries/customers.graphql +0 -76
  382. package/skills/wix-replatform/resources/rp-source-shopify/queries/delivery-profiles.graphql +0 -51
  383. package/skills/wix-replatform/resources/rp-source-shopify/queries/discounts.graphql +0 -35
  384. package/skills/wix-replatform/resources/rp-source-shopify/queries/files.graphql +0 -20
  385. package/skills/wix-replatform/resources/rp-source-shopify/queries/gift-cards.graphql +0 -18
  386. package/skills/wix-replatform/resources/rp-source-shopify/queries/inventory.graphql +0 -31
  387. package/skills/wix-replatform/resources/rp-source-shopify/queries/locations.graphql +0 -21
  388. package/skills/wix-replatform/resources/rp-source-shopify/queries/menus.graphql +0 -21
  389. package/skills/wix-replatform/resources/rp-source-shopify/queries/metaobjects.graphql +0 -30
  390. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-core.graphql +0 -150
  391. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-fulfillments.graphql +0 -36
  392. package/skills/wix-replatform/resources/rp-source-shopify/queries/orders-refunds.graphql +0 -48
  393. package/skills/wix-replatform/resources/rp-source-shopify/queries/pages.graphql +0 -20
  394. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-address.graphql +0 -8
  395. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-email.graphql +0 -6
  396. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-name.graphql +0 -8
  397. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-customers-phone.graphql +0 -8
  398. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-address.graphql +0 -12
  399. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-email.graphql +0 -6
  400. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-name.graphql +0 -13
  401. package/skills/wix-replatform/resources/rp-source-shopify/queries/probe-orders-phone.graphql +0 -13
  402. package/skills/wix-replatform/resources/rp-source-shopify/queries/products.graphql +0 -73
  403. package/skills/wix-replatform/resources/rp-source-shopify/queries/url-redirects.graphql +0 -13
  404. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-discovery.js +0 -693
  405. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-extract.js +0 -283
  406. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-gift-card-remedy.js +0 -191
  407. package/skills/wix-replatform/resources/rp-source-shopify/scripts/shopify-session-check.js +0 -115
  408. package/skills/wix-replatform/resources/rp-source-shopify/source-schema.example.json +0 -201
  409. package/skills/wix-replatform/resources/rp-source-wordpress/PLUGIN-READ-PLANS.md +0 -146
  410. package/skills/wix-replatform/resources/rp-source-wordpress/SKILL.md +0 -970
  411. package/skills/wix-replatform/resources/rp-source-wordpress/lib/blocked-data-handlers.js +0 -73
  412. package/skills/wix-replatform/resources/rp-source-wordpress/lib/checkout-field-csv-parser.js +0 -115
  413. package/skills/wix-replatform/resources/rp-source-wordpress/lib/checkout-field-csv-parser.test-fixture.js +0 -91
  414. package/skills/wix-replatform/resources/rp-source-wordpress/lib/coupon-discovery.js +0 -440
  415. package/skills/wix-replatform/resources/rp-source-wordpress/lib/currency-gate.js +0 -125
  416. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-source-keys.js +0 -252
  417. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-source-keys.json +0 -183
  418. package/skills/wix-replatform/resources/rp-source-wordpress/lib/gateway-summary.mjs +0 -333
  419. package/skills/wix-replatform/resources/rp-source-wordpress/lib/invoice-discovery.js +0 -426
  420. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-disposition.js +0 -400
  421. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-entity-read-plan.js +0 -633
  422. package/skills/wix-replatform/resources/rp-source-wordpress/lib/plugin-knowledge.js +0 -1127
  423. package/skills/wix-replatform/resources/rp-source-wordpress/lib/refund-corroboration.js +0 -194
  424. package/skills/wix-replatform/resources/rp-source-wordpress/lib/refund-corroboration.json +0 -100
  425. package/skills/wix-replatform/resources/rp-source-wordpress/lib/sampled-ids-batch.js +0 -157
  426. package/skills/wix-replatform/resources/rp-source-wordpress/lib/secret-value-guard.js +0 -234
  427. package/skills/wix-replatform/resources/rp-source-wordpress/lib/store-currency.js +0 -101
  428. package/skills/wix-replatform/resources/rp-source-wordpress/lib/structure-bridge-reader.js +0 -755
  429. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wix-wp-plugin-v2-client.js +0 -1074
  430. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wix-wp-plugin-v2-client.test-fixture.js +0 -149
  431. package/skills/wix-replatform/resources/rp-source-wordpress/lib/woo-inventory.js +0 -25
  432. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-http.js +0 -444
  433. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-image-url.js +0 -186
  434. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-plugin-detect.js +0 -1422
  435. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-redirect-sources.js +0 -343
  436. package/skills/wix-replatform/resources/rp-source-wordpress/lib/wp-route-classifier.js +0 -680
  437. package/skills/wix-replatform/resources/rp-source-wordpress/lib/yoast-product-seo-evidence.js +0 -272
  438. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/README.md +0 -373
  439. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/advanced-custom-fields.json +0 -101
  440. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/back-in-stock-notifier-for-woocommerce.json +0 -81
  441. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/capabilities-pending-decision.json +0 -128
  442. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/cms-fallback-eligible.json +0 -18
  443. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/contact-form-7.json +0 -104
  444. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/facebook-for-woocommerce.json +0 -44
  445. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/fingerprint-aliases.json +0 -49
  446. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/free-gifts-for-woocommerce.json +0 -94
  447. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/index.json +0 -863
  448. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/mailpoet.json +0 -52
  449. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/membership-for-woocommerce.json +0 -161
  450. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/mwb-bookings-for-woocommerce.json +0 -180
  451. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/no-migration-needed.json +0 -286
  452. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/pricing-deals-for-woocommerce.json +0 -79
  453. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/product-extras-for-woocommerce.json +0 -120
  454. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/pw-woocommerce-gift-cards.json +0 -128
  455. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/requires-development.json +0 -88
  456. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/seo-by-rank-math.json +0 -80
  457. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/seriously-simple-podcasting.json +0 -46
  458. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/strong-testimonials.json +0 -55
  459. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/subscriptions-for-woocommerce.json +0 -99
  460. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/tablepress.json +0 -55
  461. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/the-events-calendar.json +0 -160
  462. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/ti-woocommerce-wishlist.json +0 -81
  463. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-checkout-field-editor-pro.json +0 -60
  464. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-discount-rules.json +0 -74
  465. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woo-product-bundle.json +0 -75
  466. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-gift-cards.json +0 -60
  467. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-other-payment-gateway.json +0 -44
  468. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-pdf-invoices-packing-slips.json +0 -57
  469. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-product-addon.json +0 -141
  470. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/woocommerce-progressive-discounts.json +0 -54
  471. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wordpress-seo.json +0 -158
  472. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wpc-composite-products.json +0 -97
  473. package/skills/wix-replatform/resources/rp-source-wordpress/plugins/wpforms-lite.json +0 -86
  474. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/capture-store-settings.js +0 -90
  475. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/plugin-knowledge-validate.js +0 -51
  476. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/plugin-knowledge.js +0 -103
  477. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-discovery.js +0 -2409
  478. package/skills/wix-replatform/resources/rp-source-wordpress/scripts/wp-plugin-inventory.js +0 -273
  479. package/skills/wix-replatform/resources/rp-source-wordpress/secret-value-patterns.v1.json +0 -11
  480. package/skills/wix-replatform/resources/rp-source-wordpress/source-schema.example.json +0 -71
  481. package/skills/wix-replatform/resources/rp-source-wordpress/sub-parts.json +0 -13
  482. package/skills/wix-replatform/resources/rp-target-wix/SKILL.md +0 -1046
  483. package/skills/wix-replatform/resources/rp-target-wix/app-page-routing-capabilities.json +0 -36
  484. package/skills/wix-replatform/resources/rp-target-wix/domains/README.md +0 -57
  485. package/skills/wix-replatform/resources/rp-target-wix/domains/SERVICE-PLUGINS.md +0 -322
  486. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/docs-survey.json +0 -70
  487. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/domain.json +0 -29
  488. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/category.json +0 -71
  489. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/comment.json +0 -83
  490. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/post.json +0 -95
  491. package/skills/wix-replatform/resources/rp-target-wix/domains/blog/entities/tag.json +0 -66
  492. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/docs-survey.json +0 -332
  493. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/domain.json +0 -75
  494. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/booking.json +0 -181
  495. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/service-add-on.json +0 -130
  496. package/skills/wix-replatform/resources/rp-target-wix/domains/bookings/entities/service.json +0 -180
  497. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/docs-survey.json +0 -161
  498. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/domain.json +0 -25
  499. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/collection.json +0 -67
  500. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/data-item.json +0 -75
  501. package/skills/wix-replatform/resources/rp-target-wix/domains/cms/entities/reference.json +0 -41
  502. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/docs-survey.json +0 -204
  503. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/domain.json +0 -27
  504. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/contact.json +0 -275
  505. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/email-subscription.json +0 -105
  506. package/skills/wix-replatform/resources/rp-target-wix/domains/crm/entities/label.json +0 -77
  507. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/docs-survey.json +0 -306
  508. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/domain.json +0 -44
  509. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/delivery-profile.json +0 -171
  510. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/discount-rule.json +0 -182
  511. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-applied-discount.json +0 -129
  512. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-invoice-document.json +0 -192
  513. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item-options.json +0 -123
  514. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-line-item.json +0 -85
  515. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-merchant-note.json +0 -112
  516. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-payment.json +0 -191
  517. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order-refund.json +0 -164
  518. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/order.json +0 -462
  519. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/pickup-location.json +0 -122
  520. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/shipping-option.json +0 -98
  521. package/skills/wix-replatform/resources/rp-target-wix/domains/ecom/entities/wishlist-item.json +0 -86
  522. package/skills/wix-replatform/resources/rp-target-wix/domains/events/docs-survey.json +0 -128
  523. package/skills/wix-replatform/resources/rp-target-wix/domains/events/domain.json +0 -38
  524. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/category.json +0 -73
  525. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/event.json +0 -107
  526. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/registration-form.json +0 -89
  527. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/rsvp.json +0 -118
  528. package/skills/wix-replatform/resources/rp-target-wix/domains/events/entities/ticket-definition.json +0 -93
  529. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/docs-survey.json +0 -86
  530. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/domain.json +0 -56
  531. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/entities/form-submission.json +0 -121
  532. package/skills/wix-replatform/resources/rp-target-wix/domains/forms/entities/form.json +0 -134
  533. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/docs-survey.json +0 -41
  534. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/domain.json +0 -50
  535. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/entities/gift-card-product.json +0 -87
  536. package/skills/wix-replatform/resources/rp-target-wix/domains/gift-cards/entities/gift-card.json +0 -130
  537. package/skills/wix-replatform/resources/rp-target-wix/domains/index.json +0 -1418
  538. package/skills/wix-replatform/resources/rp-target-wix/domains/media/docs-survey.json +0 -41
  539. package/skills/wix-replatform/resources/rp-target-wix/domains/media/domain.json +0 -24
  540. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-file.json +0 -75
  541. package/skills/wix-replatform/resources/rp-target-wix/domains/media/entities/media-folder.json +0 -71
  542. package/skills/wix-replatform/resources/rp-target-wix/domains/members/docs-survey.json +0 -119
  543. package/skills/wix-replatform/resources/rp-target-wix/domains/members/domain.json +0 -23
  544. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/badge.json +0 -71
  545. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/custom-field.json +0 -82
  546. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member-about.json +0 -77
  547. package/skills/wix-replatform/resources/rp-target-wix/domains/members/entities/member.json +0 -205
  548. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/docs-survey.json +0 -41
  549. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/domain.json +0 -46
  550. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/entities/plan-order.json +0 -137
  551. package/skills/wix-replatform/resources/rp-target-wix/domains/pricing-plans/entities/plan.json +0 -133
  552. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/docs-survey.json +0 -7
  553. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/domain.json +0 -36
  554. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/amazon-shop-connect.json +0 -71
  555. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/ebay-shop-connect.json +0 -67
  556. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/google-youtube-connect.json +0 -72
  557. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/meta-catalog-connect.json +0 -74
  558. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/pinterest-catalog-connect.json +0 -69
  559. package/skills/wix-replatform/resources/rp-target-wix/domains/sales-channels/entities/tiktok-catalog-connect.json +0 -61
  560. package/skills/wix-replatform/resources/rp-target-wix/domains/schema.json +0 -111
  561. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/docs-survey.json +0 -109
  562. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/domain.json +0 -73
  563. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/item-seo-tags.json +0 -148
  564. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/seo-pattern.json +0 -91
  565. package/skills/wix-replatform/resources/rp-target-wix/domains/seo/entities/site-seo-tags.json +0 -79
  566. package/skills/wix-replatform/resources/rp-target-wix/domains/site/docs-survey.json +0 -32
  567. package/skills/wix-replatform/resources/rp-target-wix/domains/site/domain.json +0 -49
  568. package/skills/wix-replatform/resources/rp-target-wix/domains/site/entities/business-contact.json +0 -103
  569. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/docs-survey.json +0 -203
  570. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/domain.json +0 -42
  571. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/back-in-stock-request.json +0 -119
  572. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/brand.json +0 -111
  573. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/category.json +0 -81
  574. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/coupon.json +0 -241
  575. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/inventory-item.json +0 -118
  576. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-customization.json +0 -111
  577. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product-tag.json +0 -79
  578. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/product.json +0 -221
  579. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/promotion.json +0 -84
  580. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/review.json +0 -178
  581. package/skills/wix-replatform/resources/rp-target-wix/domains/stores/entities/subscription-product.json +0 -87
  582. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/docs-survey.json +0 -106
  583. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/domain.json +0 -64
  584. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/manual-tax-mapping.json +0 -119
  585. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-group.json +0 -94
  586. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-region.json +0 -113
  587. package/skills/wix-replatform/resources/rp-target-wix/domains/tax/entities/tax-settings.json +0 -65
  588. package/skills/wix-replatform/resources/rp-target-wix/lib/audit-summary.js +0 -64
  589. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-author-attribution.js +0 -165
  590. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-client.js +0 -60
  591. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-duplicates.js +0 -201
  592. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-ledger.js +0 -306
  593. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-report.js +0 -229
  594. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build-stage.js +0 -55
  595. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-build.js +0 -715
  596. package/skills/wix-replatform/resources/rp-target-wix/lib/blog-post-media.js +0 -567
  597. package/skills/wix-replatform/resources/rp-target-wix/lib/bulk-results.js +0 -73
  598. package/skills/wix-replatform/resources/rp-target-wix/lib/contact-extended-fields.js +0 -194
  599. package/skills/wix-replatform/resources/rp-target-wix/lib/contact-import.js +0 -133
  600. package/skills/wix-replatform/resources/rp-target-wix/lib/contract-ledger.js +0 -150
  601. package/skills/wix-replatform/resources/rp-target-wix/lib/coupon-redemption-drift.js +0 -491
  602. package/skills/wix-replatform/resources/rp-target-wix/lib/customer-member.js +0 -104
  603. package/skills/wix-replatform/resources/rp-target-wix/lib/data-extension-schema.js +0 -673
  604. package/skills/wix-replatform/resources/rp-target-wix/lib/domain-knowledge.js +0 -835
  605. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-balance-reconciliation.js +0 -119
  606. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-build.js +0 -566
  607. package/skills/wix-replatform/resources/rp-target-wix/lib/gift-card-redemption-build.js +0 -249
  608. package/skills/wix-replatform/resources/rp-target-wix/lib/ndjson.js +0 -260
  609. package/skills/wix-replatform/resources/rp-target-wix/lib/order-applied-discount-build.js +0 -63
  610. package/skills/wix-replatform/resources/rp-target-wix/lib/order-buyer.js +0 -187
  611. package/skills/wix-replatform/resources/rp-target-wix/lib/order-channel-build.js +0 -64
  612. package/skills/wix-replatform/resources/rp-target-wix/lib/order-history.js +0 -1027
  613. package/skills/wix-replatform/resources/rp-target-wix/lib/order-invoice-contract.js +0 -90
  614. package/skills/wix-replatform/resources/rp-target-wix/lib/order-payment-mapping.js +0 -420
  615. package/skills/wix-replatform/resources/rp-target-wix/lib/pricing-plan-definition.js +0 -177
  616. package/skills/wix-replatform/resources/rp-target-wix/lib/product-import.js +0 -151
  617. package/skills/wix-replatform/resources/rp-target-wix/lib/product-seo.js +0 -723
  618. package/skills/wix-replatform/resources/rp-target-wix/lib/seo-redirects.js +0 -353
  619. package/skills/wix-replatform/resources/rp-target-wix/lib/shipping-build.js +0 -1437
  620. package/skills/wix-replatform/resources/rp-target-wix/lib/shipping-option-stage.js +0 -354
  621. package/skills/wix-replatform/resources/rp-target-wix/lib/store-config-build.js +0 -134
  622. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-category-attach.js +0 -221
  623. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-inventory.js +0 -248
  624. package/skills/wix-replatform/resources/rp-target-wix/lib/stores-verification.js +0 -321
  625. package/skills/wix-replatform/resources/rp-target-wix/lib/tax-build.js +0 -231
  626. package/skills/wix-replatform/resources/rp-target-wix/lib/url-mapper-transport.js +0 -28
  627. package/skills/wix-replatform/resources/rp-target-wix/lib/value-utils.js +0 -14
  628. package/skills/wix-replatform/resources/rp-target-wix/lib/variant-correlation.js +0 -34
  629. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-build.js +0 -388
  630. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-target-spec.js +0 -255
  631. package/skills/wix-replatform/resources/rp-target-wix/lib/wix-writers.js +0 -6041
  632. package/skills/wix-replatform/resources/rp-target-wix/lib/write-verification.js +0 -3
  633. package/skills/wix-replatform/resources/rp-target-wix/scripts/docs-survey-sync.js +0 -150
  634. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge-validate.js +0 -69
  635. package/skills/wix-replatform/resources/rp-target-wix/scripts/domain-knowledge.js +0 -100
  636. package/skills/wix-replatform/resources/rp-target-wix/scripts/verify-stores.js +0 -112
  637. package/skills/wix-replatform/resources/rp-telemetry/SKILL.md +0 -484
  638. package/skills/wix-replatform/resources/rp-telemetry/lib/bi-sink.js +0 -318
  639. package/skills/wix-replatform/resources/rp-telemetry/lib/telemetry-recorder.js +0 -2831
  640. package/skills/wix-replatform/resources/rp-telemetry/lib/transcript-digest.js +0 -318
  641. package/skills/wix-replatform/resources/rp-telemetry/scripts/meter-from-audit.js +0 -83
  642. package/skills/wix-replatform/resources/rp-telemetry/scripts/rp-telemetry.js +0 -243
  643. package/skills/wix-replatform/resources/rp-website-continuation/SKILL.md +0 -94
  644. package/skills/wix-replatform/scripts/artifact-freshness.js +0 -76
  645. package/skills/wix-replatform/scripts/census-reconciliation.js +0 -25
  646. package/skills/wix-replatform/scripts/cms-fallback.js +0 -89
  647. package/skills/wix-replatform/scripts/discovered-census.js +0 -26
  648. package/skills/wix-replatform/scripts/discovered-set-status.js +0 -33
  649. package/skills/wix-replatform/scripts/entity-qa-attestation.js +0 -130
  650. package/skills/wix-replatform/scripts/execution-health-check.js +0 -415
  651. package/skills/wix-replatform/scripts/execution-manifest-validate.js +0 -43
  652. package/skills/wix-replatform/scripts/execution-state-prepare.js +0 -128
  653. package/skills/wix-replatform/scripts/expectations-ledger.js +0 -44
  654. package/skills/wix-replatform/scripts/import-contract-verify.js +0 -183
  655. package/skills/wix-replatform/scripts/internal-link-audit.js +0 -90
  656. package/skills/wix-replatform/scripts/item-seo-tags-verify.js +0 -205
  657. package/skills/wix-replatform/scripts/migration-completion.js +0 -76
  658. package/skills/wix-replatform/scripts/orchestration-preflight.js +0 -67
  659. package/skills/wix-replatform/scripts/orchestration-route.js +0 -77
  660. package/skills/wix-replatform/scripts/orchestration-state.js +0 -381
  661. package/skills/wix-replatform/scripts/read-back-gate.js +0 -175
  662. package/skills/wix-replatform/scripts/replatform-console.js +0 -146
  663. package/skills/wix-replatform/scripts/replatform.js +0 -436
  664. package/skills/wix-replatform/scripts/source-secrets.js +0 -77
  665. package/skills/wix-replatform/scripts/url-redirects.js +0 -286
  666. package/skills/wix-replatform/scripts/user-action.js +0 -58
  667. package/skills/wix-replatform/scripts/website-handoff-generate.js +0 -64
  668. package/skills/wix-replatform/scripts/wix-dashboard-url.js +0 -54
  669. package/skills/wix-replatform/scripts/wix-destination.js +0 -143
  670. package/skills/wix-replatform/scripts/wix-headless-scaffold.js +0 -762
  671. package/skills/wix-vibe-headless/SKILL.md +0 -183
  672. package/skills/wix-vibe-headless/install/deploy.cjs +0 -221
  673. package/skills/wix-vibe-headless/install/pin-agents-md.cjs +0 -35
  674. package/skills/wix-vibe-headless/platforms/README.md +0 -26
  675. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed-with-install.md +0 -127
  676. package/skills/wix-vibe-headless/platforms/base44-ecom-light-seed.md +0 -121
  677. package/skills/wix-vibe-headless/platforms/base44-ecom-light.md +0 -87
  678. package/skills/wix-vibe-headless/platforms/base44.md +0 -148
  679. package/skills/wix-vibe-headless/platforms/generic.md +0 -132
  680. package/skills/wix-vibe-headless/references/_shared/nav/nav.tanstack.js +0 -30
  681. package/skills/wix-vibe-headless/references/_shared/routing.md +0 -86
  682. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +0 -270
  683. package/skills/wix-vibe-headless/references/blog/app/components/PostCard.jsx +0 -43
  684. package/skills/wix-vibe-headless/references/blog/app/components/PostChips.jsx +0 -25
  685. package/skills/wix-vibe-headless/references/blog/app/components/PostGrid.jsx +0 -15
  686. package/skills/wix-vibe-headless/references/blog/app/context/TaxonomyContext.jsx +0 -35
  687. package/skills/wix-vibe-headless/references/blog/app/hooks/usePostDetail.js +0 -38
  688. package/skills/wix-vibe-headless/references/blog/app/pages/Blog.jsx +0 -40
  689. package/skills/wix-vibe-headless/references/blog/app/pages/CategoryPage.jsx +0 -54
  690. package/skills/wix-vibe-headless/references/blog/app/pages/PostDetail.jsx +0 -65
  691. package/skills/wix-vibe-headless/references/blog/app/pages/TagPage.jsx +0 -50
  692. package/skills/wix-vibe-headless/references/blog/app/rest/wix-blog.js +0 -217
  693. package/skills/wix-vibe-headless/references/blog/seed/SEED.md +0 -99
  694. package/skills/wix-vibe-headless/references/blog/seed/seed-blog.cjs +0 -269
  695. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +0 -342
  696. package/skills/wix-vibe-headless/references/bookings/app/components/BookingForm.jsx +0 -65
  697. package/skills/wix-vibe-headless/references/bookings/app/components/RentalDurationPicker.jsx +0 -67
  698. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceCard.jsx +0 -47
  699. package/skills/wix-vibe-headless/references/bookings/app/components/ServiceGrid.jsx +0 -13
  700. package/skills/wix-vibe-headless/references/bookings/app/components/SlotPicker.jsx +0 -126
  701. package/skills/wix-vibe-headless/references/bookings/app/hooks/useRentalDuration.js +0 -128
  702. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServiceDetail.js +0 -110
  703. package/skills/wix-vibe-headless/references/bookings/app/hooks/useServices.js +0 -58
  704. package/skills/wix-vibe-headless/references/bookings/app/lib/serviceFacts.js +0 -95
  705. package/skills/wix-vibe-headless/references/bookings/app/pages/ServiceDetail.jsx +0 -94
  706. package/skills/wix-vibe-headless/references/bookings/app/pages/Services.jsx +0 -89
  707. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-checkout.js +0 -148
  708. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-rentals.js +0 -250
  709. package/skills/wix-vibe-headless/references/bookings/app/rest/wix-bookings-services.js +0 -300
  710. package/skills/wix-vibe-headless/references/bookings/seed/SEED.md +0 -154
  711. package/skills/wix-vibe-headless/references/bookings/seed/seed-bookings.cjs +0 -333
  712. package/skills/wix-vibe-headless/references/bookings/seed/seed-rentals.cjs +0 -267
  713. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +0 -178
  714. package/skills/wix-vibe-headless/references/cms/app/collection.config.js +0 -31
  715. package/skills/wix-vibe-headless/references/cms/app/lib/wixImage.js +0 -18
  716. package/skills/wix-vibe-headless/references/cms/app/rest/wix-cms.js +0 -231
  717. package/skills/wix-vibe-headless/references/cms/seed/SEED.md +0 -145
  718. package/skills/wix-vibe-headless/references/donations/INSTRUCTIONS.md +0 -88
  719. package/skills/wix-vibe-headless/references/donations/app/rest/wix-donations.js +0 -112
  720. package/skills/wix-vibe-headless/references/donations/seed/SEED.md +0 -11
  721. package/skills/wix-vibe-headless/references/donations/tests/donations.test.mjs +0 -258
  722. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +0 -267
  723. package/skills/wix-vibe-headless/references/events/app/components/CategoryFilter.jsx +0 -23
  724. package/skills/wix-vibe-headless/references/events/app/components/EventCard.jsx +0 -43
  725. package/skills/wix-vibe-headless/references/events/app/components/EventGrid.jsx +0 -13
  726. package/skills/wix-vibe-headless/references/events/app/components/EventRegistration.jsx +0 -29
  727. package/skills/wix-vibe-headless/references/events/app/components/RsvpForm.jsx +0 -57
  728. package/skills/wix-vibe-headless/references/events/app/components/TicketPicker.jsx +0 -78
  729. package/skills/wix-vibe-headless/references/events/app/hooks/useEventDetail.js +0 -27
  730. package/skills/wix-vibe-headless/references/events/app/hooks/useEventsList.js +0 -54
  731. package/skills/wix-vibe-headless/references/events/app/hooks/useRsvpForm.js +0 -40
  732. package/skills/wix-vibe-headless/references/events/app/hooks/useTicketing.js +0 -81
  733. package/skills/wix-vibe-headless/references/events/app/pages/EventDetail.jsx +0 -48
  734. package/skills/wix-vibe-headless/references/events/app/pages/Events.jsx +0 -36
  735. package/skills/wix-vibe-headless/references/events/app/rest/wix-events-browse.js +0 -136
  736. package/skills/wix-vibe-headless/references/events/app/rest/wix-events-registration.js +0 -187
  737. package/skills/wix-vibe-headless/references/events/seed/SEED.md +0 -103
  738. package/skills/wix-vibe-headless/references/events/seed/seed-events.cjs +0 -251
  739. package/skills/wix-vibe-headless/references/forms/INSTRUCTIONS.md +0 -487
  740. package/skills/wix-vibe-headless/references/forms/app/hooks/useWixForm.js +0 -425
  741. package/skills/wix-vibe-headless/references/forms/app/lib/wix-form-schema-utils.js +0 -187
  742. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms-submissions.js +0 -238
  743. package/skills/wix-vibe-headless/references/forms/app/rest/wix-forms.js +0 -108
  744. package/skills/wix-vibe-headless/references/forms/seed/SEED.md +0 -1836
  745. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +0 -328
  746. package/skills/wix-vibe-headless/references/members/app/components/LoginForm.jsx +0 -101
  747. package/skills/wix-vibe-headless/references/members/app/components/MemberMenu.jsx +0 -33
  748. package/skills/wix-vibe-headless/references/members/app/components/RequireAuth.jsx +0 -21
  749. package/skills/wix-vibe-headless/references/members/app/components/SocialButtons.jsx +0 -29
  750. package/skills/wix-vibe-headless/references/members/app/context/MemberContext.jsx +0 -54
  751. package/skills/wix-vibe-headless/references/members/app/hooks/useLoginForm.js +0 -77
  752. package/skills/wix-vibe-headless/references/members/app/pages/Account.jsx +0 -36
  753. package/skills/wix-vibe-headless/references/members/app/pages/Callback.jsx +0 -32
  754. package/skills/wix-vibe-headless/references/members/app/pages/Login.jsx +0 -35
  755. package/skills/wix-vibe-headless/references/members/app/rest/wix-members-auth.js +0 -390
  756. package/skills/wix-vibe-headless/references/members/install/Register.jsx +0 -22
  757. package/skills/wix-vibe-headless/references/members/seed/SEED.md +0 -21
  758. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +0 -270
  759. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionCard.jsx +0 -31
  760. package/skills/wix-vibe-headless/references/portfolio/app/components/CollectionGrid.jsx +0 -15
  761. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectCard.jsx +0 -39
  762. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectGrid.jsx +0 -15
  763. package/skills/wix-vibe-headless/references/portfolio/app/components/ProjectMedia.jsx +0 -29
  764. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useCollectionProjects.js +0 -35
  765. package/skills/wix-vibe-headless/references/portfolio/app/hooks/usePortfolioGallery.js +0 -27
  766. package/skills/wix-vibe-headless/references/portfolio/app/hooks/useProjectDetail.js +0 -25
  767. package/skills/wix-vibe-headless/references/portfolio/app/pages/CollectionPage.jsx +0 -39
  768. package/skills/wix-vibe-headless/references/portfolio/app/pages/Portfolio.jsx +0 -27
  769. package/skills/wix-vibe-headless/references/portfolio/app/pages/ProjectDetail.jsx +0 -60
  770. package/skills/wix-vibe-headless/references/portfolio/app/rest/wix-portfolio.js +0 -223
  771. package/skills/wix-vibe-headless/references/portfolio/seed/SEED.md +0 -90
  772. package/skills/wix-vibe-headless/references/portfolio/seed/seed-portfolio.cjs +0 -236
  773. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +0 -280
  774. package/skills/wix-vibe-headless/references/pricing-plans/app/components/OrderCard.jsx +0 -35
  775. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanCard.jsx +0 -48
  776. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanGrid.jsx +0 -16
  777. package/skills/wix-vibe-headless/references/pricing-plans/app/components/PlanPrice.jsx +0 -35
  778. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/useMyPlans.js +0 -25
  779. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlanDetail.js +0 -28
  780. package/skills/wix-vibe-headless/references/pricing-plans/app/hooks/usePlans.js +0 -30
  781. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/MyPlans.jsx +0 -30
  782. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/PlanDetail.jsx +0 -53
  783. package/skills/wix-vibe-headless/references/pricing-plans/app/pages/Plans.jsx +0 -28
  784. package/skills/wix-vibe-headless/references/pricing-plans/app/rest/wix-pricing-plans.js +0 -157
  785. package/skills/wix-vibe-headless/references/pricing-plans/seed/SEED.md +0 -82
  786. package/skills/wix-vibe-headless/references/pricing-plans/seed/seed-pricing-plans.cjs +0 -251
  787. package/skills/wix-vibe-headless/references/rentals/INSTRUCTIONS.md +0 -13
  788. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +0 -290
  789. package/skills/wix-vibe-headless/references/restaurants/app/components/ItemDialog.jsx +0 -81
  790. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuItemCard.jsx +0 -71
  791. package/skills/wix-vibe-headless/references/restaurants/app/components/MenuList.jsx +0 -43
  792. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartButton.jsx +0 -21
  793. package/skills/wix-vibe-headless/references/restaurants/app/components/OrderCartDrawer.jsx +0 -72
  794. package/skills/wix-vibe-headless/references/restaurants/app/context/OrderCartContext.jsx +0 -66
  795. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useItemOrder.js +0 -32
  796. package/skills/wix-vibe-headless/references/restaurants/app/hooks/useReservation.js +0 -73
  797. package/skills/wix-vibe-headless/references/restaurants/app/pages/Menu.jsx +0 -28
  798. package/skills/wix-vibe-headless/references/restaurants/app/pages/Reservations.jsx +0 -102
  799. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-menu.js +0 -224
  800. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-ordering.js +0 -218
  801. package/skills/wix-vibe-headless/references/restaurants/app/rest/wix-restaurants-reservations.js +0 -107
  802. package/skills/wix-vibe-headless/references/restaurants/seed/SEED.md +0 -176
  803. package/skills/wix-vibe-headless/references/restaurants/seed/seed-restaurants.cjs +0 -452
  804. package/skills/wix-vibe-headless/references/shared/app/components/WixManageBanner.jsx +0 -56
  805. package/skills/wix-vibe-headless/references/shared/app/lib/nav.js +0 -9
  806. package/skills/wix-vibe-headless/references/shared/app/rest/wix-client.js +0 -185
  807. package/skills/wix-vibe-headless/references/shared/app/rest/wix-config.js +0 -8
  808. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +0 -471
  809. package/skills/wix-vibe-headless/references/storefront/app/components/CartButton.jsx +0 -20
  810. package/skills/wix-vibe-headless/references/storefront/app/components/CartDrawer.jsx +0 -167
  811. package/skills/wix-vibe-headless/references/storefront/app/context/CartContext.jsx +0 -83
  812. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductCard.js +0 -104
  813. package/skills/wix-vibe-headless/references/storefront/app/hooks/useProductDetail.js +0 -163
  814. package/skills/wix-vibe-headless/references/storefront/app/hooks/useShop.js +0 -83
  815. package/skills/wix-vibe-headless/references/storefront/app/hooks/useVariantOptions.js +0 -76
  816. package/skills/wix-vibe-headless/references/storefront/app/lib/storeImage.js +0 -64
  817. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-cart.js +0 -176
  818. package/skills/wix-vibe-headless/references/storefront/app/rest/wix-store-catalog.js +0 -218
  819. package/skills/wix-vibe-headless/references/storefront/seed/SEED.md +0 -174
  820. 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
- };