Repository navigation
Description
aggregator(quota-extract): a lowercase or non-month reset month silently discards a pool's whole read — and an out-of-range day rolls over into an invented reset date
Summary
monthDayTime in pm-stack/aggregator/src/quota-extract.ts converts a quota-view reset read like resets Oct 30, 18:01 UTC into an ISO timestamp. Its callers capture the month with case-insensitive regexes (/resets (\w{3}) (\d{1,2}), (\d{2}:\d{2}) UTC/i), but monthDayTime looks the capture up in the case-sensitive MONTHS table. A lowercase (oct) or all-caps (OCT) month — or any other 3-letter word the \w{3} capture accepts (Foo) — makes MONTHS[mon] undefined, so Date.UTC(year, undefined, …) is NaN and d.toISOString() throws RangeError: Invalid time value. extractQuotaPools catches the throw per pool and treats the extractor as if it had matched nothing: the pool's entire read is discarded — including the usage percentage the extractor had already matched — and the pool renders with its shell "No current read" note.
Separately, an out-of-range day silently rolls over instead of failing: resets Oct 39, 18:01 UTC produces a reset of 2026-11-08 — an invented date, the exact outcome the module header says the extractors must never produce ("renders with its identity and a 'no current read' note instead of vanishing or inventing numbers").
Evidence (verified this run, main 318ca58)
Probe: real extractQuotaPools under Bun, minimal ChatGPT section, now = 2026-10-29T12:00:00Z:
| reset line in the quota view | Codex pool result |
|---|---|
7-day 42% used; resets Oct 30, 18:01 UTC |
window: 42%, resetsAt 2026-10-30T18:01:00.000Z ✅ |
7-day 42% used; resets oct 30, 18:01 UTC |
no windows, "No current read" shell ❌ |
7-day 42% used; resets OCT 30, 18:01 UTC |
no windows, "No current read" shell ❌ |
7-day 42% used; resets Foo 30, 18:01 UTC |
no windows, "No current read" shell ❌ |
7-day 42% used; resets Oct 39, 18:01 UTC |
window: 42%, resetsAt 2026-11-08T18:01:00.000Z (rolled over) ❌ |
File:line (main 318ca58):
pm-stack/aggregator/src/quota-extract.ts:17-30—MONTHStable, title-case keys only.pm-stack/aggregator/src/quota-extract.ts:33-40—monthDayTime:MONTHS[mon]unchecked;Date.UTC(...)withundefinedmonth →NaN;d.toISOString()throws. No day-range check, soDate.UTCrolls day 39 into the next month.pm-stack/aggregator/src/quota-extract.ts:113—extractCodexreset regex/resets (\w{3}) (\d{1,2}), (\d{2}:\d{2}) UTC/i.pm-stack/aggregator/src/quota-extract.ts:168—goWorkspacereset regex (same shape,/i) — affects both OpenCode Go pools.pm-stack/aggregator/src/quota-extract.ts:203—extractCommandCode"period ends" regex (same shape,/i).pm-stack/aggregator/src/quota-extract.ts:351-358—extractQuotaPoolswraps each extractor intry/catchand maps a throw toraw = null(the shell pool), so the failure is silent and total for that pool.
Why it matters
The quota view is a human-written document; month case in a dated read is exactly the kind of variation the fail-soft design is meant to absorb. Today one lowercase oct in the Codex or OpenCode Go section makes a healthy, current read vanish from the hub with no log line and no diagnosable difference from "the pattern stopped matching" — and a typo'd day invents a reset date the stewardship rotation decisions then trust. Four pools share the helper (Codex, OpenCode Go Personal, OpenCode Go Lab, Command Code), so one fix covers all of them.
Acceptance criteria
- Triage pins the rule for
monthDayTime(expected: normalize the captured month case-insensitively againstMONTHS; an unrecognized month token or an out-of-range day yields anullreset for that window — the matched percentage read is kept — rather than throwing or rolling over). - Regression tests in
pm-stack/aggregator/test/quota.test.ts(or the extractor's test home):oct/OCTresets produce the sameresetsAtasOct; a non-month token and day 39 produce the window withresetsAt: null; title-case behavior unchanged. - All four
monthDayTimecall sites (Codex, both Go workspaces, Command Code) covered by the fix. - No change to the per-pool try/catch in
extractQuotaPoolssemantics for genuinely unmatched sections (shell note still renders).
Filed by new-issue-creator-code-b (lane B), run 2026-10-29 03:50 CDT. Dedup: #1204 (extractor health reporting) is observability, not this correctness bug; #1626 (closed) was reset pairing by paragraph. No open or closed issue covers monthDayTime/MONTHS.
Activity
developing-today commentedon Oct 29, 2026
CODE-1083
dezren39 commentedon Oct 29, 2026
🤖 Agent note · filed
45 remaining items
dezren39 commentedon Nov 2, 2026
Task 5221 parked for 20 minutes because the canonical PR #4135 test check is still QUEUED (started 2026-11-02T02:50Z; fresh check 2026-11-02T05:40Z). CodeRabbit is neutral and Codex review on head bfc1e0b has no findings. The targeted quota test passed in a prior checkpoint (26 tests, 0 failures); no code changed in this claim.
Resume: after CI completes, freshly verify issue #2196 and PR #4135, inspect the diff and mergeability, and merge only if all required checks are green. PR: #4135 · branch: queue/5221-2196-monthdaytime-normalize-month-case.
dezren39 commentedon Nov 2, 2026
🤖 Agent note · picked up
Merge pull request #4135 from developing-today/queue/5221-2196-monthd…
dezren39 commentedon Nov 2, 2026
🤖 Agent note · done