forked from steipete/CodexBar
-
Notifications
You must be signed in to change notification settings - Fork 119
Upgrade pnpm to 11.25.0 from #429 #457
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,245 @@ | ||
| # ADR 0006: Dependency consolidation candidates | ||
|
|
||
| Date: 2026-09-05 | ||
| Status: Proposed | ||
|
|
||
| ## Context | ||
|
|
||
| Win-CodexBar has grown across roughly 70 providers, a Rust backend, a Tauri 2 | ||
| shell, and a React frontend. The codebase now contains several places where the | ||
| same domain information or infrastructure policy is expressed repeatedly. | ||
| Adding dependencies is only worthwhile when a crate removes measurable | ||
| boilerplate, reduces synchronization points, or materially improves | ||
| correctness. This ADR records candidates for review before implementation. It | ||
| does not approve adding every crate listed below. | ||
|
|
||
| The September 2026 audit found these concrete pressure points: | ||
|
|
||
| - `rust/src/core/provider.rs` is 1,131 lines. `ProviderId` has 70 variants, with | ||
| repeated handwritten tables for iteration, CLI names, display names, cookie | ||
| domains, aliases, and brand colors. The largest repeated metadata blocks span | ||
| roughly 540 lines. | ||
| - `apps/desktop-tauri/src/types/bridge.ts` is 958 lines with 101 exported | ||
| types/interfaces that must stay aligned with Rust DTOs. | ||
| - `apps/desktop-tauri/src/lib/tauri.ts` is 534 lines with 91 handwritten invoke | ||
| wrappers, while the Rust shell exposes 98 `#[tauri::command]` functions. | ||
| - `FetchContext` is manually constructed at 26 call sites. | ||
| - The Rust code contains about 20 `lock().unwrap*` sites, including eight | ||
| explicit poison-recovery patterns using `into_inner()`. | ||
| - There are many manual `sort`, `dedup`, `HashSet` uniqueness, grouping, and | ||
| collection reshaping paths across provider, session, cost, and dashboard | ||
| code. | ||
| - URL-like configuration and command inputs are commonly represented as raw | ||
| `String`/`&str`, including gateway, proxy, dashboard, status, release, and | ||
| provider endpoint URLs. `validate_external_url` currently performs manual | ||
| HTTP(S) prefix validation. | ||
| - Provider and configuration parsing has many generic Serde error mappings that | ||
| report the parser error but not the precise failing field path. | ||
| - Several in-memory caches hand-roll `Mutex<HashMap<...>>`, timestamps, and TTL | ||
| checks for provider, chart/local-usage, status, token, and pricing data. | ||
| - Cost and spend calculations are extensively represented as `f64`. | ||
|
|
||
| ## Decision | ||
|
|
||
| Use a tiered adoption policy. A dependency is added only in the PR that also | ||
| uses it to remove or centralize existing code. Do not add dormant dependencies | ||
| for hypothetical future use. | ||
|
|
||
| ### Tier 1: highest-confidence candidates | ||
|
|
||
| #### `strum` | ||
|
|
||
| Use derives such as `EnumIter`, `EnumString`, `Display`, `VariantArray`, and | ||
| variant metadata where they eliminate repeated enum plumbing. | ||
|
|
||
| Primary target: `ProviderId` and other enums that manually implement `all`, | ||
| `parse`, `as_str`, `display_name`, or alias tables. | ||
|
|
||
| Acceptance criteria: | ||
|
|
||
| - provider metadata has one obvious source of truth per property; | ||
| - aliases and compatibility names remain behaviorally identical; | ||
| - exhaustive provider factory behavior remains compile-time checked; | ||
| - net handwritten LOC decreases materially. | ||
|
|
||
| #### `ts-rs` | ||
|
|
||
| Generate TypeScript DTO definitions from Rust for bridge types that are true | ||
| wire contracts. Keep frontend-only unions/types handwritten when Rust is not | ||
| the source of truth. | ||
|
|
||
| Primary target: the mirrored portions of `src/types/bridge.ts`. | ||
|
|
||
| Acceptance criteria: | ||
|
|
||
| - generated files are deterministic and checked in or generated by an explicit | ||
| reproducible step; | ||
| - Serde rename/tag behavior is covered by tests; | ||
| - the generated boundary removes manual Rust/TypeScript synchronization rather | ||
| than introducing a second schema layer; | ||
| - no runtime dependency is added to the frontend. | ||
|
|
||
| Do not adopt `tauri-specta` in the same step unless its Tauri 2 release line is | ||
| independently proven stable and it replaces enough of `src/lib/tauri.ts` to | ||
| justify the additional integration surface. | ||
|
|
||
| #### `serde_with` | ||
|
|
||
| Use only where it replaces custom Serde adapters or repetitive conversion | ||
| logic, for example display/from-string bridges or optional/default handling. | ||
|
|
||
| Acceptance criteria: each use deletes or simplifies existing serialization | ||
| code; avoid cosmetic attribute churn. | ||
|
|
||
| #### `url` | ||
|
|
||
| Promote URL values to `url::Url` at validation/security boundaries where the | ||
| value is semantically a URL. The crate is already present transitively through | ||
| `reqwest`, so making it direct should not materially enlarge the dependency | ||
| graph at the current lockfile state. | ||
|
|
||
| Primary targets: external URL validation and provider/gateway/proxy endpoints. | ||
|
|
||
| Acceptance criteria: | ||
|
|
||
| - scheme allowlists stay explicit; | ||
| - file/javascript and other unsafe schemes remain rejected where applicable; | ||
| - persisted wire compatibility is preserved when settings currently store | ||
| strings. | ||
|
|
||
| #### `parking_lot` | ||
|
|
||
| Use for internal synchronization where standard-library poisoning semantics are | ||
| not part of the intended behavior and where it removes repeated poison recovery. | ||
|
|
||
| Acceptance criteria: | ||
|
|
||
| - no lock is held across `.await`; | ||
| - migration is focused rather than repo-wide mechanical churn; | ||
| - test-only locks do not justify the dependency by themselves. | ||
|
|
||
| #### `itertools` | ||
|
|
||
| Use for collection transforms that become materially clearer, especially | ||
| unique/sorted/grouped pipelines that currently require temporary sets or | ||
| multi-step mutation. | ||
|
|
||
| Acceptance criteria: the replacement is shorter and easier to read than the | ||
| standard-library version; simple iterator chains remain standard library only. | ||
|
|
||
| #### `bon` | ||
|
|
||
| Prototype on `FetchContext`, which has 26 literal construction sites, before | ||
| using it elsewhere. | ||
|
|
||
| Acceptance criteria: | ||
|
|
||
| - call sites communicate only intentional overrides; | ||
| - defaults remain centralized; | ||
| - builder generation does not obscure required fields or make diagnostics | ||
| worse; | ||
| - measurable net LOC/readability improvement is shown in the prototype diff. | ||
|
|
||
| #### `serde_path_to_error` | ||
|
|
||
| Use at user-facing or provider-facing JSON boundaries where a precise field path | ||
| would materially improve diagnostics. | ||
|
|
||
| Acceptance criteria: preserve the existing provider-specific context while | ||
| adding the failing data path; do not wrap silent best-effort parsers whose | ||
| failure is intentionally ignored. | ||
|
|
||
| ### Tier 2: architecture-specific candidates | ||
|
|
||
| These need a focused prototype and should not be added merely because the crate | ||
| is useful in general. | ||
|
|
||
| #### `tokio-util` | ||
|
|
||
| Candidate for `CancellationToken` in refresh/probe/background-task ownership. | ||
| It is already present transitively through the current HTTP stack. Adopt only | ||
| where it replaces bespoke cancellation flags/channels and clarifies task | ||
| lifetime. | ||
|
|
||
| #### `secrecy` | ||
|
|
||
| Candidate for API keys, tokens, and other credentials that currently travel as | ||
| ordinary `String`s. Adoption must integrate with existing DPAPI, keyring, | ||
| redaction, and persistence behavior rather than creating a parallel secret | ||
| model. | ||
|
|
||
| #### `moka` | ||
|
|
||
| Candidate for simple in-memory TTL caches currently implemented as | ||
| `Mutex<HashMap<...>>` plus timestamps. Do not replace the JSONL/disk cost cache | ||
| or other caches with domain-specific persistence/invalidation semantics unless a | ||
| prototype proves equivalence. | ||
|
|
||
| #### `reqwest-middleware` and `reqwest-retry` | ||
|
|
||
| Candidate for genuinely shared idempotent HTTP retry/backoff policy. The repo is | ||
| currently on `reqwest 0.12`, so compatible middleware versions must be verified | ||
| before adoption. Provider-specific authentication refresh, WAF fallback, | ||
| alternate-host logic, and semantic retries must remain provider-owned. | ||
|
|
||
| #### `rust_decimal` | ||
|
|
||
| Candidate for monetary totals if floating-point rounding is demonstrated to be | ||
| a product-level correctness problem. Migration would be broad because cost, | ||
| pricing, bridge DTOs, formatting, tests, and persisted/exported values currently | ||
| use `f64`. | ||
|
|
||
| Do not migrate merely for theoretical precision. First add a failing test or | ||
| real rounding example that changes an observable result. | ||
|
|
||
| #### `phf` | ||
|
|
||
| Candidate for immutable lookup tables that are currently runtime-built | ||
| `LazyLock<HashMap<...>>` values. Prefer ordinary `match`, slices, or arrays when | ||
| those are already clearer and compile-time cheap. | ||
|
|
||
| ## Rejected default: dependency accumulation | ||
|
|
||
| Do not add all candidates in one dependency-only PR. That would increase build, | ||
| supply-chain, maintenance, and audit surface while proving none of the claimed | ||
| benefits. | ||
|
|
||
| The preferred sequence is small implementation PRs, each with before/after | ||
| evidence: | ||
|
|
||
| 1. `strum` for provider/enum metadata. | ||
| 2. `ts-rs` for Rust-to-TypeScript wire types. | ||
| 3. `url` for URL validation boundaries. | ||
| 4. `bon` prototype for `FetchContext`. | ||
| 5. `serde_path_to_error` for selected provider/config diagnostics. | ||
| 6. `parking_lot` and `itertools` where the diff clearly pays for them. | ||
| 7. Tier 2 only after a concrete problem demonstrates the need. | ||
|
|
||
| `serde_with` may be folded into one of the above only when the same PR has a | ||
| clear serialization target. | ||
|
|
||
| ## Review questions | ||
|
|
||
| Reviewers should challenge each candidate with the same questions: | ||
|
|
||
| 1. Which current code is deleted or centralized by this crate? | ||
| 2. How many call sites or synchronization points disappear? | ||
| 3. Does the dependency become part of a public/wire/persistence contract? | ||
| 4. What new failure mode, compile-time cost, runtime cost, or supply-chain | ||
| surface does it add? | ||
| 5. Could a small local helper or derive already in the graph solve the same | ||
| problem more simply? | ||
| 6. Is the migration independently reversible? | ||
| 7. What test proves behavior stayed identical? | ||
|
|
||
| ## Consequences | ||
|
|
||
| - Dependency additions become evidence-driven rather than preference-driven. | ||
| - The highest-value work focuses on duplicated sources of truth first: | ||
| `ProviderId` metadata and the Rust/TypeScript bridge contract. | ||
| - Large architectural migrations are split from low-risk boilerplate removal. | ||
| - Reviewers can reject individual candidates without blocking the rest of the | ||
| strategy. | ||
| - This ADR is intentionally `Proposed`; accepting it does not automatically | ||
| authorize every Tier 1 or Tier 2 dependency. Each implementation PR still | ||
| needs its own measured justification and tests. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
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
Assert that the status message uses
$expectedPnpm.The current negative assertion only rejects the current literal version. It passes if the message is missing, uses a stale version, or references another variable. Replace it with a positive assertion for
pnpm \$expectedPnpm,.Proposed test adjustment
🤖 Prompt for AI Agents