fix: clamp boost values to [-1, 1]

Additive layers can exceed the documented range.

Co-authored-by: Ona <no-reply@ona.com>
This commit is contained in:
2026-03-01 22:41:19 +00:00
parent 4f55439f77
commit 0f8b1ec4eb
2 changed files with 21 additions and 3 deletions

View File

@@ -1,6 +1,6 @@
import type { Context, FeedItem, FeedItemSignals } from "@aris/core" import type { FeedItem, FeedItemSignals } from "@aris/core"
import { TimeRelevance } from "@aris/core" import { Context, TimeRelevance } from "@aris/core"
import { CalDavFeedItemType } from "@aris/source-caldav" import { CalDavFeedItemType } from "@aris/source-caldav"
import { CalendarFeedItemType } from "@aris/source-google-calendar" import { CalendarFeedItemType } from "@aris/source-google-calendar"
import { TflFeedItemType } from "@aris/source-tfl" import { TflFeedItemType } from "@aris/source-tfl"
@@ -20,7 +20,7 @@ import {
// ============================================================================= // =============================================================================
function makeContext(date: Date): Context { function makeContext(date: Date): Context {
return { time: date } return new Context(date)
} }
function makeDate(year: number, month: number, day: number, hour: number, minute = 0): Date { function makeDate(year: number, month: number, day: number, hour: number, minute = 0): Date {
@@ -673,6 +673,19 @@ describe("edge cases", () => {
expect(result.boost!["w-current"]).toBeGreaterThan(0) expect(result.boost!["w-current"]).toBeGreaterThan(0)
}) })
test("boost values are clamped to [-1, 1]", async () => {
// Morning weekday: TfL alert gets +0.6 from period rules.
// Pre-meeting adds +0.5. Total would be +1.1 without clamping.
const now = tuesday(8, 45)
const enhancer = createTimeOfDayEnhancer({ clock: () => now })
const meeting = calendarEvent("c1", tuesday(9))
const alert = tflAlert("tfl-1", 0.8)
const result = await enhancer([meeting, alert], makeContext(now))
expect(result.boost!["tfl-1"]).toBeLessThanOrEqual(1)
expect(result.boost!["tfl-1"]).toBeGreaterThanOrEqual(-1)
})
test("suppress list is deduplicated", async () => { test("suppress list is deduplicated", async () => {
// An item that would be suppressed by both evening rules and pre-meeting low-urgency // An item that would be suppressed by both evening rules and pre-meeting low-urgency
const now = tuesday(19, 45) const now = tuesday(19, 45)

View File

@@ -123,6 +123,11 @@ export function createTimeOfDayEnhancer(options?: TimeOfDayEnhancerOptions): Fee
const eveningLocation = hasEveningCalendarEventWithLocation(items, now) const eveningLocation = hasEveningCalendarEventWithLocation(items, now)
applyWeatherTimeCorrelation(items, period, dayType, eveningLocation, boost) applyWeatherTimeCorrelation(items, period, dayType, eveningLocation, boost)
// Clamp boost values to [-1, 1] — additive layers can exceed the range
for (const id in boost) {
boost[id] = Math.max(-1, Math.min(1, boost[id]!))
}
const result: FeedEnhancement = {} const result: FeedEnhancement = {}
if (Object.keys(boost).length > 0) { if (Object.keys(boost).length > 0) {
result.boost = boost result.boost = boost