Skip to content

feat: local usage dashboard with per-tier and Pro version counts - #470

Open
JulianZJN wants to merge 5 commits into
miuuyy:mainfrom
JulianZJN:feat/local-usage-statistics
Open

JulianZJN wants to merge 5 commits into
miuuyy:mainfrom
JulianZJN:feat/local-usage-statistics

Conversation

@JulianZJN

@JulianZJN JulianZJN commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds local launcher activity statistics, following the usage-metrics direction discussed in #309. This is a local activity counter, not an official ChatGPT allowance, remaining-quota API, reset timer, or cross-device account total.

  • Dedicated sidebar Statistics page: 7/30-day stacked daily chart, distinct effort tiers and Pro-version series, keyboard-accessible daily details, and en/zh-CN/ja copy. Statistics is separate from Settings and follows the existing browser visibility/navigation lifecycle without stopping a task.
  • Separate GPT-5.6 Pro today and GPT-6 Pro this calendar week cards, plus a dedicated Pro lifetime table (5.5, 5.6, 6, unknown).
  • Count after browser submission evidence, not HTTP requests or Send activation. Accepted multipart parts count separately; ordinary tool exchanges and duplicate callbacks do not. Accepted sends remain counted after a generation error/cancellation, with completed/error outcomes separate.
  • Observe Pro version from the selector's existing live description nodes; missing/ambiguous metadata stays unknown. This does not select a model, probe ChatGPT, or depend on model-version selection PR feat: add optional Pro model version selection in Settings #439.
  • Zero Risk keeps its no-DOM-inspection behavior: count only after manual Sent confirmation, with self-reported Pro isolated from exact-version cards.
  • Private local storage: bounded daily aggregates and deduplication receipts, atomic replacement/process lock, restart-safe acceptance-day attribution, separate lifetime totals. No prompt/response text, credentials, cookies, or conversation content is persisted. Telemetry failures cannot fail the model turn.

Counting boundaries

Collection starts with this feature; no historical chat scraping/import. Reporting uses local calendar days and Monday-based weeks, not OpenAI's official reset schedule. Unknown versions are not guessed. Storage/observation failures or a crashed owner can leave incomplete outcomes; these are not represented as authoritative remaining allowances.

See counting, retention and privacy.

Reliability and refresh follow-up

  • Keep the first terminal outcome and timestamp even when persistence fails; later callbacks retry that outcome rather than reversing success/failure. Reproduced the original failure against the exact previous head.
  • Preserve one previous validated snapshot in a private atomic backup. Duplicate callbacks do not write or rotate snapshots; corrupt, oversized, future-schema, and missing-primary-with-backup cases do not reset history. Keep the v1 schema and existing core-home path.
  • Check stale lock ownership before recovery rather than stealing a live writer's lock based on age. Unverifiable legacy locks/orphan recovery guards still need explicit manual recovery after all writers stop, as documented.
  • Refresh every 30 seconds while visible and on foreground return; ignore obsolete range responses, coalesce reads within an active effect, and clean up listeners/timers on unmount. Failed refreshes remove stale totals.
  • Put Pro summaries first, hide unused chart legend entries, distinguish unrecorded outcomes from running tasks, and add roving keyboard navigation. No new UI/runtime dependencies.

Current validation (follow-up revision)

  • Full core suite after applying the supplied patch: 727 passed, 1 platform skip, 0 failed. Then added a POSIX permissions regression and reran the complete reliability file: 20 passed, 0 failed (including the added test); these counts overlap and are not summed.
  • Full launcher suite including the follow-up and additional UI regressions: 325 passed, 1 platform skip, 0 failed.
  • Core and launcher TypeScript checks passed.
  • Launcher renderer build, runtime bundle, version consistency, license generation (runtime build), and relocatable release smoke passed.
  • Browser acceptance tests exercise the real send boundary: no count before acceptance; independent live description nodes do not mistake explanatory Pro text for the selected state.
  • Existing Zero Risk adapter/broker tests now assert pre-send failure, confirmed send/completion, and post-accept cancellation counting. An injected store keeps all simulated manual turns in temporary test storage even when other tests clear process-level home overrides.
  • Store tests cover restart deduplication, acceptance-write recovery, midnight/DST/Monday boundaries, timezone changes, receipt pruning, corruption, and core/Electron-reader parity.
  • Inspected the synthetic statistics UI and full-launcher navigation through actual browser controls: 7/30 switching, chart/summary reconciliation, localized labels, unreadable state, and browser-to-statistics visibility transitions. Fixed a 30-day endpoint-label overlap found in that inspection. Reproduce with the fixture instructions in the documentation; no account is accessed.
  • This revision passed macOS arm64 ZIP/DMG packaging, deep/strict signature verification, and packaged launcher startup/runtime smoke in a temporary core home. The installed user application was not replaced. This is local ad-hoc signing, not notarized distribution validation.
  • Real React Strict Mode fixture verified through browser controls: quiet refresh retains the chart, 7-to-30-day range races reject obsolete results, failure removes old counts, and Home/End/arrow/Escape keys work. Two additional real React DOM checks ran with temporary test-only jsdom outside the repository; no package or lockfile changed. The checked-in hook harness is explicitly not a React DOM test.
  • Upgrade, same-version runtime repair, rejected update, and profile tests operate on the actual installer module with synthetic bundles and verify byte-identical usage/backup retention.

Historical compatibility evidence only: the previous revision was integrated with a separate local Pro-selection patch and passed 62 focused tests plus native installation checks. That previous installed build is not evidence that this follow-up has been installed into a paid-account session.

Verification limitation: bun run verify stops at existing dependency audit findings. Neither package manifests nor lockfiles change in this PR. Root audit reports three moderate Hono advisories (GHSA-gqvv-2mrq-wpjv, GHSA-g6gw-c38x-mqfc, GHSA-crvj-82cr-hjcx); launcher audit reports the high-severity js-yaml advisory GHSA-2883-xcg3-v3hh. The remaining verification steps were run separately as listed above; the aggregate verify command is not claimed green. The dependency-only fix is already tracked independently in #415 and is intentionally not duplicated in this feature PR.

No paid-model generation was used for validation, and no GPT-6 request was sent. Acceptance/Pro identity boundary coverage is fixture-based, not a claim of paid-account end-to-end generation across every model.

@JulianZJN

Copy link
Copy Markdown
Contributor Author

Pushed 186ad08 to fix automated Pro usage being recorded as version unknown.

The observed picker stores its live 5.6 Pro description on the keyboard role="menuitem" that contains the numeric, accessibility-hidden slider. The telemetry observer was reading aria-describedby from the slider itself. It now reads the nearest owning menuitem, retaining the legacy slider fallback only when no owner exists. No model selection, prompt submission, configured-version inference, or historical counter rewriting is introduced; the existing 500 ms best-effort observation boundary remains unchanged.

The regression fixture now models that actual ownership rather than placing the description attribute on the wrong element. It covers 5.5/5.6/6, unrelated Pro help text, non-Pro state, missing and conflicting descriptions, legacy ownership and detached DOM. The new ownership test failed before the fix and passes after it.

Validation on the exact pushed commit in a clean detached worktree:

  • Core suite: 730 passed, 1 platform skip, 0 failed.
  • TypeScript: passed.
  • No package manifests or lockfiles changed.

Full bun run verify is still blocked before tests by the existing hono@4.12.34 dependency audit (three moderate advisories). The current macOS/Linux/Windows CI jobs all report that same audit failure. This update does not claim a green full verification or a fresh real-account end-to-end send.

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