@aglyn/plugins-ai 1.0.0-beta.284 → 1.0.0-beta.287

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 (210) hide show
  1. package/package.json +17 -17
  2. package/src/lib/assets/site-styles/nonprofit.webp +0 -0
  3. package/src/lib/assets/site-styles/professional.webp +0 -0
  4. package/src/lib/assets/site-styles/store.webp +0 -0
  5. package/src/lib/assets/site-styles/trades.webp +0 -0
  6. package/src/lib/components/ai-theme-proposal-card.component.js +12 -3
  7. package/src/lib/components/ai-theme-proposal-card.component.js.map +1 -1
  8. package/src/lib/declarations.js +5 -2
  9. package/src/lib/declarations.js.map +1 -1
  10. package/src/lib/declarations.server.js +12 -0
  11. package/src/lib/declarations.server.js.map +1 -1
  12. package/src/lib/jobs/ai-build-capabilities.d.ts +3 -1
  13. package/src/lib/jobs/ai-build-capabilities.js +27 -2
  14. package/src/lib/jobs/ai-build-capabilities.js.map +1 -1
  15. package/src/lib/jobs/ai-image-reads.d.ts +59 -0
  16. package/src/lib/jobs/ai-image-reads.js +138 -0
  17. package/src/lib/jobs/ai-image-reads.js.map +1 -0
  18. package/src/lib/jobs/ai-job-build-step.d.ts +29 -0
  19. package/src/lib/jobs/ai-job-build-step.js +83 -12
  20. package/src/lib/jobs/ai-job-build-step.js.map +1 -1
  21. package/src/lib/jobs/ai-job-duplicate-step.d.ts +2 -1
  22. package/src/lib/jobs/ai-job-duplicate-step.js +6 -6
  23. package/src/lib/jobs/ai-job-duplicate-step.js.map +1 -1
  24. package/src/lib/jobs/ai-job-import-step.d.ts +4 -2
  25. package/src/lib/jobs/ai-job-import-step.js +15 -11
  26. package/src/lib/jobs/ai-job-import-step.js.map +1 -1
  27. package/src/lib/jobs/ai-job-insight-step.d.ts +10 -0
  28. package/src/lib/jobs/ai-job-insight-step.js +23 -5
  29. package/src/lib/jobs/ai-job-insight-step.js.map +1 -1
  30. package/src/lib/jobs/ai-job-layout-language.js +2 -1
  31. package/src/lib/jobs/ai-job-layout-language.js.map +1 -1
  32. package/src/lib/jobs/ai-job-media-step.d.ts +2 -1
  33. package/src/lib/jobs/ai-job-media-step.js +6 -8
  34. package/src/lib/jobs/ai-job-media-step.js.map +1 -1
  35. package/src/lib/jobs/ai-job-navigation-step.d.ts +2 -1
  36. package/src/lib/jobs/ai-job-navigation-step.js +7 -9
  37. package/src/lib/jobs/ai-job-navigation-step.js.map +1 -1
  38. package/src/lib/jobs/ai-job-page-language.js +7 -1
  39. package/src/lib/jobs/ai-job-page-language.js.map +1 -1
  40. package/src/lib/jobs/ai-job-page-sections.js +16 -3
  41. package/src/lib/jobs/ai-job-page-sections.js.map +1 -1
  42. package/src/lib/jobs/ai-job-page-step.js +9 -1
  43. package/src/lib/jobs/ai-job-page-step.js.map +1 -1
  44. package/src/lib/jobs/ai-job-plan-step.d.ts +30 -8
  45. package/src/lib/jobs/ai-job-plan-step.js +78 -13
  46. package/src/lib/jobs/ai-job-plan-step.js.map +1 -1
  47. package/src/lib/jobs/ai-job-privacy-step.d.ts +4 -2
  48. package/src/lib/jobs/ai-job-privacy-step.js +14 -15
  49. package/src/lib/jobs/ai-job-privacy-step.js.map +1 -1
  50. package/src/lib/jobs/ai-job-products-step.js +5 -3
  51. package/src/lib/jobs/ai-job-products-step.js.map +1 -1
  52. package/src/lib/jobs/ai-job-settings-step.d.ts +2 -1
  53. package/src/lib/jobs/ai-job-settings-step.js +7 -8
  54. package/src/lib/jobs/ai-job-settings-step.js.map +1 -1
  55. package/src/lib/jobs/ai-job-site-content.d.ts +34 -1
  56. package/src/lib/jobs/ai-job-site-content.js +67 -8
  57. package/src/lib/jobs/ai-job-site-content.js.map +1 -1
  58. package/src/lib/jobs/ai-job-site-datasets.d.ts +53 -3
  59. package/src/lib/jobs/ai-job-site-datasets.js +298 -30
  60. package/src/lib/jobs/ai-job-site-datasets.js.map +1 -1
  61. package/src/lib/jobs/ai-job-site-step.js +6 -3
  62. package/src/lib/jobs/ai-job-site-step.js.map +1 -1
  63. package/src/lib/jobs/ai-job-site-store-pages.js +3 -3
  64. package/src/lib/jobs/ai-job-site-store-pages.js.map +1 -1
  65. package/src/lib/jobs/ai-job-tracking-step.d.ts +2 -1
  66. package/src/lib/jobs/ai-job-tracking-step.js +7 -8
  67. package/src/lib/jobs/ai-job-tracking-step.js.map +1 -1
  68. package/src/lib/jobs/ai-jobs-beat.d.ts +11 -7
  69. package/src/lib/jobs/ai-jobs-beat.js +18 -8
  70. package/src/lib/jobs/ai-jobs-beat.js.map +1 -1
  71. package/src/lib/jobs/ai-jobs-notify.d.ts +66 -1
  72. package/src/lib/jobs/ai-jobs-notify.js +136 -3
  73. package/src/lib/jobs/ai-jobs-notify.js.map +1 -1
  74. package/src/lib/jobs/ai-layout-stock-photos.d.ts +59 -4
  75. package/src/lib/jobs/ai-layout-stock-photos.js +897 -81
  76. package/src/lib/jobs/ai-layout-stock-photos.js.map +1 -1
  77. package/src/lib/jobs/ai-product-image.d.ts +14 -0
  78. package/src/lib/jobs/ai-product-image.js +73 -21
  79. package/src/lib/jobs/ai-product-image.js.map +1 -1
  80. package/src/lib/jobs/ai-theme-brand-inputs.d.ts +9 -1
  81. package/src/lib/jobs/ai-theme-brand-inputs.js +28 -2
  82. package/src/lib/jobs/ai-theme-brand-inputs.js.map +1 -1
  83. package/src/lib/jobs/fixtures/ai-site-agl4065-datasets.d.ts +175 -0
  84. package/src/lib/jobs/fixtures/ai-site-agl4065-datasets.js +601 -0
  85. package/src/lib/jobs/fixtures/ai-site-agl4065-datasets.js.map +1 -0
  86. package/src/lib/jobs/fixtures/ai-site-agl4065-pages.d.ts +46 -0
  87. package/src/lib/jobs/fixtures/ai-site-agl4065-pages.js +2862 -0
  88. package/src/lib/jobs/fixtures/ai-site-agl4065-pages.js.map +1 -0
  89. package/src/lib/jobs/fixtures/ai-site-agl4065-plans.d.ts +74 -0
  90. package/src/lib/jobs/fixtures/ai-site-agl4065-plans.js +888 -0
  91. package/src/lib/jobs/fixtures/ai-site-agl4065-plans.js.map +1 -0
  92. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-judge.d.ts +29 -0
  93. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-judge.js +81 -0
  94. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-judge.js.map +1 -0
  95. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-recordings.d.ts +87 -0
  96. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-recordings.js +225 -0
  97. package/src/lib/jobs/fixtures/ai-stock-photo-agl4065-recordings.js.map +1 -0
  98. package/src/lib/layout-language/ai-layout-compiler.d.ts +11 -0
  99. package/src/lib/layout-language/ai-layout-compiler.js +194 -18
  100. package/src/lib/layout-language/ai-layout-compiler.js.map +1 -1
  101. package/src/lib/layout-language/ai-layout-copy.d.ts +37 -0
  102. package/src/lib/layout-language/ai-layout-copy.js +383 -3
  103. package/src/lib/layout-language/ai-layout-copy.js.map +1 -1
  104. package/src/lib/layout-language/ai-layout-design.d.ts +19 -0
  105. package/src/lib/layout-language/ai-layout-design.js +31 -11
  106. package/src/lib/layout-language/ai-layout-design.js.map +1 -1
  107. package/src/lib/layout-language/ai-layout-listings.d.ts +7 -1
  108. package/src/lib/layout-language/ai-layout-listings.js +9 -1
  109. package/src/lib/layout-language/ai-layout-listings.js.map +1 -1
  110. package/src/lib/layout-language/ai-layout-pictures.d.ts +30 -0
  111. package/src/lib/layout-language/ai-layout-pictures.js +131 -3
  112. package/src/lib/layout-language/ai-layout-pictures.js.map +1 -1
  113. package/src/lib/layout-language/ai-layout-storefront.d.ts +18 -4
  114. package/src/lib/layout-language/ai-layout-storefront.js +100 -20
  115. package/src/lib/layout-language/ai-layout-storefront.js.map +1 -1
  116. package/src/lib/model/ai-build-job.d.ts +7 -0
  117. package/src/lib/model/ai-build-job.js +36 -7
  118. package/src/lib/model/ai-build-job.js.map +1 -1
  119. package/src/lib/model/ai-build-plan.d.ts +28 -4
  120. package/src/lib/model/ai-build-plan.js +49 -9
  121. package/src/lib/model/ai-build-plan.js.map +1 -1
  122. package/src/lib/model/ai-build-progress.js +3 -1
  123. package/src/lib/model/ai-build-progress.js.map +1 -1
  124. package/src/lib/model/ai-job-notice.d.ts +8 -0
  125. package/src/lib/model/ai-job-notice.js +33 -0
  126. package/src/lib/model/ai-job-notice.js.map +1 -1
  127. package/src/lib/model/ai-job-plan-lines.d.ts +2 -1
  128. package/src/lib/model/ai-job-plan-lines.js +6 -1
  129. package/src/lib/model/ai-job-plan-lines.js.map +1 -1
  130. package/src/lib/model/ai-jobs.types.d.ts +8 -0
  131. package/src/lib/model/ai-jobs.types.js.map +1 -1
  132. package/src/lib/model/ai-permissions.d.ts +13 -0
  133. package/src/lib/model/ai-permissions.js +29 -1
  134. package/src/lib/model/ai-permissions.js.map +1 -1
  135. package/src/lib/model/ai-products.d.ts +18 -0
  136. package/src/lib/model/ai-products.js +32 -0
  137. package/src/lib/model/ai-products.js.map +1 -1
  138. package/src/lib/model/ai-site-inspiration.d.ts +3 -2
  139. package/src/lib/model/ai-site-inspiration.js +3 -2
  140. package/src/lib/model/ai-site-inspiration.js.map +1 -1
  141. package/src/lib/plugin.js +4 -13
  142. package/src/lib/plugin.js.map +1 -1
  143. package/src/lib/providers/anthropic.js +9 -2
  144. package/src/lib/providers/anthropic.js.map +1 -1
  145. package/src/lib/providers/catalog.js +14 -5
  146. package/src/lib/providers/catalog.js.map +1 -1
  147. package/src/lib/providers/contract.d.ts +24 -1
  148. package/src/lib/providers/contract.js.map +1 -1
  149. package/src/lib/providers/routing.js +5 -2
  150. package/src/lib/providers/routing.js.map +1 -1
  151. package/src/lib/runtime/ai-dataset-generation.d.ts +99 -1
  152. package/src/lib/runtime/ai-dataset-generation.js +251 -3
  153. package/src/lib/runtime/ai-dataset-generation.js.map +1 -1
  154. package/src/lib/runtime/ai-dev-replay.d.ts +1 -0
  155. package/src/lib/runtime/ai-dev-replay.js +4 -2
  156. package/src/lib/runtime/ai-dev-replay.js.map +1 -1
  157. package/src/lib/runtime/ai-doctrine-validators.d.ts +47 -3
  158. package/src/lib/runtime/ai-doctrine-validators.js +343 -27
  159. package/src/lib/runtime/ai-doctrine-validators.js.map +1 -1
  160. package/src/lib/runtime/ai-doctrine.js +8 -2
  161. package/src/lib/runtime/ai-doctrine.js.map +1 -1
  162. package/src/lib/runtime/ai-icon-library.d.ts +27 -1
  163. package/src/lib/runtime/ai-icon-library.js +30 -3
  164. package/src/lib/runtime/ai-icon-library.js.map +1 -1
  165. package/src/lib/runtime/ai-products-generation.d.ts +11 -1
  166. package/src/lib/runtime/ai-products-generation.js +51 -4
  167. package/src/lib/runtime/ai-products-generation.js.map +1 -1
  168. package/src/lib/runtime/assist-answer-cache.d.ts +2 -0
  169. package/src/lib/runtime/assist-answer-cache.js +5 -2
  170. package/src/lib/runtime/assist-answer-cache.js.map +1 -1
  171. package/src/lib/server/ai-allotments.js +7 -2
  172. package/src/lib/server/ai-allotments.js.map +1 -1
  173. package/src/lib/server/ai-experiment-versions.js +5 -5
  174. package/src/lib/server/ai-experiment-versions.js.map +1 -1
  175. package/src/lib/server/ai-host-permissions-roster.d.ts +25 -0
  176. package/src/lib/server/ai-host-permissions-roster.js +33 -0
  177. package/src/lib/server/ai-host-permissions-roster.js.map +1 -0
  178. package/src/lib/server/ai-host-permissions.js +8 -6
  179. package/src/lib/server/ai-host-permissions.js.map +1 -1
  180. package/src/lib/server/ai-image-reads-route.d.ts +17 -0
  181. package/src/lib/server/ai-image-reads-route.js +106 -0
  182. package/src/lib/server/ai-image-reads-route.js.map +1 -0
  183. package/src/lib/server/ai-seo-apply.js +5 -5
  184. package/src/lib/server/ai-seo-apply.js.map +1 -1
  185. package/src/lib/server/ai-site-import-route.js +7 -4
  186. package/src/lib/server/ai-site-import-route.js.map +1 -1
  187. package/src/lib/server/assist-build.js +1 -0
  188. package/src/lib/server/assist-build.js.map +1 -1
  189. package/src/lib/server/assist-chat.d.ts +11 -7
  190. package/src/lib/server/assist-chat.js +185 -48
  191. package/src/lib/server/assist-chat.js.map +1 -1
  192. package/src/lib/server/assist-docs-query.d.ts +51 -0
  193. package/src/lib/server/assist-docs-query.js +57 -0
  194. package/src/lib/server/assist-docs-query.js.map +1 -0
  195. package/src/lib/server/assist-jobs-context.d.ts +102 -0
  196. package/src/lib/server/assist-jobs-context.js +227 -0
  197. package/src/lib/server/assist-jobs-context.js.map +1 -0
  198. package/src/lib/server/assist-view-context.d.ts +8 -4
  199. package/src/lib/server/assist-view-context.js +12 -7
  200. package/src/lib/server/assist-view-context.js.map +1 -1
  201. package/src/lib/server.js +12 -0
  202. package/src/lib/server.js.map +1 -1
  203. package/src/lib/tools/ai-dataset-tool.d.ts +11 -1
  204. package/src/lib/tools/ai-dataset-tool.js +24 -7
  205. package/src/lib/tools/ai-dataset-tool.js.map +1 -1
  206. package/src/lib/tools/ai-duplicate-resource-tool.js +5 -6
  207. package/src/lib/tools/ai-duplicate-resource-tool.js.map +1 -1
  208. package/src/lib/components/ai-collaborator-permissions-column.component.d.ts +0 -32
  209. package/src/lib/components/ai-collaborator-permissions-column.component.js +0 -132
  210. package/src/lib/components/ai-collaborator-permissions-column.component.js.map +0 -1
@@ -27,13 +27,13 @@ import { AI_TEMPLATE_SUBJECT_DEFINITIONS, aiTemplateShownTokens } from "../model
27
27
  import { AI_JOB_CREATE_KINDS, AI_JOB_CREATE_NOUNS } from "../model/ai-job-creations.js";
28
28
  import { AI_PAGE_CREATE_KINDS, aiPagePlanShapeRefusal } from "../model/ai-page-job.js";
29
29
  import { AI_PLAN_COMPILED_REPEATS_SENTENCE, AI_PLAN_NO_FORM_SENTENCE, aiPlanCanPlaceForm, aiPlanCapabilitiesForJob, aiPlanCapabilityLines } from "../model/ai-plan-capabilities.js";
30
- import { aiSettleSiteForeignDatasets, aiSiteInventoryWithRecordCounts, aiSitePlanDatasetCapability } from "./ai-job-site-datasets.js";
31
- import { AI_FREE_SITE_WORST_CASE_CREDITS, AI_SITE_CREATE_KINDS, AI_SITE_FREE_PAGES, AI_SITE_FREE_POSTS, AI_SITE_PLAN_MAX_TOKENS, AI_SITE_HOME_BANDS, aiFreeSiteSectionsWithin, aiSiteFullPlanSentence, aiSiteHomeMinSections, aiSiteNameSentence, aiSitePlanIsHome, aiSitePlanShapeRefusal, aiSiteBlogStandInViolations, aiSiteThinHomeViolations, AI_SITE_GALLERY_SENTENCE, aiSiteEmptyGalleryViolations, AI_SITE_DATASETS_MAX, AI_SITE_GALLERY_MIN_ITEMS } from "../model/ai-site-job.js";
30
+ import { aiSettlePlanSplitListings, aiSettleSiteForeignDatasets, aiSiteInventoryWithRecordCounts, aiSitePlanDatasetCapability } from "./ai-job-site-datasets.js";
31
+ import { AI_FREE_SITE_WORST_CASE_CREDITS, AI_SITE_CREATE_KINDS, AI_SITE_FREE_PAGES, AI_SITE_FREE_POSTS, AI_SITE_PLAN_MAX_TOKENS, AI_SITE_HOME_BANDS, aiFreeSiteSectionsWithin, aiSiteFullPlanSentence, aiSiteHomeMinSections, aiSiteNameSentence, aiSitePlanIsHome, aiSitePlanShapeRefusal, aiSiteBlogStandInViolations, aiSiteThinHomeViolations, AI_SITE_GALLERY_SENTENCE, aiSiteEmptyGalleryViolations, AI_SITE_DATASETS_MAX, AI_SITE_GALLERY_MIN_ITEMS, AI_SITE_MAX_SECTIONS } from "../model/ai-site-job.js";
32
32
  import { aiSiteContentPart } from "./ai-job-site-content.js";
33
33
  import { aiPlanHasCustomerWords, aiSettlePlanPlaceholderNames, aiSettlePlanSaidSections } from "../model/ai-plan-said-sections.js";
34
34
  import { aiLayoutIsShopPage, aiLayoutShopGridSection } from "../layout-language/ai-layout-listings.js";
35
35
  import { aiLayoutSpeaksOtherThanEnglish } from "../layout-language/ai-layout-labels.js";
36
- import { aiStorefrontPlanScreens } from "../layout-language/ai-layout-storefront.js";
36
+ import { aiStorefrontPlanScreens, aiStorefrontSays } from "../layout-language/ai-layout-storefront.js";
37
37
  import { AI_GENERATION_MAX_ATTEMPTS } from "../runtime/ai-generation-bounds.js";
38
38
  import { aiPlanFailureCopy, aiPlanRetryRefusal } from "../model/ai-job-failure-copy.js";
39
39
  import { FREE_AI_TASTE_CREDITS_PER_MONTH } from "../plan-entitlements.js";
@@ -145,16 +145,26 @@ import { AI_JOBS_COLLECTION, registerAiJobPlanStep } from "./ai-jobs.js";
145
145
  lines.push(...aiPlanBuildLines(job, capabilities, ops, now));
146
146
  return lines.join('\n');
147
147
  }
148
+ /**
149
+ * What a build's plan does with a request it cannot make (AGL-4087). Told
150
+ * only how many pages it may hold, a Free build asked for a home and a page
151
+ * that writes a review draft from a customer's choices planned the home
152
+ * alone, kept two sections sending visitors to the other page, and said
153
+ * nothing; the member confirmed a plan that had quietly dropped half of what
154
+ * they asked for.
155
+ */ export const AI_PLAN_BUILD_LEFT_OUT_SENTENCE = 'Plan every page the request asks for. When it asks for something this build cannot make work, such as a page whose purpose is a feature the site has no way to do, or more pages than it holds, leave that out, name it in leftOut with why, and plan no section that sends visitors to it. leftOut is empty when the plan builds everything the request asks for.';
148
156
  /**
149
157
  * What a BUILD job's plan is told (AGL-3616): that one request becomes pages,
150
- * creations and items, how many pages it may hold, and the item operations
151
- * this site has with their arguments. On the job's own turn, never a cached
152
- * system block, because the operations are per site.
158
+ * creations and items, how many pages it may hold, what to do with what it
159
+ * cannot make (AGL-4087), and the item operations this site has with their
160
+ * arguments. On the job's own turn, never a cached system block, because the
161
+ * operations are per site.
153
162
  */ export function aiPlanBuildLines(job, capabilities, ops, now = null) {
154
163
  if (job.kind !== 'build') return [];
155
164
  const pages = aiBuildPageLimit((capabilities == null ? void 0 : capabilities.freeTaste) === true);
156
165
  return [
157
166
  `This is a build from one request: plan each page it asks for in screens (at most ${pages}), each new layout, form, component or email design in create, and anything else in items. Plan only what the request asks for; reuse what the site has.`,
167
+ AI_PLAN_BUILD_LEFT_OUT_SENTENCE,
158
168
  'A page section that shows a form or an item places it: put its new:<name> in that section\'s uses. An item built after another lists it in dependsOn.',
159
169
  // The layout language draws a section's repeated items (AGL-3660), so the
160
170
  // doctrine's "repeated items place a component" is not asked of a build.
@@ -419,24 +429,79 @@ import { AI_JOBS_COLLECTION, registerAiJobPlanStep } from "./ai-jobs.js";
419
429
  * What a store's home is composed of (AGL-3676): a storefront's parts, the
420
430
  * hero first and the sign-up last, between them in the order its arc gives
421
431
  * (AGL-3899).
422
- */ export const AI_SITE_STORE_HOME_BANDS = 'a hero that sells first and a "Newsletter sign-up" band last, and between them "Bestsellers" (the platform lists the real products), "Shop by collection" with 3 or 4 items, the brand story, why buy here with 3 or 4 items and "Customer reviews" (the platform shows the store\'s real ones)';
432
+ */ export const AI_SITE_STORE_HOME_BANDS = 'a hero that sells first and a "Newsletter sign-up" band last (the platform\'s own email field — never one of your forms), and between them "Bestsellers" (the platform lists the real products), "Shop by collection" with 3 or 4 items, the brand story, why buy here with 3 or 4 items and "Customer reviews" (the platform shows the store\'s real ones)';
423
433
  /**
424
434
  * A store plan held to a storefront (AGL-3676, `ai-layout-storefront.ts`):
425
435
  * on a paid start its home gains the parts a shopper expects that the plan
426
436
  * left out — bestsellers, collections, reviews, a newsletter sign-up —
427
437
  * while the page has room; on any start its Shop page opens on its grid.
428
- * Settled, never re-asked: each part has one answer, and the Free wall's
429
- * home keeps the sections it planned.
438
+ * Its sign-up band places no form of its own ({@link aiSiteSignupWithoutForms},
439
+ * AGL-4065). Settled, never re-asked: each part has one answer, and the Free
440
+ * wall's home keeps the sections it planned.
430
441
  */ export function aiSiteStorefrontPlan(plan, options) {
431
- const screens = aiStorefrontPlanScreens(plan.screens, {
442
+ var _plan_create;
443
+ const screens = aiSiteSignupWithoutForms(aiStorefrontPlanScreens(plan.screens, {
432
444
  paid: options.paid,
433
445
  isShopPage: aiLayoutIsShopPage,
434
446
  gridSection: aiLayoutShopGridSection
435
- });
447
+ }), (_plan_create = plan.create) != null ? _plan_create : []);
436
448
  return screens.every((screen, index)=>screen === plan.screens[index]) ? plan : _extends({}, plan, {
437
449
  screens
438
450
  });
439
451
  }
452
+ /** A section's reference to a form: one the plan creates (`new:<its name>`), or any whose words say form, as the listings read it. */ function namesForm(ref, create) {
453
+ const named = isAiPlanNewRef(ref) ? ref.slice(ref.indexOf(':') + 1).trim().toLowerCase() : null;
454
+ return /form/i.test(ref) || create.some((entry)=>entry.kind === 'form' && entry.name.trim().toLowerCase() === named);
455
+ }
456
+ /**
457
+ * A store's newsletter band is the platform's own email field (AGL-4065).
458
+ * The 2026-10-25 Berm & Bolt plan placed its parts inquiry form in the home's
459
+ * "Newsletter sign-up" band; the listings place no sign-up where a section
460
+ * places a form, so the home drew the inquiry form under that heading. A
461
+ * section whose name says sign-up loses every form it names. A form placed
462
+ * nowhere else keeps a band of its own, named for it, just before the
463
+ * sign-up while the page has room; else the sign-up band becomes it. Pure;
464
+ * a plan whose sign-up places no form comes back as it was.
465
+ */ export function aiSiteSignupWithoutForms(screens, create) {
466
+ const signup = (section)=>aiStorefrontSays('signup', section.name);
467
+ return screens.map((screen)=>{
468
+ if (!screen.sections.some((section)=>signup(section) && section.uses.some((ref)=>namesForm(ref, create)))) return screen;
469
+ const sections = screen.sections.flatMap((section, index)=>{
470
+ if (!signup(section)) return [
471
+ section
472
+ ];
473
+ const forms = section.uses.filter((ref)=>namesForm(ref, create));
474
+ if (!forms.length) return [
475
+ section
476
+ ];
477
+ const rest = _extends({}, section, {
478
+ uses: section.uses.filter((ref)=>!forms.includes(ref))
479
+ });
480
+ // A form no other section of any page places keeps a band of its own.
481
+ const elsewhere = (ref)=>screens.some((other)=>other.sections.some((entry, at)=>(other !== screen || at !== index) && entry.uses.includes(ref)));
482
+ const alone = forms.filter((ref)=>!elsewhere(ref));
483
+ if (!alone.length) return [
484
+ rest
485
+ ];
486
+ const own = alone[0];
487
+ const purpose = own.slice(own.indexOf(':') + 1).replace(/\s*\bform\b\s*$/i, '').trim();
488
+ const band = {
489
+ name: purpose || 'Get in touch',
490
+ uses: alone,
491
+ items: 0
492
+ };
493
+ return screen.sections.length < AI_SITE_MAX_SECTIONS ? [
494
+ band,
495
+ rest
496
+ ] : [
497
+ _extends({}, rest, band)
498
+ ];
499
+ });
500
+ return _extends({}, screen, {
501
+ sections
502
+ });
503
+ });
504
+ }
440
505
  /** The code a store plan with no Shop page is re-asked under. */ export const AI_SITE_STORE_SHOP_CODE = 'plan-store-shop-page';
441
506
  /**
442
507
  * A store plan of two or more pages with no Shop page (AGL-3676): the page
@@ -1109,7 +1174,7 @@ export function createAiJobPlanStep(deps = {}) {
1109
1174
  var _ref3;
1110
1175
  // The reused plan's draft ids name the other job's drafts; this job's are its own.
1111
1176
  // Settled again against what the datasets hold now (AGL-3912).
1112
- const kept = site ? aiSettlePlanDatasets(aiSettleSiteForeignDatasets(reused.plan, inventory, capabilities), capabilities) : reused.plan;
1177
+ const kept = site ? aiSettlePlanSplitListings(aiSettlePlanDatasets(aiSettleSiteForeignDatasets(reused.plan, inventory, capabilities), capabilities)) : reused.plan;
1113
1178
  const plan = aiPlanWithStorePages(job.kind, ops, inventory, aiPlanWithItemCredits(itemOps, aiPlanWithDraftIds(job.kind, _extends({}, aiPlanWithInspiration(kept, inspiration), {
1114
1179
  status: 'proposed',
1115
1180
  labels: aiPlanLabels(kept, inventory),
@@ -1171,7 +1236,7 @@ export function createAiJobPlanStep(deps = {}) {
1171
1236
  siteSlugs: ((_ref = inventory == null ? void 0 : inventory.screens) != null ? _ref : []).map((screen)=>screen.slug),
1172
1237
  pageLimit: aiBuildPageLimit(freeTaste),
1173
1238
  siteLayout: aiSiteLayoutOf(inventory)
1174
- }) : site ? aiSettleSiteForeignDatasets(answered, inventory, capabilities) : answered);
1239
+ }) : site ? aiSettlePlanSplitListings(aiSettleSiteForeignDatasets(answered, inventory, capabilities)) : answered);
1175
1240
  }
1176
1241
  }, site ? {
1177
1242
  settleForms: (placed)=>aiSettlePlanHomeForms(placed, inventory, {