diff --git a/CHANGELOG.md b/CHANGELOG.md index fa14541f..65c1ffe4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ ## [Ceiling] Unreleased +## [Ceiling] 1.5.37 - 2026-09-07 + +Codex usage on GPT-6 Astra finally prices correctly, so an active Astra day no longer reads as $0.00 on Charts. The rest of this release applies the same honesty to failures elsewhere: a fetch that cannot read usage reports an error instead of a healthy 0%, one Claude seat's rate-limit backoff stays with that seat, and capacity baselines stop blurring directory seats that share a login email. + +Local state gets more careful too. A settings file that cannot be decrypted is quarantined instead of silently replaced, timed-out provider CLIs are killed instead of orphaned, and MCP's Cursor status ranks the same window the desktop strip shows. + +### Fixed +- **An unreadable `settings.json` is no longer overwritten by the next save.** Parse failures already moved the file to `.bak` (SBS-954), but a DPAPI unprotect failure, an unsupported ProtectedFile version, or IO on an existing file loaded as defaults with no backup. `try_update` then replaced the live undecodable bytes. Those read failures now quarantine the same way, and the account ledger persist path fails closed instead of rewriting sightings from an empty snapshot. Closes SBS-1074. +- **MCP `get_status` now ranks Cursor the way the strip does.** After SBS-1055, `remaining_percent` used generic exhausted-first ranking over primary/secondary/tertiary, so a hotter Plan could hide Auto, and the widget snapshot still omitted `cursor-api` / on-demand while the docs claimed strip parity. Cursor now uses `cursorStripWindow` (hottest Auto/API with room, then on-demand, Plan last), those extras persist on the snapshot, and the multi-account seat picker compares the same window. Closes SBS-1076. +- **Capacity baselines keep Codex directory seats separate.** The observation scope hashed provider, source, email, and org only, so a personal and a Team seat sharing a login email shared one baseline: a drop on one seat read as a confirmed surprise reset on the other, and a missing core window was flagged unavailable on both. The directory account id is now part of the scope. Ambient seats re-key once on upgrade and rebuild their baseline from the next reading. Fixes SBS-1079. +- **A failed usage fetch reports an error instead of a healthy 0%.** Vertex AI's Resource Manager lookup, Amp, Kiro, and MiniMax turned failed or unreadable responses into a 0% reading, so an outage painted as an empty, healthy pool. Those paths fail closed now, and an errored snapshot is dropped from the widget snapshot so MCP and the statusline cannot publish the dummy 0% either. Closes SBS-1061. +- **Timed-out Kiro, Augment, and Vertex CLI fetches no longer leave orphaned children.** Those providers spawned `tokio::process::Command` without `kill_on_drop`, so a desktop refresh timeout dropped the `Child` and the CLI kept running. Fetch-path commands now kill on cancel; Augment's inner 15s deadline also kill+waits like `command_runner`. Closes SBS-1078. +- **A 429 on one Claude seat no longer pauses the others.** The OAuth rate-limit backoff was one global gate, so a rate limit on the personal seat also stopped the work seat sharing the same login email. Backoff is now keyed by config directory, the same seat identity account isolation and pace warnings already use. Closes SBS-1064. +- **Codex usage on GPT-6 Astra now has a price.** Astra tokens scanned fine from local logs but were missing from the pricing table, so an active Astra day read as $0.00 on Charts with zero percent of tokens priced. The model is priced at OpenAI's standard rates ($10 input / $1 cached input / $50 output per 1M), bare `gpt-6` maps to it, and Codex usage of Astra does not add the long-context surcharge. Fixes #413. + ## [Ceiling] 1.5.36 - 2026-08-23 This release closes out the current maintenance queue with safer local state, more accurate usage and cost reporting, and better behavior across the desktop, CLI, and MCP server. It also adds multi-account CLI usage, restores detached Settings window geometry, and strengthens accessibility regression coverage. @@ -12,9 +27,6 @@ The Windows server token now rotates after unsafe exposure. Concurrent and corru - **A leaked `serve.token` is rotated on Windows, not just Unix.** After SBS-953, a world-readable token was replaced on Unix, but Windows still tightened the DACL and reused the same secret. The ACL is now inspected before tightening; if anyone other than the current user, SYSTEM, or Administrators can read the file, the token is replaced. Closes SBS-1043. ### Fixed -- **An unreadable `settings.json` is no longer overwritten by the next save.** Parse failures already moved the file to `.bak` (SBS-954), but a DPAPI unprotect failure, an unsupported ProtectedFile version, or IO on an existing file loaded as defaults with no backup. `try_update` then replaced the live undecodable bytes. Those read failures now quarantine the same way, and the account ledger persist path fails closed instead of rewriting sightings from an empty snapshot. Closes SBS-1074. -- **MCP `get_status` now ranks Cursor the way the strip does.** After SBS-1055, `remaining_percent` used generic exhausted-first ranking over primary/secondary/tertiary, so a hotter Plan could hide Auto, and the widget snapshot still omitted `cursor-api` / on-demand while the docs claimed strip parity. Cursor now uses `cursorStripWindow` (hottest Auto/API with room, then on-demand, Plan last), those extras persist on the snapshot, and the multi-account seat picker compares the same window. Closes SBS-1076. -- **Timed-out Kiro, Augment, and Vertex CLI fetches no longer leave orphaned children.** Those providers spawned `tokio::process::Command` without `kill_on_drop`, so a desktop refresh timeout dropped the `Child` and the CLI kept running. Fetch-path commands now kill on cancel; Augment's inner 15s deadline also kill+waits like `command_runner`. Closes SBS-1078. - **Frontend tests now catch accessibility regressions automatically.** A shared axe assertion checks representative quota cards, mini charts, and update banners in the existing Frontend CI job. Color contrast remains outside jsdom coverage because it requires a rendered browser. Fixes #222. - **`usage --all-accounts` now fetches every configured Codex and Claude account.** Account fetches run with bounded concurrency, preserve configured order, and report failures independently. Text and JSON identify each configured account while the default output remains unchanged. Fixes #274. - **The detached Settings window now reopens where you left it.** Its saved size and position are restored and clamped on screen instead of being overwritten by a second frontend resize on every open. Closes #275. @@ -22,7 +34,7 @@ The Windows server token now rotates after unsafe exposure. Concurrent and corru - **Codex latest-session cost follows transcript time.** Copying or touching an older rollout no longer makes it replace a newer session in local cost summaries. Fixes #271. - **A corrupt `window_geometry.json` no longer wipes other windows' saved positions.** SBS-1024 locked the persist so two surfaces could not drop each other's keys, but a file that would not read or parse still loaded as empty defaults, and the next save replaced the whole file with only the window that just moved. Persist now refuses that write — the same fail-closed rule API keys already use — instead of rewriting siblings to an empty store. Closes SBS-1041. - **Loading settings no longer rewrites another install's start-at-login command.** Every `Settings::load` repaired `HKCU\...\Run\Ceiling` whenever the value was not the quoted path of this process. A portable CLI or a second tree therefore replaced the installed desktop's startup entry, and any extra arguments were stripped. Repair now runs only when this process owns that entry — the same intended exe, or a stale `codexbar-cli.exe` / `codexbar-desktop.exe` sibling in the same directory — and leaves custom arguments and other trees alone. Closes SBS-1053. -- **MCP `get_status` no longer hides an exhausted Weekly behind a healthy session.** Top-level `remaining_percent` copied only `usage.primary`, so a Claude/Codex 5-hour window with room made the advertised cap-check sink look fine while Weekly was already at 100%. Claude/Codex now rank primary, secondary, and tertiary (exhausted first, then highest used %). Cursor's parallel Auto/API path landed in SBS-1076. Closes SBS-1055. +- **MCP `get_status` no longer hides an exhausted Weekly behind a healthy session.** Top-level `remaining_percent` copied only `usage.primary`, so a Claude/Codex 5-hour window with room made the advertised cap-check sink look fine while Weekly was already at 100%. It now uses the same constraining-window ranking as the desktop strip across primary, secondary, and tertiary (exhausted first, then highest used %). Closes SBS-1055. - **Remembered window positions no longer drop a sibling when two surfaces save at once.** `window_geometry.json` was updated with an unlocked read-modify-write, so moving Settings while the float bar or Pop Out also wrote could replace the file with a snapshot that had never seen the other key. Geometry persist now holds the same cross-process state lock as settings and credentials. Closes SBS-1024. - **`codexbar` with no subcommand now runs `usage`.** CLI.md and `--help` already called usage the default command, but a bare `codexbar` printed an error asking for an explicit subcommand. It now does what those docs said. Closes SBS-1026. - **A corrupt `settings.json` is no longer renamed to `.bak` without the state lock.** SBS-954 moved an unparseable file aside so the next save could not overwrite it, but `Settings::load` did that rename before taking the lock. A concurrent `try_update` that had already written a good repair could then have that repair moved to `settings.json.bak`. The unlocked load now only parses; if the file is corrupt (or still carries embedded credentials) it takes the lock, re-reads, and quarantines only then. Closes SBS-1029. diff --git a/Cargo.lock b/Cargo.lock index 572904de..bef925fb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -664,7 +664,7 @@ checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "codexbar" -version = "1.5.36" +version = "1.5.37" dependencies = [ "aes-gcm", "anyhow", @@ -707,7 +707,7 @@ dependencies = [ [[package]] name = "codexbar-desktop-tauri" -version = "1.5.36" +version = "1.5.37" dependencies = [ "chrono", "chrono-tz", diff --git a/apps/desktop-tauri/package.json b/apps/desktop-tauri/package.json index ead3f861..6edd15ff 100644 --- a/apps/desktop-tauri/package.json +++ b/apps/desktop-tauri/package.json @@ -1,7 +1,7 @@ { "name": "desktop-tauri", "private": true, - "version": "1.5.36", + "version": "1.5.37", "packageManager": "pnpm@10.18.1", "type": "module", "scripts": { diff --git a/apps/desktop-tauri/src-tauri/Cargo.toml b/apps/desktop-tauri/src-tauri/Cargo.toml index 3ab283e1..a360d196 100644 --- a/apps/desktop-tauri/src-tauri/Cargo.toml +++ b/apps/desktop-tauri/src-tauri/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codexbar-desktop-tauri" -version = "1.5.36" +version = "1.5.37" edition = "2024" publish = false diff --git a/apps/desktop-tauri/src-tauri/tauri.conf.json b/apps/desktop-tauri/src-tauri/tauri.conf.json index 0873443f..5d6a8f7d 100644 --- a/apps/desktop-tauri/src-tauri/tauri.conf.json +++ b/apps/desktop-tauri/src-tauri/tauri.conf.json @@ -1,7 +1,7 @@ { "$schema": "https://schema.tauri.app/config/2", "productName": "Ceiling", - "version": "1.5.36", + "version": "1.5.37", "identifier": "io.github.tsouth89.ceiling", "build": { "beforeDevCommand": "pnpm run dev", diff --git a/rust/Cargo.toml b/rust/Cargo.toml index d73feffd..ee17b670 100755 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "codexbar" -version = "1.5.36" +version = "1.5.37" edition = "2024" authors = ["Ceiling Contributors"] description = "Local-first Windows companion for monitoring AI capacity and reset times" diff --git a/version.env b/version.env index 865bb7de..5c2ff49e 100755 --- a/version.env +++ b/version.env @@ -1,2 +1,2 @@ -MARKETING_VERSION=1.5.36 -BUILD_NUMBER=138 +MARKETING_VERSION=1.5.37 +BUILD_NUMBER=139