Skip to main content

Duration Optimization

Duration optimization is a key feature that makes habit scheduling intelligent. Instead of always using a fixed duration, the system adapts based on the available time slot and your preferences.

Flexible Duration Bounds

Each habit can have three duration settings:
SettingDescriptionDefault
PreferredThe ideal duration for this habitRequired
MinimumShortest acceptable duration50% of preferred (min 15 min)
MaximumLongest beneficial duration150% of preferred (max 180 min)
If you only set the preferred duration, the system calculates sensible defaults for min and max.

Optimization Strategy

The duration optimizer chooses the optimal duration based on slot characteristics:

1. Ideal Time Match

When the slot contains your specified ideal_time (e.g., “07:00”):
Duration = Maximum
The system maximizes duration because you’re getting your most valuable time slot. This is when you’ll get the most benefit from the habit.

2. Time Preference Match

When the slot falls within your preferred time-of-day:
PreferenceTime Range
Morning6:00 AM - 12:00 PM
Afternoon12:00 PM - 5:00 PM
Evening5:00 PM - 9:00 PM
Night9:00 PM - 12:00 AM
Duration = Preferred
The system uses your standard preferred duration since this is still a good time for the habit.

3. Constrained Slot

When the available slot is smaller than your preferred duration:
Duration = max(Minimum, Available)
The system shrinks to fit while ensuring you still get value from the habit.

4. No Special Conditions

When no preferences match:
Duration = Preferred
Falls back to your standard preferred duration.

Slot Scoring

When multiple time slots are available, the system scores each one to find the best:
function scoreSlotForHabit(habit, slot): number {
  let score = 0;

  // Ideal time match is best (+1000)
  if (slotContainsIdealTime(slot, habit.ideal_time)) {
    score += 1000;
  }

  // Time preference match is second best (+500)
  if (slotMatchesPreference(slot, habit.time_preference)) {
    score += 500;
  }

  // Prefer slots that fit preferred duration (+200/+100)
  if (slot.maxAvailable >= habit.preferred) {
    score += 200;
  } else if (slot.maxAvailable >= habit.minimum) {
    score += 100;
  }

  // Slight preference for earlier slots (tiebreaker)
  score -= slot.start.getHours() * 0.1;

  return score;
}

Examples

Morning Meditation

Habit: Morning Meditation
Preferred: 20 minutes
Minimum: 10 minutes
Maximum: 30 minutes
Ideal Time: 06:30
Preference: Morning
SlotDurationReason
6:00 AM - 7:00 AM30 minContains ideal time, maximize
8:00 AM - 9:00 AM20 minMorning preference, use preferred
12:00 PM - 1:00 PM20 minNo match, use preferred
6:00 AM - 6:15 AM15 minConstrained, use minimum

Evening Workout

Habit: Evening Workout
Preferred: 60 minutes
Minimum: 30 minutes
Maximum: 90 minutes
Ideal Time: null
Preference: Evening
SlotDurationReason
5:00 PM - 7:00 PM60 minEvening preference, use preferred
8:00 PM - 9:00 PM60 minEvening preference, use preferred
5:00 PM - 5:45 PM45 minConstrained, fit to slot
10:00 AM - 12:00 PM60 minNo match, use preferred

Implementation Details

The duration optimizer is implemented in packages/ai/src/scheduling/duration-optimizer.ts:
// Key exports
export function getEffectiveDurationBounds(habit): { preferred, min, max };
export function calculateOptimalDuration(habit, slot, characteristics): number;
export function timeMatchesSlot(idealTime: string, slot): boolean;
export function slotMatchesPreference(preference: TimeOfDayPreference, slot): boolean;
export function getSlotCharacteristics(habit, slot): SlotCharacteristics;
export function scoreSlotForHabit(habit, slot): number;
export function findBestSlotForHabit(habit, slots): TimeSlotInfo | null;

Configuration in Habit Form

When creating or editing a habit, you can configure duration optimization:
1

Set Preferred Duration

The standard duration for this habit (required)
2

Enable Flexible Duration

Toggle to allow min/max bounds
3

Set Minimum Duration

Shortest acceptable duration (optional)
4

Set Maximum Duration

Longest beneficial duration (optional)
5

Set Ideal Time

Specific time of day (optional, format: HH:MM)
6

Set Time Preference

Morning, Afternoon, Evening, or Night (optional)

Testing

The duration optimizer is tested with 54 test cases covering:
  • Duration bounds calculation
  • Time matching and preference detection
  • Slot scoring and selection
  • Integration scenarios for real-world habits
Run tests with:
npx vitest run src/scheduling/duration-optimizer.test.ts