Files
greeneclipseandClaude Fable 5 9a839d6d13 Store category prompts as EXACT split legacy text, no boilerplate
The per-category prompt editor showed English machine boilerplate
("Role: description. Build JSON …", schema intro, {{var}} context lines)
because seed/sync baked the render framing into categories.prompt. Now the
stored overlay is exactly the legacy wp_product_categories.sql content,
split into the three sections a user would type themselves:

  --- Title ---        Slovenian naming formula
  --- Description ---  legacy <H2>/<p>/<ul> body structure
  --- Meta ---         legacy metaDescription instruction

Schema, role framing, and Name/Description/Category/Attrs product context
stay render-time only (system template + ensureCategoryEnhanceUserContext),
where they already existed.

- SplitLegacyCombinedEnhancePrompt: non-legacy input now returns "" —
  categories without seed/legacy content get their override CLEARED
  (company default) instead of being stuffed with the canonical template
  (e.g. parent categories like "Bela tehnika" absent from the SQL).
- CategoryEnhancePromptNeedsRepair flags stored boilerplate ("parsed as
  JSON", "Build JSON", retired Attributes section) so Sync rewrites old
  data to the clean shape; repair supports clearing (prompt = '{}').
- seed-a1 apply-category-prompts skips instead of writing template text.
- Web editor compose stores only the user's section text: empty sections
  keep bare markers, default bodies and the default preamble are never
  persisted (DEFAULT_SECTION_BODIES removed).
- Verified locally: apply rewrote 238 A1+Demo categories (216 exact
  splits, 22 cleared), zero boilerplate matches in DB, idempotent re-run
  (would_update=0).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 00:53:26 +02:00

97 lines
3.5 KiB
Go

package aiprompts
import (
"strings"
"testing"
)
func TestCategoryEnhanceHasRoleSections(t *testing.T) {
t.Parallel()
if !CategoryEnhanceHasRoleSections(CategoryEnhanceUserTemplate) {
t.Fatal("canonical CategoryEnhanceUserTemplate must have title/description/meta sections")
}
if CategoryEnhanceHasRoleSections("legacy HTML prompt") {
t.Fatal("unstructured prompt must not report role sections")
}
if CategoryEnhanceHasRoleSections("--- Title ---\nonly title") {
t.Fatal("partial sections must not pass")
}
// Old stored prompts with an attributes section still count as sectioned
// (repair rewrites them via CategoryEnhancePromptNeedsRepair).
old := "--- Title ---\nx\n--- Description ---\ny\n--- Meta ---\nz\n--- Attributes ---\na\n--- End Attributes ---"
if !CategoryEnhanceHasRoleSections(old) {
t.Fatal("old attributes-bearing prompt must still report role sections")
}
if !CategoryEnhancePromptNeedsRepair(old) {
t.Fatal("old attributes-bearing prompt must need repair (attributes section retired)")
}
// The built-in template is render-time only; a STORED copy is boilerplate
// pollution and must be repaired (cleared to company default).
if !CategoryEnhancePromptNeedsRepair(CategoryEnhanceUserTemplate) {
t.Fatal("stored canonical template text must need repair")
}
}
func TestCategoryPromptRolesOrder(t *testing.T) {
t.Parallel()
want := []string{RoleCategorize, RoleTitle, RoleDescription, RoleMeta, RoleAttributes}
if len(CategoryPromptRoles) != len(want) {
t.Fatalf("roles len=%d want %d", len(CategoryPromptRoles), len(want))
}
for i, w := range want {
if CategoryPromptRoles[i] != w {
t.Fatalf("roles[%d]=%q want %q", i, CategoryPromptRoles[i], w)
}
}
}
func TestCategoryEnhanceUserTemplateRoleMarkers(t *testing.T) {
t.Parallel()
tpl := CategoryEnhanceUserTemplate
for _, marker := range []string{
SectionTitleStart, SectionTitleEnd,
SectionDescriptionStart, SectionDescriptionEnd,
SectionMetaStart, SectionMetaEnd,
} {
if !strings.Contains(tpl, marker) {
t.Fatalf("template missing %q", marker)
}
}
// Attribute prompting is retired from category prompts (pipeline-level only).
if strings.Contains(tpl, SectionAttributesStart) || strings.Contains(strings.ToLower(tpl), "role: attributes") {
t.Fatal("template must not carry an attributes role section")
}
lower := strings.ToLower(tpl)
for _, role := range []string{"role: title", "role: description", "role: meta"} {
if !strings.Contains(lower, role) {
t.Fatalf("template missing %q", role)
}
}
// HeuristicCompleter / labeledPromptValue depend on these product context labels.
for _, label := range []string{"Name: {{name}}", "Description: {{description}}", "Category: {{category}}", "Attrs: {{attrs}}"} {
if !strings.Contains(tpl, label) {
t.Fatalf("template missing product label %q", label)
}
}
if !strings.Contains(tpl, "meta_title") || !strings.Contains(tpl, "meta_description") {
t.Fatal("template must keep enhance meta_* schema (parallel title/meta work)")
}
if !strings.Contains(tpl, `"attrs":{}`) {
t.Fatal("template must keep enhance attrs schema (parallel attributes work)")
}
}
func TestSEOMetaUserTemplateHasMetaSection(t *testing.T) {
t.Parallel()
def, ok := DefaultFor(KeySEOMeta)
if !ok {
t.Fatal("missing seo_meta default")
}
if !strings.Contains(def.UserTemplate, SectionMetaStart) {
t.Fatal("seo_meta user template should use --- Meta --- section")
}
if !strings.Contains(strings.ToLower(def.UserTemplate), "role: meta") {
t.Fatal("seo_meta user template should declare Role: meta")
}
}