You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Blocked by: #50
Parent user stories covered: 30–34
Outcome
When no valid lifetime-token interval can be formed for the selected range, Account Token Activity may fall back to complete UTC daily buckets. The fallback never mixes with lifetime-derived intervals, never counts a partial bucket, and presents the UTC interval boundaries in the Mac's current timezone without calling them local calendar days.
This issue retains the existing API-provided daily data as a weaker factual source. It does not change local Token Activity or add calendar-day presets.
Existing code to start from
AccountTokenActivityMethod.dailyBuckets and dailyAccountTokenActivity(...) in Sources/CodexLimits/UsageIntelligenceEngine.swift.
UsageSnapshot.tokenHistory and the existing daily fallback tests in UsageIntelligenceEngineTests.swift.
Account card/source text in TokenActivityWorkspace in MenuContentView.swift.
UTC helpers already present in UsageHistory.swift; reuse Foundation Calendar/fixed UTC only to model source intervals, not reader-facing labels.
Source precedence
For one selected range, choose exactly one method:
If at least one valid lifetime Token Activity Interval is fully contained, use all contained lifetime intervals and ignore daily buckets.
Otherwise, consider daily buckets.
Include a daily bucket only if its entire actual UTC interval [00:00Z, next 00:00Z) lies inside the selected range.
Sum included daily buckets. Do not combine them with any lifetime delta.
If neither method supplies a complete interval, return No account readings in this range.
A lifetime reading pair outside the selected range does not count as an available interval inside it. Precedence is evaluated for the selected range, not globally.
Presentation contract
Method/provenance says the value comes from Codex UTC daily token totals.
Display the bucket's actual start/end formatted using the Mac's current timezone.
Do not label a UTC bucket as “Aug 2 local day” when its local boundaries span parts of two dates.
The primary card stays simple; source mechanics belong in Evidence Details.
Missing partial bucket time remains empty. Never scale a daily total to fit a partial range.
Acceptance criteria
One contained lifetime interval wins even if daily buckets also exist.
Lifetime and daily values are never present in the same selected total.
With no lifetime interval, one or more fully contained UTC buckets are summed.
A bucket crossing the selected start or end is excluded in full.
A rolling 24-hour range with no full UTC bucket and no lifetime interval is unavailable with the specific reason.
UTC interval boundaries render correctly in UTC, CET, and CEST.
A timezone label change does not alter which absolute bucket interval is included.
No data is proportionally allocated.
Existing daily API parsing remains unchanged.
Required tests
At the reader snapshot seam add cases for lifetime precedence, daily-only fallback, overlapping sources, boundary-crossing buckets on both sides, no contained source, multiple buckets, and timezone/DST presentation. Assert method, total, interval, and reader-visible source wording.
Run:
swift test --filter UsageIntelligenceEngineTests
swift test --filter AnalyticsWorkspaceTests
Documentation
Update the daily-bucket fallback section in docs/MEASUREMENT-CONTRACT.md and the source wording in docs/PRODUCT-LANGUAGE.md.
Out of scope
Mixing sources to increase coverage.
Splitting or estimating partial buckets.
Changing Codex API parsing or storage.
Adding local-calendar daily buckets.
Token forecasts or limits.
Shared delivery contract
Implement only on the shared analytics-fixes branch. Reuse the branch and all earlier completed child-issue commits.
Keep this issue as one isolated commit whose message references the issue number.
Do not create another branch or pull request. Do not merge, tag, publish, or release.
Do not close the issue manually. The single final pull request will reference all child issues; they close only when that pull request is eventually merged.
Preserve unrelated working-tree changes. Do not reformat or refactor files outside this issue's scope.
Do not add a dependency, persistence format, feature flag, protocol, or abstraction unless the acceptance criteria cannot be met by the existing types and standard library.
Run the issue-specific checks below before committing. The final full-suite and integrated UI verification happen only after all child issues are implemented.
Before finishing, scan reader-visible strings touched by this issue and remove debug text, TODOs, implementation notes, and internal terminology not explicitly required by the product contract.
Handoff evidence
The implementing agent must report:
the commit hash and exact files changed;
the commands run and whether they passed;
each acceptance criterion as pass/fail;
any remaining risk or dependency, without expanding this issue's scope.
Parent: #46
Blocked by: #50
Parent user stories covered: 30–34
Outcome
When no valid lifetime-token interval can be formed for the selected range, Account Token Activity may fall back to complete UTC daily buckets. The fallback never mixes with lifetime-derived intervals, never counts a partial bucket, and presents the UTC interval boundaries in the Mac's current timezone without calling them local calendar days.
This issue retains the existing API-provided daily data as a weaker factual source. It does not change local Token Activity or add calendar-day presets.
Existing code to start from
AccountTokenActivityMethod.dailyBucketsanddailyAccountTokenActivity(...)inSources/CodexLimits/UsageIntelligenceEngine.swift.UsageSnapshot.tokenHistoryand the existing daily fallback tests inUsageIntelligenceEngineTests.swift.TokenActivityWorkspaceinMenuContentView.swift.UsageHistory.swift; reuse FoundationCalendar/fixed UTC only to model source intervals, not reader-facing labels.Source precedence
For one selected range, choose exactly one method:
[00:00Z, next 00:00Z)lies inside the selected range.No account readings in this range.A lifetime reading pair outside the selected range does not count as an available interval inside it. Precedence is evaluated for the selected range, not globally.
Presentation contract
Acceptance criteria
Required tests
At the reader snapshot seam add cases for lifetime precedence, daily-only fallback, overlapping sources, boundary-crossing buckets on both sides, no contained source, multiple buckets, and timezone/DST presentation. Assert method, total, interval, and reader-visible source wording.
Run:
swift test --filter UsageIntelligenceEngineTestsswift test --filter AnalyticsWorkspaceTestsDocumentation
Update the daily-bucket fallback section in
docs/MEASUREMENT-CONTRACT.mdand the source wording indocs/PRODUCT-LANGUAGE.md.Out of scope
Shared delivery contract
analytics-fixesbranch. Reuse the branch and all earlier completed child-issue commits.Handoff evidence
The implementing agent must report: