Skip to content

feat: add KRW to the preferred currency picker - #2669

Merged
steipete merged 1 commit into
steipete:mainfrom
kes02:feat/krw-currency
Aug 6, 2026
Merged

feat: add KRW to the preferred currency picker#2669
steipete merged 1 commit into
steipete:mainfrom
kes02:feat/krw-currency

Conversation

@kes02

@kes02 kes02 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds KRW (₩) to the preferred currency picker in Settings → General. KRW was the one major Asian currency missing from the list introduced in #2490 (refs #2449), so won-billed users convert USD estimates by hand to compare them against a card statement.

Change

Three lines of source, no new exchange-rate logic:

  • CurrencyExchange.swift:18"KRW" joins supportedCurrencies, next to CNY/JPY rather than appended, matching the existing regional grouping.
  • CurrencyExchange.swift:30"KRW": 1428.90 joins the hardcoded fallback table. Existing fallback values are untouched.
  • PreferencesGeneralPane.swift:85,105PreferredCurrencyOption.krw and its "KRW (₩)" label.

fetchLatestRatesIfNeeded already merges every rate in the open.er-api.com/v6/latest/USD payload, and that payload carries KRW. Listing the code in supportedCurrencies is what opens the requiresLiveRates gate (CurrencyExchange.swift:116), so selecting KRW triggers the same live-fetch and 24h-cache path as the existing currencies; the hardcoded rate is only read before the first successful fetch.

No public API surface change: git diff origin/main -- '*.swift' adds and removes no public line — supportedCurrencies gains an element, its signature is unchanged.

Formatting

KRW is a zero-decimal currency, and UsageFormatter.currencyString delegates to .currency(code:), which resolves ICU's fraction digits — so no formatter change is needed: $10 renders as ₩14,289, $0.42 as ₩600.

That path pins Locale(identifier: "en_US"), so the rendering is host-independent and the new no-fractional-separator assertion holds on a localized machine too — the failure mode #2651 fixed for Perplexity does not apply here.

Validation

  • make check — swiftformat clean, swiftlint 0 violations across 1809 files
  • make test — 817 selections / 69 groups, 0 first-pass failures, 0 retries, 0 timeouts
  • swift test --filter UsageFormatter — 46 tests pass, including the new assertions
  • git diff --check — clean

New coverage in UsageFormatterTests.swift:

  • USD → KRW conversion equals the table rate (convert(usdAmount:to:))
  • is rendered and no fractional separator is emitted
  • requiresLiveRates("KRW") == true, so the live fetch is actually triggered rather than the currency silently sitting on the hardcoded rate

Real behavior proof

Fresh bundle built from this branch at 44393a0c (make start → release package → relaunch), macOS 26.5 (arm64).

1. Settings → General — Preferred Currency resolves to KRW (₩)
CodexBar Settings → General with Preferred Currency set to KRW (₩)

2. Menu card — provider costs render as won

Today ₩98,810, 30d cost ₩1,884,614, daily-chart peak ₩300,527 — thousands separated, no fractional separator, matching the zero-decimal expectation asserted in UsageFormatterTests.
CodexBar menu card showing today and 30-day costs in Korean won

Rate provenance. Selecting KRW opens the requiresLiveRates gate, so the displayed won comes from a live rate rather than the hardcoded 1428.90 fallback: the app fetched and cached CodexBar.CurrencyExchangeRates["KRW"] = 1428.890254 with CodexBar.CurrencyExchangeLastFetch = 2026-08-05 14:01:55 UTC. Earlier in the same session, before that fetch returned, the Today row still rendered $62.75; once the rate landed it became ₩89,659 — exactly 62.75 × 1428.890254. The screenshot above was taken a few minutes later, after more usage had accrued.

KRW was the one major Asian currency missing from the picker added in
steipete#2490, so won-billed users converted USD estimates by hand.

No new exchange-rate logic is needed: fetchLatestRatesIfNeeded already
merges every rate in the open.er-api.com payload, which carries KRW.
Listing the code in supportedCurrencies is what opens the
requiresLiveRates gate, so selecting KRW triggers the same live-fetch and
24h-cache path as the existing currencies. The hardcoded fallback rate is
only read before the first successful fetch.

KRW is zero-decimal and currencyString pins en_US, so ICU resolves the
fraction digits and won renders without a fractional separator on any
host.

Refs steipete#2449

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. labels Aug 5, 2026
@clawsweeper

clawsweeper Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codex review: needs maintainer review before merge. Reviewed August 5, 2026, 9:56 PM ET / August 6, 2026, 01:56 UTC.

ClawSweeper review

What this changes

Adds Korean won as a selectable preferred display currency, with an offline fallback rate and focused formatter/live-rate-gate coverage.

Merge readiness

Ready for maintainer review

Keep open for normal maintainer review: current main and v0.47.0 do not offer KRW, while this narrow extension follows the existing picker and exchange-rate design, has direct UI proof, and introduces no actionable defect.

Priority: P3
Reviewed head: 44393a0c4a33b09d9566f948dd46cb748704f584

Review scores

Measure Result What it means
Overall readiness 🦞 diamond lobster (5/6) A narrowly scoped implementation with direct native UI proof, focused tests, and no supported correctness or security concern.
Proof confidence 🦞 diamond lobster (5/6) ✨ media proof bonus Sufficient (screenshot): The PR body provides after-fix screenshots from a freshly built bundle showing both KRW selection and rendered won costs.
Patch quality 🦞 diamond lobster (5/6) No actionable review findings were identified.

Verification

Check Result Evidence
Real behavior Verified Sufficient (screenshot): The PR body provides after-fix screenshots from a freshly built bundle showing both KRW selection and rendered won costs.
Evidence reviewed 5 items Existing integration path: The current picker persists the selected currency and invokes the existing live-rate fetch only for supported non-USD codes; the PR adds KRW to the two existing inputs to that path.
Current behavior and feature history: Current main’s exchange service and picker are attributed to the recent currency-feature reintroduction; its supported list does not yet contain KRW, so the PR remains necessary.
Main and release check: The PR head is not on current main, and v0.47.0’s supported-currency list also lacks KRW.
Findings None None.
Security None None.

How this fits together

CodexBar converts provider cost estimates into a user-selected display currency. The settings picker supplies the chosen code to the exchange service, which uses cached/live or fallback rates before formatters render menu costs.

flowchart LR
A[Provider cost estimates] --> B[Preferred currency setting]
B --> C[Exchange-rate service]
C --> D[Fallback or cached live rate]
D --> E[Cost formatter]
E --> F[Menu and settings UI]
Loading

Before merge

None.

Agent review details

Security

None.

Review metrics

Metric Value Why it matters
Production/test delta production +4/-1; tests +7 The small patch extends two existing production tables and adds focused coverage without changing the exchange mechanism.

Technical review

Best possible solution:

Merge the focused KRW addition through normal maintainer review, retaining the established live-rate and offline-fallback behavior.

Do we have a high-confidence way to reproduce the issue?

Not applicable: this PR adds a choice to an existing preference rather than repairing a current failure; its after-fix UI proof directly demonstrates the intended flow.

Is this the best way to solve the issue?

Yes: adding KRW to the existing picker and rate tables reuses the established conversion, caching, and formatting path without parallel logic.

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against 4cdb349cbc57.

Labels

Label changes:

  • add rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦞 diamond lobster, so this older rating label is no longer current.

Label justifications:

  • P3: This is a small optional display-preference enhancement with limited blast radius.
  • rating: 🦞 diamond lobster: Overall readiness is 🦞 diamond lobster; proof is 🦞 diamond lobster and patch quality is 🦞 diamond lobster.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Sufficient (screenshot): The PR body provides after-fix screenshots from a freshly built bundle showing both KRW selection and rendered won costs.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR body provides after-fix screenshots from a freshly built bundle showing both KRW selection and rendered won costs.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The PR body provides after-fix screenshots from a freshly built bundle showing both KRW selection and rendered won costs.

Evidence

What I checked:

Likely related people:

  • steipete: Peter Steinberger introduced the current main copies of the exchange service, picker, and formatter tests in the recent feature work and merged the original multi-currency implementation. (role: recent area contributor and merger; confidence: high; commits: 6afa6728f3c4, 35626eb1cf5e; files: Sources/CodexBarCore/CurrencyExchange.swift, Sources/CodexBar/PreferencesGeneralPane.swift, Tests/CodexBarTests/UsageFormatterTests.swift)
  • Yuxin-Qiao: Authored the merged multi-currency PR that established the picker and live-rate model this PR extends. (role: original feature author; confidence: medium; commits: 35626eb1cf5e; files: Sources/CodexBarCore/CurrencyExchange.swift, Sources/CodexBar/PreferencesGeneralPane.swift)

Rating scale

Score Internal tier Crab rank Meaning
6/6 S 🦀 challenger crab Exceptional readiness
5/6 A 🦞 diamond lobster Very strong readiness
4/6 B 🐚 platinum hermit Good normal PR; ordinary maintainer review
3/6 C 🦐 gold shrimp Useful, but confidence is limited
2/6 D 🦪 silver shellfish Proof or implementation needs work
1/6 F 🧂 unranked krab Not merge-ready
N/A NA 🌊 off-meta tidepool Rating does not apply

Overall follows the weaker of proof and patch quality.
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.

Workflow

  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

History

Review history (4 earlier review cycles)
  • reviewed 2026-08-05T10:49:23.895Z sha 44393a0 :: needs real behavior proof before merge. :: none
  • reviewed 2026-08-05T12:09:00.399Z sha 44393a0 :: needs real behavior proof before merge. :: [P3] Add fresh-bundle KRW UI proof
  • reviewed 2026-08-05T13:31:08.119Z sha 44393a0 :: needs real behavior proof before merge. :: [P3] Add fresh-bundle KRW UI proof
  • reviewed 2026-08-05T14:39:10.518Z sha 44393a0 :: needs maintainer review before merge. :: none

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. and removed rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. labels Aug 5, 2026
@steipete
steipete merged commit aa7c2b5 into steipete:main Aug 6, 2026
9 checks passed
@steipete

steipete commented Aug 6, 2026

Copy link
Copy Markdown
Owner

Landed. Verified before merge: wiring matches existing currencies (membership-driven live-rate gate, pinned en_US_POSIX-style formatting via ICU so KRW renders zero decimals); tests assert both the ₩ symbol and absence of decimal separators. make check clean; UsageFormatter suite green. Partially addresses #2449 (adds the currency; billing-alignment remains open). Thanks @kes02!

@kes02
kes02 deleted the feat/krw-currency branch August 7, 2026 01:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

P3 Low-risk cleanup, docs, polish, ergonomics, or speculative feature. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦞 diamond lobster Very strong PR readiness with only minor maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants