Parent: #46
Blocked by: #47 and #58
Parent user stories covered: 39–46, 51–55
Outcome
Runway reflects recent Account Movement from the rolling 24 hours ending at injected now, or the shorter latest compatible segment when less history is available. A long interval between two compatible readings remains factual and does not suppress guidance. Current Estimate uses exactly the same pace and latest account reading, so text and chart cannot contradict each other.
This issue fixes the reproduced production bug: one 8-hour-36-minute gap followed by more than 24 hours of dense compatible readings must not leave Runway or Current Estimate at Not enough data.
Existing code to start from
- Current sample filtering,
evidence(...), runway(...), chart projection(...), and guidance construction in Sources/CodexLimits/UsageIntelligenceEngine.swift.
- Current forecast behavior in
Sources/CodexLimits/ForecastEngine.swift.
- Current guidance/header and Usage Remaining chart in
Sources/CodexLimits/MenuContentView.swift.
- Persisted sample loading in
UsageHistory.swift and UsageMonitor.swift.
- Tests in
UsageIntelligenceEngineTests.swift, ForecastEngineTests.swift, AnalyticsWorkspaceTests.swift, and UsageMonitorHistoryTests.swift.
Trace all callers of the existing evidence/gap gate before editing it. Remove the six-hour veto only from current Runway/Current Estimate. Do not relax stricter historical Comparable Work or Usage-per-token comparability policies.
Recent Account Movement contract
- Evaluation interval is the exact rolling 24 hours ending at
now.
- Use the latest compatible allowance segment inside that interval.
- When the active allowance window or post-break segment is younger than 24 hours, use its shorter available portion.
- Two compatible readings in the latest segment are sufficient.
- Account Movement is the factual Usage Remaining decrease between compatible readings divided by their elapsed time.
- A long elapsed time is not, by itself, an invalidation.
- Do not invent intra-interval movement; the measured total movement across the interval is the evidence.
- An unchanged Usage Remaining value is valid zero pace and maps to
Limit should last through reset, not infinity or unavailable.
Allowance Break contract
No pace may cross a scheduled weekly reset, banked/emergency reset, known account correction, account partition change, incompatible Usage Remaining increase, or another existing explicit discontinuity.
After a break, one reading establishes the new segment and the second compatible reading restores Runway and Current Estimate. An old break must not poison later compatible samples.
Current Estimate contract
- Use exactly the same recent pace object/value and same latest current account reading as Runway.
- Project only Usage Remaining according to existing chart semantics.
- Keep Target and Past estimate unchanged.
- Preserve existing safety/status behavior unless it directly depends on the removed gap veto.
- If Runway says through reset, Current Estimate must not show exhaustion before reset.
Refresh failure contract
- A failed account refresh retains previously observed chart facts exactly as observed.
- Do not extend an old Actual line or token interval to failure time.
- Runway, Current Estimate, and Suggested Pace are not presented as current when no current account read is available.
- Show the specific account-source failure instead of standalone
Not enough data.
- A later successful current reading may restore guidance according to the same compatibility rules.
Specific unavailable reasons
At minimum distinguish:
- no current weekly allowance reading;
- fewer than two compatible readings in the latest segment;
- waiting for a second reading after reset/correction;
- account changed;
- current account source failed.
Do not expose internal policy names or generic Coverage/Confidence text in the primary header. Preserve detailed evidence in Evidence Details.
Acceptance criteria
Required regression fixture
Build a deterministic fixture matching the observed failure shape:
- one active 10,080-minute weekly window;
- one 8-hour-36-minute compatible sample interval;
- approximately 38 hours 51 minutes of subsequent compatible history;
- more than 24 hours of dense readings after the gap;
- maximum later gap approximately 20 minutes;
- pinned
now inside the same active window.
Assert that the old global maximum-gap policy would have found a gap above six hours, but the reader now returns available Runway and Current Estimate. Suggested Pace must remain independent.
Required tests
At the reader seam cover: two readings, less than 24 hours, exactly 24 hours, older samples excluded, long compatible interval, zero movement, each Allowance Break, one versus two post-break readings, through-reset consistency, failed refresh, recovery after failure, and the production regression fixture.
Add a consistency assertion that Runway and Current Estimate use one shared pace input/result rather than merely similar formatting.
Run:
swift test --filter UsageIntelligenceEngineTests
swift test --filter ForecastEngineTests
swift test --filter AnalyticsWorkspaceTests
Run UsageMonitorHistoryTests only if refresh retention/plumbing changes.
Documentation
Update current Runway, Current Estimate, Allowance Break, source failure, and unavailable-reason sections. Explicitly state that removing the six-hour veto applies to current guidance, not historical Comparable Work.
Out of scope
- Target or Past estimate changes.
- Suggested Pace formula beyond consuming its already-independent result.
- Historical Comparable Work, Allowance Intensity, Reference Baseline, or Usage-per-token policy changes.
- New forecast models, smoothing, interpolation, or model-specific limits.
- Release, merge, or PR creation.
Shared delivery contract
- Implement only on the shared
analytics-fixes branch and reuse all 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, release, or close the issue manually.
- Preserve unrelated working-tree changes and avoid unrelated refactors.
- Add no dependency, new persistence, feature flag, protocol, or speculative forecast abstraction.
- Run all focused checks above before committing. Final full-suite/integrated verification follows all child issues.
- Scan touched UI text for debug/TODO/internal policy leaks.
Handoff evidence
Report commit hash, exact files, commands/results, every acceptance criterion pass/fail, and remaining risk.
Parent: #46
Blocked by: #47 and #58
Parent user stories covered: 39–46, 51–55
Outcome
Runway reflects recent Account Movement from the rolling 24 hours ending at injected
now, or the shorter latest compatible segment when less history is available. A long interval between two compatible readings remains factual and does not suppress guidance. Current Estimate uses exactly the same pace and latest account reading, so text and chart cannot contradict each other.This issue fixes the reproduced production bug: one 8-hour-36-minute gap followed by more than 24 hours of dense compatible readings must not leave Runway or Current Estimate at
Not enough data.Existing code to start from
evidence(...),runway(...), chartprojection(...), and guidance construction inSources/CodexLimits/UsageIntelligenceEngine.swift.Sources/CodexLimits/ForecastEngine.swift.Sources/CodexLimits/MenuContentView.swift.UsageHistory.swiftandUsageMonitor.swift.UsageIntelligenceEngineTests.swift,ForecastEngineTests.swift,AnalyticsWorkspaceTests.swift, andUsageMonitorHistoryTests.swift.Trace all callers of the existing evidence/gap gate before editing it. Remove the six-hour veto only from current Runway/Current Estimate. Do not relax stricter historical Comparable Work or Usage-per-token comparability policies.
Recent Account Movement contract
now.Limit should last through reset, not infinity or unavailable.Allowance Break contract
No pace may cross a scheduled weekly reset, banked/emergency reset, known account correction, account partition change, incompatible Usage Remaining increase, or another existing explicit discontinuity.
After a break, one reading establishes the new segment and the second compatible reading restores Runway and Current Estimate. An old break must not poison later compatible samples.
Current Estimate contract
Refresh failure contract
Not enough data.Specific unavailable reasons
At minimum distinguish:
Do not expose internal policy names or generic Coverage/Confidence text in the primary header. Preserve detailed evidence in Evidence Details.
Acceptance criteria
Limit should last through reset.Not enough data.Required regression fixture
Build a deterministic fixture matching the observed failure shape:
nowinside the same active window.Assert that the old global maximum-gap policy would have found a gap above six hours, but the reader now returns available Runway and Current Estimate. Suggested Pace must remain independent.
Required tests
At the reader seam cover: two readings, less than 24 hours, exactly 24 hours, older samples excluded, long compatible interval, zero movement, each Allowance Break, one versus two post-break readings, through-reset consistency, failed refresh, recovery after failure, and the production regression fixture.
Add a consistency assertion that Runway and Current Estimate use one shared pace input/result rather than merely similar formatting.
Run:
swift test --filter UsageIntelligenceEngineTestsswift test --filter ForecastEngineTestsswift test --filter AnalyticsWorkspaceTestsRun
UsageMonitorHistoryTestsonly if refresh retention/plumbing changes.Documentation
Update current Runway, Current Estimate, Allowance Break, source failure, and unavailable-reason sections. Explicitly state that removing the six-hour veto applies to current guidance, not historical Comparable Work.
Out of scope
Shared delivery contract
analytics-fixesbranch and reuse all completed child-issue commits.Handoff evidence
Report commit hash, exact files, commands/results, every acceptance criterion pass/fail, and remaining risk.