diff --git a/docs/superpowers/specs/2026-07-12-upstream-0.42.1-windows-port-design.md b/docs/superpowers/specs/2026-07-12-upstream-0.42.1-windows-port-design.md new file mode 100644 index 0000000000..3b3bf0710f --- /dev/null +++ b/docs/superpowers/specs/2026-07-12-upstream-0.42.1-windows-port-design.md @@ -0,0 +1,221 @@ +# Upstream 0.42.1 Windows Port Design + +## Scope + +Current `main` is released as Win-CodexBar 0.42.0. This release ports the +behavioral changes from `steipete/CodexBar` v0.42.1 into the active Windows +Tauri shell and shared Rust crate. It does not port the Swift/AppKit/WidgetKit, +website, or appcast structure; the seven PRs below implement Windows behavior +only. + +Each PR is independently reviewable and uses focused TDD. Do not combine these +changes into a framework migration or an upstream source sync. + +## PR 1: Bound Codex JSONL Metadata and Preserve Unpriced Events + +**Likely target paths:** `rust/src/core/jsonl_scanner.rs`, +`rust/src/codex_costs.rs`, `rust/src/cost_scanner.rs`, +`rust/src/core/cost_pricing.rs`, and their existing unit tests. + +- Bound every session-metadata JSONL line/read to 256 KiB. An oversized or + malformed line must not grow an unbounded buffer; consume it safely and + promptly release its read chunks after scanning. +- Treat a token event without an attributable model as explicitly unpriced. + It may contribute to token observability, but it must not receive fallback + model pricing, contribute dollar cost, or be reported as a priced model. +- Keep model attribution deterministic across incremental scans and cache + reloads. An oversized line must not invent an attribution. +- Cover the byte cap and chunk release, recovery to a valid later JSONL line, + and a model-less token event. + +## PR 2: Factory API Credential and Source Semantics + +**Likely target paths:** `rust/src/providers/factory/mod.rs`, +`rust/src/settings/api_keys.rs`, `rust/src/settings.rs`, +`rust/src/core/credentials.rs`, `rust/src/core/provider.rs`, +`apps/desktop-tauri/src-tauri/src/commands/provider_settings.rs`, +`apps/desktop-tauri/src/surfaces/settings/providers/ProviderDetailPane.tsx`, +and `apps/desktop-tauri/src/surfaces/settings/providers/ApiKeySection.tsx`. + +- Store a Factory API key through the existing encrypted credential path; it is + never serialized into ordinary settings, diagnostics, UI state, or logs. +- Add Factory API as a source and make Auto API-first when a key exists. Fall + back to web only for a recoverable API failure such as timeout, transient + transport failure, or server failure. Invalid credentials, authorization + failures, malformed API data, and configured-source errors remain explicit + API errors and do not silently become a web request. +- Surface the selected source in the existing provider source UI and preserve + the source setting through reloads. +- The API key must never be attached to the Factory web endpoint request or + included in an error string, trace, diagnostic, or redacted-copy payload. +- Add focused provider and credential-storage tests, including the no-web-key + assertion and the recoverable/non-recoverable fallback split. + +## PR 3: Claude Passive Probes and Credential State + +**Likely target paths:** `rust/src/providers/claude/mod.rs`, +`rust/src/providers/claude/oauth/mod.rs`, +`rust/src/providers/claude/oauth/refresh.rs`, +`rust/src/providers/claude/cli_reset.rs`, `rust/src/settings.rs`, +`rust/src/core/provider.rs`, `rust/src/cli/tty_runner.rs`, +`apps/desktop-tauri/src-tauri/src/commands/providers.rs`, +`apps/desktop-tauri/src/surfaces/settings/providers/sections/credentials/ClaudeCreds.tsx`, +and `apps/desktop-tauri/src/surfaces/settings/providers/ProviderDetailPane.tsx`. + +- While a passive Claude CLI probe runs, disable Claude Code's background + updater for that probe process only. The passive probe still runs during an + automatic refresh; explicit and manual probes keep their normal behavior. +- Detect a logged-out Claude CLI before starting an interactive usage probe and + return the existing authentication-required error without launching a probe. +- Persist the successfully selected source after Claude login, so subsequent + refreshes use the working source rather than repeating source discovery. +- An expired OAuth credential may fall through only for an Auto attempt whose + CLI result is MCP-only and has no plan-limit sample. Explicit OAuth keeps its + OAuth error, and a normal CLI/auth failure does not acquire an unrelated + fallback. +- Mark synthetic CLI placeholders as non-observations: they do not enter + notification, history, or reset state. PR 5 owns the shared state guard and + is reviewed alongside this PR. + +## PR 4: Provider Compatibility and Local CLI Discovery + +**Likely target paths:** `rust/src/providers/amp/mod.rs`, +`rust/src/providers/kiro/mod.rs`, `rust/src/providers/kiro/version.rs`, +`rust/src/cli/tty_runner.rs`, `rust/src/providers/codex/mod.rs`, +`rust/src/providers/gemini/mod.rs`, `rust/src/providers/gemini/api.rs`, and +their existing tests. + +- Parse Amp daily usage percentages directly from the current daily response; + do not reinterpret a daily percentage as a monthly quota. +- For old Kiro CLI versions, attempt the bounded pipe invocation first, then + use the existing ConPTY mechanism only when needed. Both attempts share one + caller deadline, and timeout, cancellation, and parse failure clean up the + spawned process tree before returning. +- Discover the Codex executable bundled with ChatGPT in addition to the + existing PATH/npm locations. Invoke the resolved executable directly rather + than routing through a shell. +- Verify Gemini OAuth recovery with focused existing tests. Change Gemini only + if that verification exposes a regression; this PR does not duplicate a + recovery path that already works. + +## PR 5: Codex Reset and Notification Integrity + +**Likely target paths:** `rust/src/notifications.rs`, +`rust/src/core/usage_snapshot.rs`, `rust/src/core/rate_window.rs`, +`apps/desktop-tauri/src-tauri/src/state.rs`, +`apps/desktop-tauri/src-tauri/src/commands/providers.rs`, and their tests. + +This PR follows PR 1 and is reviewed alongside PR 3. + +- Key Codex reset and notification state by stable account owner, rate-window + identity, and reset boundary. Display labels, transient emails, and provider + IDs alone are not ownership keys. +- Accept an observation only when it belongs to the same owner and window and + advances to a valid later reset boundary for that cycle. Reject stale, + cross-account, regressed-boundary, and synthetic-placeholder samples before + they mutate notification suppression, history, or reset state. +- Preserve legitimate reset transitions: a new owner or genuinely advanced + boundary starts a new cycle; a rejected sample cannot clear an alert or + overwrite a later reset. +- Test each accepted and rejected transition at the shared state boundary, not + by adding equivalent guards to individual providers. + +## PR 6: Deterministic Offline Adaptive-Refresh Replay + +**Likely target paths:** `apps/desktop-tauri/src-tauri/src/auto_refresh.rs`, +`rust/src/cli/mod.rs`, `rust/src/cli/usage.rs`, and the existing shared core +module tree under `rust/src/core/`. A small new +`rust/src/core/adaptive_refresh.rs` policy module and +`rust/src/cli/adaptive_refresh.rs` command module are allowed if the existing +files cannot hold the pure policy cleanly. + +- Extract the production adaptive-refresh decision policy into one pure shared + Rust core. The Tauri scheduler supplies clock and live observations; it does + not own a separate policy. +- Add a Rust CLI replay command that accepts caller-supplied JSONL observations + and emits deterministic decisions. It is offline: it performs no provider, + network, credential, or desktop-shell access. +- Replay has no production recording path. Tests create their own input data, + and production refresh does not write user observations solely to support + replay. +- Use fixed caller-supplied times in replay tests so equal JSONL always + produces equal output. + +## PR 7: German UI, Settings Grouping, and Cost-History Rendering + +**Likely target paths:** `rust/src/settings.rs`, `rust/src/locale.rs`, +`rust/src/locale/tests.rs`, `rust/src/locale/de-DE.ftl` (new), +`apps/desktop-tauri/src/i18n/keys.ts`, +`apps/desktop-tauri/src/i18n/LocaleProvider.tsx`, +`apps/desktop-tauri/src/surfaces/settings/tabs/GeneralTab.tsx`, +`apps/desktop-tauri/src/surfaces/settings/providers/ProviderDetailPane.tsx`, +`apps/desktop-tauri/src/surfaces/settings/providers/sections/MenuBarMetricSection.tsx`, +`apps/desktop-tauri/src/surfaces/settings/providers/sections/charts/CostHistoryChart.tsx`, +and relevant frontend tests. + +- Add German end-to-end through the existing `Language`, Fluent catalog, Rust + bridge, typed frontend key list, locale provider, tray text, FloatBar, + Settings, provider controls, and cost-history surfaces. Missing German keys + fail the existing key-completeness checks rather than silently rendering an + identifier. +- Match the existing Windows Menu bar and Connection settings grouping. This + is grouping and copy parity in the current React/Tauri UI, not a recreation + of a Swift preferences form. +- Add a rendered-content fingerprint for the cost-history chart so unchanged + rendered bars, labels, locale-formatted values, palette, and animation state + avoid redundant chart work. A changed accessible label or displayed value + must invalidate the fingerprint. +- Cover German selection and representative tray/settings/provider strings, + grouping placement, and the equal-content/different-content chart cases. + +## Explicitly Non-Applicable Upstream Items + +The following upstream work is not ported because its Windows behavior is +absent or already native: + +- Cursor WidgetKit widgets. +- AppKit menu viewport restore. +- Swift Form footer styling. +- macOS Keychain pre-alert UI. +- Website provider count and social card. +- Sparkle appcast. +- Unix foreground process-group PATH fix. + +## Review and Merge Gates + +For every PR: + +1. Start with focused failing tests, implement the smallest production change, + then retain regression coverage at the shared behavior boundary. +2. Run applicable Rust, Tauri, frontend, locale, and build checks for the + touched surfaces. +3. Require a correctness review before merge. + +PRs 2 and 3 additionally require a security review covering credential +storage, fallback behavior, error text, logging, and secret propagation. + +After all seven PRs merge, run one combined thermo-nuclear code-quality review, +Ponytail Review, Ponytail Audit, and Ponytail Debt. Fix every actionable +finding before release. + +## Release Gate + +Release follows all seven merged PRs: + +1. Smoke-test the Windows installer and portable artifact. +2. Perform CUA across tray, FloatBar, every Settings tab, provider controls, + German, and cost history. +3. Open a release PR that bumps the Windows version to 0.42.1. +4. Publish four release assets and verify their hashes and downloads. +5. Submit and validate the immutable Winget 0.42.1 manifest. + +## Self-Review + +This specification has seven focused, behavior-only PRs; PR 5 explicitly +depends on PR 1 and is paired with PR 3 review, and release explicitly +depends on all seven. The required literal concepts are defined with their +acceptance/rejection semantics, target paths, review gates, and Windows-only +scope. All existing target paths were verified in this checkout; the two +explicitly marked new modules are planned additions. No unresolved work markers +are present; the word "placeholder" appears only where the required +synthetic-placeholder behavior is specified.