From 26fc39abcf506b7d3637c438dfb913b61ceb08ff Mon Sep 17 00:00:00 2001 From: Astrid Gealer Date: Mon, 26 Oct 2026 09:30:47 +0000 Subject: [PATCH] refactor(api): take the confidence-badge thresholds from pkg/exchange confidenceBucketFor kept its own copies of the 200/3/50 cut-offs because the pinned pkg did not export them yet. The pin (ff6225d5ff04) now exports exchange.ConfidenceHighSavingsUSD, ConfidenceHighMinCount and ConfidenceMediumSavingsUSD, so use them directly. The drawer badge and the reshape ranking it accompanies can no longer drift apart. Behaviour is unchanged: the boundary table in handler_recommendations_test.go still pins the literal values. Co-Authored-By: Claude Opus 5.5 --- internal/api/handler_recommendations.go | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/internal/api/handler_recommendations.go b/internal/api/handler_recommendations.go index 70e8e2536..26c5ed1ac 100644 --- a/internal/api/handler_recommendations.go +++ b/internal/api/handler_recommendations.go @@ -7,6 +7,7 @@ import ( "time" "github.com/LeanerCloud/cloud-commitments-go/pkg/common" + "github.com/LeanerCloud/cloud-commitments-go/pkg/exchange" "github.com/LeanerCloud/cloud-commitments-platform/internal/auth" "github.com/LeanerCloud/cloud-commitments-platform/internal/config" "github.com/aws/aws-lambda-go/events" @@ -386,28 +387,19 @@ func (h *Handler) buildRecommendationDetail(ctx context.Context, rec *config.Rec } } -// Confidence bucket cut-offs for the recommendation drawer badge. They must -// stay equal to exchange.ConfidenceHighSavingsUSD, exchange.ConfidenceHighMinCount -// and exchange.ConfidenceMediumSavingsUSD in cloud-commitments-go pkg/exchange, -// which score the reshape ranking the badge accompanies. Those exported -// constants are newer than the pkg version pinned in go.mod; once the pin is -// bumped past them, alias these to the exchange constants (#343). -const ( - confidenceHighSavingsUSD = 200.0 // USD per month, high bucket - confidenceHighMinCount = 3 // instances, high bucket - confidenceMediumSavingsUSD = 50.0 // USD per month, medium bucket -) - // confidenceBucketFor mirrors the heuristic that previously lived // client-side in frontend/src/recommendations.ts. Centralizing it on // the server lets future provider-specific tuning land in one place // without a frontend deploy. Thresholds intentionally match the original // shim 1:1 so the drawer label doesn't visibly shift on rollout. // -// high = savings >= confidenceHighSavingsUSD AND count >= confidenceHighMinCount -// medium = savings >= confidenceMediumSavingsUSD +// high = savings >= exchange.ConfidenceHighSavingsUSD AND count >= exchange.ConfidenceHighMinCount +// medium = savings >= exchange.ConfidenceMediumSavingsUSD // low = otherwise // +// The cut-offs come from pkg/exchange, which scores the reshape ranking the +// badge accompanies, so the two cannot drift apart (#343). +// // A count below 1 (missing) is clamped to 1, so savings alone decide between // medium and low. This deliberately differs from the exchange ranking, which // returns a neutral score for a zero count: a badge must always show a @@ -416,10 +408,10 @@ func confidenceBucketFor(savings float64, count int) string { if count < 1 { count = 1 } - if savings >= confidenceHighSavingsUSD && count >= confidenceHighMinCount { + if savings >= exchange.ConfidenceHighSavingsUSD && count >= exchange.ConfidenceHighMinCount { return "high" } - if savings >= confidenceMediumSavingsUSD { + if savings >= exchange.ConfidenceMediumSavingsUSD { return "medium" } return "low"