Skip to content

aggregator(quota-extract): dateTimeCDT hardcodes UTC-5 year-round — winter (CST) reset reads render an hour early, and Meta's reset-passed check fires an hour early too #2197

Closed

Description

@dezren39

aggregator(quota-extract): dateTimeCDT hardcodes UTC-5 year-round — winter (CST) reset reads render an hour early

Summary

dateTimeCDT in pm-stack/aggregator/src/quota-extract.ts:43-46 converts a quota-view dated read (2026-12-16 + 14:00 CDT) into an ISO timestamp by stamping a fixed -05:00 offset:

/** "2026-10-28" + "14:00" CDT (UTC-5) -> ISO. */
function dateTimeCDT(date: string, hhmm: string): string {
  return `${date}T${hhmm}:00-05:00`;
}

US Central Time is UTC-5 only during daylight saving (CDT, mid-March to early November). For the rest of the year it is CST, UTC-6. The quota view's dated reads are Central wall-clock times (the stewardship writer stamps them "CDT" by convention — every extractor pattern matches the literal CDT), so for any read dated in the CST months the extractor emits a resetsAt one hour earlier than the wall time it claims to encode. The same codebase already knows the right model: pm-stack/aggregator/src/derive.ts:473-480 has "Calendar helpers (America/Chicago — Drew's timezone)" built on Intl.DateTimeFormat with timeZone: "America/Chicago".

Evidence (verified this run, main 318ca58)

Probe: real extractQuotaPools under Bun, minimal Claude section, now = 2026-12-10T12:00:00Z:

  • Input: weekly 68% used, weekly reset Wed 2026-12-16 14:00 CDT
  • Emitted window: resetsAt: "2026-12-16T14:00:00-05:00" = 19:00Z
  • Ground truth: 2026-12-16 falls in CST — Intl.DateTimeFormat with timeZone: "America/Chicago" reports CST for that date, and 14:00 Central wall time = 2026-12-16T20:00:00.000Z. The emitted reset is one hour early.

Call sites (all Central-time reads, all affected):

  • pm-stack/aggregator/src/quota-extract.ts:100 — extractClaude: weekly reset → the window's resetsAt.
  • pm-stack/aggregator/src/quota-extract.ts:132 — extractMeta: weekly reset → resetsAt and wallLiftsAt; extractMeta also compares now >= Date.parse(resetIso) (line 134) to decide the window has reset, so a winter wall lifts / window clears an hour early in the model, not just in display.
  • pm-stack/aggregator/src/quota-extract.ts:189 — extractClinePass: the measured-read base instant from which both relative resets (weekly/monthly) are computed — a winter ClinePass read shifts both derived resets by an hour.

Why it matters

Reset and wall-lift times drive the hub's pool state (poolState, the "walled" rendering, burn/rotation decisions in stewardship). For roughly 4.5 months of the year every Claude, Meta, and ClinePass reset derived from a dated read is an hour off — pools shown as reset (or walls shown as lifted) an hour before they actually are. October reads are correct only by accident of the calendar; the first winter dated read (the quota view is already accumulating late-October reads) silently inherits the error, and no test pins a CST-month date.

Acceptance criteria

  • Triage pins the conversion rule (expected: interpret the stamped wall time in America/Chicago — DST-aware, matching derive.ts's calendar helpers — rather than a fixed -05:00; or, if the fixed-offset convention is deliberately kept, rename/document it so the winter error is a stated choice, not an accident).
  • Regression tests in pm-stack/aggregator/test/quota.test.ts: a December/January dated reset read yields the UTC-6 instant (e.g. 2026-12-16 14:00 → 2026-12-16T20:00:00.000Z); an October read still yields UTC-5; a read on a DST transition date is covered or explicitly ruled out of scope on the issue.
  • All three call sites covered (Claude reset, Meta reset/wallLiftsAt + the reset-passed comparison, ClinePass measured base).
  • No behavior change for reads dated inside CDT.

Filed by new-issue-creator-code-b (lane B), run 2026-10-29 03:50 CDT. Dedup: searches for dateTimeCDT, "CDT offset", "daylight" (open+closed) found no covering issue; #1541 (closed) was quota-current future-skew, a different aggregator time bug.

Activity

  1. added
    kind/bugSomething isn't working (prefixed form of the classic bug label)
    task/triageQueue packet kind: verify, reproduce, and route this item
    on Oct 29, 2026
  2. developing-today commented on Oct 29, 2026

    @developing-today
    Contributor
  3. added
    source/creatorFiled by the new-issue-creator job
    priority/normalOrdinary priority (the default)
    queue/queuedHas a queued task in the Supabase agent queue
    effort/xsTrivial: expected under 30 minutes of work
    app/aggregatorPackage/app: aggregator (pm-stack in this repo)
    on Oct 29, 2026
  4. dezren39 commented on Oct 29, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · filed

    • Agent: new-issue-creator job, lane B (new-issue-creator-code-b)
    • Session / ID: cron new-issue-creator-code-b, run 2026-10-29 03:50 CDT
    • Found via: filed this run
    • Task: Filed after verifying on main 318ca58 with the real extractQuotaPools under Bun (sandbox probe /tmp/probe-laneB-quota/probe2.ts): a Claude read "weekly reset Wed 2026-12-16 14:00 CDT" yields resetsAt 2026-12-16T14:00:00-05:00 (19:00Z), but 2026-12-16 is CST in America/Chicago (Intl confirms), so 14:00 Central = 20:00Z — dateTimeCDT's fixed -05:00 renders winter resets an hour early at all three call sites (Claude, Meta reset/wallLiftsAt + reset-passed check, ClinePass base). Enqueued as a triage packet for the repo-health-code-pilot queue.
    • Expectation: effort/xs — triage pins the conversion rule (expected: DST-aware America/Chicago, matching derive.ts's calendar helpers), then routes a small_fix.
    • Links: evidence body in goal hidden_files/issue-code-quotaextract-cdt-offset-body.md; probe /tmp/probe-laneB-quota/probe2.ts
  5. added
    work/assignedQueue worker lifecycle state
    queue/claimedQueue worker lifecycle state
    and removed on Nov 1, 2026
  6. 59 remaining items

  7. added
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    status/parkedDeliberately paused with a recorded resume condition
    and removed
    queue/claimedQueue worker lifecycle state
    on Nov 2, 2026
  8. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · parked

  9. added
    queue/claimedQueue worker lifecycle state
    and removed
    status/parkedDeliberately paused with a recorded resume condition
    queue/parkedQueue task is parked (waiting on CI, time, or an event)
    on Nov 2, 2026
  10. added a commit that references this issue on Nov 2, 2026
  11. dezren39 commented on Nov 2, 2026

    @dezren39
    MemberAuthor

    🤖 Agent note · done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

app/aggregatorPackage/app: aggregator (pm-stack in this repo)app/pm-stackpm-stack (Pad/Grist) in developing-today/codeeffort/xsTrivial: expected under 30 minutes of workkind/bugSomething isn't working (prefixed form of the classic bug label)priority/normalOrdinary priority (the default)source/creatorFiled by the new-issue-creator jobtask/triageQueue packet kind: verify, reproduce, and route this item

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions