feat: add codexbar guard — quota-aware exit code to gate automation - #2237
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d2781f1d53
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let env = tokenContext.environment( | ||
| base: ProcessInfo.processInfo.environment, | ||
| provider: provider, | ||
| account: nil) |
There was a problem hiding this comment.
Resolve token accounts before fetching guard usage
When the selected provider is configured only through CodexBar token accounts (for example Claude stored session/OAuth credentials or Zai/OpenAI API-key accounts), this nil account means ProviderEnvironmentResolver never injects the active account token, while runUsage first calls resolvedAccounts and passes that account into the same environment/settings path. In that common configuration codexbar guard --provider <id> reports unknown/exit 2 (or fail-opens) even though codexbar usage can fetch the quota, so the automation gate is unreliable for stored-account users.
Useful? React with 👍 / 👎.
| let rateWindow: RateWindow? = window == .session ? usage.primary : usage.secondary | ||
| guard let rateWindow else { return nil } | ||
| return 100 - rateWindow.usedPercent |
There was a problem hiding this comment.
Ignore synthetic session placeholders in guard decisions
For Claude web accounts with five_hour: null, the core fetcher intentionally emits primary as a synthetic 0%-used placeholder (isSyntheticPlaceholder) so UI metrics drop it and use the real weekly lane instead. This guard path treats that placeholder as a real session window and returns 100% remaining, so the default codexbar guard --provider claude can exit 0 for weekly-only or exhausted accounts because the phantom session lane passes the headroom check.
Useful? React with 👍 / 👎.
|
Codex review: needs real behavior proof before merge. Reviewed July 17, 2026, 3:37 PM ET / 19:37 UTC. Summary Reproducibility: yes. for the timeout defect: source inspection identifies Claude auto mode where a web attempt can consume the same deadline reserved for the outer guard race, preventing the CLI fallback. Real quota proof remains incomplete because the supplied terminal run has no configured account. Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Risk before merge
Maintainer options:
Next step before merge
Maintainer decision needed
Security Review findings
Review detailsBest possible solution: Reserve part of the guard deadline for provider fallbacks, add a regression test for a timed-out web attempt followed by a successful CLI fallback, then land only after redacted configured-account proof shows safe and blocked decisions under the maintainer-approved CLI contract. Do we have a high-confidence way to reproduce the issue? Yes, for the timeout defect: source inspection identifies Claude auto mode where a web attempt can consume the same deadline reserved for the outer guard race, preventing the CLI fallback. Real quota proof remains incomplete because the supplied terminal run has no configured account. Is this the best way to solve the issue? No, not yet: the command's additive structure is reasonable, but it must reserve fallback time and receive maintainer agreement on the stable automation contract before it is the best durable solution. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against cfb7b8036087. Label changesLabel changes:
Label justifications:
Evidence reviewedWhat I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (6 earlier review cycles)
|
Addresses the two review findings on steipete#2237: - Resolve the configured token account (resolvedAccounts(for:).first) before fetching, matching usage, so token-only Claude/z.ai/OpenAI configs return a real decision instead of unknown. - Filter synthetic-placeholder rate windows via guardRemainingHeadroom(for:), so a phantom primary (e.g. Claude with no live session window) is treated as unknown rather than a false 100%-available exit 0. Add 4 regression tests for the window-headroom path (real, synthetic, absent, fully used).
`codexbar guard --provider <id> [--need <percent>] [--window session|weekly] [--json] [--fail-open]` exits 0 when the relevant window has at least --need% remaining, 1 when it does not, and 2 when quota is unknown/unreachable (--fail-open exits 0 instead). This turns CodexBar from a passive display into a guardrail that scripts and agent loops can gate on. The gating decision is a pure, unit-tested function (5 cases); the fetch reuses the existing provider pipeline. Proposed in steipete#2235.
- suppress function_parameter_count on emitGuardResult (matches the repo's makeUsagePayload precedent) - swiftformat: wrap payloadValue body, normalize self. on guardHumanLine, drop redundant explicit type and the no-arg @suite attribute Verified in the swift:6.3.3 container: swiftlint --strict 0 violations, swiftformat --lint clean, CodexBarCLI builds, 5/5 guard tests pass.
Addresses the two review findings on steipete#2237: - Resolve the configured token account (resolvedAccounts(for:).first) before fetching, matching usage, so token-only Claude/z.ai/OpenAI configs return a real decision instead of unknown. - Filter synthetic-placeholder rate windows via guardRemainingHeadroom(for:), so a phantom primary (e.g. Claude with no live session window) is treated as unknown rather than a false 100%-available exit 0. Add 4 regression tests for the window-headroom path (real, synthetic, absent, fully used).
4d06f79 to
5d1e380
Compare
Rebasing onto main added the hooks/hooks-test command cases to the CLI dispatch switch, and this branch's guard case pushed main()'s cyclomatic complexity to 21 (limit 20). Extract the config subcommands into a runConfig(path:values:) helper, mirroring the existing runHooks pattern. No behavior change.
Proof (for
|
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7c452fabad
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| window: window, | ||
| config: config, | ||
| verbose: verbose, | ||
| webTimeout: timeout > 0 ? timeout : 60) |
There was a problem hiding this comment.
Reserve timeout budget for fallback strategies
When Claude is in CLI auto mode, its fetch plan tries the web step before the CLI fallback, and that web step can consume context.webTimeout. Here that per-provider web timeout is set to the exact same value as the outer guard deadline, so a slow/timed-out web attempt can use the entire --timeout; the outer runGuardFetch race then returns .timeout and cancels before the CLI fallback that codexbar usage would still try can run. In that auto/Claude-CLI setup, guard reports unavailable even though quota is available via CLI; use a separate/smaller per-web timeout or otherwise leave budget for fallbacks.
Useful? React with 👍 / 👎.
|
Merged as Verification:
No changelog file changed here; batch changelog follows separately. |
Implements the proposal in #2235. Opening it with the code + proof rather than waiting, since it's small and self-contained — happy to iterate on the flag shape or close it if the direction isn't wanted.
Summary
Adds
codexbar guard— a quota-aware exit code that turns CodexBar from a passive display into a guardrail scripts and agent loops can gate on.0= safe (relevant window has ≥--need% remaining),1= insufficient headroom,2= unknown/unreachable.--needdefaults to 10.--windowdefaults tosession(primary window);weeklychecks the secondary.--fail-openexits0instead of2when quota is unknown.Design
evaluateGuard(remainingPercent:needPercent:failOpen:), kept free of I/O so it's unit-testable off-network.ProviderFetchContext→fetchProviderUsage), run under.backgroundinteraction (no Keychain prompts), exactly likeusage.Tests
TestsLinux/CLIGuardDecisionTests.swift— 5 deterministic cases: ample→ok/0, insufficient→blocked/1, unknown→2, unknown+fail-open→0, boundary (remaining == need)→ok/0.Verification (Linux,
swift:6.3.3)Built and tested on Linux (
swift:6.3.3); the macOS CI job validates the cross-platform build.Review feedback addressed (clawsweeper, commit
4d06f796)Both P2 findings fixed:
CLIGuardCommand.swift) —guardnow resolves the configured token account viaresolvedAccounts(for:).firstand threads it through the fetch (env/settings/source/context), matchingusage. Token-only Claude/z.ai/OpenAI configs now return a real decision instead ofunknown.guardRemainingHeadroom(for:)that returnsnilfor anilorisSyntheticPlaceholderwindow, so a phantom primary (e.g. Claude with no live 5-hour session) is treated asunknownrather than a false100%-available exit0.Added 4 regression tests for the window-headroom path (real / synthetic / absent / fully-used) — 9 guard tests total. Verified in
swift:6.3.3: swiftlint--strict0 violations, swiftformat--lintclean,CodexBarCLIbuilds, 9/9 tests pass.Still open for the maintainer (not contributor-fixable): (a) real known-quota terminal proof of safe/blocked from a configured account, and (b) product sign-off on the public flag/exit-code contract.