Skip to content

feat: add session time metrics (active time tracking per contribution) - #528

Merged
junhoyeo merged 2 commits into
junhoyeo:mainfrom
leecoder:feat/session-time-metrics
May 24, 2026
Merged

feat: add session time metrics (active time tracking per contribution)#528
junhoyeo merged 2 commits into
junhoyeo:mainfrom
leecoder:feat/session-time-metrics

Conversation

@leecoder

@leecoder leecoder commented May 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Add active time tracking per contribution, enabling users to see how much time they actually spent coding.

Changes

CLI (Rust)

  • Add time-metrics subcommand showing active time, longest session, and concurrency stats
  • Sessionize contributions and populate activeTimeMs in graph/submit payloads

Frontend

  • Add active_time_ms column to daily_breakdown table (migration 0006)
  • Store and aggregate active time in submit route
  • Show time metrics in leaderboard period tabs
  • Add time formatting utilities and update profile/stats components

Testing

  • Submitted data successfully to staging server
  • Verified leaderboard displays time metrics correctly

Summary by cubic

Adds end-to-end session time metrics so users can see active coding time, longest continuous session, and peak concurrency. Leaderboards and profiles now surface time (including sort by time), and the CLI adds a time-metrics report.

  • New Features

    • Core (crates/tokscale-core): Added sessionize with a 3‑min idle gap; computes per‑day activeTimeMs and global timeMetrics (total active, wall, longest continuous with idle‑gap merge, max concurrency incl. zero‑duration, session count); graph payloads include activeTimeMs and timeMetrics; added get_time_metrics_report.
    • CLI (crates/tokscale-cli): New time-metrics subcommand with date/client filters, --json, and --no-spinner; prints total active, wall‑clock, longest continuous, max concurrency, sessions, and processing time; graph JSON includes timeMetrics and per‑day activeTimeMs; skips pricing init for faster runs.
    • API/DB/UI (packages/frontend): Submit API accepts timeMetrics; persists submission metrics (total_active_time_ms, longest_continuous_ms, max_concurrent_sessions, session_count) and daily active_time_ms; leaderboard APIs and user rank support sortBy=time; leaderboard adds a “Time” column and period totals; profile and graph stats show “Active Time” and “Sessions” (hidden when a client filter is active); added formatDuration; submission validation updated to allow timeMetrics and per‑day activeTimeMs. Tests: fixed sessionize test helper to include duration_ms.
  • Migration

    • Run DB migration 0008_add_time_metrics_to_submissions.sql.

Written for commit 640bd4a. Summary will update on new commits. Review in cubic

@vercel

vercel Bot commented May 8, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
tokscale Ignored Ignored Preview May 24, 2026 4:27pm

Request Review

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

9 issues found across 24 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/frontend/src/lib/format.ts">

<violation number="1" location="packages/frontend/src/lib/format.ts:48">
P3: `formatDuration`'s example documentation does not match its actual output for sub-second durations.</violation>
</file>

<file name="packages/frontend/__tests__/api/leaderboard.test.ts">

<violation number="1" location="packages/frontend/__tests__/api/leaderboard.test.ts:68">
P1: Test expects two extra positional args for `getLeaderboardData`, so the assertion will never match the real 5-arg call.</violation>
</file>

<file name="packages/frontend/src/lib/db/migrations/0006_add_time_metrics_to_submissions.sql">

<violation number="1" location="packages/frontend/src/lib/db/migrations/0006_add_time_metrics_to_submissions.sql:1">
P1: Migration omits the `daily_breakdown.active_time_ms` column required by the updated submit path, causing runtime SQL failures.</violation>
</file>

<file name="packages/frontend/src/lib/db/schema.ts">

<violation number="1" location="packages/frontend/src/lib/db/schema.ts:184">
P1: daily_breakdown is missing the active_time_ms column even though submit/leaderboard code reads and writes it, creating schema drift and risking loss of per-day active-time data.</violation>
</file>

<file name="packages/frontend/src/components/GraphContainer.tsx">

<violation number="1" location="packages/frontend/src/components/GraphContainer.tsx:184">
P2: StatsPanel mixes filtered contribution stats with unfiltered active-time/session totals, so client filtering can make the numbers inconsistent.</violation>
</file>

<file name="packages/frontend/src/app/(main)/leaderboard/LeaderboardClient.tsx">

<violation number="1" location="packages/frontend/src/app/(main)/leaderboard/LeaderboardClient.tsx:1232">
P2: The new Time sort option is not supported by the user-rank API, so the current-user rank request silently falls back to tokens and shows inconsistent results.</violation>
</file>

<file name="crates/tokscale-core/src/lib.rs">

<violation number="1" location="crates/tokscale-core/src/lib.rs:1594">
P2: Time-metrics report loads and applies pricing even though the output does not use cost data, adding avoidable latency/work (and possible network/cache fetch) for no benefit.</violation>
</file>

<file name="crates/tokscale-core/src/sessionize.rs">

<violation number="1" location="crates/tokscale-core/src/sessionize.rs:127">
P1: `longest_continuous_ms` is calculated as the max single-session active duration and the `idle_gap_ms` parameter is ignored, so the metric does not match the documented merged-window semantics.</violation>

<violation number="2" location="crates/tokscale-core/src/sessionize.rs:182">
P2: `compute_max_concurrent` undercounts zero-duration sessions; single-message sessions can report 0 concurrent sessions even though the code intends them to count as 1.</violation>
</file>

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

Comment thread packages/frontend/__tests__/api/leaderboard.test.ts Outdated
Comment thread packages/frontend/src/lib/db/schema.ts
Comment thread crates/tokscale-core/src/sessionize.rs
Comment thread packages/frontend/src/components/GraphContainer.tsx Outdated
Comment thread packages/frontend/src/app/(main)/leaderboard/LeaderboardClient.tsx Outdated
Comment thread crates/tokscale-core/src/lib.rs Outdated
Comment thread crates/tokscale-core/src/sessionize.rs Outdated
Comment thread packages/frontend/src/lib/format.ts Outdated

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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/tokscale-core/src/sessionize.rs">

<violation number="1" location="crates/tokscale-core/src/sessionize.rs:149">
P2: `longest_continuous_ms` is computed from wall-clock session spans, so long idle gaps inside a session are counted as continuous time and inflate the metric.</violation>
</file>

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

Comment thread crates/tokscale-core/src/sessionize.rs Outdated

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

Copy link
Copy Markdown
Contributor

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 (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="crates/tokscale-core/src/sessionize.rs">

<violation number="1" location="crates/tokscale-core/src/sessionize.rs:151">
P2: Collapsing each session to `start_ts + active_duration_ms` loses intra-session timing and can miscompute the longest continuous activity window.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Comment thread crates/tokscale-core/src/sessionize.rs
leecoder and others added 2 commits May 25, 2026 01:25
…lizer

The new `duration_ms` field on `UnifiedMessage` (from junhoyeo#563) was missing from
the test-only `make_msg` helper in sessionize.rs, so this PR's sessionize
tests fail to compile after rebasing onto main.

Renamed migration to 0008 to avoid filename collision with main's
0007_add_submitted_devices.sql.
@junhoyeo
junhoyeo force-pushed the feat/session-time-metrics branch from 4ac6a96 to 640bd4a Compare May 24, 2026 16:26
@junhoyeo
junhoyeo merged commit 9ad8a67 into junhoyeo:main May 24, 2026
12 of 14 checks passed
@junhoyeo

Copy link
Copy Markdown
Owner

@leecoder this has been merged to v3.0.0: https://github.com/junhoyeo/tokscale/releases/tag/v3.0.0 thanks for the contribution!

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.

2 participants