Split A1 category prompts canonically; retire attributes prompting

- Category enhance prompts (Sync A1 / seed-a1 / repair) now use the same
  three role sections as the rest of the platform: Title / Description /
  Meta. The retired "--- Attributes ---" role section is removed from the
  canonical template, the legacy-split overlay, and the web prompt editor;
  Category/Attrs stay as plain product-context lines (attribute extraction
  remains pipeline-level via AppendAttributeConstraints).
- Stored prompts still carrying an attributes section are detected by
  CategoryEnhancePromptNeedsRepair and rewritten on the next Sync.
- Legacy wp_product_categories.sql splits now also seed a default Slovenian
  metaTitle rule (dumps only carried <metaDescription>), so every A1
  category gets all four prompt areas: title formula, description
  sections, meta title, meta description.
- Role-sectioned prompts no longer imply the A1 SEO-omit cohort
  (CompanyOmitsSEOMeta): sectioned prompts are the canonical prompt-editor
  output for every tenant, and the sniff silently disabled SEO meta for
  any company that saved a category prompt.
- Verified locally: repair-category-prompts -apply updated 238 A1 +
  Platform Demo categories from scripts/seed/wp_product_categories.sql
  (216 legacy splits), idempotent on re-run, zero attributes sections
  left in DB.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-18 00:13:44 +02:00
co-authored by Claude Fable 5
parent 2a2b01bf59
commit b595398389
14 changed files with 127 additions and 115 deletions
+18 -16
View File
@@ -50,17 +50,19 @@ type DefaultTemplate struct {
}
// CategoryEnhanceUserTemplate is the shared per-category (and built-in) enhance USER
// message, sectioned by role (title / description / meta / attributes) using the
// same "--- Section ---" markers as legacy enhance-product. Includes {{name}}
// message, sectioned by role (title / description / meta) using the same
// "--- Section ---" markers as legacy enhance-product. Includes {{name}}
// {{description}} {{attrs}} {{category}} {{language}}. Compatible with enhance
// JSON {"name","description","meta_title","meta_description","attrs"} —
// description is formula HTML product body; meta_* are plain SEO fields (legacy
// A1 <metaDescription> / cats.json metaTitle+metaDescription); attrs is the
// category-allowlisted attribute map. Title/description/meta formulas stay in
// A1 <metaDescription> / cats.json metaTitle+metaDescription). Attribute
// extraction is pipeline-level (allowlist via AppendAttributeConstraints) and is
// deliberately NOT a category prompt section; Category/Attrs stay as plain
// product-context lines. Title/description/meta formulas stay in
// title_template / description_template and are appended at render time (see
// processing.AppendFormulaConstraints / AppendAttributeConstraints). Categorize
// (unique_id) is RoleCategorize / ProductCategorize* — not this overlay. Used by
// local A1/Demo prompt repair and seed-a1 overlays.
// processing.AppendFormulaConstraints). Categorize (unique_id) is RoleCategorize
// / ProductCategorize* — not this overlay. Used by local A1/Demo prompt repair
// and seed-a1 overlays.
const CategoryEnhanceUserTemplate = `Your reply is parsed as JSON {"name":"string","description":"string","meta_title":"string","meta_description":"string","attrs":{}} only (system schema). Write all string fields in {{language}} (do not hardcode a language).
--- Title ---
@@ -77,17 +79,17 @@ Description: {{description}}
Role: meta. Build JSON "meta_title" and "meta_description" as plain SEO text (never HTML). meta_title: 50-60 chars; meta_description: 120-155 chars; follow any SEO meta formula that follows; never copy the full description HTML into meta_description.
--- End Meta ---
--- Attributes ---
Role: attributes. Build JSON "attrs" as an object of attribute_key → value strings. Prefer Allowed attribute keys / Title formula attr slots that follow; remap near-miss labels onto those keys; fill missing keys only from Name/Description/Category/Attrs evidence; never invent specs; omit unknown keys; never invent dimensions.
Product context:
Category: {{category}}
Attrs: {{attrs}}
--- End Attributes ---`
Attrs: {{attrs}}`
// CategoryEnhancePromptNeedsRepair reports whether a stored categories.prompt value
// should be rewritten into role-sectioned enhance overlay form. Empty prompts are
// left alone. Canonical CategoryEnhanceUserTemplate and per-category overlays that
// already carry Title/Description/Meta/Attributes markers (+ {{attrs}}) are OK —
// equality with the shared template is not required (legacy splits keep Slovenian rules).
// already carry Title/Description/Meta markers are OK — equality with the shared
// template is not required (legacy splits keep Slovenian rules). Prompts still
// carrying a retired "--- Attributes ---" role section are rewritten so attribute
// prompting stays out of category prompts.
func CategoryEnhancePromptNeedsRepair(prompt string) bool {
p := strings.TrimSpace(prompt)
if p == "" {
@@ -96,10 +98,10 @@ func CategoryEnhancePromptNeedsRepair(prompt string) bool {
if IsLegacyCombinedEnhancePrompt(p) {
return true
}
if CategoryEnhanceHasRoleSections(p) && strings.Contains(p, "{{attrs}}") {
return false
if !CategoryEnhanceHasRoleSections(p) {
return true
}
return true
return strings.Contains(strings.ToLower(p), strings.ToLower(SectionAttributesStart))
}
// BuiltInDefaults match the previous hardcoded system prompts, with structured user templates.