Skip to content

feat: Add pace tracking indicator for usage metrics#70

Merged
robinebers merged 5 commits into
mainfrom
feat/pace-tracking
Feb 5, 2026
Merged

feat: Add pace tracking indicator for usage metrics#70
robinebers merged 5 commits into
mainfrom
feat/pace-tracking

Conversation

@robinebers
Copy link
Copy Markdown
Owner

@robinebers robinebers commented Feb 5, 2026

TLDR

Adds a visual indicator (colored dot) showing whether your current usage rate will exhaust your quota before the reset timer. Glance at it to know if you need to slow down.

Changes

  • Plugins now report periodDurationMs for metrics with reset timers (Session=5h, Weekly=7d, Cursor billing=~30d)
  • New calculatePaceStatus() utility projects usage at end of period
  • PaceIndicator component shows green/yellow/red dot next to metric labels
  • Tooltip styling updated to use popover colors with border/shadow for better visibility

Made with Cursor


Note

Medium Risk
Touches the plugin output contract and parsing path across JS/Rust/frontend; mis-specified durations or edge-case timestamps could lead to incorrect indicators or subtle rendering differences (though the field is optional and guarded).

Overview
Adds optional pace tracking for progress metric lines by introducing periodDurationMs alongside resetsAt, documenting it in the plugin API/schema, and plumbing it through the JS host line builder and Rust runtime parsing/serialization.

Updates bundled plugins (Claude/Codex/Cursor) to provide period durations for session/weekly/billing-cycle windows, and updates the UI to render a small colored dot with tooltip next to progress labels indicating projected pace (ahead/on-track/behind) using a new calculatePaceStatus() helper; tooltip styling is also tweaked to use popover colors/border/shadow.

Written by Cursor Bugbot for commit 822debe. This will update automatically on new commits. Configure here.


Summary by cubic

Add a small pace indicator next to usage metrics that shows if you’ll hit your quota before the reset. Green/yellow/red dots help you decide when to slow down.

  • New Features

    • Plugins include periodDurationMs for timed metrics (5h, 7d, ~30d).
    • New calculatePaceStatus utility projects usage to end of period.
    • PaceIndicator renders a green/yellow/red dot with a tooltip.
    • Tooltip styling updated for better contrast.
  • Migration

    • For pace tracking, plugins must provide resetsAt and periodDurationMs on progress lines.
    • Safe to omit; existing metrics render without the indicator.

Written for commit 822debe. Summary will update on new commits.

Shows whether current usage rate will exhaust quota before reset:
- Green dot = ahead of pace (projected <80% of limit)
- Yellow dot = on track (80-100% projected)
- Red dot = using fast (>100% projected)

Changes:
- Add periodDurationMs field to progress lines (plugins report period length)
- New pace-status.ts utility for calculating projected usage
- PaceIndicator component with tooltip next to metric labels
- Update tooltip styling to use popover colors with border/shadow

Co-authored-by: Cursor <cursoragent@cursor.com>
@macroscopeapp
Copy link
Copy Markdown

macroscopeapp Bot commented Feb 5, 2026

Add pace tracking indicator to provider usage UI by parsing periodDurationMs on progress lines in runtime.rs and rendering status in provider-card.tsx

Introduce periodDurationMs on progress metrics, parse it in the runtime, and render a dot-based pace status in the provider card using pace-status.ts; update plugin probes to emit session (5h), weekly (7d), and plan/sonnet/review periods; document the new parameter in plugin docs.

📍Where to Start

Start with parse_lines and MetricLine::Progress in runtime.rs, then review calculatePaceStatus in pace-status.ts and its usage in MetricLineRenderer in provider-card.tsx.


Macroscope summarized 822debe.

Copy link
Copy Markdown

@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: 81d21ac0c3

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread plugins/codex/plugin.js Outdated
Comment on lines +276 to +279
// Use reset_after_seconds if available, otherwise fall back to session duration
var reviewPeriodMs = PERIOD_SESSION_MS
if (typeof reviewWindow.reset_after_seconds === "number") {
reviewPeriodMs = reviewWindow.reset_after_seconds * 1000
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Use full period length, not reset_after_seconds

calculatePaceStatus derives period start as resetsAtMs - periodDurationMs, so periodDurationMs must be the full window length. Here it’s set to reset_after_seconds (time remaining), which makes the period start ~= “now”, causing elapsed time to be near zero. Result: review pace indicator will stay null for a while or significantly under-project usage (likely green) even when the review window is already heavily used. Keep PERIOD_SESSION_MS or use a true window duration instead of the remaining time.

Useful? React with 👍 / 👎.

Comment on lines +369 to +376
} else if let Some(n) = val.as_number() {
let ms = n as u64;
if ms > 0 {
Some(ms)
} else {
log::warn!("periodDurationMs at index {} must be positive, omitting", idx);
None
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 Low

plugin_engine/runtime.rs:369 Consider adding an is_finite() check before casting n to u64, consistent with the validation for used and limit above. Without it, Infinity saturates to u64::MAX and silently passes the > 0 check.

Suggested change
} else if let Some(n) = val.as_number() {
let ms = n as u64;
if ms > 0 {
Some(ms)
} else {
log::warn!("periodDurationMs at index {} must be positive, omitting", idx);
None
}
} else if let Some(n) = val.as_number() {
if !n.is_finite() || n < 0.0 {
log::warn!("periodDurationMs at index {} must be a finite positive number, omitting", idx);
None
} else {
let ms = n as u64;
if ms > 0 {
Some(ms)
} else {
log::warn!("periodDurationMs at index {} must be positive, omitting", idx);
None
}
}

🚀 Want me to fix this? Reply ex: "fix it for me".

Comment thread plugins/codex/plugin.js Outdated
Comment thread plugins/cursor/plugin.js Outdated
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 10 files

- Added periodDurationMs field to MetricLine in API and schema documentation.
- Updated progress line implementation to utilize the new periodDurationMs for pace tracking.
- Clarified documentation on how periodDurationMs interacts with resetsAt for usage metrics.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 3 files (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="plugins/codex/plugin.js">

<violation number="1" location="plugins/codex/plugin.js:282">
P2: periodDurationMs is now hardcoded to PERIOD_SESSION_MS for Reviews, ignoring reset_after_seconds and potentially miscomputing pace when the review window length differs from 5 hours.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread plugins/codex/plugin.js Outdated
limit: 100,
format: { kind: "percent" },
resetsAt: getResetsAtIso(ctx, nowSec, reviewWindow),
periodDurationMs: PERIOD_SESSION_MS
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot Feb 5, 2026

Choose a reason for hiding this comment

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

P2: periodDurationMs is now hardcoded to PERIOD_SESSION_MS for Reviews, ignoring reset_after_seconds and potentially miscomputing pace when the review window length differs from 5 hours.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At plugins/codex/plugin.js, line 282:

<comment>periodDurationMs is now hardcoded to PERIOD_SESSION_MS for Reviews, ignoring reset_after_seconds and potentially miscomputing pace when the review window length differs from 5 hours.</comment>

<file context>
@@ -273,18 +273,13 @@
             format: { kind: "percent" },
             resetsAt: getResetsAtIso(ctx, nowSec, reviewWindow),
-            periodDurationMs: reviewPeriodMs
+            periodDurationMs: PERIOD_SESSION_MS
           }))
         }
</file context>
Suggested change
periodDurationMs: PERIOD_SESSION_MS
periodDurationMs: typeof reviewWindow.reset_after_seconds === "number"
? reviewWindow.reset_after_seconds * 1000
: PERIOD_SESSION_MS
Fix with Cubic

Comment thread plugins/cursor/plugin.js Outdated
Comment thread plugins/codex/plugin.js Outdated
robinebers and others added 2 commits February 5, 2026 18:27
- Codex Reviews: use PERIOD_WEEKLY_MS (7 days) per API docs
- Cursor billing: parse string timestamps, already in ms (no * 1000)

Co-authored-by: Cursor <cursoragent@cursor.com>
- Adjusted pace status calculation to always show "ahead" when usage is zero.
- Updated PaceIndicator to reflect the new pace status logic.

Co-authored-by: Cursor <cursoragent@cursor.com>
Copy link
Copy Markdown

@cursor cursor Bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Bugbot Autofix is OFF. To automatically fix reported issues with Cloud Agents, enable Autofix in the Cursor dashboard.

Comment thread src/components/provider-card.tsx Outdated
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (all issues)

Check if these issues are valid — if so, understand the root cause of each and fix them.


<file name="src/components/provider-card.tsx">

<violation number="1" location="src/components/provider-card.tsx:338">
P2: `paceStatus` is now set to "ahead" whenever `line.used === 0`, even if `resetsAt/periodDurationMs` are missing. This will render a pace indicator for lines that don’t have pace data. Keep the indicator gated by `paceResult` and only override status when pace data exists.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

Comment thread src/components/provider-card.tsx Outdated
- Updated the condition for determining pace status to include a check for periodDurationMs, ensuring "ahead" is only shown when usage is zero and a valid period duration exists.

Co-authored-by: Cursor <cursoragent@cursor.com>
@robinebers robinebers merged commit acaac92 into main Feb 5, 2026
1 check passed
@robinebers robinebers deleted the feat/pace-tracking branch February 5, 2026 14:37
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