Skip to content

feat(check): show quota reset timestamps in check output (#633)#634

Merged
ndycode merged 4 commits into
mainfrom
feat/633-check-reset-timestamps
Jul 23, 2026
Merged

feat(check): show quota reset timestamps in check output (#633)#634
ndycode merged 4 commits into
mainfrom
feat/633-check-reset-timestamps

Conversation

@ndycode

@ndycode ndycode commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Summary

  • Closes [feature] Display reset date at codex-multi-auth check #633: codex-multi-auth check now prints when each quota window resets, not just how much is left.
  • Reset display is scoped to check only. The dashboard, account menu, and forecast share these formatters and keep their existing width.
  • Missing or malformed reset timestamps degrade to today's output instead of failing the account check.

What Changed

check health lines now carry an absolute reset clock per window:

$ codex-multi-auth check
Checking 2 account(s) with quick check + live check...
Model probe: gpt-5.6-sol | prompt family gpt-5.2 | tool search yes | computer use yes
  ✓ Account 1 (...) | live session OK (5h 100%, resets 18:10 | 7d 93%, resets 13:50 on Jul 29)
  ✓ Account 2 (...) | live session OK (5h 100%, resets 18:35 | 7d 98%, resets 14:15 on Jul 29)
  • lib/quota-probe.ts — the private formatResetAt becomes the exported formatQuotaResetAt, and takes an injectable nowMs so the same-day branch is testable without freezing the clock. Behavior is otherwise unchanged.
  • lib/codex-manager/formatters/quota-formatters.ts — new opt-in CompactQuotaFormatOptions.showReset threaded through formatCompactQuotaSnapshot / formatAccountQuotaSummary. formatQuotaSnapshotForDashboard (the only check caller, despite the name) opts in.
  • lib/codex-manager/health-check.ts — passes the run's single now so every account line in one check shares a reference time.
  • Docs: new codex-multi-auth check section in docs/reference/commands.md documenting the format, the timezone, and the fallbacks; docs/features.md row updated.

Three deliberate deviations from the issue

  1. Window labels stay derived, not hardcoded. The issue proposes relabeling the second window 5h, but labels come from windowMinutes (quota-formatters.ts#L93-L102); quota is the fallback when the backend omits the window length. Hardcoding would print a wrong label for accounts whose headers lack it — which is exactly the case shown in the issue's "current output".

  2. Format is HH:MM / HH:MM on Mon DD, not Jul 29, 2026 1:50 PM. The repo already had a reset formatter with this shape, used by formatQuotaSnapshotLine. Adding the issue's 12-hour US-style variant would leave two reset formats in one product, and it costs ~30 extra columns on a line that already carries the account label twice over. Both windows are at most seven days, so the year is never ambiguous. Happy to switch if you'd rather match the issue literally.

  3. Scoped to check, not fix --live. fix --live prints a nearly identical live session OK (...) line via repair-commands.ts, but the issue asks for check. Left alone; easy follow-up if wanted.

One trap worth calling out

styleQuotaSummary matched segments against an anchored /^([0-9a-zA-Z]+)\s+(\d{1,3})%$/. Appending , resets ... fails that anchor, so every quota segment would have fallen through to the muted branch and silently lost its red/yellow/green tone. The pattern now captures the reset tail and mutes only that part, keeping the percentage toned. Covered by a regression test.

Validation

  • npm run lint
  • npm run typecheck
  • npm test — 5186 passed, 3 skipped (336 files)
  • npm test -- test/documentation.test.ts
  • npm run build

Unit — nine tests in test/codex-manager-formatters.test.ts: the opt-in boundary (default output unchanged), both windows rendering resets, same-day vs. next-week formatting, missing/NaN/negative/Infinity timestamps keeping the percentage, the showQuotaDetails: false path, and the styleQuotaSummary tone regression. Expectations derive from the same Intl calls the formatter uses, so they hold in any timezone rather than pinning one.

Command-level — two tests in test/codex-manager-cli.test.ts drive runCodexMultiAuthCli(["auth", "check"]) through the real runHealthCheck and the real formatter, mocking only fetchCodexQuotaSnapshot, and assert the actual printed line:

live session OK (5h 30%, resets 14:22 | 7d 90%, resets 11:22 on Jul 28)
live session OK (5h 30% | 7d 90%)                 <- no reset timestamp

Both were mutation-checked: flipping showReset to false makes the first fail, so they pin behavior rather than passing vacuously. Worth flagging that the pre-existing check assertions matched only stringContaining("live session OK") and would have passed whether or not reset times rendered at all — the formatter was covered, the wiring was not.

End-to-end — the real scripts/codex-multi-auth.js check binary was run against the compiled dist/, with a synthetic three-account pool in an isolated CODEX_MULTI_AUTH_DIR and only globalThis.fetch stubbed to return genuine Codex quota headers. Storage, health-check, formatter, and stdout all ran for real:

$ codex-multi-auth check
Checking 3 account(s) with quick check + live check...
Model probe: gpt-5.6-sol | prompt family gpt-5.2 | tool search yes | computer use yes
  ✓ Account 1 (one@example.com) | live session OK (5h 100%, resets 22:30 | 7d 93%, resets 20:30 on Jul 29)
  ✓ Account 2 (two@example.com) | live session OK (5h 38%, resets 20:15 | 7d 98%)
  ✓ Account 3 (three@example.com) | live session OK (quota 5%, resets 21:30 | 7d 12%)

Result: 3 Codex available | 0 signed in only | 0 need re-login

One run covers same-day vs. next-week formatting (acct 1), a window with no reset header (acct 2, 7d 98% stands alone), and the quota label fallback plus a malformed x-codex-secondary-reset-at: "not-a-real-date" (acct 3) — the bad timestamp is dropped and the percentage survives, with no probe failure. Reset input was exercised both as -reset-after-seconds and as an absolute ISO -reset-at.

The colour claim above was verified on this same binary by forcing isTTY. With the fix, 100% keeps the green quota tone and only the label and , resets … are dim. Rebuilding dist/ with the original anchored regex collapses the whole segment into a single dim wrapper and the green disappears:

fixed:   (<dim>5h</dim> <green>100%</green><dim>, resets 22:29</dim> | ...)
before:  (<dim>5h 100%, resets 22:30</dim> | <dim>7d 93%, resets 20:30 on Jul 29</dim>)

Still not done: a run against real credentials. This dev machine has no account pool (No accounts configured; no ~/.codex/multi-auth/openai-codex-accounts.json, no projects/ scope), and I did not import the local ~/.codex/auth.json token to manufacture one. So every result above uses synthetic headers. Worth one codex-multi-auth check on a real account before merging to confirm the live backend's header shape matches what this assumes.

Docs and Governance Checklist

  • README updated — not needed, no top-level capability change
  • docs/getting-started.md — onboarding flow unchanged
  • docs/features.md updated
  • docs/reference/commands.md updated
  • docs/upgrade.md — no migration behavior change
  • SECURITY.md / CONTRIBUTING.md reviewed — no impact; reset times are already-fetched quota metadata, no tokens or emails added to output

Risk and Rollback

  • Risk level: low. Presentation-only; no quota math, account selection, or auth behavior touched. resetAtMs was already parsed and cached. Blast radius is bounded by showReset defaulting to false — every non-check caller is byte-identical.
  • Rollback: revert the commit. No persisted state or config shape changes, so no migration concerns.

Additional Notes

Reset times are rendered in the local system timezone, documented in docs/reference/commands.md. Users who want a stable zone can set TZ.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro

note: greptile review for oc-chatgpt-multi-auth. cite files like lib/foo.ts:123. confirm regression tests + windows concurrency/token redaction coverage.

Greptile Summary

This PR adds quota reset times to the check command. The main changes are:

  • Opt-in reset timestamps for compact quota summaries.
  • Local-time formatting with safe fallback for missing timestamps.
  • Preserved percentage colors when reset details are present.
  • Formatter and command-level tests for the new output.
  • Updated command and feature documentation.

Confidence Score: 5/5

This looks safe to merge.

  • The calendar-day reference is refreshed for each account line.
  • Both normal and refreshed-session formatting paths avoid the stale run-level timestamp.
  • No blocking concurrency, Windows filesystem, or token-safety issue was found.
  • Tests cover the new formatter behavior and command wiring.

Important Files Changed

Filename Overview
lib/codex-manager/formatters/quota-formatters.ts Adds opt-in reset details while preserving compact output and percentage colors.
lib/quota-probe.ts Exports the reset formatter and adds an injectable reference time.
test/codex-manager-cli.test.ts Covers reset timestamps and missing reset metadata in command output.
test/codex-manager-formatters.test.ts Covers timestamp formatting, fallback behavior, opt-in output, and styled suffixes.

Reviews (4): Last reviewed commit: "fix(check): drop the stale reference tim..." | Re-trigger Greptile

Context used (4)

  • Context used - AGENTS.md (source)
  • Context used - lib/AGENTS.md (source)
  • Context used - test/AGENTS.md (source)
  • Context used - speak in lowercase, concise sentences. act like th... (source)

`codex-multi-auth check` printed the percentage left in each quota window
but never said when those windows reset, so users had to look the reset
time up elsewhere.

Append the absolute reset clock to each window in the `check` health line:

  live session OK (5h 100%, resets 18:10 | 7d 93%, resets 13:50 on Jul 29)

Reuses the existing reset formatter from `lib/quota-probe.ts` (exported as
`formatQuotaResetAt` and given an injectable `now` for deterministic tests)
rather than introducing a second reset format. Times are local, 24-hour,
and gain a day suffix once the reset is past midnight.

The reset suffix is opt-in via `CompactQuotaFormatOptions.showReset`, so
the width-constrained surfaces that share these formatters -- dashboard
rows, the account menu, and `forecast` -- keep their existing output.
`formatQuotaSnapshotForDashboard` is the only `check` caller and is the
sole place that opts in.

Also widen the `styleQuotaSummary` segment pattern to accept the reset
suffix. Without this the appended text fails the anchored percent match
and every quota segment silently falls back to the muted tone, losing the
red/yellow/green quota colouring.

A missing or malformed reset timestamp drops only the reset clause; the
percentage and the account check itself are unaffected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro
@chatgpt-codex-connector

Copy link
Copy Markdown

Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits.
Credits must be used to enable repository wide code reviews.

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor
📝 Walkthrough

Walkthrough

quota reset timestamps are now formatted locally, threaded through quota summaries, displayed by auth check, tested for missing values, and documented with showQuotaDetails behavior.

Changes

quota reset details

Layer / File(s) Summary
reset-time formatting contract
lib/quota-probe.ts, test/codex-manager-formatters.test.ts
formatQuotaResetAt supports deterministic same-day and cross-day formatting, while formatter tests cover invalid timestamps.
quota output reset rendering
lib/codex-manager/formatters/quota-formatters.ts
compact, account, dashboard, and styled quota summaries optionally include reset clauses while retaining percentages when reset data is unavailable.
auth check behavior and documentation
test/codex-manager-cli.test.ts, docs/reference/commands.md, docs/features.md
auth check tests verify reset output and omission rules; documentation describes live probing, formatting, and showQuotaDetails behavior.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant authCheck
  participant quotaProbe
  participant quotaFormatters
  participant terminal
  authCheck->>quotaProbe: live-probe stored account
  quotaProbe-->>authCheck: quota percentages and resetAtMs
  authCheck->>quotaFormatters: format account quota summary
  quotaFormatters-->>terminal: live session OK with reset details
Loading

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed the changes implement #633 by showing weekly and 5-hour reset timestamps, keeping failures soft on missing data, and adding formatter and cli tests.
Out of Scope Changes check ✅ Passed i do not see unrelated code paths; the docs, formatter, probe, health-check, and tests all support the reset timestamp feature.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed the title matches the required conventional-commit format and accurately summarizes the check output change.
Description check ✅ Passed the description follows the template sections and includes summary, changes, validation, docs, risk, and notes.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/633-check-reset-timestamps
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch feat/633-check-reset-timestamps

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread lib/codex-manager/health-check.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/reference/commands.md`:
- Around line 47-76: The command documentation incorrectly says check probes
only enabled accounts and omits the required release note. Update the
description to say it processes each configured/stored account, matching the
behavior in health-check.ts around the account iteration and re-enable path; add
an upgrade note describing the changed output and explicitly state whether any
npm scripts changed, keeping the documented flags and workflow consistent.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: cb630094-f90d-4922-bdf8-ddddfe0fa7f1

📥 Commits

Reviewing files that changed from the base of the PR and between 522baa2 and 95f8fdf.

📒 Files selected for processing (6)
  • docs/features.md
  • docs/reference/commands.md
  • lib/codex-manager/formatters/quota-formatters.ts
  • lib/codex-manager/health-check.ts
  • lib/quota-probe.ts
  • test/codex-manager-formatters.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (14)
docs/features.md

📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)

Update docs/features.md for capability coverage changes

Files:

  • docs/features.md
docs/**/*.md

📄 CodeRabbit inference engine (docs/STYLE_GUIDE.md)

docs/**/*.md: User-facing documentation should follow the page template: Title and one-line lead, Quick path commands, Core operational workflow, Troubleshooting or failure handling, and Related links
Use short sections and scan-friendly tables in documentation where they improve clarity
Prefer direct, actionable language in documentation
Use runnable command examples in documentation
Explain expected outcomes after critical commands in documentation
Keep terminology consistent with runtime names in documentation
Avoid speculative language when behavior is deterministic in documentation
Put the user problem in the first paragraph before implementation detail
Use descriptive page titles such as codex-multi-auth Features instead of generic titles on public docs
Do not repeat keyword lists in every section; search terms should appear only where they help a developer understand the page
Canonical command family is codex-multi-auth ...
Canonical runtime root is ~/.codex/multi-auth
Runtime rotation must be described as default-on unless the release policy changes
Legacy command/path references belong only in migration contexts in documentation
Compatibility aliases (codex multi auth, codex multi-auth, codex multiauth) belong only in command reference, troubleshooting, or migration contexts
Keep command flags aligned with runtime usage text in documentation
Avoid non-runnable command snippets in documentation
Avoid conflicting path guidance across documentation
Avoid legacy-first onboarding language in documentation

docs/**/*.md: Document Codex CLI multi-account capabilities, including account management, switching, health checks, recovery, project-scoped storage, runtime rotation, governance, and local bridge integrations.
Keep governance data local under ~/.codex/multi-auth; this is not a hosted multi-user service.
Usage ledger entries must be redacted and must not contain prompts or tokens.
Account pause and drain policies must be enforced at runt...

Files:

  • docs/features.md
  • docs/reference/commands.md
!{dist,dist/**}/**

📄 CodeRabbit inference engine (AGENTS.md)

Source code lives in root index.ts, lib/, and scripts/ directories; dist/ is generated output and should not be edited

Files:

  • docs/features.md
  • docs/reference/commands.md
  • test/codex-manager-formatters.test.ts
  • lib/quota-probe.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/formatters/quota-formatters.ts
docs/**

⚙️ CodeRabbit configuration file

keep README, SECURITY, and docs consistent with actual CLI flags and workflows. whenever behavior changes, require updated upgrade notes and mention new npm scripts.

Files:

  • docs/features.md
  • docs/reference/commands.md
docs/reference/**/*.md

📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)

Update relevant command/settings/path references in reference documentation when runtime changes occur

New flags/settings/paths must be reflected in docs/reference/*

Files:

  • docs/reference/commands.md
docs/reference/commands.md

📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)

Verify CLI flags documented in references match runtime parser/usage output

Files:

  • docs/reference/commands.md
test/**/*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js

Files:

  • test/codex-manager-formatters.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not use as any, @ts-ignore, or @ts-expect-error TypeScript escape hatches

Files:

  • test/codex-manager-formatters.test.ts
  • lib/quota-probe.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/formatters/quota-formatters.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode OAuth ports; use existing constants/helpers for port configuration

Files:

  • test/codex-manager-formatters.test.ts
  • lib/quota-probe.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/formatters/quota-formatters.ts
{scripts,test}/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Do not use bare recursive delete logic in Windows-sensitive scripts/tests without retry handling for transient EBUSY/EPERM/ENOTEMPTY errors

Files:

  • test/codex-manager-formatters.test.ts
**/*.{js,ts,mjs,cjs}

📄 CodeRabbit inference engine (README.md)

**/*.{js,ts,mjs,cjs}: Store multi-account OAuth credentials and configuration under ~/.codex/multi-auth/ directory structure with separate files for settings, accounts, flagged accounts, quota cache, runtime observability, usage ledger, policies, profiles, and budget guards
Allow override of the multi-auth root storage directory via the CODEX_MULTI_AUTH_DIR environment variable, defaulting to ~/.codex/multi-auth/ if not set
Implement runtime account rotation through a loopback-only local proxy that is enabled by default and can be disabled via CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0 environment variable
Respect opt-out flags for automatic Codex app bind installation (CODEX_MULTI_AUTH_APP_BIND_INSTALL=0) and launcher routing installation (CODEX_MULTI_AUTH_APP_LAUNCHER_INSTALL=0), performing these only on first CLI run when opted in
Use request timeout and stream stall timeout environment variable overrides (CODEX_AUTH_FETCH_TIMEOUT_MS and CODEX_AUTH_STREAM_STALL_TIMEOUT_MS) when making OAuth or API requests
Support stateful Responses background: true mode as an opt-in feature via CODEX_AUTH_BACKGROUND_RESPONSES=1 or backgroundResponses settings field only when explicitly enabled
Implement bounded outbound request budgets per session to prevent a single prompt from walking the entire account pool indefinitely
Disable whole-pool replay by default when every account is rate-limited and trigger short cooldowns instead of aggressive rotation after repeated cross-account 5xx error bursts
Stagger proactive account refresh operations to reduce background refresh bursts across the account pool
For the codex-multi-auth-codex wrapper, handle auth ... subcommands locally and forward all other commands to the official Codex CLI without modification
Implement account selection and switching with health-aware logic that considers account quota, cooldown state, and recent runtime metrics
Support project-scoped account storage under `~/.codex/multi-auth/...

Files:

  • test/codex-manager-formatters.test.ts
  • lib/quota-probe.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/formatters/quota-formatters.ts
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/codex-manager-formatters.test.ts
lib/**/*.ts

📄 CodeRabbit inference engine (lib/AGENTS.md)

lib/**/*.ts: All public exports should flow through lib/index.ts or documented package subpaths
Module dependencies must stay acyclic and follow the layering: types/constants → storage → accounts → runtime → manager/CLI; lower layers must never import from higher ones
Shared types/helpers must belong in the lower layer with higher layers re-exporting for surface compatibility instead of lower layers importing back from facades like lib/storage.ts
Never suppress type errors

Files:

  • lib/quota-probe.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/formatters/quota-formatters.ts
lib/**

⚙️ CodeRabbit configuration file

focus on auth rotation, windows filesystem IO, and concurrency. verify every change cites affected tests (vitest) and that new queues handle EBUSY/429 scenarios. check for logging that leaks tokens or emails.

Files:

  • lib/quota-probe.ts
  • lib/codex-manager/health-check.ts
  • lib/codex-manager/formatters/quota-formatters.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T10:26:51.543Z
Learning: Packaged Codex app integration must use reversible configuration and launcher binds rather than patching official app files.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T10:26:51.543Z
Learning: Usage ledger rows must remain local-only and must not contain prompts, tokens, authorization headers, raw account emails, or raw sensitive account IDs.
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.

Applied to files:

  • test/codex-manager-formatters.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.

Applied to files:

  • test/codex-manager-formatters.test.ts
🔇 Additional comments (5)
lib/quota-probe.ts (1)

269-295: LGTM!

Also applies to: 313-313

lib/codex-manager/formatters/quota-formatters.ts (1)

6-6: LGTM!

Also applies to: 33-55, 64-70, 104-166, 172-188

lib/codex-manager/health-check.ts (1)

147-151: LGTM!

Also applies to: 259-263

test/codex-manager-formatters.test.ts (1)

13-22: LGTM!

Also applies to: 160-291

docs/features.md (1)

17-17: LGTM!

Comment thread docs/reference/commands.md
ndycode and others added 2 commits July 23, 2026 19:21
The existing command-level coverage asserted only that the health line
contained "live session OK", so it passed whether or not the reset times
rendered at all. The formatter was covered; the wiring was not.

Add two tests that drive `runCodexMultiAuthCli(["auth", "check"])` through
the real health-check and formatter, mocking only the network probe, and
assert the printed line: one for both windows carrying a reset clock, one
for a window whose reset timestamp is absent or zero.

Verified these fail when `showReset` is flipped off, so they pin the
behavior rather than passing vacuously. The reset clock is local-timezone,
so the day suffix is matched loosely instead of pinned to one zone.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro
The new `check` section claimed it live-probes "each enabled account".
It does neither part of that: health-check.ts iterates every stored
account, and re-enables a disabled one whose token is still usable
(`account.enabled = true`). `fix` is the command that skips disabled
accounts, which is where the wrong wording came from.

Reported by CodeRabbit on PR #634.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/reference/commands.md (1)

64-69: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

document the locale-dependent reset date shape

docs/reference/commands.md:67 says resets print as HH:MM on Mon DD, but lib/quota-probe.ts:294 and lib/runtime/quota-headers.ts:143 use toLocaleDateString(undefined, { month: "short", day: "2-digit" }), so month text and ordering follow the host locale outside en-US. update the docs or pin en-US in both formatter path and lib/quota-probe.ts:294. also add a regression test for non-US locales if this is an emitted output contract.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/reference/commands.md` around lines 64 - 69, The reset-time
documentation incorrectly guarantees an English `Mon DD` shape while formatting
uses the host locale. Update the reset-time section in commands.md to describe
locale-dependent month text and ordering, and add a regression test covering a
non-US locale for the emitted reset output.

Source: Path instructions

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@test/codex-manager-cli.test.ts`:
- Around line 3287-3333: Update the test case around runCodexMultiAuthCli to
freeze Vitest’s clock using the captured now value, provision a second account
whose output crosses a day boundary, and configure its quota data as needed.
Assert the check output for both accounts, verifying each line uses the same
frozen reference time for reset-time formatting; restore the clock after the
test.
- Around line 3354-3369: Update the test case around
quotaProbeMocks.fetchCodexQuotaSnapshot and runCodexMultiAuthCli to provide
primary with a valid resetAtMs while keeping secondary.resetAtMs at 0. Change
the assertion to require mixed output: primary’s reset clause must be present,
while secondary’s reset clause remains omitted.

---

Outside diff comments:
In `@docs/reference/commands.md`:
- Around line 64-69: The reset-time documentation incorrectly guarantees an
English `Mon DD` shape while formatting uses the host locale. Update the
reset-time section in commands.md to describe locale-dependent month text and
ordering, and add a regression test covering a non-US locale for the emitted
reset output.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 45088b26-132a-4623-b251-435d71dc9f80

📥 Commits

Reviewing files that changed from the base of the PR and between 95f8fdf and 08fd208.

📒 Files selected for processing (2)
  • docs/reference/commands.md
  • test/codex-manager-cli.test.ts
📜 Review details
⏰ Context from checks skipped due to timeout. (1)
  • GitHub Check: Greptile Review
🧰 Additional context used
📓 Path-based instructions (12)
docs/reference/**/*.md

📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)

Update relevant command/settings/path references in reference documentation when runtime changes occur

New flags/settings/paths must be reflected in docs/reference/*

Files:

  • docs/reference/commands.md
docs/reference/commands.md

📄 CodeRabbit inference engine (docs/DOCUMENTATION.md)

Verify CLI flags documented in references match runtime parser/usage output

Files:

  • docs/reference/commands.md
docs/**/*.md

📄 CodeRabbit inference engine (docs/STYLE_GUIDE.md)

docs/**/*.md: User-facing documentation should follow the page template: Title and one-line lead, Quick path commands, Core operational workflow, Troubleshooting or failure handling, and Related links
Use short sections and scan-friendly tables in documentation where they improve clarity
Prefer direct, actionable language in documentation
Use runnable command examples in documentation
Explain expected outcomes after critical commands in documentation
Keep terminology consistent with runtime names in documentation
Avoid speculative language when behavior is deterministic in documentation
Put the user problem in the first paragraph before implementation detail
Use descriptive page titles such as codex-multi-auth Features instead of generic titles on public docs
Do not repeat keyword lists in every section; search terms should appear only where they help a developer understand the page
Canonical command family is codex-multi-auth ...
Canonical runtime root is ~/.codex/multi-auth
Runtime rotation must be described as default-on unless the release policy changes
Legacy command/path references belong only in migration contexts in documentation
Compatibility aliases (codex multi auth, codex multi-auth, codex multiauth) belong only in command reference, troubleshooting, or migration contexts
Keep command flags aligned with runtime usage text in documentation
Avoid non-runnable command snippets in documentation
Avoid conflicting path guidance across documentation
Avoid legacy-first onboarding language in documentation

Document the complete codex-multi-auth capability surface, including account management, forecasting, runtime rotation, governance, recovery, project-scoped storage, terminal workflows, bridge integrations, and optional plugin-host functionality.

Files:

  • docs/reference/commands.md
!{dist,dist/**}/**

📄 CodeRabbit inference engine (AGENTS.md)

Source code lives in root index.ts, lib/, and scripts/ directories; dist/ is generated output and should not be edited

Files:

  • docs/reference/commands.md
  • test/codex-manager-cli.test.ts
docs/**

⚙️ CodeRabbit configuration file

keep README, SECURITY, and docs consistent with actual CLI flags and workflows. whenever behavior changes, require updated upgrade notes and mention new npm scripts.

Files:

  • docs/reference/commands.md
test/**/*.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

test/**/*.test.ts: Write Vitest test suites with globals enabled (describe, it, expect)
Maintain 80%+ coverage threshold across statements, branches, functions, and lines
Use removeWithRetry() for Windows filesystem cleanup instead of bare fs.rm to handle EBUSY, EPERM, and ENOTEMPTY errors
Do not rely on dist/ in tests; use source files instead
Do not skip tests without justification
Relax lint rules for test files as configured in eslint.config.js

Files:

  • test/codex-manager-cli.test.ts
test/**/codex-manager-cli.test.ts

📄 CodeRabbit inference engine (test/AGENTS.md)

Test CLI settings management across 5 panels with Q cancel handling in codex-manager-cli.test.ts

Files:

  • test/codex-manager-cli.test.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

Do not use as any, @ts-ignore, or @ts-expect-error TypeScript escape hatches

Files:

  • test/codex-manager-cli.test.ts
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Do not hardcode OAuth ports; use existing constants/helpers for port configuration

Files:

  • test/codex-manager-cli.test.ts
{scripts,test}/**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

Do not use bare recursive delete logic in Windows-sensitive scripts/tests without retry handling for transient EBUSY/EPERM/ENOTEMPTY errors

Files:

  • test/codex-manager-cli.test.ts
**/*.{js,ts,mjs,cjs}

📄 CodeRabbit inference engine (README.md)

**/*.{js,ts,mjs,cjs}: Store multi-account OAuth credentials and configuration under ~/.codex/multi-auth/ directory structure with separate files for settings, accounts, flagged accounts, quota cache, runtime observability, usage ledger, policies, profiles, and budget guards
Allow override of the multi-auth root storage directory via the CODEX_MULTI_AUTH_DIR environment variable, defaulting to ~/.codex/multi-auth/ if not set
Implement runtime account rotation through a loopback-only local proxy that is enabled by default and can be disabled via CODEX_MULTI_AUTH_RUNTIME_ROTATION_PROXY=0 environment variable
Respect opt-out flags for automatic Codex app bind installation (CODEX_MULTI_AUTH_APP_BIND_INSTALL=0) and launcher routing installation (CODEX_MULTI_AUTH_APP_LAUNCHER_INSTALL=0), performing these only on first CLI run when opted in
Use request timeout and stream stall timeout environment variable overrides (CODEX_AUTH_FETCH_TIMEOUT_MS and CODEX_AUTH_STREAM_STALL_TIMEOUT_MS) when making OAuth or API requests
Support stateful Responses background: true mode as an opt-in feature via CODEX_AUTH_BACKGROUND_RESPONSES=1 or backgroundResponses settings field only when explicitly enabled
Implement bounded outbound request budgets per session to prevent a single prompt from walking the entire account pool indefinitely
Disable whole-pool replay by default when every account is rate-limited and trigger short cooldowns instead of aggressive rotation after repeated cross-account 5xx error bursts
Stagger proactive account refresh operations to reduce background refresh bursts across the account pool
For the codex-multi-auth-codex wrapper, handle auth ... subcommands locally and forward all other commands to the official Codex CLI without modification
Implement account selection and switching with health-aware logic that considers account quota, cooldown state, and recent runtime metrics
Support project-scoped account storage under `~/.codex/multi-auth/...

Files:

  • test/codex-manager-cli.test.ts
test/**

⚙️ CodeRabbit configuration file

tests must stay deterministic and use vitest. demand regression cases that reproduce concurrency bugs, token refresh races, and windows filesystem behavior. reject changes that mock real secrets or skip assertions.

Files:

  • test/codex-manager-cli.test.ts
🧠 Learnings (3)
📓 Common learnings
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Keep all governance and account data local under `~/.codex/multi-auth`; do not implement it as a hosted multi-user service.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Runtime account rotation must be local-only and default-on for forwarded official Codex Responses/model traffic.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Apply `evaluateRuntimePolicy` before account selection so pause/drain settings, budgets, routing profiles, and capability checks are enforced at runtime.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Per-invocation account force-pins must be ephemeral, fail-hard, and must never modify the persisted `switch` pin.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Keep wrapper-launched CLI provider configuration isolated using a shadow `CODEX_HOME`; do not alter normal official Codex state.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Provide reversible desktop-app binding and launcher routing without patching official Codex application files.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Record usage as redacted local ledger rows and summaries; never store prompts or tokens.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Store bridge client tokens only as hashes and safe prefixes; plain tokens must use the `cma_local_*` form and must not be re-exposed after creation.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Support bridge token lifecycle operations for creation, listing, rotation, and revocation without exposing old secrets.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Use canonical local storage under `~/.codex/multi-auth`, with Storage V3 migrations from older layouts and recovery support for interrupted or partially applied writes.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Support project-scoped account pools while sharing identity across linked worktrees of the same repository.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Synchronize the selected account into official `~/.codex` authentication files when plain Codex use requires it.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Use browser-first OAuth with device-auth and manual callback-paste fallbacks for remote, headless, non-browser, or non-TTY environments.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Provide fast and deep health checks, quota reset visibility, flagged-account verification, safe repair, diagnostics, and backup restore workflows.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:10.485Z
Learning: Expose deterministic CLI and integration entry points for account switching, forecasting, reporting, runtime status, bridge operations, history, and wrapper launching.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:18.390Z
Learning: `codex-multi-auth` is the primary account-manager CLI; compatibility aliases and wrapper entrypoints must preserve their documented routing and forwarding behavior.
Learnt from: CR
Repo: ndycode/codex-multi-auth

Timestamp: 2026-07-23T11:38:18.390Z
Learning: The documented public command, flag, JSON, CSV, exit-code, and non-TTY behaviors are compatibility surfaces and should remain stable.
📚 Learning: 2026-06-04T06:14:18.093Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/scheduling-strategy-config.test.ts:1-1
Timestamp: 2026-06-04T06:14:18.093Z
Learning: In ndycode/codex-multi-auth, do not flag explicit imports from "vitest" (e.g., describe, it, expect, beforeEach/afterEach, etc.) in test files as issues—even if the Vitest config sets `globals: true`. The repo’s established convention is to keep these imports for consistency with neighboring tests; removing them would make files outliers.

Applied to files:

  • test/codex-manager-cli.test.ts
📚 Learning: 2026-06-04T06:14:24.975Z
Learnt from: ndycode
Repo: ndycode/codex-multi-auth PR: 510
File: test/runtime-rotation-proxy.test.ts:2478-2491
Timestamp: 2026-06-04T06:14:24.975Z
Learning: In ndycode/codex-multi-auth test files (e.g. `test/*.test.ts`), when creating V3 storage fixtures for accounts, it’s an intentional convention to use `as never` for deliberately minimal stored-account objects that only include `refreshToken`, `addedAt`, and `lastUsed`. Do not treat `as never` here as a type-safety problem: optional/other fields are expected to be populated by the runtime during execution, and the cast is used solely to keep the fixture minimal and consistent across existing tests.

Applied to files:

  • test/codex-manager-cli.test.ts
🔇 Additional comments (1)
docs/reference/commands.md (1)

47-81: add the required upgrade note

docs/reference/commands.md:47 documents a user-visible check output change, but this changed section still has no upgrade note or statement about npm scripts. this is the same unresolved requirement from the prior review; add the note or link to the existing release note and explicitly state whether npm scripts changed.

as per coding guidelines, behavior changes require updated upgrade notes and mention of new npm scripts. as per path instructions, docs must stay consistent with actual cli workflows.

Sources: Coding guidelines, Path instructions

Comment on lines +3287 to +3333
it("check prints the reset time for each quota window", async () => {
const now = Date.now();
storageMocks.loadAccounts.mockResolvedValueOnce({
version: 3,
activeIndex: 0,
activeIndexByFamily: { codex: 0 },
accounts: [
{
accountId: "acc_reset",
email: "reset@example.com",
refreshToken: "refresh-reset",
accessToken: "access-reset",
expiresAt: now + 60 * 60 * 1000,
addedAt: now - 1_000,
lastUsed: now - 1_000,
enabled: true,
},
],
});
quotaProbeMocks.fetchCodexQuotaSnapshot.mockResolvedValueOnce({
status: 200,
model: DEFAULT_MODEL,
primary: {
usedPercent: 70,
windowMinutes: 300,
resetAtMs: now + 3 * 60 * 60 * 1000,
},
secondary: {
usedPercent: 10,
windowMinutes: 10080,
resetAtMs: now + 5 * 24 * 60 * 60 * 1000,
},
});
const logSpy = silenceConsole("log");
const { runCodexMultiAuthCli } = await import("../lib/codex-manager.js");

const exitCode = await runCodexMultiAuthCli(["auth", "check"]);
expect(exitCode).toBe(0);

const line = logSpy.mock.calls
.map((call) => String(call[0]))
.find((text) => text.includes("live session OK"));
expect(line).toBeDefined();
expect(line).toMatch(
/live session OK \(5h 30%, resets \d{2}:\d{2}( on \w{3} \d{2})? \| 7d 90%, resets \d{2}:\d{2} on \w{3} \d{2}\)/,
);
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

add a multi-account, fixed-clock regression

test/codex-manager-cli.test.ts:3288 captures the wall clock but provisions only one account. that cannot catch a check implementation using different reference times for different output lines, which is part of this pr’s contract. freeze time with vitest and add a second account near a day boundary; assert both lines use the same reference-time behavior.

as per path instructions, tests must stay deterministic and include regression coverage for changed behavior.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/codex-manager-cli.test.ts` around lines 3287 - 3333, Update the test
case around runCodexMultiAuthCli to freeze Vitest’s clock using the captured now
value, provision a second account whose output crosses a day boundary, and
configure its quota data as needed. Assert the check output for both accounts,
verifying each line uses the same frozen reference time for reset-time
formatting; restore the clock after the test.

Source: Path instructions

Comment on lines +3354 to +3369
quotaProbeMocks.fetchCodexQuotaSnapshot.mockResolvedValueOnce({
status: 200,
model: DEFAULT_MODEL,
primary: { usedPercent: 70, windowMinutes: 300 },
secondary: { usedPercent: 10, windowMinutes: 10080, resetAtMs: 0 },
});
const logSpy = silenceConsole("log");
const { runCodexMultiAuthCli } = await import("../lib/codex-manager.js");

const exitCode = await runCodexMultiAuthCli(["auth", "check"]);
expect(exitCode).toBe(0);

const line = logSpy.mock.calls
.map((call) => String(call[0]))
.find((text) => text.includes("live session OK"));
expect(line).toContain("live session OK (5h 30% | 7d 90%)");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

exercise one missing reset independently

test/codex-manager-cli.test.ts:3357 omits the reset timestamp from primary as well as setting secondary.resetAtMs to 0. the test therefore never proves that one window keeps its reset clause while the other omits it. give primary a valid reset timestamp and assert the mixed output.

as per path instructions, tests must demand regression cases for the changed behavior.

proposed test adjustment
-			primary: { usedPercent: 70, windowMinutes: 300 },
+			primary: {
+				usedPercent: 70,
+				windowMinutes: 300,
+				resetAtMs: now + 60 * 60 * 1000,
+			},
 			secondary: { usedPercent: 10, windowMinutes: 10080, resetAtMs: 0 },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/codex-manager-cli.test.ts` around lines 3354 - 3369, Update the test
case around quotaProbeMocks.fetchCodexQuotaSnapshot and runCodexMultiAuthCli to
provide primary with a valid resetAtMs while keeping secondary.resetAtMs at 0.
Change the assertion to require mixed output: primary’s reset clause must be
present, while secondary’s reset clause remains omitted.

Source: Path instructions

…dates

Two review findings from PR #634, both valid.

Greptile: health-check captures `now` once, before the sequential network
probes, so threading it into the formatter made the "is today" decision go
stale on a run that crosses local midnight. It also silently moved
`isQuotaCacheEntryExhausted(snapshot, now)` from call time to run-start
time, which was never intended. Reverting health-check.ts to main fixes
both -- the formatter's `now` already defaults to `Date.now()` per call,
and it stays injectable for tests.

CodeRabbit: `formatQuotaResetAt` builds the date half with
`toLocaleDateString(undefined, ...)`, so month text and field order follow
the host locale. Documenting the output as `HH:MM on Mon DD` claimed a
stability the formatter does not provide. The docs now say the date shape
is locale-dependent and label the example as en-US.

The same assumption was baked into the new command-level regex
(`\w{3} \d{2}`), which matches only en-US -- it fails on de-DE (`29. Juli`),
ja-JP, fr-FR, and en-GB (`29 Jul`). That assertion is now structural.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Xetj6c94ZqD7a5n7G9M5Ro
@ndycode

ndycode commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

Addressed in 5f3b37e. Both bots found something real.

Greptile — stale calendar-day reference (health-check.ts:147): valid, fixed.

Correct, and the impact was wider than flagged. now is captured at health-check.ts:86, before the sequential network probes, so threading it into the formatter made the "is today" decision go stale on a run crossing local midnight. It also moved isQuotaCacheEntryExhausted(snapshot, now) from call time to run-start time — an unintended behavior change, since formatQuotaSnapshotForDashboard previously let now default per call.

lib/codex-manager/health-check.ts is reverted to main and is no longer part of this diff. The formatter's now still defaults to Date.now() per call and stays injectable for tests. My "one reference time per run" rationale was simply wrong — consistency across midnight is the thing at stake, not a property worth preserving.

CodeRabbit — locale-dependent reset date: valid, fixed (docs only).

formatQuotaResetAt builds the date with toLocaleDateString(undefined, { month: "short", day: "2-digit" }), so documenting HH:MM on Mon DD claimed a stability the formatter does not provide. Docs now state the date text and field order follow the host locale, with the example labelled en-US.

The same assumption was in my new command-level regex, and it was worse than a docs nit — \w{3} \d{2} matches only en-US:

locale rendered old regex
en-US Jul 29 match
en-GB 29 Jul fail
de-DE 29. Juli fail
fr-FR 29 juil. fail
ja-JP 7月29日 fail

That assertion is now structural (/7d 90%, resets \d{2}:\d{2} on \S/). I did not pin en-US in the formatter — that would change formatQuotaSnapshotLine output for every existing caller, which is outside this PR.

Caveat on the "non-US locale regression test" ask: I could not execute one. Node ignores LC_ALL/LANG on Windows (Intl.DateTimeFormat().resolvedOptions().locale stays en-US), so a locale-forced suite run here would be a false green. The table above comes from calling the formatter with explicit locales. A genuine locale-matrix run needs Linux CI.

Declined: the docs/upgrade.md note and npm-script statement.

docs/upgrade.md is scoped to migrations — bin migration, runtime-root moves, state-format changes. This PR changes one line of terminal output; there is nothing to migrate, no persisted state or config shape touched, and no npm scripts added or changed. The repo's own PR template scopes that checklist item to "if migration behavior changed". Happy to add a line if you'd rather have it, but it looked like an org-level rule rather than this repo's convention.

Verification after the changes: npm run typecheck, npm run lint, npm test (5186 passed, 3 skipped), npm run build — all green locally.

Note for anyone reading the checks: GitHub Actions has never run in this repo. 243 runs created, 0 ever completed, oldest stuck since 2026-05-10; every push/PR workflow shows zero runs while Dependabot's sit queued indefinitely. mergeStateStatus: CLEAN here means "no required checks configured", not "CI passed". That is a repo-wide condition unrelated to this PR, but it means nothing on this branch has been CI-verified.

@ndycode
ndycode merged commit 7298fa5 into main Jul 23, 2026
2 checks passed
@ndycode
ndycode deleted the feat/633-check-reset-timestamps branch July 23, 2026 13:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feature] Display reset date at codex-multi-auth check

1 participant