feat(tuning): expose EnrichedTagScale in the tuning lab (#1520)
Promote the enriched-tag weight (#1490) from a taste.Config default into the DB-backed tuning lab so operators can dial how much folksonomy tags count vs raw ID3 genre (rule #25). - Migration 0044: taste_tuning.enriched_tag_scale (DEFAULT 0.5, backfills the existing row). - recsettings: TasteTuning gains the field; seeded/read/updated through reconcile + persistTaste; applyTastePatch validates it to [0,1] (generic non-half-life clamp) and diffTaste audits it; TasteConfig maps it into the profile build. - API: tasteTuningResp exposes enriched_tag_scale. - Web tuning card: a data-driven "Enriched tag weight" knob (0 = genre only). Tests: recsettings persist+range, web fixture field. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -182,6 +182,27 @@ func TestUpdateTaste_CurveOrderingEnforced(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateTaste_EnrichedTagScale(t *testing.T) {
|
||||
pool := newPool(t)
|
||||
s := newService(t, pool)
|
||||
// In-range update persists into cache + the assembled taste config.
|
||||
if err := s.UpdateTaste(context.Background(),
|
||||
map[string]float64{"enriched_tag_scale": 0.8}); err != nil {
|
||||
t.Fatalf("UpdateTaste: %v", err)
|
||||
}
|
||||
if got := s.Taste().EnrichedTagScale; got != 0.8 {
|
||||
t.Errorf("Taste().EnrichedTagScale = %v, want 0.8", got)
|
||||
}
|
||||
if got := s.TasteConfig().EnrichedTagScale; got != 0.8 {
|
||||
t.Errorf("TasteConfig().EnrichedTagScale = %v, want 0.8", got)
|
||||
}
|
||||
// Out of [0,1] rejects.
|
||||
if err := s.UpdateTaste(context.Background(),
|
||||
map[string]float64{"enriched_tag_scale": 1.5}); !errors.Is(err, ErrOutOfRange) {
|
||||
t.Errorf("err = %v, want ErrOutOfRange for 1.5", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReset_RestoresShippedAndAudits(t *testing.T) {
|
||||
pool := newPool(t)
|
||||
s := newService(t, pool)
|
||||
|
||||
Reference in New Issue
Block a user