Skip to content

Guidance: restore Runway and Current Estimate after long account gaps #59

Description

@thrr87

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

  • Two compatible readings produce Runway even with less than 24 hours of history.
  • A compatible interval longer than six hours remains usable.
  • Pace uses only the latest rolling 24 hours/shorter latest segment, not the whole-week average.
  • Reset, correction, account change, and incompatible increase split the pace.
  • Two compatible post-break readings restore Runway and Current Estimate.
  • Zero movement says Limit should last through reset.
  • Current Estimate consumes the exact same pace/latest reading as Runway.
  • Target and Past estimate behavior is unchanged.
  • Failed refresh preserves old observed charts without extension and withholds all current guidance with the source error.
  • Primary guidance shows results or specific reasons, never standalone Not enough data.
  • Historical Comparable Work and Usage-per-token comparability still use their existing stricter gates.
  • The real-shape 8h36m regression fixture produces available Runway and Current Estimate.

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    ready-for-agentReady for implementation by an agent

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions