This commit is contained in:
2026-08-23 16:34:50 +02:00
parent 815e26d359
commit a30b78c3b6
8 changed files with 178 additions and 33 deletions
@@ -161,29 +161,63 @@ func parseDescriptionFormula(template any) (DescriptionFormula, bool) {
}
}
// EffectiveDescriptionFormula returns the stored description_template when it has
// sections; otherwise derives sections from the category enhance prompt Description
// role (legacy HTML <H2>{…}</H2><p>{…}</p> overlays). That is how A1 and tenants
// author HTML structure in /categories/.../prompt — without this, enhance accepts
// plain prose and never runs the formula quality gate.
// EffectiveDescriptionFormula merges structured description_template with the
// category enhance prompt Title/Description/Meta role sections.
//
// Precedence for HTML body sections:
// 1. Prompt Description HTML overlay when it yields more sections than stored
// (tenants author structure in /categories/.../prompt Section instructions).
// 2. Otherwise stored description_template.sections.
//
// Meta instructions: stored metaTitle/metaDescription win; else --- Meta --- body.
func EffectiveDescriptionFormula(stored any, categoryPrompt string) DescriptionFormula {
if f, ok := parseDescriptionFormula(stored); ok && len(f.Sections) > 0 {
return f
storedF, storedOK := parseDescriptionFormula(stored)
out := DescriptionFormula{}
if storedOK {
out = storedF
}
body := ExtractEnhanceSectionBody(categoryPrompt, SectionDescriptionStart, SectionDescriptionEnd)
if body == "" {
body = strings.TrimSpace(categoryPrompt)
descBody := ExtractEnhanceSectionBody(categoryPrompt, SectionDescriptionStart, SectionDescriptionEnd)
if descBody == "" && !promptHasRoleMarkers(categoryPrompt) {
// Unsectioned prompt may still be a legacy HTML blob.
descBody = strings.TrimSpace(categoryPrompt)
}
if body == "" || !reLegacyHTMLBlock.MatchString(body) {
if f, ok := parseDescriptionFormula(stored); ok {
return f
var derived DescriptionFormula
if descBody != "" && reLegacyHTMLBlock.MatchString(descBody) {
derived = DeriveDescriptionFormulaFromLegacyParts(LegacyEnhanceParts{
DescriptionRules: descBody,
WasLegacy: true,
})
}
if len(derived.Sections) > len(out.Sections) {
out.Sections = derived.Sections
}
metaBody := ExtractEnhanceSectionBody(categoryPrompt, SectionMetaStart, SectionMetaEnd)
if strings.TrimSpace(out.MetaTitle) == "" && strings.TrimSpace(out.MetaDescription) == "" && strings.TrimSpace(metaBody) != "" {
out.MetaDescription = strings.TrimSpace(metaBody)
out.MetaTitle = DefaultLegacyMetaTitleRule
} else {
if strings.TrimSpace(out.MetaTitle) == "" && strings.TrimSpace(derived.MetaTitle) != "" {
out.MetaTitle = derived.MetaTitle
}
if strings.TrimSpace(out.MetaDescription) == "" && strings.TrimSpace(derived.MetaDescription) != "" {
out.MetaDescription = derived.MetaDescription
}
return DescriptionFormula{}
}
return DeriveDescriptionFormulaFromLegacyParts(LegacyEnhanceParts{
DescriptionRules: body,
WasLegacy: true,
})
return out
}
func promptHasRoleMarkers(prompt string) bool {
lower := strings.ToLower(prompt)
return strings.Contains(lower, strings.ToLower(SectionTitleStart)) ||
strings.Contains(lower, strings.ToLower(SectionDescriptionStart)) ||
strings.Contains(lower, strings.ToLower(SectionMetaStart))
}
// TitleSectionInstructions returns the --- Title --- body from a category prompt.
func TitleSectionInstructions(categoryPrompt string) string {
return ExtractEnhanceSectionBody(categoryPrompt, SectionTitleStart, SectionTitleEnd)
}
// EffectiveDescriptionTemplateAny is EffectiveDescriptionFormula as a JSON object
@@ -207,13 +241,18 @@ func EffectiveDescriptionTemplateAny(stored any, categoryPrompt string) any {
// CategoryTitlePromptRequiresRewrite reports whether the Title role instructs a
// new retail name (not keep/echo supplier title). Used to reject "Matched" copy-paste.
func CategoryTitlePromptRequiresRewrite(categoryPrompt string) bool {
body := ExtractEnhanceSectionBody(categoryPrompt, SectionTitleStart, SectionTitleEnd)
body := TitleSectionInstructions(categoryPrompt)
if body == "" {
body = strings.TrimSpace(categoryPrompt)
}
if body == "" {
return false
}
// Built-in CategoryEnhanceUserTemplate Title role mentions "Title formula"
// generically — that is not a tenant rewrite formula.
if strings.HasPrefix(strings.ToLower(strings.TrimSpace(body)), "role: title") {
return false
}
lower := strings.ToLower(body)
cues := []string{
"napiši novo ime",
@@ -223,8 +262,9 @@ func CategoryTitlePromptRequiresRewrite(categoryPrompt string) bool {
"write a new",
"new product name",
"rename",
"title formula",
"sentence case",
"tip izdelka",
"product type",
}
for _, c := range cues {
if strings.Contains(lower, c) {