@wix/agent-skills 1.14.0 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (247) hide show
  1. package/README.md +4 -1
  2. package/package.json +1 -1
  3. package/skills/README.md +23 -0
  4. package/skills/wix-app/SKILL.md +10 -2
  5. package/skills/wix-app/references/AUTO_PATTERNS_DASHBOARD.md +326 -0
  6. package/skills/wix-app/references/CODE_QUALITY.md +1 -0
  7. package/skills/wix-app/references/CUSTOM_ELEMENT_WIDGET.md +124 -115
  8. package/skills/wix-app/references/DASHBOARD_PAGE.md +3 -0
  9. package/skills/wix-app/references/EDITOR_REACT_COMPONENT.md +23 -9
  10. package/skills/wix-app/references/SITE_PLUGIN.md +1 -1
  11. package/skills/wix-app/references/auto-patterns-dashboard/action-cell.md +115 -0
  12. package/skills/wix-app/references/auto-patterns-dashboard/app-config-structure.md +264 -0
  13. package/skills/wix-app/references/auto-patterns-dashboard/app-context.md +37 -0
  14. package/skills/wix-app/references/auto-patterns-dashboard/bulk-actions.md +86 -0
  15. package/skills/wix-app/references/auto-patterns-dashboard/collection-page-actions.md +119 -0
  16. package/skills/wix-app/references/auto-patterns-dashboard/collection-page.md +103 -0
  17. package/skills/wix-app/references/auto-patterns-dashboard/custom-actions-override.md +76 -0
  18. package/skills/wix-app/references/auto-patterns-dashboard/custom-columns-override.md +82 -0
  19. package/skills/wix-app/references/auto-patterns-dashboard/custom-components-override.md +89 -0
  20. package/skills/wix-app/references/auto-patterns-dashboard/custom-header-override.md +124 -0
  21. package/skills/wix-app/references/auto-patterns-dashboard/custom-sections-override.md +91 -0
  22. package/skills/wix-app/references/auto-patterns-dashboard/custom-slots-override.md +71 -0
  23. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-actions.md +70 -0
  24. package/skills/wix-app/references/auto-patterns-dashboard/entity-page-view-actions.md +73 -0
  25. package/skills/wix-app/references/auto-patterns-dashboard/entity-page.md +98 -0
  26. package/skills/wix-app/references/auto-patterns-dashboard/example-patterns.json +278 -0
  27. package/skills/wix-app/references/auto-patterns-dashboard/pages-configuration.md +94 -0
  28. package/skills/wix-app/references/auto-patterns-dashboard/resolved-action.md +43 -0
  29. package/skills/wix-app/references/auto-patterns-dashboard/sdk-utilities.md +66 -0
  30. package/skills/wix-app/references/auto-patterns-dashboard/views.md +76 -0
  31. package/skills/wix-app/references/editor-react-component/ACCESSIBILITY.md +1 -14
  32. package/skills/wix-app/references/editor-react-component/COMPONENT-API.md +54 -29
  33. package/skills/wix-app/references/editor-react-component/COMPONENT-CONFIGURATION.md +2 -2
  34. package/skills/wix-app/references/editor-react-component/CSS-GUIDELINES.md +17 -105
  35. package/skills/wix-app/references/editor-react-component/DESIGN-STATES.md +127 -0
  36. package/skills/wix-app/references/editor-react-component/PARTS.md +2 -1
  37. package/skills/wix-app/references/editor-react-component/REACT-GUIDELINES.md +15 -15
  38. package/skills/wix-app/references/editor-react-component/REACT-PATTERNS.md +25 -53
  39. package/skills/wix-app/scripts/generate-auto-patterns.js +510 -0
  40. package/skills/wix-auth/SKILL.md +12 -0
  41. package/skills/wix-auth/references/device-flow.md +140 -0
  42. package/skills/wix-docs/SKILL.md +188 -0
  43. package/skills/wix-docs/references/API_SPEC_SEARCH.md +213 -0
  44. package/skills/wix-docs/references/EXTRACTING.md +120 -0
  45. package/skills/wix-headless/SKILL.md +84 -130
  46. package/skills/wix-headless/entry/bootstrap.mjs +93 -0
  47. package/skills/wix-headless/entry/skill.md +78 -0
  48. package/skills/wix-headless/references/AI_FEATURES.md +178 -0
  49. package/skills/wix-headless/references/CAPABILITIES.md +84 -0
  50. package/skills/wix-headless/references/DISCOVERY.md +34 -56
  51. package/skills/wix-headless/references/DOC_DISCOVERY.md +37 -0
  52. package/skills/wix-headless/references/FEEDBACK.md +118 -0
  53. package/skills/wix-headless/references/IMAGE_GENERATION.md +69 -0
  54. package/skills/wix-headless/references/SDK_HANDOFF.md +97 -0
  55. package/skills/wix-headless/references/SEED.md +44 -188
  56. package/skills/wix-headless/references/SETUP.md +32 -103
  57. package/skills/wix-headless/references/astro.md +98 -0
  58. package/skills/wix-headless/references/inline-recipes/how-to-code-a-blog.md +196 -0
  59. package/skills/wix-headless/references/inline-recipes/how-to-code-a-store.md +236 -0
  60. package/skills/wix-headless/references/inline-recipes/how-to-code-bookings.md +279 -0
  61. package/skills/wix-headless/references/inline-recipes/how-to-code-cms.md +163 -0
  62. package/skills/wix-headless/references/inline-recipes/how-to-code-events.md +203 -0
  63. package/skills/wix-headless/references/inline-recipes/how-to-code-forms.md +222 -0
  64. package/skills/wix-headless/references/inline-recipes/how-to-code-members-astro.md +124 -0
  65. package/skills/wix-headless/references/inline-recipes/how-to-code-members-custom-login.md +160 -0
  66. package/skills/wix-headless/references/inline-recipes/how-to-code-members-non-astro.md +118 -0
  67. package/skills/wix-headless/references/inline-recipes/how-to-code-portfolio.md +132 -0
  68. package/skills/wix-headless/references/inline-recipes/how-to-code-pricing-plans.md +124 -0
  69. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-orders.md +188 -0
  70. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurant-reservations.md +173 -0
  71. package/skills/wix-headless/references/inline-recipes/how-to-code-restaurants.md +161 -0
  72. package/skills/wix-headless/references/inline-recipes/setup-blog.md +175 -0
  73. package/skills/wix-headless/references/inline-recipes/setup-bookings.md +228 -0
  74. package/skills/wix-headless/references/inline-recipes/setup-cms.md +200 -0
  75. package/skills/wix-headless/references/inline-recipes/setup-events.md +196 -0
  76. package/skills/wix-headless/references/inline-recipes/setup-forms.md +174 -0
  77. package/skills/wix-headless/references/inline-recipes/setup-online-store.md +176 -0
  78. package/skills/wix-headless/references/inline-recipes/setup-portfolio.md +153 -0
  79. package/skills/wix-headless/references/inline-recipes/setup-pricing-plans.md +229 -0
  80. package/skills/wix-headless/references/inline-recipes/setup-restaurant-orders.md +161 -0
  81. package/skills/wix-headless/references/inline-recipes/setup-restaurant-reservations.md +117 -0
  82. package/skills/wix-headless/references/inline-recipes/setup-restaurants.md +152 -0
  83. package/skills/wix-headless/references/managed/AUTHENTICATION.md +57 -0
  84. package/skills/wix-headless/references/managed/CONNECT.md +74 -0
  85. package/skills/wix-headless/references/managed/CREATE.md +130 -0
  86. package/skills/wix-headless/references/managed/DEPLOYMENT.md +57 -0
  87. package/skills/wix-headless/references/non-astro.md +59 -0
  88. package/skills/wix-headless/references/self-managed/AUTHENTICATION.md +22 -0
  89. package/skills/wix-headless/references/self-managed/DEPLOYMENT.md +7 -0
  90. package/skills/wix-headless/references/stripe/AUTHENTICATION.md +55 -0
  91. package/skills/wix-headless/references/stripe/DEPLOYMENT.md +63 -0
  92. package/skills/wix-manage/SKILL.md +24 -1
  93. package/skills/wix-manage/references/analytics/query-site-analytics.md +241 -0
  94. package/skills/wix-manage/references/bookings/create-and-update-booking-services.md +1 -1
  95. package/skills/wix-manage/references/bookings/diagnose-availability-issues.md +265 -0
  96. package/skills/wix-manage/references/marketing/create-and-publish-social-post.md +436 -0
  97. package/skills/wix-manage/references/marketing/generate-and-publish-marketing-plan.md +209 -0
  98. package/skills/wix-manage/references/rich-content/author-ricos-rich-content.md +249 -0
  99. package/skills/wix-manage/references/stores/create-product-with-options-catalog-v3.md +51 -0
  100. package/skills/wix-vibe-headless/SKILL.md +136 -0
  101. package/skills/wix-vibe-headless/references/blog/INSTRUCTIONS.md +128 -0
  102. package/skills/wix-vibe-headless/references/blog/wix-blog.js +217 -0
  103. package/skills/wix-vibe-headless/references/bookings/INSTRUCTIONS.md +153 -0
  104. package/skills/wix-vibe-headless/references/bookings/wix-bookings-checkout.js +147 -0
  105. package/skills/wix-vibe-headless/references/bookings/wix-bookings-services.js +215 -0
  106. package/skills/wix-vibe-headless/references/cms/INSTRUCTIONS.md +154 -0
  107. package/skills/wix-vibe-headless/references/cms/wix-cms.js +186 -0
  108. package/skills/wix-vibe-headless/references/events/INSTRUCTIONS.md +142 -0
  109. package/skills/wix-vibe-headless/references/events/wix-events-browse.js +135 -0
  110. package/skills/wix-vibe-headless/references/events/wix-events-registration.js +187 -0
  111. package/skills/wix-vibe-headless/references/members/INSTRUCTIONS.md +211 -0
  112. package/skills/wix-vibe-headless/references/members/wix-members-auth.js +387 -0
  113. package/skills/wix-vibe-headless/references/portfolio/INSTRUCTIONS.md +111 -0
  114. package/skills/wix-vibe-headless/references/portfolio/wix-portfolio.js +194 -0
  115. package/skills/wix-vibe-headless/references/pricing-plans/INSTRUCTIONS.md +127 -0
  116. package/skills/wix-vibe-headless/references/pricing-plans/wix-pricing-plans.js +157 -0
  117. package/skills/wix-vibe-headless/references/restaurants/INSTRUCTIONS.md +138 -0
  118. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-menu.js +224 -0
  119. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-ordering.js +156 -0
  120. package/skills/wix-vibe-headless/references/restaurants/wix-restaurants-reservations.js +107 -0
  121. package/skills/wix-vibe-headless/references/shared/wix-client.js +186 -0
  122. package/skills/wix-vibe-headless/references/storefront/INSTRUCTIONS.md +155 -0
  123. package/skills/wix-vibe-headless/references/storefront/wix-store-cart.js +147 -0
  124. package/skills/wix-vibe-headless/references/storefront/wix-store-catalog.js +142 -0
  125. package/skills/wix-headless/references/BUILD-astro.md +0 -253
  126. package/skills/wix-headless/references/BUILD-own-build.md +0 -167
  127. package/skills/wix-headless/references/BUILD.md +0 -105
  128. package/skills/wix-headless/references/DESIGN_SYSTEM.md +0 -165
  129. package/skills/wix-headless/references/DISCOVERY-connect.md +0 -55
  130. package/skills/wix-headless/references/DISCOVERY-create.md +0 -238
  131. package/skills/wix-headless/references/PLAN-connect.md +0 -19
  132. package/skills/wix-headless/references/PLAN-create.md +0 -17
  133. package/skills/wix-headless/references/PLAN.md +0 -92
  134. package/skills/wix-headless/references/astro/blog/BLOG_PAGES.md +0 -300
  135. package/skills/wix-headless/references/astro/blog/BLOG_SETUP.md +0 -218
  136. package/skills/wix-headless/references/astro/bookings/COMPONENTS.md +0 -45
  137. package/skills/wix-headless/references/astro/bookings/SERVICES_PAGES.md +0 -77
  138. package/skills/wix-headless/references/astro/cms/CMS_FOUNDATIONS.md +0 -214
  139. package/skills/wix-headless/references/astro/cms/FAQ_KNOWLEDGE_BASE.md +0 -231
  140. package/skills/wix-headless/references/astro/cms/PORTFOLIO.md +0 -453
  141. package/skills/wix-headless/references/astro/cms/RESOURCE_LIBRARY.md +0 -354
  142. package/skills/wix-headless/references/astro/cms/TEAM_DIRECTORY.md +0 -299
  143. package/skills/wix-headless/references/astro/designer/INSTRUCTIONS.md +0 -351
  144. package/skills/wix-headless/references/astro/ecom/CART_PAGES.md +0 -119
  145. package/skills/wix-headless/references/astro/ecom/CART_WIRING.md +0 -103
  146. package/skills/wix-headless/references/astro/ecom/COMPONENTS_CSS.md +0 -132
  147. package/skills/wix-headless/references/astro/forms/CONTACT_FORM.md +0 -463
  148. package/skills/wix-headless/references/astro/gift-cards/COMPONENTS.md +0 -119
  149. package/skills/wix-headless/references/astro/gift-cards/PAGES.md +0 -129
  150. package/skills/wix-headless/references/astro/stores/BACK_IN_STOCK.md +0 -178
  151. package/skills/wix-headless/references/astro/stores/CATEGORY_PAGES.md +0 -85
  152. package/skills/wix-headless/references/astro/stores/COMPONENTS_CSS.md +0 -129
  153. package/skills/wix-headless/references/astro/stores/HOME_AND_NAV.md +0 -229
  154. package/skills/wix-headless/references/astro/stores/PRODUCT_PAGES.md +0 -215
  155. package/skills/wix-headless/references/astro/stores/SHARED_WIRING.md +0 -165
  156. package/skills/wix-headless/references/astro/templates/Layout.astro +0 -132
  157. package/skills/wix-headless/references/astro/templates/astro.config.mjs +0 -41
  158. package/skills/wix-headless/references/astro/templates/bookings/AvailabilityCalendar.tsx +0 -374
  159. package/skills/wix-headless/references/astro/templates/bookings/BookingForm.tsx +0 -136
  160. package/skills/wix-headless/references/astro/templates/bookings/SeoTags.astro +0 -25
  161. package/skills/wix-headless/references/astro/templates/bookings/ServiceBookingFlow.tsx +0 -71
  162. package/skills/wix-headless/references/astro/templates/bookings/ServiceCard.astro +0 -54
  163. package/skills/wix-headless/references/astro/templates/bookings/booking-confirmation.astro +0 -49
  164. package/skills/wix-headless/references/astro/templates/bookings/bookingDriver.ts +0 -245
  165. package/skills/wix-headless/references/astro/templates/bookings/components-bookings.css +0 -424
  166. package/skills/wix-headless/references/astro/templates/bookings/services/[slug].astro +0 -176
  167. package/skills/wix-headless/references/astro/templates/bookings/services/index.astro +0 -181
  168. package/skills/wix-headless/references/astro/templates/ecom/CartBadge.tsx +0 -84
  169. package/skills/wix-headless/references/astro/templates/ecom/CartView.tsx +0 -543
  170. package/skills/wix-headless/references/astro/templates/ecom/cart.astro +0 -13
  171. package/skills/wix-headless/references/astro/templates/ecom/components-ecom.css +0 -302
  172. package/skills/wix-headless/references/astro/templates/ecom/discounts.ts +0 -71
  173. package/skills/wix-headless/references/astro/templates/ecom/thank-you.astro +0 -24
  174. package/skills/wix-headless/references/astro/templates/gift-cards/GiftCardPurchase.tsx +0 -172
  175. package/skills/wix-headless/references/astro/templates/gift-cards/_home-teaser-snippet.astro +0 -42
  176. package/skills/wix-headless/references/astro/templates/gift-cards/_nav-snippet.astro +0 -11
  177. package/skills/wix-headless/references/astro/templates/gift-cards/components-gift-cards.css +0 -220
  178. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.astro +0 -51
  179. package/skills/wix-headless/references/astro/templates/gift-cards/gift-cards.ts +0 -75
  180. package/skills/wix-headless/references/astro/templates/global.css +0 -288
  181. package/skills/wix-headless/references/astro/templates/stores/AddToCartButton.tsx +0 -77
  182. package/skills/wix-headless/references/astro/templates/stores/BackInStockForm.tsx +0 -176
  183. package/skills/wix-headless/references/astro/templates/stores/CategoryRail.astro +0 -69
  184. package/skills/wix-headless/references/astro/templates/stores/ProductCard.astro +0 -79
  185. package/skills/wix-headless/references/astro/templates/stores/ProductPurchase.tsx +0 -397
  186. package/skills/wix-headless/references/astro/templates/stores/SeoTags.astro +0 -21
  187. package/skills/wix-headless/references/astro/templates/stores/back-in-stock.ts +0 -67
  188. package/skills/wix-headless/references/astro/templates/stores/categories.ts +0 -155
  189. package/skills/wix-headless/references/astro/templates/stores/category/[slug].astro +0 -130
  190. package/skills/wix-headless/references/astro/templates/stores/components-stores.css +0 -400
  191. package/skills/wix-headless/references/astro/templates/stores/products/[slug].astro +0 -128
  192. package/skills/wix-headless/references/astro/templates/stores/products/index.astro +0 -101
  193. package/skills/wix-headless/references/blog/BLOG_CONTENT.md +0 -161
  194. package/skills/wix-headless/references/blog/INSTRUCTIONS.md +0 -32
  195. package/skills/wix-headless/references/bookings/FLOW.md +0 -246
  196. package/skills/wix-headless/references/bookings/INSTRUCTIONS.md +0 -95
  197. package/skills/wix-headless/references/bookings/SERVICES_DATA.md +0 -355
  198. package/skills/wix-headless/references/cms/CMS_FOUNDATIONS.md +0 -176
  199. package/skills/wix-headless/references/cms/INSTRUCTIONS.md +0 -71
  200. package/skills/wix-headless/references/commands/known-apps.json +0 -6
  201. package/skills/wix-headless/references/custom/CONNECTION_PLAN.md +0 -142
  202. package/skills/wix-headless/references/custom/INSTRUCTIONS.md +0 -88
  203. package/skills/wix-headless/references/custom/blog/WIRING.md +0 -52
  204. package/skills/wix-headless/references/custom/bookings/WIRING.md +0 -197
  205. package/skills/wix-headless/references/custom/cms/WIRING.md +0 -97
  206. package/skills/wix-headless/references/custom/ecom/WIRING.md +0 -67
  207. package/skills/wix-headless/references/custom/forms/WIRING.md +0 -101
  208. package/skills/wix-headless/references/custom/stores/WIRING.md +0 -80
  209. package/skills/wix-headless/references/ecom/INSTRUCTIONS.md +0 -59
  210. package/skills/wix-headless/references/forms/INSTRUCTIONS.md +0 -43
  211. package/skills/wix-headless/references/gift-cards/INSTRUCTIONS.md +0 -51
  212. package/skills/wix-headless/references/images/INSTRUCTIONS.md +0 -357
  213. package/skills/wix-headless/references/seed-recipes.md +0 -49
  214. package/skills/wix-headless/references/shared/AGENTS_MD.md +0 -47
  215. package/skills/wix-headless/references/shared/AUTHENTICATION.md +0 -108
  216. package/skills/wix-headless/references/shared/BUILD_NOISE.md +0 -8
  217. package/skills/wix-headless/references/shared/DESIGN_MD.md +0 -84
  218. package/skills/wix-headless/references/shared/DOCS_SEARCH.md +0 -41
  219. package/skills/wix-headless/references/shared/IMAGE_GENERATION.md +0 -186
  220. package/skills/wix-headless/references/shared/IMPLEMENTER.md +0 -206
  221. package/skills/wix-headless/references/shared/PRODUCTION_SHARP_EDGES.md +0 -97
  222. package/skills/wix-headless/references/shared/RETURN_CONTRACT.md +0 -143
  223. package/skills/wix-headless/references/shared/STYLING.md +0 -140
  224. package/skills/wix-headless/references/stores/INSTRUCTIONS.md +0 -126
  225. package/skills/wix-headless/references/stores/PRODUCT_CATALOG_DATA.md +0 -252
  226. package/skills/wix-headless/references/verticals/_schema.json +0 -74
  227. package/skills/wix-headless/references/verticals/_schema.md +0 -95
  228. package/skills/wix-headless/references/verticals/blog.md +0 -31
  229. package/skills/wix-headless/references/verticals/bookings.md +0 -41
  230. package/skills/wix-headless/references/verticals/cms.md +0 -30
  231. package/skills/wix-headless/references/verticals/ecom.md +0 -25
  232. package/skills/wix-headless/references/verticals/forms.md +0 -26
  233. package/skills/wix-headless/references/verticals/gift-cards.md +0 -24
  234. package/skills/wix-headless/references/verticals/stores.md +0 -33
  235. package/skills/wix-headless/scripts/check-manifest.mjs +0 -335
  236. package/skills/wix-headless/scripts/compose.mjs +0 -520
  237. package/skills/wix-headless/scripts/emit-design-tokens.mjs +0 -157
  238. package/skills/wix-headless/scripts/flatten.sh +0 -61
  239. package/skills/wix-headless/scripts/generate-images.mjs +0 -242
  240. package/skills/wix-headless/scripts/patch-decorative-slots.mjs +0 -154
  241. package/skills/wix-headless/scripts/plan-entity-image-waves.mjs +0 -190
  242. package/skills/wix-headless/scripts/scaffold.sh +0 -139
  243. package/skills/wix-headless/scripts/seed-utilities.sh +0 -93
  244. package/skills/wix-headless/scripts/write-decorative-json.mjs +0 -62
  245. package/skills/wix-headless/shared-utilities/analytics.ts +0 -40
  246. package/skills/wix-headless/shared-utilities/ricos.ts +0 -179
  247. package/skills/wix-headless/shared-utilities/wix-image.ts +0 -72
@@ -1,520 +0,0 @@
1
- #!/usr/bin/env node
2
- // ── compose.mjs — the deterministic Composer (astro design-system phase) ──────
3
- //
4
- // Replaces the former `design-system-composer` LLM subagent (this script is now
5
- // the sole spec). The Composer's job is MECHANICAL: take the Designer's framework-
6
- // agnostic spec + the application inputs and SUBSTITUTE them into six pinned
7
- // skeletons at references/astro/templates/. There is no judgment in re-emitting
8
- // the fixed bulk (View-Transitions script, @utility btn family, view-transition
9
- // CSS), so an LLM is pure cost + run-to-run variance. This script does it in
10
- // sub-second, byte-reproducibly.
11
- //
12
- // It is a sibling of emit-design-tokens.mjs / patch-decorative-slots.mjs and,
13
- // like them, reads its input as a JSON object on stdin and takes the project
14
- // dir as argv[2]. It locates the skeletons relative to its own path (no
15
- // SKILL_ROOT needed).
16
- //
17
- // Usage:
18
- // node compose.mjs <project-dir> <<'JSON'
19
- // { "shell": {...}, "brand": {...}, "navLinks": [...],
20
- // "loadedPacks": [...], "packsWithComponents": [...], "disabledPacks": [...] }
21
- // JSON
22
- //
23
- // Tokens come from DESIGN.md — the single design format (no inline token JSON).
24
- // compose reads `<project-dir>/DESIGN.md` (or `designMdPath`), parses its
25
- // FRONTMATTER ONLY (the markdown body is documentation, never read), and applies
26
- // a role-translation table (references/shared/DESIGN_MD.md) so a DESIGN.md
27
- // authored with standard roles (primary/surface/on-surface/…) maps onto the wix
28
- // `--color-*` vocabulary; wix-native keys pass through losslessly. `rounded` →
29
- // radii; a custom `containers` group + a `googleFontsHref` key are honored.
30
- // The Designer authors that DESIGN.md directly; emit-design-tokens.mjs projects
31
- // the token CSS/types from it. DESIGN.md exists on disk before compose runs.
32
- //
33
- // stdin JSON (the application inputs — NOT the design tokens, which live in DESIGN.md):
34
- // - designMdPath — optional path to the DESIGN.md (default <project-dir>/DESIGN.md).
35
- // - shell — { heroHeadline, heroSub, footerTagline, navBrandMark }.
36
- // - brand — { name, description }.
37
- // - navLinks — [ { href, label } ]; labels used VERBATIM.
38
- // - loadedPacks — string[] of loaded vertical packs.
39
- // - packsWithComponents — string[]; one components-<pack>.css import per entry,
40
- // in order (COMPOSE § Layout.astro).
41
- // - disabledPacks — string[]; dormant packs still get their home/nav markers,
42
- // never a visible entry point.
43
- //
44
- // What it writes (the 6 design-system files), by substituting {{…}} slots into
45
- // the pinned skeletons — the fixed bulk is copied byte-for-byte:
46
- // 1. src/styles/global.css — {{theme}} ← @theme palette
47
- // 2. astro.config.mjs — MERGE (anchored codemod, not clobber)
48
- // 3. src/layouts/Layout.astro — imports, fonts href, brand title
49
- // 4. src/components/Navigation.astro — brand mark, nav links
50
- // 5. src/components/Footer.astro — brand, tagline, nav links
51
- // 6. src/pages/index.astro — hero copy, brand, home markers
52
- //
53
- // Token contract: guarantees the required-token set (STYLING.md § "Required
54
- // tokens — the component-CSS template contract") resolves in @theme. Missing
55
- // roles are DERIVED as a fail-safe (the Designer is expected to emit a complete
56
- // set + a googleFontsHref; derivation is a safety net, not the hot path).
57
- //
58
- // Output: a single manifest JSON object on stdout (the orchestrator parses it
59
- // the same way it parsed the subagent's return — same { status, phase, data,
60
- // files } shape). Diagnostics go to stderr. Exit 0 on complete, 1 on a hard
61
- // failure (missing scaffold / unrecoverable token gap / missing config anchor).
62
- //
63
- // astro only. Custom (non-astro) frontends never reach the Composer — the
64
- // orchestrator only invokes this when frontend === "astro".
65
-
66
- import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
67
- import { join, dirname, resolve, isAbsolute } from "node:path";
68
- import { fileURLToPath } from "node:url";
69
- import { execSync } from "node:child_process";
70
-
71
- const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
72
- const TEMPLATES = resolve(SCRIPT_DIR, "..", "references", "astro", "templates");
73
-
74
- const projectDir = process.argv[2] ?? process.cwd();
75
-
76
- function die(code, message) {
77
- // Emit a structured failure manifest on stdout so the orchestrator parses a
78
- // return either way, plus a human line on stderr. Hard-fail with exit 1.
79
- console.error(`compose: ${message}`);
80
- console.log(JSON.stringify({ status: "failed", phase: "compose", data: {}, files: [], errors: [{ code, message }] }, null, 2));
81
- process.exit(1);
82
- }
83
-
84
- // ── read + validate input ─────────────────────────────────────────────────────
85
- if (process.stdin.isTTY) die("NO_INPUT", "expected the compose input JSON on stdin");
86
- let input;
87
- try {
88
- const raw = readFileSync(0, "utf8").trim();
89
- if (!raw) die("EMPTY_INPUT", "stdin was empty — pass the compose input JSON object");
90
- input = JSON.parse(raw);
91
- } catch (e) {
92
- die("BAD_JSON", `stdin is not valid JSON (${e.message})`);
93
- }
94
-
95
- // ── token source: DESIGN.md frontmatter (portable) ───────────────────────────
96
- // Minimal frontmatter parser for the restricted DESIGN.md shape (groups of
97
- // `key: scalar`, plus typography tokens with an indented `fontFamily:`). Not a
98
- // general YAML parser — the body is never read. Color values are quoted in the
99
- // emitted DESIGN.md because an unquoted `#hex` after `: ` is a YAML comment.
100
- function unquote(v) {
101
- v = v.trim();
102
- const qc = v[0];
103
- if (qc === '"' || qc === "'") {
104
- // Return the quoted content up to the closing quote (handles a trailing
105
- // ` # comment` after the closing quote, and \" / \\ escapes in "…").
106
- let out = "";
107
- for (let i = 1; i < v.length; i++) {
108
- const c = v[i];
109
- if (qc === '"' && c === "\\" && i + 1 < v.length) { out += v[++i]; continue; }
110
- if (c === qc) break;
111
- out += c;
112
- }
113
- return out;
114
- }
115
- const hash = v.search(/\s#/); // strip trailing inline comment on bare scalars
116
- if (hash !== -1) v = v.slice(0, hash).trim();
117
- return v;
118
- }
119
- // Parse a flow-style inline object — `{ fontFamily: "X", fontWeight: 600 }` —
120
- // splitting top-level commas while respecting quotes (so `"Helvetica, Arial"`
121
- // stays one value). Used for typography tokens authored in flow style.
122
- function parseInlineObject(s) {
123
- const inner = s.trim().replace(/^\{/, "").replace(/\}$/, "");
124
- const obj = {};
125
- let buf = "", inq = null;
126
- const parts = [];
127
- for (const ch of inner) {
128
- if (inq) { if (ch === inq) inq = null; buf += ch; continue; }
129
- if (ch === '"' || ch === "'") { inq = ch; buf += ch; continue; }
130
- if (ch === ",") { parts.push(buf); buf = ""; continue; }
131
- buf += ch;
132
- }
133
- if (buf.trim()) parts.push(buf);
134
- for (const p of parts) {
135
- const ci = p.indexOf(":");
136
- if (ci === -1) continue;
137
- obj[p.slice(0, ci).trim()] = unquote(p.slice(ci + 1));
138
- }
139
- return obj;
140
- }
141
- function parseFrontmatter(text) {
142
- const m = text.match(/^---\r?\n([\s\S]*?)\r?\n---/);
143
- if (!m) return null;
144
- const root = {};
145
- let group = null, sub = null;
146
- for (const raw of m[1].split(/\r?\n/)) {
147
- if (!raw.trim() || /^\s*#/.test(raw)) continue;
148
- const indent = raw.match(/^ */)[0].length;
149
- const ci = raw.indexOf(":");
150
- if (ci === -1) continue;
151
- const key = raw.slice(0, ci).trim();
152
- const rest = raw.slice(ci + 1).trim();
153
- if (indent === 0) {
154
- if (rest === "") { root[key] = {}; group = key; sub = null; }
155
- else if (rest.startsWith("{")) { root[key] = parseInlineObject(rest); group = null; sub = null; }
156
- else { root[key] = unquote(rest); group = null; sub = null; }
157
- } else if (indent === 2 && group) {
158
- if (rest === "") { root[group][key] = {}; sub = key; }
159
- else if (rest.startsWith("{")) { root[group][key] = parseInlineObject(rest); sub = null; }
160
- else { root[group][key] = unquote(rest); sub = null; }
161
- } else if (indent >= 4 && group && sub) {
162
- if (typeof root[group][sub] !== "object") root[group][sub] = {};
163
- root[group][sub][key] = unquote(rest);
164
- }
165
- }
166
- return root;
167
- }
168
- // Standard DESIGN.md color roles → wix editorial `--color-*` names. wix-native
169
- // keys (paper/ink/accent/…) are NOT in this table and pass through unchanged,
170
- // winning on any conflict — so our own emission is lossless.
171
- const COLOR_ROLE_TABLE = {
172
- primary: "accent", secondary: "paper-warm", tertiary: "ink-soft", neutral: "mute",
173
- surface: "paper", "on-surface": "ink", background: "paper", "on-background": "ink",
174
- outline: "rule", error: "error",
175
- };
176
- function designMdToTokens(fm) {
177
- // Single pass preserving source key order: each key maps via the role table
178
- // (standard DESIGN.md role → wix name) or passes through unchanged (wix-native
179
- // keys aren't in the table). Order-preserving so our own round-trip is
180
- // byte-identical to the JSON path. (A file mixing a standard role and its wix
181
- // synonym — e.g. both `surface` and `paper` — is pathological; last wins.)
182
- const colors = {};
183
- for (const [k, v] of Object.entries(fm.colors ?? {})) colors[COLOR_ROLE_TABLE[k] ?? k] = v;
184
- const typ = fm.typography ?? {};
185
- const famOf = (...keys) => { for (const key of keys) if (typ[key] && typ[key].fontFamily) return typ[key].fontFamily; return undefined; };
186
- const fonts = {};
187
- const disp = famOf("display", "h1", "heading", "title");
188
- const body = famOf("body", "p", "text", "base", "paragraph");
189
- if (disp) fonts.display = disp;
190
- if (body) fonts.body = body;
191
- if (typ.mono && typ.mono.fontFamily) fonts.mono = typ.mono.fontFamily;
192
- return {
193
- colors,
194
- fonts,
195
- radii: fm.rounded ?? {}, // DESIGN.md calls corner radii `rounded`
196
- containers: fm.containers ?? {}, // custom group
197
- ...(typeof fm.googleFontsHref === "string" ? { googleFontsHref: fm.googleFontsHref } : {}),
198
- };
199
- }
200
-
201
- // DESIGN.md is the single token source — read it, parse frontmatter only.
202
- const designMdRel = input.designMdPath ?? "DESIGN.md";
203
- const designMdPath = isAbsolute(designMdRel) ? designMdRel : join(projectDir, designMdRel);
204
- if (!existsSync(designMdPath)) die("DESIGN_MD_MISSING", `no DESIGN.md at ${designMdPath} — the Designer must author it first`);
205
- const fm = parseFrontmatter(readFileSync(designMdPath, "utf8"));
206
- if (!fm) die("DESIGN_MD_BAD", `could not parse YAML frontmatter from ${designMdPath}`);
207
- const designTokens = designMdToTokens(fm);
208
- const shell = input.shell ?? {};
209
- const brand = input.brand ?? {};
210
- const navLinks = Array.isArray(input.navLinks) ? input.navLinks : [];
211
- const loadedPacks = Array.isArray(input.loadedPacks) ? input.loadedPacks : [];
212
- const packsWithComponents = Array.isArray(input.packsWithComponents) ? input.packsWithComponents : [];
213
- const disabledPacks = Array.isArray(input.disabledPacks) ? input.disabledPacks : [];
214
-
215
- // Full-page LLM generation (this branch): the LLM authors the entire visible
216
- // page — header (Navigation.astro), footer (Footer.astro), and home page
217
- // (index.astro). compose writes each verbatim; there are no templates for them.
218
- const resolveIn = (p) => { const s = typeof p === "string" ? p.trim() : ""; return s ? (isAbsolute(s) ? s : join(projectDir, s)) : null; };
219
- const navPath = resolveIn(input.navPath);
220
- const footerPath = resolveIn(input.footerPath);
221
- const homePath = resolveIn(input.homePath);
222
-
223
- const brandName = brand.name ?? "Brand";
224
-
225
- // ── small color helper (derivation fail-safe only) ────────────────────────────
226
- function parseHex(hex) {
227
- if (typeof hex !== "string") return null;
228
- let h = hex.trim().replace(/^#/, "");
229
- if (h.length === 3) h = h.split("").map((c) => c + c).join("");
230
- if (!/^[0-9a-fA-F]{6}$/.test(h)) return null;
231
- return [0, 2, 4].map((i) => parseInt(h.slice(i, i + 2), 16));
232
- }
233
- function toHex([r, g, b]) {
234
- return "#" + [r, g, b].map((v) => Math.max(0, Math.min(255, Math.round(v))).toString(16).padStart(2, "0")).join("");
235
- }
236
- // mix `a` toward `b` by weight w (0..1). Falls back to `a` if either unparseable.
237
- function mix(a, b, w) {
238
- const ca = parseHex(a), cb = parseHex(b);
239
- if (!ca || !cb) return a ?? b ?? "#000000";
240
- return toHex(ca.map((v, i) => v + (cb[i] - v) * w));
241
- }
242
-
243
- // ── build the @theme palette + guarantee the required-token contract ──────────
244
- const SYSTEM_FONTS = new Set([
245
- "system-ui", "-apple-system", "blinkmacsystemfont", "segoe ui", "sans-serif",
246
- "serif", "monospace", "ui-sans-serif", "ui-serif", "ui-monospace", "inherit",
247
- ]);
248
-
249
- const colors = { ...(designTokens.colors ?? {}) };
250
- const fonts = { ...(designTokens.fonts ?? {}) };
251
- const radii = { ...(designTokens.radii ?? {}) };
252
- const containers = { ...(designTokens.containers ?? {}) };
253
-
254
- const derived = [];
255
- function ensure(group, key, value, prefix) {
256
- if (group[key] === undefined || group[key] === null || group[key] === "") {
257
- group[key] = value;
258
- derived.push(`${prefix}${key}`);
259
- }
260
- }
261
-
262
- // Colors — required core first (sane neutral defaults if the Designer omitted a
263
- // core role), then warm/soft derivations described in COMPOSE § Token contract.
264
- ensure(colors, "paper", "#ffffff", "--color-");
265
- ensure(colors, "ink", "#1a1a1a", "--color-");
266
- ensure(colors, "accent", colors.ink, "--color-");
267
- ensure(colors, "mute", mix(colors.ink, colors.paper, 0.45), "--color-");
268
- ensure(colors, "rule", mix(colors.ink, colors.paper, 0.85), "--color-");
269
- ensure(colors, "paper-warm", mix(colors.paper, colors.accent, 0.06), "--color-"); // paper warmed
270
- ensure(colors, "ink-soft", mix(colors.ink, colors.paper, 0.25), "--color-"); // ink lightened
271
- // NOTE: cream is derived but not in REQUIRED; gift-cards CSS expects
272
- // --color-cream-deep (undeclared) and relies on the var() fallback — reconcile
273
- // with STYLING.md token contract.
274
- ensure(colors, "cream", mix(colors.paper, "#fbf3e0", 0.5), "--color-");
275
- ensure(colors, "error", "#c0392b", "--color-");
276
-
277
- // Fonts — display + body required.
278
- ensure(fonts, "display", "Georgia, serif", "--font-");
279
- ensure(fonts, "body", "system-ui, sans-serif", "--font-");
280
-
281
- // Spacing is NOT a named scale — Tailwind v4's built-in numeric spacing
282
- // (`--spacing` base → gap-4, py-24, …) is used directly. Emitting named
283
- // --spacing-<t-shirt> tokens collided with the width utilities (max-w-3xl etc.
284
- // drew from --spacing-3xl), so the named scale was removed (CODEAI-696).
285
-
286
- // Radii — sm + md required.
287
- ensure(radii, "sm", "0.25rem", "--radius-");
288
- ensure(radii, "md", "0.5rem", "--radius-");
289
-
290
- // Containers — content widths, a separate axis from spacing.
291
- const CONTAINER_DEFAULTS = { prose: "42rem", md: "48rem", "3xl": "60rem", "6xl": "72rem" };
292
- for (const [k, v] of Object.entries(CONTAINER_DEFAULTS)) ensure(containers, k, v, "--container-");
293
-
294
- // Assemble the @theme block, grouped + ordered for readability.
295
- const themeLines = [];
296
- const emitGroup = (prefix, obj) => {
297
- for (const [k, v] of Object.entries(obj)) themeLines.push(` ${prefix}${k}: ${v};`);
298
- };
299
- emitGroup("--color-", colors);
300
- themeLines.push("");
301
- emitGroup("--font-", fonts);
302
- themeLines.push("");
303
- emitGroup("--radius-", radii);
304
- themeLines.push("");
305
- emitGroup("--container-", containers);
306
- const themeBlock = themeLines.join("\n");
307
-
308
- // ── self-checks (assertions) ──────────────────────────────────────────────────
309
- const errors = [];
310
-
311
- // Required-token coverage (after derivation, every required role must resolve).
312
- const REQUIRED = [
313
- ...["paper", "paper-warm", "ink", "mute", "rule", "accent"].map((k) => `--color-${k}`),
314
- "--font-display", "--font-body",
315
- "--radius-sm", "--radius-md",
316
- ...["prose", "md", "3xl", "6xl"].map((k) => `--container-${k}`),
317
- ];
318
- const present = new Set([
319
- ...Object.keys(colors).map((k) => `--color-${k}`),
320
- ...Object.keys(fonts).map((k) => `--font-${k}`),
321
- ...Object.keys(radii).map((k) => `--radius-${k}`),
322
- ...Object.keys(containers).map((k) => `--container-${k}`),
323
- ]);
324
- for (const tok of REQUIRED) {
325
- if (!present.has(tok)) errors.push({ code: "MISSING_REQUIRED_TOKEN", token: tok });
326
- }
327
-
328
- // ── skeleton load + substitution helpers ──────────────────────────────────────
329
- function readTemplate(name) {
330
- const p = join(TEMPLATES, name);
331
- if (!existsSync(p)) die("TEMPLATE_MISSING", `skeleton not found at ${p}`);
332
- return readFileSync(p, "utf8");
333
- }
334
- function writeProject(rel, content) {
335
- const dest = join(projectDir, rel);
336
- mkdirSync(dirname(dest), { recursive: true });
337
- writeFileSync(dest, content);
338
- }
339
- function escAttr(s) {
340
- return String(s ?? "").replace(/"/g, "&quot;");
341
- }
342
- // Strip the leading "// ── Composer skeleton: … ──" authoring-comment block from
343
- // an .astro skeleton's frontmatter. Those lines document the {{…}} slots (and
344
- // thus contain placeholder text that must NOT be substituted) and are not part
345
- // of the shipped site — the real Composer output drops them too. Removes the
346
- // contiguous run of `//` comment lines immediately after the opening `---`.
347
- function stripAstroHeader(src) {
348
- return src.replace(/^(---\n)((?:[ \t]*\/\/.*\n)+)/, "$1");
349
- }
350
-
351
- // ── Google Fonts href ─────────────────────────────────────────────────────────
352
- // Prefer the Designer-supplied href; otherwise build one deterministically with
353
- // a standard weight set. Returns ""
354
- // when both families are system fonts (caller drops the <link>).
355
- function buildGoogleHref() {
356
- if (typeof designTokens.googleFontsHref === "string" && designTokens.googleFontsHref.trim()) {
357
- return designTokens.googleFontsHref.trim();
358
- }
359
- const families = [];
360
- for (const fam of [fonts.display, fonts.body]) {
361
- if (typeof fam !== "string") continue;
362
- const first = fam.split(",")[0].trim();
363
- if (!first || SYSTEM_FONTS.has(first.toLowerCase())) continue;
364
- if (!families.includes(first)) families.push(first);
365
- }
366
- if (families.length === 0) return "";
367
- const q = families
368
- .map((f) => `family=${f.replace(/\s+/g, "+")}:wght@400;500;600;700`)
369
- .join("&");
370
- return `https://fonts.googleapis.com/css2?${q}&display=swap`;
371
- }
372
-
373
- // ── 1. global.css ──────────────────────────────────────────────────────────────
374
- {
375
- const skeleton = readTemplate("global.css");
376
- // Replace the first `@theme { … }` block (its comment has no braces, so the
377
- // first `}` is its close). Everything else is literal fixed bulk.
378
- const out = skeleton.replace(/@theme\s*\{[\s\S]*?\n\}/, `@theme {\n${themeBlock}\n}`);
379
- if (out === skeleton) die("ANCHOR_THEME", "could not locate the @theme block in global.css skeleton");
380
- writeProject("src/styles/global.css", out);
381
- }
382
-
383
- // ── 2. astro.config.mjs (anchored MERGE, fail loud on missing anchor) ─────────
384
- {
385
- const dest = join(projectDir, "astro.config.mjs");
386
- // The scaffold may briefly be in flight; the new wiring invokes compose only
387
- // after Setup Step 1 awaited the scaffold, so a short retry is belt-and-braces.
388
- let src = null;
389
- for (let attempt = 0; attempt < 10; attempt++) {
390
- if (existsSync(dest)) { src = readFileSync(dest, "utf8"); break; }
391
- try { execSync("sleep 1"); } catch { /* ignore */ }
392
- }
393
- if (src === null) die("SCAFFOLD_NOT_COMPLETE", `astro.config.mjs not found at ${dest} after retries`);
394
-
395
- const hasImport = /import\s+tailwindcss\s+from\s+["']@tailwindcss\/vite["']/.test(src);
396
- const hasCall = /tailwindcss\s*\(\s*\)/.test(src);
397
-
398
- // (1a) import — insert after the last top-level import statement.
399
- if (!hasImport) {
400
- const importRe = /^import\b.*$/gm;
401
- let last = null, m;
402
- while ((m = importRe.exec(src)) !== null) last = m;
403
- if (!last) die("ANCHOR_IMPORT", "no import statement found in astro.config.mjs to anchor the @tailwindcss/vite import");
404
- const insertAt = last.index + last[0].length;
405
- src = src.slice(0, insertAt) + `\nimport tailwindcss from "@tailwindcss/vite";` + src.slice(insertAt);
406
- }
407
-
408
- // (1b) merge tailwindcss() into vite.plugins (idempotent on hasCall).
409
- if (!hasCall) {
410
- if (/plugins\s*:\s*\[/.test(src)) {
411
- src = src.replace(/plugins\s*:\s*\[/, (mm) => `${mm}tailwindcss(), `);
412
- } else if (/\bvite\s*:\s*\{/.test(src)) {
413
- src = src.replace(/(\bvite\s*:\s*\{)/, `$1\n plugins: [tailwindcss()],`);
414
- } else if (/defineConfig\s*\(\s*\{/.test(src)) {
415
- src = src.replace(/(defineConfig\s*\(\s*\{)/, `$1\n vite: { plugins: [tailwindcss()] },`);
416
- } else {
417
- die("ANCHOR_VITE", "could not find vite.plugins, a vite block, or defineConfig({ to register @tailwindcss/vite");
418
- }
419
- }
420
-
421
- // (2) process.env → globalThis guard (TS-safe under strict tsc --noEmit).
422
- const GUARD = `const isBuild =\n (/** @type {any} */ (globalThis)).process?.env?.NODE_ENV === "production";`;
423
- const alreadyGuarded = /\(globalThis\)\)\.process\?\.env\?\.NODE_ENV/.test(src);
424
- const bareRe = /const\s+isBuild\s*=\s*process\.env\.NODE_ENV\s*===?\s*["']production["']\s*;/;
425
- if (!alreadyGuarded) {
426
- if (bareRe.test(src)) {
427
- src = src.replace(bareRe, GUARD);
428
- } else if (/process\.env/.test(src)) {
429
- die("ANCHOR_PROCESS_ENV", "found a bare process.env reference but not the expected `const isBuild = process.env.NODE_ENV …` line to guard");
430
- }
431
- // else: no process.env at all — nothing to guard, leave as-is.
432
- }
433
-
434
- writeProject("astro.config.mjs", src);
435
- }
436
-
437
- // ── 3. Layout.astro ────────────────────────────────────────────────────────────
438
- const componentCssImports = packsWithComponents.map(
439
- (pack) => `import '../styles/components-${pack}.css';`,
440
- );
441
- {
442
- let out = stripAstroHeader(readTemplate("Layout.astro"));
443
- // {{components-css-imports}} — one import per pack, or drop the whole line.
444
- if (componentCssImports.length) {
445
- out = out.replace(/^\{\{components-css-imports\}\}\s*$/m, componentCssImports.join("\n"));
446
- } else {
447
- out = out.replace(/^\{\{components-css-imports\}\}\s*\n/m, "");
448
- }
449
- // {{fonts.googleHref}} — drop the <link> when no web fonts.
450
- const href = buildGoogleHref();
451
- if (href) {
452
- out = out.replace(/\{\{fonts\.googleHref\}\}/g, escAttr(href));
453
- } else {
454
- out = out.replace(/^.*\{\{fonts\.googleHref\}\}.*\n/m, "");
455
- }
456
- out = out.replaceAll("{{brand.name}}", brandName);
457
- writeProject("src/layouts/Layout.astro", out);
458
- }
459
-
460
- // ── nav-link rendering ──────────────────────────────────────────────────────────
461
- const navItems = navLinks
462
- .filter((l) => l && l.href != null && l.label != null)
463
- .map((l) => ({ href: String(l.href), label: String(l.label) }));
464
-
465
- // ── 4. Navigation.astro (LLM-generated, verbatim) ─────────────────────────────
466
- {
467
- if (!navPath || !existsSync(navPath)) die("NO_NAV", `LLM-generated header required via navPath (none at ${navPath ?? "<unset>"})`);
468
- writeProject("src/components/Navigation.astro", readFileSync(navPath, "utf8"));
469
- }
470
-
471
- // ── 5. Footer.astro (LLM-generated, verbatim) ─────────────────────────────────
472
- {
473
- if (!footerPath || !existsSync(footerPath)) die("NO_FOOTER", `LLM-generated footer required via footerPath (none at ${footerPath ?? "<unset>"})`);
474
- writeProject("src/components/Footer.astro", readFileSync(footerPath, "utf8"));
475
- }
476
-
477
- // ── 6. index.astro ────────────────────────────────────────────────────────────────
478
- // Home markers: one `<!-- home:<pack> -->` per contributing pack. Today
479
- // stores + bookings + gift-cards contribute a home section. Disabled packs
480
- // (gift-cards) still get their marker (markers are their only acceptable touchpoint).
481
- const HOME_CONTRIBUTING = ["stores", "bookings", "gift-cards"]; // canonical order
482
- const homePool = new Set([...loadedPacks, ...disabledPacks]);
483
- const homeMarkerPacks = HOME_CONTRIBUTING.filter((p) => homePool.has(p));
484
- {
485
- if (!homePath || !existsSync(homePath)) die("NO_HOME", `LLM-generated home page required via homePath (none at ${homePath ?? "<unset>"})`);
486
- writeProject("src/pages/index.astro", readFileSync(homePath, "utf8"));
487
- }
488
-
489
- // ── manifest (the orchestrator parses this off stdout) ────────────────────────
490
- const filesWritten = [
491
- "src/styles/global.css",
492
- "astro.config.mjs",
493
- "src/layouts/Layout.astro",
494
- "src/components/Navigation.astro",
495
- "src/components/Footer.astro",
496
- "src/pages/index.astro",
497
- ];
498
- const manifest = {
499
- status: errors.length ? "partial" : "complete",
500
- phase: "compose",
501
- data: {
502
- filesWritten,
503
- nav: "llm-generated",
504
- footer: "llm-generated",
505
- home: "llm-generated",
506
- componentCssImports: packsWithComponents,
507
- homeMarkers: homeMarkerPacks.map((p) => `home:${p}`),
508
- tokensApplied: {
509
- colors: Object.keys(colors).length,
510
- containers: Object.keys(containers).length,
511
- radii: Object.keys(radii).length,
512
- fonts: Object.keys(fonts).length,
513
- },
514
- ...(derived.length ? { derivedTokens: derived } : {}),
515
- },
516
- files: filesWritten,
517
- ...(errors.length ? { errors } : {}),
518
- };
519
- console.log(JSON.stringify(manifest, null, 2));
520
- process.exit(0);