package placement import ( "strings" libkg "haixun-backend/internal/library/knowledge" ) // HasTangentialTopicMismatch uses the shared intent model: broad category overlap // without product/research-map intent alignment (generalizes beyond hardcoded lists). func HasTangentialTopicMismatch(text string, ctx PostScanContext) bool { text = strings.TrimSpace(text) if text == "" { return false } if matchesTopicAnchor(text, ctx) { return false } profile := libkg.BuildIntentProfile(intentProfileInputFromPostScan(ctx)) return libkg.IsTangentialToIntent(text, profile) } func PatrolTagInputFromScanContext(ctx PostScanContext) libkg.PatrolTagInput { return intentProfileInputFromPostScan(ctx) } func intentProfileInputFromPostScan(ctx PostScanContext) libkg.PatrolTagInput { return libkg.PatrolTagInput{ ProductName: ctx.ProductName, ProductFeatures: ctx.ProductFeatures, AudienceSummary: ctx.AudienceSummary, TargetAudience: ctx.TargetAudience, MatchTags: append([]string{}, ctx.MatchTags...), Questions: append([]string{}, ctx.Questions...), Pillars: append([]string{}, ctx.Pillars...), } } // LocalIntentScore is the offline semantic scorer (no embedding API). func LocalIntentScore(text string, ctx PostScanContext) int { return libkg.ScoreIntentSimilarity(text, libkg.BuildIntentProfile(intentProfileInputFromPostScan(ctx))) }