Skip to content

Improve weekly pace projection using learned time-of-day profiles#401

Open
EthanLipnik wants to merge 1 commit intosteipete:mainfrom
EthanLipnik:main
Open

Improve weekly pace projection using learned time-of-day profiles#401
EthanLipnik wants to merge 1 commit intosteipete:mainfrom
EthanLipnik:main

Conversation

@EthanLipnik
Copy link

Why

The old pace logic was purely linear, so it assumed people use Codex uniformly 24/7. In
practice that over-reported deficit/runout (especially overnight) and frequently showed
misleading “~2 days left” style projections.

What Changed

  • Added a new weekly profile model (UsagePaceProfile) with 168 hourly bins and confidence
    thresholds.
  • Extended UsagePace with:
    • model (linear vs timeOfDayProfile)
    • confidence (high / low)
    • isFallbackLinear
  • Updated weekly pace calculation to:
    • use learned time-of-day profile when data is sufficient
    • fall back to linear when data is sparse, marked as low confidence
  • Added persistent per-provider learning/store (UsagePaceProfileStore):
    • learns hourly usage rates from weekly snapshot deltas
    • saves to ~/Library/Application Support/com.steipete.codexbar/pace-profiles-v1.json
  • Wired profile learning into refresh flow and profile-based pace into:
    • menu bar text
    • menu card details
    • menu descriptor summaries
    • provider preferences views
  • Removed codex-only restriction for weekly pace display when a valid weekly window exists.
  • Added/updated tests for:
    • profile-based pacing
    • low-confidence fallback behavior
    • provider-agnostic weekly pace display
    • updated status item/menu-bar expectations

User Impact

  • Pace/deficit is now personalized to actual usage patterns instead of assumed constant usage.
  • Overnight inactivity no longer skews projections as heavily.
  • Early in learning, UI clearly signals fallback with low confidence.

Validation

  • pnpm check
  • swift test -q (passes: 756 tests / 122 suites)
  • ./Scripts/compile_and_run.sh (build/package/relaunch verified)
image

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 37ac40c964

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +109 to +110
let minutes = window.windowMinutes ?? Self.weeklyWindowMinutes
let delta = abs(minutes - Self.weeklyWindowMinutes)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Require explicit weekly duration before showing pace

isWeeklyWindow currently treats window.windowMinutes == nil as a 7-day window, which makes non-weekly quotas eligible for weekly pace output. For example, Cursor emits windowMinutes: nil with a monthly billingCycleEnd (Sources/CodexBarCore/Providers/Cursor/CursorStatusProbe.swift:259-263), so this path will start showing a “weekly” pace during the last 7 days of a monthly cycle, producing misleading deficit/runway values.

Useful? React with 👍 / 👎.

Comment on lines +222 to +224
let minutes = window.windowMinutes ?? Self.weeklyWindowMinutes
let delta = abs(minutes - Self.weeklyWindowMinutes)
return delta <= Self.weeklyWindowToleranceMinutes

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exclude unknown-duration windows from profile learning

The profile store uses the same weekly check that defaults nil minutes to 7 days, so it will learn “weekly” time-of-day rates from windows whose period is actually unknown or non-weekly. With providers like Cursor (monthly reset, no windowMinutes), this contaminates pace-profiles-v1.json with non-weekly behavior and then feeds those profiles back into pace projections when a reset enters the final week.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

Comments