fix(planning): hasConflict only when scoreDelta strictly negative

Neutral suggestions (scoreDelta = 0) are not conflicts — they simply
don't improve variety. Changing scoreDelta <= 0 to scoreDelta < 0
lets empty-plan additions and quality-neutral swaps show without a
misleading ⚠ Variationskonflikt warning.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-09 12:47:41 +02:00
parent 1611ddabf6
commit 77cdccb26c
2 changed files with 6 additions and 6 deletions

View File

@@ -152,7 +152,7 @@ public class PlanningService {
double simulatedScore = simulateVarietyScore( double simulatedScore = simulateVarietyScore(
plan, candidate, slotDate, config, recentlyCookedIds); plan, candidate, slotDate, config, recentlyCookedIds);
double scoreDelta = simulatedScore - currentScore; double scoreDelta = simulatedScore - currentScore;
boolean hasConflict = scoreDelta <= 0; boolean hasConflict = scoreDelta < 0;
return new SuggestionResponse.SuggestionItem(toSlotRecipe(candidate), scoreDelta, hasConflict); return new SuggestionResponse.SuggestionItem(toSlotRecipe(candidate), scoreDelta, hasConflict);
}) })
.sorted((a, b) -> Double.compare(b.scoreDelta(), a.scoreDelta())) .sorted((a, b) -> Double.compare(b.scoreDelta(), a.scoreDelta()))

View File

@@ -180,10 +180,10 @@ class SuggestionsTest {
assertThat(result.suggestions()).hasSize(3); assertThat(result.suggestions()).hasSize(3);
// Empty plan → currentScore = 10.0; no penalties → scoreDelta = 0.0 for all // Empty plan → currentScore = 10.0; no penalties → scoreDelta = 0.0 for all
// hasConflict = (scoreDelta <= 0) = true even for neutral recipes // hasConflict = (scoreDelta < 0) = false for neutral recipes
assertThat(result.suggestions()).allSatisfy(s -> { assertThat(result.suggestions()).allSatisfy(s -> {
assertThat(s.scoreDelta()).isEqualTo(0.0); assertThat(s.scoreDelta()).isEqualTo(0.0);
assertThat(s.hasConflict()).isTrue(); assertThat(s.hasConflict()).isFalse();
}); });
} }
@@ -255,9 +255,9 @@ class SuggestionsTest {
class ScoreDeltaAndHasConflict { class ScoreDeltaAndHasConflict {
@Test @Test
void recipeWithNoConflictsOnEmptyPlanShouldHaveZeroDeltaAndHasConflict() { void recipeWithZeroDeltaOnEmptyPlanShouldNotHaveConflict() {
// Empty plan → currentScore = 10.0. Clean recipe → simulatedScore = 10.0. // Empty plan → currentScore = 10.0. Clean recipe → simulatedScore = 10.0.
// scoreDelta = 0.0, hasConflict = (0.0 <= 0) = true // scoreDelta = 0.0. No worsening → hasConflict = false.
var plan = createPlan(); var plan = createPlan();
var recipe = createRecipe("Clean Recipe"); var recipe = createRecipe("Clean Recipe");
stubPlan(plan); stubPlan(plan);
@@ -271,7 +271,7 @@ class SuggestionsTest {
assertThat(result.suggestions()).hasSize(1); assertThat(result.suggestions()).hasSize(1);
var item = result.suggestions().getFirst(); var item = result.suggestions().getFirst();
assertThat(item.scoreDelta()).isEqualTo(0.0); assertThat(item.scoreDelta()).isEqualTo(0.0);
assertThat(item.hasConflict()).isTrue(); assertThat(item.hasConflict()).isFalse();
} }
@Test @Test